From e0c0dfc0042749d4202049175a775c3ff9663644 Mon Sep 17 00:00:00 2001
From: Bernhard Owen Josephus <bernhard.josephus@gmail.com>
Date: Sat, 14 Feb 2026 12:30:15 +0800
Subject: [PATCH 001/435] replace with connectWithoutView

---
 src/libs/actions/Report/DeleteReport.ts | 66 +++++++++++++++++++++++++
 src/libs/actions/Report/index.ts        | 42 +---------------
 src/libs/actions/ReportActions.ts       |  2 +-
 tests/actions/IOUTest.ts                |  3 +-
 4 files changed, 70 insertions(+), 43 deletions(-)
 create mode 100644 src/libs/actions/Report/DeleteReport.ts

diff --git a/src/libs/actions/Report/DeleteReport.ts b/src/libs/actions/Report/DeleteReport.ts
new file mode 100644
index 000000000000..60e55c2e0092
--- /dev/null
+++ b/src/libs/actions/Report/DeleteReport.ts
@@ -0,0 +1,66 @@
+import Onyx from 'react-native-onyx';
+import type {OnyxCollection} from 'react-native-onyx';
+import Log from '@libs/Log';
+import {getOriginalMessage, isMoneyRequestAction} from '@libs/ReportActionsUtils';
+import CONST from '@src/CONST';
+import ONYXKEYS from '@src/ONYXKEYS';
+import type {Report, ReportAction, ReportActions} from '@src/types/onyx';
+
+// We use connectWithoutView because deleteReport doesn't affect the UI rendering
+// and this avoids unnecessary re-rendering because we recursively delete the report and its children
+// which requires us to subscribe to the whole report and report actions collection.
+let allReports: OnyxCollection<Report>;
+Onyx.connectWithoutView({
+    key: ONYXKEYS.COLLECTION.REPORT,
+    waitForCollectionCallback: true,
+    callback: (value) => (allReports = value),
+});
+
+let allReportActions: OnyxCollection<ReportActions>;
+Onyx.connectWithoutView({
+    key: ONYXKEYS.COLLECTION.REPORT_ACTIONS,
+    waitForCollectionCallback: true,
+    callback: (value) => (allReportActions = value),
+});
+
+/** Deletes a report, along with its reportActions, any linked reports, and any linked IOU report. */
+function deleteReport(reportID: string | undefined, shouldDeleteChildReports = false) {
+    if (!reportID) {
+        Log.warn('[Report] deleteReport called with no reportID');
+        return;
+    }
+    const report = allReports?.[`${ONYXKEYS.COLLECTION.REPORT}${reportID}`];
+    const onyxData: Record<string, null> = {
+        [`${ONYXKEYS.COLLECTION.REPORT}${reportID}`]: null,
+        [`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${reportID}`]: null,
+    };
+
+    // Delete linked transactions
+    const reportActionsForReport = allReportActions?.[`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${reportID}`];
+
+    const transactionIDs = Object.values(reportActionsForReport ?? {})
+        .filter((reportAction): reportAction is ReportAction<typeof CONST.REPORT.ACTIONS.TYPE.IOU> => isMoneyRequestAction(reportAction))
+        .map((reportAction) => getOriginalMessage(reportAction)?.IOUTransactionID);
+
+    for (const transactionID of [...new Set(transactionIDs)]) {
+        onyxData[`${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`] = null;
+    }
+
+    Onyx.multiSet(onyxData);
+
+    if (shouldDeleteChildReports) {
+        for (const reportAction of Object.values(reportActionsForReport ?? {})) {
+            if (!reportAction.childReportID) {
+                continue;
+            }
+            deleteReport(reportAction.childReportID, shouldDeleteChildReports);
+        }
+    }
+
+    // Delete linked IOU report
+    if (report?.iouReportID) {
+        deleteReport(report.iouReportID, shouldDeleteChildReports);
+    }
+}
+
+export default deleteReport;
diff --git a/src/libs/actions/Report/index.ts b/src/libs/actions/Report/index.ts
index dd0ad4dd74c8..cad7efccfe6a 100644
--- a/src/libs/actions/Report/index.ts
+++ b/src/libs/actions/Report/index.ts
@@ -219,6 +219,7 @@ import type {Message, ReportActions} from '@src/types/onyx/ReportAction';
 import type {FileObject} from '@src/types/utils/Attachment';
 import {isEmptyObject} from '@src/types/utils/EmptyObject';
 import type {Dimensions} from '@src/types/utils/Layout';
+import deleteReport from './DeleteReport';
 
 type SubscriberCallback = (isFromCurrentUser: boolean, reportAction: ReportAction | undefined) => void;
 
@@ -3357,46 +3358,6 @@ function addPolicyReport(policyReport: OptimisticChatReport) {
     Navigation.dismissModalWithReport({reportID: policyReport.reportID});
 }
 
-/** Deletes a report, along with its reportActions, any linked reports, and any linked IOU report. */
-function deleteReport(reportID: string | undefined, shouldDeleteChildReports = false) {
-    if (!reportID) {
-        Log.warn('[Report] deleteReport called with no reportID');
-        return;
-    }
-    const report = allReports?.[`${ONYXKEYS.COLLECTION.REPORT}${reportID}`];
-    const onyxData: Record<string, null> = {
-        [`${ONYXKEYS.COLLECTION.REPORT}${reportID}`]: null,
-        [`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${reportID}`]: null,
-    };
-
-    // Delete linked transactions
-    const reportActionsForReport = allReportActions?.[reportID];
-
-    const transactionIDs = Object.values(reportActionsForReport ?? {})
-        .filter((reportAction): reportAction is ReportAction<typeof CONST.REPORT.ACTIONS.TYPE.IOU> => ReportActionsUtils.isMoneyRequestAction(reportAction))
-        .map((reportAction) => ReportActionsUtils.getOriginalMessage(reportAction)?.IOUTransactionID);
-
-    for (const transactionID of [...new Set(transactionIDs)]) {
-        onyxData[`${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`] = null;
-    }
-
-    Onyx.multiSet(onyxData);
-
-    if (shouldDeleteChildReports) {
-        for (const reportAction of Object.values(reportActionsForReport ?? {})) {
-            if (!reportAction.childReportID) {
-                continue;
-            }
-            deleteReport(reportAction.childReportID, shouldDeleteChildReports);
-        }
-    }
-
-    // Delete linked IOU report
-    if (report?.iouReportID) {
-        deleteReport(report.iouReportID, shouldDeleteChildReports);
-    }
-}
-
 /**
  * @param reportID The reportID of the policy report (workspace room)
  */
@@ -6640,7 +6601,6 @@ export {
     clearReportFieldKeyErrors,
     completeOnboarding,
     createNewReport,
-    deleteReport,
     deleteReportActionDraft,
     deleteReportComment,
     deleteReportField,
diff --git a/src/libs/actions/ReportActions.ts b/src/libs/actions/ReportActions.ts
index 739e87d7625c..f856a0d40589 100644
--- a/src/libs/actions/ReportActions.ts
+++ b/src/libs/actions/ReportActions.ts
@@ -1,12 +1,12 @@
 import type {OnyxCollection} from 'react-native-onyx';
 import Onyx from 'react-native-onyx';
+import deleteReport from '@libs/actions/Report/DeleteReport';
 import {getLinkedTransactionID, getReportAction, getReportActionMessage, isCreatedTaskReportAction} from '@libs/ReportActionsUtils';
 import {getOriginalReportID} from '@libs/ReportUtils';
 import CONST from '@src/CONST';
 import ONYXKEYS from '@src/ONYXKEYS';
 import type * as OnyxTypes from '@src/types/onyx';
 import type ReportAction from '@src/types/onyx/ReportAction';
-import {deleteReport} from './Report';
 
 type IgnoreDirection = 'parent' | 'child';
 
diff --git a/tests/actions/IOUTest.ts b/tests/actions/IOUTest.ts
index 55dfdaac81cf..0fcb7b1592bb 100644
--- a/tests/actions/IOUTest.ts
+++ b/tests/actions/IOUTest.ts
@@ -56,7 +56,8 @@ import {getSendInvoiceInformation} from '@libs/actions/IOU/SendInvoice';
 import {completeSplitBill, splitBill, startSplitBill, updateSplitTransactionsFromSplitExpensesFlow} from '@libs/actions/IOU/Split';
 import initOnyxDerivedValues from '@libs/actions/OnyxDerived';
 import {createWorkspace, deleteWorkspace, generatePolicyID, setWorkspaceApprovalMode} from '@libs/actions/Policy/Policy';
-import {addComment, createNewReport, deleteReport, notifyNewAction, openReport} from '@libs/actions/Report';
+import {addComment, createNewReport, notifyNewAction, openReport} from '@libs/actions/Report';
+import deleteReport from '@libs/actions/Report/DeleteReport';
 import {clearAllRelatedReportActionErrors} from '@libs/actions/ReportActions';
 import {subscribeToUserEvents} from '@libs/actions/User';
 import type {ApiCommand} from '@libs/API/types';

From e9e63333a79bec491333fe544c4a43fad7b6ee48 Mon Sep 17 00:00:00 2001
From: Bernhard Owen Josephus <bernhard.josephus@gmail.com>
Date: Sat, 14 Feb 2026 13:48:14 +0800
Subject: [PATCH 002/435] lint

---
 src/libs/actions/Report/DeleteReport.ts | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/src/libs/actions/Report/DeleteReport.ts b/src/libs/actions/Report/DeleteReport.ts
index 60e55c2e0092..2a5024e35136 100644
--- a/src/libs/actions/Report/DeleteReport.ts
+++ b/src/libs/actions/Report/DeleteReport.ts
@@ -1,10 +1,10 @@
 import Onyx from 'react-native-onyx';
-import type {OnyxCollection} from 'react-native-onyx';
+import type { OnyxCollection } from 'react-native-onyx';
 import Log from '@libs/Log';
-import {getOriginalMessage, isMoneyRequestAction} from '@libs/ReportActionsUtils';
-import CONST from '@src/CONST';
+import { getOriginalMessage, isMoneyRequestAction } from '@libs/ReportActionsUtils';
+import type CONST from '@src/CONST';
 import ONYXKEYS from '@src/ONYXKEYS';
-import type {Report, ReportAction, ReportActions} from '@src/types/onyx';
+import type { Report, ReportAction, ReportActions } from '@src/types/onyx';
 
 // We use connectWithoutView because deleteReport doesn't affect the UI rendering
 // and this avoids unnecessary re-rendering because we recursively delete the report and its children

From d092763c1535c373fa34a78389c2338c97909805 Mon Sep 17 00:00:00 2001
From: Bernhard Owen Josephus <bernhard.josephus@gmail.com>
Date: Sat, 14 Feb 2026 13:48:48 +0800
Subject: [PATCH 003/435] lint

---
 src/libs/actions/ReportActions.ts | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/src/libs/actions/ReportActions.ts b/src/libs/actions/ReportActions.ts
index f856a0d40589..476a887daa52 100644
--- a/src/libs/actions/ReportActions.ts
+++ b/src/libs/actions/ReportActions.ts
@@ -1,8 +1,8 @@
-import type {OnyxCollection} from 'react-native-onyx';
+import type { OnyxCollection } from 'react-native-onyx';
 import Onyx from 'react-native-onyx';
-import deleteReport from '@libs/actions/Report/DeleteReport';
-import {getLinkedTransactionID, getReportAction, getReportActionMessage, isCreatedTaskReportAction} from '@libs/ReportActionsUtils';
-import {getOriginalReportID} from '@libs/ReportUtils';
+import deleteReport from './Report/DeleteReport';
+import { getLinkedTransactionID, getReportAction, getReportActionMessage, isCreatedTaskReportAction } from '@libs/ReportActionsUtils';
+import { getOriginalReportID } from '@libs/ReportUtils';
 import CONST from '@src/CONST';
 import ONYXKEYS from '@src/ONYXKEYS';
 import type * as OnyxTypes from '@src/types/onyx';
@@ -105,7 +105,7 @@ function clearAllRelatedReportActionErrors(reportID: string | undefined, reportA
     }
 }
 
-export type {IgnoreDirection};
+export type { IgnoreDirection };
 export {
     // eslint-disable-next-line import/prefer-default-export
     clearAllRelatedReportActionErrors,

From 59e41f12a603fa479b4814adc72dc380ce2da4d9 Mon Sep 17 00:00:00 2001
From: Bernhard Owen Josephus <bernhard.josephus@gmail.com>
Date: Sat, 14 Feb 2026 14:20:42 +0800
Subject: [PATCH 004/435] prettier

---
 src/libs/actions/Report/DeleteReport.ts |  6 +++---
 src/libs/actions/ReportActions.ts       | 10 +++++-----
 2 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/src/libs/actions/Report/DeleteReport.ts b/src/libs/actions/Report/DeleteReport.ts
index 2a5024e35136..22b334189607 100644
--- a/src/libs/actions/Report/DeleteReport.ts
+++ b/src/libs/actions/Report/DeleteReport.ts
@@ -1,10 +1,10 @@
 import Onyx from 'react-native-onyx';
-import type { OnyxCollection } from 'react-native-onyx';
+import type {OnyxCollection} from 'react-native-onyx';
 import Log from '@libs/Log';
-import { getOriginalMessage, isMoneyRequestAction } from '@libs/ReportActionsUtils';
+import {getOriginalMessage, isMoneyRequestAction} from '@libs/ReportActionsUtils';
 import type CONST from '@src/CONST';
 import ONYXKEYS from '@src/ONYXKEYS';
-import type { Report, ReportAction, ReportActions } from '@src/types/onyx';
+import type {Report, ReportAction, ReportActions} from '@src/types/onyx';
 
 // We use connectWithoutView because deleteReport doesn't affect the UI rendering
 // and this avoids unnecessary re-rendering because we recursively delete the report and its children
diff --git a/src/libs/actions/ReportActions.ts b/src/libs/actions/ReportActions.ts
index 476a887daa52..4b2d50272ba4 100644
--- a/src/libs/actions/ReportActions.ts
+++ b/src/libs/actions/ReportActions.ts
@@ -1,12 +1,12 @@
-import type { OnyxCollection } from 'react-native-onyx';
+import type {OnyxCollection} from 'react-native-onyx';
 import Onyx from 'react-native-onyx';
-import deleteReport from './Report/DeleteReport';
-import { getLinkedTransactionID, getReportAction, getReportActionMessage, isCreatedTaskReportAction } from '@libs/ReportActionsUtils';
-import { getOriginalReportID } from '@libs/ReportUtils';
+import {getLinkedTransactionID, getReportAction, getReportActionMessage, isCreatedTaskReportAction} from '@libs/ReportActionsUtils';
+import {getOriginalReportID} from '@libs/ReportUtils';
 import CONST from '@src/CONST';
 import ONYXKEYS from '@src/ONYXKEYS';
 import type * as OnyxTypes from '@src/types/onyx';
 import type ReportAction from '@src/types/onyx/ReportAction';
+import deleteReport from './Report/DeleteReport';
 
 type IgnoreDirection = 'parent' | 'child';
 
@@ -105,7 +105,7 @@ function clearAllRelatedReportActionErrors(reportID: string | undefined, reportA
     }
 }
 
-export type { IgnoreDirection };
+export type {IgnoreDirection};
 export {
     // eslint-disable-next-line import/prefer-default-export
     clearAllRelatedReportActionErrors,

From e681c5e09bf38edba5496b9e25da7a558c4d6b82 Mon Sep 17 00:00:00 2001
From: Bernhard Owen Josephus <bernhard.josephus@gmail.com>
Date: Sat, 14 Feb 2026 16:43:08 +0800
Subject: [PATCH 005/435] add test

---
 tests/unit/DeleteReportTest.ts | 114 +++++++++++++++++++++++++++++++++
 1 file changed, 114 insertions(+)
 create mode 100644 tests/unit/DeleteReportTest.ts

diff --git a/tests/unit/DeleteReportTest.ts b/tests/unit/DeleteReportTest.ts
new file mode 100644
index 000000000000..6a1633816d91
--- /dev/null
+++ b/tests/unit/DeleteReportTest.ts
@@ -0,0 +1,114 @@
+import Onyx from 'react-native-onyx';
+import deleteReport from '@libs/actions/Report/DeleteReport';
+import CONST from '@src/CONST';
+import ONYXKEYS from '@src/ONYXKEYS';
+import {ReportAction} from '@src/types/onyx';
+import createRandomReportAction from '../utils/collections/reportActions';
+import {createRandomReport} from '../utils/collections/reports';
+import createRandomTransaction from '../utils/collections/transaction';
+import getOnyxValue from '../utils/getOnyxValue';
+import waitForBatchedUpdates from '../utils/waitForBatchedUpdates';
+
+// Mock Log to avoid noise in tests
+jest.mock('@libs/Log');
+
+describe('actions/Report/DeleteReport', () => {
+    beforeAll(() => {
+        Onyx.init({
+            keys: ONYXKEYS,
+        });
+    });
+
+    beforeEach(() => {
+        return Onyx.clear();
+    });
+
+    it('should delete a report, its actions, and linked transactions', async () => {
+        // Given a report with an IOU action and a linked transaction
+        const reportID = '1';
+        const transactionID = '123';
+        const report = createRandomReport(1, undefined);
+        const transaction = createRandomTransaction(Number(transactionID));
+        const reportAction: ReportAction<typeof CONST.REPORT.ACTIONS.TYPE.IOU> = {
+            ...createRandomReportAction(100),
+            actionName: CONST.REPORT.ACTIONS.TYPE.IOU,
+            previousMessage: [],
+            message: [{text: '', html: 'iou', type: 'COMMENT'}],
+            originalMessage: {
+                type: CONST.IOU.REPORT_ACTION_TYPE.CREATE,
+                IOUTransactionID: transaction.transactionID,
+                IOUDetails: {
+                    amount: transaction.amount,
+                    currency: transaction.currency,
+                    comment: '',
+                },
+            },
+        };
+
+        await Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT}${reportID}`, report);
+        await Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${reportID}`, {
+            [reportAction.reportActionID]: reportAction,
+        });
+        await Onyx.merge(`${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`, transaction);
+
+        // When we delete the report
+        deleteReport(reportID);
+
+        await waitForBatchedUpdates();
+
+        // Then the report, its actions, and the linked transaction should be deleted
+        expect(await getOnyxValue(`${ONYXKEYS.COLLECTION.REPORT}${reportID}`)).toBeUndefined();
+        expect(await getOnyxValue(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${reportID}`)).toBeUndefined();
+        expect(await getOnyxValue(`${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`)).toBeUndefined();
+    });
+
+    it('should delete child reports recursively when shouldDeleteChildReports is true', async () => {
+        // Given a parent report with a child report
+        const parentReportID = '1';
+        const childReportID = '2';
+        const parentReport = createRandomReport(Number(parentReportID), undefined);
+        const childReport = createRandomReport(Number(childReportID), undefined);
+        const parentAction = {
+            ...createRandomReportAction(100),
+            childReportID,
+        };
+
+        await Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT}${parentReportID}`, parentReport);
+        await Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT}${childReportID}`, childReport);
+        await Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${parentReportID}`, {
+            [parentAction.reportActionID]: parentAction,
+        });
+
+        // When we delete the parent report with shouldDeleteChildReports set to true
+        deleteReport(parentReportID, true);
+
+        await waitForBatchedUpdates();
+
+        // Then both the parent and child reports should be deleted
+        expect(await getOnyxValue(`${ONYXKEYS.COLLECTION.REPORT}${parentReportID}`)).toBeUndefined();
+        expect(await getOnyxValue(`${ONYXKEYS.COLLECTION.REPORT}${childReportID}`)).toBeUndefined();
+    });
+
+    it('should delete linked IOU reports recursively', async () => {
+        // Given a report with a linked IOU report
+        const reportID = '1';
+        const iouReportID = '2';
+        const report = {
+            ...createRandomReport(Number(reportID), undefined),
+            iouReportID,
+        };
+        const iouReport = createRandomReport(Number(iouReportID), undefined);
+
+        await Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT}${reportID}`, report);
+        await Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT}${iouReportID}`, iouReport);
+
+        // When we delete the report
+        deleteReport(reportID);
+
+        await waitForBatchedUpdates();
+
+        // Then both reports should be deleted
+        expect(await getOnyxValue(`${ONYXKEYS.COLLECTION.REPORT}${reportID}`)).toBeUndefined();
+        expect(await getOnyxValue(`${ONYXKEYS.COLLECTION.REPORT}${iouReportID}`)).toBeUndefined();
+    });
+});

From 37f777963ccf609a6175dcb5ec35f2c06fe6330f Mon Sep 17 00:00:00 2001
From: Bernhard Owen Josephus <bernhard.josephus@gmail.com>
Date: Wed, 18 Feb 2026 11:54:57 +0800
Subject: [PATCH 006/435] lint

---
 tests/unit/DeleteReportTest.ts | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/tests/unit/DeleteReportTest.ts b/tests/unit/DeleteReportTest.ts
index 6a1633816d91..adeeb4b275c8 100644
--- a/tests/unit/DeleteReportTest.ts
+++ b/tests/unit/DeleteReportTest.ts
@@ -2,7 +2,7 @@ import Onyx from 'react-native-onyx';
 import deleteReport from '@libs/actions/Report/DeleteReport';
 import CONST from '@src/CONST';
 import ONYXKEYS from '@src/ONYXKEYS';
-import {ReportAction} from '@src/types/onyx';
+import type {ReportAction} from '@src/types/onyx';
 import createRandomReportAction from '../utils/collections/reportActions';
 import {createRandomReport} from '../utils/collections/reports';
 import createRandomTransaction from '../utils/collections/transaction';

From 5455d55d8db55cb85ad2a3ed8aa8a00ddb306b35 Mon Sep 17 00:00:00 2001
From: Brian Lee <brianlee@expensify.com>
Date: Mon, 30 Mar 2026 09:16:38 -0700
Subject: [PATCH 007/435] Update Domain-Migration.md

---
 docs/articles/new-expensify/domains/Domain-Migration.md | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/docs/articles/new-expensify/domains/Domain-Migration.md b/docs/articles/new-expensify/domains/Domain-Migration.md
index 04f7247bc12d..7fd5426cdeb9 100644
--- a/docs/articles/new-expensify/domains/Domain-Migration.md
+++ b/docs/articles/new-expensify/domains/Domain-Migration.md
@@ -21,7 +21,7 @@ This is the recommended approach when possible.
 
 Concierge can typically perform an automatic Domain Migration if:
 
-- The old domain or new domain is verified
+- The old domain is verified
 - Email addresses match a 1:1 format, such as `name@olddomain.com` to `name@newdomain.com`
 - Members have not already created separate accounts under the new email address
 
@@ -65,7 +65,7 @@ Yes. If done correctly, members keep their full expense history, reports, and ap
 
 ## Do I need to verify the new domain before migrating?
 
-Yes. You must claim and verify the new domain before transferring domain control or updating member login emails.
+No. It is actually preferred that you do not add or verify the new domain in Expensify.
 
 ## What happens to the Expensify Card during Domain Migration?
 

From 1a2b4b64364a56c2c692ffc80591767b1638fde1 Mon Sep 17 00:00:00 2001
From: Brian Lee <brianlee@expensify.com>
Date: Mon, 30 Mar 2026 09:23:50 -0700
Subject: [PATCH 008/435] Update Domain-Migration.md

---
 docs/articles/new-expensify/domains/Domain-Migration.md | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/docs/articles/new-expensify/domains/Domain-Migration.md b/docs/articles/new-expensify/domains/Domain-Migration.md
index 7fd5426cdeb9..7d06e6adbdcc 100644
--- a/docs/articles/new-expensify/domains/Domain-Migration.md
+++ b/docs/articles/new-expensify/domains/Domain-Migration.md
@@ -65,7 +65,8 @@ Yes. If done correctly, members keep their full expense history, reports, and ap
 
 ## Do I need to verify the new domain before migrating?
 
-No. It is actually preferred that you do not add or verify the new domain in Expensify.
+- If you are migrating your domain automatically with assistance from Concierge, you will not need to verify the new domain. It is preferred that you do not add or verify the new domain in Expensify.
+- If you are migrating your domain manually, you will need to verify the new domain.
 
 ## What happens to the Expensify Card during Domain Migration?
 

From 4cc504a4cddd8a52187525600595d236714ebffd Mon Sep 17 00:00:00 2001
From: Shawn Borton <shawn@expensify.com>
Date: Fri, 17 Apr 2026 12:29:29 +0200
Subject: [PATCH 009/435] Replace Priority Mode with Inbox Tab Filters

Replace the hidden Focus/Priority mode toggle in Account > Preferences
with visible tab filters at the top of the Inbox: All, Unread, Expenses,
and Direct messages. This gives users immediate, discoverable control
over which chats they see.

- Add CONST.INBOX_TAB and ONYXKEYS.NVP_INBOX_TAB for tab state
- Add filterReportsForInboxTab() post-filter in SidebarUtils
- Add InboxTabSelector component using TabSelectorBase with small size
- Add 'small' size variant to TabSelector components (28px height, 11px font)
- Remove isInFocusMode from the entire report pipeline
- Remove PriorityModeHandler, PriorityModeController, FocusModeNotification
- Remove PriorityModePage and its route/navigation config
- Remove updateChatPriorityMode API command
- Update all test files

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
---
 src/CONST/index.ts                            |   9 +-
 src/Expensify.tsx                             |   2 -
 src/ONYXKEYS.ts                               |  10 +-
 src/PriorityModeHandler.tsx                   |  30 -----
 src/ROUTES.ts                                 |   1 -
 src/SCREENS.ts                                |   1 -
 src/components/FocusModeNotification.tsx      |  46 --------
 .../LHNOptionsList/OptionRowLHN.tsx           |  23 ++--
 src/components/PriorityModeController.tsx     | 110 ------------------
 .../ScrollOffsetContextProvider.tsx           |  10 +-
 src/components/TabSelector/TabLabel.tsx       |  11 +-
 .../TabSelector/TabSelectorBase.tsx           |   4 +-
 .../TabSelector/TabSelectorItem.tsx           |   3 +
 src/components/TabSelector/types.ts           |  10 +-
 src/hooks/useSidebarOrderedReports.tsx        |  70 +++++++----
 src/languages/de.ts                           |  23 +---
 src/languages/en.ts                           |  23 +---
 src/languages/es.ts                           |  24 +---
 src/languages/fr.ts                           |  23 +---
 src/languages/it.ts                           |  23 +---
 src/languages/ja.ts                           |  23 +---
 src/languages/nl.ts                           |  23 +---
 src/languages/pl.ts                           |  23 +---
 src/languages/pt-BR.ts                        |  23 +---
 src/languages/zh-hans.ts                      |  22 +---
 .../UpdateChatPriorityModeParams.ts           |   9 --
 src/libs/API/parameters/index.ts              |   1 -
 src/libs/API/types.ts                         |   2 -
 src/libs/DebugUtils.ts                        |   3 -
 .../Navigation/AppNavigator/AuthScreens.tsx   |   2 -
 .../ModalStackNavigators/index.tsx            |   1 -
 .../RELATIONS/SETTINGS_TO_RHP.ts              |   7 +-
 .../linkingConfig/RELATIONS/SIDEBAR_TO_RHP.ts |   2 +-
 src/libs/Navigation/linkingConfig/config.ts   |   4 -
 src/libs/Navigation/types.ts                  |   1 -
 src/libs/OptionsListUtils/index.ts            |   1 -
 src/libs/ReportUtils.ts                       |  17 +--
 src/libs/SidebarUtils.ts                      |  59 +++++++---
 src/libs/UnreadIndicatorUpdater/index.ts      |   1 -
 src/libs/actions/App.ts                       |   1 -
 src/libs/actions/Delegate.ts                  |   1 -
 src/libs/actions/QueuedOnyxUpdates.ts         |   1 -
 src/libs/actions/Session/index.ts             |   1 -
 src/libs/actions/User.ts                      |  36 +-----
 src/pages/Debug/Report/DebugReportPage.tsx    |   4 +-
 src/pages/inbox/sidebar/BaseSidebarScreen.tsx |   2 +
 src/pages/inbox/sidebar/InboxTabSelector.tsx  |  35 ++++++
 src/pages/inbox/sidebar/SidebarLinks.tsx      |  11 +-
 src/pages/inbox/sidebar/SidebarLinksData.tsx  |   6 -
 .../settings/Preferences/PreferencesPage.tsx  |  10 --
 .../settings/Preferences/PriorityModePage.tsx |  68 -----------
 src/styles/index.ts                           |  15 +++
 src/types/onyx/InboxTab.ts                    |   6 +
 src/types/onyx/PriorityMode.ts                |   8 --
 tests/actions/QueuedOnyxUpdatesTest.ts        |   2 -
 tests/perf-test/SidebarLinks.perf-test.tsx    |   4 +-
 tests/ui/LHNItemsPresence.tsx                 |  26 -----
 tests/unit/ReportUtilsTest.ts                 |  71 -----------
 tests/unit/SidebarFilterTest.ts               |  12 --
 tests/unit/SidebarOrderTest.ts                |  17 ---
 tests/unit/SidebarTest.ts                     |   4 +-
 tests/unit/SidebarUtilsTest.ts                |  14 +--
 62 files changed, 267 insertions(+), 768 deletions(-)
 delete mode 100644 src/PriorityModeHandler.tsx
 delete mode 100644 src/components/FocusModeNotification.tsx
 delete mode 100644 src/components/PriorityModeController.tsx
 delete mode 100644 src/libs/API/parameters/UpdateChatPriorityModeParams.ts
 create mode 100644 src/pages/inbox/sidebar/InboxTabSelector.tsx
 delete mode 100644 src/pages/settings/Preferences/PriorityModePage.tsx
 create mode 100644 src/types/onyx/InboxTab.ts
 delete mode 100644 src/types/onyx/PriorityMode.ts

diff --git a/src/CONST/index.ts b/src/CONST/index.ts
index b33731461863..3fbca9aa9280 100644
--- a/src/CONST/index.ts
+++ b/src/CONST/index.ts
@@ -2083,9 +2083,11 @@ const CONST = {
             MEMORY_THRESHOLD_IOS_WARNING_MB: 300, // > 300MB monitor closely
         },
     },
-    PRIORITY_MODE: {
-        GSD: 'gsd',
-        DEFAULT: 'default',
+    INBOX_TAB: {
+        ALL: 'all',
+        UNREADS: 'unreads',
+        EXPENSES: 'expenses',
+        DIRECT_MESSAGES: 'directMessages',
     },
     THEME: {
         DEFAULT: 'system',
@@ -9485,7 +9487,6 @@ const CONST = {
             ADDRESS: 'SettingsProfile-Address',
         },
         SETTINGS_PREFERENCES: {
-            PRIORITY_MODE: 'SettingsPreferences-PriorityMode',
             LANGUAGE: 'SettingsPreferences-Language',
             PAYMENT_CURRENCY: 'SettingsPreferences-PaymentCurrency',
             THEME: 'SettingsPreferences-Theme',
diff --git a/src/Expensify.tsx b/src/Expensify.tsx
index 70f8a81666f6..902b9b101e27 100644
--- a/src/Expensify.tsx
+++ b/src/Expensify.tsx
@@ -33,7 +33,6 @@ import {startBootsplashMonitor} from './libs/telemetry/bootsplashTelemetry';
 import {cleanupMemoryTrackingTelemetry, initializeMemoryTrackingTelemetry} from './libs/telemetry/TelemetrySynchronizer';
 import Visibility from './libs/Visibility';
 import ONYXKEYS from './ONYXKEYS';
-import PriorityModeHandler from './PriorityModeHandler';
 import type {Route} from './ROUTES';
 import {useSplashScreenActions, useSplashScreenState} from './SplashScreenStateContext';
 
@@ -273,7 +272,6 @@ function Expensify() {
     return (
         <>
             {shouldInit && <GlobalModals />}
-            <PriorityModeHandler />
             <DelegateAccessHandler />
             <FullstoryInitHandler />
             <DeepLinkHandler onInitialUrl={setInitialUrl} />
diff --git a/src/ONYXKEYS.ts b/src/ONYXKEYS.ts
index b3062bf03dc7..b7da30c7c155 100755
--- a/src/ONYXKEYS.ts
+++ b/src/ONYXKEYS.ts
@@ -159,8 +159,8 @@ const ONYXKEYS = {
     /** Contains the platforms for which the user muted the sounds */
     NVP_MUTED_PLATFORMS: 'nvp_mutedPlatforms',
 
-    /** Contains the user preference for the LHN priority mode */
-    NVP_PRIORITY_MODE: 'nvp_priorityMode',
+    /** Contains the user preference for the active inbox tab filter */
+    NVP_INBOX_TAB: 'nvp_inboxTab',
 
     /** Contains the users's block expiration (if they have one) */
     NVP_BLOCKED_FROM_CONCIERGE: 'nvp_private_blockedFromConcierge',
@@ -212,9 +212,6 @@ const ONYXKEYS = {
     /** Whether the app is currently loading a translation */
     RAM_ONLY_ARE_TRANSLATIONS_LOADING: 'areTranslationsLoading',
 
-    /** Whether the user has tried focus mode yet */
-    NVP_TRY_FOCUS_MODE: 'nvp_tryFocusMode',
-
     /** Whether the user has dismissed the hold educational interstitial */
     NVP_DISMISSED_HOLD_USE_EXPLANATION: 'nvp_dismissedHoldUseExplanation',
 
@@ -1356,7 +1353,7 @@ type OnyxValuesMapping = {
     [ONYXKEYS.BETAS]: OnyxTypes.Beta[];
     [ONYXKEYS.BETA_CONFIGURATION]: OnyxTypes.BetaConfiguration;
     [ONYXKEYS.NVP_MUTED_PLATFORMS]: Partial<Record<Platform, true>>;
-    [ONYXKEYS.NVP_PRIORITY_MODE]: ValueOf<typeof CONST.PRIORITY_MODE>;
+    [ONYXKEYS.NVP_INBOX_TAB]: ValueOf<typeof CONST.INBOX_TAB>;
     [ONYXKEYS.NVP_BLOCKED_FROM_CONCIERGE]: OnyxTypes.BlockedFromConcierge;
     [ONYXKEYS.QUEUE_FLUSHED_DATA]: AnyOnyxUpdate[];
     [ONYXKEYS.TRANSACTIONS_PENDING_3DS_REVIEW]: OnyxTypes.TransactionsPending3DSReview;
@@ -1366,7 +1363,6 @@ type OnyxValuesMapping = {
     [ONYXKEYS.NVP_BLOCKED_FROM_CHAT]: string;
     [ONYXKEYS.NVP_PRIVATE_PUSH_NOTIFICATION_ID]: string;
     [ONYXKEYS.NVP_RECENT_ATTENDEES]: Attendee[];
-    [ONYXKEYS.NVP_TRY_FOCUS_MODE]: boolean;
     [ONYXKEYS.NVP_DISMISSED_HOLD_USE_EXPLANATION]: boolean;
     [ONYXKEYS.NVP_DISMISSED_ASAP_SUBMIT_EXPLANATION]: boolean;
     [ONYXKEYS.NVP_EMPTY_REPORTS_CONFIRMATION_DISMISSED]: boolean;
diff --git a/src/PriorityModeHandler.tsx b/src/PriorityModeHandler.tsx
deleted file mode 100644
index 3c3326f24807..000000000000
--- a/src/PriorityModeHandler.tsx
+++ /dev/null
@@ -1,30 +0,0 @@
-import {useEffect} from 'react';
-import CONST from './CONST';
-import useOnyx from './hooks/useOnyx';
-import usePrevious from './hooks/usePrevious';
-import {openApp} from './libs/actions/App';
-import ONYXKEYS from './ONYXKEYS';
-
-/**
- * Component that does not render anything but isolates priority-mode–related Onyx subscriptions
- * (NVP_PRIORITY_MODE, COLLECTION.REPORT_DRAFT_COMMENT) from the root Expensify component so that
- * changes to these keys do not re-render the entire navigation tree.
- */
-function PriorityModeHandler() {
-    const [priorityMode] = useOnyx(ONYXKEYS.NVP_PRIORITY_MODE);
-    const [allReportsWithDraftComments] = useOnyx(ONYXKEYS.COLLECTION.REPORT_DRAFT_COMMENT);
-    const prevPriorityMode = usePrevious(priorityMode);
-
-    useEffect(() => {
-        if (!(prevPriorityMode === CONST.PRIORITY_MODE.GSD && priorityMode === CONST.PRIORITY_MODE.DEFAULT)) {
-            return;
-        }
-        // When a user switches their priority mode away from #focus/GSD we need to call openApp
-        // to fetch all their chats because #focus mode works with a subset of a user's chats.
-        openApp(false, allReportsWithDraftComments);
-    }, [priorityMode, allReportsWithDraftComments, prevPriorityMode]);
-
-    return null;
-}
-
-export default PriorityModeHandler;
diff --git a/src/ROUTES.ts b/src/ROUTES.ts
index 5477d2b21a3c..e30765e78f81 100644
--- a/src/ROUTES.ts
+++ b/src/ROUTES.ts
@@ -556,7 +556,6 @@ const ROUTES = {
         // eslint-disable-next-line no-restricted-syntax -- Legacy route generation
         getRoute: (backTo?: string) => getUrlWithBackToParam('settings/subscription/downgrade-blocked', backTo),
     },
-    SETTINGS_PRIORITY_MODE: 'settings/preferences/priority-mode',
     SETTINGS_LANGUAGE: 'settings/preferences/language',
     SETTINGS_PAYMENT_CURRENCY: 'setting/preferences/payment-currency',
     SETTINGS_THEME: 'settings/preferences/theme',
diff --git a/src/SCREENS.ts b/src/SCREENS.ts
index 933edaedffee..8316e488c214 100644
--- a/src/SCREENS.ts
+++ b/src/SCREENS.ts
@@ -160,7 +160,6 @@ const SCREENS = {
 
         PREFERENCES: {
             ROOT: 'Settings_Preferences',
-            PRIORITY_MODE: 'Settings_Preferences_PriorityMode',
             LANGUAGE: 'Settings_Preferences_Language',
             THEME: 'Settings_Preferences_Theme',
             PAYMENT_CURRENCY: 'Settings_Payment_Currency',
diff --git a/src/components/FocusModeNotification.tsx b/src/components/FocusModeNotification.tsx
deleted file mode 100644
index d7f82bf7defc..000000000000
--- a/src/components/FocusModeNotification.tsx
+++ /dev/null
@@ -1,46 +0,0 @@
-import React from 'react';
-import {View} from 'react-native';
-import useEnvironment from '@hooks/useEnvironment';
-import {useMemoizedLazyIllustrations} from '@hooks/useLazyAsset';
-import useLocalize from '@hooks/useLocalize';
-import useStyleUtils from '@hooks/useStyleUtils';
-import useThemeStyles from '@hooks/useThemeStyles';
-import colors from '@styles/theme/colors';
-import ConfirmModal from './ConfirmModal';
-import RenderHTML from './RenderHTML';
-
-type FocusModeNotificationProps = {
-    onClose: () => void;
-};
-
-function FocusModeNotification({onClose}: FocusModeNotificationProps) {
-    const styles = useThemeStyles();
-    const StyleUtils = useStyleUtils();
-    const illustrations = useMemoizedLazyIllustrations(['ThreeLeggedLaptopWoman']);
-    const {environmentURL} = useEnvironment();
-    const {translate} = useLocalize();
-    const priorityModePageUrl = `${environmentURL}/settings/preferences/priority-mode`;
-
-    return (
-        <ConfirmModal
-            title={translate('focusModeUpdateModal.title')}
-            confirmText={translate('common.buttonConfirm')}
-            onConfirm={onClose}
-            shouldShowCancelButton={false}
-            onBackdropPress={onClose}
-            onCancel={onClose}
-            prompt={
-                <View style={[styles.renderHTML, styles.flexRow]}>
-                    <RenderHTML html={translate('focusModeUpdateModal.prompt', priorityModePageUrl)} />
-                </View>
-            }
-            success
-            isVisible
-            image={illustrations.ThreeLeggedLaptopWoman}
-            imageStyles={StyleUtils.getBackgroundColorStyle(colors.pink800)}
-            titleStyles={[styles.textHeadline, styles.mbn3]}
-        />
-    );
-}
-
-export default FocusModeNotification;
diff --git a/src/components/LHNOptionsList/OptionRowLHN.tsx b/src/components/LHNOptionsList/OptionRowLHN.tsx
index 4f230b11cbf9..c1612c0a17d4 100644
--- a/src/components/LHNOptionsList/OptionRowLHN.tsx
+++ b/src/components/LHNOptionsList/OptionRowLHN.tsx
@@ -89,12 +89,13 @@ function OptionRowLHN({
     const {translate} = useLocalize();
     const [isContextMenuActive, setIsContextMenuActive] = useState(false);
     const currentUserPersonalDetails = useCurrentUserPersonalDetails();
-    const isInFocusMode = viewMode === CONST.OPTION_MODE.COMPACT;
-    const sidebarInnerRowStyle = StyleSheet.flatten<ViewStyle>(
-        isInFocusMode
-            ? [styles.chatLinkRowPressable, styles.flexGrow1, styles.optionItemAvatarNameWrapper, styles.optionRowCompact, styles.justifyContentCenter]
-            : [styles.chatLinkRowPressable, styles.flexGrow1, styles.optionItemAvatarNameWrapper, styles.optionRow, styles.justifyContentCenter],
-    );
+    const sidebarInnerRowStyle = StyleSheet.flatten<ViewStyle>([
+        styles.chatLinkRowPressable,
+        styles.flexGrow1,
+        styles.optionItemAvatarNameWrapper,
+        styles.optionRow,
+        styles.justifyContentCenter,
+    ]);
 
     const alternateTextContainsCustomEmojiWithText = useMemo(
         () => containsCustomEmojiUtils(optionItem?.alternateText) && !containsOnlyCustomEmoji(optionItem?.alternateText),
@@ -171,11 +172,9 @@ function OptionRowLHN({
     const textStyle = isOptionFocused ? styles.sidebarLinkActiveText : styles.sidebarLinkText;
     const textUnreadStyle = shouldUseBoldText(optionItem) ? [textStyle, styles.sidebarLinkTextBold] : [textStyle];
     const displayNameStyle = [styles.optionDisplayName, styles.optionDisplayNameCompact, styles.pre, textUnreadStyle, styles.flexShrink0, style];
-    const alternateTextStyle = isInFocusMode
-        ? [textStyle, styles.textLabelSupporting, styles.optionAlternateTextCompact, styles.ml2, style]
-        : [textStyle, styles.optionAlternateText, styles.textLabelSupporting, style];
+    const alternateTextStyle = [textStyle, styles.optionAlternateText, styles.textLabelSupporting, style];
 
-    const contentContainerStyles = isInFocusMode ? [styles.flex1, styles.flexRow, styles.overflowHidden, StyleUtils.getCompactContentContainerStyles()] : [styles.flex1];
+    const contentContainerStyles = [styles.flex1];
     const hoveredBackgroundColor = !!styles.sidebarLinkHover && 'backgroundColor' in styles.sidebarLinkHover ? styles.sidebarLinkHover.backgroundColor : theme.sidebar;
     const focusedBackgroundColor = styles.sidebarLinkActive.backgroundColor;
 
@@ -329,9 +328,9 @@ function OptionRowLHN({
                                                 <LHNAvatar
                                                     icons={icons}
                                                     shouldShowSubscript={!!optionItem.shouldShowSubscript}
-                                                    size={isInFocusMode ? CONST.AVATAR_SIZE.SMALL : CONST.AVATAR_SIZE.DEFAULT}
+                                                    size={CONST.AVATAR_SIZE.DEFAULT}
                                                     subscriptAvatarBorderColor={hovered && !isOptionFocused ? hoveredBackgroundColor : subscriptAvatarBorderColor}
-                                                    useMidSubscriptSize={isInFocusMode}
+                                                    useMidSubscriptSize={false}
                                                     secondaryAvatarBackgroundColor={secondaryAvatarBgColor}
                                                     singleAvatarContainerStyle={singleAvatarContainerStyle}
                                                     shouldShowTooltip={shouldOptionShowTooltip(optionItem)}
diff --git a/src/components/PriorityModeController.tsx b/src/components/PriorityModeController.tsx
deleted file mode 100644
index bbed955ea936..000000000000
--- a/src/components/PriorityModeController.tsx
+++ /dev/null
@@ -1,110 +0,0 @@
-import {useNavigation} from '@react-navigation/native';
-import React, {useCallback, useEffect, useRef, useState} from 'react';
-import type {OnyxEntry} from 'react-native-onyx';
-import type {ValueOf} from 'type-fest';
-import useOnyx from '@hooks/useOnyx';
-import {useSidebarOrderedReportsState} from '@hooks/useSidebarOrderedReports';
-import {updateChatPriorityMode} from '@libs/actions/User';
-import getIsNarrowLayout from '@libs/getIsNarrowLayout';
-import Log from '@libs/Log';
-import navigationRef from '@libs/Navigation/navigationRef';
-import CONST from '@src/CONST';
-import ONYXKEYS from '@src/ONYXKEYS';
-import SCREENS from '@src/SCREENS';
-import isLoadingOnyxValue from '@src/types/utils/isLoadingOnyxValue';
-import FocusModeNotification from './FocusModeNotification';
-
-const isInFocusModeSelector = (priorityMode: OnyxEntry<ValueOf<typeof CONST.PRIORITY_MODE>>) => priorityMode === CONST.PRIORITY_MODE.GSD;
-
-/**
- * This component is used to automatically switch a user into #focus mode when they exceed a certain number of reports.
- * We do this primarily for performance reasons. Similar to the "Welcome action" we must wait for a number of things to
- * happen when the user signs in or refreshes the page:
- *
- *  - NVP that tracks whether they have already been switched over. We only do this once.
- *  - Priority mode NVP (that dictates the ordering/filtering logic of the LHN)
- *  - Reports to load (in ReconnectApp or OpenApp). As we check the count of the reports to determine whether the
- *    user is eligible to be automatically switched.
- *
- */
-export default function PriorityModeController() {
-    const {orderedReportIDs} = useSidebarOrderedReportsState();
-    const lhnReportCount = orderedReportIDs.length;
-    const [isLoadingReportData] = useOnyx(ONYXKEYS.IS_LOADING_REPORT_DATA);
-    const [isInFocusMode, isInFocusModeMetadata] = useOnyx(ONYXKEYS.NVP_PRIORITY_MODE, {selector: isInFocusModeSelector});
-    const [hasTriedFocusMode, hasTriedFocusModeMetadata] = useOnyx(ONYXKEYS.NVP_TRY_FOCUS_MODE);
-    const currentRouteName = useCurrentRouteName();
-    const [shouldShowModal, setShouldShowModal] = useState(false);
-    const closeModal = useCallback(() => setShouldShowModal(false), []);
-
-    // We set this when we have finally auto-switched the user of #focus mode to prevent duplication.
-    const hasSwitched = useRef(false);
-
-    // Listen for state changes and trigger the #focus mode when appropriate
-    useEffect(() => {
-        // Wait for Onyx state to fully load
-        if (
-            isLoadingReportData !== false ||
-            isLoadingOnyxValue(isInFocusModeMetadata, hasTriedFocusModeMetadata) ||
-            typeof isInFocusMode !== 'boolean' ||
-            typeof hasTriedFocusMode !== 'boolean'
-        ) {
-            return;
-        }
-
-        // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
-        if (hasSwitched.current || isInFocusMode || hasTriedFocusMode) {
-            return;
-        }
-
-        if (lhnReportCount < CONST.REPORT.MAX_COUNT_BEFORE_FOCUS_UPDATE) {
-            Log.info('[PriorityModeController] Not switching user to focus mode as they do not have enough reports', false, {lhnReportCount});
-            return;
-        }
-
-        // We wait for the user to navigate back to the home screen before triggering this switch
-        const isNarrowLayout = getIsNarrowLayout();
-        if ((isNarrowLayout && currentRouteName !== SCREENS.INBOX) || (!isNarrowLayout && currentRouteName !== SCREENS.REPORT)) {
-            Log.info("[PriorityModeController] Not switching user to focus mode as they aren't on the home screen", false, {lhnReportCount, currentRouteName});
-            return;
-        }
-
-        Log.info('[PriorityModeController] Switching user to focus mode', false, {lhnReportCount, hasTriedFocusMode, isInFocusMode, currentRouteName});
-        updateChatPriorityMode(CONST.PRIORITY_MODE.GSD, true);
-        requestAnimationFrame(() => {
-            setShouldShowModal(true);
-        });
-        hasSwitched.current = true;
-    }, [currentRouteName, hasTriedFocusMode, hasTriedFocusModeMetadata, isInFocusMode, isInFocusModeMetadata, isLoadingReportData, lhnReportCount]);
-
-    useEffect(() => {
-        if (!shouldShowModal) {
-            return;
-        }
-        const isNavigatingToPriorityModePage = currentRouteName === SCREENS.SETTINGS.PREFERENCES.PRIORITY_MODE;
-
-        // Hide focus modal when settings button is pressed from the prompt.
-        if (isNavigatingToPriorityModePage) {
-            setShouldShowModal(false);
-        }
-    }, [currentRouteName, shouldShowModal]);
-
-    return shouldShowModal ? <FocusModeNotification onClose={closeModal} /> : null;
-}
-
-/**
- * A funky but reliable way to subscribe to screen changes.
- */
-function useCurrentRouteName() {
-    const navigation = useNavigation();
-    const [currentRouteName, setCurrentRouteName] = useState<string | undefined>('');
-
-    useEffect(() => {
-        const unsubscribe = navigation.addListener('state', () => {
-            setCurrentRouteName(navigationRef.getCurrentRoute()?.name);
-        });
-        return () => unsubscribe();
-    }, [navigation]);
-
-    return currentRouteName;
-}
diff --git a/src/components/ScrollOffsetContextProvider.tsx b/src/components/ScrollOffsetContextProvider.tsx
index f051497606d4..2a59f6ee533a 100644
--- a/src/components/ScrollOffsetContextProvider.tsx
+++ b/src/components/ScrollOffsetContextProvider.tsx
@@ -60,22 +60,22 @@ function getKey(route: PlatformStackRouteProp<ParamListBase> | NavigationPartial
 }
 
 function ScrollOffsetContextProvider({children}: ScrollOffsetContextProviderProps) {
-    const [priorityMode] = useOnyx(ONYXKEYS.NVP_PRIORITY_MODE);
+    const [inboxTab] = useOnyx(ONYXKEYS.NVP_INBOX_TAB);
     const scrollOffsetsRef = useRef<Record<string, number>>({});
-    const previousPriorityMode = usePrevious(priorityMode);
+    const previousInboxTab = usePrevious(inboxTab);
 
     useEffect(() => {
-        if (previousPriorityMode === null || previousPriorityMode === priorityMode) {
+        if (previousInboxTab === null || previousInboxTab === inboxTab) {
             return;
         }
 
-        // If the priority mode changes, we need to clear the scroll offsets for the home and search screens because it affects the size of the elements and scroll positions wouldn't be correct.
+        // If the inbox tab changes, we need to clear the scroll offsets for the home and search screens because it affects the size of the elements and scroll positions wouldn't be correct.
         for (const key of Object.keys(scrollOffsetsRef.current)) {
             if (key.includes(SCREENS.INBOX) || key.includes(SCREENS.SEARCH.ROOT)) {
                 delete scrollOffsetsRef.current[key];
             }
         }
-    }, [priorityMode, previousPriorityMode]);
+    }, [inboxTab, previousInboxTab]);
 
     const saveScrollOffset: ScrollOffsetContextValue['saveScrollOffset'] = useCallback((route, scrollOffset) => {
         scrollOffsetsRef.current[getKey(route)] = scrollOffset;
diff --git a/src/components/TabSelector/TabLabel.tsx b/src/components/TabSelector/TabLabel.tsx
index e47490b89f38..c00d939cdb44 100644
--- a/src/components/TabSelector/TabLabel.tsx
+++ b/src/components/TabSelector/TabLabel.tsx
@@ -5,6 +5,7 @@ import type {StyleProp, TextStyle} from 'react-native';
 import Text from '@components/Text';
 import useThemeStyles from '@hooks/useThemeStyles';
 import variables from '@styles/variables';
+import type {TabSelectorSize} from './types';
 
 type TabLabelProps = {
     /** Title of the tab */
@@ -21,16 +22,20 @@ type TabLabelProps = {
 
     /** Text style */
     textStyle?: StyleProp<TextStyle>;
+
+    /** Size variant */
+    size?: TabSelectorSize;
 };
 
-function TabLabel({title = '', activeOpacity = 0, inactiveOpacity = 1, hasIcon = false, textStyle}: TabLabelProps) {
+function TabLabel({title = '', activeOpacity = 0, inactiveOpacity = 1, hasIcon = false, textStyle, size}: TabLabelProps) {
     const styles = useThemeStyles();
+    const smallTextStyle = size === 'small' ? styles.tabTextSmall : undefined;
     return (
         <View style={{maxWidth: variables.tabSelectorMaxTabLabelWidth}}>
             <Animated.View style={[{opacity: activeOpacity}]}>
                 <Text
                     numberOfLines={1}
-                    style={[styles.tabText(true, hasIcon), textStyle]}
+                    style={[styles.tabText(true, hasIcon), smallTextStyle, textStyle]}
                 >
                     {title}
                 </Text>
@@ -38,7 +43,7 @@ function TabLabel({title = '', activeOpacity = 0, inactiveOpacity = 1, hasIcon =
             <Animated.View style={[StyleSheet.absoluteFill, {opacity: inactiveOpacity}]}>
                 <Text
                     numberOfLines={1}
-                    style={[styles.tabText(false, hasIcon), textStyle]}
+                    style={[styles.tabText(false, hasIcon), smallTextStyle, textStyle]}
                 >
                     {title}
                 </Text>
diff --git a/src/components/TabSelector/TabSelectorBase.tsx b/src/components/TabSelector/TabSelectorBase.tsx
index 0c48ea1b091a..ff544715247e 100644
--- a/src/components/TabSelector/TabSelectorBase.tsx
+++ b/src/components/TabSelector/TabSelectorBase.tsx
@@ -27,6 +27,7 @@ function TabSelectorBase({
     position,
     shouldShowLabelWhenInactive = true,
     equalWidth = false,
+    size,
     shouldShowProductTrainingTooltip = false,
     renderProductTrainingTooltip,
 }: TabSelectorBaseProps) {
@@ -64,7 +65,7 @@ function TabSelectorBase({
             }}
             ref={containerRef}
             style={styles.scrollableTabSelector}
-            contentContainerStyle={styles.tabSelectorContentContainer}
+            contentContainerStyle={[styles.tabSelectorContentContainer, size === 'small' && styles.tabSelectorContentContainerSmall]}
             horizontal
             showsHorizontalScrollIndicator={false}
             keyboardShouldPersistTaps="handled"
@@ -123,6 +124,7 @@ function TabSelectorBase({
                         shouldShowProductTrainingTooltip={shouldShowProductTrainingTooltip}
                         renderProductTrainingTooltip={renderProductTrainingTooltip}
                         equalWidth={equalWidth}
+                        size={size}
                         badgeText={tab.badgeText}
                         pendingAction={tab.pendingAction}
                         isDisabled={tab.isDisabled}
diff --git a/src/components/TabSelector/TabSelectorItem.tsx b/src/components/TabSelector/TabSelectorItem.tsx
index fb5ada5f9d94..47c825b2f2ff 100644
--- a/src/components/TabSelector/TabSelectorItem.tsx
+++ b/src/components/TabSelector/TabSelectorItem.tsx
@@ -34,6 +34,7 @@ function TabSelectorItem({
     shouldShowProductTrainingTooltip = false,
     renderProductTrainingTooltip,
     equalWidth = false,
+    size,
     badgeText,
     isDisabled = false,
     pendingAction,
@@ -58,6 +59,7 @@ function TabSelectorItem({
             accessibilityRole={CONST.ROLE.TAB}
             style={[
                 styles.tabSelectorButton,
+                size === 'small' && styles.tabSelectorButtonSmall,
                 styles.tabBackground(isHovered, isActive, isDisabled, backgroundColor),
                 styles.userSelectNone,
                 isOfflineWithPendingAction ? styles.offlineFeedbackPending : undefined,
@@ -89,6 +91,7 @@ function TabSelectorItem({
                     activeOpacity={styles.tabOpacity(isDisabled, isHovered, isActive, activeOpacity, inactiveOpacity).opacity}
                     inactiveOpacity={styles.tabOpacity(isDisabled, isHovered, isActive, inactiveOpacity, activeOpacity).opacity}
                     hasIcon={!!icon}
+                    size={size}
                 />
             )}
             {!!badgeText && (
diff --git a/src/components/TabSelector/types.ts b/src/components/TabSelector/types.ts
index 4d5ac355b75c..20e0d3e0861d 100644
--- a/src/components/TabSelector/types.ts
+++ b/src/components/TabSelector/types.ts
@@ -52,6 +52,8 @@ type TabSelectorBaseItem = WithSentryLabel & {
     pendingAction?: PendingAction;
 };
 
+type TabSelectorSize = 'default' | 'small';
+
 type TabSelectorBaseProps = {
     /** Tabs to render. */
     tabs: TabSelectorBaseItem[];
@@ -77,6 +79,9 @@ type TabSelectorBaseProps = {
     /** Whether tabs should have equal width. */
     equalWidth?: boolean;
 
+    /** Size variant for the tabs. 'small' uses a compact 28px height. */
+    size?: TabSelectorSize;
+
     /** Determines whether the product training tooltip should be displayed to the user. */
     shouldShowProductTrainingTooltip?: boolean;
 
@@ -121,6 +126,9 @@ type TabSelectorItemProps = WithSentryLabel & {
     /** Whether tabs should have equal width */
     equalWidth?: boolean;
 
+    /** Size variant for the tabs. */
+    size?: TabSelectorSize;
+
     /** Determines whether the product training tooltip should be displayed to the user. */
     shouldShowProductTrainingTooltip?: boolean;
 
@@ -182,4 +190,4 @@ type BackgroundColor = Animated.AnimatedInterpolation<string> | string;
 
 type Opacity = 1 | 0 | Animated.AnimatedInterpolation<number>;
 
-export type {TabSelectorProps, BackgroundColor, GetBackgroundColorConfig, Opacity, GetOpacityConfig, TabSelectorBaseProps, TabSelectorBaseItem, TabSelectorItemProps};
+export type {TabSelectorProps, BackgroundColor, GetBackgroundColorConfig, Opacity, GetOpacityConfig, TabSelectorBaseProps, TabSelectorBaseItem, TabSelectorItemProps, TabSelectorSize};
diff --git a/src/hooks/useSidebarOrderedReports.tsx b/src/hooks/useSidebarOrderedReports.tsx
index 8ae7ad1a86bf..bd2ea03621c7 100644
--- a/src/hooks/useSidebarOrderedReports.tsx
+++ b/src/hooks/useSidebarOrderedReports.tsx
@@ -1,6 +1,8 @@
 import {deepEqual} from 'fast-equals';
 import React, {createContext, useCallback, useContext, useEffect, useMemo, useRef, useState} from 'react';
 import type {OnyxEntry} from 'react-native-onyx';
+import type {ValueOf} from 'type-fest';
+import {setInboxTab} from '@libs/actions/User';
 import Log from '@libs/Log';
 import {getTransactionThreadReportID} from '@libs/MergeTransactionUtils';
 import {isOneTransactionReport} from '@libs/ReportUtils';
@@ -33,10 +35,12 @@ type SidebarOrderedReportsStateContextValue = {
     orderedReportIDs: string[];
     currentReportID: string | undefined;
     chatTabBrickRoad: BrickRoad;
+    activeTab: ValueOf<typeof CONST.INBOX_TAB>;
 };
 
 type SidebarOrderedReportsActionsContextValue = {
     clearLHNCache: () => void;
+    setActiveTab: (tab: ValueOf<typeof CONST.INBOX_TAB>) => void;
 };
 
 type ReportsToDisplayInLHN = Record<string, OnyxTypes.Report & {hasErrorsOtherThanFailedReceipt?: boolean; requiresAttention?: boolean}>;
@@ -46,10 +50,12 @@ const SidebarOrderedReportsStateContext = createContext<SidebarOrderedReportsSta
     orderedReportIDs: [],
     currentReportID: '',
     chatTabBrickRoad: undefined,
+    activeTab: CONST.INBOX_TAB.ALL,
 });
 
 const SidebarOrderedReportsActionsContext = createContext<SidebarOrderedReportsActionsContextValue>({
     clearLHNCache: () => {},
+    setActiveTab: () => {},
 });
 
 const policyMapper = (policy: OnyxEntry<OnyxTypes.Policy>): PartialPolicyForSidebar =>
@@ -73,7 +79,8 @@ function SidebarOrderedReportsContextProvider({
     currentReportIDForTests,
 }: SidebarOrderedReportsContextProviderProps) {
     const {localeCompare} = useLocalize();
-    const [priorityMode = CONST.PRIORITY_MODE.DEFAULT] = useOnyx(ONYXKEYS.NVP_PRIORITY_MODE);
+    const [inboxTab = CONST.INBOX_TAB.ALL] = useOnyx(ONYXKEYS.NVP_INBOX_TAB);
+    const activeTab = inboxTab ?? CONST.INBOX_TAB.ALL;
     const [chatReports, {sourceValue: reportUpdates}] = useOnyx(ONYXKEYS.COLLECTION.REPORT);
     const [policies, {sourceValue: policiesUpdates}] = useMappedPolicies(policyMapper);
     const [transactions, {sourceValue: transactionsUpdates}] = useOnyx(ONYXKEYS.COLLECTION.TRANSACTION);
@@ -94,7 +101,6 @@ function SidebarOrderedReportsContextProvider({
     const [clearCacheDummyCounter, setClearCacheDummyCounter] = useState(0);
 
     const prevBetas = usePrevious(betas);
-    const prevPriorityMode = usePrevious(priorityMode);
 
     const perfRef = useRef<{hookDuration: number}>({
         hookDuration: 0,
@@ -107,7 +113,7 @@ function SidebarOrderedReportsContextProvider({
     const getUpdatedReports = useCallback(() => {
         const reportsToUpdate = new Set<string>();
 
-        if (betas !== prevBetas || priorityMode !== prevPriorityMode) {
+        if (betas !== prevBetas) {
             for (const key of Object.keys(chatReports ?? {})) {
                 reportsToUpdate.add(key);
             }
@@ -177,9 +183,7 @@ function SidebarOrderedReportsContextProvider({
         chatReports,
         transactions,
         betas,
-        priorityMode,
         prevBetas,
-        prevPriorityMode,
         prevDerivedCurrentReportID,
         derivedCurrentReportID,
     ]);
@@ -200,7 +204,6 @@ function SidebarOrderedReportsContextProvider({
                 reports: chatReports,
                 updatedReportsKeys: effectiveUpdatedReports,
                 currentReportId: derivedCurrentReportID,
-                isInFocusMode: priorityMode === CONST.PRIORITY_MODE.GSD,
                 betas,
                 transactionViolations,
                 reportNameValuePairs,
@@ -214,7 +217,6 @@ function SidebarOrderedReportsContextProvider({
                 derivedCurrentReportID,
                 chatReports,
                 betas,
-                priorityMode,
                 reportsDrafts,
                 transactionViolations,
                 transactions,
@@ -226,7 +228,7 @@ function SidebarOrderedReportsContextProvider({
         return reportsToDisplay;
         // Rule disabled intentionally — triggering a re-render on currentReportsToDisplay would cause an infinite loop
         // eslint-disable-next-line react-hooks/exhaustive-deps
-    }, [getUpdatedReports, chatReports, derivedCurrentReportID, priorityMode, betas, transactionViolations, reportNameValuePairs, reportAttributes, reportsDrafts, clearCacheDummyCounter]);
+    }, [getUpdatedReports, chatReports, derivedCurrentReportID, betas, transactionViolations, reportNameValuePairs, reportAttributes, reportsDrafts, clearCacheDummyCounter]);
 
     // Derive a stable boolean map indicating which reports have drafts.
     const hasDraftByReportIDRef = useRef<Record<string, boolean>>({});
@@ -253,16 +255,23 @@ function SidebarOrderedReportsContextProvider({
         setCurrentReportsToDisplay(reportsToDisplayInLHN);
     }, [reportsToDisplayInLHN]);
 
+    const useAlphabeticalSort = activeTab === CONST.INBOX_TAB.UNREADS;
+
     const getOrderedReportIDs = useCallback(
-        () => SidebarUtils.sortReportsToDisplayInLHN(reportsToDisplayInLHN, priorityMode, localeCompare, hasDraftByReportID, reportNameValuePairs, reportAttributes),
+        () => SidebarUtils.sortReportsToDisplayInLHN(reportsToDisplayInLHN, useAlphabeticalSort, localeCompare, hasDraftByReportID, reportNameValuePairs, reportAttributes),
         // Rule disabled intentionally - reports should be sorted only when the reportsToDisplayInLHN changes
         // eslint-disable-next-line react-hooks/exhaustive-deps
-        [reportsToDisplayInLHN, localeCompare, hasDraftByReportID, reportAttributes],
+        [reportsToDisplayInLHN, useAlphabeticalSort, localeCompare, hasDraftByReportID, reportAttributes],
     );
 
     const orderedReportIDs = useMemo(() => getOrderedReportIDs(), [getOrderedReportIDs]);
 
-    // Get the actual reports based on the ordered IDs
+    const filteredReportIDs = useMemo(
+        () => SidebarUtils.filterReportsForInboxTab(orderedReportIDs, reportsToDisplayInLHN, activeTab, hasDraftByReportID, reportNameValuePairs),
+        [orderedReportIDs, reportsToDisplayInLHN, activeTab, hasDraftByReportID, reportNameValuePairs],
+    );
+
+    // Get the actual reports based on the filtered IDs
     const getOrderedReports = useCallback(
         (reportIDs: string[]): OnyxTypes.Report[] => {
             if (!chatReports) {
@@ -273,7 +282,7 @@ function SidebarOrderedReportsContextProvider({
         [chatReports],
     );
 
-    const orderedReports = useMemo(() => getOrderedReports(orderedReportIDs), [getOrderedReports, orderedReportIDs]);
+    const orderedReports = useMemo(() => getOrderedReports(filteredReportIDs), [getOrderedReports, filteredReportIDs]);
 
     const clearLHNCache = useCallback(() => {
         Log.info('[useSidebarOrderedReports] Clearing sidebar cache manually via debug modal');
@@ -281,6 +290,10 @@ function SidebarOrderedReportsContextProvider({
         setClearCacheDummyCounter((current) => current + 1);
     }, []);
 
+    const setActiveTab = useCallback((tab: ValueOf<typeof CONST.INBOX_TAB>) => {
+        setInboxTab(tab);
+    }, []);
+
     const stateValue: SidebarOrderedReportsStateContextValue = useMemo(() => {
         // We need to make sure the current report is in the list of reports, but we do not want
         // to have to re-generate the list every time the currentReportID changes. To do that
@@ -293,33 +306,49 @@ function SidebarOrderedReportsContextProvider({
         // any expense, a new LHN item is added in the list and is visible on web. But on mobile, we
         // just navigate to the screen with expense details, so there seems no point to execute this logic on mobile.
         if (
-            (!shouldUseNarrowLayout || orderedReportIDs.length === 0) &&
+            (!shouldUseNarrowLayout || filteredReportIDs.length === 0) &&
             derivedCurrentReportID &&
             derivedCurrentReportID !== '-1' &&
-            orderedReportIDs.indexOf(derivedCurrentReportID) === -1
+            filteredReportIDs.indexOf(derivedCurrentReportID) === -1
         ) {
             const updatedReportIDs = getOrderedReportIDs();
-            const updatedReports = getOrderedReports(updatedReportIDs);
+            const updatedFilteredIDs = SidebarUtils.filterReportsForInboxTab(updatedReportIDs, reportsToDisplayInLHN, activeTab, hasDraftByReportID, reportNameValuePairs);
+            const updatedReports = getOrderedReports(updatedFilteredIDs);
             return {
                 orderedReports: updatedReports,
-                orderedReportIDs: updatedReportIDs,
+                orderedReportIDs: updatedFilteredIDs,
                 currentReportID: derivedCurrentReportID,
                 chatTabBrickRoad: getChatTabBrickRoad(updatedReportIDs, reportAttributes),
+                activeTab,
             };
         }
 
         return {
             orderedReports,
-            orderedReportIDs,
+            orderedReportIDs: filteredReportIDs,
             currentReportID: derivedCurrentReportID,
             chatTabBrickRoad: getChatTabBrickRoad(orderedReportIDs, reportAttributes),
+            activeTab,
         };
-    }, [getOrderedReportIDs, orderedReportIDs, derivedCurrentReportID, shouldUseNarrowLayout, getOrderedReports, orderedReports, reportAttributes]);
+    }, [
+        getOrderedReportIDs,
+        orderedReportIDs,
+        filteredReportIDs,
+        derivedCurrentReportID,
+        shouldUseNarrowLayout,
+        getOrderedReports,
+        orderedReports,
+        reportAttributes,
+        activeTab,
+        reportsToDisplayInLHN,
+        hasDraftByReportID,
+        reportNameValuePairs,
+    ]);
 
-    const actionsValue: SidebarOrderedReportsActionsContextValue = useMemo(() => ({clearLHNCache}), [clearLHNCache]);
+    const actionsValue: SidebarOrderedReportsActionsContextValue = useMemo(() => ({clearLHNCache, setActiveTab}), [clearLHNCache, setActiveTab]);
 
     const currentDeps = {
-        priorityMode,
+        activeTab,
         chatReports,
         policies,
         transactions,
@@ -334,7 +363,6 @@ function SidebarOrderedReportsContextProvider({
         derivedCurrentReportID,
         prevDerivedCurrentReportID,
         prevBetas,
-        prevPriorityMode,
         reportsToDisplayInLHN,
         orderedReportIDs,
         orderedReports,
diff --git a/src/languages/de.ts b/src/languages/de.ts
index e22f119c149c..9c9f75001ff2 100644
--- a/src/languages/de.ts
+++ b/src/languages/de.ts
@@ -2786,19 +2786,11 @@ ${amount} für ${merchant} – ${date}`,
         receiveRelevantFeatureUpdatesAndExpensifyNews: 'Erhalten Sie relevante Funktionsupdates und Expensify-Neuigkeiten',
         muteAllSounds: 'Alle Expensify-Sounds stummschalten',
     },
-    priorityModePage: {
-        priorityMode: 'Prioritätsmodus',
-        explainerText: 'Wähle, ob du dich nur auf ungelesene und angeheftete Chats #fokussieren möchtest oder alles anzeigen willst, wobei die neuesten und angehefteten Chats oben stehen.',
-        priorityModes: {
-            default: {
-                label: 'Neueste',
-                description: 'Alle Chats nach Neuestem sortiert anzeigen',
-            },
-            gsd: {
-                label: '#fokus',
-                description: 'Nur ungelesene alphabetisch sortiert anzeigen',
-            },
-        },
+    inboxTabs: {
+        all: 'All',
+        unreads: 'Unread',
+        expenses: 'Expenses',
+        directMessages: 'Direct messages',
     },
     reportDetailsPage: {
         inWorkspace: (policyName: string) => `in ${policyName}`,
@@ -3344,11 +3336,6 @@ ${amount} für ${merchant} – ${date}`,
         year: 'Jahr',
         selectYear: 'Bitte ein Jahr auswählen',
     },
-    focusModeUpdateModal: {
-        title: 'Willkommen im #Fokusmodus!',
-        prompt: (priorityModePageUrl: string) =>
-            `Behalte den Überblick, indem du nur ungelesene Chats oder Chats siehst, die deine Aufmerksamkeit benötigen. Keine Sorge, du kannst das jederzeit in den <a href="${priorityModePageUrl}">Einstellungen</a> ändern.`,
-    },
     notFound: {
         chatYouLookingForCannotBeFound: 'Der Chat, den du suchst, kann nicht gefunden werden.',
         getMeOutOfHere: 'Hol mich hier raus',
diff --git a/src/languages/en.ts b/src/languages/en.ts
index fb20d5d83d9c..12480bbb55c4 100644
--- a/src/languages/en.ts
+++ b/src/languages/en.ts
@@ -2840,19 +2840,11 @@ const translations = {
         receiveRelevantFeatureUpdatesAndExpensifyNews: 'Receive relevant feature updates and Expensify news',
         muteAllSounds: 'Mute all sounds from Expensify',
     },
-    priorityModePage: {
-        priorityMode: 'Priority mode',
-        explainerText: 'Choose whether to #focus on unread and pinned chats only, or show everything with the most recent and pinned chats at the top.',
-        priorityModes: {
-            default: {
-                label: 'Most recent',
-                description: 'Show all chats sorted by most recent',
-            },
-            gsd: {
-                label: '#focus',
-                description: 'Only show unread sorted alphabetically',
-            },
-        },
+    inboxTabs: {
+        all: 'All',
+        unreads: 'Unread',
+        expenses: 'Expenses',
+        directMessages: 'Direct messages',
     },
     reportDetailsPage: {
         inWorkspace: (policyName: string) => `in ${policyName}`,
@@ -3410,11 +3402,6 @@ const translations = {
         month: 'Month',
         selectMonth: 'Please select a month',
     },
-    focusModeUpdateModal: {
-        title: 'Welcome to #focus mode!',
-        prompt: (priorityModePageUrl: string) =>
-            `Stay on top of things by only seeing unread chats or chats that need your attention. Don’t worry, you can change this at any point in <a href="${priorityModePageUrl}">settings</a>.`,
-    },
     notFound: {
         chatYouLookingForCannotBeFound: 'The chat you are looking for cannot be found.',
         getMeOutOfHere: 'Get me out of here',
diff --git a/src/languages/es.ts b/src/languages/es.ts
index af44621bc5c6..d9243ca2d933 100644
--- a/src/languages/es.ts
+++ b/src/languages/es.ts
@@ -2657,20 +2657,11 @@ ${amount} para ${merchant} - ${date}`,
         receiveRelevantFeatureUpdatesAndExpensifyNews: 'Recibir noticias sobre Expensify y actualizaciones del producto',
         muteAllSounds: 'Silenciar todos los sonidos de Expensify',
     },
-    priorityModePage: {
-        priorityMode: 'Modo prioridad',
-        explainerText:
-            'Elige #concentración si deseas enfocarte sólo en los chats no leídos y en los anclados, o mostrarlo todo con los chats más recientes y los anclados en la parte superior.',
-        priorityModes: {
-            default: {
-                label: 'Más recientes',
-                description: 'Mostrar todos los chats ordenados desde el más reciente',
-            },
-            gsd: {
-                label: '#concentración',
-                description: 'Mostrar sólo los no leídos ordenados alfabéticamente',
-            },
-        },
+    inboxTabs: {
+        all: 'All',
+        unreads: 'Unread',
+        expenses: 'Expenses',
+        directMessages: 'Direct messages',
     },
     reportDetailsPage: {
         inWorkspace: (policyName) => `en ${policyName}`,
@@ -3219,11 +3210,6 @@ ${amount} para ${merchant} - ${date}`,
         month: 'Mes',
         selectMonth: 'Por favor, selecciona un mes',
     },
-    focusModeUpdateModal: {
-        title: '¡Bienvenido al modo #concentración!',
-        prompt: (priorityModePageUrl) =>
-            `Mantente al tanto de todo viendo sólo los chats no leídos o los que necesitan tu atención. No te preocupes, puedes cambiar el ajuste en cualquier momento desde la <a href="${priorityModePageUrl}">configuración</a>.`,
-    },
     notFound: {
         chatYouLookingForCannotBeFound: 'El chat que estás buscando no se pudo encontrar.',
         getMeOutOfHere: 'Sácame de aquí',
diff --git a/src/languages/fr.ts b/src/languages/fr.ts
index dd2cf4363012..57e3862724a6 100644
--- a/src/languages/fr.ts
+++ b/src/languages/fr.ts
@@ -2792,19 +2792,11 @@ ${amount} pour ${merchant} - ${date}`,
         receiveRelevantFeatureUpdatesAndExpensifyNews: 'Recevoir des mises à jour de fonctionnalités pertinentes et des actualités Expensify',
         muteAllSounds: 'Couper tous les sons d’Expensify',
     },
-    priorityModePage: {
-        priorityMode: 'Mode priorité',
-        explainerText: 'Choisissez de #vous concentrer uniquement sur les discussions non lues et épinglées, ou d’afficher tout avec les discussions les plus récentes et épinglées en haut.',
-        priorityModes: {
-            default: {
-                label: 'Le plus récent',
-                description: 'Afficher toutes les discussions triées par les plus récentes',
-            },
-            gsd: {
-                label: '#focus',
-                description: 'Afficher uniquement les non lus triés par ordre alphabétique',
-            },
-        },
+    inboxTabs: {
+        all: 'All',
+        unreads: 'Unread',
+        expenses: 'Expenses',
+        directMessages: 'Direct messages',
     },
     reportDetailsPage: {
         inWorkspace: (policyName: string) => `dans ${policyName}`,
@@ -3353,11 +3345,6 @@ ${amount} pour ${merchant} - ${date}`,
         year: 'Année',
         selectYear: 'Veuillez sélectionner une année',
     },
-    focusModeUpdateModal: {
-        title: 'Bienvenue en mode #focus !',
-        prompt: (priorityModePageUrl: string) =>
-            `Gardez le contrôle en affichant uniquement les discussions non lues ou celles qui nécessitent votre attention. Ne vous inquiétez pas, vous pouvez modifier ce paramètre à tout moment dans les <a href="${priorityModePageUrl}">paramètres</a>.`,
-    },
     notFound: {
         chatYouLookingForCannotBeFound: 'La discussion que vous recherchez est introuvable.',
         getMeOutOfHere: 'Faites-moi sortir d’ici',
diff --git a/src/languages/it.ts b/src/languages/it.ts
index f177ee5d7b4f..eea77cc79424 100644
--- a/src/languages/it.ts
+++ b/src/languages/it.ts
@@ -2781,19 +2781,11 @@ ${amount} per ${merchant} - ${date}`,
         receiveRelevantFeatureUpdatesAndExpensifyNews: 'Ricevi aggiornamenti rilevanti sulle funzionalità e notizie su Expensify',
         muteAllSounds: 'Disattiva tutti i suoni da Expensify',
     },
-    priorityModePage: {
-        priorityMode: 'Modalità prioritaria',
-        explainerText: 'Scegli se #concentrarti solo sulle chat non lette e fissate, oppure mostrare tutto con le chat più recenti e fissate in alto.',
-        priorityModes: {
-            default: {
-                label: 'Più recenti',
-                description: 'Mostra tutte le chat ordinate dalla più recente',
-            },
-            gsd: {
-                label: '#focus',
-                description: 'Mostra solo i non letti in ordine alfabetico',
-            },
-        },
+    inboxTabs: {
+        all: 'All',
+        unreads: 'Unread',
+        expenses: 'Expenses',
+        directMessages: 'Direct messages',
     },
     reportDetailsPage: {
         inWorkspace: (policyName: string) => `in ${policyName}`,
@@ -3336,11 +3328,6 @@ ${amount} per ${merchant} - ${date}`,
         year: 'Anno',
         selectYear: 'Seleziona un anno',
     },
-    focusModeUpdateModal: {
-        title: 'Benvenuto/a nella modalità #focus!',
-        prompt: (priorityModePageUrl: string) =>
-            `Resta sempre aggiornato vedendo solo le chat non lette o quelle che richiedono la tua attenzione. Non preoccuparti, puoi modificare questa impostazione in qualsiasi momento nelle <a href="${priorityModePageUrl}">impostazioni</a>.`,
-    },
     notFound: {
         chatYouLookingForCannotBeFound: 'La chat che stai cercando non può essere trovata.',
         getMeOutOfHere: 'Fammi uscire di qui',
diff --git a/src/languages/ja.ts b/src/languages/ja.ts
index 5fd9507b6714..455bf7a8850a 100644
--- a/src/languages/ja.ts
+++ b/src/languages/ja.ts
@@ -2754,19 +2754,11 @@ ${date} の ${merchant} への ${amount}`,
         receiveRelevantFeatureUpdatesAndExpensifyNews: '関連する機能のアップデートやExpensifyのニュースを受け取る',
         muteAllSounds: 'Expensify のすべてのサウンドをミュートする',
     },
-    priorityModePage: {
-        priorityMode: '優先モード',
-        explainerText: '未読とピン留めされたチャットのみを#focusに表示するか、すべてのチャットを表示して、最新とピン留めされたチャットを上部に表示するかを選択してください。',
-        priorityModes: {
-            default: {
-                label: '最新',
-                description: '最新順ですべてのチャットを表示',
-            },
-            gsd: {
-                label: '#focus',
-                description: '未読のみをアルファベット順で表示',
-            },
-        },
+    inboxTabs: {
+        all: 'All',
+        unreads: 'Unread',
+        expenses: 'Expenses',
+        directMessages: 'Direct messages',
     },
     reportDetailsPage: {
         inWorkspace: (policyName: string) => `${policyName} 内`,
@@ -3308,11 +3300,6 @@ ${integrationName === CONST.ONBOARDING_ACCOUNTING_MAPPING.other ? 'あなたの'
         year: '年',
         selectYear: '年を選択してください',
     },
-    focusModeUpdateModal: {
-        title: '#focusモードへようこそ！',
-        prompt: (priorityModePageUrl: string) =>
-            `未読のチャットや対応が必要なチャットだけを表示して、常に状況を把握しましょう。いつでも<a href="${priorityModePageUrl}">設定</a>から変更できます。`,
-    },
     notFound: {
         chatYouLookingForCannotBeFound: 'お探しのチャットが見つかりません。',
         getMeOutOfHere: 'ここから出して',
diff --git a/src/languages/nl.ts b/src/languages/nl.ts
index 4447363ef30f..4038df5299d4 100644
--- a/src/languages/nl.ts
+++ b/src/languages/nl.ts
@@ -2779,19 +2779,11 @@ ${amount} voor ${merchant} - ${date}`,
         receiveRelevantFeatureUpdatesAndExpensifyNews: 'Ontvang relevante functiewijzigingen en Expensify-nieuws',
         muteAllSounds: 'Alle geluiden van Expensify dempen',
     },
-    priorityModePage: {
-        priorityMode: 'Prioriteitsmodus',
-        explainerText: 'Kies of je je wilt #focussen op alleen ongelezen en vastgezette chats, of alles wilt weergeven met de meest recente en vastgezette chats bovenaan.',
-        priorityModes: {
-            default: {
-                label: 'Meest recent',
-                description: 'Toon alle chats gesorteerd op meest recent',
-            },
-            gsd: {
-                label: '#focus',
-                description: 'Toon alleen ongelezen, alfabetisch gesorteerd',
-            },
-        },
+    inboxTabs: {
+        all: 'All',
+        unreads: 'Unread',
+        expenses: 'Expenses',
+        directMessages: 'Direct messages',
     },
     reportDetailsPage: {
         inWorkspace: (policyName: string) => `in ${policyName}`,
@@ -3333,11 +3325,6 @@ ${amount} voor ${merchant} - ${date}`,
         year: 'Jaar',
         selectYear: 'Selecteer een jaar',
     },
-    focusModeUpdateModal: {
-        title: 'Welkom bij de #focus-modus!',
-        prompt: (priorityModePageUrl: string) =>
-            `Houd het overzicht door alleen ongelezen chats of chats die je aandacht nodig hebben te zien. Geen zorgen, je kunt dit op elk moment wijzigen in de <a href="${priorityModePageUrl}">instellingen</a>.`,
-    },
     notFound: {
         chatYouLookingForCannotBeFound: 'De chat die je zoekt, kan niet worden gevonden.',
         getMeOutOfHere: 'Haal me hier weg',
diff --git a/src/languages/pl.ts b/src/languages/pl.ts
index fd9e3b730a1d..496974e494b8 100644
--- a/src/languages/pl.ts
+++ b/src/languages/pl.ts
@@ -2772,19 +2772,11 @@ ${amount} dla ${merchant} - ${date}`,
         receiveRelevantFeatureUpdatesAndExpensifyNews: 'Otrzymuj istotne aktualizacje funkcji i wiadomości od Expensify',
         muteAllSounds: 'Wycisz wszystkie dźwięki z Expensify',
     },
-    priorityModePage: {
-        priorityMode: 'Tryb priorytetowy',
-        explainerText: 'Wybierz, czy #skupić się tylko na nieprzeczytanych i przypiętych czatach, czy wyświetlać wszystko, z najnowszymi i przypiętymi czatami na górze.',
-        priorityModes: {
-            default: {
-                label: 'Najnowsze',
-                description: 'Pokaż wszystkie czaty posortowane od najnowszych',
-            },
-            gsd: {
-                label: '#skupienie',
-                description: 'Pokaż tylko nieprzeczytane posortowane alfabetycznie',
-            },
-        },
+    inboxTabs: {
+        all: 'All',
+        unreads: 'Unread',
+        expenses: 'Expenses',
+        directMessages: 'Direct messages',
     },
     reportDetailsPage: {
         inWorkspace: (policyName: string) => `w ${policyName}`,
@@ -3324,11 +3316,6 @@ ${amount} dla ${merchant} - ${date}`,
         year: 'Rok',
         selectYear: 'Wybierz rok',
     },
-    focusModeUpdateModal: {
-        title: 'Witamy w trybie #focus!',
-        prompt: (priorityModePageUrl: string) =>
-            `Miej wszystko pod kontrolą, wyświetlając tylko nieprzeczytane czaty lub czaty wymagające Twojej uwagi. Nie martw się, możesz to zmienić w dowolnym momencie w <a href="${priorityModePageUrl}">ustawieniach</a>.`,
-    },
     notFound: {
         chatYouLookingForCannotBeFound: 'Nie można znaleźć czatu, którego szukasz.',
         getMeOutOfHere: 'Wyprowadź mnie stąd',
diff --git a/src/languages/pt-BR.ts b/src/languages/pt-BR.ts
index 52479b6be5a0..9cecddddfb48 100644
--- a/src/languages/pt-BR.ts
+++ b/src/languages/pt-BR.ts
@@ -2772,19 +2772,11 @@ ${amount} para ${merchant} - ${date}`,
         receiveRelevantFeatureUpdatesAndExpensifyNews: 'Receba atualizações relevantes de recursos e novidades da Expensify',
         muteAllSounds: 'Silenciar todos os sons do Expensify',
     },
-    priorityModePage: {
-        priorityMode: 'Modo prioridade',
-        explainerText: 'Escolha se deseja #focar apenas em chats não lidos e fixados ou mostrar tudo, com os chats mais recentes e fixados no topo.',
-        priorityModes: {
-            default: {
-                label: 'Mais recente',
-                description: 'Mostrar todos os chats ordenados por mais recentes',
-            },
-            gsd: {
-                label: '#foco',
-                description: 'Mostrar apenas não lidas em ordem alfabética',
-            },
-        },
+    inboxTabs: {
+        all: 'All',
+        unreads: 'Unread',
+        expenses: 'Expenses',
+        directMessages: 'Direct messages',
     },
     reportDetailsPage: {
         inWorkspace: (policyName: string) => `em ${policyName}`,
@@ -3325,11 +3317,6 @@ ${amount} para ${merchant} - ${date}`,
         year: 'Ano',
         selectYear: 'Selecione um ano',
     },
-    focusModeUpdateModal: {
-        title: 'Bem-vindo ao modo #focus!',
-        prompt: (priorityModePageUrl: string) =>
-            `Mantenha tudo sob controle vendo apenas os chats não lidos ou que precisam da sua atenção. Não se preocupe, você pode alterar isso a qualquer momento em <a href="${priorityModePageUrl}">configurações</a>.`,
-    },
     notFound: {
         chatYouLookingForCannotBeFound: 'O chat que você está procurando não foi encontrado.',
         getMeOutOfHere: 'Me tire daqui',
diff --git a/src/languages/zh-hans.ts b/src/languages/zh-hans.ts
index 40049ed183d1..aade94e81823 100644
--- a/src/languages/zh-hans.ts
+++ b/src/languages/zh-hans.ts
@@ -2704,19 +2704,11 @@ ${amount}，商户：${merchant} - 日期：${date}`,
         receiveRelevantFeatureUpdatesAndExpensifyNews: '接收相关功能更新和 Expensify 新闻',
         muteAllSounds: '静音所有来自 Expensify 的声音',
     },
-    priorityModePage: {
-        priorityMode: '优先模式',
-        explainerText: '选择仅#focus未读和置顶聊天，或显示所有聊天，并将最新和置顶聊天排在顶部。',
-        priorityModes: {
-            default: {
-                label: '最新',
-                description: '按最新排序显示所有聊天',
-            },
-            gsd: {
-                label: '#focus',
-                description: '仅按字母顺序显示未读',
-            },
-        },
+    inboxTabs: {
+        all: 'All',
+        unreads: 'Unread',
+        expenses: 'Expenses',
+        directMessages: 'Direct messages',
     },
     reportDetailsPage: {
         inWorkspace: (policyName: string) => `在 ${policyName} 中`,
@@ -3255,10 +3247,6 @@ ${amount}，商户：${merchant} - 日期：${date}`,
         year: '年份',
         selectYear: '请选择年份',
     },
-    focusModeUpdateModal: {
-        title: '欢迎进入 #focus 模式！',
-        prompt: (priorityModePageUrl: string) => `通过仅查看未读聊天或需要你关注的聊天来随时掌握进展。别担心，你可以随时在<a href="${priorityModePageUrl}">设置</a>中更改此项。`,
-    },
     notFound: {
         chatYouLookingForCannotBeFound: '找不到您要查找的聊天。',
         getMeOutOfHere: '带我离开这里',
diff --git a/src/libs/API/parameters/UpdateChatPriorityModeParams.ts b/src/libs/API/parameters/UpdateChatPriorityModeParams.ts
deleted file mode 100644
index 8bbb7bf6943c..000000000000
--- a/src/libs/API/parameters/UpdateChatPriorityModeParams.ts
+++ /dev/null
@@ -1,9 +0,0 @@
-import type {ValueOf} from 'type-fest';
-import type CONST from '@src/CONST';
-
-type UpdateChatPriorityModeParams = {
-    value: ValueOf<typeof CONST.PRIORITY_MODE>;
-    automatic: boolean;
-};
-
-export default UpdateChatPriorityModeParams;
diff --git a/src/libs/API/parameters/index.ts b/src/libs/API/parameters/index.ts
index 7c7c54e55efd..96ef0f32a456 100644
--- a/src/libs/API/parameters/index.ts
+++ b/src/libs/API/parameters/index.ts
@@ -91,7 +91,6 @@ export type {default as SignInWithShortLivedAuthTokenParams} from './SignInWithS
 export type {default as SignInWithSupportAuthTokenParams} from './SignInWithSupportAuthTokenParams';
 export type {default as UnlinkLoginParams} from './UnlinkLoginParams';
 export type {default as UpdateAutomaticTimezoneParams} from './UpdateAutomaticTimezoneParams';
-export type {default as UpdateChatPriorityModeParams} from './UpdateChatPriorityModeParams';
 export type {default as DuplicateWorkspaceParams} from './DuplicateWorkspaceParams';
 export type {default as UpdateDateOfBirthParams} from './UpdateDateOfBirthParams';
 export type {default as UpdateDisplayNameParams} from './UpdateDisplayNameParams';
diff --git a/src/libs/API/types.ts b/src/libs/API/types.ts
index 15959c65d415..05255a2dae10 100644
--- a/src/libs/API/types.ts
+++ b/src/libs/API/types.ts
@@ -90,7 +90,6 @@ const WRITE_COMMANDS = {
     VALIDATE_LOGIN: 'ValidateLogin',
     VALIDATE_SECONDARY_LOGIN: 'ValidateSecondaryLogin',
     UPDATE_PREFERRED_EMOJI_SKIN_TONE: 'UpdatePreferredEmojiSkinTone',
-    UPDATE_CHAT_PRIORITY_MODE: 'UpdateChatPriorityMode',
     TOGGLE_PLATFORM_MUTE: 'TogglePlatformMute',
     SET_CONTACT_METHOD_AS_DEFAULT: 'SetContactMethodAsDefault',
     UPDATE_THEME: 'UpdateTheme',
@@ -642,7 +641,6 @@ type WriteCommandParameters = {
     [WRITE_COMMANDS.VALIDATE_LOGIN]: Parameters.ValidateLoginParams;
     [WRITE_COMMANDS.VALIDATE_SECONDARY_LOGIN]: Parameters.ValidateSecondaryLoginParams;
     [WRITE_COMMANDS.UPDATE_PREFERRED_EMOJI_SKIN_TONE]: Parameters.UpdatePreferredEmojiSkinToneParams;
-    [WRITE_COMMANDS.UPDATE_CHAT_PRIORITY_MODE]: Parameters.UpdateChatPriorityModeParams;
     [WRITE_COMMANDS.SET_CONTACT_METHOD_AS_DEFAULT]: Parameters.SetContactMethodAsDefaultParams;
     [WRITE_COMMANDS.TOGGLE_PLATFORM_MUTE]: Parameters.TogglePlatformMuteParams;
     [WRITE_COMMANDS.UPDATE_THEME]: Parameters.UpdateThemeParams;
diff --git a/src/libs/DebugUtils.ts b/src/libs/DebugUtils.ts
index 31a0a1ee5ef5..882b2dc74af7 100644
--- a/src/libs/DebugUtils.ts
+++ b/src/libs/DebugUtils.ts
@@ -1405,7 +1405,6 @@ function getReasonForShowingRowInLHN({
     doesReportHaveViolations,
     hasRBR = false,
     isReportArchived,
-    isInFocusMode = false,
     betas = undefined,
     draftComment,
 }: {
@@ -1414,7 +1413,6 @@ function getReasonForShowingRowInLHN({
     doesReportHaveViolations: boolean;
     hasRBR?: boolean;
     isReportArchived: boolean | undefined;
-    isInFocusMode?: boolean;
     betas?: OnyxEntry<Beta[]>;
     draftComment: string | undefined;
 }): TranslationPaths | null {
@@ -1427,7 +1425,6 @@ function getReasonForShowingRowInLHN({
         chatReport,
         // We can't pass report.reportID because it will cause reason to always be isFocused
         currentReportId: '-1',
-        isInFocusMode,
         betas,
         excludeEmptyChats: true,
         doesReportHaveViolations,
diff --git a/src/libs/Navigation/AppNavigator/AuthScreens.tsx b/src/libs/Navigation/AppNavigator/AuthScreens.tsx
index 9b381ec63314..63ac14d40790 100644
--- a/src/libs/Navigation/AppNavigator/AuthScreens.tsx
+++ b/src/libs/Navigation/AppNavigator/AuthScreens.tsx
@@ -12,7 +12,6 @@ import KYCWallContextProvider from '@components/KYCWall/KYCWallContext';
 import LockedAccountModalProvider from '@components/LockedAccountModalProvider';
 import OpenAppFailureModal from '@components/OpenAppFailureModal';
 import OptionsListContextProvider from '@components/OptionListContextProvider';
-import PriorityModeController from '@components/PriorityModeController';
 import {ProductTrainingContextProvider} from '@components/ProductTrainingContext';
 import {SearchContextProvider} from '@components/Search/SearchContext';
 import {SearchRouterContextProvider} from '@components/Search/SearchRouter/SearchRouterContext';
@@ -410,7 +409,6 @@ function AuthScreens() {
                     <GPSTripStateChecker />
                     <GPSInProgressModal />
                     <OpenAppFailureModal />
-                    <PriorityModeController />
                     <OpenConfirmNavigateExpensifyClassicModal />
                 </ComposeProviders>
             </DelegatorConnectGuard>
diff --git a/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx b/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx
index 36e3c84a261f..3774bbf6a49f 100644
--- a/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx
+++ b/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx
@@ -407,7 +407,6 @@ const SettingsModalStackNavigator = createModalStackNavigator<SettingsNavigatorP
     [SCREENS.SETTINGS.PROFILE.NEW_CONTACT_METHOD_CONFIRM_MAGIC_CODE]: () =>
         require<ReactComponentModule>('../../../../pages/settings/Profile/Contacts/NewContactMethodConfirmMagicCodePage').default,
     [SCREENS.SETTINGS.PROFILE.CONTACT_METHOD_VERIFY_ACCOUNT]: () => require<ReactComponentModule>('../../../../pages/settings/Profile/Contacts/VerifyAccountPage').default,
-    [SCREENS.SETTINGS.PREFERENCES.PRIORITY_MODE]: () => require<ReactComponentModule>('../../../../pages/settings/Preferences/PriorityModePage').default,
     [SCREENS.WORKSPACE.ACCOUNTING.ROOT]: () => require<ReactComponentModule>('../../../../pages/workspace/accounting/PolicyAccountingPage').default,
     [SCREENS.SETTINGS.PREFERENCES.LANGUAGE]: () => require<ReactComponentModule>('../../../../pages/settings/Preferences/LanguagePage').default,
     [SCREENS.SETTINGS.PREFERENCES.THEME]: () => require<ReactComponentModule>('../../../../pages/settings/Preferences/ThemePage').default,
diff --git a/src/libs/Navigation/linkingConfig/RELATIONS/SETTINGS_TO_RHP.ts b/src/libs/Navigation/linkingConfig/RELATIONS/SETTINGS_TO_RHP.ts
index 7e59623ed3ac..7ae9ae4d67dc 100755
--- a/src/libs/Navigation/linkingConfig/RELATIONS/SETTINGS_TO_RHP.ts
+++ b/src/libs/Navigation/linkingConfig/RELATIONS/SETTINGS_TO_RHP.ts
@@ -24,12 +24,7 @@ const SETTINGS_TO_RHP: Partial<Record<keyof SettingsSplitNavigatorParamList, str
         SCREENS.SETTINGS.PROFILE.ADDRESS,
         SCREENS.SETTINGS.SHARE_CODE,
     ],
-    [SCREENS.SETTINGS.PREFERENCES.ROOT]: [
-        SCREENS.SETTINGS.PREFERENCES.PRIORITY_MODE,
-        SCREENS.SETTINGS.PREFERENCES.LANGUAGE,
-        SCREENS.SETTINGS.PREFERENCES.THEME,
-        SCREENS.SETTINGS.PREFERENCES.PAYMENT_CURRENCY,
-    ],
+    [SCREENS.SETTINGS.PREFERENCES.ROOT]: [SCREENS.SETTINGS.PREFERENCES.LANGUAGE, SCREENS.SETTINGS.PREFERENCES.THEME, SCREENS.SETTINGS.PREFERENCES.PAYMENT_CURRENCY],
     [SCREENS.SETTINGS.WALLET.ROOT]: [
         SCREENS.SETTINGS.WALLET.DOMAIN_CARD,
         SCREENS.SETTINGS.WALLET.DOMAIN_CARD_CONFIRM_MAGIC_CODE,
diff --git a/src/libs/Navigation/linkingConfig/RELATIONS/SIDEBAR_TO_RHP.ts b/src/libs/Navigation/linkingConfig/RELATIONS/SIDEBAR_TO_RHP.ts
index 559f38a6afad..b43481e000a2 100644
--- a/src/libs/Navigation/linkingConfig/RELATIONS/SIDEBAR_TO_RHP.ts
+++ b/src/libs/Navigation/linkingConfig/RELATIONS/SIDEBAR_TO_RHP.ts
@@ -6,7 +6,7 @@ import SCREENS from '@src/SCREENS';
  * This means that going back from RHP will take the user directly to the sidebar. On wide layout the default central screen will be used to fill the space.
  */
 const SIDEBAR_TO_RHP: Partial<Record<SplitNavigatorSidebarScreen, string[]>> = {
-    [SCREENS.SETTINGS.ROOT]: [SCREENS.SETTINGS.SHARE_CODE, SCREENS.SETTINGS.PROFILE.STATUS, SCREENS.SETTINGS.PREFERENCES.PRIORITY_MODE],
+    [SCREENS.SETTINGS.ROOT]: [SCREENS.SETTINGS.SHARE_CODE, SCREENS.SETTINGS.PROFILE.STATUS],
 };
 
 export default SIDEBAR_TO_RHP;
diff --git a/src/libs/Navigation/linkingConfig/config.ts b/src/libs/Navigation/linkingConfig/config.ts
index 3057fbe0034d..401ac54bbe29 100644
--- a/src/libs/Navigation/linkingConfig/config.ts
+++ b/src/libs/Navigation/linkingConfig/config.ts
@@ -149,10 +149,6 @@ const config: LinkingOptions<RootNavigatorParamList>['config'] = {
             screens: {
                 [SCREENS.RIGHT_MODAL.SETTINGS]: {
                     screens: {
-                        [SCREENS.SETTINGS.PREFERENCES.PRIORITY_MODE]: {
-                            path: ROUTES.SETTINGS_PRIORITY_MODE,
-                            exact: true,
-                        },
                         [SCREENS.SETTINGS.PREFERENCES.LANGUAGE]: {
                             path: ROUTES.SETTINGS_LANGUAGE,
                             exact: true,
diff --git a/src/libs/Navigation/types.ts b/src/libs/Navigation/types.ts
index 214d096a99d1..c662d36fbdd2 100644
--- a/src/libs/Navigation/types.ts
+++ b/src/libs/Navigation/types.ts
@@ -125,7 +125,6 @@ type SettingsNavigatorParamList = {
         backTo?: Routes;
         forwardTo?: Routes;
     };
-    [SCREENS.SETTINGS.PREFERENCES.PRIORITY_MODE]: undefined;
     [SCREENS.SETTINGS.PREFERENCES.PAYMENT_CURRENCY]: undefined;
     [SCREENS.SETTINGS.PREFERENCES.LANGUAGE]: undefined;
     [SCREENS.SETTINGS.PREFERENCES.THEME]: undefined;
diff --git a/src/libs/OptionsListUtils/index.ts b/src/libs/OptionsListUtils/index.ts
index 6b372a0b54bf..a6a0619ebdc6 100644
--- a/src/libs/OptionsListUtils/index.ts
+++ b/src/libs/OptionsListUtils/index.ts
@@ -2157,7 +2157,6 @@ function isValidReport(option: SearchOption<Report>, policy: OnyxEntry<Policy>,
         currentReportId: topmostReportId,
         betas,
         doesReportHaveViolations,
-        isInFocusMode: false,
         excludeEmptyChats: false,
         includeSelfDM,
         login: option.login,
diff --git a/src/libs/ReportUtils.ts b/src/libs/ReportUtils.ts
index 3c04a6ebab12..d238e7f22b62 100644
--- a/src/libs/ReportUtils.ts
+++ b/src/libs/ReportUtils.ts
@@ -9508,7 +9508,6 @@ type ShouldReportBeInOptionListParams = {
     report: OnyxEntry<Report>;
     chatReport: OnyxEntry<Report>;
     currentReportId: string | undefined;
-    isInFocusMode: boolean;
     betas: OnyxEntry<Beta[]>;
     excludeEmptyChats: boolean;
     doesReportHaveViolations: boolean;
@@ -9525,7 +9524,6 @@ function reasonForReportToBeInOptionList({
     report,
     chatReport,
     currentReportId,
-    isInFocusMode,
     betas,
     excludeEmptyChats,
     doesReportHaveViolations,
@@ -9536,8 +9534,6 @@ function reasonForReportToBeInOptionList({
     isReportArchived,
     requiresAttention,
 }: ShouldReportBeInOptionListParams): ValueOf<typeof CONST.REPORT_IN_LHN_REASONS> | null {
-    const isInDefaultMode = !isInFocusMode;
-
     // Include the currently viewed report. If we excluded the currently viewed report, then there
     // would be no way to highlight it in the options list and it would be confusing to users because they lose
     // a sense of context.
@@ -9656,17 +9652,8 @@ function reasonForReportToBeInOptionList({
         return CONST.REPORT_IN_LHN_REASONS.HAS_ADD_WORKSPACE_ROOM_ERRORS;
     }
 
-    // All unread chats (even archived ones) in GSD mode will be shown. This is because GSD mode is specifically for focusing the user on the most relevant chats, primarily, the unread ones
-    if (isInFocusMode) {
-        const oneTransactionThreadReportID = getOneTransactionThreadReportID(report, chatReport, currentReportActions);
-        const oneTransactionThreadReport = deprecatedAllReports?.[`${ONYXKEYS.COLLECTION.REPORT}${oneTransactionThreadReportID}`];
-        return isUnread(report, oneTransactionThreadReport, isReportArchived) && getReportNotificationPreference(report) !== CONST.REPORT.NOTIFICATION_PREFERENCE.MUTE
-            ? CONST.REPORT_IN_LHN_REASONS.IS_UNREAD
-            : null;
-    }
-
-    // Archived reports should always be shown when in default (most recent) mode. This is because you should still be able to access and search for the chats to find them.
-    if (isInDefaultMode && isArchivedNonExpenseReport(report, isReportArchived)) {
+    // Archived reports should always be shown so users can still access and search for them.
+    if (isArchivedNonExpenseReport(report, isReportArchived)) {
         return CONST.REPORT_IN_LHN_REASONS.IS_ARCHIVED;
     }
 
diff --git a/src/libs/SidebarUtils.ts b/src/libs/SidebarUtils.ts
index f85b14ff3336..623caf8ad8d8 100644
--- a/src/libs/SidebarUtils.ts
+++ b/src/libs/SidebarUtils.ts
@@ -21,7 +21,6 @@ import type Beta from '@src/types/onyx/Beta';
 import type {ReportAttributes} from '@src/types/onyx/DerivedValues';
 import type {Errors} from '@src/types/onyx/OnyxCommon';
 import type Policy from '@src/types/onyx/Policy';
-import type PriorityMode from '@src/types/onyx/PriorityMode';
 import type Report from '@src/types/onyx/Report';
 import type ReportAction from '@src/types/onyx/ReportAction';
 import {formatPhoneNumber as formatPhoneNumberPhoneUtils} from './LocalePhoneNumber';
@@ -169,6 +168,7 @@ import {
     isChatThread,
     isConciergeChatReport,
     isDeprecatedGroupDM,
+    isDM,
     isDomainRoom,
     isExpenseReport,
     isExpenseRequest,
@@ -177,6 +177,7 @@ import {
     isInvoiceReport,
     isInvoiceRoom,
     isIOUOwnedByCurrentUser,
+    isIOUReport,
     isJoinRequestInAdminRoom,
     isMoneyRequestReport,
     isOneOnOneChat,
@@ -264,7 +265,6 @@ function shouldDisplayReportInLHN(
     report: Report,
     reports: OnyxCollection<Report>,
     currentReportId: string | undefined,
-    isInFocusMode: boolean,
     betas: OnyxEntry<Beta[]>,
     transactionViolations: OnyxCollection<TransactionViolation[]>,
     draftComment: OnyxEntry<string>,
@@ -320,7 +320,6 @@ function shouldDisplayReportInLHN(
         report,
         chatReport,
         currentReportId,
-        isInFocusMode,
         betas,
         excludeEmptyChats: true,
         doesReportHaveViolations,
@@ -337,14 +336,12 @@ function getReportsToDisplayInLHN(
     currentReportId: string | undefined,
     reports: OnyxCollection<Report>,
     betas: OnyxEntry<Beta[]>,
-    priorityMode: OnyxEntry<PriorityMode>,
     draftComments: OnyxCollection<string>,
     transactionViolations: OnyxCollection<TransactionViolation[]>,
     transactions: OnyxCollection<Transaction>,
     reportNameValuePairs?: OnyxCollection<ReportNameValuePairs>,
     reportAttributes?: ReportAttributesDerivedValue['reports'],
 ) {
-    const isInFocusMode = priorityMode === CONST.PRIORITY_MODE.GSD;
     const allReportsDictValues = reports ?? {};
     const reportsToDisplay: ReportsToDisplayInLHN = {};
 
@@ -359,7 +356,6 @@ function getReportsToDisplayInLHN(
             report,
             reports,
             currentReportId,
-            isInFocusMode,
             betas,
             transactionViolations,
             reportDraftComment,
@@ -383,7 +379,6 @@ type UpdateReportsToDisplayInLHNProps = {
     reports: OnyxCollection<Report>;
     updatedReportsKeys: string[];
     currentReportId: string | undefined;
-    isInFocusMode: boolean;
     betas: OnyxEntry<Beta[]>;
     transactionViolations: OnyxCollection<TransactionViolation[]>;
     reportNameValuePairs?: OnyxCollection<ReportNameValuePairs>;
@@ -397,7 +392,6 @@ function updateReportsToDisplayInLHN({
     reports,
     updatedReportsKeys,
     currentReportId,
-    isInFocusMode,
     betas,
     transactionViolations,
     reportNameValuePairs,
@@ -431,7 +425,6 @@ function updateReportsToDisplayInLHN({
             report,
             reports,
             currentReportId,
-            isInFocusMode,
             betas,
             transactionViolations,
             reportDraftComment,
@@ -626,24 +619,23 @@ function combineReportCategories(
  */
 function sortReportsToDisplayInLHN(
     reportsToDisplay: ReportsToDisplayInLHN,
-    priorityMode: OnyxEntry<PriorityMode>,
+    useAlphabeticalSort: boolean,
     localeCompare: LocaleContextProps['localeCompare'],
     reportsDrafts: Record<string, boolean> | undefined,
     reportNameValuePairs: OnyxCollection<ReportNameValuePairs> | undefined,
     reportAttributes: ReportAttributesDerivedValue['reports'] | undefined,
 ): string[] {
-    const isInFocusMode = priorityMode === CONST.PRIORITY_MODE.GSD;
-    const isInDefaultMode = !isInFocusMode;
+    const isInDefaultMode = !useAlphabeticalSort;
     // The LHN is split into five distinct groups, and each group is sorted a little differently. The groups will ALWAYS be in this order:
     // 1. Pinned/GBR - Always sorted by reportDisplayName
     // 2. Error reports - Always sorted by reportDisplayName
     // 3. Drafts - Always sorted by reportDisplayName
     // 4. Non-archived reports and settled IOUs
-    //      - Sorted by lastVisibleActionCreated in default (most recent) view mode
-    //      - Sorted by reportDisplayName in GSD (focus) view mode
+    //      - Sorted by lastVisibleActionCreated when not using alphabetical sort
+    //      - Sorted by reportDisplayName when using alphabetical sort
     // 5. Archived reports
-    //      - Sorted by lastVisibleActionCreated in default (most recent) view mode
-    //      - Sorted by reportDisplayName in GSD (focus) view mode
+    //      - Sorted by lastVisibleActionCreated when not using alphabetical sort
+    //      - Sorted by reportDisplayName when using alphabetical sort
 
     // Step 1: Categorize reports
     const categories = categorizeReportsForLHN(reportsToDisplay, reportsDrafts, reportAttributes, reportNameValuePairs);
@@ -1416,6 +1408,40 @@ function getRoomWelcomeMessage(
     return welcomeMessage;
 }
 
+function filterReportsForInboxTab(
+    reportIDs: string[],
+    reportsToDisplay: ReportsToDisplayInLHN,
+    activeTab: ValueOf<typeof CONST.INBOX_TAB>,
+    reportsDrafts?: Record<string, boolean>,
+    reportNameValuePairs?: OnyxCollection<ReportNameValuePairs>,
+): string[] {
+    if (activeTab === CONST.INBOX_TAB.ALL) {
+        return reportIDs;
+    }
+
+    return reportIDs.filter((reportID) => {
+        const report = reportsToDisplay[`${ONYXKEYS.COLLECTION.REPORT}${reportID}`];
+        if (!report) {
+            return false;
+        }
+
+        switch (activeTab) {
+            case CONST.INBOX_TAB.UNREADS: {
+                const isReportArchived = isArchivedReport(reportNameValuePairs?.[`${ONYXKEYS.COLLECTION.REPORT_NAME_VALUE_PAIRS}${reportID}`]);
+                const isReportUnread = isUnread(report, undefined, isReportArchived) && getReportNotificationPreference(report) !== CONST.REPORT.NOTIFICATION_PREFERENCE.MUTE;
+                const hasDraft = !!reportsDrafts?.[reportID];
+                return isReportUnread || !!report.isPinned || !!report.requiresAttention || !!report.hasErrorsOtherThanFailedReceipt || hasDraft;
+            }
+            case CONST.INBOX_TAB.EXPENSES:
+                return isExpenseReport(report) || isIOUReport(report) || isInvoiceReport(report) || isPolicyExpenseChat(report);
+            case CONST.INBOX_TAB.DIRECT_MESSAGES:
+                return isDM(report) || isSelfDM(report) || isGroupChatUtil(report);
+            default:
+                return true;
+        }
+    });
+}
+
 // Exported for unit testing only. Do not use directly in production code.
 export {
     categorizeReportsForLHN as _categorizeReportsForLHN,
@@ -1427,6 +1453,7 @@ export {
 export default {
     getOptionData,
     sortReportsToDisplayInLHN,
+    filterReportsForInboxTab,
     getWelcomeMessage,
     getReasonAndReportActionThatHasRedBrickRoad,
     getReportsToDisplayInLHN,
diff --git a/src/libs/UnreadIndicatorUpdater/index.ts b/src/libs/UnreadIndicatorUpdater/index.ts
index 272620e70b58..b3066332fa2f 100644
--- a/src/libs/UnreadIndicatorUpdater/index.ts
+++ b/src/libs/UnreadIndicatorUpdater/index.ts
@@ -58,7 +58,6 @@ function getUnreadReportsForUnreadIndicator(reports: OnyxCollection<Report>, cur
                 currentReportId: currentReportID,
                 betas: [],
                 doesReportHaveViolations: false,
-                isInFocusMode: false,
                 excludeEmptyChats: false,
                 isReportArchived,
                 draftComment,
diff --git a/src/libs/actions/App.ts b/src/libs/actions/App.ts
index 82a90babd548..2cc411ee3d2f 100644
--- a/src/libs/actions/App.ts
+++ b/src/libs/actions/App.ts
@@ -128,7 +128,6 @@ const KEYS_TO_PRESERVE: OnyxKey[] = [
     ONYXKEYS.NETWORK,
     ONYXKEYS.SESSION,
     ONYXKEYS.SHOULD_SHOW_COMPOSE_INPUT,
-    ONYXKEYS.NVP_TRY_FOCUS_MODE,
     ONYXKEYS.PREFERRED_THEME,
     ONYXKEYS.NVP_PREFERRED_LOCALE,
     ONYXKEYS.CREDENTIALS,
diff --git a/src/libs/actions/Delegate.ts b/src/libs/actions/Delegate.ts
index a31097d7e3a7..bea82b9297c4 100644
--- a/src/libs/actions/Delegate.ts
+++ b/src/libs/actions/Delegate.ts
@@ -21,7 +21,6 @@ import updateSessionAuthTokens from './Session/updateSessionAuthTokens';
 import updateSessionUser from './Session/updateSessionUser';
 
 const KEYS_TO_PRESERVE_DELEGATE_ACCESS = [
-    ONYXKEYS.NVP_TRY_FOCUS_MODE,
     ONYXKEYS.PREFERRED_THEME,
     ONYXKEYS.NVP_PREFERRED_LOCALE,
     ONYXKEYS.RAM_ONLY_ARE_TRANSLATIONS_LOADING,
diff --git a/src/libs/actions/QueuedOnyxUpdates.ts b/src/libs/actions/QueuedOnyxUpdates.ts
index 62ce86816243..32ff59170cc7 100644
--- a/src/libs/actions/QueuedOnyxUpdates.ts
+++ b/src/libs/actions/QueuedOnyxUpdates.ts
@@ -35,7 +35,6 @@ function flushQueue(): Promise<void> {
     if (!currentAccountID && !CONFIG.IS_TEST_ENV) {
         const preservedKeys = new Set<OnyxKey>([
             ONYXKEYS.NVP_TRY_NEW_DOT,
-            ONYXKEYS.NVP_TRY_FOCUS_MODE,
             ONYXKEYS.PREFERRED_THEME,
             ONYXKEYS.NVP_PREFERRED_LOCALE,
             ONYXKEYS.RAM_ONLY_ARE_TRANSLATIONS_LOADING,
diff --git a/src/libs/actions/Session/index.ts b/src/libs/actions/Session/index.ts
index 8047f230359c..c0f55b9817ab 100644
--- a/src/libs/actions/Session/index.ts
+++ b/src/libs/actions/Session/index.ts
@@ -296,7 +296,6 @@ function isExpiredSession(sessionCreationDate: number): boolean {
 }
 
 const KEYS_TO_PRESERVE_SUPPORTAL = [
-    ONYXKEYS.NVP_TRY_FOCUS_MODE,
     ONYXKEYS.PREFERRED_THEME,
     ONYXKEYS.NVP_PREFERRED_LOCALE,
     ONYXKEYS.RAM_ONLY_ARE_TRANSLATIONS_LOADING,
diff --git a/src/libs/actions/User.ts b/src/libs/actions/User.ts
index b1fce73ddde6..138d02d821d5 100644
--- a/src/libs/actions/User.ts
+++ b/src/libs/actions/User.ts
@@ -18,7 +18,6 @@ import type {
     SetContactMethodAsDefaultParams,
     SetNameValuePairParams,
     TogglePlatformMuteParams,
-    UpdateChatPriorityModeParams,
     UpdateNewsletterSubscriptionParams,
     UpdatePreferredEmojiSkinToneParams,
     UpdateStatusParams,
@@ -950,37 +949,8 @@ function updatePreferredSkinTone(skinTone: number) {
     API.write(WRITE_COMMANDS.UPDATE_PREFERRED_EMOJI_SKIN_TONE, parameters, {optimisticData});
 }
 
-/**
- * Sync user chat priority mode with Onyx and Server
- * @param mode
- * @param [automatic] if we changed the mode automatically
- */
-function updateChatPriorityMode(mode: ValueOf<typeof CONST.PRIORITY_MODE>, automatic = false) {
-    const autoSwitchedToFocusMode = mode === CONST.PRIORITY_MODE.GSD && automatic;
-    const optimisticData: Array<OnyxUpdate<typeof ONYXKEYS.NVP_PRIORITY_MODE | typeof ONYXKEYS.NVP_TRY_FOCUS_MODE>> = [
-        {
-            onyxMethod: Onyx.METHOD.MERGE,
-            key: ONYXKEYS.NVP_PRIORITY_MODE,
-            value: mode,
-        },
-    ];
-
-    optimisticData.push({
-        onyxMethod: Onyx.METHOD.MERGE,
-        key: ONYXKEYS.NVP_TRY_FOCUS_MODE,
-        value: true,
-    });
-
-    const parameters: UpdateChatPriorityModeParams = {
-        value: mode,
-        automatic,
-    };
-
-    API.write(WRITE_COMMANDS.UPDATE_CHAT_PRIORITY_MODE, parameters, {optimisticData});
-
-    if (!autoSwitchedToFocusMode) {
-        Navigation.goBack();
-    }
+function setInboxTab(tab: ValueOf<typeof CONST.INBOX_TAB>) {
+    Onyx.merge(ONYXKEYS.NVP_INBOX_TAB, tab);
 }
 
 function setShouldUseStagingServer(shouldUseStagingServer: boolean) {
@@ -1907,12 +1877,12 @@ export {
     isBlockedFromConcierge,
     subscribeToUserEvents,
     updatePreferredSkinTone,
+    setInboxTab,
     setShouldUseStagingServer,
     togglePlatformMute,
     joinScreenShare,
     clearScreenShareRequest,
     generateStatementPDF,
-    updateChatPriorityMode,
     setContactMethodAsDefault,
     updateTheme,
     resetContactMethodValidateCodeSentState,
diff --git a/src/pages/Debug/Report/DebugReportPage.tsx b/src/pages/Debug/Report/DebugReportPage.tsx
index 1510b45cfddc..de203b55cc32 100644
--- a/src/pages/Debug/Report/DebugReportPage.tsx
+++ b/src/pages/Debug/Report/DebugReportPage.tsx
@@ -69,7 +69,6 @@ function DebugReportPage({
         [reportAttributesSelector],
     );
     const [draftComment] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT_DRAFT_COMMENT}${reportID}`);
-    const [priorityMode] = useOnyx(ONYXKEYS.NVP_PRIORITY_MODE);
     const [betas] = useOnyx(ONYXKEYS.BETAS);
     const [conciergeReportID] = useOnyx(ONYXKEYS.CONCIERGE_REPORT_ID);
     const [introSelected] = useOnyx(ONYXKEYS.NVP_INTRO_SELECTED);
@@ -106,7 +105,6 @@ function DebugReportPage({
             doesReportHaveViolations: shouldDisplayViolations,
             hasRBR,
             isReportArchived,
-            isInFocusMode: priorityMode === CONST.PRIORITY_MODE.GSD,
             draftComment,
         });
 
@@ -153,7 +151,7 @@ function DebugReportPage({
                         : undefined,
             },
         ];
-    }, [report, transactionViolations, isReportArchived, chatReport, reportActions, transactions, reportAttributes?.reportErrors, betas, priorityMode, draftComment, translate]);
+    }, [report, transactionViolations, isReportArchived, chatReport, reportActions, transactions, reportAttributes?.reportErrors, betas, draftComment, translate]);
 
     const icons = useMemoizedLazyExpensifyIcons(['Eye']);
 
diff --git a/src/pages/inbox/sidebar/BaseSidebarScreen.tsx b/src/pages/inbox/sidebar/BaseSidebarScreen.tsx
index f20aa890543e..fb4a748e7460 100644
--- a/src/pages/inbox/sidebar/BaseSidebarScreen.tsx
+++ b/src/pages/inbox/sidebar/BaseSidebarScreen.tsx
@@ -14,6 +14,7 @@ import useThemeStyles from '@hooks/useThemeStyles';
 import {isMobile} from '@libs/Browser';
 import type {SkeletonSpanReasonAttributes} from '@libs/telemetry/useSkeletonSpan';
 import ONYXKEYS from '@src/ONYXKEYS';
+import InboxTabSelector from './InboxTabSelector';
 import SidebarLinksData from './SidebarLinksData';
 
 // Once the app finishes loading for the first time, we never show the skeleton again
@@ -59,6 +60,7 @@ function BaseSidebarScreen() {
                         shouldDisplaySearch={shouldUseNarrowLayout}
                         shouldDisplayHelpButton={shouldUseNarrowLayout}
                     />
+                    {!shouldShowSkeleton && <InboxTabSelector />}
                     <View style={[styles.flex1]}>
                         {shouldShowSkeleton ? (
                             <OptionsListSkeletonView
diff --git a/src/pages/inbox/sidebar/InboxTabSelector.tsx b/src/pages/inbox/sidebar/InboxTabSelector.tsx
new file mode 100644
index 000000000000..d8e75506b891
--- /dev/null
+++ b/src/pages/inbox/sidebar/InboxTabSelector.tsx
@@ -0,0 +1,35 @@
+import React from 'react';
+import TabSelectorBase from '@components/TabSelector/TabSelectorBase';
+import TabSelectorContextProvider from '@components/TabSelector/TabSelectorContext';
+import type {TabSelectorBaseItem} from '@components/TabSelector/types';
+import useLocalize from '@hooks/useLocalize';
+import {useSidebarOrderedReportsActions, useSidebarOrderedReportsState} from '@hooks/useSidebarOrderedReports';
+import CONST from '@src/CONST';
+
+function InboxTabSelector() {
+    const {translate} = useLocalize();
+    const {activeTab} = useSidebarOrderedReportsState();
+    const {setActiveTab} = useSidebarOrderedReportsActions();
+
+    const tabs: TabSelectorBaseItem[] = [
+        {key: CONST.INBOX_TAB.ALL, title: translate('inboxTabs.all')},
+        {key: CONST.INBOX_TAB.UNREADS, title: translate('inboxTabs.unreads')},
+        {key: CONST.INBOX_TAB.EXPENSES, title: translate('inboxTabs.expenses')},
+        {key: CONST.INBOX_TAB.DIRECT_MESSAGES, title: translate('inboxTabs.directMessages')},
+    ];
+
+    return (
+        <TabSelectorContextProvider activeTabKey={activeTab}>
+            <TabSelectorBase
+                tabs={tabs}
+                activeTabKey={activeTab}
+                onTabPress={setActiveTab}
+                size="small"
+            />
+        </TabSelectorContextProvider>
+    );
+}
+
+InboxTabSelector.displayName = 'InboxTabSelector';
+
+export default InboxTabSelector;
diff --git a/src/pages/inbox/sidebar/SidebarLinks.tsx b/src/pages/inbox/sidebar/SidebarLinks.tsx
index 6793096bc0fe..38d7d019de41 100644
--- a/src/pages/inbox/sidebar/SidebarLinks.tsx
+++ b/src/pages/inbox/sidebar/SidebarLinks.tsx
@@ -1,8 +1,6 @@
 import React, {memo, useCallback, useEffect, useMemo} from 'react';
 import {StyleSheet, View} from 'react-native';
-import type {OnyxEntry} from 'react-native-onyx';
 import type {EdgeInsets} from 'react-native-safe-area-context';
-import type {ValueOf} from 'type-fest';
 import LHNEmptyState from '@components/LHNOptionsList/LHNEmptyState';
 import LHNOptionsList from '@components/LHNOptionsList/LHNOptionsList';
 import OptionsListSkeletonView from '@components/OptionsListSkeletonView';
@@ -28,14 +26,11 @@ type SidebarLinksProps = {
     /** List of options to display */
     optionListItems: Report[];
 
-    /** The chat priority mode */
-    priorityMode?: OnyxEntry<ValueOf<typeof CONST.PRIORITY_MODE>>;
-
     /** Method to change currently active report */
     isActiveReport: (reportID: string) => boolean;
 };
 
-function SidebarLinks({insets, optionListItems, priorityMode = CONST.PRIORITY_MODE.DEFAULT, isActiveReport}: SidebarLinksProps) {
+function SidebarLinks({insets, optionListItems, isActiveReport}: SidebarLinksProps) {
     const styles = useThemeStyles();
     const StyleUtils = useStyleUtils();
     const {shouldUseNarrowLayout} = useResponsiveLayout();
@@ -74,8 +69,6 @@ function SidebarLinks({insets, optionListItems, priorityMode = CONST.PRIORITY_MO
         [shouldUseNarrowLayout, isActiveReport],
     );
 
-    const viewMode = priorityMode === CONST.PRIORITY_MODE.GSD ? CONST.OPTION_MODE.COMPACT : CONST.OPTION_MODE.DEFAULT;
-
     const sidebarSkeletonReasonAttributes: SkeletonSpanReasonAttributes = {
         context: 'SidebarLinks',
         isLoadingReportData,
@@ -101,7 +94,7 @@ function SidebarLinks({insets, optionListItems, priorityMode = CONST.PRIORITY_MO
                         data={optionListItems}
                         onSelectRow={showReportPage}
                         shouldDisableFocusOptions={shouldUseNarrowLayout}
-                        optionMode={viewMode}
+                        optionMode={CONST.OPTION_MODE.DEFAULT}
                         onFirstItemRendered={setSidebarLoaded}
                     />
                 )}
diff --git a/src/pages/inbox/sidebar/SidebarLinksData.tsx b/src/pages/inbox/sidebar/SidebarLinksData.tsx
index 1c4879c15884..39e75e8a5396 100644
--- a/src/pages/inbox/sidebar/SidebarLinksData.tsx
+++ b/src/pages/inbox/sidebar/SidebarLinksData.tsx
@@ -4,12 +4,10 @@ import React, {useCallback, useEffect, useRef} from 'react';
 import {View} from 'react-native';
 import type {EdgeInsets} from 'react-native-safe-area-context';
 import useLocalize from '@hooks/useLocalize';
-import useOnyx from '@hooks/useOnyx';
 import {useSidebarOrderedReportsState} from '@hooks/useSidebarOrderedReports';
 import useThemeStyles from '@hooks/useThemeStyles';
 import {cancelSpan, endSpan, getSpan} from '@libs/telemetry/activeSpans';
 import CONST from '@src/CONST';
-import ONYXKEYS from '@src/ONYXKEYS';
 import SidebarLinks from './SidebarLinks';
 
 type SidebarLinksDataProps = {
@@ -21,7 +19,6 @@ function SidebarLinksData({insets}: SidebarLinksDataProps) {
     const isFocused = useIsFocused();
     const styles = useThemeStyles();
     const {translate} = useLocalize();
-    const [priorityMode = CONST.PRIORITY_MODE.DEFAULT] = useOnyx(ONYXKEYS.NVP_PRIORITY_MODE);
 
     const {orderedReports, currentReportID} = useSidebarOrderedReportsState('SidebarLinksData');
 
@@ -75,10 +72,7 @@ function SidebarLinksData({insets}: SidebarLinksDataProps) {
             onLayout={onLayout}
         >
             <SidebarLinks
-                // Forwarded props:
                 insets={insets}
-                priorityMode={priorityMode ?? CONST.PRIORITY_MODE.DEFAULT}
-                // Data props:
                 isActiveReport={isActiveReport}
                 optionListItems={orderedReports}
             />
diff --git a/src/pages/settings/Preferences/PreferencesPage.tsx b/src/pages/settings/Preferences/PreferencesPage.tsx
index b3426c834830..28bdc3836966 100755
--- a/src/pages/settings/Preferences/PreferencesPage.tsx
+++ b/src/pages/settings/Preferences/PreferencesPage.tsx
@@ -32,8 +32,6 @@ function PreferencesPage() {
     const {getCurrencySymbol} = useCurrencyListActions();
     const illustrations = useMemoizedLazyIllustrations(['Gears']);
     const preferencesIllustration = usePreferencesSectionIllustration();
-    const [priorityMode] = useOnyx(ONYXKEYS.NVP_PRIORITY_MODE);
-
     const platform = getPlatform(true);
     const [mutedPlatforms = getEmptyObject<Partial<Record<Platform, true>>>()] = useOnyx(ONYXKEYS.NVP_MUTED_PLATFORMS);
     const isPlatformMuted = mutedPlatforms[platform];
@@ -113,14 +111,6 @@ function PreferencesPage() {
                                     />
                                 </View>
                             </View>
-                            <MenuItemWithTopDescription
-                                shouldShowRightIcon
-                                title={translate(`priorityModePage.priorityModes.${priorityMode ?? CONST.PRIORITY_MODE.DEFAULT}.label`)}
-                                description={translate('priorityModePage.priorityMode')}
-                                onPress={() => Navigation.navigate(ROUTES.SETTINGS_PRIORITY_MODE)}
-                                wrapperStyle={styles.sectionMenuItemTopDescription}
-                                sentryLabel={CONST.SENTRY_LABEL.SETTINGS_PREFERENCES.PRIORITY_MODE}
-                            />
                             <MenuItemWithTopDescription
                                 shouldShowRightIcon
                                 title={preferredLocale ? LOCALE_TO_LANGUAGE_STRING[preferredLocale] : undefined}
diff --git a/src/pages/settings/Preferences/PriorityModePage.tsx b/src/pages/settings/Preferences/PriorityModePage.tsx
deleted file mode 100644
index 50e9355cdba5..000000000000
--- a/src/pages/settings/Preferences/PriorityModePage.tsx
+++ /dev/null
@@ -1,68 +0,0 @@
-import React, {useCallback} from 'react';
-import type {ValueOf} from 'type-fest';
-import HeaderWithBackButton from '@components/HeaderWithBackButton';
-import ScreenWrapper from '@components/ScreenWrapper';
-import SelectionList from '@components/SelectionList';
-import RadioListItem from '@components/SelectionList/ListItem/RadioListItem';
-import Text from '@components/Text';
-import useLocalize from '@hooks/useLocalize';
-import useOnyx from '@hooks/useOnyx';
-import useThemeStyles from '@hooks/useThemeStyles';
-import {updateChatPriorityMode} from '@libs/actions/User';
-import Navigation from '@libs/Navigation/Navigation';
-import CONST from '@src/CONST';
-import ONYXKEYS from '@src/ONYXKEYS';
-
-type PriorityModeItem = {
-    value: ValueOf<typeof CONST.PRIORITY_MODE>;
-    text: string;
-    alternateText: string;
-    keyForList: ValueOf<typeof CONST.PRIORITY_MODE>;
-    isSelected: boolean;
-};
-
-function PriorityModePage() {
-    const {translate} = useLocalize();
-    const [priorityMode = CONST.PRIORITY_MODE.DEFAULT] = useOnyx(ONYXKEYS.NVP_PRIORITY_MODE);
-    const styles = useThemeStyles();
-    const priorityModes = Object.values(CONST.PRIORITY_MODE).map<PriorityModeItem>((mode) => ({
-        value: mode,
-        text: translate(`priorityModePage.priorityModes.${mode}.label`),
-        alternateText: translate(`priorityModePage.priorityModes.${mode}.description`),
-        keyForList: mode,
-        isSelected: priorityMode === mode,
-    }));
-
-    const updateMode = useCallback(
-        (mode: PriorityModeItem) => {
-            if (mode.value === priorityMode) {
-                Navigation.goBack();
-                return;
-            }
-            updateChatPriorityMode(mode.value);
-        },
-        [priorityMode],
-    );
-
-    return (
-        <ScreenWrapper
-            includeSafeAreaPaddingBottom={false}
-            testID="PriorityModePage"
-        >
-            <HeaderWithBackButton
-                title={translate('priorityModePage.priorityMode')}
-                onBackButtonPress={() => Navigation.goBack()}
-            />
-            <Text style={[styles.mh5, styles.mv3]}>{translate('priorityModePage.explainerText')}</Text>
-            <SelectionList
-                data={priorityModes}
-                ListItem={RadioListItem}
-                onSelectRow={updateMode}
-                shouldSingleExecuteRowSelect
-                initiallyFocusedItemKey={priorityModes.find((mode) => mode.isSelected)?.keyForList}
-            />
-        </ScreenWrapper>
-    );
-}
-
-export default PriorityModePage;
diff --git a/src/styles/index.ts b/src/styles/index.ts
index 71ec72fea456..eae83119cc2f 100644
--- a/src/styles/index.ts
+++ b/src/styles/index.ts
@@ -4359,6 +4359,11 @@ const staticStyles = (theme: ThemeColors) =>
             scrollMarginInline: variables.tabSelectorScrollMarginInline,
         },
 
+        tabSelectorButtonSmall: {
+            height: variables.componentSizeSmall,
+            paddingHorizontal: 12,
+        },
+
         tabSelector: {
             flexDirection: 'row',
             paddingHorizontal: 20,
@@ -4371,6 +4376,11 @@ const staticStyles = (theme: ThemeColors) =>
             paddingHorizontal: 20,
         },
 
+        tabSelectorContentContainerSmall: {
+            paddingTop: 4,
+            paddingBottom: 4,
+        },
+
         scrollableTabSelector: {
             flexGrow: 0,
         },
@@ -6209,6 +6219,11 @@ const dynamicStyles = (theme: ThemeColors) =>
                 fontSize: variables.fontSizeLabel,
             }) satisfies TextStyle,
 
+        tabTextSmall: {
+            fontSize: variables.fontSizeSmall,
+            lineHeight: 16,
+        } satisfies TextStyle,
+
         tabBackground: (hovered: boolean, isFocused: boolean, isDisabled: boolean, background: string | Animated.AnimatedInterpolation<string>) => {
             if (isDisabled) {
                 return {backgroundColor: undefined};
diff --git a/src/types/onyx/InboxTab.ts b/src/types/onyx/InboxTab.ts
new file mode 100644
index 000000000000..616f5b89f764
--- /dev/null
+++ b/src/types/onyx/InboxTab.ts
@@ -0,0 +1,6 @@
+import type {ValueOf} from 'type-fest';
+import type CONST from '@src/CONST';
+
+type InboxTab = ValueOf<typeof CONST.INBOX_TAB>;
+
+export default InboxTab;
diff --git a/src/types/onyx/PriorityMode.ts b/src/types/onyx/PriorityMode.ts
deleted file mode 100644
index 404c678945ad..000000000000
--- a/src/types/onyx/PriorityMode.ts
+++ /dev/null
@@ -1,8 +0,0 @@
-import type {OnyxEntry} from 'react-native-onyx';
-import type {ValueOf} from 'type-fest';
-import type CONST from '@src/CONST';
-
-/** Modes that define how the user's chats are displayed in his chat list  */
-type PriorityMode = OnyxEntry<ValueOf<typeof CONST.PRIORITY_MODE>>;
-
-export default PriorityMode;
diff --git a/tests/actions/QueuedOnyxUpdatesTest.ts b/tests/actions/QueuedOnyxUpdatesTest.ts
index 5a7190f42945..10c0b93c3f7b 100644
--- a/tests/actions/QueuedOnyxUpdatesTest.ts
+++ b/tests/actions/QueuedOnyxUpdatesTest.ts
@@ -100,7 +100,6 @@ describe('actions/QueuedOnyxUpdates', () => {
 
             await flushQueue();
 
-            await testOnyxKeyValue(ONYXKEYS.NVP_TRY_FOCUS_MODE);
             await testOnyxKeyValue(ONYXKEYS.PREFERRED_THEME);
             await testOnyxKeyValue(ONYXKEYS.NVP_PREFERRED_LOCALE);
             await testOnyxKeyValue(ONYXKEYS.SESSION);
@@ -145,7 +144,6 @@ describe('actions/QueuedOnyxUpdates', () => {
 
             await flushQueue();
 
-            await testOnyxKeyValue(ONYXKEYS.NVP_TRY_FOCUS_MODE);
             await testOnyxKeyValue(ONYXKEYS.PREFERRED_THEME);
             await testOnyxKeyValue(ONYXKEYS.NVP_PREFERRED_LOCALE);
             await testOnyxKeyValue(ONYXKEYS.SESSION);
diff --git a/tests/perf-test/SidebarLinks.perf-test.tsx b/tests/perf-test/SidebarLinks.perf-test.tsx
index 34c7b84e2b6b..f26496ca27e3 100644
--- a/tests/perf-test/SidebarLinks.perf-test.tsx
+++ b/tests/perf-test/SidebarLinks.perf-test.tsx
@@ -80,7 +80,7 @@ describe('SidebarLinks', () => {
         await Onyx.multiSet({
             [ONYXKEYS.PERSONAL_DETAILS_LIST]: LHNTestUtils.fakePersonalDetails,
             [ONYXKEYS.BETAS]: [CONST.BETAS.DEFAULT_ROOMS],
-            [ONYXKEYS.NVP_PRIORITY_MODE]: CONST.PRIORITY_MODE.GSD,
+
             [ONYXKEYS.IS_LOADING_REPORT_DATA]: false,
             ...mockedResponseMap,
         });
@@ -102,7 +102,7 @@ describe('SidebarLinks', () => {
         await Onyx.multiSet({
             [ONYXKEYS.PERSONAL_DETAILS_LIST]: LHNTestUtils.fakePersonalDetails,
             [ONYXKEYS.BETAS]: [CONST.BETAS.DEFAULT_ROOMS],
-            [ONYXKEYS.NVP_PRIORITY_MODE]: CONST.PRIORITY_MODE.GSD,
+
             [ONYXKEYS.IS_LOADING_REPORT_DATA]: false,
             ...mockedResponseMap,
         });
diff --git a/tests/ui/LHNItemsPresence.tsx b/tests/ui/LHNItemsPresence.tsx
index a6aa9fd36dbb..2241f4654d7a 100644
--- a/tests/ui/LHNItemsPresence.tsx
+++ b/tests/ui/LHNItemsPresence.tsx
@@ -138,7 +138,6 @@ describe('SidebarLinksData', () => {
         await waitForBatchedUpdates();
         await act(async () => {
             await Onyx.multiSet({
-                [ONYXKEYS.NVP_PRIORITY_MODE]: CONST.PRIORITY_MODE.GSD,
                 [ONYXKEYS.BETAS]: betas,
                 [ONYXKEYS.PERSONAL_DETAILS_LIST]: LHNTestUtils.fakePersonalDetails,
                 [ONYXKEYS.IS_LOADING_APP]: false,
@@ -396,9 +395,7 @@ describe('SidebarLinksData', () => {
 
             await waitForBatchedUpdatesWithAct();
 
-            // When the user is in the default mode
             await act(async () => {
-                await Onyx.merge(ONYXKEYS.NVP_PRIORITY_MODE, CONST.PRIORITY_MODE.DEFAULT);
                 await Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT_NAME_VALUE_PAIRS}${archivedReport.reportID}`, reportNameValuePairs);
             });
 
@@ -440,12 +437,6 @@ describe('SidebarLinksData', () => {
             await waitForBatchedUpdatesWithAct();
 
             // When the user is in focus mode
-            await act(async () => {
-                await Onyx.merge(ONYXKEYS.NVP_PRIORITY_MODE, CONST.PRIORITY_MODE.GSD);
-            });
-
-            await waitForBatchedUpdatesWithAct();
-
             // Then the report should appear in the sidebar because it's unread
             expect(getOptionRows()).toHaveLength(1);
 
@@ -704,25 +695,8 @@ describe('SidebarLinksData', () => {
 
             await waitForBatchedUpdatesWithAct();
 
-            // And the user is in default mode
-            await act(async () => {
-                await Onyx.merge(ONYXKEYS.NVP_PRIORITY_MODE, CONST.PRIORITY_MODE.DEFAULT);
-            });
-
-            await waitForBatchedUpdatesWithAct();
-
             // Then the report should appear in the sidebar
             expect(getOptionRows()).toHaveLength(1);
-
-            await act(async () => {
-                // When the user is in focus mode
-                await Onyx.merge(ONYXKEYS.NVP_PRIORITY_MODE, CONST.PRIORITY_MODE.GSD);
-            });
-
-            await waitForBatchedUpdatesWithAct();
-
-            // Then the report should not disappear in the sidebar because it's read
-            expect(getOptionRows()).toHaveLength(0);
         });
 
         it('should not display an empty submitted report having only a CREATED action', async () => {
diff --git a/tests/unit/ReportUtilsTest.ts b/tests/unit/ReportUtilsTest.ts
index fce1994b920e..847038475834 100644
--- a/tests/unit/ReportUtilsTest.ts
+++ b/tests/unit/ReportUtilsTest.ts
@@ -5881,14 +5881,12 @@ describe('ReportUtils', () => {
         it('should return true when the report is current active report', () => {
             const report = LHNTestUtils.getFakeReport();
             const currentReportId = report.reportID;
-            const isInFocusMode = true;
             const betas = [CONST.BETAS.DEFAULT_ROOMS];
             expect(
                 shouldReportBeInOptionList({
                     report,
                     chatReport: mockedChatReport,
                     currentReportId,
-                    isInFocusMode,
                     betas,
                     doesReportHaveViolations: false,
                     excludeEmptyChats: false,
@@ -5901,8 +5899,6 @@ describe('ReportUtils', () => {
         it('should return true for empty submitted report if it is the current focused report', async () => {
             const report: Report = {...LHNTestUtils.getFakeReport(), total: 0, statusNum: CONST.REPORT.STATUS_NUM.SUBMITTED, stateNum: CONST.REPORT.STATE_NUM.SUBMITTED};
             const currentReportId = report.reportID;
-
-            const isInFocusMode = true;
             const betas = [CONST.BETAS.DEFAULT_ROOMS];
             const createdReportAction: ReportAction = {...LHNTestUtils.getFakeReportAction(), actionName: CONST.REPORT.ACTIONS.TYPE.CREATED};
             await Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${report.reportID}`, {[createdReportAction.reportActionID]: createdReportAction});
@@ -5912,7 +5908,6 @@ describe('ReportUtils', () => {
                     report,
                     chatReport: mockedChatReport,
                     currentReportId,
-                    isInFocusMode,
                     betas,
                     doesReportHaveViolations: false,
                     excludeEmptyChats: false,
@@ -5930,8 +5925,6 @@ describe('ReportUtils', () => {
                 stateNum: CONST.REPORT.STATE_NUM.SUBMITTED,
             };
             const currentReportId = `${report.reportID}1`;
-
-            const isInFocusMode = true;
             const betas = [CONST.BETAS.DEFAULT_ROOMS];
             const createdReportAction: ReportAction = {...LHNTestUtils.getFakeReportAction(), actionName: CONST.REPORT.ACTIONS.TYPE.CREATED};
             await Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${report.reportID}`, {[createdReportAction.reportActionID]: createdReportAction});
@@ -5941,7 +5934,6 @@ describe('ReportUtils', () => {
                     report,
                     chatReport: mockedChatReport,
                     currentReportId,
-                    isInFocusMode,
                     betas,
                     doesReportHaveViolations: false,
                     excludeEmptyChats: false,
@@ -5982,7 +5974,6 @@ describe('ReportUtils', () => {
             });
             const transactionThreadReport = buildTransactionThread(expenseCreatedAction1, expenseReport);
             const currentReportId = '1';
-            const isInFocusMode = false;
             const betas = [CONST.BETAS.DEFAULT_ROOMS];
             await Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT}${expenseReport.reportID}`, expenseReport);
             await Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${expenseReport.reportID}`, {
@@ -5994,7 +5985,6 @@ describe('ReportUtils', () => {
                     report: transactionThreadReport,
                     chatReport: mockedChatReport,
                     currentReportId,
-                    isInFocusMode,
                     betas,
                     doesReportHaveViolations: true,
                     excludeEmptyChats: false,
@@ -6010,14 +6000,12 @@ describe('ReportUtils', () => {
                 hasOutstandingChildRequest: true,
             };
             const currentReportId = '3';
-            const isInFocusMode = true;
             const betas = [CONST.BETAS.DEFAULT_ROOMS];
             expect(
                 shouldReportBeInOptionList({
                     report: chatReport,
                     chatReport: mockedChatReport,
                     currentReportId,
-                    isInFocusMode,
                     betas,
                     doesReportHaveViolations: false,
                     excludeEmptyChats: false,
@@ -6030,7 +6018,6 @@ describe('ReportUtils', () => {
         it('should return true when the report has valid draft comment', async () => {
             const report = LHNTestUtils.getFakeReport();
             const currentReportId = '3';
-            const isInFocusMode = false;
             const betas = [CONST.BETAS.DEFAULT_ROOMS];
 
             await Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT_DRAFT_COMMENT}${report.reportID}`, 'fake draft');
@@ -6040,7 +6027,6 @@ describe('ReportUtils', () => {
                     report,
                     chatReport: mockedChatReport,
                     currentReportId,
-                    isInFocusMode,
                     betas,
                     doesReportHaveViolations: false,
                     excludeEmptyChats: false,
@@ -6056,14 +6042,12 @@ describe('ReportUtils', () => {
                 isPinned: true,
             };
             const currentReportId = '3';
-            const isInFocusMode = false;
             const betas = [CONST.BETAS.DEFAULT_ROOMS];
             expect(
                 shouldReportBeInOptionList({
                     report,
                     chatReport: mockedChatReport,
                     currentReportId,
-                    isInFocusMode,
                     betas,
                     doesReportHaveViolations: false,
                     excludeEmptyChats: false,
@@ -6087,7 +6071,6 @@ describe('ReportUtils', () => {
                 lastMessageText: 'fake',
             };
             const currentReportId = '3';
-            const isInFocusMode = true;
             const betas = [CONST.BETAS.DEFAULT_ROOMS];
 
             await Onyx.merge(ONYXKEYS.SESSION, {
@@ -6099,7 +6082,6 @@ describe('ReportUtils', () => {
                     report,
                     chatReport: mockedChatReport,
                     currentReportId,
-                    isInFocusMode,
                     betas,
                     doesReportHaveViolations: false,
                     excludeEmptyChats: false,
@@ -6119,7 +6101,6 @@ describe('ReportUtils', () => {
                 private_isArchived: DateUtils.getDBTime(),
             };
             const currentReportId = '3';
-            const isInFocusMode = false;
             const betas = [CONST.BETAS.DEFAULT_ROOMS];
 
             await Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT_NAME_VALUE_PAIRS}${archivedReport.reportID}`, reportNameValuePairs);
@@ -6130,7 +6111,6 @@ describe('ReportUtils', () => {
                     report: archivedReport,
                     chatReport: mockedChatReport,
                     currentReportId,
-                    isInFocusMode,
                     betas,
                     doesReportHaveViolations: false,
                     excludeEmptyChats: false,
@@ -6150,7 +6130,6 @@ describe('ReportUtils', () => {
                 private_isArchived: DateUtils.getDBTime(),
             };
             const currentReportId = '3';
-            const isInFocusMode = true;
             const betas = [CONST.BETAS.DEFAULT_ROOMS];
 
             await Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT_NAME_VALUE_PAIRS}${archivedReport.reportID}`, reportNameValuePairs);
@@ -6161,7 +6140,6 @@ describe('ReportUtils', () => {
                     report: archivedReport,
                     chatReport: mockedChatReport,
                     currentReportId,
-                    isInFocusMode,
                     betas,
                     doesReportHaveViolations: false,
                     excludeEmptyChats: false,
@@ -6177,7 +6155,6 @@ describe('ReportUtils', () => {
                 chatType: CONST.REPORT.CHAT_TYPE.SELF_DM,
             };
             const currentReportId = '3';
-            const isInFocusMode = false;
             const betas = [CONST.BETAS.DEFAULT_ROOMS];
             const includeSelfDM = true;
             expect(
@@ -6185,7 +6162,6 @@ describe('ReportUtils', () => {
                     report,
                     chatReport: mockedChatReport,
                     currentReportId,
-                    isInFocusMode,
                     betas,
                     doesReportHaveViolations: false,
                     excludeEmptyChats: false,
@@ -6206,14 +6182,12 @@ describe('ReportUtils', () => {
                 },
             };
             const currentReportId = '';
-            const isInFocusMode = true;
             const betas = [CONST.BETAS.DEFAULT_ROOMS];
             expect(
                 shouldReportBeInOptionList({
                     report,
                     chatReport: mockedChatReport,
                     currentReportId,
-                    isInFocusMode,
                     betas,
                     doesReportHaveViolations: false,
                     excludeEmptyChats: false,
@@ -6226,14 +6200,12 @@ describe('ReportUtils', () => {
         it('should return false when the report does not have participants', () => {
             const report = LHNTestUtils.getFakeReport([]);
             const currentReportId = '';
-            const isInFocusMode = true;
             const betas = [CONST.BETAS.DEFAULT_ROOMS];
             expect(
                 shouldReportBeInOptionList({
                     report,
                     chatReport: mockedChatReport,
                     currentReportId,
-                    isInFocusMode,
                     betas,
                     doesReportHaveViolations: false,
                     excludeEmptyChats: false,
@@ -6249,14 +6221,12 @@ describe('ReportUtils', () => {
                 chatType: CONST.REPORT.CHAT_TYPE.DOMAIN_ALL,
             };
             const currentReportId = '';
-            const isInFocusMode = false;
             const betas: Beta[] = [];
             expect(
                 shouldReportBeInOptionList({
                     report,
                     chatReport: mockedChatReport,
                     currentReportId,
-                    isInFocusMode,
                     betas,
                     doesReportHaveViolations: false,
                     excludeEmptyChats: false,
@@ -6288,7 +6258,6 @@ describe('ReportUtils', () => {
             const transactionThreadReport = buildTransactionThread(expenseCreatedAction, expenseReport);
             expenseCreatedAction.childReportID = transactionThreadReport.reportID;
             const currentReportId = '1';
-            const isInFocusMode = false;
             const betas = [CONST.BETAS.DEFAULT_ROOMS];
             await Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT}${expenseReport.reportID}`, expenseReport);
             await Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${expenseReport.reportID}`, {
@@ -6299,7 +6268,6 @@ describe('ReportUtils', () => {
                     report: transactionThreadReport,
                     chatReport: mockedChatReport,
                     currentReportId,
-                    isInFocusMode,
                     betas,
                     doesReportHaveViolations: false,
                     excludeEmptyChats: false,
@@ -6312,14 +6280,12 @@ describe('ReportUtils', () => {
         it('should return false when the report is empty chat and the excludeEmptyChats setting is true', () => {
             const report = LHNTestUtils.getFakeReport();
             const currentReportId = '';
-            const isInFocusMode = false;
             const betas = [CONST.BETAS.DEFAULT_ROOMS];
             expect(
                 shouldReportBeInOptionList({
                     report,
                     chatReport: mockedChatReport,
                     currentReportId,
-                    isInFocusMode,
                     betas,
                     doesReportHaveViolations: false,
                     excludeEmptyChats: true,
@@ -6336,7 +6302,6 @@ describe('ReportUtils', () => {
                 reportID: conciergeReportID,
             };
             const currentReportId = '';
-            const isInFocusMode = false;
             const betas = [CONST.BETAS.DEFAULT_ROOMS];
 
             await Onyx.set(ONYXKEYS.CONCIERGE_REPORT_ID, conciergeReportID);
@@ -6347,7 +6312,6 @@ describe('ReportUtils', () => {
                     report,
                     chatReport: mockedChatReport,
                     currentReportId,
-                    isInFocusMode,
                     betas,
                     doesReportHaveViolations: false,
                     excludeEmptyChats: true,
@@ -6360,14 +6324,12 @@ describe('ReportUtils', () => {
         it('should return false when the users email is domain-based and the includeDomainEmail is false', () => {
             const report = LHNTestUtils.getFakeReport();
             const currentReportId = '';
-            const isInFocusMode = false;
             const betas = [CONST.BETAS.DEFAULT_ROOMS];
             expect(
                 shouldReportBeInOptionList({
                     report,
                     chatReport: mockedChatReport,
                     currentReportId,
-                    isInFocusMode,
                     betas,
                     doesReportHaveViolations: false,
                     login: '+@domain.com',
@@ -6402,7 +6364,6 @@ describe('ReportUtils', () => {
             report.parentReportID = parentReport.reportID;
             report.parentReportActionID = parentReportAction.reportActionID;
             const currentReportId = '';
-            const isInFocusMode = false;
             const betas = [CONST.BETAS.DEFAULT_ROOMS];
 
             await Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT}${parentReport.reportID}`, parentReport);
@@ -6415,7 +6376,6 @@ describe('ReportUtils', () => {
                     report,
                     chatReport: mockedChatReport,
                     currentReportId,
-                    isInFocusMode,
                     betas,
                     doesReportHaveViolations: false,
                     excludeEmptyChats: false,
@@ -6428,14 +6388,12 @@ describe('ReportUtils', () => {
         it('should return false when the report is read and we are in the focus mode', () => {
             const report = LHNTestUtils.getFakeReport();
             const currentReportId = '';
-            const isInFocusMode = true;
             const betas = [CONST.BETAS.DEFAULT_ROOMS];
             expect(
                 shouldReportBeInOptionList({
                     report,
                     chatReport: mockedChatReport,
                     currentReportId,
-                    isInFocusMode,
                     betas,
                     doesReportHaveViolations: false,
                     excludeEmptyChats: false,
@@ -6469,7 +6427,6 @@ describe('ReportUtils', () => {
                     report,
                     chatReport: mockedChatReport,
                     currentReportId: '',
-                    isInFocusMode: false,
                     betas: [],
                     doesReportHaveViolations: false,
                     excludeEmptyChats: true,
@@ -6500,7 +6457,6 @@ describe('ReportUtils', () => {
                     report,
                     chatReport: mockedChatReport,
                     currentReportId: '',
-                    isInFocusMode: true,
                     betas: [CONST.BETAS.DEFAULT_ROOMS],
                     doesReportHaveViolations: false,
                     excludeEmptyChats: false,
@@ -6529,7 +6485,6 @@ describe('ReportUtils', () => {
                     report,
                     chatReport: mockedChatReport,
                     currentReportId: '',
-                    isInFocusMode: true,
                     betas: [CONST.BETAS.DEFAULT_ROOMS],
                     doesReportHaveViolations: false,
                     excludeEmptyChats: false,
@@ -6551,7 +6506,6 @@ describe('ReportUtils', () => {
                     report,
                     chatReport: mockedChatReport,
                     currentReportId: '',
-                    isInFocusMode: false,
                     betas: [CONST.BETAS.DEFAULT_ROOMS],
                     doesReportHaveViolations: false,
                     excludeEmptyChats: false,
@@ -6595,7 +6549,6 @@ describe('ReportUtils', () => {
                     report: threadReport,
                     chatReport: mockedChatReport,
                     currentReportId: '',
-                    isInFocusMode: false,
                     betas: [CONST.BETAS.DEFAULT_ROOMS],
                     doesReportHaveViolations: false,
                     excludeEmptyChats: false,
@@ -6646,7 +6599,6 @@ describe('ReportUtils', () => {
                     report: threadReport,
                     chatReport: mockedChatReport,
                     currentReportId: '',
-                    isInFocusMode: false,
                     betas: [CONST.BETAS.DEFAULT_ROOMS],
                     doesReportHaveViolations: false,
                     excludeEmptyChats: false,
@@ -6667,7 +6619,6 @@ describe('ReportUtils', () => {
                     report,
                     chatReport: mockedChatReport,
                     currentReportId: '',
-                    isInFocusMode: false,
                     betas: [CONST.BETAS.DEFAULT_ROOMS],
                     doesReportHaveViolations: false,
                     excludeEmptyChats: false,
@@ -6689,7 +6640,6 @@ describe('ReportUtils', () => {
                     report,
                     chatReport: mockedChatReport,
                     currentReportId: '',
-                    isInFocusMode: false,
                     betas: [CONST.BETAS.DEFAULT_ROOMS],
                     doesReportHaveViolations: false,
                     excludeEmptyChats: true,
@@ -6710,7 +6660,6 @@ describe('ReportUtils', () => {
                     report,
                     chatReport: mockedChatReport,
                     currentReportId: '',
-                    isInFocusMode: false,
                     betas: [CONST.BETAS.DEFAULT_ROOMS],
                     doesReportHaveViolations: false,
                     excludeEmptyChats: false,
@@ -6731,7 +6680,6 @@ describe('ReportUtils', () => {
                     report,
                     chatReport: mockedChatReport,
                     currentReportId: '999',
-                    isInFocusMode: false,
                     betas: [CONST.BETAS.DEFAULT_ROOMS],
                     doesReportHaveViolations: false,
                     excludeEmptyChats: false,
@@ -6752,7 +6700,6 @@ describe('ReportUtils', () => {
                     report,
                     chatReport: mockedChatReport,
                     currentReportId: '',
-                    isInFocusMode: false,
                     betas: [CONST.BETAS.DEFAULT_ROOMS],
                     doesReportHaveViolations: false,
                     excludeEmptyChats: false,
@@ -6768,7 +6715,6 @@ describe('ReportUtils', () => {
                     report: null as unknown as Report,
                     chatReport: mockedChatReport,
                     currentReportId: '',
-                    isInFocusMode: false,
                     betas: [CONST.BETAS.DEFAULT_ROOMS],
                     doesReportHaveViolations: false,
                     excludeEmptyChats: false,
@@ -6824,7 +6770,6 @@ describe('ReportUtils', () => {
                 report: transactionThreadReport,
                 chatReport: mockedChatReport,
                 currentReportId: '',
-                isInFocusMode: false,
                 betas: [CONST.BETAS.DEFAULT_ROOMS],
                 doesReportHaveViolations: true,
                 excludeEmptyChats: false,
@@ -11986,7 +11931,6 @@ describe('ReportUtils', () => {
             report: chatReport,
             chatReport,
             currentReportId: '',
-            isInFocusMode: false,
             betas: [CONST.BETAS.DEFAULT_ROOMS],
             doesReportHaveViolations: false,
             excludeEmptyChats: false,
@@ -12044,7 +11988,6 @@ describe('ReportUtils', () => {
             report: chatReport,
             chatReport,
             currentReportId: '',
-            isInFocusMode: false,
             betas: [CONST.BETAS.DEFAULT_ROOMS],
             doesReportHaveViolations: false,
             excludeEmptyChats: false,
@@ -12151,7 +12094,6 @@ describe('ReportUtils', () => {
                 report: expenseReport,
                 chatReport: undefined,
                 currentReportId: undefined,
-                isInFocusMode: true,
                 betas: undefined,
                 doesReportHaveViolations: false,
                 excludeEmptyChats: false,
@@ -12194,7 +12136,6 @@ describe('ReportUtils', () => {
                 report: expenseReport,
                 chatReport: undefined,
                 currentReportId: undefined,
-                isInFocusMode: true,
                 betas: undefined,
                 doesReportHaveViolations: false,
                 excludeEmptyChats: false,
@@ -12545,7 +12486,6 @@ describe('ReportUtils', () => {
             report: chatReport,
             chatReport,
             currentReportId: '',
-            isInFocusMode: false,
             betas: [CONST.BETAS.DEFAULT_ROOMS],
             doesReportHaveViolations: shouldShowRBR,
             excludeEmptyChats: false,
@@ -12728,7 +12668,6 @@ describe('ReportUtils', () => {
             report: chatReport,
             chatReport,
             currentReportId: '',
-            isInFocusMode: false,
             betas: [CONST.BETAS.DEFAULT_ROOMS],
             doesReportHaveViolations: false,
             excludeEmptyChats: false,
@@ -12913,7 +12852,6 @@ describe('ReportUtils', () => {
             report: chatReport,
             chatReport,
             currentReportId: '',
-            isInFocusMode: false,
             betas: [CONST.BETAS.DEFAULT_ROOMS],
             doesReportHaveViolations: false,
             excludeEmptyChats: false,
@@ -12935,7 +12873,6 @@ describe('ReportUtils', () => {
             report: chatReport,
             chatReport,
             currentReportId: '',
-            isInFocusMode: false,
             betas: [CONST.BETAS.DEFAULT_ROOMS],
             doesReportHaveViolations: false,
             excludeEmptyChats: false,
@@ -13036,7 +12973,6 @@ describe('ReportUtils', () => {
             report: expenseReportChat,
             chatReport: expenseReportChat,
             currentReportId: '',
-            isInFocusMode: false,
             betas: [CONST.BETAS.DEFAULT_ROOMS],
             doesReportHaveViolations: false,
             excludeEmptyChats: false,
@@ -13076,7 +13012,6 @@ describe('ReportUtils', () => {
             report: expenseReportChat,
             chatReport: expenseReportChat,
             currentReportId: '',
-            isInFocusMode: false,
             betas: [CONST.BETAS.DEFAULT_ROOMS],
             doesReportHaveViolations: false,
             excludeEmptyChats: false,
@@ -13552,7 +13487,6 @@ describe('ReportUtils', () => {
                 report: chatReport,
                 chatReport,
                 currentReportId: '',
-                isInFocusMode: false,
                 betas: [CONST.BETAS.DEFAULT_ROOMS],
                 doesReportHaveViolations: false,
                 excludeEmptyChats: false,
@@ -13619,7 +13553,6 @@ describe('ReportUtils', () => {
                 report: chatReport,
                 chatReport,
                 currentReportId: '',
-                isInFocusMode: false,
                 betas: [CONST.BETAS.DEFAULT_ROOMS],
                 doesReportHaveViolations: false,
                 excludeEmptyChats: false,
@@ -13690,7 +13623,6 @@ describe('ReportUtils', () => {
                 report: chatReport,
                 chatReport,
                 currentReportId: '',
-                isInFocusMode: false,
                 betas: [CONST.BETAS.DEFAULT_ROOMS],
                 doesReportHaveViolations: false,
                 excludeEmptyChats: false,
@@ -13760,7 +13692,6 @@ describe('ReportUtils', () => {
                 report: chatReport,
                 chatReport,
                 currentReportId: '',
-                isInFocusMode: false,
                 betas: [CONST.BETAS.DEFAULT_ROOMS],
                 doesReportHaveViolations: false,
                 excludeEmptyChats: false,
@@ -15525,7 +15456,6 @@ describe('ReportUtils', () => {
                 report: policyExpenseChat,
                 chatReport: policyExpenseChat,
                 currentReportId: '',
-                isInFocusMode: false,
                 betas: [CONST.BETAS.DEFAULT_ROOMS],
                 doesReportHaveViolations: false,
                 excludeEmptyChats: false,
@@ -15594,7 +15524,6 @@ describe('ReportUtils', () => {
                 report: policyExpenseChat,
                 chatReport: policyExpenseChat,
                 currentReportId: '',
-                isInFocusMode: false,
                 betas: [CONST.BETAS.DEFAULT_ROOMS],
                 doesReportHaveViolations: false,
                 excludeEmptyChats: false,
diff --git a/tests/unit/SidebarFilterTest.ts b/tests/unit/SidebarFilterTest.ts
index 1970472dfdc3..c377ef0c6e25 100644
--- a/tests/unit/SidebarFilterTest.ts
+++ b/tests/unit/SidebarFilterTest.ts
@@ -17,7 +17,6 @@ jest.mock('@libs/Permissions');
 const ONYXKEYS = {
     PERSONAL_DETAILS_LIST: 'personalDetailsList',
     IS_LOADING_APP: 'isLoadingApp',
-    NVP_PRIORITY_MODE: 'nvp_priorityMode',
     SESSION: 'session',
     BETAS: 'betas',
     COLLECTION: {
@@ -372,7 +371,6 @@ xdescribe('Sidebar', () => {
                             // When Onyx is updated to contain that data and the sidebar re-renders
                             .then(() =>
                                 Onyx.multiSet({
-                                    [ONYXKEYS.NVP_PRIORITY_MODE]: CONST.PRIORITY_MODE.GSD,
                                     [ONYXKEYS.BETAS]: betas,
                                     [ONYXKEYS.PERSONAL_DETAILS_LIST]: LHNTestUtils.fakePersonalDetails,
                                     [ONYXKEYS.IS_LOADING_APP]: false,
@@ -421,7 +419,6 @@ xdescribe('Sidebar', () => {
                     // When Onyx is updated to contain that data and the sidebar re-renders
                     .then(() =>
                         Onyx.multiSet({
-                            [ONYXKEYS.NVP_PRIORITY_MODE]: CONST.PRIORITY_MODE.GSD,
                             [ONYXKEYS.PERSONAL_DETAILS_LIST]: LHNTestUtils.fakePersonalDetails,
                             [ONYXKEYS.IS_LOADING_APP]: false,
                             ...reportCollectionDataSet,
@@ -492,7 +489,6 @@ xdescribe('Sidebar', () => {
                     // When Onyx is updated to contain that data and the sidebar re-renders
                     .then(() =>
                         Onyx.multiSet({
-                            [ONYXKEYS.NVP_PRIORITY_MODE]: CONST.PRIORITY_MODE.GSD,
                             [ONYXKEYS.PERSONAL_DETAILS_LIST]: LHNTestUtils.fakePersonalDetails,
                             [ONYXKEYS.IS_LOADING_APP]: false,
                             [`${ONYXKEYS.COLLECTION.REPORT_DRAFT_COMMENT}${draftReport.reportID}`]: 'draft report message',
@@ -546,7 +542,6 @@ xdescribe('Sidebar', () => {
                     // When Onyx is updated to contain that data and the sidebar re-renders
                     .then(() =>
                         Onyx.multiSet({
-                            [ONYXKEYS.NVP_PRIORITY_MODE]: CONST.PRIORITY_MODE.GSD,
                             [ONYXKEYS.BETAS]: betas,
                             [ONYXKEYS.PERSONAL_DETAILS_LIST]: LHNTestUtils.fakePersonalDetails,
                             [ONYXKEYS.IS_LOADING_APP]: false,
@@ -612,7 +607,6 @@ xdescribe('Sidebar', () => {
                     // When Onyx is updated to contain that data and the sidebar re-renders
                     .then(() =>
                         Onyx.multiSet({
-                            [ONYXKEYS.NVP_PRIORITY_MODE]: CONST.PRIORITY_MODE.GSD,
                             [ONYXKEYS.BETAS]: betas,
                             [ONYXKEYS.PERSONAL_DETAILS_LIST]: LHNTestUtils.fakePersonalDetails,
                             [ONYXKEYS.IS_LOADING_APP]: false,
@@ -714,7 +708,6 @@ xdescribe('Sidebar', () => {
                         // When Onyx is updated to contain that data and the sidebar re-renders
                         .then(() =>
                             Onyx.multiSet({
-                                [ONYXKEYS.NVP_PRIORITY_MODE]: CONST.PRIORITY_MODE.GSD,
                                 [ONYXKEYS.BETAS]: betas,
                                 [ONYXKEYS.PERSONAL_DETAILS_LIST]: LHNTestUtils.fakePersonalDetails,
                                 [ONYXKEYS.IS_LOADING_APP]: false,
@@ -769,7 +762,6 @@ xdescribe('Sidebar', () => {
                         // When Onyx is updated to contain that data and the sidebar re-renders
                         .then(() =>
                             Onyx.multiSet({
-                                [ONYXKEYS.NVP_PRIORITY_MODE]: CONST.PRIORITY_MODE.DEFAULT,
                                 [ONYXKEYS.BETAS]: betas,
                                 [ONYXKEYS.PERSONAL_DETAILS_LIST]: LHNTestUtils.fakePersonalDetails,
                                 [ONYXKEYS.IS_LOADING_APP]: false,
@@ -822,7 +814,6 @@ xdescribe('Sidebar', () => {
                         // When Onyx is updated to contain that data and the sidebar re-renders
                         .then(() =>
                             Onyx.multiSet({
-                                [ONYXKEYS.NVP_PRIORITY_MODE]: CONST.PRIORITY_MODE.GSD,
                                 [ONYXKEYS.BETAS]: betas,
                                 [ONYXKEYS.PERSONAL_DETAILS_LIST]: LHNTestUtils.fakePersonalDetails,
                                 [ONYXKEYS.IS_LOADING_APP]: false,
@@ -873,7 +864,6 @@ xdescribe('Sidebar', () => {
                         // When Onyx is updated to contain that data and the sidebar re-renders
                         .then(() =>
                             Onyx.multiSet({
-                                [ONYXKEYS.NVP_PRIORITY_MODE]: CONST.PRIORITY_MODE.GSD,
                                 [ONYXKEYS.BETAS]: betas,
                                 [ONYXKEYS.PERSONAL_DETAILS_LIST]: LHNTestUtils.fakePersonalDetails,
                                 [ONYXKEYS.IS_LOADING_APP]: false,
@@ -920,7 +910,6 @@ xdescribe('Sidebar', () => {
                         // When Onyx is updated to contain that data and the sidebar re-renders
                         .then(() =>
                             Onyx.multiSet({
-                                [ONYXKEYS.NVP_PRIORITY_MODE]: CONST.PRIORITY_MODE.GSD,
                                 [ONYXKEYS.BETAS]: betas,
                                 [ONYXKEYS.PERSONAL_DETAILS_LIST]: LHNTestUtils.fakePersonalDetails,
                                 [ONYXKEYS.IS_LOADING_APP]: false,
@@ -956,7 +945,6 @@ xdescribe('Sidebar', () => {
                         // When Onyx is updated to contain that data and the sidebar re-renders
                         .then(() =>
                             Onyx.multiSet({
-                                [ONYXKEYS.NVP_PRIORITY_MODE]: CONST.PRIORITY_MODE.GSD,
                                 [ONYXKEYS.PERSONAL_DETAILS_LIST]: LHNTestUtils.fakePersonalDetails,
                                 [ONYXKEYS.IS_LOADING_APP]: false,
                                 ...reportCollectionDataSet,
diff --git a/tests/unit/SidebarOrderTest.ts b/tests/unit/SidebarOrderTest.ts
index 11975ca61b92..55a7cfbc6cbe 100644
--- a/tests/unit/SidebarOrderTest.ts
+++ b/tests/unit/SidebarOrderTest.ts
@@ -122,7 +122,6 @@ describe('Sidebar', () => {
                     // When Onyx is updated with the data and the sidebar re-renders
                     .then(() =>
                         Onyx.multiSet({
-                            [ONYXKEYS.NVP_PRIORITY_MODE]: CONST.PRIORITY_MODE.DEFAULT,
                             [ONYXKEYS.PERSONAL_DETAILS_LIST]: LHNTestUtils.fakePersonalDetails,
                             [ONYXKEYS.IS_LOADING_APP]: false,
                             ...reportCollectionDataSet,
@@ -160,7 +159,6 @@ describe('Sidebar', () => {
                     // When Onyx is updated with the data and the sidebar re-renders
                     .then(() =>
                         Onyx.multiSet({
-                            [ONYXKEYS.NVP_PRIORITY_MODE]: CONST.PRIORITY_MODE.DEFAULT,
                             [ONYXKEYS.PERSONAL_DETAILS_LIST]: LHNTestUtils.fakePersonalDetails,
                             [ONYXKEYS.IS_LOADING_APP]: false,
                             ...reportCollectionDataSet,
@@ -209,7 +207,6 @@ describe('Sidebar', () => {
                     // When Onyx is updated with the data and the sidebar re-renders
                     .then(() =>
                         Onyx.multiSet({
-                            [ONYXKEYS.NVP_PRIORITY_MODE]: CONST.PRIORITY_MODE.DEFAULT,
                             [ONYXKEYS.PERSONAL_DETAILS_LIST]: LHNTestUtils.fakePersonalDetails,
                             [ONYXKEYS.IS_LOADING_APP]: false,
                             [`${ONYXKEYS.COLLECTION.REPORT_DRAFT_COMMENT}${report1.reportID}`]: 'report1 draft',
@@ -256,7 +253,6 @@ describe('Sidebar', () => {
                     // When Onyx is updated with the data and the sidebar re-renders
                     .then(() =>
                         Onyx.multiSet({
-                            [ONYXKEYS.NVP_PRIORITY_MODE]: CONST.PRIORITY_MODE.DEFAULT,
                             [ONYXKEYS.PERSONAL_DETAILS_LIST]: LHNTestUtils.fakePersonalDetails,
                             [ONYXKEYS.IS_LOADING_APP]: false,
                             ...reportCollectionDataSet,
@@ -319,7 +315,6 @@ describe('Sidebar', () => {
                     // When Onyx is updated with the data and the sidebar re-renders
                     .then(() =>
                         Onyx.multiSet({
-                            [ONYXKEYS.NVP_PRIORITY_MODE]: CONST.PRIORITY_MODE.DEFAULT,
                             [ONYXKEYS.PERSONAL_DETAILS_LIST]: LHNTestUtils.fakePersonalDetails,
                             [ONYXKEYS.IS_LOADING_APP]: false,
                             ...reportCollectionDataSet,
@@ -393,7 +388,6 @@ describe('Sidebar', () => {
                     // When Onyx is updated with the data and the sidebar re-renders
                     .then(() =>
                         Onyx.multiSet({
-                            [ONYXKEYS.NVP_PRIORITY_MODE]: CONST.PRIORITY_MODE.DEFAULT,
                             [ONYXKEYS.PERSONAL_DETAILS_LIST]: LHNTestUtils.fakePersonalDetails,
                             [ONYXKEYS.IS_LOADING_APP]: false,
                             ...reportCollectionDataSet,
@@ -472,7 +466,6 @@ describe('Sidebar', () => {
                     // When Onyx is updated with the data and the sidebar re-renders
                     .then(() =>
                         Onyx.multiSet({
-                            [ONYXKEYS.NVP_PRIORITY_MODE]: CONST.PRIORITY_MODE.DEFAULT,
                             [ONYXKEYS.PERSONAL_DETAILS_LIST]: LHNTestUtils.fakePersonalDetails,
                             [ONYXKEYS.IS_LOADING_APP]: false,
                             [`${ONYXKEYS.COLLECTION.POLICY}${fakeReport.policyID}`]: fakePolicy,
@@ -523,7 +516,6 @@ describe('Sidebar', () => {
                     // When Onyx is updated with the data and the sidebar re-renders
                     .then(() =>
                         Onyx.multiSet({
-                            [ONYXKEYS.NVP_PRIORITY_MODE]: CONST.PRIORITY_MODE.DEFAULT,
                             [ONYXKEYS.PERSONAL_DETAILS_LIST]: LHNTestUtils.fakePersonalDetails,
                             [ONYXKEYS.IS_LOADING_APP]: false,
                             [ONYXKEYS.COLLECTION.REPORT_DRAFT_COMMENT + report2.reportID]: 'This is a draft',
@@ -570,7 +562,6 @@ describe('Sidebar', () => {
                     // When Onyx is updated with the data and the sidebar re-renders
                     .then(() =>
                         Onyx.multiSet({
-                            [ONYXKEYS.NVP_PRIORITY_MODE]: CONST.PRIORITY_MODE.DEFAULT,
                             [ONYXKEYS.PERSONAL_DETAILS_LIST]: LHNTestUtils.fakePersonalDetails,
                             [ONYXKEYS.IS_LOADING_APP]: false,
                             [`${ONYXKEYS.COLLECTION.REPORT_DRAFT_COMMENT}${report.reportID}`]: 'This is a draft',
@@ -612,7 +603,6 @@ describe('Sidebar', () => {
                     // When Onyx is updated with the data and the sidebar re-renders
                     .then(() =>
                         Onyx.multiSet({
-                            [ONYXKEYS.NVP_PRIORITY_MODE]: CONST.PRIORITY_MODE.DEFAULT,
                             [ONYXKEYS.PERSONAL_DETAILS_LIST]: LHNTestUtils.fakePersonalDetails,
                             [ONYXKEYS.IS_LOADING_APP]: false,
                             ...reportCollectionDataSet,
@@ -696,7 +686,6 @@ describe('Sidebar', () => {
                     // When Onyx is updated with the data and the sidebar re-renders
                     .then(() =>
                         Onyx.multiSet({
-                            [ONYXKEYS.NVP_PRIORITY_MODE]: CONST.PRIORITY_MODE.DEFAULT,
                             [ONYXKEYS.PERSONAL_DETAILS_LIST]: LHNTestUtils.fakePersonalDetails,
                             [ONYXKEYS.IS_LOADING_APP]: false,
                             [`${ONYXKEYS.COLLECTION.REPORT_DRAFT_COMMENT}${report2.reportID}`]: 'Report2 draft comment',
@@ -754,7 +743,6 @@ describe('Sidebar', () => {
                     // When Onyx is updated with the data and the sidebar re-renders
                     .then(() =>
                         Onyx.multiSet({
-                            [ONYXKEYS.NVP_PRIORITY_MODE]: CONST.PRIORITY_MODE.DEFAULT,
                             [ONYXKEYS.PERSONAL_DETAILS_LIST]: LHNTestUtils.fakePersonalDetails,
                             [ONYXKEYS.IS_LOADING_APP]: false,
                             ...reportCollectionDataSet,
@@ -816,7 +804,6 @@ describe('Sidebar', () => {
                     // When Onyx is updated with the data and the sidebar re-renders
                     .then(() =>
                         Onyx.multiSet({
-                            [ONYXKEYS.NVP_PRIORITY_MODE]: CONST.PRIORITY_MODE.DEFAULT,
                             [ONYXKEYS.PERSONAL_DETAILS_LIST]: LHNTestUtils.fakePersonalDetails,
                             [ONYXKEYS.IS_LOADING_APP]: false,
                             ...reportDraftCommentCollectionDataSet,
@@ -888,7 +875,6 @@ describe('Sidebar', () => {
                     .then(() =>
                         Onyx.multiSet({
                             [ONYXKEYS.BETAS]: betas,
-                            [ONYXKEYS.NVP_PRIORITY_MODE]: CONST.PRIORITY_MODE.DEFAULT,
                             [ONYXKEYS.PERSONAL_DETAILS_LIST]: LHNTestUtils.fakePersonalDetails,
                             [ONYXKEYS.IS_LOADING_APP]: false,
                             ...reportNameValuePairsCollectionDataSet,
@@ -932,7 +918,6 @@ describe('Sidebar', () => {
                     // When Onyx is updated with the data and the sidebar re-renders
                     .then(() =>
                         Onyx.multiSet({
-                            [ONYXKEYS.NVP_PRIORITY_MODE]: CONST.PRIORITY_MODE.DEFAULT,
                             [ONYXKEYS.PERSONAL_DETAILS_LIST]: LHNTestUtils.fakePersonalDetails,
                             [ONYXKEYS.IS_LOADING_APP]: false,
                             ...reportCollectionDataSet,
@@ -973,7 +958,6 @@ describe('Sidebar', () => {
                     // with all reports having unread comments
                     .then(() =>
                         Onyx.multiSet({
-                            [ONYXKEYS.NVP_PRIORITY_MODE]: CONST.PRIORITY_MODE.GSD,
                             [ONYXKEYS.IS_LOADING_APP]: false,
                             ...reportCollectionDataSet,
                         }),
@@ -1035,7 +1019,6 @@ describe('Sidebar', () => {
                     .then(() =>
                         Onyx.multiSet({
                             [ONYXKEYS.BETAS]: betas,
-                            [ONYXKEYS.NVP_PRIORITY_MODE]: CONST.PRIORITY_MODE.GSD,
                             [ONYXKEYS.PERSONAL_DETAILS_LIST]: LHNTestUtils.fakePersonalDetails,
                             [ONYXKEYS.IS_LOADING_APP]: false,
                             ...reportNameValuePairsCollectionDataSet,
diff --git a/tests/unit/SidebarTest.ts b/tests/unit/SidebarTest.ts
index a0fbc44f2995..54a42f4a4ecd 100644
--- a/tests/unit/SidebarTest.ts
+++ b/tests/unit/SidebarTest.ts
@@ -94,7 +94,7 @@ describe('Sidebar', () => {
                         return act(async () => {
                             await Onyx.multiSet({
                                 [ONYXKEYS.BETAS]: betas,
-                                [ONYXKEYS.NVP_PRIORITY_MODE]: CONST.PRIORITY_MODE.GSD,
+
                                 [ONYXKEYS.PERSONAL_DETAILS_LIST]: LHNTestUtils.fakePersonalDetails,
                                 [ONYXKEYS.IS_LOADING_APP]: false,
                                 ...reportNameValuePairsCollection,
@@ -157,7 +157,7 @@ describe('Sidebar', () => {
                         return act(async () => {
                             await Onyx.multiSet({
                                 [ONYXKEYS.BETAS]: betas,
-                                [ONYXKEYS.NVP_PRIORITY_MODE]: CONST.PRIORITY_MODE.GSD,
+
                                 [ONYXKEYS.PERSONAL_DETAILS_LIST]: LHNTestUtils.fakePersonalDetails,
                                 [ONYXKEYS.IS_LOADING_APP]: false,
                                 ...reportNameValuePairsCollection,
diff --git a/tests/unit/SidebarUtilsTest.ts b/tests/unit/SidebarUtilsTest.ts
index 31acccfe67cf..e4a52b030dd0 100644
--- a/tests/unit/SidebarUtilsTest.ts
+++ b/tests/unit/SidebarUtilsTest.ts
@@ -3471,10 +3471,10 @@ describe('SidebarUtils', () => {
                 ]);
 
                 const mockLocaleCompare = (a: string, b: string) => a.localeCompare(b);
-                const priorityMode = CONST.PRIORITY_MODE.DEFAULT;
+                const useAlphabeticalSort = false;
 
                 // When the reports are sorted
-                const result = SidebarUtils.sortReportsToDisplayInLHN(reports, priorityMode, mockLocaleCompare, undefined, undefined, undefined);
+                const result = SidebarUtils.sortReportsToDisplayInLHN(reports, useAlphabeticalSort, mockLocaleCompare, undefined, undefined, undefined);
 
                 // Then the reports are sorted in the correct order
                 expect(result).toEqual(['0', '1', '2']); // Pinned first, Error second, Normal third
@@ -3499,11 +3499,11 @@ describe('SidebarUtils', () => {
 
                 const mockLocaleCompare = (a: string, b: string) => a.localeCompare(b);
 
-                // When the reports are sorted in default mode
-                const defaultResult = SidebarUtils.sortReportsToDisplayInLHN(reports, CONST.PRIORITY_MODE.DEFAULT, mockLocaleCompare, undefined, undefined, undefined);
+                // When the reports are sorted in default mode (not alphabetical)
+                const defaultResult = SidebarUtils.sortReportsToDisplayInLHN(reports, false, mockLocaleCompare, undefined, undefined, undefined);
 
-                // When the reports are sorted in GSD mode
-                const gsdResult = SidebarUtils.sortReportsToDisplayInLHN(reports, CONST.PRIORITY_MODE.GSD, mockLocaleCompare, undefined, undefined, undefined);
+                // When the reports are sorted in alphabetical mode
+                const gsdResult = SidebarUtils.sortReportsToDisplayInLHN(reports, true, mockLocaleCompare, undefined, undefined, undefined);
 
                 // Then the reports are sorted in the correct order
                 expect(defaultResult).toEqual(['1', '0']); // Most recent first (index 1 has later date)
@@ -3523,7 +3523,6 @@ describe('SidebarUtils', () => {
                     reports,
                     updatedReportsKeys: [`${ONYXKEYS.COLLECTION.REPORT}999`],
                     currentReportId: '1',
-                    isInFocusMode: false,
                     betas: [],
                     transactions: {},
                     transactionViolations: {},
@@ -3544,7 +3543,6 @@ describe('SidebarUtils', () => {
                     reports,
                     updatedReportsKeys: ['0'],
                     currentReportId: undefined,
-                    isInFocusMode: false,
                     betas: [],
                     transactions: {},
                     transactionViolations: {},

From 9af6b204a644f685ae4648f107a917a35497c736 Mon Sep 17 00:00:00 2001
From: Shawn Borton <shawn@expensify.com>
Date: Fri, 17 Apr 2026 15:55:47 +0200
Subject: [PATCH 010/435] Update tabs to All/To do/Expenses/DMs and add Unreads
 toggle

Replace the Unread tab with a "To do" tab that shows items needing
action (GBR/RBR indicators). Rename Direct Messages to DMs.

Add a separate Unreads toggle in the Inbox header using a small 20px
Switch component. The toggle filters to show only unread items and
works across all tabs. State persists via NVP_INBOX_UNREAD_FILTER.

- Add 'small' size variant to Switch component (36x20 track, 14x14 thumb)
- Add switchTrackSmall/switchThumbSmall styles
- Add InboxUnreadToggle component with "Unreads" label + small switch
- Update filterReportsForInboxTab to apply unread filter orthogonally

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
---
 src/CONST/index.ts                            |  4 +--
 src/ONYXKEYS.ts                               |  4 +++
 src/components/Switch.tsx                     | 22 ++++++++++----
 src/hooks/useSidebarOrderedReports.tsx        | 30 ++++++++++++-------
 src/languages/de.ts                           |  5 ++--
 src/languages/en.ts                           |  5 ++--
 src/languages/es.ts                           |  5 ++--
 src/languages/fr.ts                           |  5 ++--
 src/languages/it.ts                           |  5 ++--
 src/languages/ja.ts                           |  5 ++--
 src/languages/nl.ts                           |  5 ++--
 src/languages/pl.ts                           |  5 ++--
 src/languages/pt-BR.ts                        |  5 ++--
 src/languages/zh-hans.ts                      |  5 ++--
 src/libs/SidebarUtils.ts                      | 29 ++++++++++--------
 src/libs/actions/User.ts                      |  5 ++++
 src/pages/inbox/sidebar/BaseSidebarScreen.tsx |  5 +++-
 src/pages/inbox/sidebar/InboxTabSelector.tsx  |  4 +--
 src/pages/inbox/sidebar/InboxUnreadToggle.tsx | 30 +++++++++++++++++++
 src/styles/index.ts                           | 14 +++++++++
 20 files changed, 144 insertions(+), 53 deletions(-)
 create mode 100644 src/pages/inbox/sidebar/InboxUnreadToggle.tsx

diff --git a/src/CONST/index.ts b/src/CONST/index.ts
index 3fbca9aa9280..be0e4fd88728 100644
--- a/src/CONST/index.ts
+++ b/src/CONST/index.ts
@@ -2085,9 +2085,9 @@ const CONST = {
     },
     INBOX_TAB: {
         ALL: 'all',
-        UNREADS: 'unreads',
+        TODO: 'todo',
         EXPENSES: 'expenses',
-        DIRECT_MESSAGES: 'directMessages',
+        DMS: 'dms',
     },
     THEME: {
         DEFAULT: 'system',
diff --git a/src/ONYXKEYS.ts b/src/ONYXKEYS.ts
index b7da30c7c155..3dce345ee6e7 100755
--- a/src/ONYXKEYS.ts
+++ b/src/ONYXKEYS.ts
@@ -162,6 +162,9 @@ const ONYXKEYS = {
     /** Contains the user preference for the active inbox tab filter */
     NVP_INBOX_TAB: 'nvp_inboxTab',
 
+    /** Whether to show only unread chats in the inbox */
+    NVP_INBOX_UNREAD_FILTER: 'nvp_inboxUnreadFilter',
+
     /** Contains the users's block expiration (if they have one) */
     NVP_BLOCKED_FROM_CONCIERGE: 'nvp_private_blockedFromConcierge',
 
@@ -1354,6 +1357,7 @@ type OnyxValuesMapping = {
     [ONYXKEYS.BETA_CONFIGURATION]: OnyxTypes.BetaConfiguration;
     [ONYXKEYS.NVP_MUTED_PLATFORMS]: Partial<Record<Platform, true>>;
     [ONYXKEYS.NVP_INBOX_TAB]: ValueOf<typeof CONST.INBOX_TAB>;
+    [ONYXKEYS.NVP_INBOX_UNREAD_FILTER]: boolean;
     [ONYXKEYS.NVP_BLOCKED_FROM_CONCIERGE]: OnyxTypes.BlockedFromConcierge;
     [ONYXKEYS.QUEUE_FLUSHED_DATA]: AnyOnyxUpdate[];
     [ONYXKEYS.TRANSACTIONS_PENDING_3DS_REVIEW]: OnyxTypes.TransactionsPending3DSReview;
diff --git a/src/components/Switch.tsx b/src/components/Switch.tsx
index ed82f75422e4..0c888a2efa66 100644
--- a/src/components/Switch.tsx
+++ b/src/components/Switch.tsx
@@ -26,6 +26,9 @@ type SwitchProps = {
 
     /** Callback to fire when the switch is toggled in disabled state */
     disabledAction?: () => void;
+
+    /** Size variant. 'small' renders a compact 20px tall switch. */
+    size?: 'default' | 'small';
 };
 
 const OFFSET_X = {
@@ -33,14 +36,21 @@ const OFFSET_X = {
     ON: 20,
 };
 
-function Switch({isOn, onToggle, accessibilityLabel, disabled, showLockIcon, disabledAction}: SwitchProps) {
+const OFFSET_X_SMALL = {
+    OFF: 0,
+    ON: 16,
+};
+
+function Switch({isOn, onToggle, accessibilityLabel, disabled, showLockIcon, disabledAction, size}: SwitchProps) {
     const styles = useThemeStyles();
     const {translate} = useLocalize();
-    const offsetX = useSharedValue(isOn ? OFFSET_X.ON : OFFSET_X.OFF);
+    const isSmall = size === 'small';
+    const offsets = isSmall ? OFFSET_X_SMALL : OFFSET_X;
+    const offsetX = useSharedValue(isOn ? offsets.ON : offsets.OFF);
     const theme = useTheme();
     const expensifyIcons = useMemoizedLazyExpensifyIcons(['Lock']);
 
-    const targetOffsetX = isOn ? OFFSET_X.ON : OFFSET_X.OFF;
+    const targetOffsetX = isOn ? offsets.ON : offsets.OFF;
     const prevIsOn = useRef(isOn);
     const hasUserToggled = useRef(false);
 
@@ -85,7 +95,7 @@ function Switch({isOn, onToggle, accessibilityLabel, disabled, showLockIcon, dis
     }));
 
     const animatedSwitchTrackStyle = useAnimatedStyle(() => ({
-        backgroundColor: interpolateColor(offsetX.get(), [OFFSET_X.OFF, OFFSET_X.ON], [theme.icon, theme.success]),
+        backgroundColor: interpolateColor(offsetX.get(), [offsets.OFF, offsets.ON], [theme.icon, theme.success]),
     }));
 
     // Enhance accessibility label to include locked state when disabled
@@ -109,8 +119,8 @@ function Switch({isOn, onToggle, accessibilityLabel, disabled, showLockIcon, dis
             pressDimmingValue={0.8}
             sentryLabel={enhancedAccessibilityLabel}
         >
-            <Animated.View style={[styles.switchTrack, animatedSwitchTrackStyle]}>
-                <Animated.View style={[styles.switchThumb, animatedThumbStyle]}>
+            <Animated.View style={[styles.switchTrack, isSmall && styles.switchTrackSmall, animatedSwitchTrackStyle]}>
+                <Animated.View style={[styles.switchThumb, isSmall && styles.switchThumbSmall, animatedThumbStyle]}>
                     {(!!disabled || !!showLockIcon) && (
                         <Icon
                             src={expensifyIcons.Lock}
diff --git a/src/hooks/useSidebarOrderedReports.tsx b/src/hooks/useSidebarOrderedReports.tsx
index bd2ea03621c7..c54abee7d3b8 100644
--- a/src/hooks/useSidebarOrderedReports.tsx
+++ b/src/hooks/useSidebarOrderedReports.tsx
@@ -2,7 +2,7 @@ import {deepEqual} from 'fast-equals';
 import React, {createContext, useCallback, useContext, useEffect, useMemo, useRef, useState} from 'react';
 import type {OnyxEntry} from 'react-native-onyx';
 import type {ValueOf} from 'type-fest';
-import {setInboxTab} from '@libs/actions/User';
+import {setInboxTab, setInboxUnreadFilter} from '@libs/actions/User';
 import Log from '@libs/Log';
 import {getTransactionThreadReportID} from '@libs/MergeTransactionUtils';
 import {isOneTransactionReport} from '@libs/ReportUtils';
@@ -36,11 +36,13 @@ type SidebarOrderedReportsStateContextValue = {
     currentReportID: string | undefined;
     chatTabBrickRoad: BrickRoad;
     activeTab: ValueOf<typeof CONST.INBOX_TAB>;
+    showUnreadOnly: boolean;
 };
 
 type SidebarOrderedReportsActionsContextValue = {
     clearLHNCache: () => void;
     setActiveTab: (tab: ValueOf<typeof CONST.INBOX_TAB>) => void;
+    toggleUnreadFilter: () => void;
 };
 
 type ReportsToDisplayInLHN = Record<string, OnyxTypes.Report & {hasErrorsOtherThanFailedReceipt?: boolean; requiresAttention?: boolean}>;
@@ -51,11 +53,13 @@ const SidebarOrderedReportsStateContext = createContext<SidebarOrderedReportsSta
     currentReportID: '',
     chatTabBrickRoad: undefined,
     activeTab: CONST.INBOX_TAB.ALL,
+    showUnreadOnly: false,
 });
 
 const SidebarOrderedReportsActionsContext = createContext<SidebarOrderedReportsActionsContextValue>({
     clearLHNCache: () => {},
     setActiveTab: () => {},
+    toggleUnreadFilter: () => {},
 });
 
 const policyMapper = (policy: OnyxEntry<OnyxTypes.Policy>): PartialPolicyForSidebar =>
@@ -81,6 +85,8 @@ function SidebarOrderedReportsContextProvider({
     const {localeCompare} = useLocalize();
     const [inboxTab = CONST.INBOX_TAB.ALL] = useOnyx(ONYXKEYS.NVP_INBOX_TAB);
     const activeTab = inboxTab ?? CONST.INBOX_TAB.ALL;
+    const [inboxUnreadFilter = false] = useOnyx(ONYXKEYS.NVP_INBOX_UNREAD_FILTER);
+    const showUnreadOnly = inboxUnreadFilter ?? false;
     const [chatReports, {sourceValue: reportUpdates}] = useOnyx(ONYXKEYS.COLLECTION.REPORT);
     const [policies, {sourceValue: policiesUpdates}] = useMappedPolicies(policyMapper);
     const [transactions, {sourceValue: transactionsUpdates}] = useOnyx(ONYXKEYS.COLLECTION.TRANSACTION);
@@ -255,20 +261,18 @@ function SidebarOrderedReportsContextProvider({
         setCurrentReportsToDisplay(reportsToDisplayInLHN);
     }, [reportsToDisplayInLHN]);
 
-    const useAlphabeticalSort = activeTab === CONST.INBOX_TAB.UNREADS;
-
     const getOrderedReportIDs = useCallback(
-        () => SidebarUtils.sortReportsToDisplayInLHN(reportsToDisplayInLHN, useAlphabeticalSort, localeCompare, hasDraftByReportID, reportNameValuePairs, reportAttributes),
+        () => SidebarUtils.sortReportsToDisplayInLHN(reportsToDisplayInLHN, false, localeCompare, hasDraftByReportID, reportNameValuePairs, reportAttributes),
         // Rule disabled intentionally - reports should be sorted only when the reportsToDisplayInLHN changes
         // eslint-disable-next-line react-hooks/exhaustive-deps
-        [reportsToDisplayInLHN, useAlphabeticalSort, localeCompare, hasDraftByReportID, reportAttributes],
+        [reportsToDisplayInLHN, localeCompare, hasDraftByReportID, reportAttributes],
     );
 
     const orderedReportIDs = useMemo(() => getOrderedReportIDs(), [getOrderedReportIDs]);
 
     const filteredReportIDs = useMemo(
-        () => SidebarUtils.filterReportsForInboxTab(orderedReportIDs, reportsToDisplayInLHN, activeTab, hasDraftByReportID, reportNameValuePairs),
-        [orderedReportIDs, reportsToDisplayInLHN, activeTab, hasDraftByReportID, reportNameValuePairs],
+        () => SidebarUtils.filterReportsForInboxTab(orderedReportIDs, reportsToDisplayInLHN, activeTab, showUnreadOnly, reportNameValuePairs),
+        [orderedReportIDs, reportsToDisplayInLHN, activeTab, showUnreadOnly, reportNameValuePairs],
     );
 
     // Get the actual reports based on the filtered IDs
@@ -294,6 +298,10 @@ function SidebarOrderedReportsContextProvider({
         setInboxTab(tab);
     }, []);
 
+    const toggleUnreadFilter = useCallback(() => {
+        setInboxUnreadFilter(!showUnreadOnly);
+    }, [showUnreadOnly]);
+
     const stateValue: SidebarOrderedReportsStateContextValue = useMemo(() => {
         // We need to make sure the current report is in the list of reports, but we do not want
         // to have to re-generate the list every time the currentReportID changes. To do that
@@ -312,7 +320,7 @@ function SidebarOrderedReportsContextProvider({
             filteredReportIDs.indexOf(derivedCurrentReportID) === -1
         ) {
             const updatedReportIDs = getOrderedReportIDs();
-            const updatedFilteredIDs = SidebarUtils.filterReportsForInboxTab(updatedReportIDs, reportsToDisplayInLHN, activeTab, hasDraftByReportID, reportNameValuePairs);
+            const updatedFilteredIDs = SidebarUtils.filterReportsForInboxTab(updatedReportIDs, reportsToDisplayInLHN, activeTab, showUnreadOnly, reportNameValuePairs);
             const updatedReports = getOrderedReports(updatedFilteredIDs);
             return {
                 orderedReports: updatedReports,
@@ -320,6 +328,7 @@ function SidebarOrderedReportsContextProvider({
                 currentReportID: derivedCurrentReportID,
                 chatTabBrickRoad: getChatTabBrickRoad(updatedReportIDs, reportAttributes),
                 activeTab,
+                showUnreadOnly,
             };
         }
 
@@ -329,6 +338,7 @@ function SidebarOrderedReportsContextProvider({
             currentReportID: derivedCurrentReportID,
             chatTabBrickRoad: getChatTabBrickRoad(orderedReportIDs, reportAttributes),
             activeTab,
+            showUnreadOnly,
         };
     }, [
         getOrderedReportIDs,
@@ -340,12 +350,12 @@ function SidebarOrderedReportsContextProvider({
         orderedReports,
         reportAttributes,
         activeTab,
+        showUnreadOnly,
         reportsToDisplayInLHN,
-        hasDraftByReportID,
         reportNameValuePairs,
     ]);
 
-    const actionsValue: SidebarOrderedReportsActionsContextValue = useMemo(() => ({clearLHNCache, setActiveTab}), [clearLHNCache, setActiveTab]);
+    const actionsValue: SidebarOrderedReportsActionsContextValue = useMemo(() => ({clearLHNCache, setActiveTab, toggleUnreadFilter}), [clearLHNCache, setActiveTab, toggleUnreadFilter]);
 
     const currentDeps = {
         activeTab,
diff --git a/src/languages/de.ts b/src/languages/de.ts
index 9c9f75001ff2..befcb46025c3 100644
--- a/src/languages/de.ts
+++ b/src/languages/de.ts
@@ -2788,9 +2788,10 @@ ${amount} für ${merchant} – ${date}`,
     },
     inboxTabs: {
         all: 'All',
-        unreads: 'Unread',
+        todo: 'To do',
         expenses: 'Expenses',
-        directMessages: 'Direct messages',
+        dms: 'DMs',
+        unreadToggle: 'Unreads',
     },
     reportDetailsPage: {
         inWorkspace: (policyName: string) => `in ${policyName}`,
diff --git a/src/languages/en.ts b/src/languages/en.ts
index 12480bbb55c4..9be6ecbc314c 100644
--- a/src/languages/en.ts
+++ b/src/languages/en.ts
@@ -2842,9 +2842,10 @@ const translations = {
     },
     inboxTabs: {
         all: 'All',
-        unreads: 'Unread',
+        todo: 'To do',
         expenses: 'Expenses',
-        directMessages: 'Direct messages',
+        dms: 'DMs',
+        unreadToggle: 'Unreads',
     },
     reportDetailsPage: {
         inWorkspace: (policyName: string) => `in ${policyName}`,
diff --git a/src/languages/es.ts b/src/languages/es.ts
index d9243ca2d933..741f20fc7dfb 100644
--- a/src/languages/es.ts
+++ b/src/languages/es.ts
@@ -2659,9 +2659,10 @@ ${amount} para ${merchant} - ${date}`,
     },
     inboxTabs: {
         all: 'All',
-        unreads: 'Unread',
+        todo: 'To do',
         expenses: 'Expenses',
-        directMessages: 'Direct messages',
+        dms: 'DMs',
+        unreadToggle: 'Unreads',
     },
     reportDetailsPage: {
         inWorkspace: (policyName) => `en ${policyName}`,
diff --git a/src/languages/fr.ts b/src/languages/fr.ts
index 57e3862724a6..d90ee798f375 100644
--- a/src/languages/fr.ts
+++ b/src/languages/fr.ts
@@ -2794,9 +2794,10 @@ ${amount} pour ${merchant} - ${date}`,
     },
     inboxTabs: {
         all: 'All',
-        unreads: 'Unread',
+        todo: 'To do',
         expenses: 'Expenses',
-        directMessages: 'Direct messages',
+        dms: 'DMs',
+        unreadToggle: 'Unreads',
     },
     reportDetailsPage: {
         inWorkspace: (policyName: string) => `dans ${policyName}`,
diff --git a/src/languages/it.ts b/src/languages/it.ts
index eea77cc79424..dd14322c29c2 100644
--- a/src/languages/it.ts
+++ b/src/languages/it.ts
@@ -2783,9 +2783,10 @@ ${amount} per ${merchant} - ${date}`,
     },
     inboxTabs: {
         all: 'All',
-        unreads: 'Unread',
+        todo: 'To do',
         expenses: 'Expenses',
-        directMessages: 'Direct messages',
+        dms: 'DMs',
+        unreadToggle: 'Unreads',
     },
     reportDetailsPage: {
         inWorkspace: (policyName: string) => `in ${policyName}`,
diff --git a/src/languages/ja.ts b/src/languages/ja.ts
index 455bf7a8850a..1600d5034687 100644
--- a/src/languages/ja.ts
+++ b/src/languages/ja.ts
@@ -2756,9 +2756,10 @@ ${date} の ${merchant} への ${amount}`,
     },
     inboxTabs: {
         all: 'All',
-        unreads: 'Unread',
+        todo: 'To do',
         expenses: 'Expenses',
-        directMessages: 'Direct messages',
+        dms: 'DMs',
+        unreadToggle: 'Unreads',
     },
     reportDetailsPage: {
         inWorkspace: (policyName: string) => `${policyName} 内`,
diff --git a/src/languages/nl.ts b/src/languages/nl.ts
index 4038df5299d4..9617a0d09edb 100644
--- a/src/languages/nl.ts
+++ b/src/languages/nl.ts
@@ -2781,9 +2781,10 @@ ${amount} voor ${merchant} - ${date}`,
     },
     inboxTabs: {
         all: 'All',
-        unreads: 'Unread',
+        todo: 'To do',
         expenses: 'Expenses',
-        directMessages: 'Direct messages',
+        dms: 'DMs',
+        unreadToggle: 'Unreads',
     },
     reportDetailsPage: {
         inWorkspace: (policyName: string) => `in ${policyName}`,
diff --git a/src/languages/pl.ts b/src/languages/pl.ts
index 496974e494b8..4950507eb6d8 100644
--- a/src/languages/pl.ts
+++ b/src/languages/pl.ts
@@ -2774,9 +2774,10 @@ ${amount} dla ${merchant} - ${date}`,
     },
     inboxTabs: {
         all: 'All',
-        unreads: 'Unread',
+        todo: 'To do',
         expenses: 'Expenses',
-        directMessages: 'Direct messages',
+        dms: 'DMs',
+        unreadToggle: 'Unreads',
     },
     reportDetailsPage: {
         inWorkspace: (policyName: string) => `w ${policyName}`,
diff --git a/src/languages/pt-BR.ts b/src/languages/pt-BR.ts
index 9cecddddfb48..a15d7cc509c4 100644
--- a/src/languages/pt-BR.ts
+++ b/src/languages/pt-BR.ts
@@ -2774,9 +2774,10 @@ ${amount} para ${merchant} - ${date}`,
     },
     inboxTabs: {
         all: 'All',
-        unreads: 'Unread',
+        todo: 'To do',
         expenses: 'Expenses',
-        directMessages: 'Direct messages',
+        dms: 'DMs',
+        unreadToggle: 'Unreads',
     },
     reportDetailsPage: {
         inWorkspace: (policyName: string) => `em ${policyName}`,
diff --git a/src/languages/zh-hans.ts b/src/languages/zh-hans.ts
index aade94e81823..3db3f03dda5c 100644
--- a/src/languages/zh-hans.ts
+++ b/src/languages/zh-hans.ts
@@ -2706,9 +2706,10 @@ ${amount}，商户：${merchant} - 日期：${date}`,
     },
     inboxTabs: {
         all: 'All',
-        unreads: 'Unread',
+        todo: 'To do',
         expenses: 'Expenses',
-        directMessages: 'Direct messages',
+        dms: 'DMs',
+        unreadToggle: 'Unreads',
     },
     reportDetailsPage: {
         inWorkspace: (policyName: string) => `在 ${policyName} 中`,
diff --git a/src/libs/SidebarUtils.ts b/src/libs/SidebarUtils.ts
index 623caf8ad8d8..2bec6d18432c 100644
--- a/src/libs/SidebarUtils.ts
+++ b/src/libs/SidebarUtils.ts
@@ -1412,29 +1412,34 @@ function filterReportsForInboxTab(
     reportIDs: string[],
     reportsToDisplay: ReportsToDisplayInLHN,
     activeTab: ValueOf<typeof CONST.INBOX_TAB>,
-    reportsDrafts?: Record<string, boolean>,
+    showUnreadOnly: boolean,
     reportNameValuePairs?: OnyxCollection<ReportNameValuePairs>,
 ): string[] {
-    if (activeTab === CONST.INBOX_TAB.ALL) {
-        return reportIDs;
-    }
-
     return reportIDs.filter((reportID) => {
         const report = reportsToDisplay[`${ONYXKEYS.COLLECTION.REPORT}${reportID}`];
         if (!report) {
             return false;
         }
 
-        switch (activeTab) {
-            case CONST.INBOX_TAB.UNREADS: {
-                const isReportArchived = isArchivedReport(reportNameValuePairs?.[`${ONYXKEYS.COLLECTION.REPORT_NAME_VALUE_PAIRS}${reportID}`]);
-                const isReportUnread = isUnread(report, undefined, isReportArchived) && getReportNotificationPreference(report) !== CONST.REPORT.NOTIFICATION_PREFERENCE.MUTE;
-                const hasDraft = !!reportsDrafts?.[reportID];
-                return isReportUnread || !!report.isPinned || !!report.requiresAttention || !!report.hasErrorsOtherThanFailedReceipt || hasDraft;
+        // Apply unread filter when the toggle is active
+        if (showUnreadOnly) {
+            const isReportArchived = isArchivedReport(reportNameValuePairs?.[`${ONYXKEYS.COLLECTION.REPORT_NAME_VALUE_PAIRS}${reportID}`]);
+            const isReportUnread = isUnread(report, undefined, isReportArchived) && getReportNotificationPreference(report) !== CONST.REPORT.NOTIFICATION_PREFERENCE.MUTE;
+            if (!isReportUnread && !report.isPinned && !report.requiresAttention && !report.hasErrorsOtherThanFailedReceipt) {
+                return false;
             }
+        }
+
+        if (activeTab === CONST.INBOX_TAB.ALL) {
+            return true;
+        }
+
+        switch (activeTab) {
+            case CONST.INBOX_TAB.TODO:
+                return !!report.requiresAttention || !!report.hasErrorsOtherThanFailedReceipt;
             case CONST.INBOX_TAB.EXPENSES:
                 return isExpenseReport(report) || isIOUReport(report) || isInvoiceReport(report) || isPolicyExpenseChat(report);
-            case CONST.INBOX_TAB.DIRECT_MESSAGES:
+            case CONST.INBOX_TAB.DMS:
                 return isDM(report) || isSelfDM(report) || isGroupChatUtil(report);
             default:
                 return true;
diff --git a/src/libs/actions/User.ts b/src/libs/actions/User.ts
index 138d02d821d5..975dfeaafc19 100644
--- a/src/libs/actions/User.ts
+++ b/src/libs/actions/User.ts
@@ -953,6 +953,10 @@ function setInboxTab(tab: ValueOf<typeof CONST.INBOX_TAB>) {
     Onyx.merge(ONYXKEYS.NVP_INBOX_TAB, tab);
 }
 
+function setInboxUnreadFilter(enabled: boolean) {
+    Onyx.merge(ONYXKEYS.NVP_INBOX_UNREAD_FILTER, enabled);
+}
+
 function setShouldUseStagingServer(shouldUseStagingServer: boolean) {
     if (CONFIG.IS_HYBRID_APP) {
         HybridAppModule.shouldUseStaging(shouldUseStagingServer);
@@ -1878,6 +1882,7 @@ export {
     subscribeToUserEvents,
     updatePreferredSkinTone,
     setInboxTab,
+    setInboxUnreadFilter,
     setShouldUseStagingServer,
     togglePlatformMute,
     joinScreenShare,
diff --git a/src/pages/inbox/sidebar/BaseSidebarScreen.tsx b/src/pages/inbox/sidebar/BaseSidebarScreen.tsx
index fb4a748e7460..8f3bf3d553d8 100644
--- a/src/pages/inbox/sidebar/BaseSidebarScreen.tsx
+++ b/src/pages/inbox/sidebar/BaseSidebarScreen.tsx
@@ -15,6 +15,7 @@ import {isMobile} from '@libs/Browser';
 import type {SkeletonSpanReasonAttributes} from '@libs/telemetry/useSkeletonSpan';
 import ONYXKEYS from '@src/ONYXKEYS';
 import InboxTabSelector from './InboxTabSelector';
+import InboxUnreadToggle from './InboxUnreadToggle';
 import SidebarLinksData from './SidebarLinksData';
 
 // Once the app finishes loading for the first time, we never show the skeleton again
@@ -59,7 +60,9 @@ function BaseSidebarScreen() {
                         breadcrumbLabel={translate('common.inbox')}
                         shouldDisplaySearch={shouldUseNarrowLayout}
                         shouldDisplayHelpButton={shouldUseNarrowLayout}
-                    />
+                    >
+                        {!shouldShowSkeleton && <InboxUnreadToggle />}
+                    </TopBarWithLoadingBar>
                     {!shouldShowSkeleton && <InboxTabSelector />}
                     <View style={[styles.flex1]}>
                         {shouldShowSkeleton ? (
diff --git a/src/pages/inbox/sidebar/InboxTabSelector.tsx b/src/pages/inbox/sidebar/InboxTabSelector.tsx
index d8e75506b891..0cc87b328b3e 100644
--- a/src/pages/inbox/sidebar/InboxTabSelector.tsx
+++ b/src/pages/inbox/sidebar/InboxTabSelector.tsx
@@ -13,9 +13,9 @@ function InboxTabSelector() {
 
     const tabs: TabSelectorBaseItem[] = [
         {key: CONST.INBOX_TAB.ALL, title: translate('inboxTabs.all')},
-        {key: CONST.INBOX_TAB.UNREADS, title: translate('inboxTabs.unreads')},
+        {key: CONST.INBOX_TAB.TODO, title: translate('inboxTabs.todo')},
         {key: CONST.INBOX_TAB.EXPENSES, title: translate('inboxTabs.expenses')},
-        {key: CONST.INBOX_TAB.DIRECT_MESSAGES, title: translate('inboxTabs.directMessages')},
+        {key: CONST.INBOX_TAB.DMS, title: translate('inboxTabs.dms')},
     ];
 
     return (
diff --git a/src/pages/inbox/sidebar/InboxUnreadToggle.tsx b/src/pages/inbox/sidebar/InboxUnreadToggle.tsx
new file mode 100644
index 000000000000..e5d38653b2a8
--- /dev/null
+++ b/src/pages/inbox/sidebar/InboxUnreadToggle.tsx
@@ -0,0 +1,30 @@
+import React from 'react';
+import {View} from 'react-native';
+import Switch from '@components/Switch';
+import Text from '@components/Text';
+import useLocalize from '@hooks/useLocalize';
+import {useSidebarOrderedReportsActions, useSidebarOrderedReportsState} from '@hooks/useSidebarOrderedReports';
+import useThemeStyles from '@hooks/useThemeStyles';
+
+function InboxUnreadToggle() {
+    const styles = useThemeStyles();
+    const {translate} = useLocalize();
+    const {showUnreadOnly} = useSidebarOrderedReportsState();
+    const {toggleUnreadFilter} = useSidebarOrderedReportsActions();
+
+    return (
+        <View style={[styles.flexRow, styles.alignItemsCenter, styles.gap2]}>
+            <Text style={[styles.textSmall, styles.textSupporting]}>{translate('inboxTabs.unreadToggle')}</Text>
+            <Switch
+                isOn={showUnreadOnly}
+                onToggle={() => toggleUnreadFilter()}
+                accessibilityLabel={translate('inboxTabs.unreadToggle')}
+                size="small"
+            />
+        </View>
+    );
+}
+
+InboxUnreadToggle.displayName = 'InboxUnreadToggle';
+
+export default InboxUnreadToggle;
diff --git a/src/styles/index.ts b/src/styles/index.ts
index eae83119cc2f..172579d142fb 100644
--- a/src/styles/index.ts
+++ b/src/styles/index.ts
@@ -3039,6 +3039,13 @@ const staticStyles = (theme: ThemeColors) =>
             padding: 15,
         },
 
+        switchTrackSmall: {
+            width: 36,
+            height: 20,
+            borderRadius: 10,
+            padding: 10,
+        },
+
         switchThumb: {
             width: 22,
             height: 22,
@@ -3050,6 +3057,13 @@ const staticStyles = (theme: ThemeColors) =>
             backgroundColor: theme.appBG,
         },
 
+        switchThumbSmall: {
+            width: 14,
+            height: 14,
+            borderRadius: 7,
+            left: 3,
+        },
+
         radioButtonContainer: {
             backgroundColor: theme.componentBG,
             borderRadius: 14,

From 8634be9aef25b9b6c02ab26feb9fd67635c86a6d Mon Sep 17 00:00:00 2001
From: Shawn Borton <shawn@expensify.com>
Date: Fri, 17 Apr 2026 15:56:42 +0200
Subject: [PATCH 011/435] Change 'To do' tab label to 'To-do'

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
---
 src/languages/de.ts      | 2 +-
 src/languages/en.ts      | 2 +-
 src/languages/es.ts      | 2 +-
 src/languages/fr.ts      | 2 +-
 src/languages/it.ts      | 2 +-
 src/languages/ja.ts      | 2 +-
 src/languages/nl.ts      | 2 +-
 src/languages/pl.ts      | 2 +-
 src/languages/pt-BR.ts   | 2 +-
 src/languages/zh-hans.ts | 2 +-
 10 files changed, 10 insertions(+), 10 deletions(-)

diff --git a/src/languages/de.ts b/src/languages/de.ts
index befcb46025c3..f524383c939a 100644
--- a/src/languages/de.ts
+++ b/src/languages/de.ts
@@ -2788,7 +2788,7 @@ ${amount} für ${merchant} – ${date}`,
     },
     inboxTabs: {
         all: 'All',
-        todo: 'To do',
+        todo: 'To-do',
         expenses: 'Expenses',
         dms: 'DMs',
         unreadToggle: 'Unreads',
diff --git a/src/languages/en.ts b/src/languages/en.ts
index 9be6ecbc314c..65997ac79bc6 100644
--- a/src/languages/en.ts
+++ b/src/languages/en.ts
@@ -2842,7 +2842,7 @@ const translations = {
     },
     inboxTabs: {
         all: 'All',
-        todo: 'To do',
+        todo: 'To-do',
         expenses: 'Expenses',
         dms: 'DMs',
         unreadToggle: 'Unreads',
diff --git a/src/languages/es.ts b/src/languages/es.ts
index 741f20fc7dfb..a0e6fcbbe9d2 100644
--- a/src/languages/es.ts
+++ b/src/languages/es.ts
@@ -2659,7 +2659,7 @@ ${amount} para ${merchant} - ${date}`,
     },
     inboxTabs: {
         all: 'All',
-        todo: 'To do',
+        todo: 'To-do',
         expenses: 'Expenses',
         dms: 'DMs',
         unreadToggle: 'Unreads',
diff --git a/src/languages/fr.ts b/src/languages/fr.ts
index d90ee798f375..c7eabf81d038 100644
--- a/src/languages/fr.ts
+++ b/src/languages/fr.ts
@@ -2794,7 +2794,7 @@ ${amount} pour ${merchant} - ${date}`,
     },
     inboxTabs: {
         all: 'All',
-        todo: 'To do',
+        todo: 'To-do',
         expenses: 'Expenses',
         dms: 'DMs',
         unreadToggle: 'Unreads',
diff --git a/src/languages/it.ts b/src/languages/it.ts
index dd14322c29c2..b1f599039dc7 100644
--- a/src/languages/it.ts
+++ b/src/languages/it.ts
@@ -2783,7 +2783,7 @@ ${amount} per ${merchant} - ${date}`,
     },
     inboxTabs: {
         all: 'All',
-        todo: 'To do',
+        todo: 'To-do',
         expenses: 'Expenses',
         dms: 'DMs',
         unreadToggle: 'Unreads',
diff --git a/src/languages/ja.ts b/src/languages/ja.ts
index 1600d5034687..abf3fc73df15 100644
--- a/src/languages/ja.ts
+++ b/src/languages/ja.ts
@@ -2756,7 +2756,7 @@ ${date} の ${merchant} への ${amount}`,
     },
     inboxTabs: {
         all: 'All',
-        todo: 'To do',
+        todo: 'To-do',
         expenses: 'Expenses',
         dms: 'DMs',
         unreadToggle: 'Unreads',
diff --git a/src/languages/nl.ts b/src/languages/nl.ts
index 9617a0d09edb..4cc5e5d067f1 100644
--- a/src/languages/nl.ts
+++ b/src/languages/nl.ts
@@ -2781,7 +2781,7 @@ ${amount} voor ${merchant} - ${date}`,
     },
     inboxTabs: {
         all: 'All',
-        todo: 'To do',
+        todo: 'To-do',
         expenses: 'Expenses',
         dms: 'DMs',
         unreadToggle: 'Unreads',
diff --git a/src/languages/pl.ts b/src/languages/pl.ts
index 4950507eb6d8..7cc40fa1f87c 100644
--- a/src/languages/pl.ts
+++ b/src/languages/pl.ts
@@ -2774,7 +2774,7 @@ ${amount} dla ${merchant} - ${date}`,
     },
     inboxTabs: {
         all: 'All',
-        todo: 'To do',
+        todo: 'To-do',
         expenses: 'Expenses',
         dms: 'DMs',
         unreadToggle: 'Unreads',
diff --git a/src/languages/pt-BR.ts b/src/languages/pt-BR.ts
index a15d7cc509c4..912f0c2f827d 100644
--- a/src/languages/pt-BR.ts
+++ b/src/languages/pt-BR.ts
@@ -2774,7 +2774,7 @@ ${amount} para ${merchant} - ${date}`,
     },
     inboxTabs: {
         all: 'All',
-        todo: 'To do',
+        todo: 'To-do',
         expenses: 'Expenses',
         dms: 'DMs',
         unreadToggle: 'Unreads',
diff --git a/src/languages/zh-hans.ts b/src/languages/zh-hans.ts
index 3db3f03dda5c..2eba054e6446 100644
--- a/src/languages/zh-hans.ts
+++ b/src/languages/zh-hans.ts
@@ -2706,7 +2706,7 @@ ${amount}，商户：${merchant} - 日期：${date}`,
     },
     inboxTabs: {
         all: 'All',
-        todo: 'To do',
+        todo: 'To-do',
         expenses: 'Expenses',
         dms: 'DMs',
         unreadToggle: 'Unreads',

From e2ebe4607b02abdaeac731b9e04f48017d3fe441 Mon Sep 17 00:00:00 2001
From: Shawn Borton <shawn@expensify.com>
Date: Tue, 21 Apr 2026 18:14:56 +0200
Subject: [PATCH 012/435] Replace Priority Mode with Inbox Tab Filters

Simplify inbox filtering to four straightforward tabs:
All, Unread, Expenses, and DMs. Remove the separate Unreads toggle
and To-do tab in favor of a clean Unread tab that shows only
unread and non-muted chats. Pinned/GBR/RBR items show only if
they qualify for the active tab filter.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
---
 src/CONST/index.ts                            |  2 +-
 src/ONYXKEYS.ts                               |  4 ---
 src/hooks/useSidebarOrderedReports.tsx        | 23 ++++----------
 src/languages/de.ts                           |  3 +-
 src/languages/en.ts                           |  3 +-
 src/languages/es.ts                           |  3 +-
 src/languages/fr.ts                           |  3 +-
 src/languages/it.ts                           |  3 +-
 src/languages/ja.ts                           |  3 +-
 src/languages/nl.ts                           |  3 +-
 src/languages/pl.ts                           |  3 +-
 src/languages/pt-BR.ts                        |  3 +-
 src/languages/zh-hans.ts                      |  3 +-
 src/libs/SidebarUtils.ts                      | 24 +++++----------
 src/libs/actions/User.ts                      |  5 ----
 src/pages/inbox/sidebar/BaseSidebarScreen.tsx |  5 +---
 src/pages/inbox/sidebar/InboxTabSelector.tsx  |  2 +-
 src/pages/inbox/sidebar/InboxUnreadToggle.tsx | 30 -------------------
 18 files changed, 26 insertions(+), 99 deletions(-)
 delete mode 100644 src/pages/inbox/sidebar/InboxUnreadToggle.tsx

diff --git a/src/CONST/index.ts b/src/CONST/index.ts
index be0e4fd88728..6bf0ab68c2c2 100644
--- a/src/CONST/index.ts
+++ b/src/CONST/index.ts
@@ -2085,7 +2085,7 @@ const CONST = {
     },
     INBOX_TAB: {
         ALL: 'all',
-        TODO: 'todo',
+        UNREAD: 'unread',
         EXPENSES: 'expenses',
         DMS: 'dms',
     },
diff --git a/src/ONYXKEYS.ts b/src/ONYXKEYS.ts
index 3dce345ee6e7..b7da30c7c155 100755
--- a/src/ONYXKEYS.ts
+++ b/src/ONYXKEYS.ts
@@ -162,9 +162,6 @@ const ONYXKEYS = {
     /** Contains the user preference for the active inbox tab filter */
     NVP_INBOX_TAB: 'nvp_inboxTab',
 
-    /** Whether to show only unread chats in the inbox */
-    NVP_INBOX_UNREAD_FILTER: 'nvp_inboxUnreadFilter',
-
     /** Contains the users's block expiration (if they have one) */
     NVP_BLOCKED_FROM_CONCIERGE: 'nvp_private_blockedFromConcierge',
 
@@ -1357,7 +1354,6 @@ type OnyxValuesMapping = {
     [ONYXKEYS.BETA_CONFIGURATION]: OnyxTypes.BetaConfiguration;
     [ONYXKEYS.NVP_MUTED_PLATFORMS]: Partial<Record<Platform, true>>;
     [ONYXKEYS.NVP_INBOX_TAB]: ValueOf<typeof CONST.INBOX_TAB>;
-    [ONYXKEYS.NVP_INBOX_UNREAD_FILTER]: boolean;
     [ONYXKEYS.NVP_BLOCKED_FROM_CONCIERGE]: OnyxTypes.BlockedFromConcierge;
     [ONYXKEYS.QUEUE_FLUSHED_DATA]: AnyOnyxUpdate[];
     [ONYXKEYS.TRANSACTIONS_PENDING_3DS_REVIEW]: OnyxTypes.TransactionsPending3DSReview;
diff --git a/src/hooks/useSidebarOrderedReports.tsx b/src/hooks/useSidebarOrderedReports.tsx
index c54abee7d3b8..f0164fadc729 100644
--- a/src/hooks/useSidebarOrderedReports.tsx
+++ b/src/hooks/useSidebarOrderedReports.tsx
@@ -2,7 +2,7 @@ import {deepEqual} from 'fast-equals';
 import React, {createContext, useCallback, useContext, useEffect, useMemo, useRef, useState} from 'react';
 import type {OnyxEntry} from 'react-native-onyx';
 import type {ValueOf} from 'type-fest';
-import {setInboxTab, setInboxUnreadFilter} from '@libs/actions/User';
+import {setInboxTab} from '@libs/actions/User';
 import Log from '@libs/Log';
 import {getTransactionThreadReportID} from '@libs/MergeTransactionUtils';
 import {isOneTransactionReport} from '@libs/ReportUtils';
@@ -36,13 +36,11 @@ type SidebarOrderedReportsStateContextValue = {
     currentReportID: string | undefined;
     chatTabBrickRoad: BrickRoad;
     activeTab: ValueOf<typeof CONST.INBOX_TAB>;
-    showUnreadOnly: boolean;
 };
 
 type SidebarOrderedReportsActionsContextValue = {
     clearLHNCache: () => void;
     setActiveTab: (tab: ValueOf<typeof CONST.INBOX_TAB>) => void;
-    toggleUnreadFilter: () => void;
 };
 
 type ReportsToDisplayInLHN = Record<string, OnyxTypes.Report & {hasErrorsOtherThanFailedReceipt?: boolean; requiresAttention?: boolean}>;
@@ -53,13 +51,11 @@ const SidebarOrderedReportsStateContext = createContext<SidebarOrderedReportsSta
     currentReportID: '',
     chatTabBrickRoad: undefined,
     activeTab: CONST.INBOX_TAB.ALL,
-    showUnreadOnly: false,
 });
 
 const SidebarOrderedReportsActionsContext = createContext<SidebarOrderedReportsActionsContextValue>({
     clearLHNCache: () => {},
     setActiveTab: () => {},
-    toggleUnreadFilter: () => {},
 });
 
 const policyMapper = (policy: OnyxEntry<OnyxTypes.Policy>): PartialPolicyForSidebar =>
@@ -85,8 +81,6 @@ function SidebarOrderedReportsContextProvider({
     const {localeCompare} = useLocalize();
     const [inboxTab = CONST.INBOX_TAB.ALL] = useOnyx(ONYXKEYS.NVP_INBOX_TAB);
     const activeTab = inboxTab ?? CONST.INBOX_TAB.ALL;
-    const [inboxUnreadFilter = false] = useOnyx(ONYXKEYS.NVP_INBOX_UNREAD_FILTER);
-    const showUnreadOnly = inboxUnreadFilter ?? false;
     const [chatReports, {sourceValue: reportUpdates}] = useOnyx(ONYXKEYS.COLLECTION.REPORT);
     const [policies, {sourceValue: policiesUpdates}] = useMappedPolicies(policyMapper);
     const [transactions, {sourceValue: transactionsUpdates}] = useOnyx(ONYXKEYS.COLLECTION.TRANSACTION);
@@ -271,8 +265,8 @@ function SidebarOrderedReportsContextProvider({
     const orderedReportIDs = useMemo(() => getOrderedReportIDs(), [getOrderedReportIDs]);
 
     const filteredReportIDs = useMemo(
-        () => SidebarUtils.filterReportsForInboxTab(orderedReportIDs, reportsToDisplayInLHN, activeTab, showUnreadOnly, reportNameValuePairs),
-        [orderedReportIDs, reportsToDisplayInLHN, activeTab, showUnreadOnly, reportNameValuePairs],
+        () => SidebarUtils.filterReportsForInboxTab(orderedReportIDs, reportsToDisplayInLHN, activeTab, reportNameValuePairs),
+        [orderedReportIDs, reportsToDisplayInLHN, activeTab, reportNameValuePairs],
     );
 
     // Get the actual reports based on the filtered IDs
@@ -298,10 +292,6 @@ function SidebarOrderedReportsContextProvider({
         setInboxTab(tab);
     }, []);
 
-    const toggleUnreadFilter = useCallback(() => {
-        setInboxUnreadFilter(!showUnreadOnly);
-    }, [showUnreadOnly]);
-
     const stateValue: SidebarOrderedReportsStateContextValue = useMemo(() => {
         // We need to make sure the current report is in the list of reports, but we do not want
         // to have to re-generate the list every time the currentReportID changes. To do that
@@ -320,7 +310,7 @@ function SidebarOrderedReportsContextProvider({
             filteredReportIDs.indexOf(derivedCurrentReportID) === -1
         ) {
             const updatedReportIDs = getOrderedReportIDs();
-            const updatedFilteredIDs = SidebarUtils.filterReportsForInboxTab(updatedReportIDs, reportsToDisplayInLHN, activeTab, showUnreadOnly, reportNameValuePairs);
+            const updatedFilteredIDs = SidebarUtils.filterReportsForInboxTab(updatedReportIDs, reportsToDisplayInLHN, activeTab, reportNameValuePairs);
             const updatedReports = getOrderedReports(updatedFilteredIDs);
             return {
                 orderedReports: updatedReports,
@@ -328,7 +318,6 @@ function SidebarOrderedReportsContextProvider({
                 currentReportID: derivedCurrentReportID,
                 chatTabBrickRoad: getChatTabBrickRoad(updatedReportIDs, reportAttributes),
                 activeTab,
-                showUnreadOnly,
             };
         }
 
@@ -338,7 +327,6 @@ function SidebarOrderedReportsContextProvider({
             currentReportID: derivedCurrentReportID,
             chatTabBrickRoad: getChatTabBrickRoad(orderedReportIDs, reportAttributes),
             activeTab,
-            showUnreadOnly,
         };
     }, [
         getOrderedReportIDs,
@@ -350,12 +338,11 @@ function SidebarOrderedReportsContextProvider({
         orderedReports,
         reportAttributes,
         activeTab,
-        showUnreadOnly,
         reportsToDisplayInLHN,
         reportNameValuePairs,
     ]);
 
-    const actionsValue: SidebarOrderedReportsActionsContextValue = useMemo(() => ({clearLHNCache, setActiveTab, toggleUnreadFilter}), [clearLHNCache, setActiveTab, toggleUnreadFilter]);
+    const actionsValue: SidebarOrderedReportsActionsContextValue = useMemo(() => ({clearLHNCache, setActiveTab}), [clearLHNCache, setActiveTab]);
 
     const currentDeps = {
         activeTab,
diff --git a/src/languages/de.ts b/src/languages/de.ts
index f524383c939a..80b0180e4926 100644
--- a/src/languages/de.ts
+++ b/src/languages/de.ts
@@ -2788,10 +2788,9 @@ ${amount} für ${merchant} – ${date}`,
     },
     inboxTabs: {
         all: 'All',
-        todo: 'To-do',
+        unread: 'Unread',
         expenses: 'Expenses',
         dms: 'DMs',
-        unreadToggle: 'Unreads',
     },
     reportDetailsPage: {
         inWorkspace: (policyName: string) => `in ${policyName}`,
diff --git a/src/languages/en.ts b/src/languages/en.ts
index 65997ac79bc6..8e2103eff286 100644
--- a/src/languages/en.ts
+++ b/src/languages/en.ts
@@ -2842,10 +2842,9 @@ const translations = {
     },
     inboxTabs: {
         all: 'All',
-        todo: 'To-do',
+        unread: 'Unread',
         expenses: 'Expenses',
         dms: 'DMs',
-        unreadToggle: 'Unreads',
     },
     reportDetailsPage: {
         inWorkspace: (policyName: string) => `in ${policyName}`,
diff --git a/src/languages/es.ts b/src/languages/es.ts
index a0e6fcbbe9d2..7a8425dd7fec 100644
--- a/src/languages/es.ts
+++ b/src/languages/es.ts
@@ -2659,10 +2659,9 @@ ${amount} para ${merchant} - ${date}`,
     },
     inboxTabs: {
         all: 'All',
-        todo: 'To-do',
+        unread: 'Unread',
         expenses: 'Expenses',
         dms: 'DMs',
-        unreadToggle: 'Unreads',
     },
     reportDetailsPage: {
         inWorkspace: (policyName) => `en ${policyName}`,
diff --git a/src/languages/fr.ts b/src/languages/fr.ts
index c7eabf81d038..8633626d7080 100644
--- a/src/languages/fr.ts
+++ b/src/languages/fr.ts
@@ -2794,10 +2794,9 @@ ${amount} pour ${merchant} - ${date}`,
     },
     inboxTabs: {
         all: 'All',
-        todo: 'To-do',
+        unread: 'Unread',
         expenses: 'Expenses',
         dms: 'DMs',
-        unreadToggle: 'Unreads',
     },
     reportDetailsPage: {
         inWorkspace: (policyName: string) => `dans ${policyName}`,
diff --git a/src/languages/it.ts b/src/languages/it.ts
index b1f599039dc7..cd28d7c31dad 100644
--- a/src/languages/it.ts
+++ b/src/languages/it.ts
@@ -2783,10 +2783,9 @@ ${amount} per ${merchant} - ${date}`,
     },
     inboxTabs: {
         all: 'All',
-        todo: 'To-do',
+        unread: 'Unread',
         expenses: 'Expenses',
         dms: 'DMs',
-        unreadToggle: 'Unreads',
     },
     reportDetailsPage: {
         inWorkspace: (policyName: string) => `in ${policyName}`,
diff --git a/src/languages/ja.ts b/src/languages/ja.ts
index abf3fc73df15..0da264509b32 100644
--- a/src/languages/ja.ts
+++ b/src/languages/ja.ts
@@ -2756,10 +2756,9 @@ ${date} の ${merchant} への ${amount}`,
     },
     inboxTabs: {
         all: 'All',
-        todo: 'To-do',
+        unread: 'Unread',
         expenses: 'Expenses',
         dms: 'DMs',
-        unreadToggle: 'Unreads',
     },
     reportDetailsPage: {
         inWorkspace: (policyName: string) => `${policyName} 内`,
diff --git a/src/languages/nl.ts b/src/languages/nl.ts
index 4cc5e5d067f1..ead8c12235e4 100644
--- a/src/languages/nl.ts
+++ b/src/languages/nl.ts
@@ -2781,10 +2781,9 @@ ${amount} voor ${merchant} - ${date}`,
     },
     inboxTabs: {
         all: 'All',
-        todo: 'To-do',
+        unread: 'Unread',
         expenses: 'Expenses',
         dms: 'DMs',
-        unreadToggle: 'Unreads',
     },
     reportDetailsPage: {
         inWorkspace: (policyName: string) => `in ${policyName}`,
diff --git a/src/languages/pl.ts b/src/languages/pl.ts
index 7cc40fa1f87c..0a08aad6fd97 100644
--- a/src/languages/pl.ts
+++ b/src/languages/pl.ts
@@ -2774,10 +2774,9 @@ ${amount} dla ${merchant} - ${date}`,
     },
     inboxTabs: {
         all: 'All',
-        todo: 'To-do',
+        unread: 'Unread',
         expenses: 'Expenses',
         dms: 'DMs',
-        unreadToggle: 'Unreads',
     },
     reportDetailsPage: {
         inWorkspace: (policyName: string) => `w ${policyName}`,
diff --git a/src/languages/pt-BR.ts b/src/languages/pt-BR.ts
index 912f0c2f827d..e2b81c2f510e 100644
--- a/src/languages/pt-BR.ts
+++ b/src/languages/pt-BR.ts
@@ -2774,10 +2774,9 @@ ${amount} para ${merchant} - ${date}`,
     },
     inboxTabs: {
         all: 'All',
-        todo: 'To-do',
+        unread: 'Unread',
         expenses: 'Expenses',
         dms: 'DMs',
-        unreadToggle: 'Unreads',
     },
     reportDetailsPage: {
         inWorkspace: (policyName: string) => `em ${policyName}`,
diff --git a/src/languages/zh-hans.ts b/src/languages/zh-hans.ts
index 2eba054e6446..cfbd7bf3d21d 100644
--- a/src/languages/zh-hans.ts
+++ b/src/languages/zh-hans.ts
@@ -2706,10 +2706,9 @@ ${amount}，商户：${merchant} - 日期：${date}`,
     },
     inboxTabs: {
         all: 'All',
-        todo: 'To-do',
+        unread: 'Unread',
         expenses: 'Expenses',
         dms: 'DMs',
-        unreadToggle: 'Unreads',
     },
     reportDetailsPage: {
         inWorkspace: (policyName: string) => `在 ${policyName} 中`,
diff --git a/src/libs/SidebarUtils.ts b/src/libs/SidebarUtils.ts
index 2bec6d18432c..0cf4dd3b86aa 100644
--- a/src/libs/SidebarUtils.ts
+++ b/src/libs/SidebarUtils.ts
@@ -1412,31 +1412,23 @@ function filterReportsForInboxTab(
     reportIDs: string[],
     reportsToDisplay: ReportsToDisplayInLHN,
     activeTab: ValueOf<typeof CONST.INBOX_TAB>,
-    showUnreadOnly: boolean,
     reportNameValuePairs?: OnyxCollection<ReportNameValuePairs>,
 ): string[] {
+    if (activeTab === CONST.INBOX_TAB.ALL) {
+        return reportIDs;
+    }
+
     return reportIDs.filter((reportID) => {
         const report = reportsToDisplay[`${ONYXKEYS.COLLECTION.REPORT}${reportID}`];
         if (!report) {
             return false;
         }
 
-        // Apply unread filter when the toggle is active
-        if (showUnreadOnly) {
-            const isReportArchived = isArchivedReport(reportNameValuePairs?.[`${ONYXKEYS.COLLECTION.REPORT_NAME_VALUE_PAIRS}${reportID}`]);
-            const isReportUnread = isUnread(report, undefined, isReportArchived) && getReportNotificationPreference(report) !== CONST.REPORT.NOTIFICATION_PREFERENCE.MUTE;
-            if (!isReportUnread && !report.isPinned && !report.requiresAttention && !report.hasErrorsOtherThanFailedReceipt) {
-                return false;
-            }
-        }
-
-        if (activeTab === CONST.INBOX_TAB.ALL) {
-            return true;
-        }
-
         switch (activeTab) {
-            case CONST.INBOX_TAB.TODO:
-                return !!report.requiresAttention || !!report.hasErrorsOtherThanFailedReceipt;
+            case CONST.INBOX_TAB.UNREAD: {
+                const isReportArchived = isArchivedReport(reportNameValuePairs?.[`${ONYXKEYS.COLLECTION.REPORT_NAME_VALUE_PAIRS}${reportID}`]);
+                return isUnread(report, undefined, isReportArchived) && getReportNotificationPreference(report) !== CONST.REPORT.NOTIFICATION_PREFERENCE.MUTE;
+            }
             case CONST.INBOX_TAB.EXPENSES:
                 return isExpenseReport(report) || isIOUReport(report) || isInvoiceReport(report) || isPolicyExpenseChat(report);
             case CONST.INBOX_TAB.DMS:
diff --git a/src/libs/actions/User.ts b/src/libs/actions/User.ts
index 975dfeaafc19..138d02d821d5 100644
--- a/src/libs/actions/User.ts
+++ b/src/libs/actions/User.ts
@@ -953,10 +953,6 @@ function setInboxTab(tab: ValueOf<typeof CONST.INBOX_TAB>) {
     Onyx.merge(ONYXKEYS.NVP_INBOX_TAB, tab);
 }
 
-function setInboxUnreadFilter(enabled: boolean) {
-    Onyx.merge(ONYXKEYS.NVP_INBOX_UNREAD_FILTER, enabled);
-}
-
 function setShouldUseStagingServer(shouldUseStagingServer: boolean) {
     if (CONFIG.IS_HYBRID_APP) {
         HybridAppModule.shouldUseStaging(shouldUseStagingServer);
@@ -1882,7 +1878,6 @@ export {
     subscribeToUserEvents,
     updatePreferredSkinTone,
     setInboxTab,
-    setInboxUnreadFilter,
     setShouldUseStagingServer,
     togglePlatformMute,
     joinScreenShare,
diff --git a/src/pages/inbox/sidebar/BaseSidebarScreen.tsx b/src/pages/inbox/sidebar/BaseSidebarScreen.tsx
index 8f3bf3d553d8..fb4a748e7460 100644
--- a/src/pages/inbox/sidebar/BaseSidebarScreen.tsx
+++ b/src/pages/inbox/sidebar/BaseSidebarScreen.tsx
@@ -15,7 +15,6 @@ import {isMobile} from '@libs/Browser';
 import type {SkeletonSpanReasonAttributes} from '@libs/telemetry/useSkeletonSpan';
 import ONYXKEYS from '@src/ONYXKEYS';
 import InboxTabSelector from './InboxTabSelector';
-import InboxUnreadToggle from './InboxUnreadToggle';
 import SidebarLinksData from './SidebarLinksData';
 
 // Once the app finishes loading for the first time, we never show the skeleton again
@@ -60,9 +59,7 @@ function BaseSidebarScreen() {
                         breadcrumbLabel={translate('common.inbox')}
                         shouldDisplaySearch={shouldUseNarrowLayout}
                         shouldDisplayHelpButton={shouldUseNarrowLayout}
-                    >
-                        {!shouldShowSkeleton && <InboxUnreadToggle />}
-                    </TopBarWithLoadingBar>
+                    />
                     {!shouldShowSkeleton && <InboxTabSelector />}
                     <View style={[styles.flex1]}>
                         {shouldShowSkeleton ? (
diff --git a/src/pages/inbox/sidebar/InboxTabSelector.tsx b/src/pages/inbox/sidebar/InboxTabSelector.tsx
index 0cc87b328b3e..4de90b6aa6e5 100644
--- a/src/pages/inbox/sidebar/InboxTabSelector.tsx
+++ b/src/pages/inbox/sidebar/InboxTabSelector.tsx
@@ -13,7 +13,7 @@ function InboxTabSelector() {
 
     const tabs: TabSelectorBaseItem[] = [
         {key: CONST.INBOX_TAB.ALL, title: translate('inboxTabs.all')},
-        {key: CONST.INBOX_TAB.TODO, title: translate('inboxTabs.todo')},
+        {key: CONST.INBOX_TAB.UNREAD, title: translate('inboxTabs.unread')},
         {key: CONST.INBOX_TAB.EXPENSES, title: translate('inboxTabs.expenses')},
         {key: CONST.INBOX_TAB.DMS, title: translate('inboxTabs.dms')},
     ];
diff --git a/src/pages/inbox/sidebar/InboxUnreadToggle.tsx b/src/pages/inbox/sidebar/InboxUnreadToggle.tsx
deleted file mode 100644
index e5d38653b2a8..000000000000
--- a/src/pages/inbox/sidebar/InboxUnreadToggle.tsx
+++ /dev/null
@@ -1,30 +0,0 @@
-import React from 'react';
-import {View} from 'react-native';
-import Switch from '@components/Switch';
-import Text from '@components/Text';
-import useLocalize from '@hooks/useLocalize';
-import {useSidebarOrderedReportsActions, useSidebarOrderedReportsState} from '@hooks/useSidebarOrderedReports';
-import useThemeStyles from '@hooks/useThemeStyles';
-
-function InboxUnreadToggle() {
-    const styles = useThemeStyles();
-    const {translate} = useLocalize();
-    const {showUnreadOnly} = useSidebarOrderedReportsState();
-    const {toggleUnreadFilter} = useSidebarOrderedReportsActions();
-
-    return (
-        <View style={[styles.flexRow, styles.alignItemsCenter, styles.gap2]}>
-            <Text style={[styles.textSmall, styles.textSupporting]}>{translate('inboxTabs.unreadToggle')}</Text>
-            <Switch
-                isOn={showUnreadOnly}
-                onToggle={() => toggleUnreadFilter()}
-                accessibilityLabel={translate('inboxTabs.unreadToggle')}
-                size="small"
-            />
-        </View>
-    );
-}
-
-InboxUnreadToggle.displayName = 'InboxUnreadToggle';
-
-export default InboxUnreadToggle;

From 8b34f0890860298d826b5a758bfaf371243aafbe Mon Sep 17 00:00:00 2001
From: Rayane <77965000+rayane-d@users.noreply.github.com>
Date: Wed, 6 May 2026 19:40:59 +0100
Subject: [PATCH 013/435] Add support for category tax rate update changelog
 report action

- Introduced new constant for category tax rate updates reprt action in CONST.
- Added English copy for updated category tax rate.
- Implemented message retrieval for category tax rate changes in ReportActionsUtils.
- Updated OriginalMessage type to include new tax rate details fields for categories.
---
 src/CONST/index.ts                |  1 +
 src/languages/en.ts               | 17 +++++++++++++++++
 src/libs/ReportActionsUtils.ts    | 18 ++++++++++++++++++
 src/types/onyx/OriginalMessage.ts | 10 ++++++++--
 4 files changed, 44 insertions(+), 2 deletions(-)

diff --git a/src/CONST/index.ts b/src/CONST/index.ts
index d41a326a1db3..f9852a20e0d0 100644
--- a/src/CONST/index.ts
+++ b/src/CONST/index.ts
@@ -1566,6 +1566,7 @@ const CONST = {
                     UPDATE_AUTO_REPORTING_FREQUENCY: 'POLICYCHANGELOG_UPDATE_AUTOREPORTING_FREQUENCY',
                     UPDATE_BUDGET: 'POLICYCHANGELOG_UPDATE_BUDGET',
                     UPDATE_CATEGORY: 'POLICYCHANGELOG_UPDATE_CATEGORY',
+                    UPDATE_CATEGORY_TAX_RATE: 'POLICYCHANGELOG_UPDATE_CATEGORY_TAX_RATE',
                     UPDATE_CATEGORIES: 'POLICYCHANGELOG_UPDATE_CATEGORIES',
                     UPDATE_CURRENCY: 'POLICYCHANGELOG_UPDATE_CURRENCY',
                     UPDATE_CUSTOM_UNIT: 'POLICYCHANGELOG_UPDATE_CUSTOM_UNIT',
diff --git a/src/languages/en.ts b/src/languages/en.ts
index db0c869adeb2..1b0a09b9e6e1 100644
--- a/src/languages/en.ts
+++ b/src/languages/en.ts
@@ -7453,6 +7453,23 @@ const translations = {
         updatedAutoPayApprovedReportsLimit: ({oldLimit, newLimit}: {oldLimit: string; newLimit: string}) =>
             `changed the auto-pay approved reports threshold to "${newLimit}" (previously "${oldLimit}")`,
         removedAutoPayApprovedReportsLimit: 'removed the auto-pay approved reports threshold',
+        updatedCategoryTaxRate: ({
+            categoryName,
+            oldTaxName,
+            oldTaxPercentage,
+            newTaxName,
+            newTaxPercentage,
+        }: {
+            categoryName: string;
+            oldTaxName: string;
+            oldTaxPercentage: string;
+            newTaxName: string;
+            newTaxPercentage: string;
+        }) => {
+            const oldTax = oldTaxPercentage ? `${oldTaxName} (${oldTaxPercentage})` : oldTaxName;
+            const newTax = newTaxPercentage ? `${newTaxName} (${newTaxPercentage})` : newTaxName;
+            return `changed the "${categoryName}" category default tax rate to "${newTax}" (previously "${oldTax}")`;
+        },
         changedDefaultApprover: ({newApprover, previousApprover}: {newApprover: string; previousApprover?: string}) =>
             previousApprover ? `changed the default approver to ${newApprover} (previously ${previousApprover})` : `changed the default approver to ${newApprover}`,
         changedSubmitsToApprover: ({
diff --git a/src/libs/ReportActionsUtils.ts b/src/libs/ReportActionsUtils.ts
index feb90e8ec082..8b466073746f 100644
--- a/src/libs/ReportActionsUtils.ts
+++ b/src/libs/ReportActionsUtils.ts
@@ -3452,6 +3452,23 @@ function getAutoPayApprovedReportsEnabledMessage(translate: LocalizedTranslate,
     return translate('workspaceActions.updatedAutoPayApprovedReports', {enabled: !!enabled});
 }
 
+function getCategoryTaxRateMessage(translate: LocalizedTranslate, action: ReportAction): string {
+    const {categoryName, oldTaxName, oldTaxPercentage, newTaxName, newTaxPercentage} =
+        getOriginalMessage(action as ReportAction<typeof CONST.REPORT.ACTIONS.TYPE.POLICY_CHANGE_LOG.UPDATE_CATEGORY_TAX_RATE>) ?? {};
+
+    if (!categoryName || !newTaxName) {
+        return getReportActionText(action);
+    }
+
+    return translate('workspaceActions.updatedCategoryTaxRate', {
+        categoryName,
+        oldTaxName: oldTaxName ?? '',
+        oldTaxPercentage: oldTaxPercentage ?? '',
+        newTaxName,
+        newTaxPercentage: newTaxPercentage ?? '',
+    });
+}
+
 function getAutoReimbursementMessage(translate: LocalizedTranslate, action: ReportAction): string {
     const {oldLimit, newLimit, currency} = getOriginalMessage(action as ReportAction<typeof CONST.REPORT.ACTIONS.TYPE.POLICY_CHANGE_LOG.UPDATE_AUTO_REIMBURSEMENT>) ?? {};
 
@@ -4742,6 +4759,7 @@ export {
     getRequireCompanyCardsEnabledMessage,
     getAutoPayApprovedReportsEnabledMessage,
     getAutoReimbursementMessage,
+    getCategoryTaxRateMessage,
     formatAddressToString,
     getCompanyAddressUpdateMessage,
     getDefaultApproverUpdateMessage,
diff --git a/src/types/onyx/OriginalMessage.ts b/src/types/onyx/OriginalMessage.ts
index a399136ba2b9..69a66c9aca35 100644
--- a/src/types/onyx/OriginalMessage.ts
+++ b/src/types/onyx/OriginalMessage.ts
@@ -566,12 +566,18 @@ type OriginalMessagePolicyChangeLog = {
     /** Custom unit name */
     rateName?: string;
 
-    /** Tax percentage of the new tax rate linked to distance rate */
+    /** Tax percentage of the new tax rate linked to distance rate or category */
     newTaxPercentage?: string;
 
-    /** Tax percentage of the old tax rate linked to distance rate */
+    /** Tax percentage of the old tax rate linked to distance rate or category */
     oldTaxPercentage?: string;
 
+    /** Name of the new tax rate (without percentage) for category default tax rate */
+    newTaxName?: string;
+
+    /** Name of the old tax rate (without percentage) for category default tax rate */
+    oldTaxName?: string;
+
     /** Added/Updated tag name */
     tagName?: string;
 

From 893307f8cbbecf43f14216c5068319a3934a0f99 Mon Sep 17 00:00:00 2001
From: Rayane <77965000+rayane-d@users.noreply.github.com>
Date: Wed, 6 May 2026 19:41:52 +0100
Subject: [PATCH 014/435] Integrated `getCategoryTaxRateMessage` into various
 utility files to handle category default tax rate updates report action.

---
 src/libs/OptionsListUtils/index.ts                            | 4 ++++
 src/libs/ReportNameUtils.ts                                   | 4 ++++
 src/libs/SidebarUtils.ts                                      | 3 +++
 src/pages/inbox/report/ContextMenu/ContextMenuActions.tsx     | 3 +++
 .../inbox/report/actionContents/PolicyChangeLogContent.tsx    | 2 ++
 5 files changed, 16 insertions(+)

diff --git a/src/libs/OptionsListUtils/index.ts b/src/libs/OptionsListUtils/index.ts
index 187ebbcef864..dc9af89f1105 100644
--- a/src/libs/OptionsListUtils/index.ts
+++ b/src/libs/OptionsListUtils/index.ts
@@ -40,6 +40,7 @@ import {
     getAssignedCompanyCardMessage,
     getAutoPayApprovedReportsEnabledMessage,
     getAutoReimbursementMessage,
+    getCategoryTaxRateMessage,
     getChangedApproverActionMessage,
     getCombinedReportActions,
     getCurrencyDefaultTaxUpdateMessage,
@@ -889,6 +890,9 @@ function getLastMessageTextForReport({
     if (isActionOfType(lastReportAction, CONST.REPORT.ACTIONS.TYPE.POLICY_CHANGE_LOG.UPDATE_AUTO_REIMBURSEMENT)) {
         lastMessageTextFromReport = getAutoReimbursementMessage(translate, lastReportAction);
     }
+    if (isActionOfType(lastReportAction, CONST.REPORT.ACTIONS.TYPE.POLICY_CHANGE_LOG.UPDATE_CATEGORY_TAX_RATE)) {
+        lastMessageTextFromReport = getCategoryTaxRateMessage(translate, lastReportAction);
+    }
     if (
         isActionOfType(lastReportAction, CONST.REPORT.ACTIONS.TYPE.POLICY_CHANGE_LOG.ADD_TAX) ||
         isActionOfType(lastReportAction, CONST.REPORT.ACTIONS.TYPE.POLICY_CHANGE_LOG.DELETE_TAX) ||
diff --git a/src/libs/ReportNameUtils.ts b/src/libs/ReportNameUtils.ts
index c06e0c2ab505..f9dc494c29b2 100644
--- a/src/libs/ReportNameUtils.ts
+++ b/src/libs/ReportNameUtils.ts
@@ -38,6 +38,7 @@ import {
     getAutoPayApprovedReportsEnabledMessage,
     getAutoReimbursementMessage,
     getCardIssuedMessage,
+    getCategoryTaxRateMessage,
     getChangedApproverActionMessage,
     getCompanyAddressUpdateMessage,
     getCompanyCardConnectionBrokenMessage,
@@ -587,6 +588,9 @@ function computeReportNameBasedOnReportAction(
     if (isActionOfType(parentReportAction, CONST.REPORT.ACTIONS.TYPE.POLICY_CHANGE_LOG.UPDATE_AUTO_REIMBURSEMENT)) {
         return getAutoReimbursementMessage(translate, parentReportAction);
     }
+    if (isActionOfType(parentReportAction, CONST.REPORT.ACTIONS.TYPE.POLICY_CHANGE_LOG.UPDATE_CATEGORY_TAX_RATE)) {
+        return getCategoryTaxRateMessage(translate, parentReportAction);
+    }
     if (isActionOfType(parentReportAction, CONST.REPORT.ACTIONS.TYPE.POLICY_CHANGE_LOG.UPDATE_DEFAULT_APPROVER)) {
         return getDefaultApproverUpdateMessage(translate, parentReportAction);
     }
diff --git a/src/libs/SidebarUtils.ts b/src/libs/SidebarUtils.ts
index b4068d56f90c..3cd6e9f536db 100644
--- a/src/libs/SidebarUtils.ts
+++ b/src/libs/SidebarUtils.ts
@@ -46,6 +46,7 @@ import {
     getAutoPayApprovedReportsEnabledMessage,
     getAutoReimbursementMessage,
     getCardIssuedMessage,
+    getCategoryTaxRateMessage,
     getChangedApproverActionMessage,
     getCompanyAddressUpdateMessage,
     getCompanyCardConnectionBrokenMessage,
@@ -1083,6 +1084,8 @@ function getOptionData({
             result.alternateText = getAutoPayApprovedReportsEnabledMessage(translate, lastAction);
         } else if (lastAction?.actionName === CONST.REPORT.ACTIONS.TYPE.POLICY_CHANGE_LOG.UPDATE_AUTO_REIMBURSEMENT) {
             result.alternateText = getAutoReimbursementMessage(translate, lastAction);
+        } else if (lastAction?.actionName === CONST.REPORT.ACTIONS.TYPE.POLICY_CHANGE_LOG.UPDATE_CATEGORY_TAX_RATE) {
+            result.alternateText = getCategoryTaxRateMessage(translate, lastAction);
         } else if (lastAction?.actionName === CONST.REPORT.ACTIONS.TYPE.POLICY_CHANGE_LOG.UPDATE_DEFAULT_APPROVER) {
             result.alternateText = getDefaultApproverUpdateMessage(translate, lastAction);
         } else if (lastAction?.actionName === CONST.REPORT.ACTIONS.TYPE.POLICY_CHANGE_LOG.UPDATE_SUBMITS_TO) {
diff --git a/src/pages/inbox/report/ContextMenu/ContextMenuActions.tsx b/src/pages/inbox/report/ContextMenu/ContextMenuActions.tsx
index ca78eb8814d1..683f85c24283 100644
--- a/src/pages/inbox/report/ContextMenu/ContextMenuActions.tsx
+++ b/src/pages/inbox/report/ContextMenu/ContextMenuActions.tsx
@@ -37,6 +37,7 @@ import {
     getAutoPayApprovedReportsEnabledMessage,
     getAutoReimbursementMessage,
     getCardIssuedMessage,
+    getCategoryTaxRateMessage,
     getChangedApproverActionMessage,
     getCompanyAddressUpdateMessage,
     getCompanyCardConnectionBrokenMessage,
@@ -966,6 +967,8 @@ const ContextMenuActions: ContextMenuAction[] = [
                     Clipboard.setString(getRequireCompanyCardsEnabledMessage(translate, reportAction));
                 } else if (reportAction.actionName === CONST.REPORT.ACTIONS.TYPE.POLICY_CHANGE_LOG.UPDATE_AUTO_REIMBURSEMENT) {
                     Clipboard.setString(getAutoReimbursementMessage(translate, reportAction));
+                } else if (reportAction.actionName === CONST.REPORT.ACTIONS.TYPE.POLICY_CHANGE_LOG.UPDATE_CATEGORY_TAX_RATE) {
+                    Clipboard.setString(getCategoryTaxRateMessage(translate, reportAction));
                 } else if (reportAction.actionName === CONST.REPORT.ACTIONS.TYPE.POLICY_CHANGE_LOG.UPDATE_INVOICE_COMPANY_NAME) {
                     Clipboard.setString(getInvoiceCompanyNameUpdateMessage(translate, reportAction));
                 } else if (reportAction.actionName === CONST.REPORT.ACTIONS.TYPE.POLICY_CHANGE_LOG.UPDATE_INVOICE_COMPANY_WEBSITE) {
diff --git a/src/pages/inbox/report/actionContents/PolicyChangeLogContent.tsx b/src/pages/inbox/report/actionContents/PolicyChangeLogContent.tsx
index 63ac39058150..eaee6b9f6a37 100644
--- a/src/pages/inbox/report/actionContents/PolicyChangeLogContent.tsx
+++ b/src/pages/inbox/report/actionContents/PolicyChangeLogContent.tsx
@@ -13,6 +13,7 @@ import {
     getAssignedCompanyCardMessage,
     getAutoPayApprovedReportsEnabledMessage,
     getAutoReimbursementMessage,
+    getCategoryTaxRateMessage,
     getCompanyAddressUpdateMessage,
     getCurrencyDefaultTaxUpdateMessage,
     getCustomTaxNameUpdateMessage,
@@ -143,6 +144,7 @@ const POLICY_CHANGE_LOG_RESOLVERS: Record<string, ResolverFn> = {
     [CONST.REPORT.ACTIONS.TYPE.POLICY_CHANGE_LOG.UPDATE_FORWARDS_TO]: (translate, action) => getForwardsToUpdateMessage(translate, action),
     [CONST.REPORT.ACTIONS.TYPE.POLICY_CHANGE_LOG.UPDATE_AUTO_PAY_APPROVED_REPORTS_ENABLED]: (translate, action) => getAutoPayApprovedReportsEnabledMessage(translate, action),
     [CONST.REPORT.ACTIONS.TYPE.POLICY_CHANGE_LOG.UPDATE_AUTO_REIMBURSEMENT]: (translate, action) => getAutoReimbursementMessage(translate, action),
+    [CONST.REPORT.ACTIONS.TYPE.POLICY_CHANGE_LOG.UPDATE_CATEGORY_TAX_RATE]: (translate, action) => getCategoryTaxRateMessage(translate, action),
     [CONST.REPORT.ACTIONS.TYPE.POLICY_CHANGE_LOG.UPDATE_INVOICE_COMPANY_NAME]: (translate, action) => getInvoiceCompanyNameUpdateMessage(translate, action),
     [CONST.REPORT.ACTIONS.TYPE.POLICY_CHANGE_LOG.UPDATE_INVOICE_COMPANY_WEBSITE]: (translate, action) => getInvoiceCompanyWebsiteUpdateMessage(translate, action),
     [CONST.REPORT.ACTIONS.TYPE.POLICY_CHANGE_LOG.UPDATE_REIMBURSER]: (translate, action) => getReimburserUpdateMessage(translate, action),

From 85ae38eb07a79ff0da554895eb4a45b79b7ca6a8 Mon Sep 17 00:00:00 2001
From: Rayane <77965000+rayane-d@users.noreply.github.com>
Date: Wed, 6 May 2026 19:42:54 +0100
Subject: [PATCH 015/435] Add unit tests for `getCategoryTaxRateMessage` in
 ReportActionsUtilsTest

---
 tests/unit/ReportActionsUtilsTest.ts | 41 ++++++++++++++++++++++++++++
 1 file changed, 41 insertions(+)

diff --git a/tests/unit/ReportActionsUtilsTest.ts b/tests/unit/ReportActionsUtilsTest.ts
index 3ee7c18782f8..1d1fd08f445c 100644
--- a/tests/unit/ReportActionsUtilsTest.ts
+++ b/tests/unit/ReportActionsUtilsTest.ts
@@ -18,6 +18,7 @@ import {
     getAutoPayApprovedReportsEnabledMessage,
     getAutoReimbursementMessage,
     getCardIssuedMessage,
+    getCategoryTaxRateMessage,
     getCompanyAddressUpdateMessage,
     getCreatedReportForUnapprovedTransactionsMessage,
     getCurrencyDefaultTaxUpdateMessage,
@@ -4418,6 +4419,46 @@ describe('ReportActionsUtils', () => {
         });
     });
 
+    describe('getCategoryTaxRateMessage', () => {
+        it('should render the changed-tax-rate message with both name and percentage on each side', () => {
+            const action = {
+                actionName: CONST.REPORT.ACTIONS.TYPE.POLICY_CHANGE_LOG.UPDATE_CATEGORY_TAX_RATE,
+                reportActionID: '1',
+                created: '',
+                originalMessage: {
+                    categoryName: 'Office Supplies',
+                    oldTaxName: 'Tax Exempt',
+                    oldTaxPercentage: '0%',
+                    newTaxName: 'Tax Rate 1',
+                    newTaxPercentage: '5%',
+                },
+                message: [],
+            } as ReportAction;
+
+            const result = getCategoryTaxRateMessage(translateLocal, action);
+            expect(result).toBe('changed the "Office Supplies" category default tax rate to "Tax Rate 1 (5%)" (previously "Tax Exempt (0%)")');
+        });
+
+        it('should drop the parens on the side with an empty percentage (e.g. previous tax was deleted)', () => {
+            const action = {
+                actionName: CONST.REPORT.ACTIONS.TYPE.POLICY_CHANGE_LOG.UPDATE_CATEGORY_TAX_RATE,
+                reportActionID: '1',
+                created: '',
+                originalMessage: {
+                    categoryName: 'Office Supplies',
+                    oldTaxName: 'Deleted Tax Rate',
+                    oldTaxPercentage: '',
+                    newTaxName: 'Tax Rate 1',
+                    newTaxPercentage: '5%',
+                },
+                message: [],
+            } as ReportAction;
+
+            const result = getCategoryTaxRateMessage(translateLocal, action);
+            expect(result).toBe('changed the "Office Supplies" category default tax rate to "Tax Rate 1 (5%)" (previously "Deleted Tax Rate")');
+        });
+    });
+
     describe('isNewerReportAction', () => {
         const makeAction = (overrides: Partial<ReportAction>): ReportAction =>
             ({

From fb32fe45c015f7ec38e32b27e97aeca0f1b5a20e Mon Sep 17 00:00:00 2001
From: Rayane <77965000+rayane-d@users.noreply.github.com>
Date: Wed, 6 May 2026 19:43:18 +0100
Subject: [PATCH 016/435] Add unit tests for handling
 `UPDATE_CATEGORY_TAX_RATE` action in OptionsListUtils, ReportNameUtils, and
 SidebarUtils. Ensure correct rendering of the message.

---
 tests/unit/OptionsListUtilsTest.tsx | 32 ++++++++++++++++++++
 tests/unit/ReportNameUtilsTest.ts   | 40 +++++++++++++++++++++++++
 tests/unit/SidebarUtilsTest.ts      | 46 +++++++++++++++++++++++++++++
 3 files changed, 118 insertions(+)

diff --git a/tests/unit/OptionsListUtilsTest.tsx b/tests/unit/OptionsListUtilsTest.tsx
index 7a8f6c339cb2..8bbf69453acd 100644
--- a/tests/unit/OptionsListUtilsTest.tsx
+++ b/tests/unit/OptionsListUtilsTest.tsx
@@ -4907,6 +4907,38 @@ describe('OptionsListUtils', () => {
                 );
             });
         });
+        describe('UPDATE_CATEGORY_TAX_RATE action', () => {
+            it('should surface the rendered category default tax rate change in the last-message preview', async () => {
+                const report: Report = createRandomReport(0, undefined);
+                const changelogAction: ReportAction = {
+                    ...createRandomReportAction(1),
+                    actionName: CONST.REPORT.ACTIONS.TYPE.POLICY_CHANGE_LOG.UPDATE_CATEGORY_TAX_RATE,
+                    message: [{type: 'COMMENT', text: ''}],
+                    originalMessage: {
+                        categoryName: 'Office Supplies',
+                        oldTaxName: 'Tax Exempt',
+                        oldTaxPercentage: '0%',
+                        newTaxName: 'Tax Rate 1',
+                        newTaxPercentage: '5%',
+                    },
+                };
+                await Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${report.reportID}`, {
+                    [changelogAction.reportActionID]: changelogAction,
+                });
+
+                const lastMessage = getLastMessageTextForReport({
+                    translate: translateLocal,
+                    report,
+                    lastActorDetails: null,
+                    policy: undefined,
+                    isReportArchived: false,
+
+                    currentUserLogin: CURRENT_USER_EMAIL,
+                });
+
+                expect(lastMessage).toBe('changed the "Office Supplies" category default tax rate to "Tax Rate 1 (5%)" (previously "Tax Exempt (0%)")');
+            });
+        });
     });
 
     describe('getPersonalDetailSearchTerms', () => {
diff --git a/tests/unit/ReportNameUtilsTest.ts b/tests/unit/ReportNameUtilsTest.ts
index 9c18e5886707..1dce8a6ffd14 100644
--- a/tests/unit/ReportNameUtilsTest.ts
+++ b/tests/unit/ReportNameUtilsTest.ts
@@ -648,6 +648,46 @@ describe('ReportNameUtils', () => {
             expect(disabledName).toBe('disabled the company card purchases requirement');
         });
 
+        test('UPDATE_CATEGORY_TAX_RATE parent action renders the rendered category default tax rate change', () => {
+            const thread: Report = createWorkspaceThread(160);
+            const parentAction: ReportAction = {
+                actionName: CONST.REPORT.ACTIONS.TYPE.POLICY_CHANGE_LOG.UPDATE_CATEGORY_TAX_RATE,
+                reportActionID: String(thread.parentReportActionID),
+                message: [],
+                created: '',
+                lastModified: '',
+                actorAccountID: 1,
+                person: [],
+                originalMessage: {
+                    categoryName: 'Office Supplies',
+                    oldTaxName: 'Tax Exempt',
+                    oldTaxPercentage: '0%',
+                    newTaxName: 'Tax Rate 1',
+                    newTaxPercentage: '5%',
+                },
+            } as unknown as ReportAction;
+
+            const parentId = String(thread.parentReportID);
+            const actionId = String(thread.parentReportActionID);
+            const reportActionsCollection: Record<string, ReportActions> = {
+                [`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${parentId}`]: {
+                    [actionId]: parentAction,
+                },
+            };
+
+            const name = computeReportName(
+                thread,
+                emptyCollections.reports,
+                emptyCollections.policies,
+                undefined,
+                undefined,
+                participantsPersonalDetails,
+                reportActionsCollection,
+                currentUserAccountID,
+            );
+            expect(name).toBe('changed the "Office Supplies" category default tax rate to "Tax Rate 1 (5%)" (previously "Tax Exempt (0%)")');
+        });
+
         test('DELETE_CARD_FEED parent action', () => {
             const thread: Report = createWorkspaceThread(101);
             const parentAction: ReportAction = {
diff --git a/tests/unit/SidebarUtilsTest.ts b/tests/unit/SidebarUtilsTest.ts
index 5d35405fd867..bee3e84de8b6 100644
--- a/tests/unit/SidebarUtilsTest.ts
+++ b/tests/unit/SidebarUtilsTest.ts
@@ -1873,6 +1873,52 @@ describe('SidebarUtils', () => {
             expect(result?.alternateText).toBe('changed the foreign currency default tax rate to "Foreign Tax (10%)" (previously "Foreign Tax (15%)")');
         });
 
+        it('returns the correct alternate text for UPDATE_CATEGORY_TAX_RATE action', async () => {
+            const report: Report = {
+                ...createRandomReport(4, 'policyAdmins'),
+                participants: {'18921695': {notificationPreference: 'always'}},
+            };
+            const lastAction: ReportAction = {
+                ...createRandomReportAction(2),
+                actionName: CONST.REPORT.ACTIONS.TYPE.POLICY_CHANGE_LOG.UPDATE_CATEGORY_TAX_RATE,
+                originalMessage: {
+                    categoryName: 'Office Supplies',
+                    oldTaxName: 'Tax Exempt',
+                    oldTaxPercentage: '0%',
+                    newTaxName: 'Tax Rate 1',
+                    newTaxPercentage: '5%',
+                },
+            };
+            const reportActions: ReportActions = {[lastAction.reportActionID]: lastAction};
+            await act(async () => {
+                await Onyx.set(`${ONYXKEYS.COLLECTION.REPORT}${report.reportID}`, report);
+                await Onyx.set(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${report.reportID}`, reportActions);
+            });
+
+            const result = SidebarUtils.getOptionData({
+                report,
+                reportAttributes: undefined,
+                reportNameValuePairs: {},
+                personalDetails: {},
+                policy: undefined,
+                invoiceReceiverPolicy: undefined,
+                parentReportAction: undefined,
+                conciergeReportID: '',
+                oneTransactionThreadReport: undefined,
+                card: undefined,
+                translate: translateLocal,
+                localeCompare,
+                lastAction,
+                lastActionReport: undefined,
+                isReportArchived: undefined,
+                currentUserAccountID: 0,
+                currentUserLogin: CURRENT_USER_LOGIN,
+                reportAttributesDerived: undefined,
+            });
+
+            expect(result?.alternateText).toBe('changed the "Office Supplies" category default tax rate to "Tax Rate 1 (5%)" (previously "Tax Exempt (0%)")');
+        });
+
         it('returns the correct alternate text for UPDATE_REQUIRE_COMPANY_CARDS_ENABLED action', async () => {
             const report: Report = {
                 ...createRandomReport(4, 'policyAdmins'),

From 0f3a701844bd15b8af3952f0ac6cd92016a9edae Mon Sep 17 00:00:00 2001
From: Rayane <77965000+rayane-d@users.noreply.github.com>
Date: Thu, 7 May 2026 00:33:16 +0100
Subject: [PATCH 017/435] add Spanish translation

---
 src/languages/es.ts | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)

diff --git a/src/languages/es.ts b/src/languages/es.ts
index 5cf243f95099..d12045065ac9 100644
--- a/src/languages/es.ts
+++ b/src/languages/es.ts
@@ -7327,6 +7327,23 @@ ${amount} para ${merchant} - ${date}`,
         updatedAutoPayApprovedReportsLimit: ({oldLimit, newLimit}: {oldLimit: string; newLimit: string}) =>
             `cambió el umbral de autopago de informes aprobados a "${newLimit}" (previamente "${oldLimit}")`,
         removedAutoPayApprovedReportsLimit: 'eliminó el umbral de autopago de informes aprobados',
+        updatedCategoryTaxRate: ({
+            categoryName,
+            oldTaxName,
+            oldTaxPercentage,
+            newTaxName,
+            newTaxPercentage,
+        }: {
+            categoryName: string;
+            oldTaxName: string;
+            oldTaxPercentage: string;
+            newTaxName: string;
+            newTaxPercentage: string;
+        }) => {
+            const oldTax = oldTaxPercentage ? `${oldTaxName} (${oldTaxPercentage})` : oldTaxName;
+            const newTax = newTaxPercentage ? `${newTaxName} (${newTaxPercentage})` : newTaxName;
+            return `actualizó la tasa de impuesto predeterminada de la categoría "${categoryName}" a "${newTax}" (previamente "${oldTax}")`;
+        },
         changedDefaultApprover: ({newApprover, previousApprover}: {newApprover: string; previousApprover?: string}) =>
             previousApprover ? `cambió el aprobador predeterminado a ${newApprover} (anteriormente ${previousApprover})` : `cambió el aprobador predeterminado a ${newApprover}`,
         changedSubmitsToApprover: ({

From 87aed17ec3706673e852adf5c92de41278b3a3ef Mon Sep 17 00:00:00 2001
From: Rayane <77965000+rayane-d@users.noreply.github.com>
Date: Thu, 7 May 2026 00:36:58 +0100
Subject: [PATCH 018/435] Refactor category tax rate update messages
 translations, simplified parameter structure in translation functions

---
 src/languages/en.ts            | 16 +---------------
 src/languages/es.ts            | 19 ++-----------------
 src/libs/ReportActionsUtils.ts |  9 +++++----
 3 files changed, 8 insertions(+), 36 deletions(-)

diff --git a/src/languages/en.ts b/src/languages/en.ts
index 1b0a09b9e6e1..a03f19dc7822 100644
--- a/src/languages/en.ts
+++ b/src/languages/en.ts
@@ -7453,21 +7453,7 @@ const translations = {
         updatedAutoPayApprovedReportsLimit: ({oldLimit, newLimit}: {oldLimit: string; newLimit: string}) =>
             `changed the auto-pay approved reports threshold to "${newLimit}" (previously "${oldLimit}")`,
         removedAutoPayApprovedReportsLimit: 'removed the auto-pay approved reports threshold',
-        updatedCategoryTaxRate: ({
-            categoryName,
-            oldTaxName,
-            oldTaxPercentage,
-            newTaxName,
-            newTaxPercentage,
-        }: {
-            categoryName: string;
-            oldTaxName: string;
-            oldTaxPercentage: string;
-            newTaxName: string;
-            newTaxPercentage: string;
-        }) => {
-            const oldTax = oldTaxPercentage ? `${oldTaxName} (${oldTaxPercentage})` : oldTaxName;
-            const newTax = newTaxPercentage ? `${newTaxName} (${newTaxPercentage})` : newTaxName;
+        updatedCategoryTaxRate: ({categoryName, oldTax, newTax}: {categoryName: string; oldTax: string; newTax: string}) => {
             return `changed the "${categoryName}" category default tax rate to "${newTax}" (previously "${oldTax}")`;
         },
         changedDefaultApprover: ({newApprover, previousApprover}: {newApprover: string; previousApprover?: string}) =>
diff --git a/src/languages/es.ts b/src/languages/es.ts
index d12045065ac9..2d48e2671382 100644
--- a/src/languages/es.ts
+++ b/src/languages/es.ts
@@ -7327,23 +7327,8 @@ ${amount} para ${merchant} - ${date}`,
         updatedAutoPayApprovedReportsLimit: ({oldLimit, newLimit}: {oldLimit: string; newLimit: string}) =>
             `cambió el umbral de autopago de informes aprobados a "${newLimit}" (previamente "${oldLimit}")`,
         removedAutoPayApprovedReportsLimit: 'eliminó el umbral de autopago de informes aprobados',
-        updatedCategoryTaxRate: ({
-            categoryName,
-            oldTaxName,
-            oldTaxPercentage,
-            newTaxName,
-            newTaxPercentage,
-        }: {
-            categoryName: string;
-            oldTaxName: string;
-            oldTaxPercentage: string;
-            newTaxName: string;
-            newTaxPercentage: string;
-        }) => {
-            const oldTax = oldTaxPercentage ? `${oldTaxName} (${oldTaxPercentage})` : oldTaxName;
-            const newTax = newTaxPercentage ? `${newTaxName} (${newTaxPercentage})` : newTaxName;
-            return `actualizó la tasa de impuesto predeterminada de la categoría "${categoryName}" a "${newTax}" (previamente "${oldTax}")`;
-        },
+        updatedCategoryTaxRate: ({categoryName, oldTax, newTax}: {categoryName: string; oldTax: string; newTax: string}) =>
+            `actualizó la tasa de impuesto predeterminada de la categoría "${categoryName}" a "${newTax}" (previamente "${oldTax}")`,
         changedDefaultApprover: ({newApprover, previousApprover}: {newApprover: string; previousApprover?: string}) =>
             previousApprover ? `cambió el aprobador predeterminado a ${newApprover} (anteriormente ${previousApprover})` : `cambió el aprobador predeterminado a ${newApprover}`,
         changedSubmitsToApprover: ({
diff --git a/src/libs/ReportActionsUtils.ts b/src/libs/ReportActionsUtils.ts
index 8b466073746f..317827dcedf9 100644
--- a/src/libs/ReportActionsUtils.ts
+++ b/src/libs/ReportActionsUtils.ts
@@ -3460,12 +3460,13 @@ function getCategoryTaxRateMessage(translate: LocalizedTranslate, action: Report
         return getReportActionText(action);
     }
 
+    const oldTax = oldTaxPercentage ? `${oldTaxName} (${oldTaxPercentage})` : (oldTaxName ?? '');
+    const newTax = newTaxPercentage ? `${newTaxName} (${newTaxPercentage})` : newTaxName;
+
     return translate('workspaceActions.updatedCategoryTaxRate', {
         categoryName,
-        oldTaxName: oldTaxName ?? '',
-        oldTaxPercentage: oldTaxPercentage ?? '',
-        newTaxName,
-        newTaxPercentage: newTaxPercentage ?? '',
+        oldTax,
+        newTax,
     });
 }
 

From 96ebfa29c96353c61193e128bb73e8e3a0473bba Mon Sep 17 00:00:00 2001
From: "truph01 (via MelvinBot)" <infra+melvinbot@expensify.com>
Date: Thu, 14 May 2026 06:31:42 +0000
Subject: [PATCH 019/435] Patch react-native-draggable-flatlist to unblock iOS
 autoscroll feedback loop

On iOS, scrollToOffset({animated: true}) does not emit intermediate onScroll
events, so the scrollOffset shared value never updates mid-scroll. This blocks
the autoscroll feedback loop in useAutoScroll (hasScrolledToTarget stays false),
preventing drag-to-reorder from scrolling beyond the visible viewport.

The fix manually advances scrollOffset after each scrollToOffset call, keeping
the animated scroll for smooth visuals while unblocking the next loop iteration.

Co-authored-by: truph01 <truph01@users.noreply.github.com>
---
 patches/react-native-draggable-flatlist/details.md  |  8 ++++++++
 ...list+4.0.3+003+fix-ios-autoscroll-feedback.patch | 13 +++++++++++++
 2 files changed, 21 insertions(+)
 create mode 100644 patches/react-native-draggable-flatlist/react-native-draggable-flatlist+4.0.3+003+fix-ios-autoscroll-feedback.patch

diff --git a/patches/react-native-draggable-flatlist/details.md b/patches/react-native-draggable-flatlist/details.md
index 8afd4dc971c9..c12b0dffcbf6 100644
--- a/patches/react-native-draggable-flatlist/details.md
+++ b/patches/react-native-draggable-flatlist/details.md
@@ -14,3 +14,11 @@
 - Upstream PR/issue: https://github.com/computerjazz/react-native-draggable-flatlist/pull/544
 - E/App issue: 🛑
 - PR Introducing Patch: [#55066](https://github.com/Expensify/App/pull/55066)
+
+
+### [react-native-draggable-flatlist+4.0.3+003+fix-ios-autoscroll-feedback.patch](react-native-draggable-flatlist+4.0.3+003+fix-ios-autoscroll-feedback.patch)
+
+- Reason: On iOS, `scrollToOffset({animated: true})` does not emit intermediate `onScroll` events, so the `scrollOffset` shared value never updates mid-scroll. This blocks the autoscroll feedback loop (`hasScrolledToTarget` stays false), preventing waypoint reordering beyond the visible viewport. The fix manually advances `scrollOffset` after each `scrollToOffset` call to keep the loop alive.
+- Upstream PR/issue: https://github.com/computerjazz/react-native-draggable-flatlist/issues/509
+- E/App issue: [#87362](https://github.com/Expensify/App/issues/87362)
+- PR Introducing Patch: 🛑
diff --git a/patches/react-native-draggable-flatlist/react-native-draggable-flatlist+4.0.3+003+fix-ios-autoscroll-feedback.patch b/patches/react-native-draggable-flatlist/react-native-draggable-flatlist+4.0.3+003+fix-ios-autoscroll-feedback.patch
new file mode 100644
index 000000000000..4e331c5b7383
--- /dev/null
+++ b/patches/react-native-draggable-flatlist/react-native-draggable-flatlist+4.0.3+003+fix-ios-autoscroll-feedback.patch
@@ -0,0 +1,13 @@
+diff --git a/node_modules/react-native-draggable-flatlist/src/hooks/useAutoScroll.tsx b/node_modules/react-native-draggable-flatlist/src/hooks/useAutoScroll.tsx
+index 4e30bca..b1a2f3e 100644
+--- a/node_modules/react-native-draggable-flatlist/src/hooks/useAutoScroll.tsx
++++ b/node_modules/react-native-draggable-flatlist/src/hooks/useAutoScroll.tsx
+@@ -89,6 +89,8 @@ export function useAutoScroll() {
+   function scrollToInternal(offset: number) {
+     if (flatlistRef && "current" in flatlistRef) {
+       flatlistRef.current?.scrollToOffset({ offset, animated: true });
++      // Manually advance scrollOffset so the autoscroll feedback loop is not blocked on iOS.
++      scrollOffset.value = offset;
+     }
+   }
+

From 8d509c5946889ba73c4087c6cdafd5b5e4ceac1d Mon Sep 17 00:00:00 2001
From: krishna2323 <belivethatkg@gmail.com>
Date: Mon, 18 May 2026 01:39:13 +0530
Subject: [PATCH 020/435] feat: replace distance rates list with Table UI
 behind beta gate

Signed-off-by: krishna2323 <belivethatkg@gmail.com>
---
 src/CONST/index.ts                            |   6 +
 .../WorkspaceDistanceRatesTableRow.tsx        | 155 ++++++++++++
 .../WorkspaceDistanceRatesTable/index.tsx     | 225 ++++++++++++++++++
 src/languages/en.ts                           |   4 +
 src/libs/PolicyDistanceRatesUtils.ts          |  17 +-
 .../distanceRates/PolicyDistanceRatesPage.tsx | 111 ++++++---
 6 files changed, 489 insertions(+), 29 deletions(-)
 create mode 100644 src/components/Tables/WorkspaceDistanceRatesTable/WorkspaceDistanceRatesTableRow.tsx
 create mode 100644 src/components/Tables/WorkspaceDistanceRatesTable/index.tsx

diff --git a/src/CONST/index.ts b/src/CONST/index.ts
index 2d7249f0852e..af4c515bb721 100644
--- a/src/CONST/index.ts
+++ b/src/CONST/index.ts
@@ -4015,6 +4015,12 @@ const CONST = {
         FAKE_P2P_ID: '_FAKE_P2P_ID_',
         MILES_TO_KILOMETERS: 1.609344,
         KILOMETERS_TO_MILES: 0.621371,
+        RATE_STATUS: {
+            ACTIVE: 'active',
+            FUTURE: 'future',
+            EXPIRED: 'expired',
+            INACTIVE: 'inactive',
+        },
     },
 
     TERMS: {
diff --git a/src/components/Tables/WorkspaceDistanceRatesTable/WorkspaceDistanceRatesTableRow.tsx b/src/components/Tables/WorkspaceDistanceRatesTable/WorkspaceDistanceRatesTableRow.tsx
new file mode 100644
index 000000000000..505ece8ef54a
--- /dev/null
+++ b/src/components/Tables/WorkspaceDistanceRatesTable/WorkspaceDistanceRatesTableRow.tsx
@@ -0,0 +1,155 @@
+import {format, parseISO} from 'date-fns';
+import React from 'react';
+import {View} from 'react-native';
+import Checkbox from '@components/Checkbox';
+import Icon from '@components/Icon';
+import Table from '@components/Table';
+import Text from '@components/Text';
+import TextWithTooltip from '@components/TextWithTooltip';
+import {useMemoizedLazyExpensifyIcons} from '@hooks/useLazyAsset';
+import useTheme from '@hooks/useTheme';
+import useThemeStyles from '@hooks/useThemeStyles';
+import {getRateStatus} from '@libs/PolicyDistanceRatesUtils';
+import type {SkeletonSpanReasonAttributes} from '@libs/telemetry/useSkeletonSpan';
+import variables from '@styles/variables';
+import CONST from '@src/CONST';
+import type * as OnyxCommon from '@src/types/onyx/OnyxCommon';
+import type {Rate} from '@src/types/onyx/Policy';
+
+type DistanceRateTableItemData = {
+    rateID: string;
+    rate: Rate;
+    formattedRate: string;
+    pendingAction?: OnyxCommon.PendingAction;
+    errors?: OnyxCommon.Errors;
+    onDismissError?: () => void;
+};
+
+type WorkspaceDistanceRatesTableRowProps = {
+    item: DistanceRateTableItemData;
+    rowIndex: number;
+    isSelected: boolean;
+    canSelectMultiple: boolean;
+    onToggle: () => void;
+    onPress: () => void;
+    shouldUseNarrowTableLayout: boolean;
+    statusLabels: Record<string, string>;
+};
+
+function formatDateColumn(dateString: string | undefined): string {
+    if (!dateString) {
+        return '';
+    }
+    return format(parseISO(dateString), CONST.DATE.MONTH_DAY_YEAR_FORMAT);
+}
+
+function WorkspaceDistanceRatesTableRow({item, rowIndex, isSelected, canSelectMultiple, onToggle, onPress, shouldUseNarrowTableLayout, statusLabels}: WorkspaceDistanceRatesTableRowProps) {
+    const theme = useTheme();
+    const styles = useThemeStyles();
+    const Expensicons = useMemoizedLazyExpensifyIcons(['ArrowRight']);
+
+    const {rate, formattedRate, pendingAction, errors, onDismissError} = item;
+    const isDeleting = pendingAction === CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE;
+
+    const status = getRateStatus(rate);
+
+    const reasonAttributes: SkeletonSpanReasonAttributes = {
+        context: 'WorkspaceDistanceRatesTableItem',
+        isDeleting,
+    };
+
+    return (
+        <Table.Row
+            interactive
+            rowIndex={rowIndex}
+            disabled={isDeleting}
+            skeletonReasonAttributes={reasonAttributes}
+            sentryLabel={CONST.SENTRY_LABEL.WORKSPACE.DISTANCE_RATES.ADD_BUTTON}
+            offlineWithFeedback={{errors, pendingAction, onClose: onDismissError, shouldHideOnDelete: false}}
+            onPress={onPress}
+        >
+            {({hovered}) => (
+                <>
+                    {canSelectMultiple && (
+                        <View style={[styles.mr3]}>
+                            <Checkbox
+                                isChecked={isSelected}
+                                onPress={onToggle}
+                                accessibilityLabel={rate.name ?? ''}
+                                disabled={isDeleting}
+                            />
+                        </View>
+                    )}
+
+                    <View style={[styles.flex1]}>
+                        <TextWithTooltip
+                            text={statusLabels[status] ?? ''}
+                            style={[styles.optionDisplayName, styles.pre]}
+                        />
+                        {shouldUseNarrowTableLayout && (
+                            <TextWithTooltip
+                                text={`${rate.name ?? ''} · ${formattedRate}`}
+                                style={[styles.textLabelSupporting, styles.lh16, styles.pre]}
+                            />
+                        )}
+                    </View>
+
+                    {!shouldUseNarrowTableLayout && (
+                        <View style={[styles.flex1]}>
+                            <Text
+                                numberOfLines={1}
+                                style={[styles.lh16, styles.optionDisplayName, styles.pre]}
+                            >
+                                {rate.name}
+                            </Text>
+                        </View>
+                    )}
+
+                    {!shouldUseNarrowTableLayout && (
+                        <View style={[styles.flex1]}>
+                            <Text
+                                numberOfLines={1}
+                                style={[styles.lh16, styles.optionDisplayName, styles.pre]}
+                            >
+                                {formattedRate}
+                            </Text>
+                        </View>
+                    )}
+
+                    {!shouldUseNarrowTableLayout && (
+                        <View style={[styles.flex1]}>
+                            <Text
+                                numberOfLines={1}
+                                style={[styles.lh16, styles.optionDisplayName, styles.pre]}
+                            >
+                                {formatDateColumn(rate.startDate)}
+                            </Text>
+                        </View>
+                    )}
+
+                    {!shouldUseNarrowTableLayout && (
+                        <View style={[styles.flex1]}>
+                            <Text
+                                numberOfLines={1}
+                                style={[styles.lh16, styles.optionDisplayName, styles.pre]}
+                            >
+                                {formatDateColumn(rate.endDate)}
+                            </Text>
+                        </View>
+                    )}
+
+                    <Icon
+                        src={Expensicons.ArrowRight}
+                        fill={theme.icon}
+                        additionalStyles={[styles.alignSelfCenter, !hovered && styles.opacitySemiTransparent]}
+                        width={variables.iconSizeNormal}
+                        height={variables.iconSizeNormal}
+                    />
+                </>
+            )}
+        </Table.Row>
+    );
+}
+
+export default WorkspaceDistanceRatesTableRow;
+export type {DistanceRateTableItemData};
diff --git a/src/components/Tables/WorkspaceDistanceRatesTable/index.tsx b/src/components/Tables/WorkspaceDistanceRatesTable/index.tsx
new file mode 100644
index 000000000000..d959cdbd1104
--- /dev/null
+++ b/src/components/Tables/WorkspaceDistanceRatesTable/index.tsx
@@ -0,0 +1,225 @@
+import type {ListRenderItemInfo} from '@shopify/flash-list';
+import React, {useEffect, useMemo, useRef, useState} from 'react';
+import {View} from 'react-native';
+import Checkbox from '@components/Checkbox';
+import Table from '@components/Table';
+import type {ActiveSorting, CompareItemsCallback, IsItemInSearchCallback, TableColumn, TableHandle} from '@components/Table';
+import useBottomSafeSafeAreaPaddingStyle from '@hooks/useBottomSafeSafeAreaPaddingStyle';
+import useLocalize from '@hooks/useLocalize';
+import useResponsiveLayout from '@hooks/useResponsiveLayout';
+import useThemeStyles from '@hooks/useThemeStyles';
+import {convertAmountToDisplayString} from '@libs/CurrencyUtils';
+import {getRateStatus} from '@libs/PolicyDistanceRatesUtils';
+import tokenizedSearch from '@libs/tokenizedSearch';
+import CONST from '@src/CONST';
+import type * as OnyxCommon from '@src/types/onyx/OnyxCommon';
+import type {Rate} from '@src/types/onyx/Policy';
+import WorkspaceDistanceRatesTableRow from './WorkspaceDistanceRatesTableRow';
+import type {DistanceRateTableItemData} from './WorkspaceDistanceRatesTableRow';
+
+type DistanceRatesTableColumnKey = 'status' | 'name' | 'rate' | 'startDate' | 'endDate';
+
+type WorkspaceDistanceRatesTableProps = {
+    customUnitRates: Record<string, Rate>;
+    unitTranslation: string;
+    selectedDistanceRates: string[];
+    canSelectMultiple: boolean;
+    onToggleRate: (rateID: string) => void;
+    onToggleAllRates: () => void;
+    onPressRate: (rateID: string) => void;
+    onDismissError: (rateID: string) => void;
+    pendingAction?: OnyxCommon.PendingAction;
+    pendingFields?: OnyxCommon.PendingFields<string>;
+};
+
+const STATUS_ORDER: Record<string, number> = {
+    [CONST.CUSTOM_UNITS.RATE_STATUS.ACTIVE]: 0,
+    [CONST.CUSTOM_UNITS.RATE_STATUS.FUTURE]: 1,
+    [CONST.CUSTOM_UNITS.RATE_STATUS.EXPIRED]: 2,
+    [CONST.CUSTOM_UNITS.RATE_STATUS.INACTIVE]: 3,
+};
+
+function WorkspaceDistanceRatesTable({
+    customUnitRates,
+    unitTranslation,
+    selectedDistanceRates,
+    canSelectMultiple,
+    onToggleRate,
+    onToggleAllRates,
+    onPressRate,
+    onDismissError,
+    pendingAction,
+    pendingFields,
+}: WorkspaceDistanceRatesTableProps) {
+    const styles = useThemeStyles();
+    const {translate, localeCompare} = useLocalize();
+    const {shouldUseNarrowLayout, isMediumScreenWidth} = useResponsiveLayout();
+    const shouldUseNarrowTableLayout = shouldUseNarrowLayout || isMediumScreenWidth;
+
+    const tableRef = useRef<TableHandle<DistanceRateTableItemData, DistanceRatesTableColumnKey>>(null);
+
+    const columns: Array<TableColumn<DistanceRatesTableColumnKey>> = [
+        {key: 'status', label: translate('workspace.distanceRates.status')},
+        {key: 'name', label: translate('common.name')},
+        {key: 'rate', label: translate('workspace.distanceRates.rate')},
+        {key: 'startDate', label: translate('workspace.distanceRates.startDate')},
+        {key: 'endDate', label: translate('workspace.distanceRates.endDate')},
+    ];
+
+    const ratesData: DistanceRateTableItemData[] = Object.values(customUnitRates).map((rate) => {
+        const resolvedPendingAction =
+            rate.pendingAction ??
+            rate.pendingFields?.rate ??
+            rate.pendingFields?.enabled ??
+            rate.pendingFields?.currency ??
+            rate.pendingFields?.name ??
+            pendingFields?.attributes ??
+            (pendingAction === CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD ? pendingAction : undefined);
+
+        return {
+            rateID: rate.customUnitRateID,
+            rate,
+            formattedRate: `${convertAmountToDisplayString(rate.rate, rate.currency ?? CONST.CURRENCY.USD)} / ${unitTranslation}`,
+            pendingAction: resolvedPendingAction ?? undefined,
+            errors: rate.errors ?? undefined,
+            onDismissError: () => onDismissError(rate.customUnitRateID),
+        };
+    });
+
+    const keyExtractor = (item: DistanceRateTableItemData) => item.rateID;
+
+    const tableBodyContentContainerStyle = useBottomSafeSafeAreaPaddingStyle({
+        addBottomSafeAreaPadding: true,
+        addOfflineIndicatorBottomSafeAreaPadding: true,
+        style: styles.pb4,
+    });
+
+    const compareItems: CompareItemsCallback<DistanceRateTableItemData, DistanceRatesTableColumnKey> = (a, b, activeSorting) => {
+        const orderMultiplier = activeSorting.order === 'asc' ? 1 : -1;
+
+        if (activeSorting.columnKey === 'status') {
+            const aStatus = getRateStatus(a.rate);
+            const bStatus = getRateStatus(b.rate);
+            const diff = (STATUS_ORDER[aStatus] ?? 0) - (STATUS_ORDER[bStatus] ?? 0);
+            if (diff !== 0) {
+                return diff * orderMultiplier;
+            }
+            return localeCompare(a.rate.name ?? '', b.rate.name ?? '') * orderMultiplier;
+        }
+
+        if (activeSorting.columnKey === 'name') {
+            return localeCompare(a.rate.name ?? '', b.rate.name ?? '') * orderMultiplier;
+        }
+
+        if (activeSorting.columnKey === 'rate') {
+            return ((a.rate.rate ?? 0) - (b.rate.rate ?? 0)) * orderMultiplier;
+        }
+
+        if (activeSorting.columnKey === 'startDate') {
+            return localeCompare(a.rate.startDate ?? '', b.rate.startDate ?? '') * orderMultiplier;
+        }
+
+        if (activeSorting.columnKey === 'endDate') {
+            return localeCompare(a.rate.endDate ?? '', b.rate.endDate ?? '') * orderMultiplier;
+        }
+
+        return 0;
+    };
+
+    const isItemInSearch: IsItemInSearchCallback<DistanceRateTableItemData> = (item, searchString) => {
+        const matchingItems = tokenizedSearch([item], searchString, (i) => [i.rate.name ?? '', i.formattedRate]);
+        return matchingItems.length > 0;
+    };
+
+    const statusLabels = useMemo(
+        () => ({
+            [CONST.CUSTOM_UNITS.RATE_STATUS.ACTIVE]: translate('workspace.distanceRates.statusActive'),
+            [CONST.CUSTOM_UNITS.RATE_STATUS.FUTURE]: translate('workspace.distanceRates.statusFuture'),
+            [CONST.CUSTOM_UNITS.RATE_STATUS.EXPIRED]: translate('workspace.distanceRates.statusExpired'),
+            [CONST.CUSTOM_UNITS.RATE_STATUS.INACTIVE]: translate('workspace.distanceRates.statusInactive'),
+        }),
+        [translate],
+    );
+
+    const renderItem = ({item, index}: ListRenderItemInfo<DistanceRateTableItemData>) => (
+        <WorkspaceDistanceRatesTableRow
+            key={item.rateID}
+            item={item}
+            rowIndex={index}
+            isSelected={selectedDistanceRates.includes(item.rateID)}
+            canSelectMultiple={canSelectMultiple}
+            onToggle={() => onToggleRate(item.rateID)}
+            onPress={() => onPressRate(item.rateID)}
+            shouldUseNarrowTableLayout={shouldUseNarrowTableLayout}
+            statusLabels={statusLabels}
+        />
+    );
+
+    const isNarrowLayoutRef = useRef(shouldUseNarrowTableLayout);
+    const [activeSortingInWideLayout, setActiveSortingInWideLayout] = useState<ActiveSorting<DistanceRatesTableColumnKey> | undefined>(undefined);
+
+    useEffect(() => {
+        if (shouldUseNarrowTableLayout) {
+            if (isNarrowLayoutRef.current) {
+                return;
+            }
+            isNarrowLayoutRef.current = true;
+            const activeSorting = tableRef.current?.getActiveSorting();
+            setActiveSortingInWideLayout(activeSorting);
+            tableRef.current?.updateSorting({columnKey: 'name', order: 'asc'});
+            return;
+        }
+
+        if (!activeSortingInWideLayout || !isNarrowLayoutRef.current) {
+            return;
+        }
+
+        isNarrowLayoutRef.current = false;
+        tableRef.current?.updateSorting(activeSortingInWideLayout);
+    }, [activeSortingInWideLayout, shouldUseNarrowTableLayout]);
+
+    const allSelected = ratesData.length > 0 && ratesData.every((item) => selectedDistanceRates.includes(item.rateID));
+    const someSelected = selectedDistanceRates.length > 0 && !allSelected;
+
+    const SelectAllHeader = canSelectMultiple ? (
+        <View style={[styles.mr3, styles.alignSelfCenter]}>
+            <Checkbox
+                isChecked={allSelected}
+                isIndeterminate={someSelected}
+                onPress={onToggleAllRates}
+                accessibilityLabel={translate('accessibilityHints.selectAllDistanceRates')}
+            />
+        </View>
+    ) : null;
+
+    const ListHeader = !shouldUseNarrowTableLayout ? <Table.Header /> : null;
+
+    return (
+        <Table
+            ref={tableRef}
+            data={ratesData}
+            columns={columns}
+            renderItem={renderItem}
+            keyExtractor={keyExtractor}
+            compareItems={compareItems}
+            isItemInSearch={isItemInSearch}
+            initialSortColumn="name"
+            title={translate('workspace.common.distanceRates')}
+            ListHeaderComponent={shouldUseNarrowTableLayout ? ListHeader : undefined}
+        >
+            {!shouldUseNarrowTableLayout && (
+                <View style={[styles.flexRow, styles.alignItemsCenter, styles.mh5]}>
+                    {SelectAllHeader}
+                    <View style={[styles.flex1]}>
+                        <Table.Header />
+                    </View>
+                </View>
+            )}
+
+            <Table.Body contentContainerStyle={tableBodyContentContainerStyle} />
+        </Table>
+    );
+}
+
+export default WorkspaceDistanceRatesTable;
+export type {DistanceRateTableItemData, DistanceRatesTableColumnKey};
diff --git a/src/languages/en.ts b/src/languages/en.ts
index 4b26adf07f40..cab9e3ea4a73 100644
--- a/src/languages/en.ts
+++ b/src/languages/en.ts
@@ -6570,6 +6570,10 @@ const translations = {
             }),
             enableRate: 'Enable rate',
             status: 'Status',
+            statusActive: 'Active',
+            statusFuture: 'Future',
+            statusExpired: 'Expired',
+            statusInactive: 'Inactive',
             unit: 'Unit',
             taxFeatureNotEnabledMessage:
                 '<muted-text>Taxes must be enabled on the workspace to use this feature. Head over to <a href="#">More features</a> to make that change.</muted-text>',
diff --git a/src/libs/PolicyDistanceRatesUtils.ts b/src/libs/PolicyDistanceRatesUtils.ts
index 4d046ffe7e1d..44ccbf25add9 100644
--- a/src/libs/PolicyDistanceRatesUtils.ts
+++ b/src/libs/PolicyDistanceRatesUtils.ts
@@ -1,5 +1,6 @@
 import type {NullishDeep, OnyxUpdate} from 'react-native-onyx';
 import Onyx from 'react-native-onyx';
+import type {ValueOf} from 'type-fest';
 import type {FormInputErrors, FormOnyxValues} from '@components/Form/types';
 import type {LocalizedTranslate} from '@components/LocaleContextProvider';
 import CONST from '@src/CONST';
@@ -78,6 +79,20 @@ function validateCreateDistanceRateForm(
     return errors;
 }
 
+function getRateStatus(rate: Rate): ValueOf<typeof CONST.CUSTOM_UNITS.RATE_STATUS> {
+    if (!rate.enabled) {
+        return CONST.CUSTOM_UNITS.RATE_STATUS.INACTIVE;
+    }
+    const today = new Date().toISOString().split('T').at(0) ?? '';
+    if (rate.startDate && rate.startDate > today) {
+        return CONST.CUSTOM_UNITS.RATE_STATUS.FUTURE;
+    }
+    if (rate.endDate && rate.endDate < today) {
+        return CONST.CUSTOM_UNITS.RATE_STATUS.EXPIRED;
+    }
+    return CONST.CUSTOM_UNITS.RATE_STATUS.ACTIVE;
+}
+
 type PolicyDistanceRateUpdateField = keyof Pick<Rate, 'name' | 'rate'> | keyof TaxRateAttributes;
 
 /**
@@ -164,4 +179,4 @@ function buildOnyxDataForPolicyDistanceRateUpdates(
     return {optimisticData, successData, failureData};
 }
 
-export {validateRateValue, getOptimisticRateName, validateTaxClaimableValue, validateCreateDistanceRateForm, buildOnyxDataForPolicyDistanceRateUpdates};
+export {validateRateValue, getOptimisticRateName, validateTaxClaimableValue, validateCreateDistanceRateForm, getRateStatus, buildOnyxDataForPolicyDistanceRateUpdates};
diff --git a/src/pages/workspace/distanceRates/PolicyDistanceRatesPage.tsx b/src/pages/workspace/distanceRates/PolicyDistanceRatesPage.tsx
index ae20b656115f..324ce9c45c21 100644
--- a/src/pages/workspace/distanceRates/PolicyDistanceRatesPage.tsx
+++ b/src/pages/workspace/distanceRates/PolicyDistanceRatesPage.tsx
@@ -15,6 +15,7 @@ import type {ListItem} from '@components/SelectionList/types';
 import SelectionListWithModal from '@components/SelectionListWithModal';
 import CustomListHeader from '@components/SelectionListWithModal/CustomListHeader';
 import Switch from '@components/Switch';
+import WorkspaceDistanceRatesTable from '@components/Tables/WorkspaceDistanceRatesTable';
 import Text from '@components/Text';
 import useConfirmModal from '@hooks/useConfirmModal';
 import useFilteredSelection from '@hooks/useFilteredSelection';
@@ -23,6 +24,7 @@ import useLocalize from '@hooks/useLocalize';
 import useMobileSelectionMode from '@hooks/useMobileSelectionMode';
 import useNetwork from '@hooks/useNetwork';
 import useOnyx from '@hooks/useOnyx';
+import usePermissions from '@hooks/usePermissions';
 import usePolicy from '@hooks/usePolicy';
 import useResponsiveLayout from '@hooks/useResponsiveLayout';
 import useSearchBackPress from '@hooks/useSearchBackPress';
@@ -66,6 +68,8 @@ function PolicyDistanceRatesPage({
     },
 }: PolicyDistanceRatesPageProps) {
     const icons = useMemoizedLazyExpensifyIcons(['Checkmark', 'Close', 'Gear', 'Plus', 'Trashcan']);
+    const {isBetaEnabled} = usePermissions();
+    const isDateBoundMileageRateEnabled = isBetaEnabled(CONST.BETAS.DATE_BOUND_MILEAGE_RATE);
     const {shouldUseNarrowLayout, isInLandscapeMode} = useResponsiveLayout();
     const styles = useThemeStyles();
     const {translate, localeCompare} = useLocalize();
@@ -326,13 +330,20 @@ function PolicyDistanceRatesPage({
         setSelectedDistanceRates([]);
     };
 
+    const toggleRateByID = useCallback(
+        (rateID: string) => {
+            setSelectedDistanceRates((prevSelectedRates) => {
+                if (prevSelectedRates.includes(rateID)) {
+                    return prevSelectedRates.filter((selectedRate) => selectedRate !== rateID);
+                }
+                return [...prevSelectedRates, rateID];
+            });
+        },
+        [setSelectedDistanceRates],
+    );
+
     const toggleRate = (rate: RateForList) => {
-        setSelectedDistanceRates((prevSelectedRates) => {
-            if (prevSelectedRates.includes(rate.value)) {
-                return prevSelectedRates.filter((selectedRate) => selectedRate !== rate.value);
-            }
-            return [...prevSelectedRates, rate.value];
-        });
+        toggleRateByID(rate.value);
     };
 
     const toggleAllRates = () => {
@@ -347,6 +358,36 @@ function PolicyDistanceRatesPage({
         }
     };
 
+    const toggleAllRatesForTable = useCallback(() => {
+        if (selectedDistanceRates.length > 0) {
+            setSelectedDistanceRates([]);
+        } else {
+            setSelectedDistanceRates(
+                Object.entries(selectableRates)
+                    .filter(([, rate]) => rate.pendingAction !== CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE)
+                    .map(([key]) => key),
+            );
+        }
+    }, [selectedDistanceRates.length, selectableRates, setSelectedDistanceRates]);
+
+    const dismissErrorByID = (rateID: string) => {
+        if (!customUnit?.customUnitID) {
+            return;
+        }
+        if (customUnitRates[rateID]?.errors) {
+            clearDeleteDistanceRateError(policyID, customUnit.customUnitID, rateID);
+            return;
+        }
+        clearCreateDistanceRateItemAndError(policyID, customUnit.customUnitID, rateID);
+    };
+
+    const openRateDetailsByID = useCallback(
+        (rateID: string) => {
+            Navigation.navigate(ROUTES.WORKSPACE_DISTANCE_RATE_DETAILS.getRoute(policyID, rateID));
+        },
+        [policyID],
+    );
+
     const getCustomListHeader = () => {
         if (filteredDistanceRatesList.length === 0) {
             return null;
@@ -525,28 +566,42 @@ function PolicyDistanceRatesPage({
                         reasonAttributes={reasonAttributes}
                     />
                 )}
-                {Object.values(customUnitRates).length > 0 && (
-                    <SelectionListWithModal
-                        data={filteredDistanceRatesList}
-                        ListItem={TableListItem}
-                        onSelectRow={openRateDetails}
-                        onSelectionButtonPress={toggleRate}
-                        selectedItems={selectedDistanceRates}
-                        customListHeader={getCustomListHeader()}
-                        onTurnOnSelectionMode={(item) => item && toggleRate(item)}
-                        onSelectAll={filteredDistanceRatesList.length > 0 ? toggleAllRates : undefined}
-                        shouldPreventDefaultFocusOnSelectRow={!canUseTouchScreen()}
-                        customListHeaderContent={headerContent}
-                        canSelectMultiple={canSelectMultiple}
-                        selectAllAccessibilityLabel={translate('accessibilityHints.selectAllDistanceRates')}
-                        onDismissError={dismissError}
-                        shouldShowListEmptyContent={false}
-                        showScrollIndicator={false}
-                        turnOnSelectionModeOnLongPress
-                        shouldHeaderBeInsideList
-                        shouldShowRightCaret
-                    />
-                )}
+                {Object.values(customUnitRates).length > 0 &&
+                    (isDateBoundMileageRateEnabled ? (
+                        <WorkspaceDistanceRatesTable
+                            customUnitRates={customUnitRates}
+                            unitTranslation={unitTranslation}
+                            selectedDistanceRates={selectedDistanceRates}
+                            canSelectMultiple={canSelectMultiple}
+                            onToggleRate={toggleRateByID}
+                            onToggleAllRates={toggleAllRatesForTable}
+                            onPressRate={openRateDetailsByID}
+                            onDismissError={dismissErrorByID}
+                            pendingAction={policy?.pendingAction === CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD ? policy?.pendingAction : undefined}
+                            pendingFields={customUnit?.pendingFields}
+                        />
+                    ) : (
+                        <SelectionListWithModal
+                            data={filteredDistanceRatesList}
+                            ListItem={TableListItem}
+                            onSelectRow={openRateDetails}
+                            onSelectionButtonPress={toggleRate}
+                            selectedItems={selectedDistanceRates}
+                            customListHeader={getCustomListHeader()}
+                            onTurnOnSelectionMode={(item) => item && toggleRate(item)}
+                            onSelectAll={filteredDistanceRatesList.length > 0 ? toggleAllRates : undefined}
+                            shouldPreventDefaultFocusOnSelectRow={!canUseTouchScreen()}
+                            customListHeaderContent={headerContent}
+                            canSelectMultiple={canSelectMultiple}
+                            selectAllAccessibilityLabel={translate('accessibilityHints.selectAllDistanceRates')}
+                            onDismissError={dismissError}
+                            shouldShowListEmptyContent={false}
+                            showScrollIndicator={false}
+                            turnOnSelectionModeOnLongPress
+                            shouldHeaderBeInsideList
+                            shouldShowRightCaret
+                        />
+                    ))}
             </ScreenWrapper>
         </AccessOrNotFoundWrapper>
     );

From 8646759f6d009cfeb86c07889ef02b1d7c65cb47 Mon Sep 17 00:00:00 2001
From: krishna2323 <belivethatkg@gmail.com>
Date: Mon, 18 May 2026 02:05:50 +0530
Subject: [PATCH 021/435] fix: add mobile selection mode entry via long-press
 and search bar to distance rates table

Signed-off-by: krishna2323 <belivethatkg@gmail.com>
---
 .../WorkspaceDistanceRatesTableRow.tsx        | 14 ++++++++++-
 .../WorkspaceDistanceRatesTable/index.tsx     | 25 ++++++++++++++-----
 .../distanceRates/PolicyDistanceRatesPage.tsx | 13 +++++++++-
 3 files changed, 44 insertions(+), 8 deletions(-)

diff --git a/src/components/Tables/WorkspaceDistanceRatesTable/WorkspaceDistanceRatesTableRow.tsx b/src/components/Tables/WorkspaceDistanceRatesTable/WorkspaceDistanceRatesTableRow.tsx
index 505ece8ef54a..8c729a92e36e 100644
--- a/src/components/Tables/WorkspaceDistanceRatesTable/WorkspaceDistanceRatesTableRow.tsx
+++ b/src/components/Tables/WorkspaceDistanceRatesTable/WorkspaceDistanceRatesTableRow.tsx
@@ -32,6 +32,7 @@ type WorkspaceDistanceRatesTableRowProps = {
     canSelectMultiple: boolean;
     onToggle: () => void;
     onPress: () => void;
+    onLongPress?: () => void;
     shouldUseNarrowTableLayout: boolean;
     statusLabels: Record<string, string>;
 };
@@ -43,7 +44,17 @@ function formatDateColumn(dateString: string | undefined): string {
     return format(parseISO(dateString), CONST.DATE.MONTH_DAY_YEAR_FORMAT);
 }
 
-function WorkspaceDistanceRatesTableRow({item, rowIndex, isSelected, canSelectMultiple, onToggle, onPress, shouldUseNarrowTableLayout, statusLabels}: WorkspaceDistanceRatesTableRowProps) {
+function WorkspaceDistanceRatesTableRow({
+    item,
+    rowIndex,
+    isSelected,
+    canSelectMultiple,
+    onToggle,
+    onPress,
+    onLongPress,
+    shouldUseNarrowTableLayout,
+    statusLabels,
+}: WorkspaceDistanceRatesTableRowProps) {
     const theme = useTheme();
     const styles = useThemeStyles();
     const Expensicons = useMemoizedLazyExpensifyIcons(['ArrowRight']);
@@ -67,6 +78,7 @@ function WorkspaceDistanceRatesTableRow({item, rowIndex, isSelected, canSelectMu
             sentryLabel={CONST.SENTRY_LABEL.WORKSPACE.DISTANCE_RATES.ADD_BUTTON}
             offlineWithFeedback={{errors, pendingAction, onClose: onDismissError, shouldHideOnDelete: false}}
             onPress={onPress}
+            onLongPress={onLongPress}
         >
             {({hovered}) => (
                 <>
diff --git a/src/components/Tables/WorkspaceDistanceRatesTable/index.tsx b/src/components/Tables/WorkspaceDistanceRatesTable/index.tsx
index d959cdbd1104..13d528ebcb3b 100644
--- a/src/components/Tables/WorkspaceDistanceRatesTable/index.tsx
+++ b/src/components/Tables/WorkspaceDistanceRatesTable/index.tsx
@@ -27,6 +27,7 @@ type WorkspaceDistanceRatesTableProps = {
     onToggleRate: (rateID: string) => void;
     onToggleAllRates: () => void;
     onPressRate: (rateID: string) => void;
+    onLongPressRate?: (rateID: string) => void;
     onDismissError: (rateID: string) => void;
     pendingAction?: OnyxCommon.PendingAction;
     pendingFields?: OnyxCommon.PendingFields<string>;
@@ -47,6 +48,7 @@ function WorkspaceDistanceRatesTable({
     onToggleRate,
     onToggleAllRates,
     onPressRate,
+    onLongPressRate,
     onDismissError,
     pendingAction,
     pendingFields,
@@ -150,6 +152,7 @@ function WorkspaceDistanceRatesTable({
             canSelectMultiple={canSelectMultiple}
             onToggle={() => onToggleRate(item.rateID)}
             onPress={() => onPressRate(item.rateID)}
+            onLongPress={onLongPressRate ? () => onLongPressRate(item.rateID) : undefined}
             shouldUseNarrowTableLayout={shouldUseNarrowTableLayout}
             statusLabels={statusLabels}
         />
@@ -192,7 +195,14 @@ function WorkspaceDistanceRatesTable({
         </View>
     ) : null;
 
-    const ListHeader = !shouldUseNarrowTableLayout ? <Table.Header /> : null;
+    const shouldShowSearchBar = Object.keys(customUnitRates).length > CONST.SEARCH_ITEM_LIMIT;
+
+    const ListHeader = (
+        <>
+            {shouldShowSearchBar && <Table.SearchBar />}
+            {!shouldUseNarrowTableLayout && <Table.Header />}
+        </>
+    );
 
     return (
         <Table
@@ -208,12 +218,15 @@ function WorkspaceDistanceRatesTable({
             ListHeaderComponent={shouldUseNarrowTableLayout ? ListHeader : undefined}
         >
             {!shouldUseNarrowTableLayout && (
-                <View style={[styles.flexRow, styles.alignItemsCenter, styles.mh5]}>
-                    {SelectAllHeader}
-                    <View style={[styles.flex1]}>
-                        <Table.Header />
+                <>
+                    {shouldShowSearchBar && <Table.SearchBar />}
+                    <View style={[styles.flexRow, styles.alignItemsCenter, styles.mh5]}>
+                        {SelectAllHeader}
+                        <View style={[styles.flex1]}>
+                            <Table.Header />
+                        </View>
                     </View>
-                </View>
+                </>
             )}
 
             <Table.Body contentContainerStyle={tableBodyContentContainerStyle} />
diff --git a/src/pages/workspace/distanceRates/PolicyDistanceRatesPage.tsx b/src/pages/workspace/distanceRates/PolicyDistanceRatesPage.tsx
index 324ce9c45c21..914ba3f5aea2 100644
--- a/src/pages/workspace/distanceRates/PolicyDistanceRatesPage.tsx
+++ b/src/pages/workspace/distanceRates/PolicyDistanceRatesPage.tsx
@@ -33,7 +33,7 @@ import useShouldDisplayButtonsInSeparateLine from '@hooks/useShouldDisplayButton
 import useThemeStyles from '@hooks/useThemeStyles';
 import useTransactionViolation from '@hooks/useTransactionViolation';
 import useWorkspaceDocumentTitle from '@hooks/useWorkspaceDocumentTitle';
-import {turnOffMobileSelectionMode} from '@libs/actions/MobileSelectionMode';
+import {turnOffMobileSelectionMode, turnOnMobileSelectionMode} from '@libs/actions/MobileSelectionMode';
 import {
     clearCreateDistanceRateItemAndError,
     clearDeleteDistanceRateError,
@@ -388,6 +388,16 @@ function PolicyDistanceRatesPage({
         [policyID],
     );
 
+    const handleLongPressRate = useCallback(
+        (rateID: string) => {
+            if (shouldUseNarrowLayout && !isMobileSelectionModeEnabled) {
+                turnOnMobileSelectionMode();
+            }
+            toggleRateByID(rateID);
+        },
+        [shouldUseNarrowLayout, isMobileSelectionModeEnabled, toggleRateByID],
+    );
+
     const getCustomListHeader = () => {
         if (filteredDistanceRatesList.length === 0) {
             return null;
@@ -576,6 +586,7 @@ function PolicyDistanceRatesPage({
                             onToggleRate={toggleRateByID}
                             onToggleAllRates={toggleAllRatesForTable}
                             onPressRate={openRateDetailsByID}
+                            onLongPressRate={handleLongPressRate}
                             onDismissError={dismissErrorByID}
                             pendingAction={policy?.pendingAction === CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD ? policy?.pendingAction : undefined}
                             pendingFields={customUnit?.pendingFields}

From 365fd48c70c954ce5d6a2e9351e82784dbe88918 Mon Sep 17 00:00:00 2001
From: krishna2323 <belivethatkg@gmail.com>
Date: Sun, 24 May 2026 02:56:11 +0530
Subject: [PATCH 022/435] fix: add missing getRateStatus export and fix
 SEARCH_ITEM_LIMIT reference

Signed-off-by: krishna2323 <belivethatkg@gmail.com>
---
 .../WorkspaceDistanceRatesTable/index.tsx     |  2 +-
 src/libs/PolicyDistanceRatesUtils.ts          | 21 +++++++++++++++++--
 2 files changed, 20 insertions(+), 3 deletions(-)

diff --git a/src/components/Tables/WorkspaceDistanceRatesTable/index.tsx b/src/components/Tables/WorkspaceDistanceRatesTable/index.tsx
index 13d528ebcb3b..783146b3e584 100644
--- a/src/components/Tables/WorkspaceDistanceRatesTable/index.tsx
+++ b/src/components/Tables/WorkspaceDistanceRatesTable/index.tsx
@@ -195,7 +195,7 @@ function WorkspaceDistanceRatesTable({
         </View>
     ) : null;
 
-    const shouldShowSearchBar = Object.keys(customUnitRates).length > CONST.SEARCH_ITEM_LIMIT;
+    const shouldShowSearchBar = Object.keys(customUnitRates).length >= CONST.STANDARD_LIST_ITEM_LIMIT;
 
     const ListHeader = (
         <>
diff --git a/src/libs/PolicyDistanceRatesUtils.ts b/src/libs/PolicyDistanceRatesUtils.ts
index a024f6c58d23..121427c8de37 100644
--- a/src/libs/PolicyDistanceRatesUtils.ts
+++ b/src/libs/PolicyDistanceRatesUtils.ts
@@ -1,6 +1,5 @@
 import type {NullishDeep, OnyxUpdate} from 'react-native-onyx';
 import Onyx from 'react-native-onyx';
-import type {ValueOf} from 'type-fest';
 import type {FormInputErrors, FormOnyxValues} from '@components/Form/types';
 import type {LocalizedTranslate} from '@components/LocaleContextProvider';
 import CONST from '@src/CONST';
@@ -172,4 +171,22 @@ function buildOnyxDataForPolicyDistanceRateUpdates(
     return {optimisticData, successData, failureData};
 }
 
-export {validateRateValue, getOptimisticRateName, validateTaxClaimableValue, validateCreateDistanceRateForm, buildOnyxDataForPolicyDistanceRateUpdates};
+function getRateStatus(rate: Rate): string {
+    if (!rate.enabled) {
+        return CONST.CUSTOM_UNITS.RATE_STATUS.INACTIVE;
+    }
+
+    const now = new Date().toISOString().slice(0, 10);
+
+    if (rate.startDate && rate.startDate > now) {
+        return CONST.CUSTOM_UNITS.RATE_STATUS.FUTURE;
+    }
+
+    if (rate.endDate && rate.endDate < now) {
+        return CONST.CUSTOM_UNITS.RATE_STATUS.EXPIRED;
+    }
+
+    return CONST.CUSTOM_UNITS.RATE_STATUS.ACTIVE;
+}
+
+export {validateRateValue, getOptimisticRateName, validateTaxClaimableValue, validateCreateDistanceRateForm, buildOnyxDataForPolicyDistanceRateUpdates, getRateStatus};

From 1199736219d74ea34a9953ea7658b81afed05f1f Mon Sep 17 00:00:00 2001
From: "Issa Nimaga (via MelvinBot)" <infra+melvinbot@expensify.com>
Date: Mon, 25 May 2026 09:08:35 +0000
Subject: [PATCH 023/435] Remove ViewStyle contamination from MenuItem subtitle
 Text element

The subtitle Text in MenuItem was receiving combinedStyle which includes
styles.popoverMenuItem (flexDirection, paddingHorizontal: 20, paddingVertical: 12,
justifyContent, width: 100%). These ViewStyle properties on a Text element cause
Android-specific layout shifts when the subtitle content changes width (e.g.,
member count going from single to double digits).

Co-authored-by: Issa Nimaga <inimaga@users.noreply.github.com>
---
 src/components/MenuItem.tsx | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/components/MenuItem.tsx b/src/components/MenuItem.tsx
index f8e7a748565e..1b281eec777e 100644
--- a/src/components/MenuItem.tsx
+++ b/src/components/MenuItem.tsx
@@ -1111,7 +1111,7 @@ function MenuItem({
                                                 {/* Since subtitle can be of type number, we should allow 0 to be shown */}
                                                 {(subtitle === 0 || !!subtitle) && (
                                                     <View style={[styles.justifyContentCenter, styles.mr1, subtitleStyle]}>
-                                                        <Text style={[styles.textLabelSupporting, ...(combinedStyle as TextStyle[])]}>{subtitle}</Text>
+                                                        <Text style={[styles.textLabelSupporting]}>{subtitle}</Text>
                                                     </View>
                                                 )}
                                                 {(!!rightIconAccountID || !!rightIconReportID) && (

From 2c879fc60ae82df01816a9c5ce88ef8bf205a01c Mon Sep 17 00:00:00 2001
From: Rayane <77965000+rayane-d@users.noreply.github.com>
Date: Wed, 27 May 2026 02:08:56 +0100
Subject: [PATCH 024/435] fix: decode category name in tax rate message

---
 src/libs/ReportActionsUtils.ts | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/libs/ReportActionsUtils.ts b/src/libs/ReportActionsUtils.ts
index 2d2879665adc..fa80eb535a8b 100644
--- a/src/libs/ReportActionsUtils.ts
+++ b/src/libs/ReportActionsUtils.ts
@@ -3444,7 +3444,7 @@ function getCategoryTaxRateMessage(translate: LocalizedTranslate, action: Report
     const newTax = newTaxPercentage ? `${newTaxName} (${newTaxPercentage})` : newTaxName;
 
     return translate('workspaceActions.updatedCategoryTaxRate', {
-        categoryName,
+        categoryName: getDecodedCategoryName(categoryName),
         oldTax,
         newTax,
     });

From 1e43adefb1b73452cabbc825f6737470a748b01e Mon Sep 17 00:00:00 2001
From: Adam Horodyski <ad.horodyski@gmail.com>
Date: Wed, 27 May 2026 13:32:57 +0200
Subject: [PATCH 025/435] SequentialQueue: await persist in push() before
 flush()

---
 src/libs/Network/SequentialQueue.ts | 38 +++++++----------------------
 1 file changed, 9 insertions(+), 29 deletions(-)

diff --git a/src/libs/Network/SequentialQueue.ts b/src/libs/Network/SequentialQueue.ts
index ab23074658ca..7586f1473251 100644
--- a/src/libs/Network/SequentialQueue.ts
+++ b/src/libs/Network/SequentialQueue.ts
@@ -504,7 +504,7 @@ async function handleConflictActions<TKey extends OnyxKey>(conflictAction: Confl
     }
 }
 
-function push<TKey extends OnyxKey>(newRequest: OnyxRequest<TKey>): Promise<void> {
+async function push<TKey extends OnyxKey>(newRequest: OnyxRequest<TKey>): Promise<void> {
     const currentRequests = getAllPersistedRequests();
     Log.info('[SequentialQueue] push() called', false, {
         command: newRequest.command,
@@ -514,19 +514,10 @@ function push<TKey extends OnyxKey>(newRequest: OnyxRequest<TKey>): Promise<void
         isSequentialQueueRunning,
     });
 
-    // Save the request to the persisted queue. The in-memory update inside save()
-    // happens synchronously, so flush() below will see the new request immediately.
-    // The returned promise resolves when disk persistence completes.
     let persistencePromise: Promise<void>;
 
     if (newRequest.checkAndFixConflictingRequest) {
-        const requests = currentRequests;
-        Log.info('[SequentialQueue] Checking for conflicts', false, {
-            command: newRequest.command,
-            existingRequestsCount: requests.length,
-        });
-
-        const {conflictAction} = newRequest.checkAndFixConflictingRequest(requests as Array<OnyxRequest<TKey>>);
+        const {conflictAction} = newRequest.checkAndFixConflictingRequest(currentRequests as Array<OnyxRequest<TKey>>);
         Log.info('[SequentialQueue] Conflict action determined', false, {
             command: newRequest.command,
             conflictType: conflictAction.type,
@@ -537,41 +528,30 @@ function push<TKey extends OnyxKey>(newRequest: OnyxRequest<TKey>): Promise<void
         delete newRequest.checkAndFixConflictingRequest;
         persistencePromise = handleConflictActions(conflictAction, newRequest);
     } else {
-        Log.info('[SequentialQueue] No conflict action. Adding request to Persisted Requests', false, {
-            command: newRequest.command,
-        });
-        // Add request to Persisted Requests so that it can be retried if it fails
         persistencePromise = savePersistedRequest(newRequest);
     }
 
-    // If we are offline we don't need to trigger the queue to empty as it will happen when we come back online
+    // Block until the Onyx disk commit lands so a process kill between here and the XHR
+    // still leaves the request recoverable from storage on next launch.
+    await persistencePromise;
+
     if (isOfflineNetwork()) {
         Log.info('[SequentialQueue] Request persisted but not flushing — we are offline', false, {
             command: newRequest.command,
             queueLength: getAllPersistedRequests().length,
         });
-        return persistencePromise;
+        return;
     }
 
-    // If the queue is running this request will run once it has finished processing the current batch
     if (isSequentialQueueRunning) {
         Log.info('[SequentialQueue] Queue is running. Will flush when the current request is finished.', false, {
             command: newRequest.command,
         });
-        isReadyPromise.then(() => {
-            Log.info('[SequentialQueue] isReadyPromise resolved, flushing queue', false, {
-                command: newRequest.command,
-            });
-            flush(true);
-        });
-        return persistencePromise;
+        isReadyPromise.then(() => flush(true));
+        return;
     }
 
-    Log.info('[SequentialQueue] Queue is not running. Flushing the queue.', false, {
-        command: newRequest.command,
-    });
     flush(true);
-    return persistencePromise;
 }
 
 function getCurrentRequest(): Promise<void> {

From d4aa74695797f63ee934be6d5d8da3b67266a216 Mon Sep 17 00:00:00 2001
From: Adam Horodyski <ad.horodyski@gmail.com>
Date: Wed, 27 May 2026 13:35:42 +0200
Subject: [PATCH 026/435] SequentialQueue: restore push() flush trigger logs

---
 src/libs/Network/SequentialQueue.ts | 10 +++++++++-
 1 file changed, 9 insertions(+), 1 deletion(-)

diff --git a/src/libs/Network/SequentialQueue.ts b/src/libs/Network/SequentialQueue.ts
index 7586f1473251..4ad2c056d7cc 100644
--- a/src/libs/Network/SequentialQueue.ts
+++ b/src/libs/Network/SequentialQueue.ts
@@ -547,10 +547,18 @@ async function push<TKey extends OnyxKey>(newRequest: OnyxRequest<TKey>): Promis
         Log.info('[SequentialQueue] Queue is running. Will flush when the current request is finished.', false, {
             command: newRequest.command,
         });
-        isReadyPromise.then(() => flush(true));
+        isReadyPromise.then(() => {
+            Log.info('[SequentialQueue] isReadyPromise resolved, flushing queue', false, {
+                command: newRequest.command,
+            });
+            flush(true);
+        });
         return;
     }
 
+    Log.info('[SequentialQueue] Queue is not running. Flushing the queue.', false, {
+        command: newRequest.command,
+    });
     flush(true);
 }
 

From 96aceaecba1f48412ab9f1be9c34c19568319f85 Mon Sep 17 00:00:00 2001
From: Adam Horodyski <ad.horodyski@gmail.com>
Date: Wed, 27 May 2026 13:52:55 +0200
Subject: [PATCH 027/435] SequentialQueue: defer flush onto persistencePromise;
 update tests

---
 src/libs/Network/SequentialQueue.ts |  30 ++--
 tests/unit/SequentialQueueTest.ts   | 222 ++++++++++++++--------------
 2 files changed, 132 insertions(+), 120 deletions(-)

diff --git a/src/libs/Network/SequentialQueue.ts b/src/libs/Network/SequentialQueue.ts
index 4ad2c056d7cc..503d354df5db 100644
--- a/src/libs/Network/SequentialQueue.ts
+++ b/src/libs/Network/SequentialQueue.ts
@@ -504,7 +504,7 @@ async function handleConflictActions<TKey extends OnyxKey>(conflictAction: Confl
     }
 }
 
-async function push<TKey extends OnyxKey>(newRequest: OnyxRequest<TKey>): Promise<void> {
+function push<TKey extends OnyxKey>(newRequest: OnyxRequest<TKey>): Promise<void> {
     const currentRequests = getAllPersistedRequests();
     Log.info('[SequentialQueue] push() called', false, {
         command: newRequest.command,
@@ -531,35 +531,39 @@ async function push<TKey extends OnyxKey>(newRequest: OnyxRequest<TKey>): Promis
         persistencePromise = savePersistedRequest(newRequest);
     }
 
-    // Block until the Onyx disk commit lands so a process kill between here and the XHR
-    // still leaves the request recoverable from storage on next launch.
-    await persistencePromise;
-
+    // If we are offline we don't need to trigger the queue to empty as it will happen when we come back online
     if (isOfflineNetwork()) {
         Log.info('[SequentialQueue] Request persisted but not flushing — we are offline', false, {
             command: newRequest.command,
             queueLength: getAllPersistedRequests().length,
         });
-        return;
+        return persistencePromise;
     }
 
+    // Defer flush() onto persistencePromise so the XHR cannot fire before the Onyx disk
+    // commit lands. If the process is killed between fire and commit, the request would be
+    // lost from storage on next launch. The in-memory queue is already updated synchronously
+    // above, so callers checking getAll()/getLength() right after push() still see the new state.
     if (isSequentialQueueRunning) {
         Log.info('[SequentialQueue] Queue is running. Will flush when the current request is finished.', false, {
             command: newRequest.command,
         });
-        isReadyPromise.then(() => {
-            Log.info('[SequentialQueue] isReadyPromise resolved, flushing queue', false, {
-                command: newRequest.command,
+        persistencePromise
+            .then(() => isReadyPromise)
+            .then(() => {
+                Log.info('[SequentialQueue] isReadyPromise resolved, flushing queue', false, {
+                    command: newRequest.command,
+                });
+                flush(true);
             });
-            flush(true);
-        });
-        return;
+        return persistencePromise;
     }
 
     Log.info('[SequentialQueue] Queue is not running. Flushing the queue.', false, {
         command: newRequest.command,
     });
-    flush(true);
+    persistencePromise.then(() => flush(true));
+    return persistencePromise;
 }
 
 function getCurrentRequest(): Promise<void> {
diff --git a/tests/unit/SequentialQueueTest.ts b/tests/unit/SequentialQueueTest.ts
index b49478391eaa..e90d64e542bb 100644
--- a/tests/unit/SequentialQueueTest.ts
+++ b/tests/unit/SequentialQueueTest.ts
@@ -36,29 +36,30 @@ describe('SequentialQueue', () => {
         expect(getLength()).toBe(2);
     });
 
-    it('should push two requests with conflict resolution and replace', () => {
-        SequentialQueue.push(request);
-        const requestWithConflictResolution: Request<never> = {
-            command: 'ReconnectApp',
-            data: {accountID: 56789},
-            checkAndFixConflictingRequest: (persistedRequests) => {
-                // should be one instance of ReconnectApp, get the index to replace it later
-                const index = persistedRequests.findIndex((r) => r.command === 'ReconnectApp');
-                if (index === -1) {
-                    return {conflictAction: {type: 'push'}};
-                }
-
-                return {
-                    conflictAction: {type: 'replace', index},
-                };
-            },
-        };
-        SequentialQueue.push(requestWithConflictResolution);
-        expect(getLength()).toBe(1);
-        // We know there is only one request and it's ongoing.
-        // We can get it and verify that the ongoing request is the second one.
-        const ongoingRequest = getOngoingRequest();
-        expect(ongoingRequest?.data?.accountID).toBe(56789);
+    it('should push two requests with conflict resolution and replace', async () => {
+        // Pause the queue so `process()` does not consume the first request before
+        // the conflict resolver runs. Under persist-before-fire `push()` is async,
+        // so we await both pushes and then assert on the on-disk queue directly.
+        SequentialQueue.pause();
+        try {
+            await SequentialQueue.push(request);
+            const requestWithConflictResolution: Request<never> = {
+                command: 'ReconnectApp',
+                data: {accountID: 56789},
+                checkAndFixConflictingRequest: (persistedRequests) => {
+                    const index = persistedRequests.findIndex((r) => r.command === 'ReconnectApp');
+                    if (index === -1) {
+                        return {conflictAction: {type: 'push'}};
+                    }
+                    return {conflictAction: {type: 'replace', index}};
+                },
+            };
+            await SequentialQueue.push(requestWithConflictResolution);
+            expect(getLength()).toBe(1);
+            expect(getAll().at(0)?.data?.accountID).toBe(56789);
+        } finally {
+            SequentialQueue.unpause();
+        }
     });
 
     it('should push two requests with conflict resolution and push', () => {
@@ -88,105 +89,112 @@ describe('SequentialQueue', () => {
     });
 
     it('should add a new request even if a similar one is ongoing', async () => {
-        // .push at the end flush the queue
-        SequentialQueue.push(request);
+        // Pause fetch so the first request lands as `ongoingRequest` but never completes.
+        // The conflict checker on push 2 inspects the persisted queue (which excludes the
+        // ongoing request), so it cannot find a 'ReconnectApp' to replace and falls back
+        // to 'push'. The new request is therefore added to the queue.
+        const mockedFetch = global.fetch as ReturnType<typeof TestHelper.getGlobalFetchMock> & {pause: () => void; resume: () => Promise<void>};
+        mockedFetch.pause();
+        try {
+            await SequentialQueue.push(request);
+            await waitForBatchedUpdates();
+            expect(getOngoingRequest()?.command).toBe('ReconnectApp');
+
+            const requestWithConflictResolution: Request<never> = {
+                command: 'ReconnectApp',
+                data: {accountID: 56789},
+                checkAndFixConflictingRequest: (persistedRequests) => {
+                    const index = persistedRequests.findIndex((r) => r.command === 'ReconnectApp');
+                    if (index === -1) {
+                        return {conflictAction: {type: 'push'}};
+                    }
+                    return {conflictAction: {type: 'replace', index}};
+                },
+            };
 
-        // wait for Onyx.connect execute the callback and start processing the queue
-        await Promise.resolve();
+            await SequentialQueue.push(requestWithConflictResolution);
 
-        const requestWithConflictResolution: Request<never> = {
-            command: 'ReconnectApp',
-            data: {accountID: 56789},
-            checkAndFixConflictingRequest: (persistedRequests) => {
-                // should be one instance of ReconnectApp, get the index to replace it later
+            // The new request is in the persisted queue with the expected accountID.
+            expect(getAll().some((r) => r.data?.accountID === 56789)).toBe(true);
+        } finally {
+            await mockedFetch.resume();
+        }
+    });
+
+    it('should replace request request in queue while a similar one is ongoing', async () => {
+        const mockedFetch = global.fetch as ReturnType<typeof TestHelper.getGlobalFetchMock> & {pause: () => void; resume: () => Promise<void>};
+        mockedFetch.pause();
+        try {
+            await SequentialQueue.push(request);
+            await waitForBatchedUpdates();
+            expect(getOngoingRequest()?.command).toBe('ReconnectApp');
+
+            const conflictResolver = <TKey extends OnyxKey>(persistedRequests: Array<Request<TKey>>): ConflictActionData => {
                 const index = persistedRequests.findIndex((r) => r.command === 'ReconnectApp');
                 if (index === -1) {
                     return {conflictAction: {type: 'push'}};
                 }
-
-                return {
-                    conflictAction: {type: 'replace', index},
-                };
-            },
-        };
-
-        SequentialQueue.push(requestWithConflictResolution);
-
-        const ongoingRequest = getOngoingRequest();
-        expect(ongoingRequest?.data?.accountID).toBe(56789);
-    });
-
-    it('should replace request request in queue while a similar one is ongoing', async () => {
-        // .push at the end flush the queue
-        SequentialQueue.push(request);
-
-        // wait for Onyx.connect execute the callback and start processing the queue
-        await Promise.resolve();
-
-        const conflictResolver = <TKey extends OnyxKey>(persistedRequests: Array<Request<TKey>>): ConflictActionData => {
-            // should be one instance of ReconnectApp, get the index to replace it later
-            const index = persistedRequests.findIndex((r) => r.command === 'ReconnectApp');
-            if (index === -1) {
-                return {conflictAction: {type: 'push'}};
-            }
-
-            return {
-                conflictAction: {type: 'replace', index},
+                return {conflictAction: {type: 'replace', index}};
             };
-        };
 
-        const requestWithConflictResolution: Request<never> = {
-            command: 'ReconnectApp',
-            data: {accountID: 56789},
-            checkAndFixConflictingRequest: conflictResolver,
-        };
+            const requestWithConflictResolution: Request<never> = {
+                command: 'ReconnectApp',
+                data: {accountID: 56789},
+                checkAndFixConflictingRequest: conflictResolver,
+            };
 
-        const requestWithConflictResolution2: Request<never> = {
-            command: 'ReconnectApp',
-            data: {accountID: 56789},
-            checkAndFixConflictingRequest: conflictResolver,
-        };
+            const requestWithConflictResolution2: Request<never> = {
+                command: 'ReconnectApp',
+                data: {accountID: 56789},
+                checkAndFixConflictingRequest: conflictResolver,
+            };
 
-        SequentialQueue.push(requestWithConflictResolution);
-        SequentialQueue.push(requestWithConflictResolution2);
+            // First conflict push: queue is empty (ongoing not in queue) → push action → queue=[r2].
+            // Second conflict push: queue=[r2] → replace at 0 → queue=[r3].
+            // Total in-flight items: ongoing + queue = 2.
+            await SequentialQueue.push(requestWithConflictResolution);
+            await SequentialQueue.push(requestWithConflictResolution2);
 
-        expect(getLength()).toBe(2);
+            expect(getLength()).toBe(2);
+        } finally {
+            await mockedFetch.resume();
+        }
     });
 
-    it('should replace request request in queue while a similar one is ongoing and keep the same index', () => {
-        SequentialQueue.push({command: 'OpenReport'});
-        SequentialQueue.push(request);
-
-        const requestWithConflictResolution: Request<never> = {
-            command: 'ReconnectApp',
-            data: {accountID: 56789},
-            checkAndFixConflictingRequest: (persistedRequests) => {
-                // should be one instance of ReconnectApp, get the index to replace it later
-                const index = persistedRequests.findIndex((r) => r.command === 'ReconnectApp');
-                if (index === -1) {
-                    return {conflictAction: {type: 'push'}};
-                }
-
-                return {
-                    conflictAction: {type: 'replace', index},
-                };
-            },
-        };
-
-        SequentialQueue.push(requestWithConflictResolution);
-        SequentialQueue.push({command: 'AddComment'});
-        SequentialQueue.push({command: 'OpenReport'});
-
-        expect(getLength()).toBe(4);
-        const persistedRequests = getAll();
-        const ongoingRequest = getOngoingRequest();
+    it('should replace request request in queue while a similar one is ongoing and keep the same index', async () => {
+        const mockedFetch = global.fetch as ReturnType<typeof TestHelper.getGlobalFetchMock> & {pause: () => void; resume: () => Promise<void>};
+        mockedFetch.pause();
+        try {
+            // First push moves into `ongoingRequest`; subsequent pushes stack in the queue.
+            await SequentialQueue.push({command: 'OpenReport'});
+            await waitForBatchedUpdates();
+            expect(getOngoingRequest()?.command).toBe('OpenReport');
+
+            await SequentialQueue.push(request);
+
+            const requestWithConflictResolution: Request<never> = {
+                command: 'ReconnectApp',
+                data: {accountID: 56789},
+                checkAndFixConflictingRequest: (persistedRequests) => {
+                    const index = persistedRequests.findIndex((r) => r.command === 'ReconnectApp');
+                    if (index === -1) {
+                        return {conflictAction: {type: 'push'}};
+                    }
+                    return {conflictAction: {type: 'replace', index}};
+                },
+            };
 
-        // The first OpenReport call is ongoing
-        expect(ongoingRequest?.command).toBe('OpenReport');
+            await SequentialQueue.push(requestWithConflictResolution);
+            await SequentialQueue.push({command: 'AddComment'});
+            await SequentialQueue.push({command: 'OpenReport'});
 
-        // We know ReconnectApp is at index 0 in the queue now, so we can get it to verify
-        // that was replaced by the new request.
-        expect(persistedRequests.at(0)?.data?.accountID).toBe(56789);
+            expect(getLength()).toBe(4);
+            const persistedRequests = getAll();
+            expect(getOngoingRequest()?.command).toBe('OpenReport');
+            expect(persistedRequests.at(0)?.data?.accountID).toBe(56789);
+        } finally {
+            await mockedFetch.resume();
+        }
     });
 
     // need to test a rance condition between processing the next request and then pushing a new request with conflict resolver

From ce33aa97492daf99fba7771fab1d3f0223c6c8e7 Mon Sep 17 00:00:00 2001
From: Adam Horodyski <ad.horodyski@gmail.com>
Date: Wed, 27 May 2026 14:46:22 +0200
Subject: [PATCH 028/435] SequentialQueue: async push() with idempotent
 isReadyPromise marker

---
 src/libs/Network/SequentialQueue.ts | 73 ++++++++++++++++-------------
 1 file changed, 41 insertions(+), 32 deletions(-)

diff --git a/src/libs/Network/SequentialQueue.ts b/src/libs/Network/SequentialQueue.ts
index 503d354df5db..35e27716f8ab 100644
--- a/src/libs/Network/SequentialQueue.ts
+++ b/src/libs/Network/SequentialQueue.ts
@@ -44,13 +44,28 @@ type RequestError = Error & {
     status?: string;
 };
 
-let resolveIsReadyPromise: ((args?: unknown[]) => void) | undefined;
-let isReadyPromise = new Promise((resolve) => {
-    resolveIsReadyPromise = resolve;
-});
+let resolveIsReadyPromise: (() => void) | undefined;
+let isReadyPromise: Promise<void> = Promise.resolve();
+let isReadyPromisePending = false;
 
-// Resolve the isReadyPromise immediately so that the queue starts working as soon as the page loads
-resolveIsReadyPromise?.();
+/**
+ * Marks isReadyPromise as pending so any READ that consults waitForIdle() parks behind us.
+ * Idempotent: if already pending, no-op (avoids orphaning subscribers from prior pushes).
+ * Called from push()'s sync prelude before the first await, so READs on the next sync line
+ * see the pending promise.
+ */
+function setIsReadyPromisePending() {
+    if (isReadyPromisePending) {
+        return;
+    }
+    isReadyPromise = new Promise<void>((resolve) => {
+        resolveIsReadyPromise = () => {
+            isReadyPromisePending = false;
+            resolve();
+        };
+    });
+    isReadyPromisePending = true;
+}
 
 let isSequentialQueueRunning = false;
 let currentRequestPromise: Promise<void> | null = null;
@@ -334,10 +349,9 @@ function flush(shouldResetPromise = true) {
     isSequentialQueueRunning = true;
 
     if (shouldResetPromise) {
-        // Reset the isReadyPromise so that the queue will be flushed as soon as the request is finished
-        isReadyPromise = new Promise((resolve) => {
-            resolveIsReadyPromise = resolve;
-        });
+        // Mark isReadyPromise as pending so READs (waitForIdle) park behind us.
+        // Idempotent — safe if push() already marked it pending in its sync prelude.
+        setIsReadyPromisePending();
     }
 
     // Ensure persistedRequests are read from storage before proceeding with the queue
@@ -504,7 +518,7 @@ async function handleConflictActions<TKey extends OnyxKey>(conflictAction: Confl
     }
 }
 
-function push<TKey extends OnyxKey>(newRequest: OnyxRequest<TKey>): Promise<void> {
+async function push<TKey extends OnyxKey>(newRequest: OnyxRequest<TKey>): Promise<void> {
     const currentRequests = getAllPersistedRequests();
     Log.info('[SequentialQueue] push() called', false, {
         command: newRequest.command,
@@ -531,39 +545,35 @@ function push<TKey extends OnyxKey>(newRequest: OnyxRequest<TKey>): Promise<void
         persistencePromise = savePersistedRequest(newRequest);
     }
 
-    // If we are offline we don't need to trigger the queue to empty as it will happen when we come back online
     if (isOfflineNetwork()) {
         Log.info('[SequentialQueue] Request persisted but not flushing — we are offline', false, {
             command: newRequest.command,
             queueLength: getAllPersistedRequests().length,
         });
-        return persistencePromise;
+        await persistencePromise;
+        return;
     }
 
-    // Defer flush() onto persistencePromise so the XHR cannot fire before the Onyx disk
-    // commit lands. If the process is killed between fire and commit, the request would be
-    // lost from storage on next launch. The in-memory queue is already updated synchronously
-    // above, so callers checking getAll()/getLength() right after push() still see the new state.
+    // Mark the ready-promise pending sync (before the first await) so any READ that fires on
+    // the next synchronous line via waitForIdle() correctly parks behind this write.
+    setIsReadyPromisePending();
+
+    // Block until the Onyx disk commit lands so flush() → XHR cannot race the disk write —
+    // a process kill in that window would lose the request on next launch.
+    await persistencePromise;
+
     if (isSequentialQueueRunning) {
         Log.info('[SequentialQueue] Queue is running. Will flush when the current request is finished.', false, {
             command: newRequest.command,
         });
-        persistencePromise
-            .then(() => isReadyPromise)
-            .then(() => {
-                Log.info('[SequentialQueue] isReadyPromise resolved, flushing queue', false, {
-                    command: newRequest.command,
-                });
-                flush(true);
-            });
-        return persistencePromise;
+        isReadyPromise.then(() => flush(false));
+        return;
     }
 
     Log.info('[SequentialQueue] Queue is not running. Flushing the queue.', false, {
         command: newRequest.command,
     });
-    persistencePromise.then(() => flush(true));
-    return persistencePromise;
+    flush(false);
 }
 
 function getCurrentRequest(): Promise<void> {
@@ -588,10 +598,9 @@ function resetQueue(): void {
     isSequentialQueueRunning = false;
     currentRequestPromise = null;
     isQueuePaused = false;
-    isReadyPromise = new Promise((resolve) => {
-        resolveIsReadyPromise = resolve;
-    });
-    resolveIsReadyPromise?.();
+    isReadyPromise = Promise.resolve();
+    isReadyPromisePending = false;
+    resolveIsReadyPromise = undefined;
 }
 
 export {

From cfd043fd0b003d25e14b63c2a43602bd49c7ecb9 Mon Sep 17 00:00:00 2001
From: Alex Beaman <alexbeaman@expensify.com>
Date: Wed, 27 May 2026 14:17:49 -0600
Subject: [PATCH 029/435] Add IOURequestStepVendor RHP + nav wiring (Phase 3)

New vendor selector RHP that lists QBO vendors with name search and writes
the user pick via the Phase 1 updateMoneyRequestVendor action (isManuallySet
hardcoded true). Wires the screen, route, navigation type, linking config,
modal-stack registration, withWritableReportOrNotFound + withFullTransactionOrNotFound
union members, and adds the common.vendor translation in all 10 supported
locales.
---
 src/ROUTES.ts                                 |  10 ++
 src/SCREENS.ts                                |   1 +
 src/languages/de.ts                           |   1 +
 src/languages/en.ts                           |   1 +
 src/languages/es.ts                           |   1 +
 src/languages/fr.ts                           |   1 +
 src/languages/it.ts                           |   1 +
 src/languages/ja.ts                           |   1 +
 src/languages/nl.ts                           |   1 +
 src/languages/pl.ts                           |   1 +
 src/languages/pt-BR.ts                        |   1 +
 src/languages/zh-hans.ts                      |   1 +
 .../ModalStackNavigators/index.tsx            |   1 +
 src/libs/Navigation/linkingConfig/config.ts   |   1 +
 src/libs/Navigation/types.ts                  |   9 ++
 .../iou/request/step/IOURequestStepVendor.tsx | 129 ++++++++++++++++++
 .../step/withFullTransactionOrNotFound.tsx    |   1 +
 .../step/withWritableReportOrNotFound.tsx     |   1 +
 18 files changed, 163 insertions(+)
 create mode 100644 src/pages/iou/request/step/IOURequestStepVendor.tsx

diff --git a/src/ROUTES.ts b/src/ROUTES.ts
index cf6f8f95f7a5..f8ce0e5aee4d 100644
--- a/src/ROUTES.ts
+++ b/src/ROUTES.ts
@@ -1636,6 +1636,16 @@ const ROUTES = {
             return getUrlWithBackToParam(`${action as string}/${iouType as string}/category/${transactionID}/${reportID}${reportActionID ? `/${reportActionID}` : ''}`, backTo);
         },
     },
+    MONEY_REQUEST_STEP_VENDOR: {
+        route: ':action/:iouType/vendor/:transactionID/:reportID/:reportActionID?',
+        getRoute: (action: IOUAction, iouType: IOUType, transactionID: string | undefined, reportID: string | undefined, backTo = '', reportActionID?: string) => {
+            if (!transactionID || !reportID) {
+                Log.warn('Invalid transactionID or reportID is used to build the MONEY_REQUEST_STEP_VENDOR route');
+            }
+
+            return getUrlWithBackToParam(`${action as string}/${iouType as string}/vendor/${transactionID}/${reportID}${reportActionID ? `/${reportActionID}` : ''}`, backTo);
+        },
+    },
     MONEY_REQUEST_ATTENDEE: {
         route: ':action/:iouType/attendees/:transactionID/:reportID',
         getRoute: (action: IOUAction, iouType: IOUType, transactionID: string | undefined, reportID: string | undefined, backTo = '') => {
diff --git a/src/SCREENS.ts b/src/SCREENS.ts
index 66956e3afc50..264c5861356b 100644
--- a/src/SCREENS.ts
+++ b/src/SCREENS.ts
@@ -386,6 +386,7 @@ const SCREENS = {
         STEP_WAYPOINT: 'Money_Request_Step_Waypoint',
         STEP_TAX_AMOUNT: 'Money_Request_Step_Tax_Amount',
         STEP_TAX_RATE: 'Money_Request_Step_Tax_Rate',
+        STEP_VENDOR: 'Money_Request_Step_Vendor',
         RECEIPT_VIEW: 'Money_Request_Receipt_View',
         STEP_SEND_FROM: 'Money_Request_Step_Send_From',
         STEP_COMPANY_INFO: 'Money_Request_Step_Company_Info',
diff --git a/src/languages/de.ts b/src/languages/de.ts
index a6cf5c09960f..8f31b9739542 100644
--- a/src/languages/de.ts
+++ b/src/languages/de.ts
@@ -314,6 +314,7 @@ const translations: TranslationDeepObject<typeof en> = {
         merchant: 'Händler',
         change: 'Ändern',
         category: 'Kategorie',
+        vendor: 'Anbieter',
         report: 'Bericht',
         billable: 'Abrechenbar',
         nonBillable: 'Nicht abrechenbar',
diff --git a/src/languages/en.ts b/src/languages/en.ts
index 0b50e1b7b55e..a6545036592b 100644
--- a/src/languages/en.ts
+++ b/src/languages/en.ts
@@ -328,6 +328,7 @@ const translations = {
         merchant: 'Merchant',
         change: 'Change',
         category: 'Category',
+        vendor: 'Vendor',
         report: 'Report',
         billable: 'Billable',
         nonBillable: 'Non-billable',
diff --git a/src/languages/es.ts b/src/languages/es.ts
index f84ec9f6a162..b8c4a13a52a0 100644
--- a/src/languages/es.ts
+++ b/src/languages/es.ts
@@ -270,6 +270,7 @@ const translations: TranslationDeepObject<typeof en> = {
         merchant: 'Comerciante',
         change: 'Cambio',
         category: 'Categoría',
+        vendor: 'Proveedor',
         report: 'Informe',
         billable: 'Facturable',
         nonBillable: 'No facturable',
diff --git a/src/languages/fr.ts b/src/languages/fr.ts
index eb8b2d3b96f3..1fabec4c19e0 100644
--- a/src/languages/fr.ts
+++ b/src/languages/fr.ts
@@ -314,6 +314,7 @@ const translations: TranslationDeepObject<typeof en> = {
         merchant: 'Commerçant',
         change: 'Modifier',
         category: 'Catégorie',
+        vendor: 'Fournisseur',
         report: 'Note de frais',
         billable: 'Facturable',
         nonBillable: 'Non refacturable',
diff --git a/src/languages/it.ts b/src/languages/it.ts
index 8b55789d977a..fb9cd6d330df 100644
--- a/src/languages/it.ts
+++ b/src/languages/it.ts
@@ -314,6 +314,7 @@ const translations: TranslationDeepObject<typeof en> = {
         merchant: 'Esercente',
         change: 'Modifica',
         category: 'Categoria',
+        vendor: 'Fornitore',
         report: 'Report',
         billable: 'Fatturabile',
         nonBillable: 'Non fatturabile',
diff --git a/src/languages/ja.ts b/src/languages/ja.ts
index 7dadd52e6801..141707562870 100644
--- a/src/languages/ja.ts
+++ b/src/languages/ja.ts
@@ -314,6 +314,7 @@ const translations: TranslationDeepObject<typeof en> = {
         merchant: '加盟店',
         change: '変更',
         category: 'カテゴリ',
+        vendor: 'ベンダー',
         report: 'レポート',
         billable: '請求可能',
         nonBillable: '請求不可',
diff --git a/src/languages/nl.ts b/src/languages/nl.ts
index 9a7bb8d0ffb0..6d0737fb7a0d 100644
--- a/src/languages/nl.ts
+++ b/src/languages/nl.ts
@@ -314,6 +314,7 @@ const translations: TranslationDeepObject<typeof en> = {
         merchant: 'Handelaar',
         change: 'Wijzigen',
         category: 'Categorie',
+        vendor: 'Leverancier',
         report: 'Rapport',
         billable: 'Factureerbaar',
         nonBillable: 'Niet-factureerbaar',
diff --git a/src/languages/pl.ts b/src/languages/pl.ts
index f4011e201ee0..8faecbccac51 100644
--- a/src/languages/pl.ts
+++ b/src/languages/pl.ts
@@ -314,6 +314,7 @@ const translations: TranslationDeepObject<typeof en> = {
         merchant: 'Sprzedawca',
         change: 'Zmień',
         category: 'Kategoria',
+        vendor: 'Dostawca',
         report: 'Raport',
         billable: 'Fakturowalne',
         nonBillable: 'Nierozliczalne',
diff --git a/src/languages/pt-BR.ts b/src/languages/pt-BR.ts
index da031573508b..67867a639057 100644
--- a/src/languages/pt-BR.ts
+++ b/src/languages/pt-BR.ts
@@ -314,6 +314,7 @@ const translations: TranslationDeepObject<typeof en> = {
         merchant: 'Estabelecimento',
         change: 'Alterar',
         category: 'Categoria',
+        vendor: 'Fornecedor',
         report: 'Relatório',
         billable: 'Faturável',
         nonBillable: 'Não faturável',
diff --git a/src/languages/zh-hans.ts b/src/languages/zh-hans.ts
index ea9c4e854831..df924a6431e6 100644
--- a/src/languages/zh-hans.ts
+++ b/src/languages/zh-hans.ts
@@ -314,6 +314,7 @@ const translations: TranslationDeepObject<typeof en> = {
         merchant: '商户',
         change: '更改',
         category: '类别',
+        vendor: '供应商',
         report: '报表',
         billable: '可计费',
         nonBillable: '不可计费',
diff --git a/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx b/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx
index 24eb086ebc38..a1c85a4195c7 100644
--- a/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx
+++ b/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx
@@ -211,6 +211,7 @@ const MoneyRequestModalStackNavigator = createModalStackNavigator<MoneyRequestNa
     [SCREENS.MONEY_REQUEST.STEP_TAX_RATE]: () => require<ReactComponentModule>('../../../../pages/iou/request/step/IOURequestStepTaxRatePage').default,
     [SCREENS.MONEY_REQUEST.STEP_CATEGORY]: () => require<ReactComponentModule>('../../../../pages/iou/request/step/IOURequestStepCategory').default,
     [SCREENS.MONEY_REQUEST.STEP_CATEGORY_CREATE]: () => require<ReactComponentModule>('../../../../pages/iou/request/step/IOURequestStepCategoryCreate').default,
+    [SCREENS.MONEY_REQUEST.STEP_VENDOR]: () => require<ReactComponentModule>('../../../../pages/iou/request/step/IOURequestStepVendor').default,
     [SCREENS.MONEY_REQUEST.STEP_DATE]: () => require<ReactComponentModule>('../../../../pages/iou/request/step/IOURequestStepDate').default,
     [SCREENS.MONEY_REQUEST.STEP_DESCRIPTION]: () => require<ReactComponentModule>('../../../../pages/iou/request/step/IOURequestStepDescription').default,
     [SCREENS.MONEY_REQUEST.STEP_DISTANCE]: () => require<ReactComponentModule>('../../../../pages/iou/request/step/IOURequestStepDistance').default,
diff --git a/src/libs/Navigation/linkingConfig/config.ts b/src/libs/Navigation/linkingConfig/config.ts
index 4ff99bc12147..f70dd2e6b460 100644
--- a/src/libs/Navigation/linkingConfig/config.ts
+++ b/src/libs/Navigation/linkingConfig/config.ts
@@ -1744,6 +1744,7 @@ const config: LinkingOptions<RootNavigatorParamList>['config'] = {
                         [SCREENS.MONEY_REQUEST.STEP_AMOUNT]: ROUTES.MONEY_REQUEST_STEP_AMOUNT.route,
                         [SCREENS.MONEY_REQUEST.STEP_CATEGORY]: ROUTES.MONEY_REQUEST_STEP_CATEGORY.route,
                         [SCREENS.MONEY_REQUEST.STEP_CATEGORY_CREATE]: ROUTES.MONEY_REQUEST_STEP_CATEGORY_CREATE.route,
+                        [SCREENS.MONEY_REQUEST.STEP_VENDOR]: ROUTES.MONEY_REQUEST_STEP_VENDOR.route,
                         [SCREENS.MONEY_REQUEST.STEP_CONFIRMATION]: ROUTES.MONEY_REQUEST_STEP_CONFIRMATION.route,
                         [SCREENS.MONEY_REQUEST.STEP_CONFIRMATION_VERIFY_ACCOUNT]: ROUTES.MONEY_REQUEST_STEP_CONFIRMATION_VERIFY_ACCOUNT.route,
                         [SCREENS.MONEY_REQUEST.STEP_DATE]: ROUTES.MONEY_REQUEST_STEP_DATE.route,
diff --git a/src/libs/Navigation/types.ts b/src/libs/Navigation/types.ts
index 4957871c9dc0..8ccf18e4ea58 100644
--- a/src/libs/Navigation/types.ts
+++ b/src/libs/Navigation/types.ts
@@ -1884,6 +1884,15 @@ type MoneyRequestNavigatorParamList = {
         // eslint-disable-next-line no-restricted-syntax -- `backTo` usages in this file are legacy. Do not add new `backTo` params to screens. See contributingGuides/NAVIGATION.md
         backTo: Routes;
     };
+    [SCREENS.MONEY_REQUEST.STEP_VENDOR]: {
+        action: IOUAction;
+        iouType: Exclude<IOUType, typeof CONST.IOU.TYPE.REQUEST | typeof CONST.IOU.TYPE.SEND>;
+        transactionID: string;
+        reportActionID: string;
+        reportID: string;
+        // eslint-disable-next-line no-restricted-syntax -- `backTo` usages in this file are legacy. Do not add new `backTo` params to screens. See contributingGuides/NAVIGATION.md
+        backTo: Routes;
+    };
     [SCREENS.MONEY_REQUEST.STEP_CATEGORY_CREATE]: {
         action: IOUAction;
         iouType: Exclude<IOUType, typeof CONST.IOU.TYPE.REQUEST | typeof CONST.IOU.TYPE.SEND>;
diff --git a/src/pages/iou/request/step/IOURequestStepVendor.tsx b/src/pages/iou/request/step/IOURequestStepVendor.tsx
new file mode 100644
index 000000000000..94dd9d49971e
--- /dev/null
+++ b/src/pages/iou/request/step/IOURequestStepVendor.tsx
@@ -0,0 +1,129 @@
+import React, {useMemo, useState} from 'react';
+import BlockingView from '@components/BlockingViews/BlockingView';
+import SelectionList from '@components/SelectionList';
+import SingleSelectListItem from '@components/SelectionList/ListItem/SingleSelectListItem';
+import type {ListItem} from '@components/SelectionList/types';
+import {useMemoizedLazyIllustrations} from '@hooks/useLazyAsset';
+import useLocalize from '@hooks/useLocalize';
+import usePermissions from '@hooks/usePermissions';
+import usePolicyForTransaction from '@hooks/usePolicyForTransaction';
+import useShowNotFoundPageInIOUStep from '@hooks/useShowNotFoundPageInIOUStep';
+import useThemeStyles from '@hooks/useThemeStyles';
+import {updateMoneyRequestVendor} from '@libs/actions/IOU/UpdateMoneyRequest';
+import Navigation from '@libs/Navigation/Navigation';
+import {getQBOVendors, hasVendorFeature} from '@libs/PolicyUtils';
+import {isPerDiemRequest} from '@libs/TransactionUtils';
+import variables from '@styles/variables';
+import CONST from '@src/CONST';
+import type SCREENS from '@src/SCREENS';
+import StepScreenWrapper from './StepScreenWrapper';
+import type {WithFullTransactionOrNotFoundProps} from './withFullTransactionOrNotFound';
+import withFullTransactionOrNotFound from './withFullTransactionOrNotFound';
+import type {WithWritableReportOrNotFoundProps} from './withWritableReportOrNotFound';
+import withWritableReportOrNotFound from './withWritableReportOrNotFound';
+
+type VendorListItem = ListItem & {
+    value: string;
+};
+
+type IOURequestStepVendorProps = WithWritableReportOrNotFoundProps<typeof SCREENS.MONEY_REQUEST.STEP_VENDOR> & WithFullTransactionOrNotFoundProps<typeof SCREENS.MONEY_REQUEST.STEP_VENDOR>;
+
+function IOURequestStepVendor({
+    report,
+    route: {
+        params: {action, iouType, transactionID, reportActionID, backTo},
+    },
+    transaction,
+}: IOURequestStepVendorProps) {
+    const styles = useThemeStyles();
+    const {translate} = useLocalize();
+    const {isBetaEnabled} = usePermissions();
+    const illustrations = useMemoizedLazyIllustrations(['Telescope']);
+    const [searchValue, setSearchValue] = useState('');
+
+    const {policy} = usePolicyForTransaction({
+        transaction,
+        reportPolicyID: report?.policyID,
+        action,
+        iouType,
+        isPerDiemRequest: isPerDiemRequest(transaction),
+    });
+
+    const isFeatureAvailable = hasVendorFeature(policy, isBetaEnabled(CONST.BETAS.VENDOR_MATCHING));
+    const vendors = useMemo(() => getQBOVendors(policy), [policy]);
+    const currentVendorID = transaction?.comment?.vendor?.externalID;
+
+    const data: VendorListItem[] = useMemo(() => {
+        const trimmed = searchValue.trim().toLowerCase();
+        return vendors
+            .filter((vendor) => !trimmed || vendor.name.toLowerCase().includes(trimmed))
+            .map((vendor) => ({
+                value: vendor.id,
+                text: vendor.name,
+                keyForList: vendor.id,
+                isSelected: vendor.id === currentVendorID,
+                searchText: vendor.name,
+            }));
+    }, [vendors, currentVendorID, searchValue]);
+
+    const shouldShowNotFoundPage = useShowNotFoundPageInIOUStep(action, iouType, reportActionID, report, transaction) || !isFeatureAvailable;
+
+    const navigateBack = () => {
+        Navigation.goBack(backTo);
+    };
+
+    const selectVendor = (item: VendorListItem) => {
+        if (item.value !== currentVendorID) {
+            updateMoneyRequestVendor(transactionID, item.value, transaction);
+        }
+        navigateBack();
+    };
+
+    const headerMessage = searchValue && data.length === 0 ? translate('common.noResultsFound') : '';
+
+    const listEmptyContent = useMemo(
+        () =>
+            vendors.length === 0 ? (
+                <BlockingView
+                    icon={illustrations.Telescope}
+                    iconWidth={variables.emptyListIconWidth}
+                    iconHeight={variables.emptyListIconHeight}
+                    title={translate('workspace.qbo.noAccountsFound')}
+                    subtitle={translate('workspace.qbo.noAccountsFoundDescription')}
+                    containerStyle={styles.pb10}
+                />
+            ) : null,
+        [vendors.length, illustrations.Telescope, translate, styles.pb10],
+    );
+
+    return (
+        <StepScreenWrapper
+            headerTitle={translate('common.vendor')}
+            onBackButtonPress={navigateBack}
+            shouldShowWrapper
+            shouldShowNotFoundPage={shouldShowNotFoundPage}
+            testID="IOURequestStepVendor"
+            includeSafeAreaPaddingBottom
+        >
+            <SelectionList
+                data={data}
+                onSelectRow={selectVendor}
+                textInputOptions={{
+                    label: translate('common.search'),
+                    value: searchValue,
+                    onChangeText: setSearchValue,
+                    headerMessage,
+                }}
+                initiallyFocusedItemKey={data.find((item) => item.isSelected)?.keyForList}
+                ListItem={SingleSelectListItem}
+                shouldShowLoadingPlaceholder={!policy}
+                listEmptyContent={listEmptyContent}
+                shouldSingleExecuteRowSelect
+            />
+        </StepScreenWrapper>
+    );
+}
+
+IOURequestStepVendor.displayName = 'IOURequestStepVendor';
+
+export default withWritableReportOrNotFound(withFullTransactionOrNotFound(IOURequestStepVendor));
diff --git a/src/pages/iou/request/step/withFullTransactionOrNotFound.tsx b/src/pages/iou/request/step/withFullTransactionOrNotFound.tsx
index f37b4127d942..df3be6584abc 100644
--- a/src/pages/iou/request/step/withFullTransactionOrNotFound.tsx
+++ b/src/pages/iou/request/step/withFullTransactionOrNotFound.tsx
@@ -39,6 +39,7 @@ type MoneyRequestRouteName =
     | typeof SCREENS.MONEY_REQUEST.STEP_DISTANCE_RATE
     | typeof SCREENS.MONEY_REQUEST.STEP_CONFIRMATION
     | typeof SCREENS.MONEY_REQUEST.STEP_CATEGORY
+    | typeof SCREENS.MONEY_REQUEST.STEP_VENDOR
     | typeof SCREENS.MONEY_REQUEST.STEP_TAX_RATE
     | typeof SCREENS.MONEY_REQUEST.STEP_SCAN
     | typeof SCREENS.MONEY_REQUEST.STEP_SEND_FROM
diff --git a/src/pages/iou/request/step/withWritableReportOrNotFound.tsx b/src/pages/iou/request/step/withWritableReportOrNotFound.tsx
index 5eb13936ed83..9b25511beb50 100644
--- a/src/pages/iou/request/step/withWritableReportOrNotFound.tsx
+++ b/src/pages/iou/request/step/withWritableReportOrNotFound.tsx
@@ -29,6 +29,7 @@ type MoneyRequestRouteName =
     | typeof SCREENS.MONEY_REQUEST.STEP_DESCRIPTION
     | typeof SCREENS.MONEY_REQUEST.STEP_DATE
     | typeof SCREENS.MONEY_REQUEST.STEP_CATEGORY
+    | typeof SCREENS.MONEY_REQUEST.STEP_VENDOR
     | typeof SCREENS.MONEY_REQUEST.STEP_DISTANCE_RATE
     | typeof SCREENS.MONEY_REQUEST.STEP_CONFIRMATION
     | typeof SCREENS.MONEY_REQUEST.STEP_TAX_RATE

From 85ccf233532f6622016cfdb7c81d6ec1e4e09a5c Mon Sep 17 00:00:00 2001
From: Alex Beaman <alexbeaman@expensify.com>
Date: Wed, 27 May 2026 14:19:56 -0600
Subject: [PATCH 030/435] Add Vendor row on MoneyRequestView (Phase 3)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Surfaces the current expense vendor below the Category row when the
workspace has the vendorMatching beta + QBO Credit/Debit-card export
config AND the expense is non-reimbursable. Tapping opens the new
MONEY_REQUEST_STEP_VENDOR RHP. The inactiveVendor violation is surfaced
via getErrorForField('vendor') using the Phase 1 useViolations mapping
(inactiveVendor → 'vendor' field).
---
 .../ReportActionItem/MoneyRequestView.tsx     | 34 +++++++++++++++++++
 1 file changed, 34 insertions(+)

diff --git a/src/components/ReportActionItem/MoneyRequestView.tsx b/src/components/ReportActionItem/MoneyRequestView.tsx
index 0e24f5e95356..e3015041af29 100644
--- a/src/components/ReportActionItem/MoneyRequestView.tsx
+++ b/src/components/ReportActionItem/MoneyRequestView.tsx
@@ -58,8 +58,10 @@ import {
     getLengthOfTag,
     getPerDiemCustomUnit,
     getPolicyByCustomUnitID,
+    getQBOVendorByID,
     getTagLists,
     hasDependentTags as hasDependentTagsPolicyUtils,
+    hasVendorFeature,
     isAttendeeTrackingEnabled,
     isPolicyAccessible,
     isTaxTrackingEnabled,
@@ -450,6 +452,10 @@ function MoneyRequestView({
         });
     const shouldShowAttendees = shouldShowAttendeesTransactionUtils(iouType, policy);
 
+    const transactionVendor = transaction?.comment?.vendor;
+    const transactionVendorName = getQBOVendorByID(policy, transactionVendor?.externalID)?.name ?? '';
+    const shouldShowVendor = hasVendorFeature(policy, isBetaEnabled(CONST.BETAS.VENDOR_MATCHING)) && !(updatedTransaction?.reimbursable ?? !!transactionReimbursable);
+
     const tripID = getTripIDFromTransactionParentReportID(parentReport?.parentReportID);
     const shouldShowViewTripDetails = hasReservationList(transaction) && !!tripID;
 
@@ -1120,6 +1126,34 @@ function MoneyRequestView({
                         />
                     </OfflineWithFeedback>
                 )}
+                {shouldShowVendor && (
+                    <OfflineWithFeedback pendingAction={getPendingFieldAction('comment')}>
+                        <MenuItemWithTopDescription
+                            description={translate('common.vendor')}
+                            title={transactionVendorName}
+                            numberOfLinesTitle={2}
+                            interactive={canEdit}
+                            shouldShowRightIcon={canEdit}
+                            titleStyle={styles.flex1}
+                            onPress={() => {
+                                if (!transactionThreadReport?.reportID) {
+                                    return;
+                                }
+                                Navigation.navigate(
+                                    ROUTES.MONEY_REQUEST_STEP_VENDOR.getRoute(
+                                        CONST.IOU.ACTION.EDIT,
+                                        iouType,
+                                        transaction.transactionID,
+                                        transactionThreadReport.reportID,
+                                        Navigation.getActiveRoute(),
+                                    ),
+                                );
+                            }}
+                            brickRoadIndicator={getErrorForField('vendor') ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR : undefined}
+                            errorText={getErrorForField('vendor')}
+                        />
+                    </OfflineWithFeedback>
+                )}
                 {shouldShowTag && tagList}
                 {!!shouldShowCard && (
                     <OfflineWithFeedback pendingAction={getPendingFieldAction('cardID')}>

From 630162241b07e7c87ac93096d1c9793fc0260595 Mon Sep 17 00:00:00 2001
From: Alex Beaman <alexbeaman@expensify.com>
Date: Wed, 27 May 2026 14:24:28 -0600
Subject: [PATCH 031/435] Add ConciergeAutoMatchVendor action rendering (Phase
 3)

Wires the App side of the Phase 1 Auth-emitted CONCIERGEAUTOMATCHVENDOR
report action: new CONST entry, OriginalMessage type (vendorName +
reasoning), renderer using ReportActionItemMessageWithExplain (Explain
link surfaces automatically via hasReasoning check), and translations
across all 10 supported locales.
---
 src/CONST/index.ts                            |  1 +
 src/languages/de.ts                           |  1 +
 src/languages/en.ts                           |  1 +
 src/languages/es.ts                           |  1 +
 src/languages/fr.ts                           |  1 +
 src/languages/it.ts                           |  1 +
 src/languages/ja.ts                           |  1 +
 src/languages/nl.ts                           |  1 +
 src/languages/pl.ts                           |  1 +
 src/languages/pt-BR.ts                        |  1 +
 src/languages/zh-hans.ts                      |  1 +
 .../actionContents/ActionContentRouter.tsx    |  9 +++++
 .../ConciergeAutoMatchVendorContent.tsx       | 37 +++++++++++++++++++
 src/types/onyx/OriginalMessage.ts             | 11 ++++++
 14 files changed, 68 insertions(+)
 create mode 100644 src/pages/inbox/report/actionContents/ConciergeAutoMatchVendorContent.tsx

diff --git a/src/CONST/index.ts b/src/CONST/index.ts
index 05b4259c0b2f..02ffba7b3b89 100644
--- a/src/CONST/index.ts
+++ b/src/CONST/index.ts
@@ -1585,6 +1585,7 @@ const CONST = {
                 MARK_REIMBURSED_FROM_INTEGRATION: 'ACTIONMARKEDREIMBURSEDFROMINTEGRATION', // OldDot Action
                 MERGED_WITH_CASH_TRANSACTION: 'MERGEDWITHCASHTRANSACTION',
                 MODIFIED_EXPENSE: 'MODIFIEDEXPENSE',
+                CONCIERGE_AUTO_MATCH_VENDOR: 'CONCIERGEAUTOMATCHVENDOR',
                 MOVED: 'MOVED',
                 MOVED_TRANSACTION: 'MOVEDTRANSACTION',
                 UNREPORTED_TRANSACTION: 'UNREPORTEDTRANSACTION',
diff --git a/src/languages/de.ts b/src/languages/de.ts
index 8f31b9739542..e9dbd7028368 100644
--- a/src/languages/de.ts
+++ b/src/languages/de.ts
@@ -1657,6 +1657,7 @@ const translations: TranslationDeepObject<typeof en> = {
         },
         correctRateError: 'Beheben Sie den Kursfehler und versuchen Sie es erneut.',
         AskToExplain: `. <a href="${CONST.CONCIERGE_EXPLAIN_LINK_PATH}">Erklären<sparkles-icon/></a>`,
+        conciergeAutoMatchedVendor: ({vendorName}: {vendorName: string}) => `Concierge hat diese Ausgabe <strong>${vendorName}</strong> zugeordnet`,
         duplicateNonDefaultWorkspacePerDiemError:
             'Sie können Per-Diem-Ausgaben nicht über mehrere Workspaces hinweg duplizieren, da sich die Sätze zwischen den Workspaces unterscheiden können.',
         rulesModifiedFields: {
diff --git a/src/languages/en.ts b/src/languages/en.ts
index a6545036592b..c8f362962950 100644
--- a/src/languages/en.ts
+++ b/src/languages/en.ts
@@ -1711,6 +1711,7 @@ const translations = {
         },
         correctRateError: 'Fix the rate error and try again.',
         AskToExplain: `. <a href="${CONST.CONCIERGE_EXPLAIN_LINK_PATH}">Explain<sparkles-icon/></a>`,
+        conciergeAutoMatchedVendor: ({vendorName}: {vendorName: string}) => `Concierge matched this expense to <strong>${vendorName}</strong>`,
         rulesModifiedFields: {
             reimbursable: (value: boolean) => (value ? 'marked the expense as "reimbursable"' : 'marked the expense as "non-reimbursable"'),
             billable: (value: boolean) => (value ? 'marked the expense as "billable"' : 'marked the expense as "non-billable"'),
diff --git a/src/languages/es.ts b/src/languages/es.ts
index b8c4a13a52a0..6257665a4a84 100644
--- a/src/languages/es.ts
+++ b/src/languages/es.ts
@@ -1620,6 +1620,7 @@ const translations: TranslationDeepObject<typeof en> = {
         },
         correctRateError: 'Corrige el error de la tasa y vuelve a intentarlo.',
         AskToExplain: `. <a href="${CONST.CONCIERGE_EXPLAIN_LINK_PATH}">Explicar<sparkles-icon/></a>`,
+        conciergeAutoMatchedVendor: ({vendorName}: {vendorName: string}) => `Concierge asoció este gasto con <strong>${vendorName}</strong>`,
         rulesModifiedFields: {
             reimbursable: (value: boolean) => (value ? 'marcó el gasto como "reembolsable"' : 'marcó el gasto como "no reembolsable"'),
             billable: (value: boolean) => (value ? 'marcó el gasto como "facturable"' : 'marcó el gasto como "no facturable"'),
diff --git a/src/languages/fr.ts b/src/languages/fr.ts
index 1fabec4c19e0..5d630887a5b3 100644
--- a/src/languages/fr.ts
+++ b/src/languages/fr.ts
@@ -1663,6 +1663,7 @@ const translations: TranslationDeepObject<typeof en> = {
         },
         correctRateError: 'Corrigez l’erreur de taux et réessayez.',
         AskToExplain: `. <a href="${CONST.CONCIERGE_EXPLAIN_LINK_PATH}">Expliquer<sparkles-icon/></a>`,
+        conciergeAutoMatchedVendor: ({vendorName}: {vendorName: string}) => `Concierge a associé cette dépense au fournisseur <strong>${vendorName}</strong>`,
         duplicateNonDefaultWorkspacePerDiemError:
             'Vous ne pouvez pas dupliquer les indemnités journalières entre plusieurs espaces de travail, car les taux peuvent différer d’un espace de travail à l’autre.',
         rulesModifiedFields: {
diff --git a/src/languages/it.ts b/src/languages/it.ts
index fb9cd6d330df..f4336fa77d4c 100644
--- a/src/languages/it.ts
+++ b/src/languages/it.ts
@@ -1656,6 +1656,7 @@ const translations: TranslationDeepObject<typeof en> = {
         },
         correctRateError: "Correggi l'errore di tariffa e riprova.",
         AskToExplain: `. <a href="${CONST.CONCIERGE_EXPLAIN_LINK_PATH}">Spiega<sparkles-icon/></a>`,
+        conciergeAutoMatchedVendor: ({vendorName}: {vendorName: string}) => `Concierge ha associato questa spesa al fornitore <strong>${vendorName}</strong>`,
         duplicateNonDefaultWorkspacePerDiemError: 'Non puoi duplicare le spese di diaria tra diversi spazi di lavoro perché le tariffe potrebbero essere diverse tra gli spazi di lavoro.',
         rulesModifiedFields: {
             reimbursable: (value: boolean) => (value ? 'ha contrassegnato la spesa come "rimborsabile"' : 'ha contrassegnato la spesa come "non rimborsabile"'),
diff --git a/src/languages/ja.ts b/src/languages/ja.ts
index 141707562870..ba954497372f 100644
--- a/src/languages/ja.ts
+++ b/src/languages/ja.ts
@@ -1637,6 +1637,7 @@ const translations: TranslationDeepObject<typeof en> = {
         },
         correctRateError: 'レートのエラーを修正して、もう一度お試しください。',
         AskToExplain: `・<a href="${CONST.CONCIERGE_EXPLAIN_LINK_PATH}">説明<sparkles-icon/></a>`,
+        conciergeAutoMatchedVendor: ({vendorName}: {vendorName: string}) => `Concierge がこの経費を <strong>${vendorName}</strong> に一致させました`,
         duplicateNonDefaultWorkspacePerDiemError: 'ワークスペースごとに日当レートが異なる場合があるため、日当経費をワークスペース間で複製することはできません。',
         rulesModifiedFields: {
             reimbursable: (value: boolean) => (value ? '経費を「精算対象」に指定しました' : '経費を「精算対象外」にマークしました'),
diff --git a/src/languages/nl.ts b/src/languages/nl.ts
index 6d0737fb7a0d..2d4a7ef5ab32 100644
--- a/src/languages/nl.ts
+++ b/src/languages/nl.ts
@@ -1652,6 +1652,7 @@ const translations: TranslationDeepObject<typeof en> = {
         },
         correctRateError: 'Los de tarieffout op en probeer het opnieuw.',
         AskToExplain: `. <a href="${CONST.CONCIERGE_EXPLAIN_LINK_PATH}">Uitleggen<sparkles-icon/></a>`,
+        conciergeAutoMatchedVendor: ({vendorName}: {vendorName: string}) => `Concierge heeft deze uitgave gekoppeld aan <strong>${vendorName}</strong>`,
         duplicateNonDefaultWorkspacePerDiemError: 'Je kunt dagvergoedingen niet dupliceren tussen werkruimtes, omdat de tarieven per werkruimte kunnen verschillen.',
         rulesModifiedFields: {
             reimbursable: (value: boolean) => (value ? 'markeerde de uitgave als „terugbetaalbaar”' : 'heeft de uitgave als ‘niet-vergoedbaar’ gemarkeerd'),
diff --git a/src/languages/pl.ts b/src/languages/pl.ts
index 8faecbccac51..d4e705e51421 100644
--- a/src/languages/pl.ts
+++ b/src/languages/pl.ts
@@ -1651,6 +1651,7 @@ const translations: TranslationDeepObject<typeof en> = {
         },
         correctRateError: 'Napraw błąd stawki i spróbuj ponownie.',
         AskToExplain: `. <a href="${CONST.CONCIERGE_EXPLAIN_LINK_PATH}">Wyjaśnij<sparkles-icon/></a>`,
+        conciergeAutoMatchedVendor: ({vendorName}: {vendorName: string}) => `Concierge dopasował ten wydatek do <strong>${vendorName}</strong>`,
         duplicateNonDefaultWorkspacePerDiemError:
             'Nie możesz duplikować wydatków z tytułu diet między przestrzeniami roboczymi, ponieważ stawki mogą się różnić między poszczególnymi przestrzeniami.',
         rulesModifiedFields: {
diff --git a/src/languages/pt-BR.ts b/src/languages/pt-BR.ts
index 67867a639057..d005d8705aab 100644
--- a/src/languages/pt-BR.ts
+++ b/src/languages/pt-BR.ts
@@ -1650,6 +1650,7 @@ const translations: TranslationDeepObject<typeof en> = {
         },
         correctRateError: 'Corrija o erro de taxa e tente novamente.',
         AskToExplain: `. <a href="${CONST.CONCIERGE_EXPLAIN_LINK_PATH}">Explicar<sparkles-icon/></a>`,
+        conciergeAutoMatchedVendor: ({vendorName}: {vendorName: string}) => `Concierge associou esta despesa ao fornecedor <strong>${vendorName}</strong>`,
         duplicateNonDefaultWorkspacePerDiemError: 'Você não pode duplicar despesas de diárias entre espaços de trabalho porque as tarifas podem variar entre eles.',
         rulesModifiedFields: {
             reimbursable: (value: boolean) => (value ? 'marcou a despesa como "reembolsável"' : 'marcou a despesa como “não reembolsável”'),
diff --git a/src/languages/zh-hans.ts b/src/languages/zh-hans.ts
index df924a6431e6..141c6e4c991e 100644
--- a/src/languages/zh-hans.ts
+++ b/src/languages/zh-hans.ts
@@ -1602,6 +1602,7 @@ const translations: TranslationDeepObject<typeof en> = {
         },
         correctRateError: '修复费率错误后请重试。',
         AskToExplain: `。<a href="${CONST.CONCIERGE_EXPLAIN_LINK_PATH}">说明<sparkles-icon/></a>`,
+        conciergeAutoMatchedVendor: ({vendorName}: {vendorName: string}) => `Concierge 已将此支出匹配到<strong>${vendorName}</strong>`,
         duplicateNonDefaultWorkspacePerDiemError: '您无法在不同工作区之间复制每日津贴报销，因为各工作区的补贴标准可能不同。',
         rulesModifiedFields: {
             reimbursable: (value: boolean) => (value ? '将该报销单标记为“可报销”' : '将该报销单标记为“不可报销”'),
diff --git a/src/pages/inbox/report/actionContents/ActionContentRouter.tsx b/src/pages/inbox/report/actionContents/ActionContentRouter.tsx
index 5cab7d5f5f75..212520a4443b 100644
--- a/src/pages/inbox/report/actionContents/ActionContentRouter.tsx
+++ b/src/pages/inbox/report/actionContents/ActionContentRouter.tsx
@@ -49,6 +49,7 @@ import ApprovalFlowContent, {isApprovalFlowAction} from './ApprovalFlowContent';
 import CardBrokenConnectionContent from './CardBrokenConnectionContent';
 import ChatMessageContent from './ChatMessageContent';
 import ChatTransactionPreview from './ChatTransactionPreview';
+import ConciergeAutoMatchVendorContent from './ConciergeAutoMatchVendorContent';
 import ConfirmWhisperContent from './ConfirmWhisperContent';
 import FraudAlertContent from './FraudAlertContent';
 import IntegrationSyncFailedMessage from './IntegrationSyncFailedMessage';
@@ -256,6 +257,14 @@ function ActionContentRouter({
             />
         );
     }
+    if (action.actionName === CONST.REPORT.ACTIONS.TYPE.CONCIERGE_AUTO_MATCH_VENDOR) {
+        return (
+            <ConciergeAutoMatchVendorContent
+                action={action}
+                originalReport={originalReport}
+            />
+        );
+    }
     if (isApprovalFlowAction(action)) {
         return (
             <ApprovalFlowContent
diff --git a/src/pages/inbox/report/actionContents/ConciergeAutoMatchVendorContent.tsx b/src/pages/inbox/report/actionContents/ConciergeAutoMatchVendorContent.tsx
new file mode 100644
index 000000000000..b4e5f0861e0e
--- /dev/null
+++ b/src/pages/inbox/report/actionContents/ConciergeAutoMatchVendorContent.tsx
@@ -0,0 +1,37 @@
+import React from 'react';
+import type {OnyxEntry} from 'react-native-onyx';
+import useLocalize from '@hooks/useLocalize';
+import useOnyx from '@hooks/useOnyx';
+import getNonEmptyStringOnyxID from '@libs/getNonEmptyStringOnyxID';
+import {getOriginalMessage} from '@libs/ReportActionsUtils';
+import ReportActionItemMessageWithExplain from '@pages/inbox/report/ReportActionItemMessageWithExplain';
+import CONST from '@src/CONST';
+import ONYXKEYS from '@src/ONYXKEYS';
+import type {Report, ReportAction} from '@src/types/onyx';
+
+type ConciergeAutoMatchVendorContentProps = {
+    action: ReportAction;
+    originalReport: OnyxEntry<Report>;
+};
+
+function ConciergeAutoMatchVendorContent({action, originalReport}: ConciergeAutoMatchVendorContentProps) {
+    const {translate} = useLocalize();
+    const [childReport] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${getNonEmptyStringOnyxID(action.childReportID)}`);
+
+    const originalMessage = getOriginalMessage(action);
+    const vendorName = originalMessage && typeof originalMessage === 'object' && 'vendorName' in originalMessage ? (originalMessage.vendorName ?? '') : '';
+    const message = translate('iou.conciergeAutoMatchedVendor', {vendorName});
+
+    return (
+        <ReportActionItemMessageWithExplain
+            message={message}
+            action={action}
+            childReport={childReport}
+            originalReport={originalReport}
+        />
+    );
+}
+
+ConciergeAutoMatchVendorContent.displayName = 'ConciergeAutoMatchVendorContent';
+
+export default ConciergeAutoMatchVendorContent;
diff --git a/src/types/onyx/OriginalMessage.ts b/src/types/onyx/OriginalMessage.ts
index 0bc0e4fb9975..ddcffb4d25c3 100644
--- a/src/types/onyx/OriginalMessage.ts
+++ b/src/types/onyx/OriginalMessage.ts
@@ -889,6 +889,15 @@ type OriginalMessageModifiedExpense = {
     reasoning?: string;
 };
 
+/** Model of `concierge auto match vendor` report action — emitted on the transaction thread when the PHP fuzzy matcher auto-matches a non-reimbursable expense to a QBO vendor. */
+type OriginalMessageConciergeAutoMatchVendor = {
+    /** Display name of the matched vendor */
+    vendorName?: string;
+
+    /** LLM-consumable explanation of why this vendor was matched — surfaced behind the "Explain" link */
+    reasoning?: string;
+};
+
 /** Policy rules modified fields */
 type PolicyRulesModifiedFields = {
     /** The value that the merchant was changed to */
@@ -1527,6 +1536,7 @@ type OriginalMessageMap = {
     [CONST.REPORT.ACTIONS.TYPE.MARKED_REIMBURSED]: OriginalMessageMarkedReimbursed;
     [CONST.REPORT.ACTIONS.TYPE.MERGED_WITH_CASH_TRANSACTION]: never;
     [CONST.REPORT.ACTIONS.TYPE.MODIFIED_EXPENSE]: OriginalMessageModifiedExpense;
+    [CONST.REPORT.ACTIONS.TYPE.CONCIERGE_AUTO_MATCH_VENDOR]: OriginalMessageConciergeAutoMatchVendor;
     [CONST.REPORT.ACTIONS.TYPE.MOVED]: OriginalMessageMoved;
     [CONST.REPORT.ACTIONS.TYPE.MOVED_TRANSACTION]: OriginalMessageMovedTransaction;
     [CONST.REPORT.ACTIONS.TYPE.UNREPORTED_TRANSACTION]: OriginalMessageUnreportedTransaction;
@@ -1610,6 +1620,7 @@ export type {
     OriginalMessageChangeLog,
     JoinWorkspaceResolution,
     OriginalMessageModifiedExpense,
+    OriginalMessageConciergeAutoMatchVendor,
     OriginalMessageExportIntegration,
     IssueNewCardOriginalMessage,
     OriginalMessageChangePolicy,

From 0064c86f2f4e2027fb7a8be73f8bcdb656e148c7 Mon Sep 17 00:00:00 2001
From: Alex Beaman <alexbeaman@expensify.com>
Date: Wed, 27 May 2026 14:27:33 -0600
Subject: [PATCH 032/435] Phase 3 cleanup: drop deprecated backTo from
 MONEY_REQUEST_STEP_VENDOR

Removes getUrlWithBackToParam usage from the new route (the deprecated
backTo pattern, per contributingGuides/NAVIGATION.md) and removes the
unused CONST import in ConciergeAutoMatchVendorContent. Navigation back
from the RHP just closes the modal, returning to the previous view.
---
 src/ROUTES.ts                                          |  4 ++--
 src/components/ReportActionItem/MoneyRequestView.tsx   | 10 +---------
 src/libs/Navigation/types.ts                           |  2 --
 .../actionContents/ConciergeAutoMatchVendorContent.tsx |  1 -
 src/pages/iou/request/step/IOURequestStepVendor.tsx    |  4 ++--
 5 files changed, 5 insertions(+), 16 deletions(-)

diff --git a/src/ROUTES.ts b/src/ROUTES.ts
index f8ce0e5aee4d..bd4b6283a66a 100644
--- a/src/ROUTES.ts
+++ b/src/ROUTES.ts
@@ -1638,12 +1638,12 @@ const ROUTES = {
     },
     MONEY_REQUEST_STEP_VENDOR: {
         route: ':action/:iouType/vendor/:transactionID/:reportID/:reportActionID?',
-        getRoute: (action: IOUAction, iouType: IOUType, transactionID: string | undefined, reportID: string | undefined, backTo = '', reportActionID?: string) => {
+        getRoute: (action: IOUAction, iouType: IOUType, transactionID: string | undefined, reportID: string | undefined, reportActionID?: string) => {
             if (!transactionID || !reportID) {
                 Log.warn('Invalid transactionID or reportID is used to build the MONEY_REQUEST_STEP_VENDOR route');
             }
 
-            return getUrlWithBackToParam(`${action as string}/${iouType as string}/vendor/${transactionID}/${reportID}${reportActionID ? `/${reportActionID}` : ''}`, backTo);
+            return `${action as string}/${iouType as string}/vendor/${transactionID}/${reportID}${reportActionID ? `/${reportActionID}` : ''}` as const;
         },
     },
     MONEY_REQUEST_ATTENDEE: {
diff --git a/src/components/ReportActionItem/MoneyRequestView.tsx b/src/components/ReportActionItem/MoneyRequestView.tsx
index e3015041af29..5c616f2e7508 100644
--- a/src/components/ReportActionItem/MoneyRequestView.tsx
+++ b/src/components/ReportActionItem/MoneyRequestView.tsx
@@ -1139,15 +1139,7 @@ function MoneyRequestView({
                                 if (!transactionThreadReport?.reportID) {
                                     return;
                                 }
-                                Navigation.navigate(
-                                    ROUTES.MONEY_REQUEST_STEP_VENDOR.getRoute(
-                                        CONST.IOU.ACTION.EDIT,
-                                        iouType,
-                                        transaction.transactionID,
-                                        transactionThreadReport.reportID,
-                                        Navigation.getActiveRoute(),
-                                    ),
-                                );
+                                Navigation.navigate(ROUTES.MONEY_REQUEST_STEP_VENDOR.getRoute(CONST.IOU.ACTION.EDIT, iouType, transaction.transactionID, transactionThreadReport.reportID));
                             }}
                             brickRoadIndicator={getErrorForField('vendor') ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR : undefined}
                             errorText={getErrorForField('vendor')}
diff --git a/src/libs/Navigation/types.ts b/src/libs/Navigation/types.ts
index 8ccf18e4ea58..397deb024220 100644
--- a/src/libs/Navigation/types.ts
+++ b/src/libs/Navigation/types.ts
@@ -1890,8 +1890,6 @@ type MoneyRequestNavigatorParamList = {
         transactionID: string;
         reportActionID: string;
         reportID: string;
-        // eslint-disable-next-line no-restricted-syntax -- `backTo` usages in this file are legacy. Do not add new `backTo` params to screens. See contributingGuides/NAVIGATION.md
-        backTo: Routes;
     };
     [SCREENS.MONEY_REQUEST.STEP_CATEGORY_CREATE]: {
         action: IOUAction;
diff --git a/src/pages/inbox/report/actionContents/ConciergeAutoMatchVendorContent.tsx b/src/pages/inbox/report/actionContents/ConciergeAutoMatchVendorContent.tsx
index b4e5f0861e0e..a5c9b2fe999e 100644
--- a/src/pages/inbox/report/actionContents/ConciergeAutoMatchVendorContent.tsx
+++ b/src/pages/inbox/report/actionContents/ConciergeAutoMatchVendorContent.tsx
@@ -5,7 +5,6 @@ import useOnyx from '@hooks/useOnyx';
 import getNonEmptyStringOnyxID from '@libs/getNonEmptyStringOnyxID';
 import {getOriginalMessage} from '@libs/ReportActionsUtils';
 import ReportActionItemMessageWithExplain from '@pages/inbox/report/ReportActionItemMessageWithExplain';
-import CONST from '@src/CONST';
 import ONYXKEYS from '@src/ONYXKEYS';
 import type {Report, ReportAction} from '@src/types/onyx';
 
diff --git a/src/pages/iou/request/step/IOURequestStepVendor.tsx b/src/pages/iou/request/step/IOURequestStepVendor.tsx
index 94dd9d49971e..3742ee6e28c0 100644
--- a/src/pages/iou/request/step/IOURequestStepVendor.tsx
+++ b/src/pages/iou/request/step/IOURequestStepVendor.tsx
@@ -31,7 +31,7 @@ type IOURequestStepVendorProps = WithWritableReportOrNotFoundProps<typeof SCREEN
 function IOURequestStepVendor({
     report,
     route: {
-        params: {action, iouType, transactionID, reportActionID, backTo},
+        params: {action, iouType, transactionID, reportActionID},
     },
     transaction,
 }: IOURequestStepVendorProps) {
@@ -69,7 +69,7 @@ function IOURequestStepVendor({
     const shouldShowNotFoundPage = useShowNotFoundPageInIOUStep(action, iouType, reportActionID, report, transaction) || !isFeatureAvailable;
 
     const navigateBack = () => {
-        Navigation.goBack(backTo);
+        Navigation.goBack();
     };
 
     const selectVendor = (item: VendorListItem) => {

From e35837c7da711ce10b8774ec0e1f6bde48c9ea70 Mon Sep 17 00:00:00 2001
From: "James Dean (via MelvinBot)" <infra+melvinbot@expensify.com>
Date: Thu, 28 May 2026 01:16:15 +0000
Subject: [PATCH 033/435] Update validateAccount title copy

Remove 'to continue using Expensify' from the validateAccount
onboarding checklist title in both en.ts and es.ts.

Co-authored-by: James Dean <jamesdeanexpensify@users.noreply.github.com>
---
 src/languages/en.ts | 2 +-
 src/languages/es.ts | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/languages/en.ts b/src/languages/en.ts
index 430175e6c170..ec1ee3f56a8c 100644
--- a/src/languages/en.ts
+++ b/src/languages/en.ts
@@ -994,7 +994,7 @@ const translations = {
                 cta: 'Review',
             },
             validateAccount: {
-                title: 'Validate your account to continue using Expensify',
+                title: 'Validate your account',
                 subtitle: 'Account',
                 cta: 'Validate',
             },
diff --git a/src/languages/es.ts b/src/languages/es.ts
index ef5cd5023b18..98028e852668 100644
--- a/src/languages/es.ts
+++ b/src/languages/es.ts
@@ -906,7 +906,7 @@ const translations: TranslationDeepObject<typeof en> = {
                 cta: 'Revisar',
             },
             validateAccount: {
-                title: 'Valida tu cuenta para continuar usando Expensify',
+                title: 'Valida tu cuenta',
                 subtitle: 'Cuenta',
                 cta: 'Validar',
             },

From 1a7e29734fb5cdb5793d3616d985e9ac3fc26a3f Mon Sep 17 00:00:00 2001
From: "James Dean (via MelvinBot)" <infra+melvinbot@expensify.com>
Date: Thu, 28 May 2026 01:23:29 +0000
Subject: [PATCH 034/435] Apply Polyglot Parrot translations for
 validateAccount title

Remove 'to continue using Expensify' suffix from validateAccount
title across all remaining language files (nl, pt-BR, ja, de, fr,
zh-hans, pl, it) to match the simplified en.ts and es.ts copy.

Co-authored-by: James Dean <jamesdeanexpensify@users.noreply.github.com>
---
 src/languages/de.ts      | 2 +-
 src/languages/fr.ts      | 2 +-
 src/languages/it.ts      | 2 +-
 src/languages/ja.ts      | 2 +-
 src/languages/nl.ts      | 2 +-
 src/languages/pl.ts      | 2 +-
 src/languages/pt-BR.ts   | 2 +-
 src/languages/zh-hans.ts | 2 +-
 8 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/src/languages/de.ts b/src/languages/de.ts
index 6a38095edd8d..346fa4b64ebd 100644
--- a/src/languages/de.ts
+++ b/src/languages/de.ts
@@ -951,7 +951,7 @@ const translations: TranslationDeepObject<typeof en> = {
                 title: ({cardName}: {cardName?: string}) => (cardName ? `Verbindung der persönlichen Karte ${cardName} reparieren` : 'Verbindung der persönlichen Karte reparieren'),
                 subtitle: 'Wallet',
             },
-            validateAccount: {title: 'Bestätigen Sie Ihr Konto, um Expensify weiter zu verwenden', subtitle: 'Konto', cta: 'Bestätigen'},
+            validateAccount: {title: 'Bestätigen Sie Ihr Konto', subtitle: 'Konto', cta: 'Bestätigen'},
             fixFailedBilling: {title: 'Wir konnten Ihre hinterlegte Karte nicht belasten', subtitle: 'Abonnement'},
             unlockBankAccount: {
                 workspaceTitle: 'Ihr Geschäftskonto wurde gesperrt',
diff --git a/src/languages/fr.ts b/src/languages/fr.ts
index 8b1470f46f90..030cfb7413f1 100644
--- a/src/languages/fr.ts
+++ b/src/languages/fr.ts
@@ -954,7 +954,7 @@ const translations: TranslationDeepObject<typeof en> = {
                 title: ({cardName}: {cardName?: string}) => (cardName ? `Réparer la connexion de la carte personnelle ${cardName}` : 'Corriger la connexion de la carte personnelle'),
                 subtitle: 'Portefeuille',
             },
-            validateAccount: {title: 'Validez votre compte pour continuer à utiliser Expensify', subtitle: 'Compte', cta: 'Valider'},
+            validateAccount: {title: 'Validez votre compte', subtitle: 'Compte', cta: 'Valider'},
             fixFailedBilling: {title: 'Nous n’avons pas pu débiter votre carte enregistrée', subtitle: 'Abonnement'},
             unlockBankAccount: {
                 workspaceTitle: 'Votre compte bancaire professionnel a été verrouillé',
diff --git a/src/languages/it.ts b/src/languages/it.ts
index 05e7bda1109b..db4a1ec4ae3a 100644
--- a/src/languages/it.ts
+++ b/src/languages/it.ts
@@ -952,7 +952,7 @@ const translations: TranslationDeepObject<typeof en> = {
                 title: ({cardName}: {cardName?: string}) => (cardName ? `Correggi la connessione della carta personale ${cardName}` : 'Correggi connessione carta personale'),
                 subtitle: 'Portafoglio',
             },
-            validateAccount: {title: 'Conferma il tuo account per continuare a usare Expensify', subtitle: 'Account', cta: 'Conferma'},
+            validateAccount: {title: 'Conferma il tuo account', subtitle: 'Account', cta: 'Conferma'},
             fixFailedBilling: {title: 'Non abbiamo potuto addebitare la carta salvata nel profilo', subtitle: 'Abbonamento'},
             unlockBankAccount: {
                 workspaceTitle: 'Il conto bancario della tua azienda è stato bloccato',
diff --git a/src/languages/ja.ts b/src/languages/ja.ts
index 52f924cbee80..e5e2ed24f429 100644
--- a/src/languages/ja.ts
+++ b/src/languages/ja.ts
@@ -935,7 +935,7 @@ const translations: TranslationDeepObject<typeof en> = {
                 subtitle: ({policyName}: {policyName: string}) => `${policyName} > 会計`,
             },
             fixPersonalCardConnection: {title: ({cardName}: {cardName?: string}) => (cardName ? `${cardName}個人カードの接続を修正` : '個人カードの連携を修正'), subtitle: 'ウォレット'},
-            validateAccount: {title: 'Expensify を引き続きご利用いただくには、アカウントを認証してください', subtitle: 'アカウント', cta: '検証する'},
+            validateAccount: {title: 'アカウントを認証してください', subtitle: 'アカウント', cta: '検証する'},
             fixFailedBilling: {title: '登録されているカードから請求できませんでした', subtitle: 'サブスクリプション'},
             unlockBankAccount: {
                 workspaceTitle: 'ビジネス用銀行口座がロックされました',
diff --git a/src/languages/nl.ts b/src/languages/nl.ts
index 0882a062989d..a0a76d3a9b4b 100644
--- a/src/languages/nl.ts
+++ b/src/languages/nl.ts
@@ -950,7 +950,7 @@ const translations: TranslationDeepObject<typeof en> = {
                 title: ({cardName}: {cardName?: string}) => (cardName ? `Verbinding van persoonlijke kaart ${cardName} herstellen` : 'Verbinding persoonlijke kaart herstellen'),
                 subtitle: 'Portemonnee',
             },
-            validateAccount: {title: 'Valideer je account om Expensify te blijven gebruiken', subtitle: 'Account', cta: 'Valideren'},
+            validateAccount: {title: 'Valideer je account', subtitle: 'Account', cta: 'Valideren'},
             fixFailedBilling: {title: 'We konden je kaart in ons bestand niet belasten', subtitle: 'Abonnement'},
             unlockBankAccount: {
                 workspaceTitle: 'Je zakelijke bankrekening is geblokkeerd',
diff --git a/src/languages/pl.ts b/src/languages/pl.ts
index 584f54a50230..a3807f7f905f 100644
--- a/src/languages/pl.ts
+++ b/src/languages/pl.ts
@@ -952,7 +952,7 @@ const translations: TranslationDeepObject<typeof en> = {
                 title: ({cardName}: {cardName?: string}) => (cardName ? `Napraw połączenie z prywatną kartą ${cardName}` : 'Napraw połączenie karty prywatnej'),
                 subtitle: 'Portfel',
             },
-            validateAccount: {title: 'Zweryfikuj swoje konto, aby dalej korzystać z Expensify', subtitle: 'Konto', cta: 'Zatwierdź'},
+            validateAccount: {title: 'Zweryfikuj swoje konto', subtitle: 'Konto', cta: 'Zatwierdź'},
             fixFailedBilling: {title: 'Nie mogliśmy obciążyć zapisanej karty', subtitle: 'Subskrypcja'},
             unlockBankAccount: {
                 workspaceTitle: 'Twoje firmowe konto bankowe zostało zablokowane',
diff --git a/src/languages/pt-BR.ts b/src/languages/pt-BR.ts
index f97f6980e7df..5c0c7492029a 100644
--- a/src/languages/pt-BR.ts
+++ b/src/languages/pt-BR.ts
@@ -950,7 +950,7 @@ const translations: TranslationDeepObject<typeof en> = {
                 title: ({cardName}: {cardName?: string}) => (cardName ? `Corrigir conexão do cartão pessoal ${cardName}` : 'Corrigir conexão do cartão pessoal'),
                 subtitle: 'Carteira',
             },
-            validateAccount: {title: 'Valide sua conta para continuar usando o Expensify', subtitle: 'Conta', cta: 'Validar'},
+            validateAccount: {title: 'Valide sua conta', subtitle: 'Conta', cta: 'Validar'},
             fixFailedBilling: {title: 'Não foi possível cobrar o cartão cadastrado', subtitle: 'Assinatura'},
             unlockBankAccount: {
                 workspaceTitle: 'Sua conta bancária comercial foi bloqueada',
diff --git a/src/languages/zh-hans.ts b/src/languages/zh-hans.ts
index 585e8461e2a2..8031299b0ab7 100644
--- a/src/languages/zh-hans.ts
+++ b/src/languages/zh-hans.ts
@@ -918,7 +918,7 @@ const translations: TranslationDeepObject<typeof en> = {
                 defaultSubtitle: '工作区',
                 subtitle: ({policyName}: {policyName: string}) => `${policyName} > 会计`,
             },
-            validateAccount: {title: '验证您的账户以继续使用 Expensify', subtitle: '账户', cta: '验证'},
+            validateAccount: {title: '验证您的账户', subtitle: '账户', cta: '验证'},
             fixFailedBilling: {title: '我们无法向您档案中的银行卡收费', subtitle: '订阅'},
             unlockBankAccount: {
                 workspaceTitle: '您的企业银行账户已被锁定',

From d228bd14cfe02775591c05f06d1904d74cf01102 Mon Sep 17 00:00:00 2001
From: "Carlos Alvarez (via MelvinBot)" <infra+melvinbot@expensify.com>
Date: Thu, 28 May 2026 02:25:21 +0000
Subject: [PATCH 035/435] Increase recent attendees NVP max size from 5 to 40

The recentAttendees NVP was capped at MAX_RECENT_REPORTS_TO_SHOW (5),
which is a UI display constant. This adds a separate MAX_RECENT_ATTENDEES
constant (40) for the NVP storage cap, increasing the pool of attendees
searchable in the New Expensify attendees dropdown.

Co-authored-by: Carlos Alvarez <cead22@users.noreply.github.com>
---
 src/CONST/index.ts                              | 1 +
 src/libs/actions/IOU/UpdateMoneyRequest.ts      | 2 +-
 tests/actions/IOUTest/UpdateMoneyRequestTest.ts | 4 ++--
 3 files changed, 4 insertions(+), 3 deletions(-)

diff --git a/src/CONST/index.ts b/src/CONST/index.ts
index db9567f28314..1556bf9ec773 100644
--- a/src/CONST/index.ts
+++ b/src/CONST/index.ts
@@ -3596,6 +3596,7 @@ const CONST = {
 
     IOU: {
         MAX_RECENT_REPORTS_TO_SHOW: 5,
+        MAX_RECENT_ATTENDEES: 40,
         // This will guranatee that the quantity input will not exceed 9,007,199,254,740,991 (Number.MAX_SAFE_INTEGER).
         QUANTITY_MAX_LENGTH: 12,
         // This is the transactionID used when going through the create expense flow so that it mimics a real transaction (like the edit flow)
diff --git a/src/libs/actions/IOU/UpdateMoneyRequest.ts b/src/libs/actions/IOU/UpdateMoneyRequest.ts
index 5f9b15b60312..3eb26503dc08 100644
--- a/src/libs/actions/IOU/UpdateMoneyRequest.ts
+++ b/src/libs/actions/IOU/UpdateMoneyRequest.ts
@@ -1551,7 +1551,7 @@ function getUpdateMoneyRequestParams(params: GetUpdateMoneyRequestParamsType): U
                 getRecentAttendees(),
                 // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
                 (attendee) => attendee.email || attendee.displayName,
-            ).slice(0, CONST.IOU.MAX_RECENT_REPORTS_TO_SHOW),
+            ).slice(0, CONST.IOU.MAX_RECENT_ATTENDEES),
         });
     }
 
diff --git a/tests/actions/IOUTest/UpdateMoneyRequestTest.ts b/tests/actions/IOUTest/UpdateMoneyRequestTest.ts
index c63112d19646..b1f732cbbe95 100644
--- a/tests/actions/IOUTest/UpdateMoneyRequestTest.ts
+++ b/tests/actions/IOUTest/UpdateMoneyRequestTest.ts
@@ -679,7 +679,7 @@ describe('actions/IOU/UpdateMoneyRequest', () => {
             });
             await waitForBatchedUpdates();
 
-            // Then the recent attendees should be updated with a maximum of 5 attendees
+            // Then all 6 recent attendees should be stored (below the max of 40)
             const recentAttendees = await new Promise<OnyxEntry<Attendee[]>>((resolve) => {
                 const connection = Onyx.connectWithoutView({
                     key: ONYXKEYS.NVP_RECENT_ATTENDEES,
@@ -689,7 +689,7 @@ describe('actions/IOU/UpdateMoneyRequest', () => {
                     },
                 });
             });
-            expect(recentAttendees?.length).toBe(CONST.IOU.MAX_RECENT_REPORTS_TO_SHOW);
+            expect(recentAttendees?.length).toBe(6);
         });
 
         it('should keep displayName-only attendees in recent attendees', async () => {

From 00199797ed225335be787e623fcd7e25d528c0c8 Mon Sep 17 00:00:00 2001
From: "Carlos Alvarez (via MelvinBot)" <infra+melvinbot@expensify.com>
Date: Thu, 28 May 2026 02:38:58 +0000
Subject: [PATCH 036/435] Add blank line after MAX_RECENT_ATTENDEES constant

Co-authored-by: Carlos Alvarez <cead22@users.noreply.github.com>
---
 src/CONST/index.ts | 1 +
 1 file changed, 1 insertion(+)

diff --git a/src/CONST/index.ts b/src/CONST/index.ts
index 1556bf9ec773..bb06f3e49ab7 100644
--- a/src/CONST/index.ts
+++ b/src/CONST/index.ts
@@ -3597,6 +3597,7 @@ const CONST = {
     IOU: {
         MAX_RECENT_REPORTS_TO_SHOW: 5,
         MAX_RECENT_ATTENDEES: 40,
+
         // This will guranatee that the quantity input will not exceed 9,007,199,254,740,991 (Number.MAX_SAFE_INTEGER).
         QUANTITY_MAX_LENGTH: 12,
         // This is the transactionID used when going through the create expense flow so that it mimics a real transaction (like the edit flow)

From 0700258610b32ea45dfb4c1920b758420e0478d6 Mon Sep 17 00:00:00 2001
From: Adam Grzybowski <adam.grzybowski@swmansion.com>
Date: Thu, 28 May 2026 17:01:05 +0200
Subject: [PATCH 037/435] Add review expenses row to ForYouSection

---
 src/ONYXKEYS.ts                               |   2 +
 src/languages/en.ts                           |   1 +
 .../OnyxDerived/ONYX_DERIVED_VALUES.ts        |   2 +
 .../OnyxDerived/configs/flaggedExpenses.ts    |  87 ++++++
 src/pages/home/ForYouSection/index.tsx        |  62 +++-
 src/selectors/Todos.ts                        |  47 +++-
 src/types/onyx/DerivedValues.ts               |  18 ++
 src/types/onyx/index.ts                       |   2 +
 tests/ui/ForYouSectionTest.tsx                | 193 ++++++++++++-
 tests/unit/OnyxDerived/flaggedExpensesTest.ts | 264 ++++++++++++++++++
 tests/unit/selectors/TodosTest.ts             |  70 ++++-
 11 files changed, 733 insertions(+), 15 deletions(-)
 create mode 100644 src/libs/actions/OnyxDerived/configs/flaggedExpenses.ts
 create mode 100644 tests/unit/OnyxDerived/flaggedExpensesTest.ts

diff --git a/src/ONYXKEYS.ts b/src/ONYXKEYS.ts
index 8e30de4e3f7b..9ac7bb02a226 100755
--- a/src/ONYXKEYS.ts
+++ b/src/ONYXKEYS.ts
@@ -1159,6 +1159,7 @@ const ONYXKEYS = {
         TODOS: 'todos',
         RAM_ONLY_SORTED_REPORT_ACTIONS: 'sortedReportActions',
         OPEN_AND_SUBMITTED_REPORTS_BY_POLICY_ID: 'openAndSubmittedReportsByPolicyID',
+        FLAGGED_EXPENSES: 'flaggedExpenses',
     },
 
     /** Stores HybridApp specific state required to interoperate with OldDot */
@@ -1637,6 +1638,7 @@ type OnyxDerivedValuesMapping = {
     [ONYXKEYS.DERIVED.TODOS]: OnyxTypes.TodosDerivedValue;
     [ONYXKEYS.DERIVED.RAM_ONLY_SORTED_REPORT_ACTIONS]: OnyxTypes.SortedReportActionsDerivedValue;
     [ONYXKEYS.DERIVED.OPEN_AND_SUBMITTED_REPORTS_BY_POLICY_ID]: OnyxTypes.OpenAndSubmittedReportsByPolicyIDDerivedValue;
+    [ONYXKEYS.DERIVED.FLAGGED_EXPENSES]: OnyxTypes.FlaggedExpensesDerivedValue;
 };
 
 type OnyxValues = OnyxValuesMapping & OnyxCollectionValuesMapping & OnyxFormValuesMapping & OnyxFormDraftValuesMapping & OnyxDerivedValuesMapping;
diff --git a/src/languages/en.ts b/src/languages/en.ts
index 88e0bbe8b673..f30a79060920 100644
--- a/src/languages/en.ts
+++ b/src/languages/en.ts
@@ -1037,6 +1037,7 @@ const translations = {
             menuItemDescription: 'See what Expensify can do in 2 min',
         },
         forYouSection: {
+            reviewExpenses: ({count}: {count: number}) => `Review ${count} ${count === 1 ? 'expense' : 'expenses'}`,
             submit: ({count}: {count: number}) => `Submit ${count} ${count === 1 ? 'report' : 'reports'}`,
             approve: ({count}: {count: number}) => `Approve ${count} ${count === 1 ? 'report' : 'reports'}`,
             pay: ({count}: {count: number}) => `Pay ${count} ${count === 1 ? 'report' : 'reports'}`,
diff --git a/src/libs/actions/OnyxDerived/ONYX_DERIVED_VALUES.ts b/src/libs/actions/OnyxDerived/ONYX_DERIVED_VALUES.ts
index 161c7f72ecf8..63d8bfd1478c 100644
--- a/src/libs/actions/OnyxDerived/ONYX_DERIVED_VALUES.ts
+++ b/src/libs/actions/OnyxDerived/ONYX_DERIVED_VALUES.ts
@@ -1,6 +1,7 @@
 import type {ValueOf} from 'type-fest';
 import ONYXKEYS from '@src/ONYXKEYS';
 import cardFeedErrorsConfig from './configs/cardFeedErrors';
+import flaggedExpensesConfig from './configs/flaggedExpenses';
 import nonPersonalAndWorkspaceCardListConfig from './configs/nonPersonalAndWorkspaceCardList';
 import openAndSubmittedReportsByPolicyIDConfig from './configs/openAndSubmittedReportsByPolicyID';
 import outstandingReportsByPolicyIDConfig from './configs/outstandingReportsByPolicyID';
@@ -27,6 +28,7 @@ const ONYX_DERIVED_VALUES = {
     [ONYXKEYS.DERIVED.TODOS]: todosConfig,
     [ONYXKEYS.DERIVED.RAM_ONLY_SORTED_REPORT_ACTIONS]: sortedReportActionsConfig,
     [ONYXKEYS.DERIVED.OPEN_AND_SUBMITTED_REPORTS_BY_POLICY_ID]: openAndSubmittedReportsByPolicyIDConfig,
+    [ONYXKEYS.DERIVED.FLAGGED_EXPENSES]: flaggedExpensesConfig,
 } as const satisfies {
     // eslint-disable-next-line @typescript-eslint/no-explicit-any
     [Key in ValueOf<typeof ONYXKEYS.DERIVED>]: OnyxDerivedValueConfig<Key, any>;
diff --git a/src/libs/actions/OnyxDerived/configs/flaggedExpenses.ts b/src/libs/actions/OnyxDerived/configs/flaggedExpenses.ts
new file mode 100644
index 000000000000..e555f50f3107
--- /dev/null
+++ b/src/libs/actions/OnyxDerived/configs/flaggedExpenses.ts
@@ -0,0 +1,87 @@
+import createOnyxDerivedValueConfig from '@userActions/OnyxDerived/createOnyxDerivedValueConfig';
+import CONST from '@src/CONST';
+import ONYXKEYS from '@src/ONYXKEYS';
+import type {FlaggedExpensesDerivedValue} from '@src/types/onyx';
+import type Report from '@src/types/onyx/Report';
+import type TransactionViolations from '@src/types/onyx/TransactionViolation';
+
+type FlaggedExpenseEntry = FlaggedExpensesDerivedValue['flaggedExpenses'][number];
+
+const EMPTY_VALUE: FlaggedExpensesDerivedValue = {flaggedExpenses: []};
+
+/**
+ * Returns true when this report is an OPEN/OPEN expense report owned by the current user.
+ *
+ * `currentUserAccountID` is required. Callers should pass `session?.accountID ?? CONST.DEFAULT_NUMBER_ID`
+ * so that the ownership check fails closed when the session is not yet populated (no real ownerAccountID is 0).
+ */
+function isCurrentUserOpenExpenseReport(report: Report | null | undefined, currentUserAccountID: number): boolean {
+    if (!report) {
+        return false;
+    }
+    if (report.type !== CONST.REPORT.TYPE.EXPENSE) {
+        return false;
+    }
+    if (report.ownerAccountID !== currentUserAccountID) {
+        return false;
+    }
+    return report.stateNum === CONST.REPORT.STATE_NUM.OPEN && report.statusNum === CONST.REPORT.STATUS_NUM.OPEN;
+}
+
+/**
+ * Returns true when the given violation list has at least one entry that should surface in the
+ * `Review X expenses` row: a transaction-level violation that the user can act on. Violations
+ * marked `showInReview === false` and report-field violations (`fieldRequired`) are excluded.
+ */
+function hasReviewableViolation(violations: TransactionViolations | null | undefined): boolean {
+    if (!violations || violations.length === 0) {
+        return false;
+    }
+
+    return violations.some((violation) => {
+        if (!violation) {
+            return false;
+        }
+        if (violation.showInReview === false) {
+            return false;
+        }
+        if (violation.name === CONST.REPORT_VIOLATIONS.FIELD_REQUIRED) {
+            return false;
+        }
+        return true;
+    });
+}
+
+export default createOnyxDerivedValueConfig({
+    key: ONYXKEYS.DERIVED.FLAGGED_EXPENSES,
+    dependencies: [ONYXKEYS.COLLECTION.REPORT, ONYXKEYS.COLLECTION.TRANSACTION, ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS, ONYXKEYS.SESSION],
+    compute: ([allReports, allTransactions, allTransactionViolations, session]) => {
+        if (!allReports || !allTransactions) {
+            return EMPTY_VALUE;
+        }
+
+        const currentUserAccountID = session?.accountID ?? CONST.DEFAULT_NUMBER_ID;
+        const flaggedExpenses: FlaggedExpenseEntry[] = [];
+
+        for (const transactionKey of Object.keys(allTransactions)) {
+            const transaction = allTransactions[transactionKey];
+            if (!transaction?.transactionID || !transaction.reportID) {
+                continue;
+            }
+
+            const report = allReports[`${ONYXKEYS.COLLECTION.REPORT}${transaction.reportID}`];
+            if (!isCurrentUserOpenExpenseReport(report, currentUserAccountID)) {
+                continue;
+            }
+
+            const violations = allTransactionViolations?.[`${ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS}${transaction.transactionID}`];
+            if (!hasReviewableViolation(violations)) {
+                continue;
+            }
+
+            flaggedExpenses.push({transactionID: transaction.transactionID, reportID: transaction.reportID});
+        }
+
+        return {flaggedExpenses};
+    },
+});
diff --git a/src/pages/home/ForYouSection/index.tsx b/src/pages/home/ForYouSection/index.tsx
index ac4074b2224c..f4f7d537ffd7 100644
--- a/src/pages/home/ForYouSection/index.tsx
+++ b/src/pages/home/ForYouSection/index.tsx
@@ -15,7 +15,7 @@ import CONST from '@src/CONST';
 import ONYXKEYS from '@src/ONYXKEYS';
 import ROUTES from '@src/ROUTES';
 import {accountIDSelector} from '@src/selectors/Session';
-import todosReportCountsSelector, {EMPTY_TODOS_SINGLE_REPORT_IDS, todosSingleReportIDsSelector} from '@src/selectors/Todos';
+import todosReportCountsSelector, {EMPTY_FLAGGED_EXPENSES_REVIEW, EMPTY_TODOS_SINGLE_REPORT_IDS, flaggedExpensesReviewSelector, todosSingleReportIDsSelector} from '@src/selectors/Todos';
 import EmptyState from './EmptyState';
 import ForYouSkeleton from './ForYouSkeleton';
 
@@ -29,24 +29,33 @@ function ForYouSection() {
     const [isLoadingReportData = false] = useOnyx(ONYXKEYS.IS_LOADING_REPORT_DATA);
     const [reportCounts = CONST.EMPTY_TODOS_REPORT_COUNTS] = useOnyx(ONYXKEYS.DERIVED.TODOS, {selector: todosReportCountsSelector});
     const [singleReportIDs = EMPTY_TODOS_SINGLE_REPORT_IDS] = useOnyx(ONYXKEYS.DERIVED.TODOS, {selector: todosSingleReportIDsSelector});
+    const [flaggedExpensesReview = EMPTY_FLAGGED_EXPENSES_REVIEW] = useOnyx(ONYXKEYS.DERIVED.FLAGGED_EXPENSES, {selector: flaggedExpensesReviewSelector});
 
-    const icons = useMemoizedLazyExpensifyIcons(['MoneyBag', 'Send', 'ThumbsUp', 'Export']);
+    const icons = useMemoizedLazyExpensifyIcons(['Exclamation', 'MoneyBag', 'Send', 'ThumbsUp', 'Export']);
 
     const submitCount = reportCounts?.[CONST.SEARCH.SEARCH_KEYS.SUBMIT] ?? 0;
     const approveCount = reportCounts?.[CONST.SEARCH.SEARCH_KEYS.APPROVE] ?? 0;
     const payCount = reportCounts?.[CONST.SEARCH.SEARCH_KEYS.PAY] ?? 0;
     const exportCount = reportCounts?.[CONST.SEARCH.SEARCH_KEYS.EXPORT] ?? 0;
+    const flaggedExpensesCount = flaggedExpensesReview.count;
 
-    const hasAnyTodos = submitCount > 0 || approveCount > 0 || payCount > 0 || exportCount > 0;
+    const hasAnyTodos = flaggedExpensesCount > 0 || submitCount > 0 || approveCount > 0 || payCount > 0 || exportCount > 0;
+
+    const navigateToReport = useCallback(
+        (reportID: string) => {
+            if (shouldUseNarrowLayout) {
+                Navigation.navigate(ROUTES.REPORT_WITH_ID.getRoute(reportID, undefined, undefined, ROUTES.HOME));
+                return;
+            }
+            Navigation.navigate(ROUTES.EXPENSE_REPORT_RHP.getRoute({reportID, backTo: ROUTES.HOME}));
+        },
+        [shouldUseNarrowLayout],
+    );
 
     const createNavigationHandler = useCallback(
         (action: string, queryParams: Record<string, unknown>, reportID?: string) => () => {
             if (reportID) {
-                if (shouldUseNarrowLayout) {
-                    Navigation.navigate(ROUTES.REPORT_WITH_ID.getRoute(reportID, undefined, undefined, ROUTES.HOME));
-                } else {
-                    Navigation.navigate(ROUTES.EXPENSE_REPORT_RHP.getRoute({reportID, backTo: ROUTES.HOME}));
-                }
+                navigateToReport(reportID);
                 return;
             }
 
@@ -60,12 +69,29 @@ function ForYouSection() {
                 }),
             );
         },
-        [shouldUseNarrowLayout],
+        [navigateToReport],
+    );
+
+    const createReviewExpensesHandler = useCallback(
+        (firstReportID: string | undefined) => () => {
+            if (!firstReportID) {
+                return;
+            }
+            navigateToReport(firstReportID);
+        },
+        [navigateToReport],
     );
 
     const todoItems = useMemo(
         () =>
             [
+                {
+                    key: 'reviewExpenses',
+                    count: flaggedExpensesCount,
+                    icon: icons.Exclamation,
+                    translationKey: 'homePage.forYouSection.reviewExpenses' as const,
+                    handler: createReviewExpensesHandler(flaggedExpensesReview.firstReportID),
+                },
                 {
                     key: 'submit',
                     count: submitCount,
@@ -103,7 +129,23 @@ function ForYouSection() {
                     ),
                 },
             ].filter((item) => item.count > 0),
-        [accountID, approveCount, createNavigationHandler, exportCount, icons.Export, icons.MoneyBag, icons.Send, icons.ThumbsUp, payCount, singleReportIDs, submitCount],
+        [
+            accountID,
+            approveCount,
+            createNavigationHandler,
+            createReviewExpensesHandler,
+            exportCount,
+            flaggedExpensesCount,
+            flaggedExpensesReview.firstReportID,
+            icons.Exclamation,
+            icons.Export,
+            icons.MoneyBag,
+            icons.Send,
+            icons.ThumbsUp,
+            payCount,
+            singleReportIDs,
+            submitCount,
+        ],
     );
 
     const renderTodoItems = () => (
diff --git a/src/selectors/Todos.ts b/src/selectors/Todos.ts
index a1108233c703..84ff216de5c0 100644
--- a/src/selectors/Todos.ts
+++ b/src/selectors/Todos.ts
@@ -1,7 +1,7 @@
 import {shallowEqual} from 'fast-equals';
 import type {OnyxEntry} from 'react-native-onyx';
 import CONST from '@src/CONST';
-import type {TodosDerivedValue} from '@src/types/onyx';
+import type {FlaggedExpensesDerivedValue, TodosDerivedValue} from '@src/types/onyx';
 
 const EMPTY_TODOS_SINGLE_REPORT_IDS = Object.freeze({
     [CONST.SEARCH.SEARCH_KEYS.SUBMIT]: undefined,
@@ -66,5 +66,48 @@ const todosSingleReportIDsSelector = (todos: OnyxEntry<TodosDerivedValue>) => {
     return newValue;
 };
 
+type FlaggedExpensesReview = {
+    /** Total number of flagged expenses */
+    count: number;
+    /** Transaction ID of the first flagged expense, used to seed the carousel handoff */
+    firstTransactionID: string | undefined;
+    /** Parent report ID of the first flagged expense */
+    firstReportID: string | undefined;
+};
+
+const EMPTY_FLAGGED_EXPENSES_REVIEW: FlaggedExpensesReview = Object.freeze({
+    count: 0,
+    firstTransactionID: undefined,
+    firstReportID: undefined,
+}) as FlaggedExpensesReview;
+
+// Manual memoization mirrors `todosSingleReportIDsSelector`: ForYouSection's useMemo dependency
+// list consumes the returned object as a whole, so we need referential stability across
+// equivalent derived snapshots to avoid cascading re-renders on every Onyx churn.
+let previousFlaggedExpensesReview: FlaggedExpensesReview = EMPTY_FLAGGED_EXPENSES_REVIEW;
+
+const flaggedExpensesReviewSelector = (flaggedExpensesValue: OnyxEntry<FlaggedExpensesDerivedValue>): FlaggedExpensesReview => {
+    const flaggedExpenses = flaggedExpensesValue?.flaggedExpenses;
+    if (!flaggedExpenses || flaggedExpenses.length === 0) {
+        previousFlaggedExpensesReview = EMPTY_FLAGGED_EXPENSES_REVIEW;
+        return EMPTY_FLAGGED_EXPENSES_REVIEW;
+    }
+
+    const first = flaggedExpenses.at(0);
+    const newValue: FlaggedExpensesReview = {
+        count: flaggedExpenses.length,
+        firstTransactionID: first?.transactionID,
+        firstReportID: first?.reportID,
+    };
+
+    if (shallowEqual(previousFlaggedExpensesReview, newValue)) {
+        return previousFlaggedExpensesReview;
+    }
+
+    previousFlaggedExpensesReview = newValue;
+    return newValue;
+};
+
 export default todosReportCountsSelector;
-export {todosSingleReportIDsSelector, EMPTY_TODOS_SINGLE_REPORT_IDS};
+export {EMPTY_FLAGGED_EXPENSES_REVIEW, EMPTY_TODOS_SINGLE_REPORT_IDS, flaggedExpensesReviewSelector, todosSingleReportIDsSelector};
+export type {FlaggedExpensesReview};
diff --git a/src/types/onyx/DerivedValues.ts b/src/types/onyx/DerivedValues.ts
index bbcecb4f4d6f..46128996dce1 100644
--- a/src/types/onyx/DerivedValues.ts
+++ b/src/types/onyx/DerivedValues.ts
@@ -266,6 +266,23 @@ type TodosDerivedValue = {
     transactionsByReportID: Record<string, Transaction[]>;
 };
 
+/**
+ * The derived value for flagged expenses.
+ *
+ * Aggregates transactions on the current user's `OPEN`/`OPEN` expense reports that have
+ * at least one transaction-level violation (excluding `showInReview === false` entries and
+ * `REPORT_VIOLATIONS.FIELD_REQUIRED` entries that may slip into the collection).
+ */
+type FlaggedExpensesDerivedValue = {
+    /** Ordered list of flagged transactions with their parent report IDs */
+    flaggedExpenses: Array<{
+        /** ID of the flagged transaction */
+        transactionID: string;
+        /** ID of the parent expense report */
+        reportID: string;
+    }>;
+};
+
 /**
  * The derived value for sorted report actions, last report actions, and cached transaction thread report IDs.
  */
@@ -297,6 +314,7 @@ export type {
     CardFeedErrorsDerivedValue,
     TodosDerivedValue,
     TodoMetadata,
+    FlaggedExpensesDerivedValue,
     CardFeedErrorsObject,
     CardFeedErrorState,
     CardFeedErrors,
diff --git a/src/types/onyx/index.ts b/src/types/onyx/index.ts
index 574568fa4d17..4346973a81e2 100644
--- a/src/types/onyx/index.ts
+++ b/src/types/onyx/index.ts
@@ -46,6 +46,7 @@ import type {CurrencyList} from './Currency';
 import type CustomStatusDraft from './CustomStatusDraft';
 import type {
     CardFeedErrorsDerivedValue,
+    FlaggedExpensesDerivedValue,
     NonPersonalAndWorkspaceCardListDerivedValue,
     OpenAndSubmittedReportsByPolicyIDDerivedValue,
     OutstandingReportsByPolicyIDDerivedValue,
@@ -395,6 +396,7 @@ export type {
     CardFeedErrorsDerivedValue,
     TodosDerivedValue,
     TodoMetadata,
+    FlaggedExpensesDerivedValue,
     ScheduleCallDraft,
     ValidateUserAndGetAccessiblePolicies,
     VacationDelegate,
diff --git a/tests/ui/ForYouSectionTest.tsx b/tests/ui/ForYouSectionTest.tsx
index ebdcf1ce65ca..02792c2de4c5 100644
--- a/tests/ui/ForYouSectionTest.tsx
+++ b/tests/ui/ForYouSectionTest.tsx
@@ -6,7 +6,7 @@ import Navigation from '@libs/Navigation/Navigation';
 import ForYouSection from '@pages/home/ForYouSection';
 import ONYXKEYS from '@src/ONYXKEYS';
 import ROUTES from '@src/ROUTES';
-import type {TodosDerivedValue} from '@src/types/onyx';
+import type {FlaggedExpensesDerivedValue, TodosDerivedValue} from '@src/types/onyx';
 import waitForBatchedUpdatesWithAct from '../utils/waitForBatchedUpdatesWithAct';
 
 jest.mock('@libs/Navigation/Navigation', () => ({
@@ -44,12 +44,15 @@ jest.mock('@hooks/useThemeStyles', () =>
 
 jest.mock('@hooks/useTheme', () => jest.fn(() => ({})));
 
+const EXCLAMATION_ASSET = {testID: 'exclamation-icon'};
+
 jest.mock('@hooks/useLazyAsset', () => ({
     useMemoizedLazyExpensifyIcons: jest.fn(() => ({
         MoneyBag: null,
         Send: null,
         ThumbsUp: null,
         Export: null,
+        Exclamation: EXCLAMATION_ASSET,
     })),
     useMemoizedLazyIllustrations: jest.fn(() => ({
         ThumbsUpStars: null,
@@ -75,6 +78,8 @@ const BASE_TODOS: TodosDerivedValue = {
     transactionsByReportID: {},
 };
 
+const EMPTY_FLAGGED_EXPENSES: FlaggedExpensesDerivedValue = {flaggedExpenses: []};
+
 function renderForYouSection() {
     return render(<ForYouSection />);
 }
@@ -125,6 +130,7 @@ describe('ForYouSection', () => {
         it('renders EmptyState when there are no todos', async () => {
             await act(async () => {
                 await Onyx.set(ONYXKEYS.DERIVED.TODOS, BASE_TODOS);
+                await Onyx.set(ONYXKEYS.DERIVED.FLAGGED_EXPENSES, EMPTY_FLAGGED_EXPENSES);
             });
             await waitForBatchedUpdatesWithAct();
 
@@ -135,6 +141,191 @@ describe('ForYouSection', () => {
         });
     });
 
+    describe('review row', () => {
+        it('is not rendered when there are no flagged expenses', async () => {
+            await act(async () => {
+                await Onyx.set(ONYXKEYS.DERIVED.TODOS, {
+                    ...BASE_TODOS,
+                    reportsToSubmit: [{reportID: '1'} as TodosDerivedValue['reportsToSubmit'][number]],
+                });
+                await Onyx.set(ONYXKEYS.DERIVED.FLAGGED_EXPENSES, EMPTY_FLAGGED_EXPENSES);
+            });
+            await waitForBatchedUpdatesWithAct();
+
+            renderForYouSection();
+            await waitForBatchedUpdatesWithAct();
+
+            expect(screen.queryByText(/homePage\.forYouSection\.reviewExpenses/)).not.toBeOnTheScreen();
+        });
+
+        it('renders with the count-1 string when exactly one expense is flagged', async () => {
+            await act(async () => {
+                await Onyx.set(ONYXKEYS.DERIVED.TODOS, BASE_TODOS);
+                await Onyx.set(ONYXKEYS.DERIVED.FLAGGED_EXPENSES, {
+                    flaggedExpenses: [{transactionID: 't1', reportID: 'r1'}],
+                });
+            });
+            await waitForBatchedUpdatesWithAct();
+
+            renderForYouSection();
+            await waitForBatchedUpdatesWithAct();
+
+            expect(screen.getByText('homePage.forYouSection.reviewExpenses:{"count":1}')).toBeOnTheScreen();
+        });
+
+        it('renders with the count-N string when multiple expenses are flagged', async () => {
+            await act(async () => {
+                await Onyx.set(ONYXKEYS.DERIVED.TODOS, BASE_TODOS);
+                await Onyx.set(ONYXKEYS.DERIVED.FLAGGED_EXPENSES, {
+                    flaggedExpenses: [
+                        {transactionID: 't1', reportID: 'r1'},
+                        {transactionID: 't2', reportID: 'r2'},
+                        {transactionID: 't3', reportID: 'r3'},
+                    ],
+                });
+            });
+            await waitForBatchedUpdatesWithAct();
+
+            renderForYouSection();
+            await waitForBatchedUpdatesWithAct();
+
+            expect(screen.getByText('homePage.forYouSection.reviewExpenses:{"count":3}')).toBeOnTheScreen();
+        });
+
+        it('renders the review row above submit/approve/pay/export rows', async () => {
+            await act(async () => {
+                await Onyx.set(ONYXKEYS.DERIVED.TODOS, {
+                    ...BASE_TODOS,
+                    reportsToSubmit: [{reportID: 's1'} as TodosDerivedValue['reportsToSubmit'][number]],
+                    reportsToApprove: [{reportID: 'a1'} as TodosDerivedValue['reportsToApprove'][number]],
+                    reportsToPay: [{reportID: 'p1'} as TodosDerivedValue['reportsToPay'][number]],
+                    reportsToExport: [{reportID: 'e1'} as TodosDerivedValue['reportsToExport'][number]],
+                });
+                await Onyx.set(ONYXKEYS.DERIVED.FLAGGED_EXPENSES, {
+                    flaggedExpenses: [{transactionID: 't1', reportID: 'r1'}],
+                });
+            });
+            await waitForBatchedUpdatesWithAct();
+
+            renderForYouSection();
+            await waitForBatchedUpdatesWithAct();
+
+            const reviewTitle = screen.getByText('homePage.forYouSection.reviewExpenses:{"count":1}');
+            const submitTitle = screen.getByText('homePage.forYouSection.submit:{"count":1}');
+            const approveTitle = screen.getByText('homePage.forYouSection.approve:{"count":1}');
+            const payTitle = screen.getByText('homePage.forYouSection.pay:{"count":1}');
+            const exportTitle = screen.getByText('homePage.forYouSection.export:{"count":1}');
+
+            // jest-native renderer assigns sequential _nativeTag-like positions; we rely on
+            // the order returned by getAllByText to verify rendering order.
+            const allTitles = screen.getAllByText(/homePage\.forYouSection\.(reviewExpenses|submit|approve|pay|export):/);
+            const getChildren = (node: {props: {children?: unknown}}) => node.props.children;
+            const titleOrder = allTitles.map(getChildren);
+
+            expect(titleOrder.at(0)).toBe(getChildren(reviewTitle));
+            expect(titleOrder).toEqual([getChildren(reviewTitle), getChildren(submitTitle), getChildren(approveTitle), getChildren(payTitle), getChildren(exportTitle)]);
+        });
+
+        it('exposes a Begin CTA and uses the Exclamation icon asset', async () => {
+            await act(async () => {
+                await Onyx.set(ONYXKEYS.DERIVED.TODOS, BASE_TODOS);
+                await Onyx.set(ONYXKEYS.DERIVED.FLAGGED_EXPENSES, {
+                    flaggedExpenses: [{transactionID: 't1', reportID: 'r1'}],
+                });
+            });
+            await waitForBatchedUpdatesWithAct();
+
+            const {UNSAFE_root: unsafeRoot} = renderForYouSection();
+            await waitForBatchedUpdatesWithAct();
+
+            expect(screen.getByText('Begin')).toBeOnTheScreen();
+
+            // The Exclamation asset should be passed as the `icon` prop on at least one BaseWidgetItem.
+            // We look for any rendered element whose `icon` prop is the EXCLAMATION_ASSET reference.
+            const matchingNodes = unsafeRoot.findAll((node) => node.props && (node.props as {icon?: unknown}).icon === EXCLAMATION_ASSET);
+            expect(matchingNodes.length).toBeGreaterThan(0);
+        });
+    });
+
+    describe('review row navigation', () => {
+        describe('wide layout', () => {
+            it('navigates to EXPENSE_REPORT_RHP with the first flagged expense parent report and backTo=HOME', async () => {
+                await act(async () => {
+                    await Onyx.set(ONYXKEYS.DERIVED.TODOS, BASE_TODOS);
+                    await Onyx.set(ONYXKEYS.DERIVED.FLAGGED_EXPENSES, {
+                        flaggedExpenses: [
+                            {transactionID: 't1', reportID: 'r1'},
+                            {transactionID: 't2', reportID: 'r2'},
+                        ],
+                    });
+                });
+                await waitForBatchedUpdatesWithAct();
+
+                renderForYouSection();
+                await waitForBatchedUpdatesWithAct();
+
+                pressFirstBeginButton();
+
+                expect(mockNavigate).toHaveBeenCalledTimes(1);
+                expect(mockNavigate).toHaveBeenCalledWith(ROUTES.EXPENSE_REPORT_RHP.getRoute({reportID: 'r1', backTo: ROUTES.HOME}));
+            });
+
+            it('still uses the per-report RHP route when only one expense is flagged', async () => {
+                await act(async () => {
+                    await Onyx.set(ONYXKEYS.DERIVED.TODOS, BASE_TODOS);
+                    await Onyx.set(ONYXKEYS.DERIVED.FLAGGED_EXPENSES, {
+                        flaggedExpenses: [{transactionID: 't1', reportID: 'rOnly'}],
+                    });
+                });
+                await waitForBatchedUpdatesWithAct();
+
+                renderForYouSection();
+                await waitForBatchedUpdatesWithAct();
+
+                pressFirstBeginButton();
+
+                expect(mockNavigate).toHaveBeenCalledTimes(1);
+                expect(mockNavigate).toHaveBeenCalledWith(ROUTES.EXPENSE_REPORT_RHP.getRoute({reportID: 'rOnly', backTo: ROUTES.HOME}));
+            });
+        });
+
+        describe('narrow layout', () => {
+            beforeEach(() => {
+                mockUseResponsiveLayout.mockReturnValue({
+                    shouldUseNarrowLayout: true,
+                    isSmallScreenWidth: true,
+                    isInNarrowPaneModal: false,
+                    isExtraSmallScreenHeight: false,
+                    isMediumScreenWidth: false,
+                    isLargeScreenWidth: false,
+                    isExtraLargeScreenWidth: false,
+                    isExtraSmallScreenWidth: false,
+                    isSmallScreen: true,
+                    onboardingIsMediumOrLargerScreenWidth: false,
+                    isInLandscapeMode: false,
+                });
+            });
+
+            it('navigates to REPORT_WITH_ID with the first flagged expense parent report and backTo=HOME', async () => {
+                await act(async () => {
+                    await Onyx.set(ONYXKEYS.DERIVED.TODOS, BASE_TODOS);
+                    await Onyx.set(ONYXKEYS.DERIVED.FLAGGED_EXPENSES, {
+                        flaggedExpenses: [{transactionID: 't1', reportID: 'rNarrow'}],
+                    });
+                });
+                await waitForBatchedUpdatesWithAct();
+
+                renderForYouSection();
+                await waitForBatchedUpdatesWithAct();
+
+                pressFirstBeginButton();
+
+                expect(mockNavigate).toHaveBeenCalledTimes(1);
+                expect(mockNavigate).toHaveBeenCalledWith(ROUTES.REPORT_WITH_ID.getRoute('rNarrow', undefined, undefined, ROUTES.HOME));
+            });
+        });
+    });
+
     describe('navigation with multiple reports (search route)', () => {
         it('navigates to SEARCH_ROOT when submit has multiple reports', async () => {
             await act(async () => {
diff --git a/tests/unit/OnyxDerived/flaggedExpensesTest.ts b/tests/unit/OnyxDerived/flaggedExpensesTest.ts
new file mode 100644
index 000000000000..4b59525f2d10
--- /dev/null
+++ b/tests/unit/OnyxDerived/flaggedExpensesTest.ts
@@ -0,0 +1,264 @@
+import type {OnyxCollection} from 'react-native-onyx';
+import flaggedExpensesConfig from '@libs/actions/OnyxDerived/configs/flaggedExpenses';
+import type {DerivedValueContext} from '@libs/actions/OnyxDerived/types';
+import CONST from '@src/CONST';
+import ONYXKEYS from '@src/ONYXKEYS';
+import type {Report, Session, Transaction, TransactionViolations} from '@src/types/onyx';
+import {createMockReport} from '../../utils/ReportTestUtils';
+
+const CURRENT_USER_ACCOUNT_ID = 1;
+const OTHER_USER_ACCOUNT_ID = 2;
+const POLICY_ID_1 = 'policy1';
+const POLICY_ID_2 = 'policy2';
+
+function createExpenseReport(reportID: string, overrides: Partial<Report> = {}): Report {
+    return createMockReport({
+        reportID,
+        type: CONST.REPORT.TYPE.EXPENSE,
+        ownerAccountID: CURRENT_USER_ACCOUNT_ID,
+        policyID: POLICY_ID_1,
+        stateNum: CONST.REPORT.STATE_NUM.OPEN,
+        statusNum: CONST.REPORT.STATUS_NUM.OPEN,
+        ...overrides,
+    });
+}
+
+function createTransaction(transactionID: string, reportID: string, overrides: Partial<Transaction> = {}): Transaction {
+    return {
+        transactionID,
+        reportID,
+        amount: 100,
+        currency: 'USD',
+        created: '2024-01-01',
+        merchant: 'Test Merchant',
+        ...overrides,
+    } as Transaction;
+}
+
+function buildReports(...reports: Report[]): OnyxCollection<Report> {
+    const result: OnyxCollection<Report> = {};
+    for (const report of reports) {
+        result[`${ONYXKEYS.COLLECTION.REPORT}${report.reportID}`] = report;
+    }
+    return result;
+}
+
+function buildTransactions(...transactions: Transaction[]): OnyxCollection<Transaction> {
+    const result: OnyxCollection<Transaction> = {};
+    for (const transaction of transactions) {
+        result[`${ONYXKEYS.COLLECTION.TRANSACTION}${transaction.transactionID}`] = transaction;
+    }
+    return result;
+}
+
+function buildViolations(violationsByTransactionID: Record<string, TransactionViolations>): OnyxCollection<TransactionViolations> {
+    const result: OnyxCollection<TransactionViolations> = {};
+    for (const [transactionID, violations] of Object.entries(violationsByTransactionID)) {
+        result[`${ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS}${transactionID}`] = violations;
+    }
+    return result;
+}
+
+function createSession(accountID: number = CURRENT_USER_ACCOUNT_ID): Session {
+    return {accountID} as Session;
+}
+
+const {compute} = flaggedExpensesConfig;
+const emptyContext = {} as DerivedValueContext<
+    typeof ONYXKEYS.DERIVED.FLAGGED_EXPENSES,
+    [typeof ONYXKEYS.COLLECTION.REPORT, typeof ONYXKEYS.COLLECTION.TRANSACTION, typeof ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS, typeof ONYXKEYS.SESSION]
+>;
+
+describe('flaggedExpenses derived value', () => {
+    describe('presence and count', () => {
+        it('reports zero flagged expenses and an empty list when no transactions have violations', () => {
+            const report = createExpenseReport('r1');
+            const transaction = createTransaction('t1', 'r1');
+            const result = compute([buildReports(report), buildTransactions(transaction), {}, createSession()], emptyContext);
+
+            expect(result.flaggedExpenses).toEqual([]);
+        });
+
+        it('counts two flagged transactions on OPEN/OPEN expense reports across two workspaces', () => {
+            const report1 = createExpenseReport('r1', {policyID: POLICY_ID_1});
+            const report2 = createExpenseReport('r2', {policyID: POLICY_ID_2});
+            const transaction1 = createTransaction('t1', 'r1');
+            const transaction2 = createTransaction('t2', 'r2');
+            const violations = buildViolations({
+                t1: [{type: CONST.VIOLATION_TYPES.VIOLATION, name: CONST.VIOLATIONS.MISSING_CATEGORY}],
+                t2: [{type: CONST.VIOLATION_TYPES.VIOLATION, name: CONST.VIOLATIONS.MISSING_CATEGORY}],
+            });
+
+            const result = compute([buildReports(report1, report2), buildTransactions(transaction1, transaction2), violations, createSession()], emptyContext);
+
+            expect(result.flaggedExpenses).toHaveLength(2);
+            const ids = result.flaggedExpenses.map((entry) => entry.transactionID).sort();
+            expect(ids).toEqual(['t1', 't2']);
+            const reportIDs = result.flaggedExpenses.map((entry) => entry.reportID).sort();
+            expect(reportIDs).toEqual(['r1', 'r2']);
+        });
+
+        it('counts a single transaction with multiple violations as 1 expense', () => {
+            const report = createExpenseReport('r1');
+            const transaction = createTransaction('t1', 'r1');
+            const violations = buildViolations({
+                t1: [
+                    {type: CONST.VIOLATION_TYPES.VIOLATION, name: CONST.VIOLATIONS.MISSING_CATEGORY},
+                    {type: CONST.VIOLATION_TYPES.VIOLATION, name: CONST.VIOLATIONS.MISSING_TAG},
+                ],
+            });
+
+            const result = compute([buildReports(report), buildTransactions(transaction), violations, createSession()], emptyContext);
+
+            expect(result.flaggedExpenses).toHaveLength(1);
+            expect(result.flaggedExpenses.at(0)).toEqual({transactionID: 't1', reportID: 'r1'});
+        });
+
+        it('counts every non-report-field violation type that OpenApp returns', () => {
+            const report = createExpenseReport('r1');
+            const transactions = [createTransaction('tA', 'r1'), createTransaction('tB', 'r1'), createTransaction('tC', 'r1')];
+            const violations = buildViolations({
+                tA: [{type: CONST.VIOLATION_TYPES.VIOLATION, name: CONST.VIOLATIONS.OVER_CATEGORY_LIMIT}],
+                tB: [{type: CONST.VIOLATION_TYPES.VIOLATION, name: CONST.VIOLATIONS.MISSING_ATTENDEES}],
+                tC: [{type: CONST.VIOLATION_TYPES.VIOLATION, name: CONST.VIOLATIONS.MISSING_COMMENT}],
+            });
+
+            const result = compute([buildReports(report), buildTransactions(...transactions), violations, createSession()], emptyContext);
+
+            expect(result.flaggedExpenses).toHaveLength(3);
+            expect(result.flaggedExpenses.map((entry) => entry.transactionID).sort()).toEqual(['tA', 'tB', 'tC']);
+        });
+
+        it('excludes violations with showInReview === false', () => {
+            const report = createExpenseReport('r1');
+            const transaction = createTransaction('t1', 'r1');
+            const violations = buildViolations({
+                t1: [{type: CONST.VIOLATION_TYPES.VIOLATION, name: CONST.VIOLATIONS.MISSING_CATEGORY, showInReview: false}],
+            });
+
+            const result = compute([buildReports(report), buildTransactions(transaction), violations, createSession()], emptyContext);
+
+            expect(result.flaggedExpenses).toEqual([]);
+        });
+    });
+
+    describe('Draft-report scope and resolution', () => {
+        it('excludes flagged transactions on submitted expense reports', () => {
+            const draftReport = createExpenseReport('r1');
+            const submittedReport = createExpenseReport('r2', {
+                stateNum: CONST.REPORT.STATE_NUM.SUBMITTED,
+                statusNum: CONST.REPORT.STATUS_NUM.SUBMITTED,
+            });
+            const draftTransaction = createTransaction('t1', 'r1');
+            const submittedTransaction = createTransaction('t2', 'r2');
+            const violations = buildViolations({
+                t1: [{type: CONST.VIOLATION_TYPES.VIOLATION, name: CONST.VIOLATIONS.MISSING_CATEGORY}],
+                t2: [{type: CONST.VIOLATION_TYPES.VIOLATION, name: CONST.VIOLATIONS.MISSING_CATEGORY}],
+            });
+
+            const result = compute([buildReports(draftReport, submittedReport), buildTransactions(draftTransaction, submittedTransaction), violations, createSession()], emptyContext);
+
+            expect(result.flaggedExpenses).toHaveLength(1);
+            expect(result.flaggedExpenses.at(0)).toEqual({transactionID: 't1', reportID: 'r1'});
+        });
+
+        it('excludes flagged transactions whose parent report is not an expense report', () => {
+            const expenseReport = createExpenseReport('r1');
+            const chatReport = createMockReport({
+                reportID: 'r2',
+                type: CONST.REPORT.TYPE.CHAT,
+                ownerAccountID: CURRENT_USER_ACCOUNT_ID,
+                stateNum: CONST.REPORT.STATE_NUM.OPEN,
+                statusNum: CONST.REPORT.STATUS_NUM.OPEN,
+            });
+            const t1 = createTransaction('t1', 'r1');
+            const t2 = createTransaction('t2', 'r2');
+            const violations = buildViolations({
+                t1: [{type: CONST.VIOLATION_TYPES.VIOLATION, name: CONST.VIOLATIONS.MISSING_CATEGORY}],
+                t2: [{type: CONST.VIOLATION_TYPES.VIOLATION, name: CONST.VIOLATIONS.MISSING_CATEGORY}],
+            });
+
+            const result = compute([buildReports(expenseReport, chatReport), buildTransactions(t1, t2), violations, createSession()], emptyContext);
+
+            expect(result.flaggedExpenses).toHaveLength(1);
+            expect(result.flaggedExpenses.at(0)).toEqual({transactionID: 't1', reportID: 'r1'});
+        });
+
+        it('does not count report-field violations as flagged expenses', () => {
+            const report = createExpenseReport('r1');
+            const transaction = createTransaction('t1', 'r1');
+            const violations = buildViolations({
+                t1: [{type: CONST.VIOLATION_TYPES.VIOLATION, name: CONST.REPORT_VIOLATIONS.FIELD_REQUIRED} as TransactionViolations[number]],
+            });
+
+            const result = compute([buildReports(report), buildTransactions(transaction), violations, createSession()], emptyContext);
+
+            expect(result.flaggedExpenses).toEqual([]);
+        });
+
+        it('drops a transaction from the list when its last violation is cleared', () => {
+            const report = createExpenseReport('r1');
+            const transaction = createTransaction('t1', 'r1');
+            const flaggedViolations = buildViolations({
+                t1: [{type: CONST.VIOLATION_TYPES.VIOLATION, name: CONST.VIOLATIONS.MISSING_CATEGORY}],
+            });
+
+            const flaggedResult = compute([buildReports(report), buildTransactions(transaction), flaggedViolations, createSession()], emptyContext);
+            expect(flaggedResult.flaggedExpenses).toHaveLength(1);
+
+            const clearedViolations = buildViolations({t1: []});
+            const clearedResult = compute([buildReports(report), buildTransactions(transaction), clearedViolations, createSession()], emptyContext);
+            expect(clearedResult.flaggedExpenses).toEqual([]);
+        });
+
+        it('restores a previously cleaned transaction once it is re-flagged', () => {
+            const report = createExpenseReport('r1');
+            const transaction = createTransaction('t1', 'r1');
+
+            const clearedResult = compute([buildReports(report), buildTransactions(transaction), buildViolations({t1: []}), createSession()], emptyContext);
+            expect(clearedResult.flaggedExpenses).toEqual([]);
+
+            const reflaggedResult = compute(
+                [
+                    buildReports(report),
+                    buildTransactions(transaction),
+                    buildViolations({
+                        t1: [{type: CONST.VIOLATION_TYPES.VIOLATION, name: CONST.VIOLATIONS.MISSING_CATEGORY}],
+                    }),
+                    createSession(),
+                ],
+                emptyContext,
+            );
+            expect(reflaggedResult.flaggedExpenses).toHaveLength(1);
+            expect(reflaggedResult.flaggedExpenses.at(0)?.transactionID).toBe('t1');
+        });
+
+        it('excludes flagged transactions on expense reports the current user does not own', () => {
+            const ownReport = createExpenseReport('r1');
+            const foreignReport = createExpenseReport('r2', {ownerAccountID: OTHER_USER_ACCOUNT_ID});
+            const ownTransaction = createTransaction('t1', 'r1');
+            const foreignTransaction = createTransaction('t2', 'r2');
+            const violations = buildViolations({
+                t1: [{type: CONST.VIOLATION_TYPES.VIOLATION, name: CONST.VIOLATIONS.MISSING_CATEGORY}],
+                t2: [{type: CONST.VIOLATION_TYPES.VIOLATION, name: CONST.VIOLATIONS.MISSING_CATEGORY}],
+            });
+
+            const result = compute([buildReports(ownReport, foreignReport), buildTransactions(ownTransaction, foreignTransaction), violations, createSession()], emptyContext);
+
+            expect(result.flaggedExpenses).toHaveLength(1);
+            expect(result.flaggedExpenses.at(0)).toEqual({transactionID: 't1', reportID: 'r1'});
+        });
+
+        it('excludes all flagged transactions when the session has no accountID', () => {
+            const report = createExpenseReport('r1', {ownerAccountID: OTHER_USER_ACCOUNT_ID});
+            const transaction = createTransaction('t1', 'r1');
+            const violations = buildViolations({
+                t1: [{type: CONST.VIOLATION_TYPES.VIOLATION, name: CONST.VIOLATIONS.MISSING_CATEGORY}],
+            });
+
+            const result = compute([buildReports(report), buildTransactions(transaction), violations, {} as Session], emptyContext);
+
+            expect(result.flaggedExpenses).toEqual([]);
+        });
+    });
+});
diff --git a/tests/unit/selectors/TodosTest.ts b/tests/unit/selectors/TodosTest.ts
index 25e57801cd2a..9d90b76cb698 100644
--- a/tests/unit/selectors/TodosTest.ts
+++ b/tests/unit/selectors/TodosTest.ts
@@ -1,6 +1,6 @@
-import todosReportCountsSelector, {todosSingleReportIDsSelector} from '@selectors/Todos';
+import todosReportCountsSelector, {flaggedExpensesReviewSelector, todosSingleReportIDsSelector} from '@selectors/Todos';
 import CONST from '@src/CONST';
-import type {TodosDerivedValue} from '@src/types/onyx';
+import type {FlaggedExpensesDerivedValue, TodosDerivedValue} from '@src/types/onyx';
 
 describe('todosReportCountsSelector', () => {
     it('returns undefined when todos is undefined', () => {
@@ -212,3 +212,69 @@ describe('todosSingleReportIDsSelector', () => {
         expect(second[CONST.SEARCH.SEARCH_KEYS.SUBMIT]).toBe('21');
     });
 });
+
+describe('flaggedExpensesReviewSelector', () => {
+    it('returns count 0 and undefined identifiers when input is undefined', () => {
+        const result = flaggedExpensesReviewSelector(undefined);
+
+        expect(result.count).toBe(0);
+        expect(result.firstTransactionID).toBeUndefined();
+        expect(result.firstReportID).toBeUndefined();
+    });
+
+    it('returns count 0 and undefined identifiers when there are no flagged expenses', () => {
+        const value: FlaggedExpensesDerivedValue = {flaggedExpenses: []};
+
+        const result = flaggedExpensesReviewSelector(value);
+
+        expect(result.count).toBe(0);
+        expect(result.firstTransactionID).toBeUndefined();
+        expect(result.firstReportID).toBeUndefined();
+    });
+
+    it('returns aggregated count and stable first identifiers for multiple flagged expenses', () => {
+        const value: FlaggedExpensesDerivedValue = {
+            flaggedExpenses: [
+                {transactionID: 't1', reportID: 'r1'},
+                {transactionID: 't2', reportID: 'r2'},
+                {transactionID: 't3', reportID: 'r3'},
+            ],
+        };
+
+        const result = flaggedExpensesReviewSelector(value);
+
+        expect(result.count).toBe(3);
+        expect(result.firstTransactionID).toBe('t1');
+        expect(result.firstReportID).toBe('r1');
+    });
+
+    it('returns the same object reference when called twice with shallowly equal values', () => {
+        const value: FlaggedExpensesDerivedValue = {
+            flaggedExpenses: [{transactionID: 'tA', reportID: 'rA'}],
+        };
+        const first = flaggedExpensesReviewSelector(value);
+
+        const clone: FlaggedExpensesDerivedValue = {
+            flaggedExpenses: [{transactionID: 'tA', reportID: 'rA'}],
+        };
+        const second = flaggedExpensesReviewSelector(clone);
+
+        expect(second).toBe(first);
+    });
+
+    it('returns a new object reference when the first flagged expense changes', () => {
+        const value: FlaggedExpensesDerivedValue = {
+            flaggedExpenses: [{transactionID: 'tA', reportID: 'rA'}],
+        };
+        const first = flaggedExpensesReviewSelector(value);
+
+        const changed: FlaggedExpensesDerivedValue = {
+            flaggedExpenses: [{transactionID: 'tB', reportID: 'rB'}],
+        };
+        const second = flaggedExpensesReviewSelector(changed);
+
+        expect(second).not.toBe(first);
+        expect(second.firstTransactionID).toBe('tB');
+        expect(second.firstReportID).toBe('rB');
+    });
+});

From e5867011838de160659f2e281b5c5376cfc9a855 Mon Sep 17 00:00:00 2001
From: jayeshmangwani <jayeshmangwani@gmail.com>
Date: Fri, 29 May 2026 01:52:15 +0530
Subject: [PATCH 038/435] =?UTF-8?q?added=20a=20different=20CTA=20for=20tra?=
 =?UTF-8?q?ck=20intent=20users=20=E2=80=94=20=E2=80=9CMark=20as=20done?=
 =?UTF-8?q?=E2=80=9D?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 src/CONST/index.ts                            |   1 +
 src/components/AnimatedSubmitButton/index.tsx |   7 +-
 .../OptionRowLHN/OptionRow/ErrorBadge.tsx     |   8 +-
 .../OptionRowLHN/OptionRow/InfoBadge.tsx      |   7 +-
 .../OptionRowLHN/OptionRow/Pressable.tsx      |   8 +-
 .../OptionRowLHN/OptionRowLHN.tsx             |   5 +-
 .../OptionRowLHN/OptionRowLHNData.tsx         |  13 +-
 src/components/LHNOptionsList/types.ts        |   2 +
 .../MoneyReportHeaderSelectionDropdown.tsx    |  15 +-
 .../ApprovePrimaryAction.tsx                  |  12 +-
 .../SubmitPrimaryAction.tsx                   |  12 +-
 .../SubmitActionButton.tsx                    |  13 +-
 src/components/ReportWelcomeText.tsx          |   6 +
 .../SearchList/ListItem/ActionCell/index.tsx  |  16 +-
 src/components/utils/getActionBadgeText.ts    |  11 ++
 src/hooks/useSearchBulkActions.ts             |  17 +-
 src/hooks/useSearchTypeMenuSections.ts        |   6 +-
 src/languages/de.ts                           |  19 +++
 src/languages/en.ts                           |  21 +++
 src/languages/es.ts                           |  15 ++
 src/languages/fr.ts                           |  19 +++
 src/languages/it.ts                           |  19 +++
 src/languages/ja.ts                           |  19 +++
 src/languages/nl.ts                           |  19 +++
 src/languages/pl.ts                           |  19 +++
 src/languages/pt-BR.ts                        |  19 +++
 src/languages/zh-hans.ts                      |  19 +++
 src/libs/NextStepUtils.ts                     |  27 ++-
 src/libs/OptionsListUtils/index.ts            |  11 +-
 src/libs/ReportUtils.ts                       |  13 ++
 src/libs/SidebarUtils.ts                      |  12 ++
 .../BaseReportActionContextMenu.tsx           |   4 +-
 .../report/ContextMenu/ContextMenuActions.tsx |  13 +-
 .../inbox/report/PureReportActionItem.tsx     |   5 +
 src/pages/inbox/report/ReportActionItem.tsx   |   3 +
 .../actionContents/ActionContentRouter.tsx    |   5 +
 .../actionContents/ApprovalFlowContent.tsx    |  23 ++-
 src/selectors/Onboarding.ts                   |  10 +-
 tests/unit/OnboardingSelectorsTest.ts         |  32 +++-
 tests/unit/ReportUtilsTest.ts                 | 134 +++++++++++++++
 tests/unit/SidebarUtilsTest.ts                | 158 ++++++++++++++++++
 41 files changed, 760 insertions(+), 37 deletions(-)
 create mode 100644 src/components/utils/getActionBadgeText.ts

diff --git a/src/CONST/index.ts b/src/CONST/index.ts
index 202d637610f3..2fdbe033c4ff 100644
--- a/src/CONST/index.ts
+++ b/src/CONST/index.ts
@@ -1897,6 +1897,7 @@ const CONST = {
         MESSAGE_KEY: {
             WAITING_TO_ADD_TRANSACTIONS: 'waitingToAddTransactions',
             WAITING_TO_SUBMIT: 'waitingToSubmit',
+            WAITING_TO_MARK_AS_DONE: 'waitingToMarkAsDone',
             NO_FURTHER_ACTION: 'noFurtherAction',
             WAITING_FOR_SUBMITTER_ACCOUNT: 'waitingForSubmitterAccount',
             WAITING_FOR_AUTOMATIC_SUBMIT: 'waitingForAutomaticSubmit',
diff --git a/src/components/AnimatedSubmitButton/index.tsx b/src/components/AnimatedSubmitButton/index.tsx
index 945d5333fc9b..6e3e010aae1e 100644
--- a/src/components/AnimatedSubmitButton/index.tsx
+++ b/src/components/AnimatedSubmitButton/index.tsx
@@ -28,9 +28,12 @@ type AnimatedSubmitButtonProps = WithSentryLabel & {
 
     // Whether the button should be disabled
     isDisabled?: boolean;
+
+    /** Whether to show "Mark as done" copy instead of "Submit" copy for track-intent users */
+    isMarkAsDone?: boolean;
 };
 
-function AnimatedSubmitButton({success, text, onPress, isSubmittingAnimationRunning, onAnimationFinish, isDisabled, sentryLabel}: AnimatedSubmitButtonProps) {
+function AnimatedSubmitButton({success, text, onPress, isSubmittingAnimationRunning, onAnimationFinish, isDisabled, sentryLabel, isMarkAsDone}: AnimatedSubmitButtonProps) {
     const styles = useThemeStyles();
     const {translate} = useLocalize();
     const isAnimationRunning = isSubmittingAnimationRunning;
@@ -120,7 +123,7 @@ function AnimatedSubmitButton({success, text, onPress, isSubmittingAnimationRunn
                 >
                     <Button
                         success={success}
-                        text={showLoading ? text : translate('common.submitted')}
+                        text={showLoading ? text : translate(isMarkAsDone ? 'common.markedAsDoneStatus' : 'common.submitted')}
                         isLoading={showLoading}
                         icon={!showLoading ? icon : undefined}
                         isDisabled
diff --git a/src/components/LHNOptionsList/OptionRowLHN/OptionRow/ErrorBadge.tsx b/src/components/LHNOptionsList/OptionRowLHN/OptionRow/ErrorBadge.tsx
index 011d1202a30b..2c43f54746bb 100644
--- a/src/components/LHNOptionsList/OptionRowLHN/OptionRow/ErrorBadge.tsx
+++ b/src/components/LHNOptionsList/OptionRowLHN/OptionRow/ErrorBadge.tsx
@@ -2,6 +2,7 @@ import React from 'react';
 import {View} from 'react-native';
 import Badge from '@components/Badge';
 import Icon from '@components/Icon';
+import getActionBadgeText from '@components/utils/getActionBadgeText';
 import {useMemoizedLazyExpensifyIcons} from '@hooks/useLazyAsset';
 import useLocalize from '@hooks/useLocalize';
 import useTheme from '@hooks/useTheme';
@@ -15,9 +16,12 @@ type ErrorBadgeProps = {
 
     /** Action badge key used to derive the badge label. */
     actionBadge: OptionData['actionBadge'];
+
+    /** Whether to show the "Mark as Done" state for this row. */
+    isMarkAsDone?: boolean;
 };
 
-function ErrorBadge({brickRoadIndicator, actionBadge}: ErrorBadgeProps) {
+function ErrorBadge({brickRoadIndicator, actionBadge, isMarkAsDone}: ErrorBadgeProps) {
     const theme = useTheme();
     const styles = useThemeStyles();
     const {translate} = useLocalize();
@@ -27,7 +31,7 @@ function ErrorBadge({brickRoadIndicator, actionBadge}: ErrorBadgeProps) {
         return null;
     }
 
-    const actionBadgeText = actionBadge ? translate(`common.actionBadge.${actionBadge}`) : '';
+    const actionBadgeText = getActionBadgeText(actionBadge, translate, isMarkAsDone);
 
     return (
         <View style={[styles.alignItemsCenter, styles.justifyContentCenter]}>
diff --git a/src/components/LHNOptionsList/OptionRowLHN/OptionRow/InfoBadge.tsx b/src/components/LHNOptionsList/OptionRowLHN/OptionRow/InfoBadge.tsx
index 86d7b6ee160e..b50bc3e269a8 100644
--- a/src/components/LHNOptionsList/OptionRowLHN/OptionRow/InfoBadge.tsx
+++ b/src/components/LHNOptionsList/OptionRowLHN/OptionRow/InfoBadge.tsx
@@ -2,6 +2,7 @@ import React from 'react';
 import {View} from 'react-native';
 import Badge from '@components/Badge';
 import Icon from '@components/Icon';
+import getActionBadgeText from '@components/utils/getActionBadgeText';
 import {useMemoizedLazyExpensifyIcons} from '@hooks/useLazyAsset';
 import useLocalize from '@hooks/useLocalize';
 import useTheme from '@hooks/useTheme';
@@ -15,9 +16,11 @@ type InfoBadgeProps = {
 
     /** Action badge key used to derive the badge label. */
     actionBadge: OptionData['actionBadge'];
+    /** Whether to show the "Mark as Done" state for this row. */
+    isMarkAsDone?: boolean;
 };
 
-function InfoBadge({brickRoadIndicator, actionBadge}: InfoBadgeProps) {
+function InfoBadge({brickRoadIndicator, actionBadge, isMarkAsDone}: InfoBadgeProps) {
     const theme = useTheme();
     const styles = useThemeStyles();
     const {translate} = useLocalize();
@@ -27,7 +30,7 @@ function InfoBadge({brickRoadIndicator, actionBadge}: InfoBadgeProps) {
         return null;
     }
 
-    const actionBadgeText = actionBadge ? translate(`common.actionBadge.${actionBadge}`) : '';
+    const actionBadgeText = getActionBadgeText(actionBadge, translate, isMarkAsDone);
 
     if (actionBadgeText) {
         return (
diff --git a/src/components/LHNOptionsList/OptionRowLHN/OptionRow/Pressable.tsx b/src/components/LHNOptionsList/OptionRowLHN/OptionRow/Pressable.tsx
index 73c86874c118..1e0e3d71643b 100644
--- a/src/components/LHNOptionsList/OptionRowLHN/OptionRow/Pressable.tsx
+++ b/src/components/LHNOptionsList/OptionRowLHN/OptionRow/Pressable.tsx
@@ -5,6 +5,7 @@ import Hoverable from '@components/Hoverable';
 import {useLHNTooltipContext} from '@components/LHNOptionsList/LHNTooltipContext';
 import useLHNRowProductTrainingTooltip from '@components/LHNOptionsList/OptionRowLHN/useLHNRowProductTrainingTooltip';
 import PressableWithSecondaryInteraction from '@components/PressableWithSecondaryInteraction';
+import getActionBadgeText from '@components/utils/getActionBadgeText';
 import getContextMenuAccessibilityHint from '@components/utils/getContextMenuAccessibilityHint';
 import getContextMenuAccessibilityProps from '@components/utils/getContextMenuAccessibilityProps';
 import useLocalize from '@hooks/useLocalize';
@@ -41,9 +42,12 @@ type PressableProps = {
 
     /** Row content. */
     children: ReactNode;
+
+    /** Whether to show the "Mark as Done" state for this row. */
+    isMarkAsDone?: boolean;
 };
 
-function Pressable({optionItem, isOptionFocused, onSelectRow, onLayout, onHoverIn, onHoverOut, children}: PressableProps) {
+function Pressable({optionItem, isOptionFocused, onSelectRow, onLayout, onHoverIn, onHoverOut, children, isMarkAsDone}: PressableProps) {
     const theme = useTheme();
     const styles = useThemeStyles();
     const StyleUtils = useStyleUtils();
@@ -57,7 +61,7 @@ function Pressable({optionItem, isOptionFocused, onSelectRow, onLayout, onHoverI
 
     const reportID = optionItem.reportID;
     const brickRoadIndicator = optionItem.brickRoadIndicator;
-    const actionBadgeText = optionItem.actionBadge ? translate(`common.actionBadge.${optionItem.actionBadge}`) : '';
+    const actionBadgeText = getActionBadgeText(optionItem.actionBadge, translate, isMarkAsDone);
 
     let accessibilityLabelForBadge = '';
     if (brickRoadIndicator) {
diff --git a/src/components/LHNOptionsList/OptionRowLHN/OptionRowLHN.tsx b/src/components/LHNOptionsList/OptionRowLHN/OptionRowLHN.tsx
index 44e8b25fabe2..c787a7e4548e 100644
--- a/src/components/LHNOptionsList/OptionRowLHN/OptionRowLHN.tsx
+++ b/src/components/LHNOptionsList/OptionRowLHN/OptionRowLHN.tsx
@@ -5,7 +5,7 @@ import useThemeStyles from '@hooks/useThemeStyles';
 import OptionRow from './OptionRow';
 import useOptionRowChrome from './useOptionRowChrome';
 
-function OptionRowLHN({isOptionFocused = false, onSelectRow = () => {}, optionItem, viewMode = 'default', onLayout = () => {}, hasDraftComment, testID}: OptionRowLHNProps) {
+function OptionRowLHN({isOptionFocused = false, onSelectRow = () => {}, optionItem, viewMode = 'default', onLayout = () => {}, hasDraftComment, testID, isMarkAsDone}: OptionRowLHNProps) {
     const styles = useThemeStyles();
     const {setHovered, sidebarInnerRowStyle, contentContainerStyles, avatarBackgroundColor} = useOptionRowChrome({
         isOptionFocused,
@@ -27,6 +27,7 @@ function OptionRowLHN({isOptionFocused = false, onSelectRow = () => {}, optionIt
                     onLayout={onLayout}
                     onHoverIn={() => setHovered(true)}
                     onHoverOut={() => setHovered(false)}
+                    isMarkAsDone={isMarkAsDone}
                 >
                     <View style={sidebarInnerRowStyle}>
                         <View style={[styles.flexRow, styles.alignItemsCenter]}>
@@ -55,6 +56,7 @@ function OptionRowLHN({isOptionFocused = false, onSelectRow = () => {}, optionIt
                             <OptionRow.ErrorBadge
                                 brickRoadIndicator={brickRoadIndicator}
                                 actionBadge={optionItem.actionBadge}
+                                isMarkAsDone={isMarkAsDone}
                             />
                         </View>
                     </View>
@@ -62,6 +64,7 @@ function OptionRowLHN({isOptionFocused = false, onSelectRow = () => {}, optionIt
                         <OptionRow.InfoBadge
                             brickRoadIndicator={brickRoadIndicator}
                             actionBadge={optionItem.actionBadge}
+                            isMarkAsDone={isMarkAsDone}
                         />
                         <OptionRow.DraftIndicator
                             hasDraftComment={hasDraftComment}
diff --git a/src/components/LHNOptionsList/OptionRowLHN/OptionRowLHNData.tsx b/src/components/LHNOptionsList/OptionRowLHN/OptionRowLHNData.tsx
index c797dfcef367..0e30da791d95 100644
--- a/src/components/LHNOptionsList/OptionRowLHN/OptionRowLHNData.tsx
+++ b/src/components/LHNOptionsList/OptionRowLHN/OptionRowLHNData.tsx
@@ -1,3 +1,4 @@
+import {isTrackIntentUserSelector} from '@selectors/Onboarding';
 import React, {useCallback, useMemo} from 'react';
 import type {ViewStyle} from 'react-native';
 import {StyleSheet, View} from 'react-native';
@@ -12,7 +13,7 @@ import useOnyx from '@hooks/useOnyx';
 import useThemeStyles from '@hooks/useThemeStyles';
 import getNonEmptyStringOnyxID from '@libs/getNonEmptyStringOnyxID';
 import {getLastVisibleActionIncludingTransactionThread, getOriginalMessage, isActionableTrackExpense, isInviteOrRemovedAction} from '@libs/ReportActionsUtils';
-import {canUserPerformWriteAction as canUserPerformWriteActionUtil} from '@libs/ReportUtils';
+import {canUserPerformWriteAction as canUserPerformWriteActionUtil, shouldShowMarkAsDone} from '@libs/ReportUtils';
 import SidebarUtils from '@libs/SidebarUtils';
 import CONST from '@src/CONST';
 import {getMovedReportID} from '@src/libs/ModifiedExpenseMessage';
@@ -121,6 +122,7 @@ function OptionRowLHNData({
     const [movedFromReport] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${getMovedReportID(lastAction, CONST.REPORT.MOVE_TYPE.FROM)}`);
     const [movedToReport] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${getMovedReportID(lastAction, CONST.REPORT.MOVE_TYPE.TO)}`);
     const [policyTags] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY_TAGS}${fullReport?.policyID}`);
+    const [isTrackIntentUser] = useOnyx(ONYXKEYS.NVP_INTRO_SELECTED, {selector: isTrackIntentUserSelector});
 
     const card = useGetExpensifyCardFromReportAction({reportAction: lastAction, policyID: fullReport?.policyID});
 
@@ -159,6 +161,7 @@ function OptionRowLHNData({
         reportAttributesDerived,
         policyTags,
         currentUserLogin: login ?? '',
+        isTrackIntentUser,
     });
 
     // For single-sender IOUs, trim to the sender's avatar to match the header.
@@ -190,6 +193,13 @@ function OptionRowLHNData({
         return isReportFocused ? null : <View style={placeholderRowStyle} />;
     }
 
+    const shouldUseMarkAsDone =
+        shouldShowMarkAsDone({
+            report: fullReport,
+            isTrackIntentUser,
+            policy,
+        }) && finalOptionItem?.actionBadge === CONST.REPORT.ACTION_BADGE.SUBMIT;
+
     return (
         <OptionRowLHN
             {...propsToForward}
@@ -197,6 +207,7 @@ function OptionRowLHNData({
             isOptionFocused={isReportFocused}
             optionItem={finalOptionItem}
             hasDraftComment={hasDraftComment}
+            isMarkAsDone={shouldUseMarkAsDone}
         />
     );
 }
diff --git a/src/components/LHNOptionsList/types.ts b/src/components/LHNOptionsList/types.ts
index 829de863508a..f8aad940fdb2 100644
--- a/src/components/LHNOptionsList/types.ts
+++ b/src/components/LHNOptionsList/types.ts
@@ -95,6 +95,8 @@ type OptionRowLHNProps = {
 
     /** The testID of the row */
     testID: number;
+    /** Whether to show "Mark as done" copy instead of "Submit" copy for track-intent users */
+    isMarkAsDone?: boolean;
 };
 
 type RenderItemProps = {item: Report; index: number};
diff --git a/src/components/MoneyReportHeaderActions/MoneyReportHeaderSelectionDropdown.tsx b/src/components/MoneyReportHeaderActions/MoneyReportHeaderSelectionDropdown.tsx
index a97c7ec65438..54764d87bbb0 100644
--- a/src/components/MoneyReportHeaderActions/MoneyReportHeaderSelectionDropdown.tsx
+++ b/src/components/MoneyReportHeaderActions/MoneyReportHeaderSelectionDropdown.tsx
@@ -1,6 +1,6 @@
 import {useRoute} from '@react-navigation/native';
 import {delegateEmailSelector, isUserValidatedSelector} from '@selectors/Account';
-import {hasSeenTourSelector} from '@selectors/Onboarding';
+import {hasSeenTourSelector, isTrackIntentUserSelector} from '@selectors/Onboarding';
 import truncate from 'lodash/truncate';
 import React, {useContext} from 'react';
 import type {StyleProp, ViewStyle} from 'react-native';
@@ -53,6 +53,7 @@ import {
     hasViolations as hasViolationsReportUtils,
     isInvoiceReport as isInvoiceReportUtil,
     isIOUReport as isIOUReportUtil,
+    shouldShowMarkAsDone,
 } from '@libs/ReportUtils';
 import shouldPopoverUseScrollView from '@libs/shouldPopoverUseScrollView';
 import {isTransactionPendingDelete} from '@libs/TransactionUtils';
@@ -380,7 +381,15 @@ function MoneyReportHeaderSelectionDropdown({reportID, primaryAction, isReportIn
         });
     };
 
+    const [isTrackIntentUser] = useOnyx(ONYXKEYS.NVP_INTRO_SELECTED, {selector: isTrackIntentUserSelector});
+    const shouldUseMarkAsDoneCopy = shouldShowMarkAsDone({
+        policy,
+        report: moneyRequestReport,
+        isTrackIntentUser,
+    });
     const allExpensesSelected = selectedTransactionIDs.length > 0 && selectedTransactionIDs.length === nonPendingDeleteTransactions.length;
+    const submitButtonText = shouldUseMarkAsDoneCopy ? translate('common.markAsDone') : translate('common.submit');
+    const approveButtonText = shouldUseMarkAsDoneCopy ? translate('common.markAsDone') : translate('iou.approve');
 
     // Ref writes below are inside onSelected callbacks that only fire on user interaction, never during render.
 
@@ -388,7 +397,7 @@ function MoneyReportHeaderSelectionDropdown({reportID, primaryAction, isReportIn
         ...(hasSubmitAction && !shouldBlockSubmit
             ? [
                   {
-                      text: translate('common.submit'),
+                      text: submitButtonText,
                       icon: expensifyIcons.Send,
                       value: CONST.REPORT.PRIMARY_ACTIONS.SUBMIT,
                       onSelected: () => handleSubmitReport(true),
@@ -398,7 +407,7 @@ function MoneyReportHeaderSelectionDropdown({reportID, primaryAction, isReportIn
         ...(hasApproveAction && !isBlockSubmitDueToPreventSelfApproval
             ? [
                   {
-                      text: translate('iou.approve'),
+                      text: approveButtonText,
                       icon: expensifyIcons.ThumbsUp,
                       value: CONST.REPORT.PRIMARY_ACTIONS.APPROVE,
                       onSelected: () => confirmApproval(true),
diff --git a/src/components/MoneyReportHeaderPrimaryAction/ApprovePrimaryAction.tsx b/src/components/MoneyReportHeaderPrimaryAction/ApprovePrimaryAction.tsx
index d4f2ea916bee..688368ada57c 100644
--- a/src/components/MoneyReportHeaderPrimaryAction/ApprovePrimaryAction.tsx
+++ b/src/components/MoneyReportHeaderPrimaryAction/ApprovePrimaryAction.tsx
@@ -1,10 +1,11 @@
+import {isTrackIntentUserSelector} from '@selectors/Onboarding';
 import React from 'react';
 import Button from '@components/Button';
 import {usePaymentAnimationsContext} from '@components/PaymentAnimationsContext';
 import useLocalize from '@hooks/useLocalize';
 import useOnyx from '@hooks/useOnyx';
 import getNonEmptyStringOnyxID from '@libs/getNonEmptyStringOnyxID';
-import {getNextApproverAccountID, isReportOwner} from '@libs/ReportUtils';
+import {getNextApproverAccountID, isReportOwner, shouldShowMarkAsDone} from '@libs/ReportUtils';
 import ONYXKEYS from '@src/ONYXKEYS';
 import useConfirmApproval from './useConfirmApproval';
 
@@ -18,6 +19,13 @@ function ApprovePrimaryAction({reportID}: ApprovePrimaryActionProps) {
 
     const [moneyRequestReport] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${reportID}`);
     const [policy] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY}${getNonEmptyStringOnyxID(moneyRequestReport?.policyID)}`);
+    const [isTrackIntentUser] = useOnyx(ONYXKEYS.NVP_INTRO_SELECTED, {selector: isTrackIntentUserSelector});
+
+    const shouldUseMarkAsDoneCopy = shouldShowMarkAsDone({
+        isTrackIntentUser,
+        report: moneyRequestReport,
+        policy,
+    });
 
     const nextApproverAccountID = getNextApproverAccountID(moneyRequestReport);
     const isSubmitterSameAsNextApprover =
@@ -30,7 +38,7 @@ function ApprovePrimaryAction({reportID}: ApprovePrimaryActionProps) {
         <Button
             success
             onPress={confirmApproval}
-            text={translate('iou.approve')}
+            text={shouldUseMarkAsDoneCopy ? translate('common.markAsDone') : translate('iou.approve')}
             isDisabled={isBlockSubmitDueToPreventSelfApproval}
         />
     );
diff --git a/src/components/MoneyReportHeaderPrimaryAction/SubmitPrimaryAction.tsx b/src/components/MoneyReportHeaderPrimaryAction/SubmitPrimaryAction.tsx
index f788022b2b1e..c63c326a8356 100644
--- a/src/components/MoneyReportHeaderPrimaryAction/SubmitPrimaryAction.tsx
+++ b/src/components/MoneyReportHeaderPrimaryAction/SubmitPrimaryAction.tsx
@@ -1,4 +1,5 @@
 import {delegateEmailSelector} from '@selectors/Account';
+import {isTrackIntentUserSelector} from '@selectors/Onboarding';
 import React from 'react';
 import AnimatedSubmitButton from '@components/AnimatedSubmitButton';
 import {usePaymentAnimationsContext} from '@components/PaymentAnimationsContext';
@@ -17,7 +18,7 @@ import useTransactionsAndViolationsForReport from '@hooks/useTransactionsAndViol
 import {search} from '@libs/actions/Search';
 import getNonEmptyStringOnyxID from '@libs/getNonEmptyStringOnyxID';
 import {getFilteredReportActionsForReportView} from '@libs/ReportActionsUtils';
-import {hasViolations as hasViolationsReportUtils, shouldBlockSubmitDueToPreventSelfApproval, shouldBlockSubmitDueToStrictPolicyRules} from '@libs/ReportUtils';
+import {hasViolations as hasViolationsReportUtils, shouldBlockSubmitDueToPreventSelfApproval, shouldBlockSubmitDueToStrictPolicyRules, shouldShowMarkAsDone} from '@libs/ReportUtils';
 import {hasAnyPendingRTERViolation as hasAnyPendingRTERViolationTransactionUtils, hasOnlyPendingCardTransactions, showPendingCardTransactionsBlockModal} from '@libs/TransactionUtils';
 import {submitReport} from '@userActions/IOU/ReportWorkflow';
 import {markPendingRTERTransactionsAsCash} from '@userActions/Transaction';
@@ -44,6 +45,7 @@ function SubmitPrimaryAction({reportID}: SubmitPrimaryActionProps) {
     const [ownerBillingGracePeriodEnd] = useOnyx(ONYXKEYS.NVP_PRIVATE_OWNER_BILLING_GRACE_PERIOD_END);
     const [allTransactionViolations] = useOnyx(ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS);
     const [delegateEmail] = useOnyx(ONYXKEYS.ACCOUNT, {selector: delegateEmailSelector});
+    const [isTrackIntentUser] = useOnyx(ONYXKEYS.NVP_INTRO_SELECTED, {selector: isTrackIntentUserSelector});
 
     const isASAPSubmitBetaEnabled = isBetaEnabled(CONST.BETAS.ASAP_SUBMIT);
     const {reportActions: unfilteredReportActions} = usePaginatedReportActions(moneyRequestReport?.reportID);
@@ -70,6 +72,11 @@ function SubmitPrimaryAction({reportID}: SubmitPrimaryActionProps) {
         transactions,
     );
     const shouldBlockSubmit = isBlockSubmitDueToStrictPolicyRules || isBlockSubmitDueToPreventSelfApproval;
+    const shouldUseMarkAsDoneCopy = shouldShowMarkAsDone({
+        policy,
+        report: moneyRequestReport,
+        isTrackIntentUser,
+    });
 
     const {currentSearchQueryJSON, currentSearchKey} = useSearchQueryContext();
     const {currentSearchResults} = useSearchResultsContext();
@@ -116,7 +123,8 @@ function SubmitPrimaryAction({reportID}: SubmitPrimaryActionProps) {
     return (
         <AnimatedSubmitButton
             success
-            text={translate('common.submit')}
+            text={shouldUseMarkAsDoneCopy ? translate('common.markAsDone') : translate('common.submit')}
+            isMarkAsDone={shouldUseMarkAsDoneCopy}
             onPress={handleSubmit}
             isSubmittingAnimationRunning={isSubmittingAnimationRunning}
             onAnimationFinish={stopAnimation}
diff --git a/src/components/ReportActionItem/MoneyRequestReportPreview/SubmitActionButton.tsx b/src/components/ReportActionItem/MoneyRequestReportPreview/SubmitActionButton.tsx
index c9d7b8684d70..dc4acd7818b0 100644
--- a/src/components/ReportActionItem/MoneyRequestReportPreview/SubmitActionButton.tsx
+++ b/src/components/ReportActionItem/MoneyRequestReportPreview/SubmitActionButton.tsx
@@ -1,4 +1,5 @@
 import {delegateEmailSelector} from '@selectors/Account';
+import {isTrackIntentUserSelector} from '@selectors/Onboarding';
 import React from 'react';
 import AnimatedSubmitButton from '@components/AnimatedSubmitButton';
 import useConfirmModal from '@hooks/useConfirmModal';
@@ -9,7 +10,7 @@ import useNetwork from '@hooks/useNetwork';
 import useOnyx from '@hooks/useOnyx';
 import usePermissions from '@hooks/usePermissions';
 import useReportTransactionsCollection from '@hooks/useReportTransactionsCollection';
-import {hasViolations as hasViolationsReportUtils} from '@libs/ReportUtils';
+import {hasViolations as hasViolationsReportUtils, shouldShowMarkAsDone} from '@libs/ReportUtils';
 import {hasAnyPendingRTERViolation as hasAnyPendingRTERViolationTransactionUtils, hasOnlyPendingCardTransactions, showPendingCardTransactionsBlockModal} from '@libs/TransactionUtils';
 import {submitReport} from '@userActions/IOU/ReportWorkflow';
 import {markPendingRTERTransactionsAsCash} from '@userActions/Transaction';
@@ -40,6 +41,7 @@ function SubmitActionButton({iouReportID, isSubmittingAnimationRunning, stopAnim
     const [ownerBillingGracePeriodEnd] = useOnyx(ONYXKEYS.NVP_PRIVATE_OWNER_BILLING_GRACE_PERIOD_END);
     const [transactionViolations] = useOnyx(ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS);
     const [reportActions] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${iouReportID}`);
+    const [isTrackIntentUser] = useOnyx(ONYXKEYS.NVP_INTRO_SELECTED, {selector: isTrackIntentUserSelector});
     const [delegateEmail] = useOnyx(ONYXKEYS.ACCOUNT, {selector: delegateEmailSelector});
     const {isOffline} = useNetwork();
     const reportTransactionsCollection = useReportTransactionsCollection(iouReportID);
@@ -56,11 +58,16 @@ function SubmitActionButton({iouReportID, isSubmittingAnimationRunning, stopAnim
     };
 
     const confirmPendingRTERAndProceed = useConfirmPendingRTERAndProceed(hasAnyPendingRTERViolation, handleMarkPendingRTERTransactionsAsCash);
-
+    const shouldUseMarkAsDoneCopy = shouldShowMarkAsDone({
+        isTrackIntentUser,
+        report: iouReport,
+        policy,
+    });
     return (
         <AnimatedSubmitButton
             success
-            text={translate('common.submit')}
+            text={shouldUseMarkAsDoneCopy ? translate('common.markAsDone') : translate('common.submit')}
+            isMarkAsDone={shouldUseMarkAsDoneCopy}
             onPress={() => {
                 if (hasOnlyPendingCardTransactions(transactions)) {
                     showPendingCardTransactionsBlockModal(showConfirmModal, translate);
diff --git a/src/components/ReportWelcomeText.tsx b/src/components/ReportWelcomeText.tsx
index c380e245f0c1..3074434811db 100644
--- a/src/components/ReportWelcomeText.tsx
+++ b/src/components/ReportWelcomeText.tsx
@@ -1,6 +1,8 @@
+import {isTrackIntentUserSelector} from '@selectors/Onboarding';
 import React from 'react';
 import {View} from 'react-native';
 import type {OnyxEntry} from 'react-native-onyx';
+import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails';
 import useEnvironment from '@hooks/useEnvironment';
 import useLocalize from '@hooks/useLocalize';
 import useOnyx from '@hooks/useOnyx';
@@ -54,6 +56,7 @@ function ReportWelcomeText({report, policy}: ReportWelcomeTextProps) {
     const [invoiceReceiverPolicy] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY}${invoiceReceiverPolicyID}`);
     const isReportArchived = useReportIsArchived(report?.reportID);
     const [conciergeReportID] = useOnyx(ONYXKEYS.CONCIERGE_REPORT_ID);
+    const [isTrackIntentUser] = useOnyx(ONYXKEYS.NVP_INTRO_SELECTED, {selector: isTrackIntentUserSelector});
     const isConciergeChat = isConciergeChatReport(report, conciergeReportID);
     const isChatRoom = isChatRoomReportUtils(report);
     const isSelfDM = isSelfDMReportUtils(report);
@@ -64,6 +67,7 @@ function ReportWelcomeText({report, policy}: ReportWelcomeTextProps) {
     const participantAccountIDs = getParticipantsAccountIDsForDisplay(report, undefined, true, true, reportMetadata);
     const moneyRequestOptions = temporary_getMoneyRequestOptions(report, policy, participantAccountIDs, betas, isReportArchived, isRestrictedToPreferredPolicy);
     const policyName = getPolicyName({report});
+    const {accountID: currentUserAccountID} = useCurrentUserPersonalDetails();
 
     const filteredOptions = moneyRequestOptions.filter(
         (
@@ -124,6 +128,8 @@ function ReportWelcomeText({report, policy}: ReportWelcomeTextProps) {
         reportDetailsLink,
         shouldShowUsePlusButtonText,
         additionalText,
+        isTrackIntentUser: !!isTrackIntentUser,
+        currentUserAccountID,
     });
 
     return (
diff --git a/src/components/Search/SearchList/ListItem/ActionCell/index.tsx b/src/components/Search/SearchList/ListItem/ActionCell/index.tsx
index 97c1fe4ceda5..b2188185cd9d 100644
--- a/src/components/Search/SearchList/ListItem/ActionCell/index.tsx
+++ b/src/components/Search/SearchList/ListItem/ActionCell/index.tsx
@@ -1,10 +1,15 @@
+import {isTrackIntentUserSelector} from '@selectors/Onboarding';
 import React from 'react';
 import Button from '@components/Button';
 import useLocalize from '@hooks/useLocalize';
 import useNetwork from '@hooks/useNetwork';
+import useOnyx from '@hooks/useOnyx';
 import useThemeStyles from '@hooks/useThemeStyles';
+import getNonEmptyStringOnyxID from '@libs/getNonEmptyStringOnyxID';
 import type {ModifiedMouseEvent} from '@libs/Navigation/helpers/openInternalRouteInNewTab';
+import {shouldShowMarkAsDone} from '@libs/ReportUtils';
 import CONST from '@src/CONST';
+import ONYXKEYS from '@src/ONYXKEYS';
 import type {SearchTransactionAction} from '@src/types/onyx/SearchResults';
 import actionTranslationsMap from './actionTranslationsMap';
 import PayActionCell from './PayActionCell';
@@ -39,6 +44,9 @@ function ActionCell({
     const {translate} = useLocalize();
     const styles = useThemeStyles();
     const {isOffline} = useNetwork();
+    const [isTrackIntentUser] = useOnyx(ONYXKEYS.NVP_INTRO_SELECTED, {selector: isTrackIntentUserSelector});
+    const [actionCellPolicy] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY}${getNonEmptyStringOnyxID(policyID)}`);
+    const [actionCellReport] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${getNonEmptyStringOnyxID(reportID)}`);
 
     const shouldUseViewAction = action === CONST.SEARCH.ACTION_TYPES.VIEW || action === CONST.SEARCH.ACTION_TYPES.PAID || action === CONST.SEARCH.ACTION_TYPES.DONE;
 
@@ -79,7 +87,13 @@ function ActionCell({
         );
     }
 
-    const text = translate(actionTranslationsMap[action]);
+    const shouldUseMarkAsDone =
+        shouldShowMarkAsDone({
+            isTrackIntentUser,
+            report: actionCellReport,
+            policy: actionCellPolicy,
+        }) && action === CONST.SEARCH.ACTION_TYPES.SUBMIT;
+    const text = shouldUseMarkAsDone ? translate('common.done') : translate(actionTranslationsMap[action]);
 
     const shouldBeDisabledOffline = action !== CONST.SEARCH.ACTION_TYPES.UNDELETE && isOffline;
     const buttonInnerStyles = isSelected && action === CONST.SEARCH.ACTION_TYPES.UNDELETE ? styles.buttonDefaultSelected : {};
diff --git a/src/components/utils/getActionBadgeText.ts b/src/components/utils/getActionBadgeText.ts
new file mode 100644
index 000000000000..79d5105c6dfc
--- /dev/null
+++ b/src/components/utils/getActionBadgeText.ts
@@ -0,0 +1,11 @@
+import type {OptionData} from '@libs/ReportUtils';
+import type {TranslationPaths} from '@src/languages/types';
+
+function getActionBadgeText(actionBadge: OptionData['actionBadge'], translate: (key: TranslationPaths) => string, isMarkAsDone?: boolean): string {
+    if (!actionBadge) {
+        return '';
+    }
+    return isMarkAsDone ? translate('common.markAsDone') : translate(`common.actionBadge.${actionBadge}`);
+}
+
+export default getActionBadgeText;
diff --git a/src/hooks/useSearchBulkActions.ts b/src/hooks/useSearchBulkActions.ts
index e4ec2edd1929..02bef5178d40 100644
--- a/src/hooks/useSearchBulkActions.ts
+++ b/src/hooks/useSearchBulkActions.ts
@@ -1,4 +1,5 @@
 /* eslint-disable react-hooks/refs -- Refs in this hook are used inside callbacks that capture stable references; the lint rule flags false positives for these patterns */
+import {isTrackIntentUserSelector} from '@selectors/Onboarding';
 import {useCallback, useEffect, useMemo, useRef, useState} from 'react';
 // eslint-disable-next-line no-restricted-imports
 import {InteractionManager} from 'react-native';
@@ -35,7 +36,7 @@ import initSplitExpense from '@libs/actions/SplitExpenses';
 import {setNameValuePair} from '@libs/actions/User';
 import {getTransactionsAndReportsFromSearch} from '@libs/MergeTransactionUtils';
 import Navigation from '@libs/Navigation/Navigation';
-import {getConnectedIntegration} from '@libs/PolicyUtils';
+import {getConnectedIntegration, isSubmitAndClose} from '@libs/PolicyUtils';
 import {getSecondaryExportReportActions, isMergeActionForSelectedTransactions} from '@libs/ReportSecondaryActionUtils';
 import {
     canEditMultipleTransactions,
@@ -307,6 +308,7 @@ function useSearchBulkActions({queryJSON}: UseSearchBulkActionsParams) {
 
     const [dismissedRejectUseExplanation] = useOnyx(ONYXKEYS.NVP_DISMISSED_REJECT_USE_EXPLANATION);
     const [dismissedHoldUseExplanation] = useOnyx(ONYXKEYS.NVP_DISMISSED_HOLD_USE_EXPLANATION);
+    const [isTrackIntentUser] = useOnyx(ONYXKEYS.NVP_INTRO_SELECTED, {selector: isTrackIntentUserSelector});
 
     const isExpenseReportType = queryJSON?.type === CONST.SEARCH.DATA_TYPES.EXPENSE_REPORT;
     const expensifyIcons = useMemoizedLazyExpensifyIcons([
@@ -1343,13 +1345,21 @@ function useSearchBulkActions({queryJSON}: UseSearchBulkActionsParams) {
             !isOffline &&
             areSelectedTransactionsIncludedInReports &&
             (selectedReports.length
-                ? selectedReports.every((report) => report.allActions.includes(CONST.SEARCH.ACTION_TYPES.SUBMIT))
+                ? selectedReports.every((report) => report.allActions.includes(CONST.SEARCH.ACTION_TYPES.SUBMIT)) &&
+                  // Disable for mixed selections: all must be the same submit type
+                  (isTrackIntentUser
+                      ? selectedReports.every((report) => isSubmitAndClose(policies?.[`${ONYXKEYS.COLLECTION.POLICY}${report.policyID}`])) ||
+                        selectedReports.every((report) => !isSubmitAndClose(policies?.[`${ONYXKEYS.COLLECTION.POLICY}${report.policyID}`]))
+                      : true)
                 : selectedTransactionsKeys.every((id) => selectedTransactions[id].action === CONST.SEARCH.ACTION_TYPES.SUBMIT));
 
         if (shouldShowSubmitOption) {
             options.push({
                 icon: expensifyIcons.Send,
-                text: translate('common.submit'),
+                text:
+                    isTrackIntentUser && selectedReports.length > 0 && selectedReports.every((report) => isSubmitAndClose(policies?.[`${ONYXKEYS.COLLECTION.POLICY}${report.policyID}`]))
+                        ? translate('common.markAsDone')
+                        : translate('common.submit'),
                 value: CONST.SEARCH.BULK_ACTION_TYPES.SUBMIT,
                 shouldCloseModalOnSelect: true,
                 onSelected: () => {
@@ -1700,6 +1710,7 @@ function useSearchBulkActions({queryJSON}: UseSearchBulkActionsParams) {
         userBillingGracePeriodEnds,
         ownerBillingGracePeriodEnd,
         currentSearchKey,
+        isTrackIntentUser,
         getCurrencyDecimals,
         amountOwed,
         allTransactions,
diff --git a/src/hooks/useSearchTypeMenuSections.ts b/src/hooks/useSearchTypeMenuSections.ts
index b30b4d0bd8d8..28920ad130ff 100644
--- a/src/hooks/useSearchTypeMenuSections.ts
+++ b/src/hooks/useSearchTypeMenuSections.ts
@@ -2,11 +2,11 @@ import {defaultExpensifyCardSelector} from '@selectors/Card';
 import {validTransactionDraftIDsSelector} from '@selectors/TransactionDraft';
 import {useCallback, useEffect, useMemo, useState} from 'react';
 import type {OnyxEntry} from 'react-native-onyx';
-import isTrackOnboardingChoice from '@libs/OnboardingUtils';
 import {createTypeMenuSections, doesSearchItemMatchSort} from '@libs/SearchUIUtils';
 import CONST from '@src/CONST';
 import ONYXKEYS from '@src/ONYXKEYS';
-import type {IntroSelected, Policy, Session} from '@src/types/onyx';
+import {isTrackIntentUserSelector} from '@src/selectors/Onboarding';
+import type {Policy, Session} from '@src/types/onyx';
 import useCardFeedsForDisplay from './useCardFeedsForDisplay';
 import useCreateEmptyReportConfirmation from './useCreateEmptyReportConfirmation';
 import useMappedPolicies from './useMappedPolicies';
@@ -44,8 +44,6 @@ const currentUserLoginAndAccountIDSelector = (session: OnyxEntry<Session>) => ({
     accountID: session?.accountID,
 });
 
-const isTrackIntentUserSelector = (introSelected: OnyxEntry<IntroSelected>) => isTrackOnboardingChoice(introSelected?.choice);
-
 type UseSearchTypeMenuSectionsParams = {
     hash?: number;
     similarSearchHash?: number;
diff --git a/src/languages/de.ts b/src/languages/de.ts
index a1428306253a..245cd30d521a 100644
--- a/src/languages/de.ts
+++ b/src/languages/de.ts
@@ -108,7 +108,9 @@ const translations: TranslationDeepObject<typeof en> = {
         selectMultiple: 'Mehrfachauswahl',
         saveChanges: 'Änderungen speichern',
         submit: 'Senden',
+        markAsDone: 'Als erledigt markieren',
         submitted: 'Übermittelt',
+        markedAsDoneStatus: 'Als erledigt markiert',
         rotate: 'Drehen',
         zoom: 'Zoom',
         password: 'Passwort',
@@ -847,6 +849,7 @@ const translations: TranslationDeepObject<typeof en> = {
         beginningOfChatHistory: (users: string) => `Dieser Chat ist mit ${users}.`,
         beginningOfChatHistoryPolicyExpenseChat: (workspaceName: string, submitterDisplayName: string) =>
             `Hier reicht <strong>${submitterDisplayName}</strong> Auslagen bei <strong>${workspaceName}</strong> ein. Nutze einfach die +-Taste.`,
+        beginningOfChatHistoryPolicyExpenseChatTrack: 'Hier können Sie Ausgaben nachverfolgen',
         beginningOfChatHistorySelfDM: 'Dies ist dein persönlicher Bereich. Nutze ihn für Notizen, Aufgaben, Entwürfe und Erinnerungen.',
         beginningOfChatHistorySystemDM: 'Willkommen! Lassen Sie uns Ihre Einrichtung vornehmen.',
         chatWithAccountManager: 'Chatte hier mit deiner/deinem Account Manager',
@@ -1342,6 +1345,7 @@ const translations: TranslationDeepObject<typeof en> = {
         sendInvoice: (amount: string) => `${amount}-Rechnung senden`,
         expenseAmount: (formattedAmount: string, comment?: string) => `${formattedAmount}${comment ? `für ${comment}` : ''}`,
         submitted: (memo?: string) => `eingereicht${memo ? `, mit dem Vermerk ${memo}` : ''}`,
+        markedAsDone: (memo) => `als erledigt markiert${memo ? `, mit dem Vermerk ${memo}` : ''}`,
         automaticallySubmitted: `eingereicht über <a href="${CONST.SELECT_WORKFLOWS_HELP_URL}">Einreichungen verzögern</a>`,
         queuedToSubmitViaDEW: 'zur Einreichung über benutzerdefinierten Genehmigungsworkflow eingereiht',
         queuedToApproveViaDEW: 'Zur Genehmigung über benutzerdefinierten Genehmigungsworkflow eingereiht',
@@ -1786,6 +1790,21 @@ const translations: TranslationDeepObject<typeof en> = {
                         return `Warten darauf, dass ein Admin Spesen einreicht.`;
                 }
             },
+            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_TO_MARK_AS_DONE]: (
+                actor: string,
+                actorType: ValueOf<typeof CONST.NEXT_STEP.ACTOR_TYPE>,
+                _eta?: string,
+                _etaType?: ValueOf<typeof CONST.NEXT_STEP.ETA_TYPE>,
+            ) => {
+                switch (actorType) {
+                    case CONST.NEXT_STEP.ACTOR_TYPE.CURRENT_USER:
+                        return `Wartet darauf, dass <strong>Sie</strong> dies als erledigt markieren.`;
+                    case CONST.NEXT_STEP.ACTOR_TYPE.OTHER_USER:
+                        return `Warten darauf, dass <strong>${actor}</strong> dies als erledigt markiert.`;
+                    case CONST.NEXT_STEP.ACTOR_TYPE.UNSPECIFIED_ADMIN:
+                        return `Warten darauf, dass ein Admin dies als erledigt markiert.`;
+                }
+            },
             [CONST.NEXT_STEP.MESSAGE_KEY.NO_FURTHER_ACTION]: (
                 _actor: string,
                 _actorType: ValueOf<typeof CONST.NEXT_STEP.ACTOR_TYPE>,
diff --git a/src/languages/en.ts b/src/languages/en.ts
index b37663c2ee86..dd648a0532e0 100644
--- a/src/languages/en.ts
+++ b/src/languages/en.ts
@@ -109,8 +109,11 @@ const translations = {
         selectMultiple: 'Select multiple',
         saveChanges: 'Save changes',
         submit: 'Submit',
+        markAsDone: 'Mark as done',
         // @context Status label meaning an item has already been sent or submitted (e.g., a form or report). Not the action “to submit.”
         submitted: 'Submitted',
+        // @context Status label meaning an item has been marked as done (track-intent users). Not the action “to mark as done.”
+        markedAsDoneStatus: 'Marked as done',
         rotate: 'Rotate',
         zoom: 'Zoom',
         password: 'Password',
@@ -880,6 +883,7 @@ const translations = {
         beginningOfChatHistory: (users: string) => `This chat is with ${users}.`,
         beginningOfChatHistoryPolicyExpenseChat: (workspaceName: string, submitterDisplayName: string) =>
             `This is where <strong>${submitterDisplayName}</strong> will submit expenses to <strong>${workspaceName}</strong>. Just use the + button.`,
+        beginningOfChatHistoryPolicyExpenseChatTrack: "This is where you'll track expenses.",
         beginningOfChatHistorySelfDM: 'This is your personal space. Use it for notes, tasks, drafts, and reminders.',
         beginningOfChatHistorySystemDM: "Welcome! Let's get you set up.",
         chatWithAccountManager: 'Chat with your account manager here',
@@ -1399,6 +1403,7 @@ const translations = {
         sendInvoice: (amount: string) => `Send ${amount} invoice`,
         expenseAmount: (formattedAmount: string, comment?: string) => `${formattedAmount}${comment ? ` for ${comment}` : ''}`,
         submitted: (memo?: string) => `submitted${memo ? `, saying ${memo}` : ''}`,
+        markedAsDone: (memo?: string) => `marked as done${memo ? `, saying ${memo}` : ''}`,
         automaticallySubmitted: `submitted via <a href="${CONST.SELECT_WORKFLOWS_HELP_URL}">delay submissions</a>`,
         queuedToSubmitViaDEW: 'queued to submit via custom approval workflow',
         failedToAutoSubmitViaDEW: (reason: string) => `failed to submit the report via <a href="${CONST.SELECT_WORKFLOWS_HELP_URL}">delay submissions</a>. ${reason}`,
@@ -1842,6 +1847,22 @@ const translations = {
                         return `Waiting for an admin to submit expenses.`;
                 }
             },
+            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_TO_MARK_AS_DONE]: (
+                actor: string,
+                actorType: ValueOf<typeof CONST.NEXT_STEP.ACTOR_TYPE>,
+                _eta?: string,
+                _etaType?: ValueOf<typeof CONST.NEXT_STEP.ETA_TYPE>,
+            ) => {
+                // eslint-disable-next-line default-case
+                switch (actorType) {
+                    case CONST.NEXT_STEP.ACTOR_TYPE.CURRENT_USER:
+                        return `Waiting for <strong>you</strong> to mark this as done.`;
+                    case CONST.NEXT_STEP.ACTOR_TYPE.OTHER_USER:
+                        return `Waiting for <strong>${actor}</strong> to mark this as done.`;
+                    case CONST.NEXT_STEP.ACTOR_TYPE.UNSPECIFIED_ADMIN:
+                        return `Waiting for an admin to mark this as done.`;
+                }
+            },
             [CONST.NEXT_STEP.MESSAGE_KEY.NO_FURTHER_ACTION]: (
                 _actor: string,
                 _actorType: ValueOf<typeof CONST.NEXT_STEP.ACTOR_TYPE>,
diff --git a/src/languages/es.ts b/src/languages/es.ts
index 49c6c41c3537..c405cfac9c34 100644
--- a/src/languages/es.ts
+++ b/src/languages/es.ts
@@ -63,7 +63,9 @@ const translations: TranslationDeepObject<typeof en> = {
         save: 'Guardar',
         saveChanges: 'Guardar cambios',
         submit: 'Enviar',
+        markAsDone: 'Marcar como listo',
         submitted: 'Enviado',
+        markedAsDoneStatus: 'Marcado como listo',
         rotate: 'Rotar',
         zoom: 'Zoom',
         password: 'Contraseña',
@@ -795,6 +797,7 @@ const translations: TranslationDeepObject<typeof en> = {
         beginningOfChatHistory: (users) => `Este chat es con ${users}.`,
         beginningOfChatHistoryPolicyExpenseChat: (workspaceName, submitterDisplayName) =>
             `Aquí es donde <strong>${submitterDisplayName}</strong> enviará los gastos al espacio de trabajo <strong>${workspaceName}</strong>. Solo usa el botón +.`,
+        beginningOfChatHistoryPolicyExpenseChatTrack: 'Aquí es donde harás seguimiento de los gastos',
         beginningOfChatHistorySelfDM: 'Este es tu espacio personal. Úsalo para notas, tareas, borradores y recordatorios.',
         beginningOfChatHistorySystemDM: '¡Bienvenido! Vamos a configurar tu cuenta.',
         chatWithAccountManager: 'Chatea con tu gestor de cuenta aquí',
@@ -1305,6 +1308,7 @@ const translations: TranslationDeepObject<typeof en> = {
         sendInvoice: (amount) => `Enviar factura de ${amount}`,
         expenseAmount: (formattedAmount, comment) => `${formattedAmount}${comment ? ` para ${comment}` : ''}`,
         submitted: (memo) => `enviado${memo ? `, dijo ${memo}` : ''}`,
+        markedAsDone: (memo) => `marcado como listo${memo ? `, dijo ${memo}` : ''}`,
         automaticallySubmitted: `envió mediante <a href="${CONST.SELECT_WORKFLOWS_HELP_URL}">retrasar envíos</a>`,
         queuedToSubmitViaDEW: 'en cola para enviar a través del flujo de aprobación personalizado',
         failedToAutoSubmitViaDEW: (reason: string) => `no ha podido enviar este informe mediante <a href="${CONST.SELECT_WORKFLOWS_HELP_URL}">retrasar envíos</a>. ${reason}`,
@@ -1731,6 +1735,17 @@ const translations: TranslationDeepObject<typeof en> = {
                         return `Esperando a que un administrador envíe los gastos.`;
                 }
             },
+            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_TO_MARK_AS_DONE]: (actor, actorType, _eta, _etaType) => {
+                // eslint-disable-next-line default-case
+                switch (actorType) {
+                    case CONST.NEXT_STEP.ACTOR_TYPE.CURRENT_USER:
+                        return `Esperando a que <strong>tú</strong> lo marques como listo.`;
+                    case CONST.NEXT_STEP.ACTOR_TYPE.OTHER_USER:
+                        return `Esperando a que <strong>${actor}</strong> lo marque como listo.`;
+                    case CONST.NEXT_STEP.ACTOR_TYPE.UNSPECIFIED_ADMIN:
+                        return `Esperando a que un administrador lo marque como listo.`;
+                }
+            },
             [CONST.NEXT_STEP.MESSAGE_KEY.NO_FURTHER_ACTION]: (_actor, _actorType, _eta, _etaType) => `¡No se requiere ninguna acción adicional!`,
             [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_FOR_SUBMITTER_ACCOUNT]: (actor, actorType, _eta, _etaType) => {
                 switch (actorType) {
diff --git a/src/languages/fr.ts b/src/languages/fr.ts
index 28fa0270c5ca..8187484cac72 100644
--- a/src/languages/fr.ts
+++ b/src/languages/fr.ts
@@ -108,7 +108,9 @@ const translations: TranslationDeepObject<typeof en> = {
         selectMultiple: 'Sélection multiple',
         saveChanges: 'Enregistrer les modifications',
         submit: 'Soumettre',
+        markAsDone: 'Marquer comme terminé',
         submitted: 'Soumis',
+        markedAsDoneStatus: 'Marqué comme terminé',
         rotate: 'Pivoter',
         zoom: 'Zoom',
         password: 'Mot de passe',
@@ -850,6 +852,7 @@ const translations: TranslationDeepObject<typeof en> = {
         beginningOfChatHistory: (users: string) => `Cette discussion est avec ${users}.`,
         beginningOfChatHistoryPolicyExpenseChat: (workspaceName: string, submitterDisplayName: string) =>
             `C’est ici que <strong>${submitterDisplayName}</strong> soumettra des dépenses à <strong>${workspaceName}</strong>. Utilisez simplement le bouton +.`,
+        beginningOfChatHistoryPolicyExpenseChatTrack: 'C\u2019est ici que vous suivrez vos dépenses',
         beginningOfChatHistorySelfDM: 'Ceci est votre espace personnel. Utilisez-le pour vos notes, tâches, brouillons et rappels.',
         beginningOfChatHistorySystemDM: 'Bienvenue ! Procédons à la configuration.',
         chatWithAccountManager: 'Discutez avec votre gestionnaire de compte ici',
@@ -1347,6 +1350,7 @@ const translations: TranslationDeepObject<typeof en> = {
         sendInvoice: (amount: string) => `Envoyer la facture de ${amount}`,
         expenseAmount: (formattedAmount: string, comment?: string) => `${formattedAmount}${comment ? `pour ${comment}` : ''}`,
         submitted: (memo?: string) => `soumis${memo ? `, indiquant « ${memo} »` : ''}`,
+        markedAsDone: (memo?: string) => `marqué comme terminé${memo ? `, en indiquant « ${memo} »` : ''}`,
         automaticallySubmitted: `soumis via <a href="${CONST.SELECT_WORKFLOWS_HELP_URL}">soumissions différées</a>`,
         queuedToSubmitViaDEW: 'en file d’attente pour être soumis via le circuit d’approbation personnalisé',
         queuedToApproveViaDEW: 'mis en file d’attente pour approbation via un processus d’approbation personnalisé',
@@ -1792,6 +1796,21 @@ const translations: TranslationDeepObject<typeof en> = {
                         return `En attente qu’un administrateur soumette des dépenses.`;
                 }
             },
+            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_TO_MARK_AS_DONE]: (
+                actor: string,
+                actorType: ValueOf<typeof CONST.NEXT_STEP.ACTOR_TYPE>,
+                _eta?: string,
+                _etaType?: ValueOf<typeof CONST.NEXT_STEP.ETA_TYPE>,
+            ) => {
+                switch (actorType) {
+                    case CONST.NEXT_STEP.ACTOR_TYPE.CURRENT_USER:
+                        return `En attente que <strong>vous</strong> marquiez ceci comme terminé.`;
+                    case CONST.NEXT_STEP.ACTOR_TYPE.OTHER_USER:
+                        return `En attente que <strong>${actor}</strong> marque ceci comme terminé.`;
+                    case CONST.NEXT_STEP.ACTOR_TYPE.UNSPECIFIED_ADMIN:
+                        return `En attente qu'un administrateur marque ceci comme terminé.`;
+                }
+            },
             [CONST.NEXT_STEP.MESSAGE_KEY.NO_FURTHER_ACTION]: (
                 _actor: string,
                 _actorType: ValueOf<typeof CONST.NEXT_STEP.ACTOR_TYPE>,
diff --git a/src/languages/it.ts b/src/languages/it.ts
index 8ab6b4ea1ee0..46ba81c40fa8 100644
--- a/src/languages/it.ts
+++ b/src/languages/it.ts
@@ -108,7 +108,9 @@ const translations: TranslationDeepObject<typeof en> = {
         selectMultiple: 'Selezione multipla',
         saveChanges: 'Salva modifiche',
         submit: 'Invia',
+        markAsDone: 'Segna come completata',
         submitted: 'Inviato',
+        markedAsDoneStatus: 'Contrassegnato come completato',
         rotate: 'Ruota',
         zoom: 'Zoom',
         password: 'Password',
@@ -848,6 +850,7 @@ const translations: TranslationDeepObject<typeof en> = {
         beginningOfChatHistory: (users: string) => `Questa chat è con ${users}.`,
         beginningOfChatHistoryPolicyExpenseChat: (workspaceName: string, submitterDisplayName: string) =>
             `Qui è dove <strong>${submitterDisplayName}</strong> invierà le spese a <strong>${workspaceName}</strong>. Usa semplicemente il pulsante +.`,
+        beginningOfChatHistoryPolicyExpenseChatTrack: 'Qui è dove terrai traccia delle spese',
         beginningOfChatHistorySelfDM: 'Questo è il tuo spazio personale. Usalo per note, attività, bozze e promemoria.',
         beginningOfChatHistorySystemDM: 'Benvenuto/a! Procediamo con la configurazione.',
         chatWithAccountManager: 'Chatta qui con il tuo account manager',
@@ -1342,6 +1345,7 @@ const translations: TranslationDeepObject<typeof en> = {
         sendInvoice: (amount: string) => `Invia fattura da ${amount}`,
         expenseAmount: (formattedAmount: string, comment?: string) => `${formattedAmount}${comment ? `per ${comment}` : ''}`,
         submitted: (memo?: string) => `inviato${memo ? `, con nota: ${memo}` : ''}`,
+        markedAsDone: (memo) => `contrassegnata come completata${memo ? `, dicendo ${memo}` : ''}`,
         automaticallySubmitted: `inviato tramite <a href="${CONST.SELECT_WORKFLOWS_HELP_URL}">invio posticipato</a>`,
         queuedToSubmitViaDEW: 'in coda per l’invio tramite flusso di approvazione personalizzato',
         queuedToApproveViaDEW: 'in coda per l’approvazione tramite flusso di approvazione personalizzato',
@@ -1784,6 +1788,21 @@ const translations: TranslationDeepObject<typeof en> = {
                         return `In attesa che un amministratore invii le spese.`;
                 }
             },
+            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_TO_MARK_AS_DONE]: (
+                actor: string,
+                actorType: ValueOf<typeof CONST.NEXT_STEP.ACTOR_TYPE>,
+                _eta?: string,
+                _etaType?: ValueOf<typeof CONST.NEXT_STEP.ETA_TYPE>,
+            ) => {
+                switch (actorType) {
+                    case CONST.NEXT_STEP.ACTOR_TYPE.CURRENT_USER:
+                        return `In attesa che <strong>tu</strong> lo segni come completato.`;
+                    case CONST.NEXT_STEP.ACTOR_TYPE.OTHER_USER:
+                        return `In attesa che <strong>${actor}</strong> lo segni come completato.`;
+                    case CONST.NEXT_STEP.ACTOR_TYPE.UNSPECIFIED_ADMIN:
+                        return `In attesa che un amministratore lo segni come completato.`;
+                }
+            },
             [CONST.NEXT_STEP.MESSAGE_KEY.NO_FURTHER_ACTION]: (
                 _actor: string,
                 _actorType: ValueOf<typeof CONST.NEXT_STEP.ACTOR_TYPE>,
diff --git a/src/languages/ja.ts b/src/languages/ja.ts
index c2cd656b7a3c..ea9fa1edc6d0 100644
--- a/src/languages/ja.ts
+++ b/src/languages/ja.ts
@@ -108,7 +108,9 @@ const translations: TranslationDeepObject<typeof en> = {
         selectMultiple: '複数選択',
         saveChanges: '変更を保存',
         submit: '送信',
+        markAsDone: '完了にする',
         submitted: '送信済み',
+        markedAsDoneStatus: '完了済み',
         rotate: '回転',
         zoom: 'ズーム',
         password: 'パスワード',
@@ -837,6 +839,7 @@ const translations: TranslationDeepObject<typeof en> = {
         beginningOfChatHistory: (users: string) => `このチャットの相手は${users}です。`,
         beginningOfChatHistoryPolicyExpenseChat: (workspaceName: string, submitterDisplayName: string) =>
             `ここは<strong>${submitterDisplayName}</strong>さんが<strong>${workspaceName}</strong>に経費精算を提出する場所です。+ボタンを押すだけでOKです。`,
+        beginningOfChatHistoryPolicyExpenseChatTrack: 'ここは経費を管理する場所です',
         beginningOfChatHistorySelfDM: 'ここはあなたの個人スペースです。メモ、タスク、下書き、リマインダーに活用してください。',
         beginningOfChatHistorySystemDM: 'ようこそ！設定を始めましょう。',
         chatWithAccountManager: 'ここでアカウントマネージャーとチャットする',
@@ -1328,6 +1331,7 @@ const translations: TranslationDeepObject<typeof en> = {
         sendInvoice: (amount: string) => `${amount} の請求書を送信`,
         expenseAmount: (formattedAmount: string, comment?: string) => `${formattedAmount}${comment ? `${comment}用` : ''}`,
         submitted: (memo?: string) => `送信済み${memo ? `、メモ: ${memo}` : ''}`,
+        markedAsDone: (memo) => `完了としてマークしました${memo ? `（メモ：${memo}）` : ''}`,
         automaticallySubmitted: `<a href="${CONST.SELECT_WORKFLOWS_HELP_URL}">提出の延期</a> 経由で提出されました`,
         queuedToSubmitViaDEW: 'カスタム承認ワークフローで提出待ち',
         queuedToApproveViaDEW: 'カスタム承認ワークフローで承認待ちに設定されました',
@@ -1767,6 +1771,21 @@ const translations: TranslationDeepObject<typeof en> = {
                         return `管理者が経費を送信するのを待っています。`;
                 }
             },
+            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_TO_MARK_AS_DONE]: (
+                actor: string,
+                actorType: ValueOf<typeof CONST.NEXT_STEP.ACTOR_TYPE>,
+                _eta?: string,
+                _etaType?: ValueOf<typeof CONST.NEXT_STEP.ETA_TYPE>,
+            ) => {
+                switch (actorType) {
+                    case CONST.NEXT_STEP.ACTOR_TYPE.CURRENT_USER:
+                        return `<strong>あなた</strong>が完了にするのを待っています。`;
+                    case CONST.NEXT_STEP.ACTOR_TYPE.OTHER_USER:
+                        return `<strong>${actor}</strong>が完了にするのを待っています。`;
+                    case CONST.NEXT_STEP.ACTOR_TYPE.UNSPECIFIED_ADMIN:
+                        return `管理者が完了にするのを待っています。`;
+                }
+            },
             [CONST.NEXT_STEP.MESSAGE_KEY.NO_FURTHER_ACTION]: (
                 _actor: string,
                 _actorType: ValueOf<typeof CONST.NEXT_STEP.ACTOR_TYPE>,
diff --git a/src/languages/nl.ts b/src/languages/nl.ts
index 6a1181594d1a..f44ba8c1d33a 100644
--- a/src/languages/nl.ts
+++ b/src/languages/nl.ts
@@ -108,7 +108,9 @@ const translations: TranslationDeepObject<typeof en> = {
         selectMultiple: 'Meerdere selecteren',
         saveChanges: 'Wijzigingen opslaan',
         submit: 'Verzenden',
+        markAsDone: 'Markeren als voltooid',
         submitted: 'Ingediend',
+        markedAsDoneStatus: 'Als voltooid gemarkeerd',
         rotate: 'Draaien',
         zoom: 'Zoom',
         password: 'Wachtwoord',
@@ -846,6 +848,7 @@ const translations: TranslationDeepObject<typeof en> = {
         beginningOfChatHistory: (users: string) => `Deze chat is met ${users}.`,
         beginningOfChatHistoryPolicyExpenseChat: (workspaceName: string, submitterDisplayName: string) =>
             `Dit is waar <strong>${submitterDisplayName}</strong> declaraties indient bij <strong>${workspaceName}</strong>. Gebruik gewoon de +-knop.`,
+        beginningOfChatHistoryPolicyExpenseChatTrack: 'Hier houd je je uitgaven bij',
         beginningOfChatHistorySelfDM: 'Dit is je persoonlijke ruimte. Gebruik het voor notities, taken, concepten en herinneringen.',
         beginningOfChatHistorySystemDM: 'Welkom! Laten we je instellen.',
         chatWithAccountManager: 'Chat hier met je accountmanager',
@@ -1340,6 +1343,7 @@ const translations: TranslationDeepObject<typeof en> = {
         sendInvoice: (amount: string) => `Verzend factuur van ${amount}`,
         expenseAmount: (formattedAmount: string, comment?: string) => `${formattedAmount}${comment ? `voor ${comment}` : ''}`,
         submitted: (memo?: string) => `ingediend${memo ? `, met de omschrijving ${memo}` : ''}`,
+        markedAsDone: (memo) => `gemarkeerd als voltooid${memo ? `, met als omschrijving ${memo}` : ''}`,
         automaticallySubmitted: `ingediend via <a href="${CONST.SELECT_WORKFLOWS_HELP_URL}">uitgestelde indieningen</a>`,
         queuedToSubmitViaDEW: 'in wachtrij om via aangepast goedkeuringsproces in te dienen',
         queuedToApproveViaDEW: 'in de wachtrij gezet voor goedkeuring via aangepaste goedkeuringsworkflow',
@@ -1779,6 +1783,21 @@ const translations: TranslationDeepObject<typeof en> = {
                         return `Wachten tot een beheerder de onkosten indient.`;
                 }
             },
+            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_TO_MARK_AS_DONE]: (
+                actor: string,
+                actorType: ValueOf<typeof CONST.NEXT_STEP.ACTOR_TYPE>,
+                _eta?: string,
+                _etaType?: ValueOf<typeof CONST.NEXT_STEP.ETA_TYPE>,
+            ) => {
+                switch (actorType) {
+                    case CONST.NEXT_STEP.ACTOR_TYPE.CURRENT_USER:
+                        return `Er wordt gewacht tot <strong>jij</strong> dit als voltooid markeert.`;
+                    case CONST.NEXT_STEP.ACTOR_TYPE.OTHER_USER:
+                        return `Wachten tot <strong>${actor}</strong> dit als voltooid markeert.`;
+                    case CONST.NEXT_STEP.ACTOR_TYPE.UNSPECIFIED_ADMIN:
+                        return `Wachten tot een beheerder dit als voltooid markeert.`;
+                }
+            },
             [CONST.NEXT_STEP.MESSAGE_KEY.NO_FURTHER_ACTION]: (
                 _actor: string,
                 _actorType: ValueOf<typeof CONST.NEXT_STEP.ACTOR_TYPE>,
diff --git a/src/languages/pl.ts b/src/languages/pl.ts
index a7140cf7275f..39c5d5dd9e4a 100644
--- a/src/languages/pl.ts
+++ b/src/languages/pl.ts
@@ -108,7 +108,9 @@ const translations: TranslationDeepObject<typeof en> = {
         selectMultiple: 'Wielokrotny wybór',
         saveChanges: 'Zapisz zmiany',
         submit: 'Wyślij',
+        markAsDone: 'Oznacz jako wykonane',
         submitted: 'Przesłano',
+        markedAsDoneStatus: 'Oznaczone jako ukończone',
         rotate: 'Obróć',
         zoom: 'Powiększenie',
         password: 'Hasło',
@@ -847,6 +849,7 @@ const translations: TranslationDeepObject<typeof en> = {
         beginningOfChatHistory: (users: string) => `Ten czat jest z ${users}.`,
         beginningOfChatHistoryPolicyExpenseChat: (workspaceName: string, submitterDisplayName: string) =>
             `Tutaj <strong>${submitterDisplayName}</strong> będzie przesyłać wydatki do <strong>${workspaceName}</strong>. Po prostu użyj przycisku +.`,
+        beginningOfChatHistoryPolicyExpenseChatTrack: 'Tutaj będziesz śledzić wydatki',
         beginningOfChatHistorySelfDM: 'To Twoja osobista przestrzeń. Używaj jej na notatki, zadania, szkice i przypomnienia.',
         beginningOfChatHistorySystemDM: 'Witamy! Zacznijmy konfigurację.',
         chatWithAccountManager: 'Porozmawiaj tutaj z opiekunem konta',
@@ -1340,6 +1343,7 @@ const translations: TranslationDeepObject<typeof en> = {
         sendInvoice: (amount: string) => `Wyślij fakturę na ${amount}`,
         expenseAmount: (formattedAmount: string, comment?: string) => `${formattedAmount}${comment ? `za ${comment}` : ''}`,
         submitted: (memo?: string) => `przesłano${memo ? `, wpisując ${memo}` : ''}`,
+        markedAsDone: (memo) => `oznaczono jako zakończone${memo ? `, z adnotacją: ${memo}` : ''}`,
         automaticallySubmitted: `przesłano przez <a href="${CONST.SELECT_WORKFLOWS_HELP_URL}">opóźnianie wysyłania</a>`,
         queuedToSubmitViaDEW: 'w kolejce do przesłania przez niestandardowy proces zatwierdzania',
         queuedToApproveViaDEW: 'oczekuje na zatwierdzenie w niestandardowym procesie akceptacji',
@@ -1780,6 +1784,21 @@ const translations: TranslationDeepObject<typeof en> = {
                         return `Oczekiwanie, aż administrator złoży wydatki.`;
                 }
             },
+            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_TO_MARK_AS_DONE]: (
+                actor: string,
+                actorType: ValueOf<typeof CONST.NEXT_STEP.ACTOR_TYPE>,
+                _eta?: string,
+                _etaType?: ValueOf<typeof CONST.NEXT_STEP.ETA_TYPE>,
+            ) => {
+                switch (actorType) {
+                    case CONST.NEXT_STEP.ACTOR_TYPE.CURRENT_USER:
+                        return `Czekamy, aż <strong>Ty</strong> oznaczysz to jako wykonane.`;
+                    case CONST.NEXT_STEP.ACTOR_TYPE.OTHER_USER:
+                        return `Oczekiwanie, aż <strong>${actor}</strong> oznaczy to jako wykonane.`;
+                    case CONST.NEXT_STEP.ACTOR_TYPE.UNSPECIFIED_ADMIN:
+                        return `Oczekiwanie, aż administrator oznaczy to jako wykonane.`;
+                }
+            },
             [CONST.NEXT_STEP.MESSAGE_KEY.NO_FURTHER_ACTION]: (
                 _actor: string,
                 _actorType: ValueOf<typeof CONST.NEXT_STEP.ACTOR_TYPE>,
diff --git a/src/languages/pt-BR.ts b/src/languages/pt-BR.ts
index d513966555f1..1b673006e558 100644
--- a/src/languages/pt-BR.ts
+++ b/src/languages/pt-BR.ts
@@ -108,7 +108,9 @@ const translations: TranslationDeepObject<typeof en> = {
         selectMultiple: 'Seleção múltipla',
         saveChanges: 'Salvar alterações',
         submit: 'Enviar',
+        markAsDone: 'Marcar como concluído',
         submitted: 'Enviado',
+        markedAsDoneStatus: 'Marcado como concluído',
         rotate: 'Girar',
         zoom: 'Zoom',
         password: 'Senha',
@@ -846,6 +848,7 @@ const translations: TranslationDeepObject<typeof en> = {
         beginningOfChatHistory: (users: string) => `Este chat é com ${users}.`,
         beginningOfChatHistoryPolicyExpenseChat: (workspaceName: string, submitterDisplayName: string) =>
             `É aqui que <strong>${submitterDisplayName}</strong> enviará despesas para <strong>${workspaceName}</strong>. Basta usar o botão +.`,
+        beginningOfChatHistoryPolicyExpenseChatTrack: 'É aqui que você vai acompanhar as despesas',
         beginningOfChatHistorySelfDM: 'Este é o seu espaço pessoal. Use-o para anotações, tarefas, rascunhos e lembretes.',
         beginningOfChatHistorySystemDM: 'Bem-vindo(a)! Vamos fazer a sua configuração.',
         chatWithAccountManager: 'Converse com seu gerente de conta aqui',
@@ -1340,6 +1343,7 @@ const translations: TranslationDeepObject<typeof en> = {
         sendInvoice: (amount: string) => `Enviar fatura de ${amount}`,
         expenseAmount: (formattedAmount: string, comment?: string) => `${formattedAmount}${comment ? `para ${comment}` : ''}`,
         submitted: (memo?: string) => `enviado${memo ? `, dizendo ${memo}` : ''}`,
+        markedAsDone: (memo) => `marcado como concluído${memo ? `, dizendo ${memo}` : ''}`,
         automaticallySubmitted: `enviado via <a href="${CONST.SELECT_WORKFLOWS_HELP_URL}">atrasar envios</a>`,
         queuedToSubmitViaDEW: 'na fila para enviar via fluxo de aprovação personalizado',
         queuedToApproveViaDEW: 'na fila para aprovar via fluxo de aprovação personalizado',
@@ -1777,6 +1781,21 @@ const translations: TranslationDeepObject<typeof en> = {
                         return `Aguardando um administrador enviar as despesas.`;
                 }
             },
+            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_TO_MARK_AS_DONE]: (
+                actor: string,
+                actorType: ValueOf<typeof CONST.NEXT_STEP.ACTOR_TYPE>,
+                _eta?: string,
+                _etaType?: ValueOf<typeof CONST.NEXT_STEP.ETA_TYPE>,
+            ) => {
+                switch (actorType) {
+                    case CONST.NEXT_STEP.ACTOR_TYPE.CURRENT_USER:
+                        return `Aguardando <strong>você</strong> marcar como concluído.`;
+                    case CONST.NEXT_STEP.ACTOR_TYPE.OTHER_USER:
+                        return `Aguardando <strong>${actor}</strong> marcar como concluído.`;
+                    case CONST.NEXT_STEP.ACTOR_TYPE.UNSPECIFIED_ADMIN:
+                        return `Aguardando um administrador marcar como concluído.`;
+                }
+            },
             [CONST.NEXT_STEP.MESSAGE_KEY.NO_FURTHER_ACTION]: (
                 _actor: string,
                 _actorType: ValueOf<typeof CONST.NEXT_STEP.ACTOR_TYPE>,
diff --git a/src/languages/zh-hans.ts b/src/languages/zh-hans.ts
index 882adf310116..67252a8e584f 100644
--- a/src/languages/zh-hans.ts
+++ b/src/languages/zh-hans.ts
@@ -108,7 +108,9 @@ const translations: TranslationDeepObject<typeof en> = {
         selectMultiple: '多选',
         saveChanges: '保存更改',
         submit: '提交',
+        markAsDone: '标记为完成',
         submitted: '已提交',
+        markedAsDoneStatus: '已标记为完成',
         rotate: '旋转',
         zoom: '缩放',
         password: '密码',
@@ -825,6 +827,7 @@ const translations: TranslationDeepObject<typeof en> = {
         beginningOfChatHistory: (users: string) => `此聊天对象为 ${users}。`,
         beginningOfChatHistoryPolicyExpenseChat: (workspaceName: string, submitterDisplayName: string) =>
             `这是 <strong>${submitterDisplayName}</strong> 向 <strong>${workspaceName}</strong> 提交报销的地方。只需使用“+”按钮即可。`,
+        beginningOfChatHistoryPolicyExpenseChatTrack: '在这里跟踪你的报销费用',
         beginningOfChatHistorySelfDM: '这是你的个人空间。可在此记录笔记、任务、草稿和提醒事项。',
         beginningOfChatHistorySystemDM: '欢迎！让我们帮你完成设置。',
         chatWithAccountManager: '在这里与您的客户经理聊天',
@@ -1299,6 +1302,7 @@ const translations: TranslationDeepObject<typeof en> = {
         sendInvoice: (amount: string) => `发送 ${amount} 发票`,
         expenseAmount: (formattedAmount: string, comment?: string) => `${formattedAmount}${comment ? `用于 ${comment}` : ''}`,
         submitted: (memo?: string) => `已提交${memo ? `，备注为 ${memo}` : ''}`,
+        markedAsDone: (memo) => `标记为已完成${memo ? `，说明：${memo}` : ''}`,
         automaticallySubmitted: `通过<a href="${CONST.SELECT_WORKFLOWS_HELP_URL}">延迟提交</a>提交`,
         queuedToSubmitViaDEW: '已排队，待通过自定义审批流程提交',
         queuedToApproveViaDEW: '已排队，等待通过自定义审批流程批准',
@@ -1728,6 +1732,21 @@ const translations: TranslationDeepObject<typeof en> = {
                         return `正在等待管理员提交报销。`;
                 }
             },
+            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_TO_MARK_AS_DONE]: (
+                actor: string,
+                actorType: ValueOf<typeof CONST.NEXT_STEP.ACTOR_TYPE>,
+                _eta?: string,
+                _etaType?: ValueOf<typeof CONST.NEXT_STEP.ETA_TYPE>,
+            ) => {
+                switch (actorType) {
+                    case CONST.NEXT_STEP.ACTOR_TYPE.CURRENT_USER:
+                        return `正在等待<strong>你</strong>标记为完成。`;
+                    case CONST.NEXT_STEP.ACTOR_TYPE.OTHER_USER:
+                        return `正在等待<strong>${actor}</strong>标记为完成。`;
+                    case CONST.NEXT_STEP.ACTOR_TYPE.UNSPECIFIED_ADMIN:
+                        return `正在等待管理员标记为完成。`;
+                }
+            },
             [CONST.NEXT_STEP.MESSAGE_KEY.NO_FURTHER_ACTION]: (
                 _actor: string,
                 _actorType: ValueOf<typeof CONST.NEXT_STEP.ACTOR_TYPE>,
diff --git a/src/libs/NextStepUtils.ts b/src/libs/NextStepUtils.ts
index 4da56fc3b94c..a7bdb39b3bda 100644
--- a/src/libs/NextStepUtils.ts
+++ b/src/libs/NextStepUtils.ts
@@ -1,15 +1,18 @@
 import {addMonths, format, isPast, setDate} from 'date-fns';
 import {Str} from 'expensify-common';
 import type {OnyxCollection, OnyxEntry} from 'react-native-onyx';
+import Onyx from 'react-native-onyx';
 import type {ValueOf} from 'type-fest';
 import type {LocaleContextProps} from '@components/LocaleContextProvider';
 import CONST from '@src/CONST';
-import type {Policy, Report, ReportNextStepDeprecated, Transaction, TransactionViolations} from '@src/types/onyx';
+import ONYXKEYS from '@src/ONYXKEYS';
+import type {IntroSelected, Policy, Report, ReportNextStepDeprecated, Transaction, TransactionViolations} from '@src/types/onyx';
 import type {ReportNextStep} from '@src/types/onyx/Report';
 import type {Message} from '@src/types/onyx/ReportNextStepDeprecated';
 import type DeepValueOf from '@src/types/utils/DeepValueOf';
 import EmailUtils from './EmailUtils';
 import {formatPhoneNumber as formatPhoneNumberPhoneUtils} from './LocalePhoneNumber';
+import isTrackOnboardingChoice from './OnboardingUtils';
 import {getLoginsByAccountIDs, getPersonalDetailsByIDs} from './PersonalDetailsUtils';
 import {getApprovalWorkflow, getCorrectedAutoReportingFrequency, getReimburserAccountID} from './PolicyUtils';
 import {
@@ -22,9 +25,19 @@ import {
     isOpenExpenseReport,
     isPayer,
     shouldBlockSubmitDueToPreventSelfApproval,
+    shouldShowMarkAsDone,
 } from './ReportUtils';
 import {hasSubmissionBlockingViolations} from './TransactionUtils';
 
+let introSelected: OnyxEntry<IntroSelected>;
+// eslint-disable-next-line rulesdir/no-onyx-connect -- NextStepUtils is a pure utility called from action files that cannot use hooks
+Onyx.connect({
+    key: ONYXKEYS.NVP_INTRO_SELECTED,
+    callback: (value) => {
+        introSelected = value;
+    },
+});
+
 type BuildNextStepNewParams = {
     report: OnyxEntry<Report>;
     policy?: OnyxEntry<Policy>;
@@ -139,7 +152,9 @@ function buildOptimisticNextStep(params: BuildNextStepNewParams): ReportNextStep
             }
             if (isReopen) {
                 nextStep = {
-                    messageKey: CONST.NEXT_STEP.MESSAGE_KEY.WAITING_TO_SUBMIT,
+                    messageKey: shouldShowMarkAsDone({isTrackIntentUser: isTrackOnboardingChoice(introSelected?.choice), report, policy})
+                        ? CONST.NEXT_STEP.MESSAGE_KEY.WAITING_TO_MARK_AS_DONE
+                        : CONST.NEXT_STEP.MESSAGE_KEY.WAITING_TO_SUBMIT,
                     icon: CONST.NEXT_STEP.ICONS.HOURGLASS,
                     actorAccountID: ownerAccountID,
                 };
@@ -200,7 +215,13 @@ function buildOptimisticNextStep(params: BuildNextStepNewParams): ReportNextStep
             // Manual submission
             if (hasTransactions && !policy?.harvesting?.enabled) {
                 nextStep = {
-                    messageKey: CONST.NEXT_STEP.MESSAGE_KEY.WAITING_TO_SUBMIT,
+                    messageKey: shouldShowMarkAsDone({
+                        isTrackIntentUser: isTrackOnboardingChoice(introSelected?.choice),
+                        report,
+                        policy,
+                    })
+                        ? CONST.NEXT_STEP.MESSAGE_KEY.WAITING_TO_MARK_AS_DONE
+                        : CONST.NEXT_STEP.MESSAGE_KEY.WAITING_TO_SUBMIT,
                     icon: CONST.NEXT_STEP.ICONS.HOURGLASS,
                     actorAccountID: ownerAccountID,
                 };
diff --git a/src/libs/OptionsListUtils/index.ts b/src/libs/OptionsListUtils/index.ts
index e96137578b7a..7ebcf79af621 100644
--- a/src/libs/OptionsListUtils/index.ts
+++ b/src/libs/OptionsListUtils/index.ts
@@ -161,6 +161,7 @@ import {
     isSelfDM as reportUtilsIsSelfDM,
     isTaskReport as reportUtilsIsTaskReport,
     shouldReportBeInOptionList,
+    shouldShowMarkAsDone,
 } from '@libs/ReportUtils';
 import StringUtils from '@libs/StringUtils';
 import {getTaskCreatedMessage, getTaskReportActionMessage} from '@libs/TaskUtils';
@@ -657,6 +658,7 @@ function getLastMessageTextForReport({
     policyTags,
     currentUserLogin,
     conciergeReportID,
+    isTrackIntentUser = false,
     // eslint-disable-next-line @typescript-eslint/no-deprecated
     sortedActions = deprecatedAllSortedReportActions,
 }: {
@@ -676,6 +678,7 @@ function getLastMessageTextForReport({
     currentUserLogin?: string;
     // TODO: conciergeReportID will be required eventually. Refactor issue: https://github.com/Expensify/App/issues/66411
     conciergeReportID?: string;
+    isTrackIntentUser?: boolean;
     sortedActions?: Record<string, ReportAction[]>;
 }): string {
     const reportID = report?.reportID;
@@ -814,7 +817,13 @@ function getLastMessageTextForReport({
         } else if (hasPendingDEWSubmit(reportMetadata, isDEWPolicy) && isPendingAdd) {
             lastMessageTextFromReport = translate('iou.queuedToSubmitViaDEW');
         } else {
-            lastMessageTextFromReport = translate('iou.submitted', getOriginalMessage(lastReportAction)?.message);
+            lastMessageTextFromReport = shouldShowMarkAsDone({
+                report,
+                isTrackIntentUser,
+                policy,
+            })
+                ? translate('iou.markedAsDone', getOriginalMessage(lastReportAction)?.message)
+                : translate('iou.submitted', getOriginalMessage(lastReportAction)?.message);
         }
     } else if (isActionOfType(lastReportAction, CONST.REPORT.ACTIONS.TYPE.APPROVED)) {
         const {automaticAction} = getOriginalMessage(lastReportAction) ?? {};
diff --git a/src/libs/ReportUtils.ts b/src/libs/ReportUtils.ts
index 6faa15662367..f35c84e3033d 100644
--- a/src/libs/ReportUtils.ts
+++ b/src/libs/ReportUtils.ts
@@ -13213,6 +13213,18 @@ function getLinkedIOUTransaction(reportAction: OnyxEntry<ReportAction | Optimist
     return transactionID ? transactions.find((item) => item.transactionID === transactionID) : undefined;
 }
 
+/**
+ * Returns true if the "Mark as done" copy/button should be shown.
+ * Aligns with backend: only shown when all four conditions are true (isTrackIntentUser, isSubmitAndClose, isSubmitter, isSubmittingToSelf).
+ *
+ */
+function shouldShowMarkAsDone({isTrackIntentUser, report, policy}: {isTrackIntentUser?: boolean; report: OnyxEntry<Report>; policy: OnyxEntry<Policy>}): boolean {
+    if (!isTrackIntentUser || !isSubmitAndClose(policy) || !isReportOwner(report)) {
+        return false;
+    }
+    return getNextApproverAccountID(report) === report?.ownerAccountID;
+}
+
 export {
     areAllRequestsBeingSmartScanned,
     buildConciergeGreetingReportAction,
@@ -13595,6 +13607,7 @@ export {
     getTransactionSortValue,
     isSortableColumnName,
     getLinkedIOUTransaction,
+    shouldShowMarkAsDone,
     hasHeldExpensesFromTransactions,
 };
 
diff --git a/src/libs/SidebarUtils.ts b/src/libs/SidebarUtils.ts
index 9db647aaef81..91b0c5e0b776 100644
--- a/src/libs/SidebarUtils.ts
+++ b/src/libs/SidebarUtils.ts
@@ -213,6 +213,8 @@ type WelcomeMessageParams = {
     reportDetailsLink?: string;
     shouldShowUsePlusButtonText?: boolean;
     additionalText?: string;
+    isTrackIntentUser?: boolean;
+    currentUserAccountID?: number;
 };
 
 function compareStringDates(a: string, b: string): 0 | 1 | -1 {
@@ -791,6 +793,7 @@ function getOptionData({
     reportAttributesDerived,
     policyTags,
     currentUserLogin,
+    isTrackIntentUser,
 }: {
     report: OnyxEntry<Report>;
     oneTransactionThreadReport: OnyxEntry<Report>;
@@ -815,6 +818,7 @@ function getOptionData({
     reportAttributesDerived?: ReportAttributesDerivedValue['reports'];
     policyTags?: OnyxEntry<PolicyTagLists>;
     currentUserLogin: string;
+    isTrackIntentUser?: boolean;
 }): OptionData | undefined {
     // When a user signs out, Onyx is cleared. Due to the lazy rendering with a virtual list, it's possible for
     // this method to be called after the Onyx data has been cleared out. In that case, it's fine to do
@@ -973,6 +977,7 @@ function getOptionData({
             policyTags,
             currentUserLogin,
             lastAction,
+            isTrackIntentUser,
         });
     }
 
@@ -1271,6 +1276,8 @@ function getOptionData({
                         conciergeReportID,
                         reportAttributes: reportAttributesDerived,
                         isReportArchived,
+                        isTrackIntentUser,
+                        currentUserAccountID,
                     }).messageText ?? translate('report.noActivityYet'),
                 );
             }
@@ -1376,6 +1383,8 @@ function getWelcomeMessage(params: WelcomeMessageParams): WelcomeMessage {
         reportDetailsLink = '',
         shouldShowUsePlusButtonText = false,
         additionalText = '',
+        isTrackIntentUser = false,
+        currentUserAccountID,
     } = params;
 
     const welcomeMessage: WelcomeMessage = {};
@@ -1391,6 +1400,9 @@ function getWelcomeMessage(params: WelcomeMessageParams): WelcomeMessage {
         if (policy?.description) {
             welcomeMessage.messageHtml = policy.description;
             welcomeMessage.messageText = Parser.htmlToText(welcomeMessage.messageHtml);
+        } else if (isTrackIntentUser && report?.ownerAccountID === currentUserAccountID) {
+            welcomeMessage.messageHtml = translate('reportActionsView.beginningOfChatHistoryPolicyExpenseChatTrack');
+            welcomeMessage.messageText = Parser.htmlToText(welcomeMessage.messageHtml);
         } else {
             welcomeMessage.messageHtml = translate(
                 'reportActionsView.beginningOfChatHistoryPolicyExpenseChat',
diff --git a/src/pages/inbox/report/ContextMenu/BaseReportActionContextMenu.tsx b/src/pages/inbox/report/ContextMenu/BaseReportActionContextMenu.tsx
index 824b0773b8c2..291ea0c1a59a 100755
--- a/src/pages/inbox/report/ContextMenu/BaseReportActionContextMenu.tsx
+++ b/src/pages/inbox/report/ContextMenu/BaseReportActionContextMenu.tsx
@@ -1,4 +1,4 @@
-import {hasSeenTourSelector} from '@selectors/Onboarding';
+import {hasSeenTourSelector, isTrackIntentUserSelector} from '@selectors/Onboarding';
 import {deepEqual} from 'fast-equals';
 import type {RefObject} from 'react';
 import React, {memo, useMemo, useRef, useState} from 'react';
@@ -239,6 +239,7 @@ function BaseReportActionContextMenu({
     const {transactions} = useTransactionsAndViolationsForReport(childReport?.reportID);
     const [tryNewDot] = useOnyx(ONYXKEYS.NVP_TRY_NEW_DOT);
     const [introSelected] = useOnyx(ONYXKEYS.NVP_INTRO_SELECTED);
+    const [isTrackIntentUser] = useOnyx(ONYXKEYS.NVP_INTRO_SELECTED, {selector: isTrackIntentUserSelector});
     const [isSelfTourViewed] = useOnyx(ONYXKEYS.NVP_ONBOARDING, {selector: hasSeenTourSelector});
     const [bankAccountList] = useOnyx(ONYXKEYS.BANK_ACCOUNT_LIST);
     const [conciergeReportID] = useOnyx(ONYXKEYS.CONCIERGE_REPORT_ID);
@@ -397,6 +398,7 @@ function BaseReportActionContextMenu({
                                 card,
                                 originalReport,
                                 isTryNewDotNVPDismissed,
+                                isTrackIntentUser,
                                 childReport,
                                 movedFromReport,
                                 movedToReport,
diff --git a/src/pages/inbox/report/ContextMenu/ContextMenuActions.tsx b/src/pages/inbox/report/ContextMenu/ContextMenuActions.tsx
index e4269707544d..21681adc6dcc 100644
--- a/src/pages/inbox/report/ContextMenu/ContextMenuActions.tsx
+++ b/src/pages/inbox/report/ContextMenu/ContextMenuActions.tsx
@@ -185,6 +185,7 @@ import {
     isSelfDM,
     shouldDisableThread,
     shouldDisplayThreadReplies as shouldDisplayThreadRepliesReportUtils,
+    shouldShowMarkAsDone,
 } from '@libs/ReportUtils';
 import {getTaskCreatedMessage, getTaskReportActionMessage} from '@libs/TaskUtils';
 import {isExpenseSplit, isPerDiemRequest} from '@libs/TransactionUtils';
@@ -297,6 +298,7 @@ type ContextMenuActionPayload = {
     originalReport: OnyxEntry<ReportType>;
     isHarvestReport?: boolean;
     isTryNewDotNVPDismissed?: boolean;
+    isTrackIntentUser?: boolean;
     childReport?: OnyxEntry<ReportType>;
     movedFromReport?: OnyxEntry<ReportType>;
     movedToReport?: OnyxEntry<ReportType>;
@@ -836,6 +838,7 @@ const ContextMenuActions: ContextMenuAction[] = [
                 originalReport,
                 isHarvestReport,
                 isTryNewDotNVPDismissed,
+                isTrackIntentUser,
                 movedFromReport,
                 movedToReport,
                 childReport,
@@ -1029,7 +1032,15 @@ const ContextMenuActions: ContextMenuAction[] = [
                     if (harvesting) {
                         setClipboardMessage(translate('iou.automaticallySubmitted'));
                     } else {
-                        Clipboard.setString(translate('iou.submitted', getOriginalMessage(reportAction)?.message));
+                        Clipboard.setString(
+                            shouldShowMarkAsDone({
+                                policy,
+                                isTrackIntentUser,
+                                report,
+                            })
+                                ? translate('iou.markedAsDone', getOriginalMessage(reportAction)?.message)
+                                : translate('iou.submitted', getOriginalMessage(reportAction)?.message),
+                        );
                     }
                 } else if (isActionOfType(reportAction, CONST.REPORT.ACTIONS.TYPE.APPROVED)) {
                     const {automaticAction} = getOriginalMessage(reportAction) ?? {};
diff --git a/src/pages/inbox/report/PureReportActionItem.tsx b/src/pages/inbox/report/PureReportActionItem.tsx
index 491c5aeecc69..609b53c9b085 100644
--- a/src/pages/inbox/report/PureReportActionItem.tsx
+++ b/src/pages/inbox/report/PureReportActionItem.tsx
@@ -155,6 +155,9 @@ type PureReportActionItemProps = {
 
     /** Whether the action is the "Created" action of a harvest-created expense report */
     isHarvestCreatedExpenseReport?: boolean;
+
+    /** Whether the user is a track intent user */
+    isTrackIntentUser?: boolean;
 };
 
 function PureReportActionItem({
@@ -182,6 +185,7 @@ function PureReportActionItem({
     shouldShowBorder,
     shouldHighlight = false,
     isHarvestCreatedExpenseReport = false,
+    isTrackIntentUser,
 }: PureReportActionItemProps) {
     const isConciergeGreeting = action.reportActionID === CONST.CONCIERGE_GREETING_ACTION_ID;
     const shouldDisplayContextMenuValue = shouldDisplayContextMenu && !isConciergeGreeting;
@@ -605,6 +609,7 @@ function PureReportActionItem({
                                                                 shouldShowBorder={shouldShowBorder}
                                                                 isOnSearch={isOnSearch}
                                                                 setIsPaymentMethodPopoverActive={setIsPaymentMethodPopoverActive}
+                                                                isTrackIntentUser={isTrackIntentUser ?? false}
                                                             />
                                                             {Permissions.canUseLinkPreviews() && !isHidden && (action.linkMetadata?.length ?? 0) > 0 && (
                                                                 <View style={hasDraft ? styles.chatItemReactionsDraftRight : {}}>
diff --git a/src/pages/inbox/report/ReportActionItem.tsx b/src/pages/inbox/report/ReportActionItem.tsx
index 881251b20bfe..78c5143ce8d2 100644
--- a/src/pages/inbox/report/ReportActionItem.tsx
+++ b/src/pages/inbox/report/ReportActionItem.tsx
@@ -1,3 +1,4 @@
+import {isTrackIntentUserSelector} from '@selectors/Onboarding';
 import React, {useCallback} from 'react';
 import type {OnyxEntry} from 'react-native-onyx';
 import useOnyx from '@hooks/useOnyx';
@@ -26,6 +27,7 @@ function ReportActionItem({action, report, draftMessage: draftMessageProp, perso
     const [stableOriginalReport] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${originalReportID}`, {selector: getStableReportSelector});
     const [iouReport] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${getIOUReportIDFromReportActionPreview(action)}`);
 
+    const [isTrackIntentUser] = useOnyx(ONYXKEYS.NVP_INTRO_SELECTED, {selector: isTrackIntentUserSelector});
     const transactionsOnIOUReport = useReportTransactions(iouReport?.reportID);
     const transactionID = isMoneyRequestAction(action) && getOriginalMessage(action)?.IOUTransactionID;
 
@@ -54,6 +56,7 @@ function ReportActionItem({action, report, draftMessage: draftMessageProp, perso
             originalReportID={originalReportID}
             originalReport={stableOriginalReport}
             isClosedExpenseReportWithNoExpenses={isClosedExpenseReportWithNoExpenses(iouReport, transactionsOnIOUReport)}
+            isTrackIntentUser={isTrackIntentUser}
         />
     );
 }
diff --git a/src/pages/inbox/report/actionContents/ActionContentRouter.tsx b/src/pages/inbox/report/actionContents/ActionContentRouter.tsx
index 5cab7d5f5f75..f106978d8d16 100644
--- a/src/pages/inbox/report/actionContents/ActionContentRouter.tsx
+++ b/src/pages/inbox/report/actionContents/ActionContentRouter.tsx
@@ -118,6 +118,9 @@ type ActionContentRouterProps = {
 
     /** Toggle whether the payment method popover is active */
     setIsPaymentMethodPopoverActive: (value: boolean) => void;
+
+    /** Whether the user is a track intent user */
+    isTrackIntentUser?: boolean;
 };
 
 function ActionContentRouter({
@@ -139,6 +142,7 @@ function ActionContentRouter({
     shouldShowBorder,
     isOnSearch,
     setIsPaymentMethodPopoverActive,
+    isTrackIntentUser,
 }: ActionContentRouterProps): React.JSX.Element | null {
     const {translate, formatTravelDate} = useLocalize();
     const styles = useThemeStyles();
@@ -263,6 +267,7 @@ function ActionContentRouter({
                 policyID={policyID}
                 reportID={reportID}
                 originalReport={originalReport}
+                isTrackIntentUser={isTrackIntentUser ?? false}
             />
         );
     }
diff --git a/src/pages/inbox/report/actionContents/ApprovalFlowContent.tsx b/src/pages/inbox/report/actionContents/ApprovalFlowContent.tsx
index 80a93e1d8353..131432c4d316 100644
--- a/src/pages/inbox/report/actionContents/ApprovalFlowContent.tsx
+++ b/src/pages/inbox/report/actionContents/ApprovalFlowContent.tsx
@@ -6,6 +6,7 @@ import useOnyx from '@hooks/useOnyx';
 import getNonEmptyStringOnyxID from '@libs/getNonEmptyStringOnyxID';
 import {hasDynamicExternalWorkflow} from '@libs/PolicyUtils';
 import {getOriginalMessage, hasPendingDEWApprove, hasPendingDEWSubmit, isActionOfType, isMarkAsClosedAction} from '@libs/ReportActionsUtils';
+import {shouldShowMarkAsDone} from '@libs/ReportUtils';
 import ReportActionItemBasicMessage from '@pages/inbox/report/ReportActionItemBasicMessage';
 import ReportActionItemMessageWithExplain from '@pages/inbox/report/ReportActionItemMessageWithExplain';
 import CONST from '@src/CONST';
@@ -17,6 +18,7 @@ type ApprovalFlowContentProps = {
     policyID: string | undefined;
     reportID: string | undefined;
     originalReport: OnyxEntry<OnyxTypes.Report>;
+    isTrackIntentUser: boolean;
 };
 
 function isApprovalFlowAction(action: OnyxTypes.ReportAction): boolean {
@@ -29,7 +31,7 @@ function isApprovalFlowAction(action: OnyxTypes.ReportAction): boolean {
     );
 }
 
-function ApprovalFlowContent({action, policyID, reportID, originalReport}: ApprovalFlowContentProps) {
+function ApprovalFlowContent({action, policyID, reportID, originalReport, isTrackIntentUser}: ApprovalFlowContentProps) {
     const {translate} = useLocalize();
     const [reportMetadata] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT_METADATA}${reportID}`);
     const [policy] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY}${policyID}`);
@@ -40,6 +42,16 @@ function ApprovalFlowContent({action, policyID, reportID, originalReport}: Appro
     if (isActionOfType(action, CONST.REPORT.ACTIONS.TYPE.SUBMITTED) || isActionOfType(action, CONST.REPORT.ACTIONS.TYPE.SUBMITTED_AND_CLOSED) || isMarkAsClosedAction(action)) {
         const wasSubmittedViaHarvesting = !isMarkAsClosedAction(action) ? (getOriginalMessage(action)?.harvesting ?? false) : false;
 
+        if (
+            shouldShowMarkAsDone({
+                isTrackIntentUser,
+                policy,
+                report: originalReport,
+            })
+        ) {
+            return <ReportActionItemBasicMessage message={translate('iou.markedAsDone', getOriginalMessage(action)?.message)} />;
+        }
+
         if (wasSubmittedViaHarvesting) {
             return (
                 <ReportActionItemMessageWithExplain
@@ -66,6 +78,15 @@ function ApprovalFlowContent({action, policyID, reportID, originalReport}: Appro
     if (isActionOfType(action, CONST.REPORT.ACTIONS.TYPE.APPROVED)) {
         const wasAutoApproved = getOriginalMessage(action)?.automaticAction ?? false;
 
+        if (
+            shouldShowMarkAsDone({
+                isTrackIntentUser,
+                policy,
+                report: originalReport,
+            })
+        ) {
+            return <ReportActionItemBasicMessage message={translate('iou.markedAsDone')} />;
+        }
         if (wasAutoApproved) {
             return (
                 <ReportActionItemMessageWithExplain
diff --git a/src/selectors/Onboarding.ts b/src/selectors/Onboarding.ts
index 651578b5778d..26077e9e5cc6 100644
--- a/src/selectors/Onboarding.ts
+++ b/src/selectors/Onboarding.ts
@@ -1,4 +1,5 @@
 import type {OnyxValue} from 'react-native-onyx';
+import isTrackOnboardingChoice from '@libs/OnboardingUtils';
 import type ONYXKEYS from '@src/ONYXKEYS';
 import {isEmptyObject} from '@src/types/utils/EmptyObject';
 
@@ -79,4 +80,11 @@ function guidedSetupAndTourStatusSelector(onboarding: OnyxValue<typeof ONYXKEYS.
     };
 }
 
-export {hasCompletedGuidedSetupFlowSelector, tryNewDotOnyxSelector, hasSeenTourSelector, wasInvitedToNewDotSelector, guidedSetupAndTourStatusSelector};
+/**
+ * Selector to check if the user selected a track-intent onboarding choice
+ */
+function isTrackIntentUserSelector(introSelected: OnyxValue<typeof ONYXKEYS.NVP_INTRO_SELECTED>): boolean {
+    return isTrackOnboardingChoice(introSelected?.choice);
+}
+
+export {hasCompletedGuidedSetupFlowSelector, tryNewDotOnyxSelector, hasSeenTourSelector, wasInvitedToNewDotSelector, guidedSetupAndTourStatusSelector, isTrackIntentUserSelector};
diff --git a/tests/unit/OnboardingSelectorsTest.ts b/tests/unit/OnboardingSelectorsTest.ts
index f568760d06a8..c0fc5b52bce2 100644
--- a/tests/unit/OnboardingSelectorsTest.ts
+++ b/tests/unit/OnboardingSelectorsTest.ts
@@ -1,4 +1,4 @@
-import {hasCompletedGuidedSetupFlowSelector, hasSeenTourSelector} from '@selectors/Onboarding';
+import {hasCompletedGuidedSetupFlowSelector, hasSeenTourSelector, isTrackIntentUserSelector} from '@selectors/Onboarding';
 import type {OnyxValue} from 'react-native-onyx';
 import CONST from '@src/CONST';
 import type ONYXKEYS from '@src/ONYXKEYS';
@@ -59,4 +59,34 @@ describe('onboardingSelectors', () => {
             expect(hasSeenTourSelector(onboarding)).toBe(false);
         });
     });
+    describe('isTrackIntentUserSelector', () => {
+        it('Should return true for PERSONAL_SPEND choice', () => {
+            const introSelected = {choice: CONST.ONBOARDING_CHOICES.PERSONAL_SPEND} as OnyxValue<typeof ONYXKEYS.NVP_INTRO_SELECTED>;
+            expect(isTrackIntentUserSelector(introSelected)).toBe(true);
+        });
+
+        it('Should return true for TRACK_BUSINESS choice', () => {
+            const introSelected = {choice: CONST.ONBOARDING_CHOICES.TRACK_BUSINESS} as OnyxValue<typeof ONYXKEYS.NVP_INTRO_SELECTED>;
+            expect(isTrackIntentUserSelector(introSelected)).toBe(true);
+        });
+
+        it('Should return true for TRACK_PERSONAL choice', () => {
+            const introSelected = {choice: CONST.ONBOARDING_CHOICES.TRACK_PERSONAL} as OnyxValue<typeof ONYXKEYS.NVP_INTRO_SELECTED>;
+            expect(isTrackIntentUserSelector(introSelected)).toBe(true);
+        });
+
+        it('Should return false for MANAGE_TEAM choice', () => {
+            const introSelected = {choice: CONST.ONBOARDING_CHOICES.MANAGE_TEAM} as OnyxValue<typeof ONYXKEYS.NVP_INTRO_SELECTED>;
+            expect(isTrackIntentUserSelector(introSelected)).toBe(false);
+        });
+
+        it('Should return false for undefined introSelected', () => {
+            expect(isTrackIntentUserSelector(undefined)).toBe(false);
+        });
+
+        it('Should return false when choice is undefined', () => {
+            const introSelected = {} as OnyxValue<typeof ONYXKEYS.NVP_INTRO_SELECTED>;
+            expect(isTrackIntentUserSelector(introSelected)).toBe(false);
+        });
+    });
 });
diff --git a/tests/unit/ReportUtilsTest.ts b/tests/unit/ReportUtilsTest.ts
index b18610680a6d..4861568caec4 100644
--- a/tests/unit/ReportUtilsTest.ts
+++ b/tests/unit/ReportUtilsTest.ts
@@ -160,6 +160,7 @@ import {
     shouldReportBeInOptionList,
     shouldReportShowSubscript,
     shouldShowFlagComment,
+    shouldShowMarkAsDone,
     sortIconsByName,
     sortOutstandingReportsBySelected,
     temporary_getMoneyRequestOptions,
@@ -17913,3 +17914,136 @@ describe('ReportUtils', () => {
         });
     });
 });
+describe('shouldShowMarkAsDone', () => {
+    const policyID = '1';
+    const otherAccountID = 42;
+
+    it('should return false when user is not a track-intent user', () => {
+        const report = {
+            reportID: 'report1',
+            ownerAccountID: currentUserAccountID,
+            managerID: currentUserAccountID,
+            policyID,
+            type: CONST.REPORT.TYPE.EXPENSE,
+        } as Report;
+        const testPolicy = {
+            id: policyID,
+            approvalMode: CONST.POLICY.APPROVAL_MODE.OPTIONAL,
+            type: CONST.POLICY.TYPE.TEAM,
+        } as Policy;
+
+        expect(shouldShowMarkAsDone({isTrackIntentUser: false, report, policy: testPolicy})).toBe(false);
+    });
+
+    it('should return false when policy is not submit-and-close', () => {
+        const report = {
+            reportID: 'report1',
+            ownerAccountID: currentUserAccountID,
+            managerID: currentUserAccountID,
+            policyID,
+            type: CONST.REPORT.TYPE.EXPENSE,
+        } as Report;
+        const testPolicy = {
+            id: policyID,
+            approvalMode: CONST.POLICY.APPROVAL_MODE.BASIC,
+            type: CONST.POLICY.TYPE.TEAM,
+        } as Policy;
+
+        expect(shouldShowMarkAsDone({isTrackIntentUser: true, report, policy: testPolicy})).toBe(false);
+    });
+
+    it('should return false when user does not own the report', () => {
+        const report = {
+            reportID: 'report1',
+            ownerAccountID: otherAccountID,
+            managerID: otherAccountID,
+            policyID,
+            type: CONST.REPORT.TYPE.EXPENSE,
+        } as Report;
+        const testPolicy = {
+            id: policyID,
+            approvalMode: CONST.POLICY.APPROVAL_MODE.OPTIONAL,
+            type: CONST.POLICY.TYPE.TEAM,
+        } as Policy;
+
+        expect(shouldShowMarkAsDone({isTrackIntentUser: true, report, policy: testPolicy})).toBe(false);
+    });
+
+    it('should return false when next approver is different from owner', () => {
+        const report = {
+            reportID: 'report1',
+            ownerAccountID: currentUserAccountID,
+            managerID: otherAccountID,
+            policyID,
+            type: CONST.REPORT.TYPE.EXPENSE,
+        } as Report;
+        const testPolicy = {
+            id: policyID,
+            approvalMode: CONST.POLICY.APPROVAL_MODE.OPTIONAL,
+            type: CONST.POLICY.TYPE.TEAM,
+        } as Policy;
+
+        expect(shouldShowMarkAsDone({isTrackIntentUser: true, report, policy: testPolicy})).toBe(false);
+    });
+
+    it('should return false when isTrackIntentUser is undefined', () => {
+        const report = {
+            reportID: 'report1',
+            ownerAccountID: currentUserAccountID,
+            managerID: currentUserAccountID,
+            policyID,
+            type: CONST.REPORT.TYPE.EXPENSE,
+        } as Report;
+        const testPolicy = {
+            id: policyID,
+            approvalMode: CONST.POLICY.APPROVAL_MODE.OPTIONAL,
+            type: CONST.POLICY.TYPE.TEAM,
+        } as Policy;
+
+        expect(shouldShowMarkAsDone({isTrackIntentUser: undefined, report, policy: testPolicy})).toBe(false);
+    });
+
+    it('should return false when report is undefined', () => {
+        const testPolicy = {
+            id: policyID,
+            approvalMode: CONST.POLICY.APPROVAL_MODE.OPTIONAL,
+            type: CONST.POLICY.TYPE.TEAM,
+        } as Policy;
+
+        expect(shouldShowMarkAsDone({isTrackIntentUser: true, report: undefined, policy: testPolicy})).toBe(false);
+    });
+
+    it('should return false when policy is undefined', () => {
+        const report = {
+            reportID: 'report1',
+            ownerAccountID: currentUserAccountID,
+            managerID: currentUserAccountID,
+            policyID,
+            type: CONST.REPORT.TYPE.EXPENSE,
+        } as Report;
+
+        expect(shouldShowMarkAsDone({isTrackIntentUser: true, report, policy: undefined})).toBe(false);
+    });
+
+    it('should return true when user is track-intent, policy is submit-and-close, user owns report, and submits to self', async () => {
+        const report = {
+            reportID: 'report1',
+            ownerAccountID: currentUserAccountID,
+            managerID: currentUserAccountID,
+            policyID,
+            type: CONST.REPORT.TYPE.EXPENSE,
+        } as Report;
+        const testPolicy = {
+            id: policyID,
+            approvalMode: CONST.POLICY.APPROVAL_MODE.OPTIONAL,
+            type: CONST.POLICY.TYPE.TEAM,
+            owner: currentUserEmail,
+        } as Policy;
+        await Onyx.merge(`${ONYXKEYS.COLLECTION.POLICY}${policyID}`, testPolicy);
+        await Onyx.merge(ONYXKEYS.PERSONAL_DETAILS_LIST, {
+            [currentUserAccountID]: {accountID: currentUserAccountID, login: currentUserEmail},
+        });
+        await waitForBatchedUpdates();
+        expect(shouldShowMarkAsDone({isTrackIntentUser: true, report, policy: testPolicy})).toBe(true);
+    });
+});
diff --git a/tests/unit/SidebarUtilsTest.ts b/tests/unit/SidebarUtilsTest.ts
index 058c41917496..df03d4823042 100644
--- a/tests/unit/SidebarUtilsTest.ts
+++ b/tests/unit/SidebarUtilsTest.ts
@@ -1630,6 +1630,164 @@ describe('SidebarUtils', () => {
             expect(result.messageText).toBeTruthy();
             expect(result.messageText).not.toContain('Concierge');
         });
+
+        it('returns track-intent welcome message for policy expense chat when user is track-intent and owns the report', async () => {
+            const currentUserAccountID = 1;
+            const MOCK_REPORT: Report = {
+                ...LHNTestUtils.getFakeReport(),
+                chatType: CONST.REPORT.CHAT_TYPE.POLICY_EXPENSE_CHAT,
+                type: CONST.REPORT.TYPE.CHAT,
+                ownerAccountID: currentUserAccountID,
+                policyID: 'testPolicy',
+            };
+            const MOCK_POLICY: Policy = {
+                id: 'testPolicy',
+                name: 'Test Workspace',
+                type: CONST.POLICY.TYPE.TEAM,
+            } as Policy;
+
+            await waitForBatchedUpdates();
+            await act(async () => {
+                await Onyx.multiSet({
+                    [ONYXKEYS.PERSONAL_DETAILS_LIST]: LHNTestUtils.fakePersonalDetails,
+                    [ONYXKEYS.SESSION]: {accountID: currentUserAccountID},
+                });
+            });
+
+            const result = SidebarUtils.getWelcomeMessage({
+                report: MOCK_REPORT,
+                policy: MOCK_POLICY,
+                invoiceReceiverPolicy: undefined,
+                participantPersonalDetailList: [],
+                translate: translateLocal,
+                localeCompare,
+                conciergeReportID: MOCK_CONCIERGE_REPORT_ID,
+                isTrackIntentUser: true,
+                currentUserAccountID,
+            });
+            expect(result.messageText).toBe("This is where you'll track expenses.");
+        });
+
+        it('returns standard welcome message for policy expense chat when user is track-intent but does NOT own the report', async () => {
+            const currentUserAccountID = 1;
+            const otherUserAccountID = 2;
+            const MOCK_REPORT: Report = {
+                ...LHNTestUtils.getFakeReport(),
+                chatType: CONST.REPORT.CHAT_TYPE.POLICY_EXPENSE_CHAT,
+                type: CONST.REPORT.TYPE.CHAT,
+                ownerAccountID: otherUserAccountID,
+                policyID: 'testPolicy',
+            };
+            const MOCK_POLICY: Policy = {
+                id: 'testPolicy',
+                name: 'Test Workspace',
+                type: CONST.POLICY.TYPE.TEAM,
+            } as Policy;
+
+            await waitForBatchedUpdates();
+            await act(async () => {
+                await Onyx.multiSet({
+                    [ONYXKEYS.PERSONAL_DETAILS_LIST]: {
+                        ...LHNTestUtils.fakePersonalDetails,
+                        [otherUserAccountID]: {
+                            accountID: otherUserAccountID,
+                            displayName: 'Other User',
+                            login: 'other@test.com',
+                            avatar: '',
+                        },
+                    },
+                    [ONYXKEYS.SESSION]: {accountID: currentUserAccountID},
+                });
+            });
+
+            const result = SidebarUtils.getWelcomeMessage({
+                report: MOCK_REPORT,
+                policy: MOCK_POLICY,
+                invoiceReceiverPolicy: undefined,
+                participantPersonalDetailList: [],
+                translate: translateLocal,
+                localeCompare,
+                conciergeReportID: MOCK_CONCIERGE_REPORT_ID,
+                isTrackIntentUser: true,
+                currentUserAccountID,
+            });
+            expect(result.messageHtml).toContain('will submit expenses to');
+        });
+
+        it('returns standard welcome message for policy expense chat when user is NOT track-intent', async () => {
+            const currentUserAccountID = 1;
+            const MOCK_REPORT: Report = {
+                ...LHNTestUtils.getFakeReport(),
+                chatType: CONST.REPORT.CHAT_TYPE.POLICY_EXPENSE_CHAT,
+                type: CONST.REPORT.TYPE.CHAT,
+                ownerAccountID: currentUserAccountID,
+                policyID: 'testPolicy',
+            };
+            const MOCK_POLICY: Policy = {
+                id: 'testPolicy',
+                name: 'Test Workspace',
+                type: CONST.POLICY.TYPE.TEAM,
+            } as Policy;
+
+            await waitForBatchedUpdates();
+            await act(async () => {
+                await Onyx.multiSet({
+                    [ONYXKEYS.PERSONAL_DETAILS_LIST]: LHNTestUtils.fakePersonalDetails,
+                    [ONYXKEYS.SESSION]: {accountID: currentUserAccountID},
+                });
+            });
+
+            const result = SidebarUtils.getWelcomeMessage({
+                report: MOCK_REPORT,
+                policy: MOCK_POLICY,
+                invoiceReceiverPolicy: undefined,
+                participantPersonalDetailList: [],
+                translate: translateLocal,
+                localeCompare,
+                conciergeReportID: MOCK_CONCIERGE_REPORT_ID,
+                isTrackIntentUser: false,
+                currentUserAccountID,
+            });
+            expect(result.messageHtml).toContain('will submit expenses to');
+        });
+
+        it('returns standard welcome message when policy has a custom description even for track-intent users', async () => {
+            const currentUserAccountID = 1;
+            const MOCK_REPORT: Report = {
+                ...LHNTestUtils.getFakeReport(),
+                chatType: CONST.REPORT.CHAT_TYPE.POLICY_EXPENSE_CHAT,
+                type: CONST.REPORT.TYPE.CHAT,
+                ownerAccountID: currentUserAccountID,
+                policyID: 'testPolicy',
+            };
+            const MOCK_POLICY: Policy = {
+                id: 'testPolicy',
+                name: 'Test Workspace',
+                description: 'Custom workspace description',
+                type: CONST.POLICY.TYPE.TEAM,
+            } as Policy;
+
+            await waitForBatchedUpdates();
+            await act(async () => {
+                await Onyx.multiSet({
+                    [ONYXKEYS.PERSONAL_DETAILS_LIST]: LHNTestUtils.fakePersonalDetails,
+                    [ONYXKEYS.SESSION]: {accountID: currentUserAccountID},
+                });
+            });
+
+            const result = SidebarUtils.getWelcomeMessage({
+                report: MOCK_REPORT,
+                policy: MOCK_POLICY,
+                invoiceReceiverPolicy: undefined,
+                participantPersonalDetailList: [],
+                translate: translateLocal,
+                localeCompare,
+                conciergeReportID: MOCK_CONCIERGE_REPORT_ID,
+                isTrackIntentUser: true,
+                currentUserAccountID,
+            });
+            expect(result.messageHtml).toBe('Custom workspace description');
+        });
     });
 
     describe('getOptionData', () => {

From d8c1da241129833d7c94bea755ec46f546abd280 Mon Sep 17 00:00:00 2001
From: krishna2323 <belivethatkg@gmail.com>
Date: Fri, 29 May 2026 17:25:34 +0530
Subject: [PATCH 039/435] feat: Add sticky group headers to Spend table by
 splitting groups into header + children pairs

Signed-off-by: krishna2323 <belivethatkg@gmail.com>
---
 .../BaseSearchList/index.native.tsx           |   4 +
 .../SearchList/BaseSearchList/index.tsx       |   4 +
 .../Search/SearchList/BaseSearchList/types.ts |   4 +
 .../ListItem/GroupChildrenContainer.tsx       | 279 +++++++++++++++
 .../SearchList/ListItem/GroupHeader.tsx       | 318 ++++++++++++++++++
 .../Search/SearchList/ListItem/types.ts       |  10 +
 src/components/Search/SearchList/index.tsx    |  97 +++++-
 src/libs/SearchUIUtils.ts                     |  21 ++
 8 files changed, 731 insertions(+), 6 deletions(-)
 create mode 100644 src/components/Search/SearchList/ListItem/GroupChildrenContainer.tsx
 create mode 100644 src/components/Search/SearchList/ListItem/GroupHeader.tsx

diff --git a/src/components/Search/SearchList/BaseSearchList/index.native.tsx b/src/components/Search/SearchList/BaseSearchList/index.native.tsx
index ad5d017c708f..a6955e67be8b 100644
--- a/src/components/Search/SearchList/BaseSearchList/index.native.tsx
+++ b/src/components/Search/SearchList/BaseSearchList/index.native.tsx
@@ -18,6 +18,8 @@ function BaseSearchList({
     onViewableItemsChanged,
     onLayout,
     contentContainerStyle,
+    stickyHeaderIndices,
+    getItemType,
 }: BaseSearchListProps) {
     const renderItemWithoutKeyboardFocus = useCallback(
         ({item, index}: {item: SearchListItem; index: number}) => {
@@ -43,6 +45,8 @@ function BaseSearchList({
             drawDistance={250}
             contentContainerStyle={contentContainerStyle}
             maintainVisibleContentPosition={{disabled: true}}
+            stickyHeaderIndices={stickyHeaderIndices}
+            getItemType={getItemType}
         />
     );
 }
diff --git a/src/components/Search/SearchList/BaseSearchList/index.tsx b/src/components/Search/SearchList/BaseSearchList/index.tsx
index 8af495aaacb5..9a88c06fea2e 100644
--- a/src/components/Search/SearchList/BaseSearchList/index.tsx
+++ b/src/components/Search/SearchList/BaseSearchList/index.tsx
@@ -37,6 +37,8 @@ function BaseSearchList({
     selectedTransactions,
     isAttendeesEnabledForMovingPolicy,
     nonPersonalAndWorkspaceCards,
+    stickyHeaderIndices,
+    getItemType,
 }: BaseSearchListProps) {
     const hasKeyBeenPressed = useRef(false);
     const isFocused = useIsFocused();
@@ -152,6 +154,8 @@ function BaseSearchList({
             drawDistance={250}
             contentContainerStyle={contentContainerStyle}
             maintainVisibleContentPosition={{disabled: true}}
+            stickyHeaderIndices={stickyHeaderIndices}
+            getItemType={getItemType}
         />
     );
 }
diff --git a/src/components/Search/SearchList/BaseSearchList/types.ts b/src/components/Search/SearchList/BaseSearchList/types.ts
index 98a95be7c065..d30c3ebfa9f0 100644
--- a/src/components/Search/SearchList/BaseSearchList/types.ts
+++ b/src/components/Search/SearchList/BaseSearchList/types.ts
@@ -17,6 +17,7 @@ type BaseSearchListProps = Pick<
     | 'keyExtractor'
     | 'showsVerticalScrollIndicator'
     | 'onLayout'
+    | 'stickyHeaderIndices'
 > & {
     /** The data to display in the list */
     data: SearchListItem[];
@@ -50,6 +51,9 @@ type BaseSearchListProps = Pick<
 
     /** Non-personal and workspace cards for triggering re-render via extraData */
     nonPersonalAndWorkspaceCards?: CardList;
+
+    /** Function to determine item type for FlashList recycling */
+    getItemType?: (item: SearchListItem, index: number) => string | number | undefined;
 };
 
 export default BaseSearchListProps;
diff --git a/src/components/Search/SearchList/ListItem/GroupChildrenContainer.tsx b/src/components/Search/SearchList/ListItem/GroupChildrenContainer.tsx
new file mode 100644
index 000000000000..8843ca2e9084
--- /dev/null
+++ b/src/components/Search/SearchList/ListItem/GroupChildrenContainer.tsx
@@ -0,0 +1,279 @@
+import {useIsFocused} from '@react-navigation/native';
+import React, {useEffect, useState} from 'react';
+import {View} from 'react-native';
+import Animated, {useAnimatedStyle, useDerivedValue, useSharedValue, withTiming} from 'react-native-reanimated';
+import {scheduleOnRN} from 'react-native-worklets';
+import {easing} from '@components/Modal/ReanimatedModal/utils';
+import {useSearchSelectionContext} from '@components/Search/SearchContext';
+import type {SearchColumnType, SearchGroupBy} from '@components/Search/types';
+import useActionLoadingReportIDs from '@hooks/useActionLoadingReportIDs';
+import {useCurrencyListActions} from '@hooks/useCurrencyList';
+import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails';
+import useLocalize from '@hooks/useLocalize';
+import useNetwork from '@hooks/useNetwork';
+import useOnyx from '@hooks/useOnyx';
+import useResponsiveLayout from '@hooks/useResponsiveLayout';
+import useTheme from '@hooks/useTheme';
+import useThemeStyles from '@hooks/useThemeStyles';
+import {search} from '@libs/actions/Search';
+import type {TransactionPreviewData} from '@libs/actions/Search';
+import type {ModifiedMouseEvent} from '@libs/Navigation/helpers/openInternalRouteInNewTab';
+import {getSections} from '@libs/SearchUIUtils';
+import {mergeProhibitedViolations, shouldShowViolation} from '@libs/TransactionUtils';
+import CONST from '@src/CONST';
+import ONYXKEYS from '@src/ONYXKEYS';
+import type {CardList, Transaction, TransactionViolation, TransactionViolations} from '@src/types/onyx';
+import type {SearchDataTypes} from '@src/types/onyx/SearchResults';
+import TransactionGroupListExpandedItem from './TransactionGroupListExpanded';
+import type {GroupChildrenContainerItemType, SearchListItem, TransactionGroupListItemType, TransactionListItemType} from './types';
+
+type GroupChildrenContainerProps = {
+    item: GroupChildrenContainerItemType;
+    isExpanded: boolean;
+    groupBy?: SearchGroupBy;
+    searchType?: SearchDataTypes;
+    columns?: SearchColumnType[];
+    canSelectMultiple: boolean;
+    onSelectRow: (item: SearchListItem, transactionPreviewData?: TransactionPreviewData, event?: ModifiedMouseEvent) => void;
+    onCheckboxPress: (item: SearchListItem, itemTransactions?: TransactionListItemType[]) => void;
+    onLongPressRow?: (item: SearchListItem, itemTransactions?: TransactionListItemType[]) => void;
+    nonPersonalAndWorkspaceCards?: CardList;
+    onUndelete?: (transaction: Transaction) => void;
+};
+
+function GroupChildrenContainer({
+    item,
+    isExpanded,
+    groupBy,
+    searchType,
+    columns,
+    canSelectMultiple,
+    onSelectRow,
+    onCheckboxPress,
+    onLongPressRow,
+    nonPersonalAndWorkspaceCards,
+    onUndelete,
+}: GroupChildrenContainerProps) {
+    const theme = useTheme();
+    const styles = useThemeStyles();
+    const {translate, formatPhoneNumber} = useLocalize();
+    const {selectedTransactions} = useSearchSelectionContext();
+    const currentUserDetails = useCurrentUserPersonalDetails();
+    const isScreenFocused = useIsFocused();
+    const {convertToDisplayString} = useCurrencyListActions();
+    const {isOffline} = useNetwork();
+    const {isLargeScreenWidth} = useResponsiveLayout();
+
+    const groupItem = item as unknown as TransactionGroupListItemType;
+    const isExpenseReportType = searchType === CONST.SEARCH.DATA_TYPES.EXPENSE_REPORT;
+
+    const selectedTransactionIDsSet = new Set(Object.keys(selectedTransactions));
+    const [transactionsSnapshot] = useOnyx(`${ONYXKEYS.COLLECTION.SNAPSHOT}${groupItem.transactionsQueryJSON?.hash}`);
+    const [transactionsVisibleLimit, setTransactionsVisibleLimit] = useState(CONST.TRANSACTION.RESULTS_PAGE_SIZE as number);
+    const isActionLoadingSet = useActionLoadingReportIDs();
+    const [allReportMetadata] = useOnyx(ONYXKEYS.COLLECTION.REPORT_METADATA);
+    const [bankAccountList] = useOnyx(ONYXKEYS.BANK_ACCOUNT_LIST);
+    const [cardFeeds] = useOnyx(ONYXKEYS.COLLECTION.SHARED_NVP_PRIVATE_DOMAIN_MEMBER);
+    const [conciergeReportID] = useOnyx(ONYXKEYS.CONCIERGE_REPORT_ID);
+
+    let transactions: TransactionListItemType[];
+    if (isExpenseReportType) {
+        transactions = groupItem.transactions;
+    } else if (!transactionsSnapshot?.data) {
+        transactions = [];
+    } else {
+        const [sectionData] = getSections({
+            type: CONST.SEARCH.DATA_TYPES.EXPENSE,
+            data: transactionsSnapshot?.data,
+            currentAccountID: currentUserDetails.accountID,
+            currentUserEmail: currentUserDetails.email ?? '',
+            translate,
+            formatPhoneNumber,
+            bankAccountList,
+            isActionLoadingSet,
+            allReportMetadata,
+            cardFeeds,
+            conciergeReportID,
+            convertToDisplayString,
+        }) as [TransactionListItemType[], number, boolean];
+        transactions = sectionData.map((transactionItem) => ({
+            ...transactionItem,
+            isSelected: selectedTransactionIDsSet.has(transactionItem.transactionID),
+        }));
+    }
+
+    const isEmpty = transactions.length === 0;
+    const shouldDisplayEmptyView = isEmpty && isExpenseReportType;
+
+    const refreshTransactions = () => {
+        if (!groupItem.transactionsQueryJSON) {
+            return;
+        }
+        search({
+            queryJSON: groupItem.transactionsQueryJSON,
+            searchKey: undefined,
+            offset: 0,
+            shouldCalculateTotals: false,
+            isLoading: !!transactionsSnapshot?.search?.isLoading,
+            isOffline,
+        });
+    };
+
+    const searchTransactions = (pageSize = 0) => {
+        if (!groupItem.transactionsQueryJSON) {
+            return;
+        }
+        search({
+            queryJSON: groupItem.transactionsQueryJSON,
+            searchKey: undefined,
+            offset: (transactionsSnapshot?.search?.offset ?? 0) + pageSize,
+            shouldCalculateTotals: false,
+            isLoading: !!transactionsSnapshot?.search?.isLoading,
+            isOffline,
+        });
+    };
+
+    useEffect(() => {
+        if (!isExpanded || isExpenseReportType) {
+            return;
+        }
+        refreshTransactions();
+        // eslint-disable-next-line react-hooks/exhaustive-deps
+    }, [isExpanded]);
+
+    const wasScreenFocusedRef = React.useRef(isScreenFocused);
+    useEffect(() => {
+        const didReturnToScreen = wasScreenFocusedRef.current === false && isScreenFocused === true;
+        wasScreenFocusedRef.current = isScreenFocused;
+        if (!didReturnToScreen || !isExpanded || isExpenseReportType) {
+            return;
+        }
+        refreshTransactions();
+        // eslint-disable-next-line react-hooks/exhaustive-deps
+    }, [isScreenFocused]);
+
+    const snapshotData = transactionsSnapshot?.data;
+    const groupViolations: Record<string, TransactionViolations | undefined> = {};
+    if (snapshotData) {
+        for (const [key, value] of Object.entries(snapshotData)) {
+            if (key.startsWith(ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS)) {
+                groupViolations[key] = value as TransactionViolations;
+            }
+        }
+    }
+
+    const filteredViolations: Record<string, TransactionViolation[]> = {};
+    if (snapshotData) {
+        for (const key of Object.keys(snapshotData)) {
+            if (!key.startsWith(ONYXKEYS.COLLECTION.TRANSACTION)) {
+                continue;
+            }
+            const snapshotTransaction = snapshotData[key as keyof typeof snapshotData] as Transaction;
+            if (!snapshotTransaction || typeof snapshotTransaction !== 'object' || !('transactionID' in snapshotTransaction) || !('reportID' in snapshotTransaction)) {
+                continue;
+            }
+
+            const report = snapshotData[`${ONYXKEYS.COLLECTION.REPORT}${snapshotTransaction.reportID}`];
+            const policy = snapshotData[`${ONYXKEYS.COLLECTION.POLICY}${report?.policyID}`];
+
+            if (report && policy) {
+                const transactionViolations = groupViolations[`${ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS}${snapshotTransaction.transactionID}`];
+                if (transactionViolations) {
+                    const merged = mergeProhibitedViolations(
+                        transactionViolations.filter((violation) => shouldShowViolation(report, policy, violation.name, currentUserDetails?.email ?? '', true, snapshotTransaction)),
+                    );
+                    if (merged.length > 0) {
+                        filteredViolations[`${ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS}${snapshotTransaction.transactionID}`] = merged;
+                    }
+                }
+            }
+        }
+    }
+
+    const onExpandedRowLongPress = (transaction: TransactionListItemType) => {
+        onLongPressRow?.(transaction, transactions);
+    };
+
+    // Animation: replicate AnimatedCollapsible's height animation pattern
+    const contentHeight = useSharedValue(0);
+    const hasExpanded = useSharedValue(isExpanded);
+    const [isRendered, setIsRendered] = useState(isExpanded);
+
+    hasExpanded.set(isExpanded);
+    if (isExpanded && !isRendered) {
+        setIsRendered(true);
+    }
+
+    const animatedHeight = useDerivedValue(() => {
+        if (!contentHeight.get()) {
+            return 0;
+        }
+        const target = hasExpanded.get() ? contentHeight.get() : 0;
+        return withTiming(target, {duration: 300, easing}, (finished) => {
+            if (!finished || target) {
+                return;
+            }
+            scheduleOnRN(setIsRendered, false);
+        });
+    }, []);
+
+    const animatedOpacity = useDerivedValue(() => {
+        if (!contentHeight.get()) {
+            return 0;
+        }
+        return withTiming(hasExpanded.get() ? 1 : 0, {duration: 300, easing});
+    });
+
+    const contentAnimatedStyle = useAnimatedStyle(() => ({
+        height: animatedHeight.get(),
+        opacity: animatedOpacity.get(),
+    }));
+
+    return (
+        <View style={[styles.mh5, {backgroundColor: theme.highlightBG}]}>
+            <Animated.View style={contentAnimatedStyle}>
+                {isExpanded || isRendered ? (
+                    <Animated.View
+                        style={styles.stickToTop}
+                        onLayout={(e) => {
+                            const height = e.nativeEvent.layout.height;
+                            if (height) {
+                                contentHeight.set(height);
+                            }
+                        }}
+                    >
+                        <View style={isLargeScreenWidth ? [styles.pv2, styles.ph3, styles.pb1] : styles.ph3}>
+                            <View style={styles.borderBottom} />
+                        </View>
+                        <TransactionGroupListExpandedItem
+                            showTooltip
+                            canSelectMultiple={canSelectMultiple}
+                            onSelectionButtonPress={onCheckboxPress}
+                            onSelectRow={onSelectRow}
+                            columns={columns}
+                            groupBy={groupBy}
+                            accountID={currentUserDetails.accountID}
+                            isOffline={isOffline}
+                            violations={filteredViolations}
+                            transactions={transactions}
+                            transactionsVisibleLimit={transactionsVisibleLimit}
+                            setTransactionsVisibleLimit={setTransactionsVisibleLimit}
+                            isEmpty={isEmpty}
+                            shouldDisplayEmptyView={shouldDisplayEmptyView}
+                            isExpenseReportType={isExpenseReportType}
+                            transactionsSnapshot={transactionsSnapshot}
+                            transactionsQueryJSON={groupItem.transactionsQueryJSON}
+                            searchTransactions={searchTransactions}
+                            isInSingleTransactionReport={groupItem.transactions.length === 1}
+                            onLongPress={onExpandedRowLongPress}
+                            nonPersonalAndWorkspaceCards={nonPersonalAndWorkspaceCards}
+                            onUndelete={onUndelete}
+                        />
+                    </Animated.View>
+                ) : null}
+            </Animated.View>
+        </View>
+    );
+}
+
+export default GroupChildrenContainer;
diff --git a/src/components/Search/SearchList/ListItem/GroupHeader.tsx b/src/components/Search/SearchList/ListItem/GroupHeader.tsx
new file mode 100644
index 000000000000..ec8a46028aa0
--- /dev/null
+++ b/src/components/Search/SearchList/ListItem/GroupHeader.tsx
@@ -0,0 +1,318 @@
+import React from 'react';
+import {View} from 'react-native';
+import {getButtonRole} from '@components/Button/utils';
+import OfflineWithFeedback from '@components/OfflineWithFeedback';
+import {PressableWithFeedback} from '@components/Pressable';
+import {useSearchSelectionContext} from '@components/Search/SearchContext';
+import type {SearchColumnType, SearchGroupBy} from '@components/Search/types';
+import useAnimatedHighlightStyle from '@hooks/useAnimatedHighlightStyle';
+import useResponsiveLayout from '@hooks/useResponsiveLayout';
+import useStyleUtils from '@hooks/useStyleUtils';
+import useTheme from '@hooks/useTheme';
+import useThemeStyles from '@hooks/useThemeStyles';
+import type {ModifiedMouseEvent} from '@libs/Navigation/helpers/openInternalRouteInNewTab';
+import CONST from '@src/CONST';
+import type {SearchDataTypes} from '@src/types/onyx/SearchResults';
+import CardListItemHeader from './CardListItemHeader';
+import CategoryListItemHeader from './CategoryListItemHeader';
+import ExpandCollapseArrowButton from './ExpandCollapseArrowButton';
+import MemberListItemHeader from './MemberListItemHeader';
+import MerchantListItemHeader from './MerchantListItemHeader';
+import MonthListItemHeader from './MonthListItemHeader';
+import QuarterListItemHeader from './QuarterListItemHeader';
+import ReportListItemHeader from './ReportListItemHeader';
+import TagListItemHeader from './TagListItemHeader';
+import type {
+    GroupHeaderItemType,
+    SearchListItem,
+    TransactionCardGroupListItemType,
+    TransactionCategoryGroupListItemType,
+    TransactionGroupListItemType,
+    TransactionMemberGroupListItemType,
+    TransactionMerchantGroupListItemType,
+    TransactionMonthGroupListItemType,
+    TransactionQuarterGroupListItemType,
+    TransactionReportGroupListItemType,
+    TransactionTagGroupListItemType,
+    TransactionWeekGroupListItemType,
+    TransactionWithdrawalIDGroupListItemType,
+    TransactionYearGroupListItemType,
+} from './types';
+import WeekListItemHeader from './WeekListItemHeader';
+import WithdrawalIDListItemHeader from './WithdrawalIDListItemHeader';
+import YearListItemHeader from './YearListItemHeader';
+
+type GroupHeaderProps = {
+    item: GroupHeaderItemType;
+    groupBy?: SearchGroupBy;
+    searchType?: SearchDataTypes;
+    columns?: SearchColumnType[];
+    canSelectMultiple: boolean;
+    isExpanded: boolean;
+    onToggle: () => void;
+    onSelectRow: (item: SearchListItem, event?: ModifiedMouseEvent) => void;
+    onCheckboxPress: (item: GroupHeaderItemType) => void;
+    isFocused?: boolean;
+    isFirstItem: boolean;
+    isLastItem: boolean;
+};
+
+function GroupHeader({item, groupBy, searchType, columns, canSelectMultiple, isExpanded, onToggle, onSelectRow, onCheckboxPress, isFocused, isFirstItem, isLastItem}: GroupHeaderProps) {
+    const theme = useTheme();
+    const styles = useThemeStyles();
+    const StyleUtils = useStyleUtils();
+    const {isLargeScreenWidth} = useResponsiveLayout();
+    const {selectedTransactions} = useSearchSelectionContext();
+
+    const groupItem = item as unknown as TransactionGroupListItemType;
+    const isExpenseReportType = searchType === CONST.SEARCH.DATA_TYPES.EXPENSE_REPORT;
+
+    const selectedTransactionIDs = Object.keys(selectedTransactions);
+    const selectedTransactionIDsSet = new Set(selectedTransactionIDs);
+    const selectedItemsLength = groupItem.transactions.reduce((acc, transaction) => (selectedTransactionIDsSet.has(transaction.transactionID) ? acc + 1 : acc), 0);
+    const transactionsWithoutPendingDelete = groupItem.transactions.filter((transaction) => transaction.pendingAction !== CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE);
+    const isEmpty = groupItem.transactions.length === 0;
+    const isEmptyReportSelected = isEmpty && item?.keyForList && selectedTransactions[item.keyForList]?.isSelected;
+    const isSelectAllChecked = isEmptyReportSelected || (selectedItemsLength === transactionsWithoutPendingDelete.length && transactionsWithoutPendingDelete.length > 0);
+    const isIndeterminate = selectedItemsLength > 0 && selectedItemsLength !== transactionsWithoutPendingDelete.length;
+    const isDisabledOrEmpty = isEmpty;
+
+    const isItemSelected = isSelectAllChecked || item?.isSelected;
+
+    const animatedHighlightStyle = useAnimatedHighlightStyle({
+        shouldHighlight: item?.shouldAnimateInHighlight ?? false,
+        highlightColor: theme.messageHighlightBG,
+        backgroundColor: isItemSelected ? theme.activeComponentBG : theme.highlightBG,
+        shouldApplyOtherStyles: false,
+    });
+
+    const handleSelectionButtonPress = () => {
+        onCheckboxPress(item);
+    };
+
+    const pendingAction =
+        item.pendingAction ??
+        (groupItem.transactions.length > 0 && groupItem.transactions.every((transaction) => transaction.pendingAction === CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE)
+            ? CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE
+            : undefined);
+
+    const handleSelectRow = (rowItem: SearchListItem, event?: ModifiedMouseEvent) => {
+        onSelectRow(rowItem, event);
+    };
+
+    const renderHeader = () => {
+        if (isExpenseReportType) {
+            return (
+                <ReportListItemHeader
+                    report={groupItem as TransactionReportGroupListItemType}
+                    onSelectRow={handleSelectRow}
+                    onCheckboxPress={handleSelectionButtonPress}
+                    isDisabled={isDisabledOrEmpty}
+                    canSelectMultiple={canSelectMultiple}
+                    isSelectAllChecked={isSelectAllChecked}
+                    isIndeterminate={isIndeterminate}
+                    onDownArrowClick={onToggle}
+                    isExpanded={isExpanded}
+                />
+            );
+        }
+
+        if (!groupBy) {
+            return null;
+        }
+
+        const headers: Record<SearchGroupBy, React.JSX.Element> = {
+            [CONST.SEARCH.GROUP_BY.FROM]: (
+                <MemberListItemHeader
+                    member={groupItem as TransactionMemberGroupListItemType}
+                    onCheckboxPress={handleSelectionButtonPress}
+                    isDisabled={isDisabledOrEmpty}
+                    columns={columns}
+                    canSelectMultiple={canSelectMultiple}
+                    isSelectAllChecked={isSelectAllChecked}
+                    isIndeterminate={isIndeterminate}
+                    onDownArrowClick={onToggle}
+                    isExpanded={isExpanded}
+                />
+            ),
+            [CONST.SEARCH.GROUP_BY.CARD]: (
+                <CardListItemHeader
+                    card={groupItem as TransactionCardGroupListItemType}
+                    onCheckboxPress={handleSelectionButtonPress}
+                    isDisabled={isDisabledOrEmpty}
+                    columns={columns}
+                    canSelectMultiple={canSelectMultiple}
+                    isSelectAllChecked={isSelectAllChecked}
+                    isIndeterminate={isIndeterminate}
+                    onDownArrowClick={onToggle}
+                    isExpanded={isExpanded}
+                    isFocused={isFocused}
+                />
+            ),
+            [CONST.SEARCH.GROUP_BY.WITHDRAWAL_ID]: (
+                <WithdrawalIDListItemHeader
+                    withdrawalID={groupItem as TransactionWithdrawalIDGroupListItemType}
+                    onCheckboxPress={handleSelectionButtonPress}
+                    isDisabled={isDisabledOrEmpty}
+                    columns={columns}
+                    canSelectMultiple={canSelectMultiple}
+                    isSelectAllChecked={isSelectAllChecked}
+                    isIndeterminate={isIndeterminate}
+                    onDownArrowClick={onToggle}
+                    isExpanded={isExpanded}
+                />
+            ),
+            [CONST.SEARCH.GROUP_BY.CATEGORY]: (
+                <CategoryListItemHeader
+                    category={groupItem as TransactionCategoryGroupListItemType}
+                    onCheckboxPress={handleSelectionButtonPress}
+                    isDisabled={isDisabledOrEmpty}
+                    columns={columns}
+                    canSelectMultiple={canSelectMultiple}
+                    isSelectAllChecked={isSelectAllChecked}
+                    isIndeterminate={isIndeterminate}
+                    onDownArrowClick={onToggle}
+                    isExpanded={isExpanded}
+                />
+            ),
+            [CONST.SEARCH.GROUP_BY.MERCHANT]: (
+                <MerchantListItemHeader
+                    merchant={groupItem as TransactionMerchantGroupListItemType}
+                    onCheckboxPress={handleSelectionButtonPress}
+                    isDisabled={isDisabledOrEmpty}
+                    columns={columns}
+                    canSelectMultiple={canSelectMultiple}
+                    isSelectAllChecked={isSelectAllChecked}
+                    isIndeterminate={isIndeterminate}
+                    onDownArrowClick={onToggle}
+                    isExpanded={isExpanded}
+                />
+            ),
+            [CONST.SEARCH.GROUP_BY.TAG]: (
+                <TagListItemHeader
+                    tag={groupItem as TransactionTagGroupListItemType}
+                    onCheckboxPress={handleSelectionButtonPress}
+                    isDisabled={isDisabledOrEmpty}
+                    columns={columns}
+                    canSelectMultiple={canSelectMultiple}
+                    isSelectAllChecked={isSelectAllChecked}
+                    isIndeterminate={isIndeterminate}
+                    onDownArrowClick={onToggle}
+                    isExpanded={isExpanded}
+                />
+            ),
+            [CONST.SEARCH.GROUP_BY.MONTH]: (
+                <MonthListItemHeader
+                    month={groupItem as TransactionMonthGroupListItemType}
+                    onCheckboxPress={handleSelectionButtonPress}
+                    isDisabled={isDisabledOrEmpty}
+                    columns={columns}
+                    canSelectMultiple={canSelectMultiple}
+                    isSelectAllChecked={isSelectAllChecked}
+                    isIndeterminate={isIndeterminate}
+                    onDownArrowClick={onToggle}
+                    isExpanded={isExpanded}
+                />
+            ),
+            [CONST.SEARCH.GROUP_BY.WEEK]: (
+                <WeekListItemHeader
+                    week={groupItem as TransactionWeekGroupListItemType}
+                    onCheckboxPress={handleSelectionButtonPress}
+                    isDisabled={isDisabledOrEmpty}
+                    columns={columns}
+                    canSelectMultiple={canSelectMultiple}
+                    isSelectAllChecked={isSelectAllChecked}
+                    isIndeterminate={isIndeterminate}
+                    onDownArrowClick={onToggle}
+                    isExpanded={isExpanded}
+                />
+            ),
+            [CONST.SEARCH.GROUP_BY.YEAR]: (
+                <YearListItemHeader
+                    year={groupItem as TransactionYearGroupListItemType}
+                    onCheckboxPress={handleSelectionButtonPress}
+                    isDisabled={isDisabledOrEmpty}
+                    columns={columns}
+                    canSelectMultiple={canSelectMultiple}
+                    isSelectAllChecked={isSelectAllChecked}
+                    isIndeterminate={isIndeterminate}
+                    onDownArrowClick={onToggle}
+                    isExpanded={isExpanded}
+                />
+            ),
+            [CONST.SEARCH.GROUP_BY.QUARTER]: (
+                <QuarterListItemHeader
+                    quarter={groupItem as TransactionQuarterGroupListItemType}
+                    onCheckboxPress={handleSelectionButtonPress}
+                    isDisabled={isDisabledOrEmpty}
+                    columns={columns}
+                    canSelectMultiple={canSelectMultiple}
+                    isSelectAllChecked={isSelectAllChecked}
+                    isIndeterminate={isIndeterminate}
+                    onDownArrowClick={onToggle}
+                    isExpanded={isExpanded}
+                />
+            ),
+        };
+
+        return headers[groupBy];
+    };
+
+    const pressableStyle = [
+        styles.transactionGroupListItemStyle,
+        isLargeScreenWidth && {
+            ...styles.tableRowHeight,
+            borderRadius: 0,
+            paddingVertical: 0,
+            ...(isLastItem ? styles.tableBottomRadius : {}),
+        },
+        isItemSelected && styles.activeComponentBG,
+    ];
+
+    return (
+        <OfflineWithFeedback pendingAction={pendingAction}>
+            <PressableWithFeedback
+                onPress={onToggle}
+                disabled={false}
+                sentryLabel={CONST.SENTRY_LABEL.SEARCH.TRANSACTION_GROUP_LIST_ITEM}
+                accessibilityLabel={item.text ?? ''}
+                role={getButtonRole(true)}
+                isNested
+                hoverStyle={[!item.isDisabled && styles.hoveredComponentBG, isItemSelected && styles.activeComponentBG]}
+                dataSet={{[CONST.SELECTION_SCRAPER_HIDDEN_ELEMENT]: true, [CONST.INNER_BOX_SHADOW_ELEMENT]: false}}
+                onMouseDown={(e) => e.preventDefault()}
+                id={item.keyForList ?? ''}
+                style={[
+                    pressableStyle,
+                    isFocused && StyleUtils.getItemBackgroundColorStyle(!!isItemSelected, !!isFocused, !!item.isDisabled, theme.activeComponentBG, theme.hoverComponentBG),
+                ]}
+                wrapperStyle={[
+                    styles.mh5,
+                    animatedHighlightStyle,
+                    styles.userSelectNone,
+                    isLargeScreenWidth
+                        ? [StyleUtils.getSearchTableGroupRowBorderStyle(isFirstItem, isLastItem, isItemSelected), isLastItem && styles.overflowHidden]
+                        : [
+                              isFirstItem && [styles.tableTopRadius, styles.overflowHidden],
+                              isLastItem && [styles.tableBottomRadius, styles.overflowHidden],
+                              !isLastItem && StyleUtils.getSelectedBorderBottomStyle(isItemSelected),
+                          ],
+                ]}
+            >
+                {() => (
+                    <View style={[styles.flex1, styles.flexRow, styles.alignItemsCenter]}>
+                        <View style={styles.flex1}>{renderHeader()}</View>
+                        {isLargeScreenWidth && (
+                            <ExpandCollapseArrowButton
+                                isExpanded={isExpanded}
+                                onPress={onToggle}
+                            />
+                        )}
+                    </View>
+                )}
+            </PressableWithFeedback>
+        </OfflineWithFeedback>
+    );
+}
+
+export default GroupHeader;
diff --git a/src/components/Search/SearchList/ListItem/types.ts b/src/components/Search/SearchList/ListItem/types.ts
index d74fa21f2c56..308e47fa8dcc 100644
--- a/src/components/Search/SearchList/ListItem/types.ts
+++ b/src/components/Search/SearchList/ListItem/types.ts
@@ -450,6 +450,14 @@ type TransactionGroupListExpandedProps<TItem extends ListItem> = Pick<
     onLongPress: (transaction: TransactionListItemType) => void;
 };
 
+type GroupHeaderItemType = TransactionGroupListItemType & {
+    listItemType: 'group_header';
+};
+
+type GroupChildrenContainerItemType = TransactionGroupListItemType & {
+    listItemType: 'children_container';
+};
+
 type UnreportedExpenseListItemType = Transaction & {
     isDisabled: boolean;
     keyForList: string;
@@ -482,4 +490,6 @@ export type {
     TransactionListItemProps,
     ReportActionListItemType,
     UnreportedExpenseListItemType,
+    GroupHeaderItemType,
+    GroupChildrenContainerItemType,
 };
diff --git a/src/components/Search/SearchList/index.tsx b/src/components/Search/SearchList/index.tsx
index 9599b0db8683..4ce7f188cec2 100644
--- a/src/components/Search/SearchList/index.tsx
+++ b/src/components/Search/SearchList/index.tsx
@@ -31,7 +31,7 @@ import {turnOnMobileSelectionMode} from '@libs/actions/MobileSelectionMode';
 import DateUtils from '@libs/DateUtils';
 import type {ModifiedMouseEvent} from '@libs/Navigation/helpers/openInternalRouteInNewTab';
 import navigationRef from '@libs/Navigation/navigationRef';
-import {applySelectionToItem, getTableMinWidth} from '@libs/SearchUIUtils';
+import {applySelectionToItem, getTableMinWidth, splitGroupsIntoPairs} from '@libs/SearchUIUtils';
 import variables from '@styles/variables';
 import type {TransactionPreviewData} from '@userActions/Search';
 import CONST from '@src/CONST';
@@ -40,10 +40,14 @@ import type {CardList, Transaction} from '@src/types/onyx';
 import BaseSearchList from './BaseSearchList';
 import type ChatListItem from './ListItem/ChatListItem';
 import type ExpenseReportListItem from './ListItem/ExpenseReportListItem';
+import GroupChildrenContainer from './ListItem/GroupChildrenContainer';
+import GroupHeader from './ListItem/GroupHeader';
 import type TaskListItem from './ListItem/TaskListItem';
 import type TransactionGroupListItem from './ListItem/TransactionGroupListItem';
 import type TransactionListItem from './ListItem/TransactionListItem';
 import type {
+    GroupChildrenContainerItemType,
+    GroupHeaderItemType,
     ReportActionListItemType,
     TaskListItemType,
     TransactionCardGroupListItemType,
@@ -296,6 +300,40 @@ function SearchList({
     const hasItemsBeingRemoved = prevDataLength && prevDataLength > data.length;
     const {isEditingCell, wasRecentlyEditingCell} = useEditingCellState();
 
+    const isGroupByActive = !!groupBy || type === CONST.SEARCH.DATA_TYPES.EXPENSE_REPORT;
+    const [expandedGroups, setExpandedGroups] = useState<Set<string>>(() => new Set());
+
+    const onToggleGroup = useCallback((key: string) => {
+        setExpandedGroups((prev) => {
+            const next = new Set(prev);
+            if (next.has(key)) {
+                next.delete(key);
+            } else {
+                next.add(key);
+            }
+            return next;
+        });
+    }, []);
+
+    const {splitData: listData, stickyHeaderIndices} = useMemo(() => {
+        if (!isGroupByActive) {
+            return {splitData: data, stickyHeaderIndices: undefined};
+        }
+        return splitGroupsIntoPairs(data);
+    }, [data, isGroupByActive]);
+
+    const getItemType = useMemo(() => {
+        if (!isGroupByActive) {
+            return undefined;
+        }
+        return (item: SearchListItem) => {
+            if ('listItemType' in item) {
+                return (item as GroupHeaderItemType | GroupChildrenContainerItemType).listItemType;
+            }
+            return 'default';
+        };
+    }, [isGroupByActive]);
+
     const [lastPaymentMethod] = useOnyx(ONYXKEYS.NVP_LAST_PAYMENT_METHOD);
     const [personalPolicyID] = useOnyx(ONYXKEYS.PERSONAL_POLICY_ID);
     const [userBillingGracePeriodEnds] = useOnyx(ONYXKEYS.COLLECTION.SHARED_NVP_PRIVATE_USER_BILLING_GRACE_PERIOD_END);
@@ -430,11 +468,54 @@ function SearchList({
 
     const renderItem = useCallback(
         (item: SearchListItem, index: number, isItemFocused: boolean, onFocus?: (event: NativeSyntheticEvent<ExtendedTargetedEvent>) => void) => {
+            // Handle group header items (sticky)
+            if ('listItemType' in item && (item as GroupHeaderItemType).listItemType === 'group_header') {
+                const headerItem = item as GroupHeaderItemType;
+                const originalKey = (item.keyForList ?? '').replace('header_', '');
+                return (
+                    <GroupHeader
+                        item={headerItem}
+                        groupBy={groupBy}
+                        searchType={type}
+                        columns={columns}
+                        canSelectMultiple={canSelectMultiple}
+                        isExpanded={expandedGroups.has(originalKey)}
+                        onToggle={() => onToggleGroup(originalKey)}
+                        onSelectRow={(val, event) => onSelectRow(val, undefined, event)}
+                        onCheckboxPress={(val) => onCheckboxPress(val as SearchListItem)}
+                        isFocused={isItemFocused}
+                        isFirstItem={index === firstVisibleIndex}
+                        isLastItem={index === lastVisibleIndex && !ListFooterComponent}
+                    />
+                );
+            }
+
+            // Handle children container items (animated expand/collapse)
+            if ('listItemType' in item && (item as GroupChildrenContainerItemType).listItemType === 'children_container') {
+                const containerItem = item as GroupChildrenContainerItemType;
+                const originalKey = (item.keyForList ?? '').replace('children_', '');
+                return (
+                    <GroupChildrenContainer
+                        item={containerItem}
+                        isExpanded={expandedGroups.has(originalKey)}
+                        groupBy={groupBy}
+                        searchType={type}
+                        columns={columns}
+                        canSelectMultiple={canSelectMultiple}
+                        onSelectRow={onSelectRow}
+                        onCheckboxPress={onCheckboxPress}
+                        onLongPressRow={isMobileSelectionModeEnabled ? handleLongPressRowInMobileSelectionMode : handleLongPressRow}
+                        nonPersonalAndWorkspaceCards={nonPersonalAndWorkspaceCards}
+                        onUndelete={handleUndelete}
+                    />
+                );
+            }
+
+            // Default rendering for non-group items
             const isDisabled = item.pendingAction === CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE;
-            const shouldApplyAnimation = shouldAnimate && index < data.length - 1;
+            const shouldApplyAnimation = shouldAnimate && index < listData.length - 1;
 
             const newTransactionID = item.keyForList ? newTransactionIDByItemKey.get(item.keyForList) : undefined;
-            // Apply selection lazily per row so we don't rebuild a list-wide wrapper structure on every render.
             const {itemWithSelection} = applySelectionToItem(item, canSelectMultiple, selectedTransactions);
 
             return (
@@ -477,7 +558,7 @@ function SearchList({
             groupBy,
             newTransactionIDByItemKey,
             shouldAnimate,
-            data.length,
+            listData.length,
             styles.overflowHidden,
             hasItemsBeingRemoved,
             ListItem,
@@ -499,6 +580,8 @@ function SearchList({
             handleUndelete,
             firstVisibleIndex,
             lastVisibleIndex,
+            expandedGroups,
+            onToggleGroup,
         ],
     );
 
@@ -547,7 +630,7 @@ function SearchList({
                 </View>
             )}
             <BaseSearchList
-                data={data}
+                data={listData}
                 renderItem={renderItem}
                 onSelectRow={onSelectRow}
                 keyExtractor={keyExtractor}
@@ -556,7 +639,7 @@ function SearchList({
                 ref={listRef}
                 columns={columns}
                 scrollToIndex={scrollToIndex}
-                flattenedItemsLength={data.length}
+                flattenedItemsLength={listData.length}
                 onEndReached={onEndReached}
                 onEndReachedThreshold={onEndReachedThreshold}
                 ListFooterComponent={ListFooterComponent}
@@ -567,6 +650,8 @@ function SearchList({
                 selectedTransactions={selectedTransactions}
                 isAttendeesEnabledForMovingPolicy={isAttendeesEnabledForMovingPolicy}
                 nonPersonalAndWorkspaceCards={nonPersonalAndWorkspaceCards}
+                stickyHeaderIndices={stickyHeaderIndices}
+                getItemType={getItemType}
             />
             <Modal
                 isVisible={isModalVisible}
diff --git a/src/libs/SearchUIUtils.ts b/src/libs/SearchUIUtils.ts
index 8ed8aad1a1a7..2938974874a7 100644
--- a/src/libs/SearchUIUtils.ts
+++ b/src/libs/SearchUIUtils.ts
@@ -17,6 +17,8 @@ import TransactionGroupListItem from '@components/Search/SearchList/ListItem/Tra
 import TransactionListItem from '@components/Search/SearchList/ListItem/TransactionListItem';
 import type {
     ExpenseReportListItemType,
+    GroupChildrenContainerItemType,
+    GroupHeaderItemType,
     ReportActionListItemType,
     SearchListItem,
     TaskListItemType,
@@ -5966,6 +5968,24 @@ function hasFlexColumn(columns?: SearchColumnType[]): boolean {
     return !!columns?.some((col) => FLEX_COLUMNS.has(col));
 }
 
+function splitGroupsIntoPairs(data: SearchListItem[]): {splitData: SearchListItem[]; stickyHeaderIndices: number[]} {
+    const splitData: SearchListItem[] = [];
+    const stickyHeaderIndices: number[] = [];
+
+    for (const item of data) {
+        if ('transactions' in item) {
+            const key = item.keyForList ?? '';
+            stickyHeaderIndices.push(splitData.length);
+            splitData.push({...item, listItemType: 'group_header', keyForList: `header_${key}`} as GroupHeaderItemType);
+            splitData.push({...item, listItemType: 'children_container', keyForList: `children_${key}`} as GroupChildrenContainerItemType);
+        } else {
+            splitData.push(item);
+        }
+    }
+
+    return {splitData, stickyHeaderIndices};
+}
+
 export {
     getSearchBulkEditPolicyID,
     getSuggestedSearches,
@@ -6049,6 +6069,7 @@ export {
     isPolicyEligibleForSpendOverTime,
     hasFlexColumn,
     isTransactionSearchType,
+    splitGroupsIntoPairs,
     SKIPPED_SEARCH_FILTERS,
 };
 export type {SavedSearchMenuItem, SearchTypeMenuSection, SearchTypeMenuItem, SearchDateModifier, SearchDateModifierLower, SearchKey, ArchivedReportsIDSet, GroupBySection, SearchFilter};

From bea81da29c1695a60fe2af2e44b4fe57296bd050 Mon Sep 17 00:00:00 2001
From: krishna2323 <belivethatkg@gmail.com>
Date: Fri, 29 May 2026 17:41:02 +0530
Subject: [PATCH 040/435] fix: Match GroupHeader styles with original
 TransactionGroupListItem layout

Signed-off-by: krishna2323 <belivethatkg@gmail.com>
---
 .../SearchList/ListItem/GroupHeader.tsx       | 22 +++++++++++--------
 1 file changed, 13 insertions(+), 9 deletions(-)

diff --git a/src/components/Search/SearchList/ListItem/GroupHeader.tsx b/src/components/Search/SearchList/ListItem/GroupHeader.tsx
index ec8a46028aa0..d4a9f8024120 100644
--- a/src/components/Search/SearchList/ListItem/GroupHeader.tsx
+++ b/src/components/Search/SearchList/ListItem/GroupHeader.tsx
@@ -133,6 +133,7 @@ function GroupHeader({item, groupBy, searchType, columns, canSelectMultiple, isE
                     isIndeterminate={isIndeterminate}
                     onDownArrowClick={onToggle}
                     isExpanded={isExpanded}
+                    isLargeScreenWidth={isLargeScreenWidth}
                 />
             ),
             [CONST.SEARCH.GROUP_BY.CARD]: (
@@ -263,7 +264,6 @@ function GroupHeader({item, groupBy, searchType, columns, canSelectMultiple, isE
         isLargeScreenWidth && {
             ...styles.tableRowHeight,
             borderRadius: 0,
-            paddingVertical: 0,
             ...(isLastItem ? styles.tableBottomRadius : {}),
         },
         isItemSelected && styles.activeComponentBG,
@@ -300,14 +300,18 @@ function GroupHeader({item, groupBy, searchType, columns, canSelectMultiple, isE
                 ]}
             >
                 {() => (
-                    <View style={[styles.flex1, styles.flexRow, styles.alignItemsCenter]}>
-                        <View style={styles.flex1}>{renderHeader()}</View>
-                        {isLargeScreenWidth && (
-                            <ExpandCollapseArrowButton
-                                isExpanded={isExpanded}
-                                onPress={onToggle}
-                            />
-                        )}
+                    <View style={styles.flex1}>
+                        <View style={[styles.flexRow, styles.alignItemsCenter]}>
+                            <View style={styles.flex1}>{renderHeader()}</View>
+                            {isLargeScreenWidth && (
+                                <View style={{paddingRight: 14}}>
+                                    <ExpandCollapseArrowButton
+                                        isExpanded={isExpanded}
+                                        onPress={onToggle}
+                                    />
+                                </View>
+                            )}
+                        </View>
                     </View>
                 )}
             </PressableWithFeedback>

From 1db3b332124b324262daf5f4728a95be7c93f5a5 Mon Sep 17 00:00:00 2001
From: Jakub Korytko <jakub@korytko.me>
Date: Fri, 29 May 2026 14:20:49 +0200
Subject: [PATCH 041/435] fix: hr duplicated window

---
 src/components/ConnectToHRFlow/index.ios.tsx  | 57 +++++++++++++
 .../ConnectToHRFlow/index.native.tsx          | 79 ++++++++++++++-----
 src/libs/actions/Link.ts                      | 15 ++++
 3 files changed, 133 insertions(+), 18 deletions(-)
 create mode 100644 src/components/ConnectToHRFlow/index.ios.tsx

diff --git a/src/components/ConnectToHRFlow/index.ios.tsx b/src/components/ConnectToHRFlow/index.ios.tsx
new file mode 100644
index 000000000000..8fce75748ab2
--- /dev/null
+++ b/src/components/ConnectToHRFlow/index.ios.tsx
@@ -0,0 +1,57 @@
+import {openAuthSessionAsync} from 'expo-web-browser';
+import React, {useEffect, useRef, useState} from 'react';
+import {StyleSheet, View} from 'react-native';
+import ActivityIndicator from '@components/ActivityIndicator';
+import FullPageOfflineBlockingView from '@components/BlockingViews/FullPageOfflineBlockingView';
+import HeaderWithBackButton from '@components/HeaderWithBackButton';
+import Modal from '@components/Modal';
+import useLocalize from '@hooks/useLocalize';
+import useThemeStyles from '@hooks/useThemeStyles';
+import {getShortLivedAuthTokenURL} from '@userActions/Link';
+import CONST from '@src/CONST';
+import type ConnectToHRFlowProps from './types';
+
+function ConnectToHRFlow({setupLink}: ConnectToHRFlowProps) {
+    const {translate} = useLocalize();
+    const styles = useThemeStyles();
+    const hasOpened = useRef(false);
+    const [isModalOpen, setIsModalOpen] = useState(true);
+
+    useEffect(() => {
+        if (hasOpened.current) {
+            return;
+        }
+        hasOpened.current = true;
+
+        getShortLivedAuthTokenURL(setupLink)
+            .then((url) => openAuthSessionAsync(url, CONST.DEEPLINK_BASE_URL, {preferEphemeralSession: true}))
+            .finally(() => {
+                setIsModalOpen(false);
+            });
+    }, [setupLink]);
+
+    return (
+        <Modal
+            onClose={() => setIsModalOpen(false)}
+            fullscreen
+            isVisible={isModalOpen}
+            type={CONST.MODAL.MODAL_TYPE.CENTERED_UNSWIPEABLE}
+        >
+            <HeaderWithBackButton
+                title={translate('workspace.common.hr')}
+                onBackButtonPress={() => setIsModalOpen(false)}
+                shouldDisplayHelpButton={false}
+            />
+            <FullPageOfflineBlockingView>
+                <View style={[StyleSheet.absoluteFill, styles.fullScreenLoading]}>
+                    <ActivityIndicator
+                        size={CONST.ACTIVITY_INDICATOR_SIZE.LARGE}
+                        reasonAttributes={{context: 'ConnectToHRFlow'}}
+                    />
+                </View>
+            </FullPageOfflineBlockingView>
+        </Modal>
+    );
+}
+
+export default ConnectToHRFlow;
diff --git a/src/components/ConnectToHRFlow/index.native.tsx b/src/components/ConnectToHRFlow/index.native.tsx
index bb5e859d952d..505669a8059d 100644
--- a/src/components/ConnectToHRFlow/index.native.tsx
+++ b/src/components/ConnectToHRFlow/index.native.tsx
@@ -1,15 +1,15 @@
-import React, {useRef, useState} from 'react';
+import React, {useEffect, useRef, useState} from 'react';
 import {StyleSheet, View} from 'react-native';
 import {WebView} from 'react-native-webview';
+import type {WebViewOpenWindowEvent} from 'react-native-webview/lib/WebViewTypes';
 import ActivityIndicator from '@components/ActivityIndicator';
 import FullPageOfflineBlockingView from '@components/BlockingViews/FullPageOfflineBlockingView';
 import HeaderWithBackButton from '@components/HeaderWithBackButton';
 import Modal from '@components/Modal';
 import useLocalize from '@hooks/useLocalize';
-import useOnyx from '@hooks/useOnyx';
 import useThemeStyles from '@hooks/useThemeStyles';
+import {getShortLivedAuthTokenURL} from '@userActions/Link';
 import CONST from '@src/CONST';
-import ONYXKEYS from '@src/ONYXKEYS';
 import type ConnectToHRFlowProps from './types';
 
 function ConnectToHRFlow({setupLink}: ConnectToHRFlowProps) {
@@ -17,7 +17,14 @@ function ConnectToHRFlow({setupLink}: ConnectToHRFlowProps) {
     const styles = useThemeStyles();
     const webViewRef = useRef<WebView>(null);
     const [isWebViewOpen, setIsWebViewOpen] = useState(true);
-    const [session] = useOnyx(ONYXKEYS.SESSION);
+    const [popupUrl, setPopupUrl] = useState<string | null>(null);
+    const [isPopupVisible, setIsPopupVisible] = useState(false);
+    const [authenticatedUrl, setAuthenticatedUrl] = useState<string | null>(null);
+    const [cookiesCleared, setCookiesCleared] = useState(false);
+
+    useEffect(() => {
+        getShortLivedAuthTokenURL(setupLink).then(setAuthenticatedUrl);
+    }, [setupLink]);
 
     const renderLoading = () => (
         <View style={[StyleSheet.absoluteFill, styles.fullScreenLoading]}>
@@ -28,7 +35,21 @@ function ConnectToHRFlow({setupLink}: ConnectToHRFlowProps) {
         </View>
     );
 
-    const authToken = session?.authToken ?? null;
+    const handleOpenWindow = (event: WebViewOpenWindowEvent) => {
+        setPopupUrl(event.nativeEvent.targetUrl);
+        setIsPopupVisible(true);
+    };
+
+    const handleBackPress = () => {
+        if (isPopupVisible) {
+            setIsPopupVisible(false);
+            return;
+        }
+        setIsWebViewOpen(false);
+    };
+
+    const isReady = cookiesCleared && !!authenticatedUrl;
+
     return (
         <Modal
             onClose={() => setIsWebViewOpen(false)}
@@ -38,22 +59,44 @@ function ConnectToHRFlow({setupLink}: ConnectToHRFlowProps) {
         >
             <HeaderWithBackButton
                 title={translate('workspace.common.hr')}
-                onBackButtonPress={() => setIsWebViewOpen(false)}
+                onBackButtonPress={handleBackPress}
                 shouldDisplayHelpButton={false}
             />
             <FullPageOfflineBlockingView>
-                <WebView
-                    ref={webViewRef}
-                    source={{
-                        uri: setupLink,
-                        headers: {
-                            Cookie: `authToken=${authToken}`,
-                        },
-                    }}
-                    incognito
-                    startInLoadingState
-                    renderLoading={renderLoading}
-                />
+                <View style={styles.flex1}>
+                    {!cookiesCleared && (
+                        <WebView
+                            source={{uri: 'about:blank'}}
+                            incognito
+                            onLoadEnd={() => {
+                                setTimeout(() => setCookiesCleared(true), 500);
+                            }}
+                            style={styles.opacity0}
+                        />
+                    )}
+                    {!isReady && renderLoading()}
+                    {isReady && (
+                        <WebView
+                            ref={webViewRef}
+                            source={{uri: authenticatedUrl}}
+                            onOpenWindow={handleOpenWindow}
+                            startInLoadingState
+                            renderLoading={renderLoading}
+                        />
+                    )}
+                    {!!popupUrl && (
+                        <View
+                            style={[StyleSheet.absoluteFill, !isPopupVisible && styles.opacity0]}
+                            pointerEvents={isPopupVisible ? 'auto' : 'none'}
+                        >
+                            <WebView
+                                source={{uri: popupUrl}}
+                                startInLoadingState
+                                renderLoading={renderLoading}
+                            />
+                        </View>
+                    )}
+                </View>
             </FullPageOfflineBlockingView>
         </Modal>
     );
diff --git a/src/libs/actions/Link.ts b/src/libs/actions/Link.ts
index f777337f5f90..578ee0d6ea29 100644
--- a/src/libs/actions/Link.ts
+++ b/src/libs/actions/Link.ts
@@ -407,6 +407,20 @@ function getTravelDotLink(policyID: OnyxEntry<string>) {
     });
 }
 
+/**
+ * Fetches a short-lived auth token and appends it to the given setup link.
+ * Falls back to returning the original link if the token request fails.
+ */
+function getShortLivedAuthTokenURL(setupLink: string): Promise<string> {
+    // eslint-disable-next-line rulesdir/no-api-side-effects-method
+    return API.makeRequestWithSideEffects(SIDE_EFFECT_REQUEST_COMMANDS.OPEN_OLD_DOT_LINK, {}, {})
+        .then((response) => {
+            const tokenParam = response?.shortLivedAuthToken ? `&authToken=${response.shortLivedAuthToken}` : '';
+            return setupLink + tokenParam;
+        })
+        .catch(() => setupLink);
+}
+
 export {
     openOldDotLink,
     openExternalLink,
@@ -418,4 +432,5 @@ export {
     getTravelDotLink,
     buildOldDotURL,
     openReportFromDeepLink,
+    getShortLivedAuthTokenURL,
 };

From c93a49acc05c07da0498f356913cc0850a4d275a Mon Sep 17 00:00:00 2001
From: krishna2323 <belivethatkg@gmail.com>
Date: Fri, 29 May 2026 18:17:19 +0530
Subject: [PATCH 042/435] fix: Match GroupHeader arrow and separator styles
 with original AnimatedCollapsible

Signed-off-by: krishna2323 <belivethatkg@gmail.com>
---
 .../ListItem/GroupChildrenContainer.tsx       |  4 +--
 .../SearchList/ListItem/GroupHeader.tsx       | 26 ++++++++++++++-----
 2 files changed, 21 insertions(+), 9 deletions(-)

diff --git a/src/components/Search/SearchList/ListItem/GroupChildrenContainer.tsx b/src/components/Search/SearchList/ListItem/GroupChildrenContainer.tsx
index 8843ca2e9084..ba7e241cbe76 100644
--- a/src/components/Search/SearchList/ListItem/GroupChildrenContainer.tsx
+++ b/src/components/Search/SearchList/ListItem/GroupChildrenContainer.tsx
@@ -242,8 +242,8 @@ function GroupChildrenContainer({
                             }
                         }}
                     >
-                        <View style={isLargeScreenWidth ? [styles.pv2, styles.ph3, styles.pb1] : styles.ph3}>
-                            <View style={styles.borderBottom} />
+                        <View style={isLargeScreenWidth ? [styles.pv2, styles.ph3, styles.pb1, styles.pt1] : styles.ph3}>
+                            <View style={[styles.borderBottom, isLargeScreenWidth && styles.borderNone]} />
                         </View>
                         <TransactionGroupListExpandedItem
                             showTooltip
diff --git a/src/components/Search/SearchList/ListItem/GroupHeader.tsx b/src/components/Search/SearchList/ListItem/GroupHeader.tsx
index d4a9f8024120..28db919ee24b 100644
--- a/src/components/Search/SearchList/ListItem/GroupHeader.tsx
+++ b/src/components/Search/SearchList/ListItem/GroupHeader.tsx
@@ -1,11 +1,13 @@
 import React from 'react';
 import {View} from 'react-native';
 import {getButtonRole} from '@components/Button/utils';
+import Icon from '@components/Icon';
 import OfflineWithFeedback from '@components/OfflineWithFeedback';
 import {PressableWithFeedback} from '@components/Pressable';
 import {useSearchSelectionContext} from '@components/Search/SearchContext';
 import type {SearchColumnType, SearchGroupBy} from '@components/Search/types';
 import useAnimatedHighlightStyle from '@hooks/useAnimatedHighlightStyle';
+import {useMemoizedLazyExpensifyIcons} from '@hooks/useLazyAsset';
 import useResponsiveLayout from '@hooks/useResponsiveLayout';
 import useStyleUtils from '@hooks/useStyleUtils';
 import useTheme from '@hooks/useTheme';
@@ -15,7 +17,6 @@ import CONST from '@src/CONST';
 import type {SearchDataTypes} from '@src/types/onyx/SearchResults';
 import CardListItemHeader from './CardListItemHeader';
 import CategoryListItemHeader from './CategoryListItemHeader';
-import ExpandCollapseArrowButton from './ExpandCollapseArrowButton';
 import MemberListItemHeader from './MemberListItemHeader';
 import MerchantListItemHeader from './MerchantListItemHeader';
 import MonthListItemHeader from './MonthListItemHeader';
@@ -63,6 +64,7 @@ function GroupHeader({item, groupBy, searchType, columns, canSelectMultiple, isE
     const StyleUtils = useStyleUtils();
     const {isLargeScreenWidth} = useResponsiveLayout();
     const {selectedTransactions} = useSearchSelectionContext();
+    const expensifyIcons = useMemoizedLazyExpensifyIcons(['UpArrow', 'DownArrow']);
 
     const groupItem = item as unknown as TransactionGroupListItemType;
     const isExpenseReportType = searchType === CONST.SEARCH.DATA_TYPES.EXPENSE_REPORT;
@@ -304,12 +306,22 @@ function GroupHeader({item, groupBy, searchType, columns, canSelectMultiple, isE
                         <View style={[styles.flexRow, styles.alignItemsCenter]}>
                             <View style={styles.flex1}>{renderHeader()}</View>
                             {isLargeScreenWidth && (
-                                <View style={{paddingRight: 14}}>
-                                    <ExpandCollapseArrowButton
-                                        isExpanded={isExpanded}
-                                        onPress={onToggle}
-                                    />
-                                </View>
+                                <PressableWithFeedback
+                                    onPress={onToggle}
+                                    style={[styles.p3Half, styles.justifyContentCenter, styles.alignItemsCenter, styles.pv2]}
+                                    accessibilityRole={CONST.ROLE.BUTTON}
+                                    accessibilityLabel={isExpanded ? CONST.ACCESSIBILITY_LABELS.COLLAPSE : CONST.ACCESSIBILITY_LABELS.EXPAND}
+                                    sentryLabel={CONST.SENTRY_LABEL.SEARCH.GROUP_EXPAND_TOGGLE}
+                                >
+                                    {({hovered}) => (
+                                        <Icon
+                                            src={isExpanded ? expensifyIcons.UpArrow : expensifyIcons.DownArrow}
+                                            fill={theme.icon}
+                                            additionalStyles={!hovered && styles.opacitySemiTransparent}
+                                            small
+                                        />
+                                    )}
+                                </PressableWithFeedback>
                             )}
                         </View>
                     </View>

From e148a5b04e3b53aded25aeddfe94db8312c5c8f8 Mon Sep 17 00:00:00 2001
From: krishna2323 <belivethatkg@gmail.com>
Date: Fri, 29 May 2026 18:29:21 +0530
Subject: [PATCH 043/435] fix: Move bottom padding inside animated content to
 avoid space when collapsed

Signed-off-by: krishna2323 <belivethatkg@gmail.com>
---
 .../Search/SearchList/ListItem/GroupChildrenContainer.tsx       | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/components/Search/SearchList/ListItem/GroupChildrenContainer.tsx b/src/components/Search/SearchList/ListItem/GroupChildrenContainer.tsx
index ba7e241cbe76..e97ac76f5cc8 100644
--- a/src/components/Search/SearchList/ListItem/GroupChildrenContainer.tsx
+++ b/src/components/Search/SearchList/ListItem/GroupChildrenContainer.tsx
@@ -234,7 +234,7 @@ function GroupChildrenContainer({
             <Animated.View style={contentAnimatedStyle}>
                 {isExpanded || isRendered ? (
                     <Animated.View
-                        style={styles.stickToTop}
+                        style={[styles.stickToTop, {paddingBottom: 4}]}
                         onLayout={(e) => {
                             const height = e.nativeEvent.layout.height;
                             if (height) {

From 248eecf6fb2b4415f5ffadf455529911a863615b Mon Sep 17 00:00:00 2001
From: krishna2323 <belivethatkg@gmail.com>
Date: Fri, 29 May 2026 19:04:35 +0530
Subject: [PATCH 044/435] feat: Add sticky animated sub-header to GroupHeader
 for grouped search results

Signed-off-by: krishna2323 <belivethatkg@gmail.com>
---
 .../ListItem/GroupChildrenContainer.tsx       |  1 +
 .../SearchList/ListItem/GroupHeader.tsx       | 98 ++++++++++++++++++-
 .../ListItem/TransactionGroupListExpanded.tsx |  3 +-
 .../Search/SearchList/ListItem/types.ts       |  1 +
 4 files changed, 101 insertions(+), 2 deletions(-)

diff --git a/src/components/Search/SearchList/ListItem/GroupChildrenContainer.tsx b/src/components/Search/SearchList/ListItem/GroupChildrenContainer.tsx
index e97ac76f5cc8..7df2d4842dea 100644
--- a/src/components/Search/SearchList/ListItem/GroupChildrenContainer.tsx
+++ b/src/components/Search/SearchList/ListItem/GroupChildrenContainer.tsx
@@ -268,6 +268,7 @@ function GroupChildrenContainer({
                             onLongPress={onExpandedRowLongPress}
                             nonPersonalAndWorkspaceCards={nonPersonalAndWorkspaceCards}
                             onUndelete={onUndelete}
+                            hideSearchTableHeader
                         />
                     </Animated.View>
                 ) : null}
diff --git a/src/components/Search/SearchList/ListItem/GroupHeader.tsx b/src/components/Search/SearchList/ListItem/GroupHeader.tsx
index 28db919ee24b..ac2982451a03 100644
--- a/src/components/Search/SearchList/ListItem/GroupHeader.tsx
+++ b/src/components/Search/SearchList/ListItem/GroupHeader.tsx
@@ -1,19 +1,29 @@
-import React from 'react';
+import React, {useState} from 'react';
 import {View} from 'react-native';
+import Animated, {useAnimatedStyle, useDerivedValue, useSharedValue, withTiming} from 'react-native-reanimated';
+import {scheduleOnRN} from 'react-native-worklets';
 import {getButtonRole} from '@components/Button/utils';
 import Icon from '@components/Icon';
+import {easing} from '@components/Modal/ReanimatedModal/utils';
 import OfflineWithFeedback from '@components/OfflineWithFeedback';
 import {PressableWithFeedback} from '@components/Pressable';
 import {useSearchSelectionContext} from '@components/Search/SearchContext';
+import SearchTableHeader from '@components/Search/SearchTableHeader';
 import type {SearchColumnType, SearchGroupBy} from '@components/Search/types';
 import useAnimatedHighlightStyle from '@hooks/useAnimatedHighlightStyle';
+import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails';
 import {useMemoizedLazyExpensifyIcons} from '@hooks/useLazyAsset';
+import useOnyx from '@hooks/useOnyx';
 import useResponsiveLayout from '@hooks/useResponsiveLayout';
 import useStyleUtils from '@hooks/useStyleUtils';
 import useTheme from '@hooks/useTheme';
 import useThemeStyles from '@hooks/useThemeStyles';
 import type {ModifiedMouseEvent} from '@libs/Navigation/helpers/openInternalRouteInNewTab';
+import {getColumnsToShow} from '@libs/SearchUIUtils';
+import {isDeletedTransaction} from '@libs/TransactionUtils';
 import CONST from '@src/CONST';
+import ONYXKEYS from '@src/ONYXKEYS';
+import {columnsSelector} from '@src/selectors/AdvancedSearchFiltersForm';
 import type {SearchDataTypes} from '@src/types/onyx/SearchResults';
 import CardListItemHeader from './CardListItemHeader';
 import CategoryListItemHeader from './CategoryListItemHeader';
@@ -65,10 +75,63 @@ function GroupHeader({item, groupBy, searchType, columns, canSelectMultiple, isE
     const {isLargeScreenWidth} = useResponsiveLayout();
     const {selectedTransactions} = useSearchSelectionContext();
     const expensifyIcons = useMemoizedLazyExpensifyIcons(['UpArrow', 'DownArrow']);
+    const currentUserDetails = useCurrentUserPersonalDetails();
 
     const groupItem = item as unknown as TransactionGroupListItemType;
     const isExpenseReportType = searchType === CONST.SEARCH.DATA_TYPES.EXPENSE_REPORT;
 
+    // Compute sub-header columns (same logic as TransactionGroupListExpanded)
+    const [transactionsSnapshot] = useOnyx(`${ONYXKEYS.COLLECTION.SNAPSHOT}${groupItem.transactionsQueryJSON?.hash}`);
+    const [visibleColumns] = useOnyx(ONYXKEYS.FORMS.SEARCH_ADVANCED_FILTERS_FORM, {selector: columnsSelector});
+
+    let subHeaderColumns = columns ?? [];
+    if (!isExpenseReportType) {
+        if (!transactionsSnapshot?.data) {
+            subHeaderColumns = [];
+        } else {
+            subHeaderColumns = getColumnsToShow({
+                currentAccountID: currentUserDetails.accountID,
+                data: transactionsSnapshot?.data,
+                visibleColumns,
+                type: transactionsSnapshot?.search.type,
+            });
+        }
+    }
+
+    // Compute sub-header column widths from transactions
+    const isSubHeaderAmountColumnWide = groupItem.transactions.some((transaction) => transaction.isAmountColumnWide);
+    const isSubHeaderTaxAmountColumnWide = groupItem.transactions.some((transaction) => transaction.isTaxAmountColumnWide);
+    const shouldSubHeaderShowYear = groupItem.transactions.some((transaction) => transaction.shouldShowYear);
+    const isSubHeaderActionColumnWide = groupItem.transactions.some((transaction) => !!transaction.isActionColumnWide || isDeletedTransaction(transaction));
+
+    // Animated sub-header (SearchTableHeader) height
+    const subHeaderHeight = useSharedValue(0);
+    const hasExpanded = useSharedValue(isExpanded);
+    const [isSubHeaderRendered, setIsSubHeaderRendered] = useState(isExpanded);
+
+    hasExpanded.set(isExpanded);
+    if (isExpanded && !isSubHeaderRendered) {
+        setIsSubHeaderRendered(true);
+    }
+
+    const animatedSubHeaderHeight = useDerivedValue(() => {
+        if (!subHeaderHeight.get()) {
+            return 0;
+        }
+        const target = hasExpanded.get() ? subHeaderHeight.get() : 0;
+        return withTiming(target, {duration: 300, easing}, (finished) => {
+            if (!finished || target) {
+                return;
+            }
+            scheduleOnRN(setIsSubHeaderRendered, false);
+        });
+    }, []);
+
+    const subHeaderAnimatedStyle = useAnimatedStyle(() => ({
+        height: animatedSubHeaderHeight.get(),
+        overflow: 'hidden' as const,
+    }));
+
     const selectedTransactionIDs = Object.keys(selectedTransactions);
     const selectedTransactionIDsSet = new Set(selectedTransactionIDs);
     const selectedItemsLength = groupItem.transactions.reduce((acc, transaction) => (selectedTransactionIDsSet.has(transaction.transactionID) ? acc + 1 : acc), 0);
@@ -327,6 +390,39 @@ function GroupHeader({item, groupBy, searchType, columns, canSelectMultiple, isE
                     </View>
                 )}
             </PressableWithFeedback>
+            {isLargeScreenWidth && (
+                <Animated.View style={[subHeaderAnimatedStyle, styles.mh5, {backgroundColor: theme.highlightBG}]}>
+                    {(isExpanded || isSubHeaderRendered) && (
+                        <Animated.View
+                            style={styles.stickToTop}
+                            onLayout={(e) => {
+                                const height = e.nativeEvent.layout.height;
+                                if (height) {
+                                    subHeaderHeight.set(height);
+                                }
+                            }}
+                        >
+                            <View style={[styles.searchListHeaderContainerStyle, styles.groupSearchListTableContainerStyle, styles.bgTransparent, styles.pl8, styles.borderNone]}>
+                                <SearchTableHeader
+                                    canSelectMultiple
+                                    type={CONST.SEARCH.DATA_TYPES.EXPENSE}
+                                    onSortPress={() => {}}
+                                    sortOrder={undefined}
+                                    sortBy={undefined}
+                                    shouldShowYear={shouldSubHeaderShowYear}
+                                    isAmountColumnWide={isSubHeaderAmountColumnWide}
+                                    isTaxAmountColumnWide={isSubHeaderTaxAmountColumnWide}
+                                    shouldShowSorting={false}
+                                    columns={subHeaderColumns}
+                                    groupBy={groupBy}
+                                    isExpenseReportView
+                                    isActionColumnWide={isSubHeaderActionColumnWide}
+                                />
+                            </View>
+                        </Animated.View>
+                    )}
+                </Animated.View>
+            )}
         </OfflineWithFeedback>
     );
 }
diff --git a/src/components/Search/SearchList/ListItem/TransactionGroupListExpanded.tsx b/src/components/Search/SearchList/ListItem/TransactionGroupListExpanded.tsx
index 44be71152603..b0c3ba33ef01 100644
--- a/src/components/Search/SearchList/ListItem/TransactionGroupListExpanded.tsx
+++ b/src/components/Search/SearchList/ListItem/TransactionGroupListExpanded.tsx
@@ -63,6 +63,7 @@ function TransactionGroupListExpanded<TItem extends ListItem>({
     onLongPress,
     nonPersonalAndWorkspaceCards,
     onUndelete,
+    hideSearchTableHeader,
 }: TransactionGroupListExpandedProps<TItem>) {
     const theme = useTheme();
     const styles = useThemeStyles();
@@ -272,7 +273,7 @@ function TransactionGroupListExpanded<TItem extends ListItem>({
 
     const content = (
         <View style={[styles.flexColumn, styles.flex1]}>
-            {isLargeScreenWidth && !(isEmpty && shouldDisplayLoadingIndicator) && (
+            {isLargeScreenWidth && !hideSearchTableHeader && !(isEmpty && shouldDisplayLoadingIndicator) && (
                 <>
                     <View style={[styles.searchListHeaderContainerStyle, styles.groupSearchListTableContainerStyle, styles.bgTransparent, styles.pl8, styles.borderNone]}>
                         <SearchTableHeader
diff --git a/src/components/Search/SearchList/ListItem/types.ts b/src/components/Search/SearchList/ListItem/types.ts
index 308e47fa8dcc..b21ee664b8c9 100644
--- a/src/components/Search/SearchList/ListItem/types.ts
+++ b/src/components/Search/SearchList/ListItem/types.ts
@@ -448,6 +448,7 @@ type TransactionGroupListExpandedProps<TItem extends ListItem> = Pick<
     isInSingleTransactionReport: boolean;
     searchTransactions: (pageSize?: number) => void;
     onLongPress: (transaction: TransactionListItemType) => void;
+    hideSearchTableHeader?: boolean;
 };
 
 type GroupHeaderItemType = TransactionGroupListItemType & {

From ff25d79e3784cb37315c4a318871fb759de66f84 Mon Sep 17 00:00:00 2001
From: Jakub Korytko <jakub@korytko.me>
Date: Fri, 29 May 2026 15:35:58 +0200
Subject: [PATCH 045/435] address copilot review

---
 src/components/ConnectToHRFlow/index.ios.tsx    | 2 ++
 src/components/ConnectToHRFlow/index.native.tsx | 8 ++++++++
 src/libs/actions/Link.ts                        | 6 ++++--
 3 files changed, 14 insertions(+), 2 deletions(-)

diff --git a/src/components/ConnectToHRFlow/index.ios.tsx b/src/components/ConnectToHRFlow/index.ios.tsx
index 8fce75748ab2..04d0b7cc61c6 100644
--- a/src/components/ConnectToHRFlow/index.ios.tsx
+++ b/src/components/ConnectToHRFlow/index.ios.tsx
@@ -24,6 +24,8 @@ function ConnectToHRFlow({setupLink}: ConnectToHRFlowProps) {
         hasOpened.current = true;
 
         getShortLivedAuthTokenURL(setupLink)
+            // CONST.DEEPLINK_BASE_URL is used as a sentinel so ASWebAuthenticationSession
+            // auto-dismisses when the flow redirects back to the app via deep link.
             .then((url) => openAuthSessionAsync(url, CONST.DEEPLINK_BASE_URL, {preferEphemeralSession: true}))
             .finally(() => {
                 setIsModalOpen(false);
diff --git a/src/components/ConnectToHRFlow/index.native.tsx b/src/components/ConnectToHRFlow/index.native.tsx
index 505669a8059d..53fab3d83dee 100644
--- a/src/components/ConnectToHRFlow/index.native.tsx
+++ b/src/components/ConnectToHRFlow/index.native.tsx
@@ -42,6 +42,8 @@ function ConnectToHRFlow({setupLink}: ConnectToHRFlowProps) {
 
     const handleBackPress = () => {
         if (isPopupVisible) {
+            // Keep the popup WebView mounted (hidden) so in-flight OAuth redirects
+            // can complete and shared cookies remain intact for Merge Link.
             setIsPopupVisible(false);
             return;
         }
@@ -69,6 +71,9 @@ function ConnectToHRFlow({setupLink}: ConnectToHRFlowProps) {
                             source={{uri: 'about:blank'}}
                             incognito
                             onLoadEnd={() => {
+                                // Brief delay to ensure the incognito WebView has fully cleared cookies
+                                // before mounting the main WebView. No deterministic completion signal is
+                                // available from the incognito session teardown.
                                 setTimeout(() => setCookiesCleared(true), 500);
                             }}
                             style={styles.opacity0}
@@ -76,6 +81,8 @@ function ConnectToHRFlow({setupLink}: ConnectToHRFlowProps) {
                     )}
                     {!isReady && renderLoading()}
                     {isReady && (
+                        // Not using incognito here so the popup WebView can share cookies
+                        // with the main flow (required for OAuth handoffs).
                         <WebView
                             ref={webViewRef}
                             source={{uri: authenticatedUrl}}
@@ -91,6 +98,7 @@ function ConnectToHRFlow({setupLink}: ConnectToHRFlowProps) {
                         >
                             <WebView
                                 source={{uri: popupUrl}}
+                                onOpenWindow={handleOpenWindow}
                                 startInLoadingState
                                 renderLoading={renderLoading}
                             />
diff --git a/src/libs/actions/Link.ts b/src/libs/actions/Link.ts
index 578ee0d6ea29..9073a1e66154 100644
--- a/src/libs/actions/Link.ts
+++ b/src/libs/actions/Link.ts
@@ -415,8 +415,10 @@ function getShortLivedAuthTokenURL(setupLink: string): Promise<string> {
     // eslint-disable-next-line rulesdir/no-api-side-effects-method
     return API.makeRequestWithSideEffects(SIDE_EFFECT_REQUEST_COMMANDS.OPEN_OLD_DOT_LINK, {}, {})
         .then((response) => {
-            const tokenParam = response?.shortLivedAuthToken ? `&authToken=${response.shortLivedAuthToken}` : '';
-            return setupLink + tokenParam;
+            if (!response?.shortLivedAuthToken) {
+                return setupLink;
+            }
+            return Url.appendParam(setupLink, 'authToken', response.shortLivedAuthToken);
         })
         .catch(() => setupLink);
 }

From 5980a0aa061dd3614bf3ad4c9024238f33794e5c Mon Sep 17 00:00:00 2001
From: krishna2323 <belivethatkg@gmail.com>
Date: Fri, 29 May 2026 19:08:36 +0530
Subject: [PATCH 046/435] feat: Add sticky animated sub-header to GroupHeader
 with proper column widths and borders

Signed-off-by: krishna2323 <belivethatkg@gmail.com>
---
 .../Search/SearchList/ListItem/GroupChildrenContainer.tsx | 8 +++++---
 src/components/Search/SearchList/ListItem/GroupHeader.tsx | 4 ++++
 2 files changed, 9 insertions(+), 3 deletions(-)

diff --git a/src/components/Search/SearchList/ListItem/GroupChildrenContainer.tsx b/src/components/Search/SearchList/ListItem/GroupChildrenContainer.tsx
index 7df2d4842dea..78a53d75d8d4 100644
--- a/src/components/Search/SearchList/ListItem/GroupChildrenContainer.tsx
+++ b/src/components/Search/SearchList/ListItem/GroupChildrenContainer.tsx
@@ -242,9 +242,11 @@ function GroupChildrenContainer({
                             }
                         }}
                     >
-                        <View style={isLargeScreenWidth ? [styles.pv2, styles.ph3, styles.pb1, styles.pt1] : styles.ph3}>
-                            <View style={[styles.borderBottom, isLargeScreenWidth && styles.borderNone]} />
-                        </View>
+                        {!isLargeScreenWidth && (
+                            <View style={styles.ph3}>
+                                <View style={styles.borderBottom} />
+                            </View>
+                        )}
                         <TransactionGroupListExpandedItem
                             showTooltip
                             canSelectMultiple={canSelectMultiple}
diff --git a/src/components/Search/SearchList/ListItem/GroupHeader.tsx b/src/components/Search/SearchList/ListItem/GroupHeader.tsx
index ac2982451a03..371063ac20af 100644
--- a/src/components/Search/SearchList/ListItem/GroupHeader.tsx
+++ b/src/components/Search/SearchList/ListItem/GroupHeader.tsx
@@ -402,6 +402,9 @@ function GroupHeader({item, groupBy, searchType, columns, canSelectMultiple, isE
                                 }
                             }}
                         >
+                            <View style={[styles.pv2, styles.ph3, styles.pb1, styles.pt1]}>
+                                <View style={[styles.borderBottom, styles.borderNone]} />
+                            </View>
                             <View style={[styles.searchListHeaderContainerStyle, styles.groupSearchListTableContainerStyle, styles.bgTransparent, styles.pl8, styles.borderNone]}>
                                 <SearchTableHeader
                                     canSelectMultiple
@@ -419,6 +422,7 @@ function GroupHeader({item, groupBy, searchType, columns, canSelectMultiple, isE
                                     isActionColumnWide={isSubHeaderActionColumnWide}
                                 />
                             </View>
+                            <View style={[StyleUtils.getSelectedBorderBottomStyle(groupItem.transactions.at(0)?.isSelected), styles.ml3, styles.mr3]} />
                         </Animated.View>
                     )}
                 </Animated.View>

From eeee0d0b6c6a662ac18169d1c91e754b181ae693 Mon Sep 17 00:00:00 2001
From: Jakub Korytko <jakub@korytko.me>
Date: Fri, 29 May 2026 15:53:48 +0200
Subject: [PATCH 047/435] address copilot & codex comments

---
 src/CONST/index.ts                              |  1 +
 src/components/ConnectToHRFlow/index.ios.tsx    | 15 +++++++++++++--
 src/components/ConnectToHRFlow/index.native.tsx |  6 ++----
 3 files changed, 16 insertions(+), 6 deletions(-)

diff --git a/src/CONST/index.ts b/src/CONST/index.ts
index 7c4769c5c8a8..7cd6cfae2ee2 100644
--- a/src/CONST/index.ts
+++ b/src/CONST/index.ts
@@ -3003,6 +3003,7 @@ const CONST = {
             MANAGER: 'manager',
             CUSTOM: 'custom',
         },
+        COOKIE_CLEAR_DELAY_MS: 500,
         SYNC_STATUS: {
             SYNCING: 'SYNCING',
             DONE: 'DONE',
diff --git a/src/components/ConnectToHRFlow/index.ios.tsx b/src/components/ConnectToHRFlow/index.ios.tsx
index 04d0b7cc61c6..b0a53d922898 100644
--- a/src/components/ConnectToHRFlow/index.ios.tsx
+++ b/src/components/ConnectToHRFlow/index.ios.tsx
@@ -6,6 +6,7 @@ import FullPageOfflineBlockingView from '@components/BlockingViews/FullPageOffli
 import HeaderWithBackButton from '@components/HeaderWithBackButton';
 import Modal from '@components/Modal';
 import useLocalize from '@hooks/useLocalize';
+import useNetwork from '@hooks/useNetwork';
 import useThemeStyles from '@hooks/useThemeStyles';
 import {getShortLivedAuthTokenURL} from '@userActions/Link';
 import CONST from '@src/CONST';
@@ -17,7 +18,7 @@ function ConnectToHRFlow({setupLink}: ConnectToHRFlowProps) {
     const hasOpened = useRef(false);
     const [isModalOpen, setIsModalOpen] = useState(true);
 
-    useEffect(() => {
+    const openSession = () => {
         if (hasOpened.current) {
             return;
         }
@@ -30,7 +31,17 @@ function ConnectToHRFlow({setupLink}: ConnectToHRFlowProps) {
             .finally(() => {
                 setIsModalOpen(false);
             });
-    }, [setupLink]);
+    };
+
+    const {isOffline} = useNetwork({onReconnect: openSession});
+
+    useEffect(() => {
+        if (isOffline) {
+            return;
+        }
+        openSession();
+        // eslint-disable-next-line react-hooks/exhaustive-deps -- only the initial setupLink should be used; re-opening the auth session on prop change is not desired
+    }, []);
 
     return (
         <Modal
diff --git a/src/components/ConnectToHRFlow/index.native.tsx b/src/components/ConnectToHRFlow/index.native.tsx
index 53fab3d83dee..02efe66f1b46 100644
--- a/src/components/ConnectToHRFlow/index.native.tsx
+++ b/src/components/ConnectToHRFlow/index.native.tsx
@@ -1,4 +1,4 @@
-import React, {useEffect, useRef, useState} from 'react';
+import React, {useEffect, useState} from 'react';
 import {StyleSheet, View} from 'react-native';
 import {WebView} from 'react-native-webview';
 import type {WebViewOpenWindowEvent} from 'react-native-webview/lib/WebViewTypes';
@@ -15,7 +15,6 @@ import type ConnectToHRFlowProps from './types';
 function ConnectToHRFlow({setupLink}: ConnectToHRFlowProps) {
     const {translate} = useLocalize();
     const styles = useThemeStyles();
-    const webViewRef = useRef<WebView>(null);
     const [isWebViewOpen, setIsWebViewOpen] = useState(true);
     const [popupUrl, setPopupUrl] = useState<string | null>(null);
     const [isPopupVisible, setIsPopupVisible] = useState(false);
@@ -74,7 +73,7 @@ function ConnectToHRFlow({setupLink}: ConnectToHRFlowProps) {
                                 // Brief delay to ensure the incognito WebView has fully cleared cookies
                                 // before mounting the main WebView. No deterministic completion signal is
                                 // available from the incognito session teardown.
-                                setTimeout(() => setCookiesCleared(true), 500);
+                                setTimeout(() => setCookiesCleared(true), CONST.MERGE_HR.COOKIE_CLEAR_DELAY_MS);
                             }}
                             style={styles.opacity0}
                         />
@@ -84,7 +83,6 @@ function ConnectToHRFlow({setupLink}: ConnectToHRFlowProps) {
                         // Not using incognito here so the popup WebView can share cookies
                         // with the main flow (required for OAuth handoffs).
                         <WebView
-                            ref={webViewRef}
                             source={{uri: authenticatedUrl}}
                             onOpenWindow={handleOpenWindow}
                             startInLoadingState

From e3dbccc6745e6c7bbafccb0148f30c68013417ab Mon Sep 17 00:00:00 2001
From: Jakub Korytko <jakub@korytko.me>
Date: Fri, 29 May 2026 16:22:43 +0200
Subject: [PATCH 048/435] add log to catch

---
 src/libs/actions/Link.ts | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/src/libs/actions/Link.ts b/src/libs/actions/Link.ts
index 9073a1e66154..9ba860d7aa58 100644
--- a/src/libs/actions/Link.ts
+++ b/src/libs/actions/Link.ts
@@ -10,6 +10,7 @@ import asyncOpenURL from '@libs/asyncOpenURL';
 import * as Environment from '@libs/Environment/Environment';
 import getIsNarrowLayout from '@libs/getIsNarrowLayout';
 import isPublicScreenRoute from '@libs/isPublicScreenRoute';
+import Log from '@libs/Log';
 import {isOnboardingFlowName} from '@libs/Navigation/helpers/isNavigatorName';
 import normalizePath from '@libs/Navigation/helpers/normalizePath';
 import shouldOpenOnAdminRoom from '@libs/Navigation/helpers/shouldOpenOnAdminRoom';
@@ -420,7 +421,10 @@ function getShortLivedAuthTokenURL(setupLink: string): Promise<string> {
             }
             return Url.appendParam(setupLink, 'authToken', response.shortLivedAuthToken);
         })
-        .catch(() => setupLink);
+        .catch((error) => {
+            Log.warn('[Link] Failed to fetch short-lived auth token', {error});
+            return setupLink;
+        });
 }
 
 export {

From c284f34907f43e4de551ec0ed8829ad93de66c23 Mon Sep 17 00:00:00 2001
From: Jakub Korytko <jakub@korytko.me>
Date: Fri, 29 May 2026 16:34:27 +0200
Subject: [PATCH 049/435] correct android back button behavior

---
 src/components/ConnectToHRFlow/index.native.tsx | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/components/ConnectToHRFlow/index.native.tsx b/src/components/ConnectToHRFlow/index.native.tsx
index 02efe66f1b46..4e875fe827e4 100644
--- a/src/components/ConnectToHRFlow/index.native.tsx
+++ b/src/components/ConnectToHRFlow/index.native.tsx
@@ -53,7 +53,7 @@ function ConnectToHRFlow({setupLink}: ConnectToHRFlowProps) {
 
     return (
         <Modal
-            onClose={() => setIsWebViewOpen(false)}
+            onClose={handleBackPress}
             fullscreen
             isVisible={isWebViewOpen}
             type={CONST.MODAL.MODAL_TYPE.CENTERED_UNSWIPEABLE}

From 4cadd73b6151577ef67e770fd139e57a7cde15e3 Mon Sep 17 00:00:00 2001
From: Jakub Korytko <jakub@korytko.me>
Date: Fri, 29 May 2026 16:46:48 +0200
Subject: [PATCH 050/435] add android offline guard

---
 .../ConnectToHRFlow/index.native.tsx          | 20 +++++++++++++++++--
 1 file changed, 18 insertions(+), 2 deletions(-)

diff --git a/src/components/ConnectToHRFlow/index.native.tsx b/src/components/ConnectToHRFlow/index.native.tsx
index 4e875fe827e4..cd6c4040c233 100644
--- a/src/components/ConnectToHRFlow/index.native.tsx
+++ b/src/components/ConnectToHRFlow/index.native.tsx
@@ -1,4 +1,4 @@
-import React, {useEffect, useState} from 'react';
+import React, {useCallback, useEffect, useRef, useState} from 'react';
 import {StyleSheet, View} from 'react-native';
 import {WebView} from 'react-native-webview';
 import type {WebViewOpenWindowEvent} from 'react-native-webview/lib/WebViewTypes';
@@ -7,6 +7,7 @@ import FullPageOfflineBlockingView from '@components/BlockingViews/FullPageOffli
 import HeaderWithBackButton from '@components/HeaderWithBackButton';
 import Modal from '@components/Modal';
 import useLocalize from '@hooks/useLocalize';
+import useNetwork from '@hooks/useNetwork';
 import useThemeStyles from '@hooks/useThemeStyles';
 import {getShortLivedAuthTokenURL} from '@userActions/Link';
 import CONST from '@src/CONST';
@@ -20,11 +21,26 @@ function ConnectToHRFlow({setupLink}: ConnectToHRFlowProps) {
     const [isPopupVisible, setIsPopupVisible] = useState(false);
     const [authenticatedUrl, setAuthenticatedUrl] = useState<string | null>(null);
     const [cookiesCleared, setCookiesCleared] = useState(false);
+    const hasFetched = useRef(false);
 
-    useEffect(() => {
+    const fetchAuthUrl = useCallback(() => {
+        if (hasFetched.current) {
+            return;
+        }
+        hasFetched.current = true;
         getShortLivedAuthTokenURL(setupLink).then(setAuthenticatedUrl);
     }, [setupLink]);
 
+    const {isOffline} = useNetwork({onReconnect: fetchAuthUrl});
+
+    useEffect(() => {
+        if (isOffline) {
+            return;
+        }
+        fetchAuthUrl();
+        // eslint-disable-next-line react-hooks/exhaustive-deps -- only fetch once on mount when online
+    }, []);
+
     const renderLoading = () => (
         <View style={[StyleSheet.absoluteFill, styles.fullScreenLoading]}>
             <ActivityIndicator

From c43a4ea75d39109e6be33b0fd020c46bc75be693 Mon Sep 17 00:00:00 2001
From: Jakub Korytko <jakub@korytko.me>
Date: Fri, 29 May 2026 17:03:32 +0200
Subject: [PATCH 051/435] add isDismissed guard

---
 src/components/ConnectToHRFlow/index.ios.tsx | 17 ++++++++++++++---
 1 file changed, 14 insertions(+), 3 deletions(-)

diff --git a/src/components/ConnectToHRFlow/index.ios.tsx b/src/components/ConnectToHRFlow/index.ios.tsx
index b0a53d922898..b84d5ed1d74b 100644
--- a/src/components/ConnectToHRFlow/index.ios.tsx
+++ b/src/components/ConnectToHRFlow/index.ios.tsx
@@ -16,8 +16,14 @@ function ConnectToHRFlow({setupLink}: ConnectToHRFlowProps) {
     const {translate} = useLocalize();
     const styles = useThemeStyles();
     const hasOpened = useRef(false);
+    const isDismissed = useRef(false);
     const [isModalOpen, setIsModalOpen] = useState(true);
 
+    const dismiss = () => {
+        isDismissed.current = true;
+        setIsModalOpen(false);
+    };
+
     const openSession = () => {
         if (hasOpened.current) {
             return;
@@ -27,7 +33,12 @@ function ConnectToHRFlow({setupLink}: ConnectToHRFlowProps) {
         getShortLivedAuthTokenURL(setupLink)
             // CONST.DEEPLINK_BASE_URL is used as a sentinel so ASWebAuthenticationSession
             // auto-dismisses when the flow redirects back to the app via deep link.
-            .then((url) => openAuthSessionAsync(url, CONST.DEEPLINK_BASE_URL, {preferEphemeralSession: true}))
+            .then((url) => {
+                if (isDismissed.current) {
+                    return;
+                }
+                return openAuthSessionAsync(url, CONST.DEEPLINK_BASE_URL, {preferEphemeralSession: true});
+            })
             .finally(() => {
                 setIsModalOpen(false);
             });
@@ -45,14 +56,14 @@ function ConnectToHRFlow({setupLink}: ConnectToHRFlowProps) {
 
     return (
         <Modal
-            onClose={() => setIsModalOpen(false)}
+            onClose={dismiss}
             fullscreen
             isVisible={isModalOpen}
             type={CONST.MODAL.MODAL_TYPE.CENTERED_UNSWIPEABLE}
         >
             <HeaderWithBackButton
                 title={translate('workspace.common.hr')}
-                onBackButtonPress={() => setIsModalOpen(false)}
+                onBackButtonPress={dismiss}
                 shouldDisplayHelpButton={false}
             />
             <FullPageOfflineBlockingView>

From 7fa26847f682ff89b96609c0791ae435d36012e1 Mon Sep 17 00:00:00 2001
From: "Stephanie Elliott (via MelvinBot)" <infra+melvinbot@expensify.com>
Date: Fri, 29 May 2026 23:28:29 +0000
Subject: [PATCH 052/435] =?UTF-8?q?Docs:=20Close=20help-site=20content=20g?=
 =?UTF-8?q?aps=20for=20New=20Expensify=E2=80=93only=20features?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Co-authored-by: Stephanie Elliott <stephanieelliott@users.noreply.github.com>
---
 .../Assign-Company-Cards.md                   | 21 +++++++++++++++++++
 .../Getting-Started-with-the-Spend-Page.md    |  4 ++--
 .../How-to-Export-Expenses.md                 | 10 ++++-----
 ...-Search-Operators-to-Filter-and-Analyze.md |  3 ++-
 4 files changed, 30 insertions(+), 8 deletions(-)

diff --git a/docs/articles/new-expensify/connect-credit-cards/Assign-Company-Cards.md b/docs/articles/new-expensify/connect-credit-cards/Assign-Company-Cards.md
index 5ccfe82e069b..bf44f6532592 100644
--- a/docs/articles/new-expensify/connect-credit-cards/Assign-Company-Cards.md
+++ b/docs/articles/new-expensify/connect-credit-cards/Assign-Company-Cards.md
@@ -37,6 +37,23 @@ If you haven’t set up a feed yet, learn how to set one up:
  - Posted transactions from the assigned card import automatically into the member's account as expenses.
  - The imported company card expenses are added to reports and submitted according to Workspace rules.
 
+---
+
+## How to change the transaction start date on an assigned card
+
+The transaction start date controls how far back Expensify imports transactions for an assigned card. In New Expensify, Workspace Admins can change this date at any time after a card is assigned — without unassigning and reassigning the card.
+
+1. Click the navigation tabs (on the left on web, on the bottom on mobile) and select **Workspaces > [Workspace Name]**.
+2. Select **Company cards**.
+3. Select the assigned card you want to update.
+4. Update the **Transaction start date**.
+
+Already imported expenses on earlier or later dates are not affected by the change. Moving the start date earlier will import any additional transactions available from the feed back to the new date; moving it later will not delete expenses that are already imported.
+
+**Note:** This differs from Expensify Classic, where the transaction start date is locked when the card is assigned and can only be changed by deleting and reassigning the card.
+
+---
+
 # FAQ
 
 ## Can I assign a company card to someone who is not a member of the Workspace? 
@@ -50,3 +67,7 @@ Yes. A member can have multiple company cards assigned. Each card’s transactio
 ## Can members unassign their own company cards?
 
 No. Only Workspace Admins and their Copilots can assign or reassign company cards.
+
+## Do I need to unassign a card to change its transaction start date?
+
+No. In New Expensify, you can amend the transaction start date on an assigned card at any time from the card details page. Already imported expenses are not affected.
diff --git a/docs/articles/new-expensify/reports-and-expenses/Getting-Started-with-the-Spend-Page.md b/docs/articles/new-expensify/reports-and-expenses/Getting-Started-with-the-Spend-Page.md
index 819b9d95edf9..137c25f645cb 100644
--- a/docs/articles/new-expensify/reports-and-expenses/Getting-Started-with-the-Spend-Page.md
+++ b/docs/articles/new-expensify/reports-and-expenses/Getting-Started-with-the-Spend-Page.md
@@ -104,9 +104,9 @@ Filters help you narrow down expenses or reports so you can find exactly what yo
 
 You can filter your **expenses** and **reports** using dropdowns, search bars, and chips. 
 
-- **Expenses:** can be filtered by `Date`, `Merchant`, `Category`, `Tag`, `Amount`, `Reimbursable`, `Billable`, `Status` (e.g. Unreported, Deleted)
+- **Expenses:** can be filtered by `Date`, `Merchant`, `Category`, `Tag`, `Amount`, `Reimbursable`, `Billable`, `Status` (e.g. Unreported, Deleted), and `Exported to` (filter by where the expense was exported, such as an accounting integration or a specific export template).
 
-- **Reports**: can be filtered by `Submitter`, `Workspace`, `Report Status` (e.g. Draft, Outstanding, Approved, Paid), `Date`
+- **Reports**: can be filtered by `Submitter`, `Workspace`, `Report Status` (e.g. Draft, Outstanding, Approved, Paid), `Date`, and `Exported to` (see which reports were exported to a connected accounting integration or a specific export template — useful for confirming what's already been exported and what still needs to be).
 
 To view other available filters, click into the **search box** on the **Spend** page while viewing **Reports** or **Expenses** under **Explore**.
 
diff --git a/docs/articles/new-expensify/reports-and-expenses/How-to-Export-Expenses.md b/docs/articles/new-expensify/reports-and-expenses/How-to-Export-Expenses.md
index e17e44e77517..0e432a6338c3 100644
--- a/docs/articles/new-expensify/reports-and-expenses/How-to-Export-Expenses.md
+++ b/docs/articles/new-expensify/reports-and-expenses/How-to-Export-Expenses.md
@@ -38,15 +38,15 @@ You'll receive the exported CSV file in a message from Concierge.
 
 ## What export templates can I choose from? 
 
-Expensify offers pre-built export templates, or you can build your own custom export template. All available templates will appear in the menu when you export an expense. 
+Expensify offers pre-built export templates, or you can build your own custom export template. In New Expensify, **any available export template can be used at the expense level** — there is no restriction limiting certain template types to reports only.
 
    - **Basic export** - Essential fields including date, amount, merchant, category, and receipt URL.
    - **All Data - expense level** - One row per expense with all available data fields.
-   - **custom templates** - Any custom template created by you or your Workspace Admin, if available.
-
    - **Custom templates** - Any custom template created by you or your Workspace Admin, if available.
 
-**Note** Currently, it's not possible to build custom export templates on New Expensify, they can only be created on Expensify Classic. However, once built they will be available on New Expensify when exporting expenses. [Learn how to build a custom export template in Expensify Classic](/articles/expensify-classic/spending-insights/Export-Expenses-And-Reports#create-a-custom-export-template).  
+**Note:** This differs from Expensify Classic, where some template types are only available when exporting from a report. In New Expensify, every available template — including templates custom-built by Expensify — appears in the menu when you export an expense, which is useful for flat-file imports into another system such as your accounting software.
+
+**Note:** Currently, it's not possible to build custom export templates on New Expensify, they can only be created on Expensify Classic. However, once built they will be available on New Expensify when exporting expenses. [Learn how to build a custom export template in Expensify Classic](/articles/expensify-classic/spending-insights/Export-Expenses-And-Reports#create-a-custom-export-template).
 
 ## Where do I find the exported file?
 
@@ -58,7 +58,7 @@ If your Workspace Admin has created custom export templates, you can select one
 
 ## Why don't I see certain export templates?
 
-Report-level templates (such as All Data - Report Level Export) only appear when exporting from **Spend > Reports** page with full reports selected. When exporting individual expenses from the Expenses page, only expense-level templates are available.
+Report-level templates (such as All Data - Report Level Export) only appear when exporting from the **Spend > Reports** page with full reports selected, because those templates produce a row per report. All other template types — including custom export templates built in Expensify Classic — are available from both the **Reports** and **Expenses** views.
 
 If all selected expenses are deleted, only the **Basic export** template is available. Other export templates require a report, and deleted expenses are not associated with any report.
 
diff --git a/docs/articles/new-expensify/reports-and-expenses/Use-Search-Operators-to-Filter-and-Analyze.md b/docs/articles/new-expensify/reports-and-expenses/Use-Search-Operators-to-Filter-and-Analyze.md
index b6aafb12ab1c..c47b67937895 100644
--- a/docs/articles/new-expensify/reports-and-expenses/Use-Search-Operators-to-Filter-and-Analyze.md
+++ b/docs/articles/new-expensify/reports-and-expenses/Use-Search-Operators-to-Filter-and-Analyze.md
@@ -76,6 +76,7 @@ You can use the following operators to filter reports:
 - `report-id:` – unique report reference
 - `status:` – draft, outstanding, approved, paid, done
 - `submitted:` / `approved:` / `paid:` / `exported:` – supports absolute or relative dates, and comparisons for date ranges (e.g., `submitted>=2024-01-01 submitted<=2024-01-31`)
+- `exported-to:` – filter by where reports or expenses were exported, such as a connected accounting integration (e.g. `xero`, `quickbooks-online`, `netsuite`, `sage-intacct`, `quickbooks-desktop`) or an export template name. Combine values with commas to match any of them.
 - `title:` – report title
 - `total:` – total amount with relative comparisons
 - `withdrawn:` – ACH withdrawal date
@@ -83,7 +84,7 @@ You can use the following operators to filter reports:
 - `action:` – blocking report action, e.g. `action:approve`
 
 **Example query:**
-`status:paid exported<=2026-01-01`
+`status:paid exported<=2026-01-01 exported-to:xero`
 
 ---
 

From 84730da27fcb714059bec9b25a70028ca5491fc4 Mon Sep 17 00:00:00 2001
From: Stephanie Elliott <31225194+stephanieelliott@users.noreply.github.com>
Date: Fri, 29 May 2026 18:08:52 -1000
Subject: [PATCH 053/435] Update Assign-Company-Cards.md

---
 .../connect-credit-cards/Assign-Company-Cards.md          | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/docs/articles/new-expensify/connect-credit-cards/Assign-Company-Cards.md b/docs/articles/new-expensify/connect-credit-cards/Assign-Company-Cards.md
index bf44f6532592..fffdfe170f95 100644
--- a/docs/articles/new-expensify/connect-credit-cards/Assign-Company-Cards.md
+++ b/docs/articles/new-expensify/connect-credit-cards/Assign-Company-Cards.md
@@ -28,13 +28,15 @@ If you haven’t set up a feed yet, learn how to set one up:
 3. Select the card connection name. 
 4. Click **Assign card** on the card you want to assign. 
 5. Enter the assignee's name, email address, or phone number. 
-6. Review the details and click **Assign card** to finalize the assignment.
+7. If needed, update the **Transaction start date** to choose the date from which Expensify starts importing transactions for the card.
+8. Cick **Assign card** to finalize the assignment.
 
 ---
 
 ## What happens after you assign company cards
 
  - Posted transactions from the assigned card import automatically into the member's account as expenses.
+ - Expensify imports transactions from the Transaction start date onward.
  - The imported company card expenses are added to reports and submitted according to Workspace rules.
 
 ---
@@ -50,8 +52,6 @@ The transaction start date controls how far back Expensify imports transactions
 
 Already imported expenses on earlier or later dates are not affected by the change. Moving the start date earlier will import any additional transactions available from the feed back to the new date; moving it later will not delete expenses that are already imported.
 
-**Note:** This differs from Expensify Classic, where the transaction start date is locked when the card is assigned and can only be changed by deleting and reassigning the card.
-
 ---
 
 # FAQ
@@ -70,4 +70,4 @@ No. Only Workspace Admins and their Copilots can assign or reassign company card
 
 ## Do I need to unassign a card to change its transaction start date?
 
-No. In New Expensify, you can amend the transaction start date on an assigned card at any time from the card details page. Already imported expenses are not affected.
+No. You can update the Transaction start date at any time from the assigned card's details. The Transaction start date determines the date from which Expensify imports transactions for the card.

From 03d33de2f1dbec42d8d1b2c62a5b15773fad1063 Mon Sep 17 00:00:00 2001
From: Stephanie Elliott <31225194+stephanieelliott@users.noreply.github.com>
Date: Fri, 29 May 2026 18:10:06 -1000
Subject: [PATCH 054/435] Update Getting-Started-with-the-Spend-Page.md

---
 .../Getting-Started-with-the-Spend-Page.md                    | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/docs/articles/new-expensify/reports-and-expenses/Getting-Started-with-the-Spend-Page.md b/docs/articles/new-expensify/reports-and-expenses/Getting-Started-with-the-Spend-Page.md
index 137c25f645cb..dd39d268f9c1 100644
--- a/docs/articles/new-expensify/reports-and-expenses/Getting-Started-with-the-Spend-Page.md
+++ b/docs/articles/new-expensify/reports-and-expenses/Getting-Started-with-the-Spend-Page.md
@@ -104,9 +104,9 @@ Filters help you narrow down expenses or reports so you can find exactly what yo
 
 You can filter your **expenses** and **reports** using dropdowns, search bars, and chips. 
 
-- **Expenses:** can be filtered by `Date`, `Merchant`, `Category`, `Tag`, `Amount`, `Reimbursable`, `Billable`, `Status` (e.g. Unreported, Deleted), and `Exported to` (filter by where the expense was exported, such as an accounting integration or a specific export template).
+- **Expenses:** can be filtered by `Date`, `Merchant`, `Category`, `Tag`, `Amount`, `Reimbursable`, `Billable`, `Status` (e.g. Unreported, Deleted), and `Exported to`.
 
-- **Reports**: can be filtered by `Submitter`, `Workspace`, `Report Status` (e.g. Draft, Outstanding, Approved, Paid), `Date`, and `Exported to` (see which reports were exported to a connected accounting integration or a specific export template — useful for confirming what's already been exported and what still needs to be).
+- **Reports**: can be filtered by `Submitter`, `Workspace`, `Report Status` (e.g. Draft, Outstanding, Approved, Paid), `Date`, and `Exported to`.
 
 To view other available filters, click into the **search box** on the **Spend** page while viewing **Reports** or **Expenses** under **Explore**.
 

From ecb52b8ab2f3dbb8b47a98e246c070b1e78df3aa Mon Sep 17 00:00:00 2001
From: Stephanie Elliott <31225194+stephanieelliott@users.noreply.github.com>
Date: Fri, 29 May 2026 18:11:19 -1000
Subject: [PATCH 055/435] Update Use-Search-Operators-to-Filter-and-Analyze.md

---
 .../Use-Search-Operators-to-Filter-and-Analyze.md               | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/docs/articles/new-expensify/reports-and-expenses/Use-Search-Operators-to-Filter-and-Analyze.md b/docs/articles/new-expensify/reports-and-expenses/Use-Search-Operators-to-Filter-and-Analyze.md
index c47b67937895..4f221397ad91 100644
--- a/docs/articles/new-expensify/reports-and-expenses/Use-Search-Operators-to-Filter-and-Analyze.md
+++ b/docs/articles/new-expensify/reports-and-expenses/Use-Search-Operators-to-Filter-and-Analyze.md
@@ -76,7 +76,7 @@ You can use the following operators to filter reports:
 - `report-id:` – unique report reference
 - `status:` – draft, outstanding, approved, paid, done
 - `submitted:` / `approved:` / `paid:` / `exported:` – supports absolute or relative dates, and comparisons for date ranges (e.g., `submitted>=2024-01-01 submitted<=2024-01-31`)
-- `exported-to:` – filter by where reports or expenses were exported, such as a connected accounting integration (e.g. `xero`, `quickbooks-online`, `netsuite`, `sage-intacct`, `quickbooks-desktop`) or an export template name. Combine values with commas to match any of them.
+- `exported-to:` – filter by where reports or expenses were exported, such as a connected accounting integration.
 - `title:` – report title
 - `total:` – total amount with relative comparisons
 - `withdrawn:` – ACH withdrawal date

From f257d0603c484de1eae8cc52f2401327448f04b8 Mon Sep 17 00:00:00 2001
From: "Stephanie Elliott (via MelvinBot)" <infra+melvinbot@expensify.com>
Date: Sat, 30 May 2026 04:13:15 +0000
Subject: [PATCH 056/435] Fix: typo Cick -> Click in Assign-Company-Cards.md

Co-authored-by: Stephanie Elliott <stephanieelliott@users.noreply.github.com>
---
 .../new-expensify/connect-credit-cards/Assign-Company-Cards.md  | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/docs/articles/new-expensify/connect-credit-cards/Assign-Company-Cards.md b/docs/articles/new-expensify/connect-credit-cards/Assign-Company-Cards.md
index fffdfe170f95..c238a2d44a05 100644
--- a/docs/articles/new-expensify/connect-credit-cards/Assign-Company-Cards.md
+++ b/docs/articles/new-expensify/connect-credit-cards/Assign-Company-Cards.md
@@ -29,7 +29,7 @@ If you haven’t set up a feed yet, learn how to set one up:
 4. Click **Assign card** on the card you want to assign. 
 5. Enter the assignee's name, email address, or phone number. 
 7. If needed, update the **Transaction start date** to choose the date from which Expensify starts importing transactions for the card.
-8. Cick **Assign card** to finalize the assignment.
+8. Click **Assign card** to finalize the assignment.
 
 ---
 

From eb9c5a980a88c252184b2b139a6fe490d065c684 Mon Sep 17 00:00:00 2001
From: Stephanie Elliott <31225194+stephanieelliott@users.noreply.github.com>
Date: Fri, 29 May 2026 18:14:04 -1000
Subject: [PATCH 057/435] Update export templates information in documentation

Removed details about template restrictions in New Expensify and clarified custom template availability.
---
 .../reports-and-expenses/How-to-Export-Expenses.md          | 6 +-----
 1 file changed, 1 insertion(+), 5 deletions(-)

diff --git a/docs/articles/new-expensify/reports-and-expenses/How-to-Export-Expenses.md b/docs/articles/new-expensify/reports-and-expenses/How-to-Export-Expenses.md
index 0e432a6338c3..268ff7f1dbf8 100644
--- a/docs/articles/new-expensify/reports-and-expenses/How-to-Export-Expenses.md
+++ b/docs/articles/new-expensify/reports-and-expenses/How-to-Export-Expenses.md
@@ -38,14 +38,12 @@ You'll receive the exported CSV file in a message from Concierge.
 
 ## What export templates can I choose from? 
 
-Expensify offers pre-built export templates, or you can build your own custom export template. In New Expensify, **any available export template can be used at the expense level** — there is no restriction limiting certain template types to reports only.
+Expensify offers pre-built export templates, or you can build your own custom export template. 
 
    - **Basic export** - Essential fields including date, amount, merchant, category, and receipt URL.
    - **All Data - expense level** - One row per expense with all available data fields.
    - **Custom templates** - Any custom template created by you or your Workspace Admin, if available.
 
-**Note:** This differs from Expensify Classic, where some template types are only available when exporting from a report. In New Expensify, every available template — including templates custom-built by Expensify — appears in the menu when you export an expense, which is useful for flat-file imports into another system such as your accounting software.
-
 **Note:** Currently, it's not possible to build custom export templates on New Expensify, they can only be created on Expensify Classic. However, once built they will be available on New Expensify when exporting expenses. [Learn how to build a custom export template in Expensify Classic](/articles/expensify-classic/spending-insights/Export-Expenses-And-Reports#create-a-custom-export-template).
 
 ## Where do I find the exported file?
@@ -58,8 +56,6 @@ If your Workspace Admin has created custom export templates, you can select one
 
 ## Why don't I see certain export templates?
 
-Report-level templates (such as All Data - Report Level Export) only appear when exporting from the **Spend > Reports** page with full reports selected, because those templates produce a row per report. All other template types — including custom export templates built in Expensify Classic — are available from both the **Reports** and **Expenses** views.
-
 If all selected expenses are deleted, only the **Basic export** template is available. Other export templates require a report, and deleted expenses are not associated with any report.
 
 ## The data looks wrong in Excel. How can I fix it?

From ed8137590e8f66870f2a049263c3372bc4633fdc Mon Sep 17 00:00:00 2001
From: Stephanie Elliott <31225194+stephanieelliott@users.noreply.github.com>
Date: Fri, 29 May 2026 18:15:47 -1000
Subject: [PATCH 058/435] Update Assign-Company-Cards.md

---
 .../Assign-Company-Cards.md                     | 17 ++---------------
 1 file changed, 2 insertions(+), 15 deletions(-)

diff --git a/docs/articles/new-expensify/connect-credit-cards/Assign-Company-Cards.md b/docs/articles/new-expensify/connect-credit-cards/Assign-Company-Cards.md
index c238a2d44a05..95803e1f2bda 100644
--- a/docs/articles/new-expensify/connect-credit-cards/Assign-Company-Cards.md
+++ b/docs/articles/new-expensify/connect-credit-cards/Assign-Company-Cards.md
@@ -41,19 +41,6 @@ If you haven’t set up a feed yet, learn how to set one up:
 
 ---
 
-## How to change the transaction start date on an assigned card
-
-The transaction start date controls how far back Expensify imports transactions for an assigned card. In New Expensify, Workspace Admins can change this date at any time after a card is assigned — without unassigning and reassigning the card.
-
-1. Click the navigation tabs (on the left on web, on the bottom on mobile) and select **Workspaces > [Workspace Name]**.
-2. Select **Company cards**.
-3. Select the assigned card you want to update.
-4. Update the **Transaction start date**.
-
-Already imported expenses on earlier or later dates are not affected by the change. Moving the start date earlier will import any additional transactions available from the feed back to the new date; moving it later will not delete expenses that are already imported.
-
----
-
 # FAQ
 
 ## Can I assign a company card to someone who is not a member of the Workspace? 
@@ -68,6 +55,6 @@ Yes. A member can have multiple company cards assigned. Each card’s transactio
 
 No. Only Workspace Admins and their Copilots can assign or reassign company cards.
 
-## Do I need to unassign a card to change its transaction start date?
+## Can I change the transaction start date on an assigned card?
 
-No. You can update the Transaction start date at any time from the assigned card's details. The Transaction start date determines the date from which Expensify imports transactions for the card.
+Yes. You can update the Transaction start date at any time from the assigned card's details. The Transaction start date determines the date from which Expensify imports transactions for the card.

From 1a393fadc736529a62fabf178a8056871a5c07d2 Mon Sep 17 00:00:00 2001
From: krishna2323 <belivethatkg@gmail.com>
Date: Sat, 30 May 2026 19:53:44 +0530
Subject: [PATCH 059/435] fix: Correct border radius for last group item in
 split header/children layout

Signed-off-by: krishna2323 <belivethatkg@gmail.com>
---
 .../SearchList/ListItem/GroupChildrenContainer.tsx     |  4 +++-
 .../Search/SearchList/ListItem/GroupHeader.tsx         | 10 ++++++----
 src/components/Search/SearchList/index.tsx             |  7 ++++---
 3 files changed, 13 insertions(+), 8 deletions(-)

diff --git a/src/components/Search/SearchList/ListItem/GroupChildrenContainer.tsx b/src/components/Search/SearchList/ListItem/GroupChildrenContainer.tsx
index 78a53d75d8d4..5caf3de02a7f 100644
--- a/src/components/Search/SearchList/ListItem/GroupChildrenContainer.tsx
+++ b/src/components/Search/SearchList/ListItem/GroupChildrenContainer.tsx
@@ -39,6 +39,7 @@ type GroupChildrenContainerProps = {
     onLongPressRow?: (item: SearchListItem, itemTransactions?: TransactionListItemType[]) => void;
     nonPersonalAndWorkspaceCards?: CardList;
     onUndelete?: (transaction: Transaction) => void;
+    isLastItem?: boolean;
 };
 
 function GroupChildrenContainer({
@@ -53,6 +54,7 @@ function GroupChildrenContainer({
     onLongPressRow,
     nonPersonalAndWorkspaceCards,
     onUndelete,
+    isLastItem,
 }: GroupChildrenContainerProps) {
     const theme = useTheme();
     const styles = useThemeStyles();
@@ -230,7 +232,7 @@ function GroupChildrenContainer({
     }));
 
     return (
-        <View style={[styles.mh5, {backgroundColor: theme.highlightBG}]}>
+        <View style={[styles.mh5, {backgroundColor: theme.highlightBG}, isLastItem && [styles.tableBottomRadius, styles.overflowHidden]]}>
             <Animated.View style={contentAnimatedStyle}>
                 {isExpanded || isRendered ? (
                     <Animated.View
diff --git a/src/components/Search/SearchList/ListItem/GroupHeader.tsx b/src/components/Search/SearchList/ListItem/GroupHeader.tsx
index 371063ac20af..e5b4e79e0fb9 100644
--- a/src/components/Search/SearchList/ListItem/GroupHeader.tsx
+++ b/src/components/Search/SearchList/ListItem/GroupHeader.tsx
@@ -324,12 +324,14 @@ function GroupHeader({item, groupBy, searchType, columns, canSelectMultiple, isE
         return headers[groupBy];
     };
 
+    const isLastItemCollapsed = isLastItem && !isExpanded;
+
     const pressableStyle = [
         styles.transactionGroupListItemStyle,
         isLargeScreenWidth && {
             ...styles.tableRowHeight,
             borderRadius: 0,
-            ...(isLastItem ? styles.tableBottomRadius : {}),
+            ...(isLastItemCollapsed ? styles.tableBottomRadius : {}),
         },
         isItemSelected && styles.activeComponentBG,
     ];
@@ -356,11 +358,11 @@ function GroupHeader({item, groupBy, searchType, columns, canSelectMultiple, isE
                     animatedHighlightStyle,
                     styles.userSelectNone,
                     isLargeScreenWidth
-                        ? [StyleUtils.getSearchTableGroupRowBorderStyle(isFirstItem, isLastItem, isItemSelected), isLastItem && styles.overflowHidden]
+                        ? [StyleUtils.getSearchTableGroupRowBorderStyle(isFirstItem, isLastItemCollapsed, isItemSelected), isLastItemCollapsed && styles.overflowHidden]
                         : [
                               isFirstItem && [styles.tableTopRadius, styles.overflowHidden],
-                              isLastItem && [styles.tableBottomRadius, styles.overflowHidden],
-                              !isLastItem && StyleUtils.getSelectedBorderBottomStyle(isItemSelected),
+                              isLastItemCollapsed && [styles.tableBottomRadius, styles.overflowHidden],
+                              !isLastItemCollapsed && StyleUtils.getSelectedBorderBottomStyle(isItemSelected),
                           ],
                 ]}
             >
diff --git a/src/components/Search/SearchList/index.tsx b/src/components/Search/SearchList/index.tsx
index 4ce7f188cec2..b70c9e38abc9 100644
--- a/src/components/Search/SearchList/index.tsx
+++ b/src/components/Search/SearchList/index.tsx
@@ -463,8 +463,8 @@ function SearchList({
     useImperativeHandle(ref, () => ({scrollToIndex}), [scrollToIndex]);
 
     const isItemVisible = useCallback((item: SearchListItem) => item.pendingAction !== CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE || isOffline, [isOffline]);
-    const firstVisibleIndex = useMemo(() => data.findIndex(isItemVisible), [data, isItemVisible]);
-    const lastVisibleIndex = useMemo(() => data.findLastIndex(isItemVisible), [data, isItemVisible]);
+    const firstVisibleIndex = useMemo(() => listData.findIndex(isItemVisible), [listData, isItemVisible]);
+    const lastVisibleIndex = useMemo(() => listData.findLastIndex(isItemVisible), [listData, isItemVisible]);
 
     const renderItem = useCallback(
         (item: SearchListItem, index: number, isItemFocused: boolean, onFocus?: (event: NativeSyntheticEvent<ExtendedTargetedEvent>) => void) => {
@@ -485,7 +485,7 @@ function SearchList({
                         onCheckboxPress={(val) => onCheckboxPress(val as SearchListItem)}
                         isFocused={isItemFocused}
                         isFirstItem={index === firstVisibleIndex}
-                        isLastItem={index === lastVisibleIndex && !ListFooterComponent}
+                        isLastItem={index + 1 >= lastVisibleIndex && !ListFooterComponent}
                     />
                 );
             }
@@ -507,6 +507,7 @@ function SearchList({
                         onLongPressRow={isMobileSelectionModeEnabled ? handleLongPressRowInMobileSelectionMode : handleLongPressRow}
                         nonPersonalAndWorkspaceCards={nonPersonalAndWorkspaceCards}
                         onUndelete={handleUndelete}
+                        isLastItem={index === lastVisibleIndex && !ListFooterComponent}
                     />
                 );
             }

From 34adab1f2739fc07a1bb8c750cd9d507437042e1 Mon Sep 17 00:00:00 2001
From: krishna2323 <belivethatkg@gmail.com>
Date: Sat, 30 May 2026 20:01:18 +0530
Subject: [PATCH 060/435] fix: Border radius, clickable sub-header, and
 deferred radius until animation completes

Signed-off-by: krishna2323 <belivethatkg@gmail.com>
---
 .../Search/SearchList/ListItem/GroupHeader.tsx        | 11 +++++++----
 1 file changed, 7 insertions(+), 4 deletions(-)

diff --git a/src/components/Search/SearchList/ListItem/GroupHeader.tsx b/src/components/Search/SearchList/ListItem/GroupHeader.tsx
index e5b4e79e0fb9..6a087089b5ca 100644
--- a/src/components/Search/SearchList/ListItem/GroupHeader.tsx
+++ b/src/components/Search/SearchList/ListItem/GroupHeader.tsx
@@ -324,7 +324,7 @@ function GroupHeader({item, groupBy, searchType, columns, canSelectMultiple, isE
         return headers[groupBy];
     };
 
-    const isLastItemCollapsed = isLastItem && !isExpanded;
+    const isLastItemCollapsed = isLastItem && !isExpanded && !isSubHeaderRendered;
 
     const pressableStyle = [
         styles.transactionGroupListItemStyle,
@@ -395,14 +395,17 @@ function GroupHeader({item, groupBy, searchType, columns, canSelectMultiple, isE
             {isLargeScreenWidth && (
                 <Animated.View style={[subHeaderAnimatedStyle, styles.mh5, {backgroundColor: theme.highlightBG}]}>
                     {(isExpanded || isSubHeaderRendered) && (
-                        <Animated.View
-                            style={styles.stickToTop}
+                        <PressableWithFeedback
+                            onPress={onToggle}
+                            style={[styles.stickToTop, styles.cursorPointer]}
                             onLayout={(e) => {
                                 const height = e.nativeEvent.layout.height;
                                 if (height) {
                                     subHeaderHeight.set(height);
                                 }
                             }}
+                            accessibilityRole={CONST.ROLE.BUTTON}
+                            accessibilityLabel={isExpanded ? CONST.ACCESSIBILITY_LABELS.COLLAPSE : CONST.ACCESSIBILITY_LABELS.EXPAND}
                         >
                             <View style={[styles.pv2, styles.ph3, styles.pb1, styles.pt1]}>
                                 <View style={[styles.borderBottom, styles.borderNone]} />
@@ -425,7 +428,7 @@ function GroupHeader({item, groupBy, searchType, columns, canSelectMultiple, isE
                                 />
                             </View>
                             <View style={[StyleUtils.getSelectedBorderBottomStyle(groupItem.transactions.at(0)?.isSelected), styles.ml3, styles.mr3]} />
-                        </Animated.View>
+                        </PressableWithFeedback>
                     )}
                 </Animated.View>
             )}

From 05c4306db84bf27ac90c952a2942cea383c67497 Mon Sep 17 00:00:00 2001
From: krishna2323 <belivethatkg@gmail.com>
Date: Sat, 30 May 2026 20:02:13 +0530
Subject: [PATCH 061/435] add sentryLabel

Signed-off-by: krishna2323 <belivethatkg@gmail.com>
---
 src/components/Search/SearchList/ListItem/GroupHeader.tsx | 1 +
 1 file changed, 1 insertion(+)

diff --git a/src/components/Search/SearchList/ListItem/GroupHeader.tsx b/src/components/Search/SearchList/ListItem/GroupHeader.tsx
index 6a087089b5ca..03747faed655 100644
--- a/src/components/Search/SearchList/ListItem/GroupHeader.tsx
+++ b/src/components/Search/SearchList/ListItem/GroupHeader.tsx
@@ -406,6 +406,7 @@ function GroupHeader({item, groupBy, searchType, columns, canSelectMultiple, isE
                             }}
                             accessibilityRole={CONST.ROLE.BUTTON}
                             accessibilityLabel={isExpanded ? CONST.ACCESSIBILITY_LABELS.COLLAPSE : CONST.ACCESSIBILITY_LABELS.EXPAND}
+                            sentryLabel={CONST.SENTRY_LABEL.SEARCH.GROUP_EXPAND_TOGGLE}
                         >
                             <View style={[styles.pv2, styles.ph3, styles.pb1, styles.pt1]}>
                                 <View style={[styles.borderBottom, styles.borderNone]} />

From 97c9a104ad6d8acf5037f7453db164f867856cd1 Mon Sep 17 00:00:00 2001
From: krishna2323 <belivethatkg@gmail.com>
Date: Sat, 30 May 2026 20:15:44 +0530
Subject: [PATCH 062/435] fix: Sub-header selection bg, clickable toggle,
 sentry label, and border clipping

Signed-off-by: krishna2323 <belivethatkg@gmail.com>
---
 .../Search/SearchList/ListItem/GroupHeader.tsx        | 11 +++++++++--
 1 file changed, 9 insertions(+), 2 deletions(-)

diff --git a/src/components/Search/SearchList/ListItem/GroupHeader.tsx b/src/components/Search/SearchList/ListItem/GroupHeader.tsx
index 03747faed655..ea81827bb5b4 100644
--- a/src/components/Search/SearchList/ListItem/GroupHeader.tsx
+++ b/src/components/Search/SearchList/ListItem/GroupHeader.tsx
@@ -393,7 +393,7 @@ function GroupHeader({item, groupBy, searchType, columns, canSelectMultiple, isE
                 )}
             </PressableWithFeedback>
             {isLargeScreenWidth && (
-                <Animated.View style={[subHeaderAnimatedStyle, styles.mh5, {backgroundColor: theme.highlightBG}]}>
+                <Animated.View style={[subHeaderAnimatedStyle, styles.mh5, {backgroundColor: isItemSelected ? theme.activeComponentBG : theme.highlightBG}]}>
                     {(isExpanded || isSubHeaderRendered) && (
                         <PressableWithFeedback
                             onPress={onToggle}
@@ -428,7 +428,14 @@ function GroupHeader({item, groupBy, searchType, columns, canSelectMultiple, isE
                                     isActionColumnWide={isSubHeaderActionColumnWide}
                                 />
                             </View>
-                            <View style={[StyleUtils.getSelectedBorderBottomStyle(groupItem.transactions.at(0)?.isSelected), styles.ml3, styles.mr3]} />
+                            <View
+                                style={[
+                                    StyleUtils.getSelectedBorderBottomStyle(isItemSelected),
+                                    styles.ml3,
+                                    styles.mr3,
+                                    {marginBottom: 1},
+                                ]}
+                            />
                         </PressableWithFeedback>
                     )}
                 </Animated.View>

From c2a32ec61dbfdbe2b8f84d0508092bc62711ad3f Mon Sep 17 00:00:00 2001
From: krishna2323 <belivethatkg@gmail.com>
Date: Sat, 30 May 2026 20:19:32 +0530
Subject: [PATCH 063/435] fix: Disable hover effect on group header when
 expanded

Signed-off-by: krishna2323 <belivethatkg@gmail.com>
---
 .../Search/SearchList/ListItem/GroupHeader.tsx        | 11 ++---------
 1 file changed, 2 insertions(+), 9 deletions(-)

diff --git a/src/components/Search/SearchList/ListItem/GroupHeader.tsx b/src/components/Search/SearchList/ListItem/GroupHeader.tsx
index ea81827bb5b4..b72fdbda99af 100644
--- a/src/components/Search/SearchList/ListItem/GroupHeader.tsx
+++ b/src/components/Search/SearchList/ListItem/GroupHeader.tsx
@@ -345,7 +345,7 @@ function GroupHeader({item, groupBy, searchType, columns, canSelectMultiple, isE
                 accessibilityLabel={item.text ?? ''}
                 role={getButtonRole(true)}
                 isNested
-                hoverStyle={[!item.isDisabled && styles.hoveredComponentBG, isItemSelected && styles.activeComponentBG]}
+                hoverStyle={[!isExpanded && !item.isDisabled && styles.hoveredComponentBG, isItemSelected && styles.activeComponentBG]}
                 dataSet={{[CONST.SELECTION_SCRAPER_HIDDEN_ELEMENT]: true, [CONST.INNER_BOX_SHADOW_ELEMENT]: false}}
                 onMouseDown={(e) => e.preventDefault()}
                 id={item.keyForList ?? ''}
@@ -428,14 +428,7 @@ function GroupHeader({item, groupBy, searchType, columns, canSelectMultiple, isE
                                     isActionColumnWide={isSubHeaderActionColumnWide}
                                 />
                             </View>
-                            <View
-                                style={[
-                                    StyleUtils.getSelectedBorderBottomStyle(isItemSelected),
-                                    styles.ml3,
-                                    styles.mr3,
-                                    {marginBottom: 1},
-                                ]}
-                            />
+                            <View style={[StyleUtils.getSelectedBorderBottomStyle(isItemSelected), styles.ml3, styles.mr3, {marginBottom: 1}]} />
                         </PressableWithFeedback>
                     )}
                 </Animated.View>

From 87cbc9b9ef042ae9d7feb306c4cead67ca7eb64c Mon Sep 17 00:00:00 2001
From: krishna2323 <belivethatkg@gmail.com>
Date: Sat, 30 May 2026 20:31:10 +0530
Subject: [PATCH 064/435] fix: Preserve report row navigation and pass payment
 context to GroupHeader

Signed-off-by: krishna2323 <belivethatkg@gmail.com>
---
 .../SearchList/ListItem/GroupHeader.tsx       | 62 +++++++++++++++++--
 src/components/Search/SearchList/index.tsx    |  6 +-
 2 files changed, 62 insertions(+), 6 deletions(-)

diff --git a/src/components/Search/SearchList/ListItem/GroupHeader.tsx b/src/components/Search/SearchList/ListItem/GroupHeader.tsx
index b72fdbda99af..2455d9e0b3c8 100644
--- a/src/components/Search/SearchList/ListItem/GroupHeader.tsx
+++ b/src/components/Search/SearchList/ListItem/GroupHeader.tsx
@@ -1,5 +1,8 @@
 import React, {useState} from 'react';
 import {View} from 'react-native';
+import type {OnyxEntry} from 'react-native-onyx';
+// eslint-disable-next-line no-restricted-imports
+import {useOnyx as originalUseOnyx} from 'react-native-onyx';
 import Animated, {useAnimatedStyle, useDerivedValue, useSharedValue, withTiming} from 'react-native-reanimated';
 import {scheduleOnRN} from 'react-native-worklets';
 import {getButtonRole} from '@components/Button/utils';
@@ -18,12 +21,15 @@ import useResponsiveLayout from '@hooks/useResponsiveLayout';
 import useStyleUtils from '@hooks/useStyleUtils';
 import useTheme from '@hooks/useTheme';
 import useThemeStyles from '@hooks/useThemeStyles';
+import type {TransactionPreviewData} from '@libs/actions/Search';
+import getNonEmptyStringOnyxID from '@libs/getNonEmptyStringOnyxID';
 import type {ModifiedMouseEvent} from '@libs/Navigation/helpers/openInternalRouteInNewTab';
 import {getColumnsToShow} from '@libs/SearchUIUtils';
 import {isDeletedTransaction} from '@libs/TransactionUtils';
 import CONST from '@src/CONST';
 import ONYXKEYS from '@src/ONYXKEYS';
 import {columnsSelector} from '@src/selectors/AdvancedSearchFiltersForm';
+import type {ReportAction, ReportActions} from '@src/types/onyx';
 import type {SearchDataTypes} from '@src/types/onyx/SearchResults';
 import CardListItemHeader from './CardListItemHeader';
 import CategoryListItemHeader from './CategoryListItemHeader';
@@ -35,6 +41,7 @@ import ReportListItemHeader from './ReportListItemHeader';
 import TagListItemHeader from './TagListItemHeader';
 import type {
     GroupHeaderItemType,
+    SearchListActionProps,
     SearchListItem,
     TransactionCardGroupListItemType,
     TransactionCategoryGroupListItemType,
@@ -53,7 +60,7 @@ import WeekListItemHeader from './WeekListItemHeader';
 import WithdrawalIDListItemHeader from './WithdrawalIDListItemHeader';
 import YearListItemHeader from './YearListItemHeader';
 
-type GroupHeaderProps = {
+type GroupHeaderProps = SearchListActionProps & {
     item: GroupHeaderItemType;
     groupBy?: SearchGroupBy;
     searchType?: SearchDataTypes;
@@ -61,14 +68,31 @@ type GroupHeaderProps = {
     canSelectMultiple: boolean;
     isExpanded: boolean;
     onToggle: () => void;
-    onSelectRow: (item: SearchListItem, event?: ModifiedMouseEvent) => void;
+    onSelectRow: (item: SearchListItem, transactionPreviewData?: TransactionPreviewData, event?: ModifiedMouseEvent) => void;
     onCheckboxPress: (item: GroupHeaderItemType) => void;
     isFocused?: boolean;
     isFirstItem: boolean;
     isLastItem: boolean;
 };
 
-function GroupHeader({item, groupBy, searchType, columns, canSelectMultiple, isExpanded, onToggle, onSelectRow, onCheckboxPress, isFocused, isFirstItem, isLastItem}: GroupHeaderProps) {
+function GroupHeader({
+    item,
+    groupBy,
+    searchType,
+    columns,
+    canSelectMultiple,
+    isExpanded,
+    onToggle,
+    onSelectRow,
+    onCheckboxPress,
+    isFocused,
+    isFirstItem,
+    isLastItem,
+    lastPaymentMethod,
+    personalPolicyID,
+    userBillingGracePeriodEnds,
+    ownerBillingGracePeriodEnd,
+}: GroupHeaderProps) {
     const theme = useTheme();
     const styles = useThemeStyles();
     const StyleUtils = useStyleUtils();
@@ -80,6 +104,21 @@ function GroupHeader({item, groupBy, searchType, columns, canSelectMultiple, isE
     const groupItem = item as unknown as TransactionGroupListItemType;
     const isExpenseReportType = searchType === CONST.SEARCH.DATA_TYPES.EXPENSE_REPORT;
 
+    const oneTransactionItem = groupItem.isOneTransactionReport ? groupItem.transactions.at(0) : undefined;
+    const [parentReport] = originalUseOnyx(`${ONYXKEYS.COLLECTION.REPORT}${getNonEmptyStringOnyxID(oneTransactionItem?.reportID)}`);
+    const [oneTransactionThreadReport] = originalUseOnyx(`${ONYXKEYS.COLLECTION.REPORT}${oneTransactionItem?.reportAction?.childReportID}`);
+    const [oneTransaction] = originalUseOnyx(`${ONYXKEYS.COLLECTION.TRANSACTION}${getNonEmptyStringOnyxID(oneTransactionItem?.transactionID)}`);
+    const parentReportActionSelector = (reportActions: OnyxEntry<ReportActions>): OnyxEntry<ReportAction> => reportActions?.[`${oneTransactionItem?.reportAction?.reportActionID}`];
+    const [parentReportAction] = originalUseOnyx(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${getNonEmptyStringOnyxID(oneTransactionItem?.reportID)}`, {selector: parentReportActionSelector}, [
+        oneTransactionItem,
+    ]);
+    const transactionPreviewData: TransactionPreviewData = {
+        hasParentReport: !!parentReport,
+        hasTransaction: !!oneTransaction,
+        hasParentReportAction: !!parentReportAction,
+        hasTransactionThreadReport: !!oneTransactionThreadReport,
+    };
+
     // Compute sub-header columns (same logic as TransactionGroupListExpanded)
     const [transactionsSnapshot] = useOnyx(`${ONYXKEYS.COLLECTION.SNAPSHOT}${groupItem.transactionsQueryJSON?.hash}`);
     const [visibleColumns] = useOnyx(ONYXKEYS.FORMS.SEARCH_ADVANCED_FILTERS_FORM, {selector: columnsSelector});
@@ -162,7 +201,7 @@ function GroupHeader({item, groupBy, searchType, columns, canSelectMultiple, isE
             : undefined);
 
     const handleSelectRow = (rowItem: SearchListItem, event?: ModifiedMouseEvent) => {
-        onSelectRow(rowItem, event);
+        onSelectRow(rowItem, transactionPreviewData, event);
     };
 
     const renderHeader = () => {
@@ -178,6 +217,10 @@ function GroupHeader({item, groupBy, searchType, columns, canSelectMultiple, isE
                     isIndeterminate={isIndeterminate}
                     onDownArrowClick={onToggle}
                     isExpanded={isExpanded}
+                    lastPaymentMethod={lastPaymentMethod}
+                    personalPolicyID={personalPolicyID}
+                    userBillingGracePeriodEnds={userBillingGracePeriodEnds}
+                    ownerBillingGracePeriodEnd={ownerBillingGracePeriodEnd}
                 />
             );
         }
@@ -336,10 +379,19 @@ function GroupHeader({item, groupBy, searchType, columns, canSelectMultiple, isE
         isItemSelected && styles.activeComponentBG,
     ];
 
+    const handlePress = (event?: ModifiedMouseEvent) => {
+        if (isExpenseReportType) {
+            onSelectRow(item, transactionPreviewData, event);
+        }
+        if (!isExpenseReportType) {
+            onToggle();
+        }
+    };
+
     return (
         <OfflineWithFeedback pendingAction={pendingAction}>
             <PressableWithFeedback
-                onPress={onToggle}
+                onPress={handlePress}
                 disabled={false}
                 sentryLabel={CONST.SENTRY_LABEL.SEARCH.TRANSACTION_GROUP_LIST_ITEM}
                 accessibilityLabel={item.text ?? ''}
diff --git a/src/components/Search/SearchList/index.tsx b/src/components/Search/SearchList/index.tsx
index b70c9e38abc9..8e3b52244f05 100644
--- a/src/components/Search/SearchList/index.tsx
+++ b/src/components/Search/SearchList/index.tsx
@@ -481,11 +481,15 @@ function SearchList({
                         canSelectMultiple={canSelectMultiple}
                         isExpanded={expandedGroups.has(originalKey)}
                         onToggle={() => onToggleGroup(originalKey)}
-                        onSelectRow={(val, event) => onSelectRow(val, undefined, event)}
+                        onSelectRow={onSelectRow}
                         onCheckboxPress={(val) => onCheckboxPress(val as SearchListItem)}
                         isFocused={isItemFocused}
                         isFirstItem={index === firstVisibleIndex}
                         isLastItem={index + 1 >= lastVisibleIndex && !ListFooterComponent}
+                        lastPaymentMethod={lastPaymentMethod}
+                        personalPolicyID={personalPolicyID}
+                        userBillingGracePeriodEnds={userBillingGracePeriodEnds}
+                        ownerBillingGracePeriodEnd={ownerBillingGracePeriodEnd}
                     />
                 );
             }

From d3d7d63eacf67b7dd9f5d8af62c618546e360e93 Mon Sep 17 00:00:00 2001
From: krishna2323 <belivethatkg@gmail.com>
Date: Sat, 30 May 2026 20:55:36 +0530
Subject: [PATCH 065/435] refactor: Merge header and sub-header into single
 pressable, fix onLongPress and hover props

Signed-off-by: krishna2323 <belivethatkg@gmail.com>
---
 .../SearchList/ListItem/GroupHeader.tsx       | 98 ++++++++++---------
 src/components/Search/SearchList/index.tsx    |  1 +
 2 files changed, 53 insertions(+), 46 deletions(-)

diff --git a/src/components/Search/SearchList/ListItem/GroupHeader.tsx b/src/components/Search/SearchList/ListItem/GroupHeader.tsx
index 2455d9e0b3c8..7c3e329095e2 100644
--- a/src/components/Search/SearchList/ListItem/GroupHeader.tsx
+++ b/src/components/Search/SearchList/ListItem/GroupHeader.tsx
@@ -46,6 +46,7 @@ import type {
     TransactionCardGroupListItemType,
     TransactionCategoryGroupListItemType,
     TransactionGroupListItemType,
+    TransactionListItemType,
     TransactionMemberGroupListItemType,
     TransactionMerchantGroupListItemType,
     TransactionMonthGroupListItemType,
@@ -70,6 +71,7 @@ type GroupHeaderProps = SearchListActionProps & {
     onToggle: () => void;
     onSelectRow: (item: SearchListItem, transactionPreviewData?: TransactionPreviewData, event?: ModifiedMouseEvent) => void;
     onCheckboxPress: (item: GroupHeaderItemType) => void;
+    onLongPressRow?: (item: SearchListItem, itemTransactions?: TransactionListItemType[]) => void;
     isFocused?: boolean;
     isFirstItem: boolean;
     isLastItem: boolean;
@@ -85,6 +87,7 @@ function GroupHeader({
     onToggle,
     onSelectRow,
     onCheckboxPress,
+    onLongPressRow,
     isFocused,
     isFirstItem,
     isLastItem,
@@ -204,7 +207,7 @@ function GroupHeader({
         onSelectRow(rowItem, transactionPreviewData, event);
     };
 
-    const renderHeader = () => {
+    const renderHeader = (hovered: boolean) => {
         if (isExpenseReportType) {
             return (
                 <ReportListItemHeader
@@ -212,9 +215,11 @@ function GroupHeader({
                     onSelectRow={handleSelectRow}
                     onCheckboxPress={handleSelectionButtonPress}
                     isDisabled={isDisabledOrEmpty}
+                    isFocused={isFocused}
                     canSelectMultiple={canSelectMultiple}
                     isSelectAllChecked={isSelectAllChecked}
                     isIndeterminate={isIndeterminate}
+                    isHovered={hovered}
                     onDownArrowClick={onToggle}
                     isExpanded={isExpanded}
                     lastPaymentMethod={lastPaymentMethod}
@@ -388,10 +393,15 @@ function GroupHeader({
         }
     };
 
+    const handleLongPress = () => {
+        onLongPressRow?.(item, isExpenseReportType ? undefined : groupItem.transactions);
+    };
+
     return (
         <OfflineWithFeedback pendingAction={pendingAction}>
             <PressableWithFeedback
                 onPress={handlePress}
+                onLongPress={handleLongPress}
                 disabled={false}
                 sentryLabel={CONST.SENTRY_LABEL.SEARCH.TRANSACTION_GROUP_LIST_ITEM}
                 accessibilityLabel={item.text ?? ''}
@@ -418,10 +428,10 @@ function GroupHeader({
                           ],
                 ]}
             >
-                {() => (
+                {({hovered}) => (
                     <View style={styles.flex1}>
                         <View style={[styles.flexRow, styles.alignItemsCenter]}>
-                            <View style={styles.flex1}>{renderHeader()}</View>
+                            <View style={styles.flex1}>{renderHeader(hovered)}</View>
                             {isLargeScreenWidth && (
                                 <PressableWithFeedback
                                     onPress={onToggle}
@@ -430,61 +440,57 @@ function GroupHeader({
                                     accessibilityLabel={isExpanded ? CONST.ACCESSIBILITY_LABELS.COLLAPSE : CONST.ACCESSIBILITY_LABELS.EXPAND}
                                     sentryLabel={CONST.SENTRY_LABEL.SEARCH.GROUP_EXPAND_TOGGLE}
                                 >
-                                    {({hovered}) => (
+                                    {({hovered: arrowHovered}) => (
                                         <Icon
                                             src={isExpanded ? expensifyIcons.UpArrow : expensifyIcons.DownArrow}
                                             fill={theme.icon}
-                                            additionalStyles={!hovered && styles.opacitySemiTransparent}
+                                            additionalStyles={!arrowHovered && styles.opacitySemiTransparent}
                                             small
                                         />
                                     )}
                                 </PressableWithFeedback>
                             )}
                         </View>
+                        {isLargeScreenWidth && (
+                            <Animated.View style={subHeaderAnimatedStyle}>
+                                {(isExpanded || isSubHeaderRendered) && (
+                                    <View
+                                        style={styles.stickToTop}
+                                        onLayout={(e) => {
+                                            const height = e.nativeEvent.layout.height;
+                                            if (height) {
+                                                subHeaderHeight.set(height);
+                                            }
+                                        }}
+                                    >
+                                        <View style={[styles.pv2, styles.ph3, styles.pb1, styles.pt1]}>
+                                            <View style={[styles.borderBottom, styles.borderNone]} />
+                                        </View>
+                                        <View style={[styles.searchListHeaderContainerStyle, styles.groupSearchListTableContainerStyle, styles.bgTransparent, styles.pl8, styles.borderNone]}>
+                                            <SearchTableHeader
+                                                canSelectMultiple
+                                                type={CONST.SEARCH.DATA_TYPES.EXPENSE}
+                                                onSortPress={() => {}}
+                                                sortOrder={undefined}
+                                                sortBy={undefined}
+                                                shouldShowYear={shouldSubHeaderShowYear}
+                                                isAmountColumnWide={isSubHeaderAmountColumnWide}
+                                                isTaxAmountColumnWide={isSubHeaderTaxAmountColumnWide}
+                                                shouldShowSorting={false}
+                                                columns={subHeaderColumns}
+                                                groupBy={groupBy}
+                                                isExpenseReportView
+                                                isActionColumnWide={isSubHeaderActionColumnWide}
+                                            />
+                                        </View>
+                                        <View style={[StyleUtils.getSelectedBorderBottomStyle(isItemSelected), styles.ml3, styles.mr3, {marginBottom: 1}]} />
+                                    </View>
+                                )}
+                            </Animated.View>
+                        )}
                     </View>
                 )}
             </PressableWithFeedback>
-            {isLargeScreenWidth && (
-                <Animated.View style={[subHeaderAnimatedStyle, styles.mh5, {backgroundColor: isItemSelected ? theme.activeComponentBG : theme.highlightBG}]}>
-                    {(isExpanded || isSubHeaderRendered) && (
-                        <PressableWithFeedback
-                            onPress={onToggle}
-                            style={[styles.stickToTop, styles.cursorPointer]}
-                            onLayout={(e) => {
-                                const height = e.nativeEvent.layout.height;
-                                if (height) {
-                                    subHeaderHeight.set(height);
-                                }
-                            }}
-                            accessibilityRole={CONST.ROLE.BUTTON}
-                            accessibilityLabel={isExpanded ? CONST.ACCESSIBILITY_LABELS.COLLAPSE : CONST.ACCESSIBILITY_LABELS.EXPAND}
-                            sentryLabel={CONST.SENTRY_LABEL.SEARCH.GROUP_EXPAND_TOGGLE}
-                        >
-                            <View style={[styles.pv2, styles.ph3, styles.pb1, styles.pt1]}>
-                                <View style={[styles.borderBottom, styles.borderNone]} />
-                            </View>
-                            <View style={[styles.searchListHeaderContainerStyle, styles.groupSearchListTableContainerStyle, styles.bgTransparent, styles.pl8, styles.borderNone]}>
-                                <SearchTableHeader
-                                    canSelectMultiple
-                                    type={CONST.SEARCH.DATA_TYPES.EXPENSE}
-                                    onSortPress={() => {}}
-                                    sortOrder={undefined}
-                                    sortBy={undefined}
-                                    shouldShowYear={shouldSubHeaderShowYear}
-                                    isAmountColumnWide={isSubHeaderAmountColumnWide}
-                                    isTaxAmountColumnWide={isSubHeaderTaxAmountColumnWide}
-                                    shouldShowSorting={false}
-                                    columns={subHeaderColumns}
-                                    groupBy={groupBy}
-                                    isExpenseReportView
-                                    isActionColumnWide={isSubHeaderActionColumnWide}
-                                />
-                            </View>
-                            <View style={[StyleUtils.getSelectedBorderBottomStyle(isItemSelected), styles.ml3, styles.mr3, {marginBottom: 1}]} />
-                        </PressableWithFeedback>
-                    )}
-                </Animated.View>
-            )}
         </OfflineWithFeedback>
     );
 }
diff --git a/src/components/Search/SearchList/index.tsx b/src/components/Search/SearchList/index.tsx
index 8e3b52244f05..3e631f4a88e5 100644
--- a/src/components/Search/SearchList/index.tsx
+++ b/src/components/Search/SearchList/index.tsx
@@ -483,6 +483,7 @@ function SearchList({
                         onToggle={() => onToggleGroup(originalKey)}
                         onSelectRow={onSelectRow}
                         onCheckboxPress={(val) => onCheckboxPress(val as SearchListItem)}
+                        onLongPressRow={isMobileSelectionModeEnabled ? handleLongPressRowInMobileSelectionMode : handleLongPressRow}
                         isFocused={isItemFocused}
                         isFirstItem={index === firstVisibleIndex}
                         isLastItem={index + 1 >= lastVisibleIndex && !ListFooterComponent}

From 912eaefbb5ff68b39936ee422f50c4d50843a617 Mon Sep 17 00:00:00 2001
From: krishna2323 <belivethatkg@gmail.com>
Date: Sat, 30 May 2026 21:38:13 +0530
Subject: [PATCH 066/435] refactor: Merge header and sub-header into single
 pressable, restore onLongPress and hover props

Signed-off-by: krishna2323 <belivethatkg@gmail.com>
---
 src/components/Search/SearchList/ListItem/GroupHeader.tsx | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/src/components/Search/SearchList/ListItem/GroupHeader.tsx b/src/components/Search/SearchList/ListItem/GroupHeader.tsx
index 7c3e329095e2..0e14042e1169 100644
--- a/src/components/Search/SearchList/ListItem/GroupHeader.tsx
+++ b/src/components/Search/SearchList/ListItem/GroupHeader.tsx
@@ -377,11 +377,11 @@ function GroupHeader({
     const pressableStyle = [
         styles.transactionGroupListItemStyle,
         isLargeScreenWidth && {
-            ...styles.tableRowHeight,
             borderRadius: 0,
             ...(isLastItemCollapsed ? styles.tableBottomRadius : {}),
         },
         isItemSelected && styles.activeComponentBG,
+        {minHeight: 0},
     ];
 
     const handlePress = (event?: ModifiedMouseEvent) => {
@@ -430,7 +430,7 @@ function GroupHeader({
             >
                 {({hovered}) => (
                     <View style={styles.flex1}>
-                        <View style={[styles.flexRow, styles.alignItemsCenter]}>
+                        <View style={[styles.flexRow, styles.alignItemsCenter, isLargeScreenWidth && styles.tableRowHeight]}>
                             <View style={styles.flex1}>{renderHeader(hovered)}</View>
                             {isLargeScreenWidth && (
                                 <PressableWithFeedback
@@ -463,7 +463,7 @@ function GroupHeader({
                                             }
                                         }}
                                     >
-                                        <View style={[styles.pv2, styles.ph3, styles.pb1, styles.pt1]}>
+                                        <View style={[styles.ph3, styles.pb1]}>
                                             <View style={[styles.borderBottom, styles.borderNone]} />
                                         </View>
                                         <View style={[styles.searchListHeaderContainerStyle, styles.groupSearchListTableContainerStyle, styles.bgTransparent, styles.pl8, styles.borderNone]}>

From c7ca12dc9cd4f93b61858ecb1aaabedce045e932 Mon Sep 17 00:00:00 2001
From: krishna2323 <belivethatkg@gmail.com>
Date: Sat, 30 May 2026 22:04:27 +0530
Subject: [PATCH 067/435] fix: Remove subpixel gaps by returning null from
 collapsed children container

Signed-off-by: krishna2323 <belivethatkg@gmail.com>
---
 .../Search/SearchList/ListItem/GroupChildrenContainer.tsx     | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/src/components/Search/SearchList/ListItem/GroupChildrenContainer.tsx b/src/components/Search/SearchList/ListItem/GroupChildrenContainer.tsx
index 5caf3de02a7f..29a1465de78c 100644
--- a/src/components/Search/SearchList/ListItem/GroupChildrenContainer.tsx
+++ b/src/components/Search/SearchList/ListItem/GroupChildrenContainer.tsx
@@ -231,6 +231,10 @@ function GroupChildrenContainer({
         opacity: animatedOpacity.get(),
     }));
 
+    if (!isExpanded && !isRendered) {
+        return null;
+    }
+
     return (
         <View style={[styles.mh5, {backgroundColor: theme.highlightBG}, isLastItem && [styles.tableBottomRadius, styles.overflowHidden]]}>
             <Animated.View style={contentAnimatedStyle}>

From 53cd10fe3a4a990b86f917052b1d3904f79360ed Mon Sep 17 00:00:00 2001
From: Youssef Lourayad <youssef@expensify.com>
Date: Sat, 30 May 2026 21:47:39 +0000
Subject: [PATCH 068/435] Remove DM & expense filters

---
 src/CONST/index.ts                           |  3 +--
 src/languages/de.ts                          |  3 +--
 src/languages/en.ts                          |  3 +--
 src/languages/es.ts                          |  3 +--
 src/languages/fr.ts                          |  3 +--
 src/languages/it.ts                          |  3 +--
 src/languages/ja.ts                          |  3 +--
 src/languages/nl.ts                          |  3 +--
 src/languages/pl.ts                          |  3 +--
 src/languages/pt-BR.ts                       |  3 +--
 src/languages/zh-hans.ts                     |  3 +--
 src/libs/SidebarUtils.ts                     |  9 +++------
 src/pages/inbox/sidebar/InboxTabSelector.tsx |  6 +++---
 src/types/onyx/InboxTab.ts                   |  1 +
 tests/perf-test/SidebarLinks.perf-test.tsx   |  4 ++--
 tests/unit/SidebarFilterTest.ts              | 12 ++++++++++++
 tests/unit/SidebarTest.ts                    |  4 ++--
 tests/unit/SidebarUtilsTest.ts               | 14 ++++++++------
 18 files changed, 42 insertions(+), 41 deletions(-)

diff --git a/src/CONST/index.ts b/src/CONST/index.ts
index d3eed1c741bc..d06fa29aa180 100644
--- a/src/CONST/index.ts
+++ b/src/CONST/index.ts
@@ -2245,9 +2245,8 @@ const CONST = {
     },
     INBOX_TAB: {
         ALL: 'all',
+        TODO: 'todo',
         UNREAD: 'unread',
-        EXPENSES: 'expenses',
-        DMS: 'dms',
     },
     THEME: {
         DEFAULT: 'system',
diff --git a/src/languages/de.ts b/src/languages/de.ts
index b57d98074f67..e3222cf3a286 100644
--- a/src/languages/de.ts
+++ b/src/languages/de.ts
@@ -2896,9 +2896,8 @@ ${amount} für ${merchant} – ${date}`,
     },
     inboxTabs: {
         all: 'All',
+        todo: 'To-do',
         unread: 'Unread',
-        expenses: 'Expenses',
-        dms: 'DMs',
     },
     reportDetailsPage: {
         inWorkspace: (policyName: string) => `in ${policyName}`,
diff --git a/src/languages/en.ts b/src/languages/en.ts
index 3dd1a57e6add..62629563c128 100644
--- a/src/languages/en.ts
+++ b/src/languages/en.ts
@@ -2967,9 +2967,8 @@ const translations = {
     },
     inboxTabs: {
         all: 'All',
+        todo: 'To-do',
         unread: 'Unread',
-        expenses: 'Expenses',
-        dms: 'DMs',
     },
     reportDetailsPage: {
         inWorkspace: (policyName: string) => `in ${policyName}`,
diff --git a/src/languages/es.ts b/src/languages/es.ts
index 3412103bef82..a222c9dd554d 100644
--- a/src/languages/es.ts
+++ b/src/languages/es.ts
@@ -2775,9 +2775,8 @@ ${amount} para ${merchant} - ${date}`,
     },
     inboxTabs: {
         all: 'All',
+        todo: 'To-do',
         unread: 'Unread',
-        expenses: 'Expenses',
-        dms: 'DMs',
     },
     reportDetailsPage: {
         inWorkspace: (policyName) => `en ${policyName}`,
diff --git a/src/languages/fr.ts b/src/languages/fr.ts
index 7a7719b72631..48d1f73eb2dd 100644
--- a/src/languages/fr.ts
+++ b/src/languages/fr.ts
@@ -2904,9 +2904,8 @@ ${amount} pour ${merchant} - ${date}`,
     },
     inboxTabs: {
         all: 'All',
+        todo: 'To-do',
         unread: 'Unread',
-        expenses: 'Expenses',
-        dms: 'DMs',
     },
     reportDetailsPage: {
         inWorkspace: (policyName: string) => `dans ${policyName}`,
diff --git a/src/languages/it.ts b/src/languages/it.ts
index 7a16dcfd21e9..74008d5b625a 100644
--- a/src/languages/it.ts
+++ b/src/languages/it.ts
@@ -2892,9 +2892,8 @@ ${amount} per ${merchant} - ${date}`,
     },
     inboxTabs: {
         all: 'All',
+        todo: 'To-do',
         unread: 'Unread',
-        expenses: 'Expenses',
-        dms: 'DMs',
     },
     reportDetailsPage: {
         inWorkspace: (policyName: string) => `in ${policyName}`,
diff --git a/src/languages/ja.ts b/src/languages/ja.ts
index 744f96150eab..846c4766166c 100644
--- a/src/languages/ja.ts
+++ b/src/languages/ja.ts
@@ -2868,9 +2868,8 @@ ${date} の ${merchant} への ${amount}`,
     },
     inboxTabs: {
         all: 'All',
+        todo: 'To-do',
         unread: 'Unread',
-        expenses: 'Expenses',
-        dms: 'DMs',
     },
     reportDetailsPage: {
         inWorkspace: (policyName: string) => `${policyName} 内`,
diff --git a/src/languages/nl.ts b/src/languages/nl.ts
index e057783c5813..c522b5421e4e 100644
--- a/src/languages/nl.ts
+++ b/src/languages/nl.ts
@@ -2889,9 +2889,8 @@ ${amount} voor ${merchant} - ${date}`,
     },
     inboxTabs: {
         all: 'All',
+        todo: 'To-do',
         unread: 'Unread',
-        expenses: 'Expenses',
-        dms: 'DMs',
     },
     reportDetailsPage: {
         inWorkspace: (policyName: string) => `in ${policyName}`,
diff --git a/src/languages/pl.ts b/src/languages/pl.ts
index 3a736a4f510f..58a4b7b49757 100644
--- a/src/languages/pl.ts
+++ b/src/languages/pl.ts
@@ -2883,9 +2883,8 @@ ${amount} dla ${merchant} - ${date}`,
     },
     inboxTabs: {
         all: 'All',
+        todo: 'To-do',
         unread: 'Unread',
-        expenses: 'Expenses',
-        dms: 'DMs',
     },
     reportDetailsPage: {
         inWorkspace: (policyName: string) => `w ${policyName}`,
diff --git a/src/languages/pt-BR.ts b/src/languages/pt-BR.ts
index 1bb944ab259b..0de92a894209 100644
--- a/src/languages/pt-BR.ts
+++ b/src/languages/pt-BR.ts
@@ -2883,9 +2883,8 @@ ${amount} para ${merchant} - ${date}`,
     },
     inboxTabs: {
         all: 'All',
+        todo: 'To-do',
         unread: 'Unread',
-        expenses: 'Expenses',
-        dms: 'DMs',
     },
     reportDetailsPage: {
         inWorkspace: (policyName: string) => `em ${policyName}`,
diff --git a/src/languages/zh-hans.ts b/src/languages/zh-hans.ts
index 2b07dcc88697..c0641efcf72e 100644
--- a/src/languages/zh-hans.ts
+++ b/src/languages/zh-hans.ts
@@ -2810,9 +2810,8 @@ ${amount}，商户：${merchant} - 日期：${date}`,
     },
     inboxTabs: {
         all: 'All',
+        todo: 'To-do',
         unread: 'Unread',
-        expenses: 'Expenses',
-        dms: 'DMs',
     },
     reportDetailsPage: {
         inWorkspace: (policyName: string) => `在 ${policyName} 中`,
diff --git a/src/libs/SidebarUtils.ts b/src/libs/SidebarUtils.ts
index 7594fb6e9a81..0e8efa2ba988 100644
--- a/src/libs/SidebarUtils.ts
+++ b/src/libs/SidebarUtils.ts
@@ -171,7 +171,6 @@ import {
     isChatThread,
     isConciergeChatReport,
     isDeprecatedGroupDM,
-    isDM,
     isDomainRoom,
     isExpenseReport,
     isExpenseRequest,
@@ -180,7 +179,6 @@ import {
     isInvoiceReport,
     isInvoiceRoom,
     isIOUOwnedByCurrentUser,
-    isIOUReport,
     isJoinRequestInAdminRoom,
     isMoneyRequestReport,
     isOneOnOneChat,
@@ -1505,14 +1503,13 @@ function filterReportsForInboxTab(
         }
 
         switch (activeTab) {
+            case CONST.INBOX_TAB.TODO:
+                // Reports with an outstanding GBR (requiresAttention) or RBR (errors) require the user's action.
+                return !!report.requiresAttention || !!report.hasErrorsOtherThanFailedReceipt;
             case CONST.INBOX_TAB.UNREAD: {
                 const isReportArchived = isArchivedReport(reportNameValuePairs?.[`${ONYXKEYS.COLLECTION.REPORT_NAME_VALUE_PAIRS}${reportID}`]);
                 return isUnread(report, undefined, isReportArchived) && getReportNotificationPreference(report) !== CONST.REPORT.NOTIFICATION_PREFERENCE.MUTE;
             }
-            case CONST.INBOX_TAB.EXPENSES:
-                return isExpenseReport(report) || isIOUReport(report) || isInvoiceReport(report) || isPolicyExpenseChat(report);
-            case CONST.INBOX_TAB.DMS:
-                return isDM(report) || isSelfDM(report) || isGroupChatUtil(report);
             default:
                 return true;
         }
diff --git a/src/pages/inbox/sidebar/InboxTabSelector.tsx b/src/pages/inbox/sidebar/InboxTabSelector.tsx
index 4de90b6aa6e5..89c44a76b9c0 100644
--- a/src/pages/inbox/sidebar/InboxTabSelector.tsx
+++ b/src/pages/inbox/sidebar/InboxTabSelector.tsx
@@ -1,4 +1,5 @@
 import React from 'react';
+import type {ValueOf} from 'type-fest';
 import TabSelectorBase from '@components/TabSelector/TabSelectorBase';
 import TabSelectorContextProvider from '@components/TabSelector/TabSelectorContext';
 import type {TabSelectorBaseItem} from '@components/TabSelector/types';
@@ -13,9 +14,8 @@ function InboxTabSelector() {
 
     const tabs: TabSelectorBaseItem[] = [
         {key: CONST.INBOX_TAB.ALL, title: translate('inboxTabs.all')},
+        {key: CONST.INBOX_TAB.TODO, title: translate('inboxTabs.todo')},
         {key: CONST.INBOX_TAB.UNREAD, title: translate('inboxTabs.unread')},
-        {key: CONST.INBOX_TAB.EXPENSES, title: translate('inboxTabs.expenses')},
-        {key: CONST.INBOX_TAB.DMS, title: translate('inboxTabs.dms')},
     ];
 
     return (
@@ -23,7 +23,7 @@ function InboxTabSelector() {
             <TabSelectorBase
                 tabs={tabs}
                 activeTabKey={activeTab}
-                onTabPress={setActiveTab}
+                onTabPress={(key) => setActiveTab(key as ValueOf<typeof CONST.INBOX_TAB>)}
                 size="small"
             />
         </TabSelectorContextProvider>
diff --git a/src/types/onyx/InboxTab.ts b/src/types/onyx/InboxTab.ts
index 616f5b89f764..3fc35c106b39 100644
--- a/src/types/onyx/InboxTab.ts
+++ b/src/types/onyx/InboxTab.ts
@@ -1,6 +1,7 @@
 import type {ValueOf} from 'type-fest';
 import type CONST from '@src/CONST';
 
+/** The active Inbox tab filter (All, To-do, or Unread) */
 type InboxTab = ValueOf<typeof CONST.INBOX_TAB>;
 
 export default InboxTab;
diff --git a/tests/perf-test/SidebarLinks.perf-test.tsx b/tests/perf-test/SidebarLinks.perf-test.tsx
index 46f35544a7ee..66f9493aa726 100644
--- a/tests/perf-test/SidebarLinks.perf-test.tsx
+++ b/tests/perf-test/SidebarLinks.perf-test.tsx
@@ -81,7 +81,7 @@ describe('SidebarLinks', () => {
         await Onyx.multiSet({
             [ONYXKEYS.PERSONAL_DETAILS_LIST]: LHNTestUtils.fakePersonalDetails,
             [ONYXKEYS.BETAS]: [CONST.BETAS.DEFAULT_ROOMS],
-
+            [ONYXKEYS.NVP_PRIORITY_MODE]: CONST.PRIORITY_MODE.GSD,
             [ONYXKEYS.IS_LOADING_REPORT_DATA]: false,
             ...mockedResponseMap,
         });
@@ -103,7 +103,7 @@ describe('SidebarLinks', () => {
         await Onyx.multiSet({
             [ONYXKEYS.PERSONAL_DETAILS_LIST]: LHNTestUtils.fakePersonalDetails,
             [ONYXKEYS.BETAS]: [CONST.BETAS.DEFAULT_ROOMS],
-
+            [ONYXKEYS.NVP_PRIORITY_MODE]: CONST.PRIORITY_MODE.GSD,
             [ONYXKEYS.IS_LOADING_REPORT_DATA]: false,
             ...mockedResponseMap,
         });
diff --git a/tests/unit/SidebarFilterTest.ts b/tests/unit/SidebarFilterTest.ts
index c377ef0c6e25..1970472dfdc3 100644
--- a/tests/unit/SidebarFilterTest.ts
+++ b/tests/unit/SidebarFilterTest.ts
@@ -17,6 +17,7 @@ jest.mock('@libs/Permissions');
 const ONYXKEYS = {
     PERSONAL_DETAILS_LIST: 'personalDetailsList',
     IS_LOADING_APP: 'isLoadingApp',
+    NVP_PRIORITY_MODE: 'nvp_priorityMode',
     SESSION: 'session',
     BETAS: 'betas',
     COLLECTION: {
@@ -371,6 +372,7 @@ xdescribe('Sidebar', () => {
                             // When Onyx is updated to contain that data and the sidebar re-renders
                             .then(() =>
                                 Onyx.multiSet({
+                                    [ONYXKEYS.NVP_PRIORITY_MODE]: CONST.PRIORITY_MODE.GSD,
                                     [ONYXKEYS.BETAS]: betas,
                                     [ONYXKEYS.PERSONAL_DETAILS_LIST]: LHNTestUtils.fakePersonalDetails,
                                     [ONYXKEYS.IS_LOADING_APP]: false,
@@ -419,6 +421,7 @@ xdescribe('Sidebar', () => {
                     // When Onyx is updated to contain that data and the sidebar re-renders
                     .then(() =>
                         Onyx.multiSet({
+                            [ONYXKEYS.NVP_PRIORITY_MODE]: CONST.PRIORITY_MODE.GSD,
                             [ONYXKEYS.PERSONAL_DETAILS_LIST]: LHNTestUtils.fakePersonalDetails,
                             [ONYXKEYS.IS_LOADING_APP]: false,
                             ...reportCollectionDataSet,
@@ -489,6 +492,7 @@ xdescribe('Sidebar', () => {
                     // When Onyx is updated to contain that data and the sidebar re-renders
                     .then(() =>
                         Onyx.multiSet({
+                            [ONYXKEYS.NVP_PRIORITY_MODE]: CONST.PRIORITY_MODE.GSD,
                             [ONYXKEYS.PERSONAL_DETAILS_LIST]: LHNTestUtils.fakePersonalDetails,
                             [ONYXKEYS.IS_LOADING_APP]: false,
                             [`${ONYXKEYS.COLLECTION.REPORT_DRAFT_COMMENT}${draftReport.reportID}`]: 'draft report message',
@@ -542,6 +546,7 @@ xdescribe('Sidebar', () => {
                     // When Onyx is updated to contain that data and the sidebar re-renders
                     .then(() =>
                         Onyx.multiSet({
+                            [ONYXKEYS.NVP_PRIORITY_MODE]: CONST.PRIORITY_MODE.GSD,
                             [ONYXKEYS.BETAS]: betas,
                             [ONYXKEYS.PERSONAL_DETAILS_LIST]: LHNTestUtils.fakePersonalDetails,
                             [ONYXKEYS.IS_LOADING_APP]: false,
@@ -607,6 +612,7 @@ xdescribe('Sidebar', () => {
                     // When Onyx is updated to contain that data and the sidebar re-renders
                     .then(() =>
                         Onyx.multiSet({
+                            [ONYXKEYS.NVP_PRIORITY_MODE]: CONST.PRIORITY_MODE.GSD,
                             [ONYXKEYS.BETAS]: betas,
                             [ONYXKEYS.PERSONAL_DETAILS_LIST]: LHNTestUtils.fakePersonalDetails,
                             [ONYXKEYS.IS_LOADING_APP]: false,
@@ -708,6 +714,7 @@ xdescribe('Sidebar', () => {
                         // When Onyx is updated to contain that data and the sidebar re-renders
                         .then(() =>
                             Onyx.multiSet({
+                                [ONYXKEYS.NVP_PRIORITY_MODE]: CONST.PRIORITY_MODE.GSD,
                                 [ONYXKEYS.BETAS]: betas,
                                 [ONYXKEYS.PERSONAL_DETAILS_LIST]: LHNTestUtils.fakePersonalDetails,
                                 [ONYXKEYS.IS_LOADING_APP]: false,
@@ -762,6 +769,7 @@ xdescribe('Sidebar', () => {
                         // When Onyx is updated to contain that data and the sidebar re-renders
                         .then(() =>
                             Onyx.multiSet({
+                                [ONYXKEYS.NVP_PRIORITY_MODE]: CONST.PRIORITY_MODE.DEFAULT,
                                 [ONYXKEYS.BETAS]: betas,
                                 [ONYXKEYS.PERSONAL_DETAILS_LIST]: LHNTestUtils.fakePersonalDetails,
                                 [ONYXKEYS.IS_LOADING_APP]: false,
@@ -814,6 +822,7 @@ xdescribe('Sidebar', () => {
                         // When Onyx is updated to contain that data and the sidebar re-renders
                         .then(() =>
                             Onyx.multiSet({
+                                [ONYXKEYS.NVP_PRIORITY_MODE]: CONST.PRIORITY_MODE.GSD,
                                 [ONYXKEYS.BETAS]: betas,
                                 [ONYXKEYS.PERSONAL_DETAILS_LIST]: LHNTestUtils.fakePersonalDetails,
                                 [ONYXKEYS.IS_LOADING_APP]: false,
@@ -864,6 +873,7 @@ xdescribe('Sidebar', () => {
                         // When Onyx is updated to contain that data and the sidebar re-renders
                         .then(() =>
                             Onyx.multiSet({
+                                [ONYXKEYS.NVP_PRIORITY_MODE]: CONST.PRIORITY_MODE.GSD,
                                 [ONYXKEYS.BETAS]: betas,
                                 [ONYXKEYS.PERSONAL_DETAILS_LIST]: LHNTestUtils.fakePersonalDetails,
                                 [ONYXKEYS.IS_LOADING_APP]: false,
@@ -910,6 +920,7 @@ xdescribe('Sidebar', () => {
                         // When Onyx is updated to contain that data and the sidebar re-renders
                         .then(() =>
                             Onyx.multiSet({
+                                [ONYXKEYS.NVP_PRIORITY_MODE]: CONST.PRIORITY_MODE.GSD,
                                 [ONYXKEYS.BETAS]: betas,
                                 [ONYXKEYS.PERSONAL_DETAILS_LIST]: LHNTestUtils.fakePersonalDetails,
                                 [ONYXKEYS.IS_LOADING_APP]: false,
@@ -945,6 +956,7 @@ xdescribe('Sidebar', () => {
                         // When Onyx is updated to contain that data and the sidebar re-renders
                         .then(() =>
                             Onyx.multiSet({
+                                [ONYXKEYS.NVP_PRIORITY_MODE]: CONST.PRIORITY_MODE.GSD,
                                 [ONYXKEYS.PERSONAL_DETAILS_LIST]: LHNTestUtils.fakePersonalDetails,
                                 [ONYXKEYS.IS_LOADING_APP]: false,
                                 ...reportCollectionDataSet,
diff --git a/tests/unit/SidebarTest.ts b/tests/unit/SidebarTest.ts
index 54a42f4a4ecd..a0fbc44f2995 100644
--- a/tests/unit/SidebarTest.ts
+++ b/tests/unit/SidebarTest.ts
@@ -94,7 +94,7 @@ describe('Sidebar', () => {
                         return act(async () => {
                             await Onyx.multiSet({
                                 [ONYXKEYS.BETAS]: betas,
-
+                                [ONYXKEYS.NVP_PRIORITY_MODE]: CONST.PRIORITY_MODE.GSD,
                                 [ONYXKEYS.PERSONAL_DETAILS_LIST]: LHNTestUtils.fakePersonalDetails,
                                 [ONYXKEYS.IS_LOADING_APP]: false,
                                 ...reportNameValuePairsCollection,
@@ -157,7 +157,7 @@ describe('Sidebar', () => {
                         return act(async () => {
                             await Onyx.multiSet({
                                 [ONYXKEYS.BETAS]: betas,
-
+                                [ONYXKEYS.NVP_PRIORITY_MODE]: CONST.PRIORITY_MODE.GSD,
                                 [ONYXKEYS.PERSONAL_DETAILS_LIST]: LHNTestUtils.fakePersonalDetails,
                                 [ONYXKEYS.IS_LOADING_APP]: false,
                                 ...reportNameValuePairsCollection,
diff --git a/tests/unit/SidebarUtilsTest.ts b/tests/unit/SidebarUtilsTest.ts
index 21d5e19e41f4..058c41917496 100644
--- a/tests/unit/SidebarUtilsTest.ts
+++ b/tests/unit/SidebarUtilsTest.ts
@@ -3776,10 +3776,10 @@ describe('SidebarUtils', () => {
                 ]);
 
                 const mockLocaleCompare = (a: string, b: string) => a.localeCompare(b);
-                const useAlphabeticalSort = false;
+                const priorityMode = CONST.PRIORITY_MODE.DEFAULT;
 
                 // When the reports are sorted
-                const result = SidebarUtils.sortReportsToDisplayInLHN(reports, useAlphabeticalSort, mockLocaleCompare, undefined, undefined, undefined);
+                const result = SidebarUtils.sortReportsToDisplayInLHN(reports, priorityMode, mockLocaleCompare, undefined, undefined, undefined);
 
                 // Then the reports are sorted in the correct order
                 expect(result).toEqual(['0', '1', '2']); // Pinned first, Error second, Normal third
@@ -3804,11 +3804,11 @@ describe('SidebarUtils', () => {
 
                 const mockLocaleCompare = (a: string, b: string) => a.localeCompare(b);
 
-                // When the reports are sorted in default mode (not alphabetical)
-                const defaultResult = SidebarUtils.sortReportsToDisplayInLHN(reports, false, mockLocaleCompare, undefined, undefined, undefined);
+                // When the reports are sorted in default mode
+                const defaultResult = SidebarUtils.sortReportsToDisplayInLHN(reports, CONST.PRIORITY_MODE.DEFAULT, mockLocaleCompare, undefined, undefined, undefined);
 
-                // When the reports are sorted in alphabetical mode
-                const gsdResult = SidebarUtils.sortReportsToDisplayInLHN(reports, true, mockLocaleCompare, undefined, undefined, undefined);
+                // When the reports are sorted in GSD mode
+                const gsdResult = SidebarUtils.sortReportsToDisplayInLHN(reports, CONST.PRIORITY_MODE.GSD, mockLocaleCompare, undefined, undefined, undefined);
 
                 // Then the reports are sorted in the correct order
                 expect(defaultResult).toEqual(['1', '0']); // Most recent first (index 1 has later date)
@@ -3828,6 +3828,7 @@ describe('SidebarUtils', () => {
                     reports,
                     updatedReportsKeys: [`${ONYXKEYS.COLLECTION.REPORT}999`],
                     currentReportId: '1',
+                    isInFocusMode: false,
                     betas: [],
                     transactions: {},
                     transactionViolations: {},
@@ -3851,6 +3852,7 @@ describe('SidebarUtils', () => {
                     reports,
                     updatedReportsKeys: ['0'],
                     currentReportId: undefined,
+                    isInFocusMode: false,
                     betas: [],
                     transactions: {},
                     transactionViolations: {},

From d8015354bb7a3a51585ca503f8d701fe42dec709 Mon Sep 17 00:00:00 2001
From: Youssef Lourayad <youssef@expensify.com>
Date: Sat, 30 May 2026 21:58:22 +0000
Subject: [PATCH 069/435] Perf: improve computing of unread reports

---
 src/hooks/useSidebarOrderedReports.tsx | 10 ++----
 src/libs/SidebarUtils.ts               | 43 +++++++++++++++-----------
 2 files changed, 28 insertions(+), 25 deletions(-)

diff --git a/src/hooks/useSidebarOrderedReports.tsx b/src/hooks/useSidebarOrderedReports.tsx
index 21d39d51b348..7dd37487b1bd 100644
--- a/src/hooks/useSidebarOrderedReports.tsx
+++ b/src/hooks/useSidebarOrderedReports.tsx
@@ -43,7 +43,7 @@ type SidebarOrderedReportsActionsContextValue = {
     setActiveTab: (tab: ValueOf<typeof CONST.INBOX_TAB>) => void;
 };
 
-type ReportsToDisplayInLHN = Record<string, OnyxTypes.Report & {hasErrorsOtherThanFailedReceipt?: boolean; requiresAttention?: boolean}>;
+type ReportsToDisplayInLHN = Record<string, OnyxTypes.Report & {hasErrorsOtherThanFailedReceipt?: boolean; requiresAttention?: boolean; isUnreadReport?: boolean}>;
 
 const SidebarOrderedReportsStateContext = createContext<SidebarOrderedReportsStateContextValue>({
     orderedReports: [],
@@ -296,10 +296,7 @@ function SidebarOrderedReportsContextProvider({
 
     // Narrow the ordered reports down to the ones belonging to the active Inbox tab. The "All" tab
     // returns everything (still honoring Most Recent / Focus mode from the ordering above).
-    const filteredReportIDs = useMemo(
-        () => SidebarUtils.filterReportsForInboxTab(orderedReportIDs, reportsToDisplayInLHN, activeTab, reportNameValuePairs),
-        [orderedReportIDs, reportsToDisplayInLHN, activeTab, reportNameValuePairs],
-    );
+    const filteredReportIDs = useMemo(() => SidebarUtils.filterReportsForInboxTab(orderedReportIDs, reportsToDisplayInLHN, activeTab), [orderedReportIDs, reportsToDisplayInLHN, activeTab]);
 
     // Get the actual reports based on the filtered IDs
     const getOrderedReports = useCallback(
@@ -342,7 +339,7 @@ function SidebarOrderedReportsContextProvider({
             filteredReportIDs.indexOf(derivedCurrentReportID) === -1
         ) {
             const updatedReportIDs = getOrderedReportIDs();
-            const updatedFilteredIDs = SidebarUtils.filterReportsForInboxTab(updatedReportIDs, reportsToDisplayInLHN, activeTab, reportNameValuePairs);
+            const updatedFilteredIDs = SidebarUtils.filterReportsForInboxTab(updatedReportIDs, reportsToDisplayInLHN, activeTab);
             const updatedReports = getOrderedReports(updatedFilteredIDs);
             return {
                 orderedReports: updatedReports,
@@ -371,7 +368,6 @@ function SidebarOrderedReportsContextProvider({
         reportAttributes,
         activeTab,
         reportsToDisplayInLHN,
-        reportNameValuePairs,
     ]);
 
     const actionsValue: SidebarOrderedReportsActionsContextValue = useMemo(() => ({clearLHNCache, setActiveTab}), [clearLHNCache, setActiveTab]);
diff --git a/src/libs/SidebarUtils.ts b/src/libs/SidebarUtils.ts
index 0e8efa2ba988..8fda67f74a6b 100644
--- a/src/libs/SidebarUtils.ts
+++ b/src/libs/SidebarUtils.ts
@@ -393,6 +393,7 @@ function getReportsToDisplayInLHN({
         }
 
         const reportDraftComment = draftComments?.[`${ONYXKEYS.COLLECTION.REPORT_DRAFT_COMMENT}${report.reportID}`];
+        const isReportArchived = isArchivedReport(reportNameValuePairs?.[`${ONYXKEYS.COLLECTION.REPORT_NAME_VALUE_PAIRS}${report.reportID}`]);
 
         const {shouldDisplay, hasErrorsOtherThanFailedReceipt} = shouldDisplayReportInLHN({
             report,
@@ -404,7 +405,7 @@ function getReportsToDisplayInLHN({
             draftComment: reportDraftComment,
             transactions,
             isOffline,
-            isReportArchived: isArchivedReport(reportNameValuePairs?.[`${ONYXKEYS.COLLECTION.REPORT_NAME_VALUE_PAIRS}${report.reportID}`]),
+            isReportArchived,
             reportAttributes,
             currentUserLogin,
             currentUserAccountID,
@@ -412,8 +413,9 @@ function getReportsToDisplayInLHN({
 
         if (shouldDisplay) {
             const requiresAttention = reportAttributes?.[report?.reportID]?.requiresAttention ?? false;
-            const hasAttentionOrError = requiresAttention || hasErrorsOtherThanFailedReceipt;
-            reportsToDisplay[reportID] = hasAttentionOrError ? {...report, requiresAttention, hasErrorsOtherThanFailedReceipt} : report;
+            const isUnreadReport = getIsUnreadReportForInboxTab(report, isReportArchived);
+            reportsToDisplay[reportID] =
+                requiresAttention || hasErrorsOtherThanFailedReceipt || isUnreadReport ? {...report, requiresAttention, hasErrorsOtherThanFailedReceipt, isUnreadReport} : report;
         }
     }
 
@@ -474,6 +476,7 @@ function updateReportsToDisplayInLHN({
         // Get the specific draft comment for this report instead of using a single draft comment for all reports
         // This fixes the issue where the current report's draft comment was incorrectly used to filter all reports
         const reportDraftComment = draftComments?.[`${ONYXKEYS.COLLECTION.REPORT_DRAFT_COMMENT}${report.reportID}`];
+        const isReportArchived = isArchivedReport(reportNameValuePairs?.[`${ONYXKEYS.COLLECTION.REPORT_NAME_VALUE_PAIRS}${report.reportID}`] ?? {});
 
         const {shouldDisplay, hasErrorsOtherThanFailedReceipt} = shouldDisplayReportInLHN({
             report,
@@ -485,7 +488,7 @@ function updateReportsToDisplayInLHN({
             draftComment: reportDraftComment,
             transactions,
             isOffline,
-            isReportArchived: isArchivedReport(reportNameValuePairs?.[`${ONYXKEYS.COLLECTION.REPORT_NAME_VALUE_PAIRS}${report.reportID}`] ?? {}),
+            isReportArchived,
             reportAttributes,
             currentUserLogin,
             currentUserAccountID,
@@ -493,16 +496,19 @@ function updateReportsToDisplayInLHN({
 
         if (shouldDisplay) {
             const requiresAttention = reportAttributes?.[report?.reportID]?.requiresAttention ?? false;
-            const hasAttentionOrError = requiresAttention || hasErrorsOtherThanFailedReceipt;
+            const isUnreadReport = getIsUnreadReportForInboxTab(report, isReportArchived);
+            // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
+            const hasFlags = requiresAttention || hasErrorsOtherThanFailedReceipt || isUnreadReport;
             const existingEntry = displayedReports[reportID];
 
-            if (hasAttentionOrError) {
+            if (hasFlags) {
                 if (
                     existingEntry !== report ||
                     existingEntry?.requiresAttention !== requiresAttention ||
-                    existingEntry?.hasErrorsOtherThanFailedReceipt !== hasErrorsOtherThanFailedReceipt
+                    existingEntry?.hasErrorsOtherThanFailedReceipt !== hasErrorsOtherThanFailedReceipt ||
+                    existingEntry?.isUnreadReport !== isUnreadReport
                 ) {
-                    getMutableCopy()[reportID] = {...report, requiresAttention, hasErrorsOtherThanFailedReceipt};
+                    getMutableCopy()[reportID] = {...report, requiresAttention, hasErrorsOtherThanFailedReceipt, isUnreadReport};
                 }
             } else if (existingEntry !== report) {
                 getMutableCopy()[reportID] = report;
@@ -1486,12 +1492,15 @@ function getRoomWelcomeMessage(
  * The "All" tab returns everything (and still honors Most Recent / Focus mode upstream); the other
  * tabs narrow that same set to unread, expense-related, or direct-message reports.
  */
-function filterReportsForInboxTab(
-    reportIDs: string[],
-    reportsToDisplay: ReportsToDisplayInLHN,
-    activeTab: ValueOf<typeof CONST.INBOX_TAB>,
-    reportNameValuePairs?: OnyxCollection<ReportNameValuePairs>,
-): string[] {
+/**
+ * Whether a report should appear in the "Unread" Inbox tab: it has unread messages and is not muted.
+ * Computed once while building the LHN report set (which is cached/incremental) so the tab filter only reads a flag.
+ */
+function getIsUnreadReportForInboxTab(report: Report, isReportArchived: boolean): boolean {
+    return isUnread(report, undefined, isReportArchived) && getReportNotificationPreference(report) !== CONST.REPORT.NOTIFICATION_PREFERENCE.MUTE;
+}
+
+function filterReportsForInboxTab(reportIDs: string[], reportsToDisplay: ReportsToDisplayInLHN, activeTab: ValueOf<typeof CONST.INBOX_TAB>): string[] {
     if (activeTab === CONST.INBOX_TAB.ALL) {
         return reportIDs;
     }
@@ -1506,10 +1515,8 @@ function filterReportsForInboxTab(
             case CONST.INBOX_TAB.TODO:
                 // Reports with an outstanding GBR (requiresAttention) or RBR (errors) require the user's action.
                 return !!report.requiresAttention || !!report.hasErrorsOtherThanFailedReceipt;
-            case CONST.INBOX_TAB.UNREAD: {
-                const isReportArchived = isArchivedReport(reportNameValuePairs?.[`${ONYXKEYS.COLLECTION.REPORT_NAME_VALUE_PAIRS}${reportID}`]);
-                return isUnread(report, undefined, isReportArchived) && getReportNotificationPreference(report) !== CONST.REPORT.NOTIFICATION_PREFERENCE.MUTE;
-            }
+            case CONST.INBOX_TAB.UNREAD:
+                return !!report.isUnreadReport;
             default:
                 return true;
         }

From a45d7d47d44948185454d10ed3c57cbc5f81241a Mon Sep 17 00:00:00 2001
From: Youssef Lourayad <youssef@expensify.com>
Date: Sun, 31 May 2026 00:00:32 +0000
Subject: [PATCH 070/435] Fix checks

---
 src/styles/index.ts                         | 25 ++++++++++-----------
 tests/unit/useSidebarOrderedReportsTest.tsx |  1 +
 2 files changed, 13 insertions(+), 13 deletions(-)

diff --git a/src/styles/index.ts b/src/styles/index.ts
index 296ade6c010f..1bbd24d798ee 100644
--- a/src/styles/index.ts
+++ b/src/styles/index.ts
@@ -4478,6 +4478,11 @@ const staticStyles = (theme: ThemeColors) =>
             paddingBottom: 4,
         },
 
+        tabTextSmall: {
+            fontSize: variables.fontSizeSmall,
+            lineHeight: 16,
+        },
+
         scrollableTabSelector: {
             flexGrow: 0,
         },
@@ -6351,19 +6356,13 @@ const dynamicStyles = (theme: ThemeColors) =>
                 top: fileTopPosition,
             }) satisfies ViewStyle,
 
-        tabText: (isSelected: boolean, hasIcon = false) =>
-            ({
-                marginLeft: hasIcon ? 8 : 0,
-                ...FontUtils.fontFamily.platform.EXP_NEUE_BOLD,
-                color: isSelected ? theme.text : theme.textSupporting,
-                lineHeight: variables.lineHeightLarge,
-                fontSize: variables.fontSizeLabel,
-            }) satisfies TextStyle,
-
-        tabTextSmall: {
-            fontSize: variables.fontSizeSmall,
-            lineHeight: 16,
-        } satisfies TextStyle,
+        tabText: (isSelected: boolean, hasIcon = false): TextStyle => ({
+            marginLeft: hasIcon ? 8 : 0,
+            ...FontUtils.fontFamily.platform.EXP_NEUE_BOLD,
+            color: isSelected ? theme.text : theme.textSupporting,
+            lineHeight: variables.lineHeightLarge,
+            fontSize: variables.fontSizeLabel,
+        }),
 
         tabBackground: (hovered: boolean, isFocused: boolean, isDisabled: boolean, background: string | Animated.AnimatedInterpolation<string>) => {
             if (isDisabled) {
diff --git a/tests/unit/useSidebarOrderedReportsTest.tsx b/tests/unit/useSidebarOrderedReportsTest.tsx
index 442bd868d9d9..16da3a2ad99a 100644
--- a/tests/unit/useSidebarOrderedReportsTest.tsx
+++ b/tests/unit/useSidebarOrderedReportsTest.tsx
@@ -16,6 +16,7 @@ jest.mock('@libs/SidebarUtils', () => ({
     sortReportsToDisplayInLHN: jest.fn(),
     getReportsToDisplayInLHN: jest.fn(),
     updateReportsToDisplayInLHN: jest.fn(),
+    filterReportsForInboxTab: jest.fn((reportIDs: string[]) => reportIDs),
 }));
 jest.mock('@libs/Navigation/Navigation', () => ({
     getActiveRouteWithoutParams: jest.fn(() => ''),

From 602427880686246a099cbb01afa05484eabe7d3f Mon Sep 17 00:00:00 2001
From: Jakub Korytko <jakub@korytko.me>
Date: Mon, 1 Jun 2026 12:06:38 +0200
Subject: [PATCH 071/435] address PR comments

---
 src/components/ConnectToHRFlow/index.ios.tsx  |  5 ++--
 .../ConnectToHRFlow/index.native.tsx          | 23 ++++++++++++++-----
 src/components/ConnectToHRFlow/types.ts       |  3 +++
 src/pages/workspace/hr/WorkspaceHRPage.tsx    |  1 +
 4 files changed, 24 insertions(+), 8 deletions(-)

diff --git a/src/components/ConnectToHRFlow/index.ios.tsx b/src/components/ConnectToHRFlow/index.ios.tsx
index b84d5ed1d74b..b23f6c79a2bf 100644
--- a/src/components/ConnectToHRFlow/index.ios.tsx
+++ b/src/components/ConnectToHRFlow/index.ios.tsx
@@ -12,7 +12,7 @@ import {getShortLivedAuthTokenURL} from '@userActions/Link';
 import CONST from '@src/CONST';
 import type ConnectToHRFlowProps from './types';
 
-function ConnectToHRFlow({setupLink}: ConnectToHRFlowProps) {
+function ConnectToHRFlow({setupLink, onDone}: ConnectToHRFlowProps) {
     const {translate} = useLocalize();
     const styles = useThemeStyles();
     const hasOpened = useRef(false);
@@ -22,6 +22,7 @@ function ConnectToHRFlow({setupLink}: ConnectToHRFlowProps) {
     const dismiss = () => {
         isDismissed.current = true;
         setIsModalOpen(false);
+        onDone?.();
     };
 
     const openSession = () => {
@@ -41,6 +42,7 @@ function ConnectToHRFlow({setupLink}: ConnectToHRFlowProps) {
             })
             .finally(() => {
                 setIsModalOpen(false);
+                onDone?.();
             });
     };
 
@@ -64,7 +66,6 @@ function ConnectToHRFlow({setupLink}: ConnectToHRFlowProps) {
             <HeaderWithBackButton
                 title={translate('workspace.common.hr')}
                 onBackButtonPress={dismiss}
-                shouldDisplayHelpButton={false}
             />
             <FullPageOfflineBlockingView>
                 <View style={[StyleSheet.absoluteFill, styles.fullScreenLoading]}>
diff --git a/src/components/ConnectToHRFlow/index.native.tsx b/src/components/ConnectToHRFlow/index.native.tsx
index cd6c4040c233..30f7133d7461 100644
--- a/src/components/ConnectToHRFlow/index.native.tsx
+++ b/src/components/ConnectToHRFlow/index.native.tsx
@@ -1,4 +1,4 @@
-import React, {useCallback, useEffect, useRef, useState} from 'react';
+import React, {useEffect, useRef, useState} from 'react';
 import {StyleSheet, View} from 'react-native';
 import {WebView} from 'react-native-webview';
 import type {WebViewOpenWindowEvent} from 'react-native-webview/lib/WebViewTypes';
@@ -13,7 +13,7 @@ import {getShortLivedAuthTokenURL} from '@userActions/Link';
 import CONST from '@src/CONST';
 import type ConnectToHRFlowProps from './types';
 
-function ConnectToHRFlow({setupLink}: ConnectToHRFlowProps) {
+function ConnectToHRFlow({setupLink, onDone}: ConnectToHRFlowProps) {
     const {translate} = useLocalize();
     const styles = useThemeStyles();
     const [isWebViewOpen, setIsWebViewOpen] = useState(true);
@@ -22,14 +22,15 @@ function ConnectToHRFlow({setupLink}: ConnectToHRFlowProps) {
     const [authenticatedUrl, setAuthenticatedUrl] = useState<string | null>(null);
     const [cookiesCleared, setCookiesCleared] = useState(false);
     const hasFetched = useRef(false);
+    const cookieTimerRef = useRef<NodeJS.Timeout | null>(null);
 
-    const fetchAuthUrl = useCallback(() => {
+    const fetchAuthUrl = () => {
         if (hasFetched.current) {
             return;
         }
         hasFetched.current = true;
         getShortLivedAuthTokenURL(setupLink).then(setAuthenticatedUrl);
-    }, [setupLink]);
+    };
 
     const {isOffline} = useNetwork({onReconnect: fetchAuthUrl});
 
@@ -41,6 +42,16 @@ function ConnectToHRFlow({setupLink}: ConnectToHRFlowProps) {
         // eslint-disable-next-line react-hooks/exhaustive-deps -- only fetch once on mount when online
     }, []);
 
+    useEffect(
+        () => () => {
+            if (!cookieTimerRef.current) {
+                return;
+            }
+            clearTimeout(cookieTimerRef.current);
+        },
+        [],
+    );
+
     const renderLoading = () => (
         <View style={[StyleSheet.absoluteFill, styles.fullScreenLoading]}>
             <ActivityIndicator
@@ -63,6 +74,7 @@ function ConnectToHRFlow({setupLink}: ConnectToHRFlowProps) {
             return;
         }
         setIsWebViewOpen(false);
+        onDone?.();
     };
 
     const isReady = cookiesCleared && !!authenticatedUrl;
@@ -77,7 +89,6 @@ function ConnectToHRFlow({setupLink}: ConnectToHRFlowProps) {
             <HeaderWithBackButton
                 title={translate('workspace.common.hr')}
                 onBackButtonPress={handleBackPress}
-                shouldDisplayHelpButton={false}
             />
             <FullPageOfflineBlockingView>
                 <View style={styles.flex1}>
@@ -89,7 +100,7 @@ function ConnectToHRFlow({setupLink}: ConnectToHRFlowProps) {
                                 // Brief delay to ensure the incognito WebView has fully cleared cookies
                                 // before mounting the main WebView. No deterministic completion signal is
                                 // available from the incognito session teardown.
-                                setTimeout(() => setCookiesCleared(true), CONST.MERGE_HR.COOKIE_CLEAR_DELAY_MS);
+                                cookieTimerRef.current = setTimeout(() => setCookiesCleared(true), CONST.MERGE_HR.COOKIE_CLEAR_DELAY_MS);
                             }}
                             style={styles.opacity0}
                         />
diff --git a/src/components/ConnectToHRFlow/types.ts b/src/components/ConnectToHRFlow/types.ts
index 56f5e1be2809..85b230c23ed8 100644
--- a/src/components/ConnectToHRFlow/types.ts
+++ b/src/components/ConnectToHRFlow/types.ts
@@ -1,6 +1,9 @@
 type ConnectToHRFlowProps = {
     /** The URL to open for the HR provider's connection flow */
     setupLink: string;
+
+    /** Called when the flow is dismissed or completed so the parent can unmount the component */
+    onDone?: () => void;
 };
 
 export default ConnectToHRFlowProps;
diff --git a/src/pages/workspace/hr/WorkspaceHRPage.tsx b/src/pages/workspace/hr/WorkspaceHRPage.tsx
index 1f41debc53be..f53dcc47965b 100644
--- a/src/pages/workspace/hr/WorkspaceHRPage.tsx
+++ b/src/pages/workspace/hr/WorkspaceHRPage.tsx
@@ -121,6 +121,7 @@ function WorkspaceHRPage({
                     <ConnectToHRFlow
                         key={activeHRFlow.key}
                         setupLink={activeHRFlow.setupLink}
+                        onDone={() => setActiveHRFlow(undefined)}
                     />
                 )}
                 <HeaderWithBackButton

From efb10fa5a4298afe88a8f554ee437d2cba0e5cb9 Mon Sep 17 00:00:00 2001
From: Youssef Lourayad <youssef@expensify.com>
Date: Mon, 1 Jun 2026 12:53:51 +0000
Subject: [PATCH 072/435] Add count badges

---
 src/hooks/useSidebarOrderedReports.tsx       | 12 ++++++
 src/libs/SidebarUtils.ts                     | 44 ++++++++++++++++----
 src/pages/inbox/sidebar/InboxTabSelector.tsx | 10 +++--
 tests/unit/useSidebarOrderedReportsTest.tsx  |  1 +
 4 files changed, 56 insertions(+), 11 deletions(-)

diff --git a/src/hooks/useSidebarOrderedReports.tsx b/src/hooks/useSidebarOrderedReports.tsx
index 7dd37487b1bd..32f77dd9cb87 100644
--- a/src/hooks/useSidebarOrderedReports.tsx
+++ b/src/hooks/useSidebarOrderedReports.tsx
@@ -36,6 +36,7 @@ type SidebarOrderedReportsStateContextValue = {
     currentReportID: string | undefined;
     chatTabBrickRoad: BrickRoad;
     activeTab: ValueOf<typeof CONST.INBOX_TAB>;
+    inboxTabCounts: Record<ValueOf<typeof CONST.INBOX_TAB>, number>;
 };
 
 type SidebarOrderedReportsActionsContextValue = {
@@ -51,6 +52,11 @@ const SidebarOrderedReportsStateContext = createContext<SidebarOrderedReportsSta
     currentReportID: '',
     chatTabBrickRoad: undefined,
     activeTab: CONST.INBOX_TAB.ALL,
+    inboxTabCounts: {
+        [CONST.INBOX_TAB.ALL]: 0,
+        [CONST.INBOX_TAB.TODO]: 0,
+        [CONST.INBOX_TAB.UNREAD]: 0,
+    },
 });
 
 const SidebarOrderedReportsActionsContext = createContext<SidebarOrderedReportsActionsContextValue>({
@@ -298,6 +304,9 @@ function SidebarOrderedReportsContextProvider({
     // returns everything (still honoring Most Recent / Focus mode from the ordering above).
     const filteredReportIDs = useMemo(() => SidebarUtils.filterReportsForInboxTab(orderedReportIDs, reportsToDisplayInLHN, activeTab), [orderedReportIDs, reportsToDisplayInLHN, activeTab]);
 
+    // The count shown in each tab's badge, derived from the full "All" set (not the currently filtered view).
+    const inboxTabCounts = useMemo(() => SidebarUtils.getInboxTabCounts(orderedReportIDs, reportsToDisplayInLHN), [orderedReportIDs, reportsToDisplayInLHN]);
+
     // Get the actual reports based on the filtered IDs
     const getOrderedReports = useCallback(
         (reportIDs: string[]): OnyxTypes.Report[] => {
@@ -347,6 +356,7 @@ function SidebarOrderedReportsContextProvider({
                 currentReportID: derivedCurrentReportID,
                 chatTabBrickRoad: getChatTabBrickRoad(updatedReportIDs, reportAttributes),
                 activeTab,
+                inboxTabCounts,
             };
         }
 
@@ -356,6 +366,7 @@ function SidebarOrderedReportsContextProvider({
             currentReportID: derivedCurrentReportID,
             chatTabBrickRoad: getChatTabBrickRoad(orderedReportIDs, reportAttributes),
             activeTab,
+            inboxTabCounts,
         };
     }, [
         getOrderedReportIDs,
@@ -367,6 +378,7 @@ function SidebarOrderedReportsContextProvider({
         orderedReports,
         reportAttributes,
         activeTab,
+        inboxTabCounts,
         reportsToDisplayInLHN,
     ]);
 
diff --git a/src/libs/SidebarUtils.ts b/src/libs/SidebarUtils.ts
index 8fda67f74a6b..6fce8796468e 100644
--- a/src/libs/SidebarUtils.ts
+++ b/src/libs/SidebarUtils.ts
@@ -1487,11 +1487,6 @@ function getRoomWelcomeMessage(
     return welcomeMessage;
 }
 
-/**
- * Filters the already-ordered LHN report IDs down to the ones that belong to the active Inbox tab.
- * The "All" tab returns everything (and still honors Most Recent / Focus mode upstream); the other
- * tabs narrow that same set to unread, expense-related, or direct-message reports.
- */
 /**
  * Whether a report should appear in the "Unread" Inbox tab: it has unread messages and is not muted.
  * Computed once while building the LHN report set (which is cached/incremental) so the tab filter only reads a flag.
@@ -1500,6 +1495,16 @@ function getIsUnreadReportForInboxTab(report: Report, isReportArchived: boolean)
     return isUnread(report, undefined, isReportArchived) && getReportNotificationPreference(report) !== CONST.REPORT.NOTIFICATION_PREFERENCE.MUTE;
 }
 
+/** Whether a report belongs in the "To-do" Inbox tab: it has an outstanding GBR (requiresAttention) or RBR (errors). */
+function getIsTodoReportForInboxTab(report: ReportsToDisplayInLHN[string]): boolean {
+    return !!report.requiresAttention || !!report.hasErrorsOtherThanFailedReceipt;
+}
+
+/**
+ * Filters the already-ordered LHN report IDs down to the ones that belong to the active Inbox tab.
+ * The "All" tab returns everything (and still honors Most Recent / Focus mode upstream); the other
+ * tabs narrow that same set to reports requiring action (To-do) or with unread messages (Unread).
+ */
 function filterReportsForInboxTab(reportIDs: string[], reportsToDisplay: ReportsToDisplayInLHN, activeTab: ValueOf<typeof CONST.INBOX_TAB>): string[] {
     if (activeTab === CONST.INBOX_TAB.ALL) {
         return reportIDs;
@@ -1513,8 +1518,7 @@ function filterReportsForInboxTab(reportIDs: string[], reportsToDisplay: Reports
 
         switch (activeTab) {
             case CONST.INBOX_TAB.TODO:
-                // Reports with an outstanding GBR (requiresAttention) or RBR (errors) require the user's action.
-                return !!report.requiresAttention || !!report.hasErrorsOtherThanFailedReceipt;
+                return getIsTodoReportForInboxTab(report);
             case CONST.INBOX_TAB.UNREAD:
                 return !!report.isUnreadReport;
             default:
@@ -1523,6 +1527,31 @@ function filterReportsForInboxTab(reportIDs: string[], reportsToDisplay: Reports
     });
 }
 
+/** Counts how many of the ordered reports fall into each Inbox tab, for the count shown next to each tab label. */
+function getInboxTabCounts(reportIDs: string[], reportsToDisplay: ReportsToDisplayInLHN): Record<ValueOf<typeof CONST.INBOX_TAB>, number> {
+    let todoCount = 0;
+    let unreadCount = 0;
+
+    for (const reportID of reportIDs) {
+        const report = reportsToDisplay[`${ONYXKEYS.COLLECTION.REPORT}${reportID}`];
+        if (!report) {
+            continue;
+        }
+        if (getIsTodoReportForInboxTab(report)) {
+            todoCount++;
+        }
+        if (report.isUnreadReport) {
+            unreadCount++;
+        }
+    }
+
+    return {
+        [CONST.INBOX_TAB.ALL]: reportIDs.length,
+        [CONST.INBOX_TAB.TODO]: todoCount,
+        [CONST.INBOX_TAB.UNREAD]: unreadCount,
+    };
+}
+
 // Exported for unit testing only. Do not use directly in production code.
 export {
     categorizeReportsForLHN as _categorizeReportsForLHN,
@@ -1540,4 +1569,5 @@ export default {
     updateReportsToDisplayInLHN,
     shouldDisplayReportInLHN,
     filterReportsForInboxTab,
+    getInboxTabCounts,
 };
diff --git a/src/pages/inbox/sidebar/InboxTabSelector.tsx b/src/pages/inbox/sidebar/InboxTabSelector.tsx
index 89c44a76b9c0..61196cc2d81d 100644
--- a/src/pages/inbox/sidebar/InboxTabSelector.tsx
+++ b/src/pages/inbox/sidebar/InboxTabSelector.tsx
@@ -9,13 +9,15 @@ import CONST from '@src/CONST';
 
 function InboxTabSelector() {
     const {translate} = useLocalize();
-    const {activeTab} = useSidebarOrderedReportsState();
+    const {activeTab, inboxTabCounts} = useSidebarOrderedReportsState();
     const {setActiveTab} = useSidebarOrderedReportsActions();
 
+    const getBadgeText = (count: number) => (count > 0 ? count.toString() : undefined);
+
     const tabs: TabSelectorBaseItem[] = [
-        {key: CONST.INBOX_TAB.ALL, title: translate('inboxTabs.all')},
-        {key: CONST.INBOX_TAB.TODO, title: translate('inboxTabs.todo')},
-        {key: CONST.INBOX_TAB.UNREAD, title: translate('inboxTabs.unread')},
+        {key: CONST.INBOX_TAB.ALL, title: translate('inboxTabs.all'), badgeText: getBadgeText(inboxTabCounts[CONST.INBOX_TAB.ALL])},
+        {key: CONST.INBOX_TAB.TODO, title: translate('inboxTabs.todo'), badgeText: getBadgeText(inboxTabCounts[CONST.INBOX_TAB.TODO])},
+        {key: CONST.INBOX_TAB.UNREAD, title: translate('inboxTabs.unread'), badgeText: getBadgeText(inboxTabCounts[CONST.INBOX_TAB.UNREAD])},
     ];
 
     return (
diff --git a/tests/unit/useSidebarOrderedReportsTest.tsx b/tests/unit/useSidebarOrderedReportsTest.tsx
index 16da3a2ad99a..aa8d3bf916da 100644
--- a/tests/unit/useSidebarOrderedReportsTest.tsx
+++ b/tests/unit/useSidebarOrderedReportsTest.tsx
@@ -17,6 +17,7 @@ jest.mock('@libs/SidebarUtils', () => ({
     getReportsToDisplayInLHN: jest.fn(),
     updateReportsToDisplayInLHN: jest.fn(),
     filterReportsForInboxTab: jest.fn((reportIDs: string[]) => reportIDs),
+    getInboxTabCounts: jest.fn(() => ({})),
 }));
 jest.mock('@libs/Navigation/Navigation', () => ({
     getActiveRouteWithoutParams: jest.fn(() => ''),

From 31ad82cc1718b5f9fb8544408c19347aa559e12f Mon Sep 17 00:00:00 2001
From: Adam Horodyski <ad.horodyski@gmail.com>
Date: Mon, 1 Jun 2026 14:56:39 +0200
Subject: [PATCH 073/435] SequentialQueue: resolve isReadyPromise when conflict
 empties the queue

push() marks isReadyPromise pending in its sync prelude before awaiting
persistence. If a conflict resolver deletes the only request without
pushing a replacement (e.g. resolveEnableFeatureConflicts on a rapid
feature toggle), flush() exits via the "no requests" early-return without
resolving it, leaving API.read() callers parked on waitForIdle() hanging
until unrelated queue activity releases the stale promise.

Resolve isReadyPromise at that early-return so readiness is always
released when there is nothing to flush.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
---
 src/libs/Network/SequentialQueue.ts | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/src/libs/Network/SequentialQueue.ts b/src/libs/Network/SequentialQueue.ts
index 4ed8c0e40051..5253764a3679 100644
--- a/src/libs/Network/SequentialQueue.ts
+++ b/src/libs/Network/SequentialQueue.ts
@@ -337,6 +337,10 @@ function flush(shouldResetPromise = true) {
 
     if (persistedRequestsLength === 0 && !currentOngoingRequest && !hasOnyxUpdates) {
         Log.info('[SequentialQueue] Unable to flush. No requests or queued Onyx updates to process.');
+        // push() may have marked isReadyPromise pending in its sync prelude (e.g. a conflict
+        // resolver deleted the only request without pushing a replacement). Resolve here so READs
+        // parked on waitForIdle() don't hang until unrelated queue activity releases them.
+        resolveIsReadyPromise?.();
         return;
     }
 

From 2b36db9aa456c41e6d780482c52ba20907135685 Mon Sep 17 00:00:00 2001
From: Youssef Lourayad <youssef@expensify.com>
Date: Mon, 1 Jun 2026 14:03:09 +0000
Subject: [PATCH 074/435] Change copy

---
 src/languages/de.ts                          |  2 +-
 src/languages/en.ts                          |  2 +-
 src/languages/es.ts                          |  2 +-
 src/languages/fr.ts                          |  2 +-
 src/languages/it.ts                          |  2 +-
 src/languages/ja.ts                          |  2 +-
 src/languages/nl.ts                          |  2 +-
 src/languages/pl.ts                          |  2 +-
 src/languages/pt-BR.ts                       |  2 +-
 src/languages/zh-hans.ts                     |  2 +-
 src/pages/inbox/sidebar/InboxTabSelector.tsx | 42 +++++++++++++++-----
 11 files changed, 43 insertions(+), 19 deletions(-)

diff --git a/src/languages/de.ts b/src/languages/de.ts
index e3222cf3a286..6ffbda993d8d 100644
--- a/src/languages/de.ts
+++ b/src/languages/de.ts
@@ -2896,7 +2896,7 @@ ${amount} für ${merchant} – ${date}`,
     },
     inboxTabs: {
         all: 'All',
-        todo: 'To-do',
+        todo: 'To-dos',
         unread: 'Unread',
     },
     reportDetailsPage: {
diff --git a/src/languages/en.ts b/src/languages/en.ts
index 62629563c128..817b74657fda 100644
--- a/src/languages/en.ts
+++ b/src/languages/en.ts
@@ -2967,7 +2967,7 @@ const translations = {
     },
     inboxTabs: {
         all: 'All',
-        todo: 'To-do',
+        todo: 'To-dos',
         unread: 'Unread',
     },
     reportDetailsPage: {
diff --git a/src/languages/es.ts b/src/languages/es.ts
index a222c9dd554d..a5f734aeade3 100644
--- a/src/languages/es.ts
+++ b/src/languages/es.ts
@@ -2775,7 +2775,7 @@ ${amount} para ${merchant} - ${date}`,
     },
     inboxTabs: {
         all: 'All',
-        todo: 'To-do',
+        todo: 'To-dos',
         unread: 'Unread',
     },
     reportDetailsPage: {
diff --git a/src/languages/fr.ts b/src/languages/fr.ts
index 48d1f73eb2dd..75089caf711c 100644
--- a/src/languages/fr.ts
+++ b/src/languages/fr.ts
@@ -2904,7 +2904,7 @@ ${amount} pour ${merchant} - ${date}`,
     },
     inboxTabs: {
         all: 'All',
-        todo: 'To-do',
+        todo: 'To-dos',
         unread: 'Unread',
     },
     reportDetailsPage: {
diff --git a/src/languages/it.ts b/src/languages/it.ts
index 74008d5b625a..b3262b4dc363 100644
--- a/src/languages/it.ts
+++ b/src/languages/it.ts
@@ -2892,7 +2892,7 @@ ${amount} per ${merchant} - ${date}`,
     },
     inboxTabs: {
         all: 'All',
-        todo: 'To-do',
+        todo: 'To-dos',
         unread: 'Unread',
     },
     reportDetailsPage: {
diff --git a/src/languages/ja.ts b/src/languages/ja.ts
index 846c4766166c..5d612b92f598 100644
--- a/src/languages/ja.ts
+++ b/src/languages/ja.ts
@@ -2868,7 +2868,7 @@ ${date} の ${merchant} への ${amount}`,
     },
     inboxTabs: {
         all: 'All',
-        todo: 'To-do',
+        todo: 'To-dos',
         unread: 'Unread',
     },
     reportDetailsPage: {
diff --git a/src/languages/nl.ts b/src/languages/nl.ts
index c522b5421e4e..9797bfd35fde 100644
--- a/src/languages/nl.ts
+++ b/src/languages/nl.ts
@@ -2889,7 +2889,7 @@ ${amount} voor ${merchant} - ${date}`,
     },
     inboxTabs: {
         all: 'All',
-        todo: 'To-do',
+        todo: 'To-dos',
         unread: 'Unread',
     },
     reportDetailsPage: {
diff --git a/src/languages/pl.ts b/src/languages/pl.ts
index 58a4b7b49757..b3d149e4a055 100644
--- a/src/languages/pl.ts
+++ b/src/languages/pl.ts
@@ -2883,7 +2883,7 @@ ${amount} dla ${merchant} - ${date}`,
     },
     inboxTabs: {
         all: 'All',
-        todo: 'To-do',
+        todo: 'To-dos',
         unread: 'Unread',
     },
     reportDetailsPage: {
diff --git a/src/languages/pt-BR.ts b/src/languages/pt-BR.ts
index 0de92a894209..fb2c6aeec2b0 100644
--- a/src/languages/pt-BR.ts
+++ b/src/languages/pt-BR.ts
@@ -2883,7 +2883,7 @@ ${amount} para ${merchant} - ${date}`,
     },
     inboxTabs: {
         all: 'All',
-        todo: 'To-do',
+        todo: 'To-dos',
         unread: 'Unread',
     },
     reportDetailsPage: {
diff --git a/src/languages/zh-hans.ts b/src/languages/zh-hans.ts
index c0641efcf72e..2ee02c1d7e3f 100644
--- a/src/languages/zh-hans.ts
+++ b/src/languages/zh-hans.ts
@@ -2810,7 +2810,7 @@ ${amount}，商户：${merchant} - 日期：${date}`,
     },
     inboxTabs: {
         all: 'All',
-        todo: 'To-do',
+        todo: 'To-dos',
         unread: 'Unread',
     },
     reportDetailsPage: {
diff --git a/src/pages/inbox/sidebar/InboxTabSelector.tsx b/src/pages/inbox/sidebar/InboxTabSelector.tsx
index 61196cc2d81d..c049a6037533 100644
--- a/src/pages/inbox/sidebar/InboxTabSelector.tsx
+++ b/src/pages/inbox/sidebar/InboxTabSelector.tsx
@@ -1,33 +1,57 @@
 import React from 'react';
+import {View} from 'react-native';
 import type {ValueOf} from 'type-fest';
 import TabSelectorBase from '@components/TabSelector/TabSelectorBase';
 import TabSelectorContextProvider from '@components/TabSelector/TabSelectorContext';
 import type {TabSelectorBaseItem} from '@components/TabSelector/types';
 import useLocalize from '@hooks/useLocalize';
 import {useSidebarOrderedReportsActions, useSidebarOrderedReportsState} from '@hooks/useSidebarOrderedReports';
+import useThemeStyles from '@hooks/useThemeStyles';
 import CONST from '@src/CONST';
 
 function InboxTabSelector() {
     const {translate} = useLocalize();
+    const styles = useThemeStyles();
     const {activeTab, inboxTabCounts} = useSidebarOrderedReportsState();
     const {setActiveTab} = useSidebarOrderedReportsActions();
 
     const getBadgeText = (count: number) => (count > 0 ? count.toString() : undefined);
 
     const tabs: TabSelectorBaseItem[] = [
-        {key: CONST.INBOX_TAB.ALL, title: translate('inboxTabs.all'), badgeText: getBadgeText(inboxTabCounts[CONST.INBOX_TAB.ALL])},
-        {key: CONST.INBOX_TAB.TODO, title: translate('inboxTabs.todo'), badgeText: getBadgeText(inboxTabCounts[CONST.INBOX_TAB.TODO])},
-        {key: CONST.INBOX_TAB.UNREAD, title: translate('inboxTabs.unread'), badgeText: getBadgeText(inboxTabCounts[CONST.INBOX_TAB.UNREAD])},
+        {
+            key: CONST.INBOX_TAB.ALL,
+            title: translate('inboxTabs.all'),
+            badgeText: getBadgeText(inboxTabCounts[CONST.INBOX_TAB.ALL]),
+            isBadgeCondensed: true,
+            badgeStyles: styles.inboxTabBadge,
+        },
+        {
+            key: CONST.INBOX_TAB.UNREAD,
+            title: translate('inboxTabs.unread'),
+            badgeText: getBadgeText(inboxTabCounts[CONST.INBOX_TAB.UNREAD]),
+            isBadgeCondensed: true,
+            badgeStyles: styles.inboxTabBadge,
+        },
+        {
+            key: CONST.INBOX_TAB.TODO,
+            title: translate('inboxTabs.todo'),
+            badgeText: getBadgeText(inboxTabCounts[CONST.INBOX_TAB.TODO]),
+            isBadgeCondensed: true,
+            badgeStyles: styles.inboxTabBadge,
+        },
     ];
 
     return (
         <TabSelectorContextProvider activeTabKey={activeTab}>
-            <TabSelectorBase
-                tabs={tabs}
-                activeTabKey={activeTab}
-                onTabPress={(key) => setActiveTab(key as ValueOf<typeof CONST.INBOX_TAB>)}
-                size="small"
-            />
+            <View style={styles.mb2}>
+                <TabSelectorBase
+                    tabs={tabs}
+                    activeTabKey={activeTab}
+                    onTabPress={(key) => setActiveTab(key as ValueOf<typeof CONST.INBOX_TAB>)}
+                    size="small"
+                    equalWidth
+                />
+            </View>
         </TabSelectorContextProvider>
     );
 }

From 7216fe1259c9e2817d24e9ef08b71747179f8312 Mon Sep 17 00:00:00 2001
From: Youssef Lourayad <youssef@expensify.com>
Date: Mon, 1 Jun 2026 14:03:26 +0000
Subject: [PATCH 075/435] Adjust styles

---
 src/components/TabSelector/TabSelectorBase.tsx |  2 ++
 src/components/TabSelector/TabSelectorItem.tsx |  4 ++++
 src/components/TabSelector/types.ts            | 14 +++++++++++++-
 src/styles/index.ts                            | 11 +++++++++--
 4 files changed, 28 insertions(+), 3 deletions(-)

diff --git a/src/components/TabSelector/TabSelectorBase.tsx b/src/components/TabSelector/TabSelectorBase.tsx
index 5f400417248f..03b89482707c 100644
--- a/src/components/TabSelector/TabSelectorBase.tsx
+++ b/src/components/TabSelector/TabSelectorBase.tsx
@@ -125,6 +125,8 @@ function TabSelectorBase({
                         equalWidth={equalWidth}
                         size={size}
                         badgeText={tab.badgeText}
+                        isBadgeCondensed={tab.isBadgeCondensed}
+                        badgeStyles={tab.badgeStyles}
                         pendingAction={tab.pendingAction}
                         isDisabled={tab.isDisabled}
                     />
diff --git a/src/components/TabSelector/TabSelectorItem.tsx b/src/components/TabSelector/TabSelectorItem.tsx
index 47c825b2f2ff..7723d8722750 100644
--- a/src/components/TabSelector/TabSelectorItem.tsx
+++ b/src/components/TabSelector/TabSelectorItem.tsx
@@ -36,6 +36,8 @@ function TabSelectorItem({
     equalWidth = false,
     size,
     badgeText,
+    isBadgeCondensed = false,
+    badgeStyles,
     isDisabled = false,
     pendingAction,
 }: TabSelectorItemProps) {
@@ -98,6 +100,8 @@ function TabSelectorItem({
                 <Badge
                     text={badgeText}
                     success
+                    isCondensed={isBadgeCondensed}
+                    badgeStyles={badgeStyles}
                 />
             )}
         </AnimatedPressableWithFeedback>
diff --git a/src/components/TabSelector/types.ts b/src/components/TabSelector/types.ts
index 20e0d3e0861d..813525bbc8ce 100644
--- a/src/components/TabSelector/types.ts
+++ b/src/components/TabSelector/types.ts
@@ -1,6 +1,6 @@
 import type {MaterialTopTabBarProps} from '@react-navigation/material-top-tabs';
 // eslint-disable-next-line no-restricted-imports
-import type {Animated} from 'react-native';
+import type {Animated, StyleProp, ViewStyle} from 'react-native';
 import type {ThemeColors} from '@styles/theme/types';
 import type {PendingAction} from '@src/types/onyx/OnyxCommon';
 import type IconAsset from '@src/types/utils/IconAsset';
@@ -45,6 +45,12 @@ type TabSelectorBaseItem = WithSentryLabel & {
     /** Text to display on the badge on the tab. */
     badgeText?: string;
 
+    /** Whether the tab's badge should use the condensed (smaller) style. */
+    isBadgeCondensed?: boolean;
+
+    /** Additional styles for the tab's badge. */
+    badgeStyles?: StyleProp<ViewStyle>;
+
     /** Whether this tab is disabled */
     isDisabled?: boolean;
 
@@ -138,6 +144,12 @@ type TabSelectorItemProps = WithSentryLabel & {
     /** Text to display on the badge on the tab. */
     badgeText?: string;
 
+    /** Whether the tab's badge should use the condensed (smaller) style. */
+    isBadgeCondensed?: boolean;
+
+    /** Additional styles for the tab's badge. */
+    badgeStyles?: StyleProp<ViewStyle>;
+
     /** Whether this tab is disabled */
     isDisabled?: boolean;
 
diff --git a/src/styles/index.ts b/src/styles/index.ts
index 1bbd24d798ee..0d8a64abf75a 100644
--- a/src/styles/index.ts
+++ b/src/styles/index.ts
@@ -4474,8 +4474,8 @@ const staticStyles = (theme: ThemeColors) =>
         },
 
         tabSelectorContentContainerSmall: {
-            paddingTop: 4,
-            paddingBottom: 4,
+            paddingTop: 0,
+            paddingBottom: 0,
         },
 
         tabTextSmall: {
@@ -4483,6 +4483,13 @@ const staticStyles = (theme: ThemeColors) =>
             lineHeight: 16,
         },
 
+        inboxTabBadge: {
+            minWidth: 18,
+            height: 16,
+            marginLeft: 4,
+            justifyContent: 'center',
+        },
+
         scrollableTabSelector: {
             flexGrow: 0,
         },

From a81d7a669ea479670b2b3be1d0fe76012bbdb876 Mon Sep 17 00:00:00 2001
From: Youssef Lourayad <youssef@expensify.com>
Date: Mon, 1 Jun 2026 14:24:58 +0000
Subject: [PATCH 076/435] Remove count badge from the "All" tab

---
 src/hooks/useSidebarOrderedReports.tsx       | 3 +--
 src/libs/SidebarUtils.ts                     | 5 ++---
 src/pages/inbox/sidebar/InboxTabSelector.tsx | 3 ---
 3 files changed, 3 insertions(+), 8 deletions(-)

diff --git a/src/hooks/useSidebarOrderedReports.tsx b/src/hooks/useSidebarOrderedReports.tsx
index 32f77dd9cb87..9c9350fa19c6 100644
--- a/src/hooks/useSidebarOrderedReports.tsx
+++ b/src/hooks/useSidebarOrderedReports.tsx
@@ -36,7 +36,7 @@ type SidebarOrderedReportsStateContextValue = {
     currentReportID: string | undefined;
     chatTabBrickRoad: BrickRoad;
     activeTab: ValueOf<typeof CONST.INBOX_TAB>;
-    inboxTabCounts: Record<ValueOf<typeof CONST.INBOX_TAB>, number>;
+    inboxTabCounts: Record<typeof CONST.INBOX_TAB.TODO | typeof CONST.INBOX_TAB.UNREAD, number>;
 };
 
 type SidebarOrderedReportsActionsContextValue = {
@@ -53,7 +53,6 @@ const SidebarOrderedReportsStateContext = createContext<SidebarOrderedReportsSta
     chatTabBrickRoad: undefined,
     activeTab: CONST.INBOX_TAB.ALL,
     inboxTabCounts: {
-        [CONST.INBOX_TAB.ALL]: 0,
         [CONST.INBOX_TAB.TODO]: 0,
         [CONST.INBOX_TAB.UNREAD]: 0,
     },
diff --git a/src/libs/SidebarUtils.ts b/src/libs/SidebarUtils.ts
index 6fce8796468e..f665343db310 100644
--- a/src/libs/SidebarUtils.ts
+++ b/src/libs/SidebarUtils.ts
@@ -1527,8 +1527,8 @@ function filterReportsForInboxTab(reportIDs: string[], reportsToDisplay: Reports
     });
 }
 
-/** Counts how many of the ordered reports fall into each Inbox tab, for the count shown next to each tab label. */
-function getInboxTabCounts(reportIDs: string[], reportsToDisplay: ReportsToDisplayInLHN): Record<ValueOf<typeof CONST.INBOX_TAB>, number> {
+/** Counts how many of the ordered reports fall into the To-do and Unread Inbox tabs, for the count badge shown on each. */
+function getInboxTabCounts(reportIDs: string[], reportsToDisplay: ReportsToDisplayInLHN): Record<typeof CONST.INBOX_TAB.TODO | typeof CONST.INBOX_TAB.UNREAD, number> {
     let todoCount = 0;
     let unreadCount = 0;
 
@@ -1546,7 +1546,6 @@ function getInboxTabCounts(reportIDs: string[], reportsToDisplay: ReportsToDispl
     }
 
     return {
-        [CONST.INBOX_TAB.ALL]: reportIDs.length,
         [CONST.INBOX_TAB.TODO]: todoCount,
         [CONST.INBOX_TAB.UNREAD]: unreadCount,
     };
diff --git a/src/pages/inbox/sidebar/InboxTabSelector.tsx b/src/pages/inbox/sidebar/InboxTabSelector.tsx
index c049a6037533..294a5dd3a2fb 100644
--- a/src/pages/inbox/sidebar/InboxTabSelector.tsx
+++ b/src/pages/inbox/sidebar/InboxTabSelector.tsx
@@ -21,9 +21,6 @@ function InboxTabSelector() {
         {
             key: CONST.INBOX_TAB.ALL,
             title: translate('inboxTabs.all'),
-            badgeText: getBadgeText(inboxTabCounts[CONST.INBOX_TAB.ALL]),
-            isBadgeCondensed: true,
-            badgeStyles: styles.inboxTabBadge,
         },
         {
             key: CONST.INBOX_TAB.UNREAD,

From 41d1e9978223fab2ee4206c99390c94cb9b95c32 Mon Sep 17 00:00:00 2001
From: Adam Grzybowski <adam.grzybowski@swmansion.com>
Date: Mon, 1 Jun 2026 16:28:34 +0200
Subject: [PATCH 077/435] Replace Exclamation icon with ReceiptSearch for
 review expenses widget

---
 assets/images/receipt-search.svg               |  1 +
 .../Icon/chunks/expensify-icons.chunk.ts       |  2 ++
 src/pages/home/ForYouSection/index.tsx         | 18 +++++++++++-------
 tests/ui/ForYouSectionTest.tsx                 | 12 ++++++------
 4 files changed, 20 insertions(+), 13 deletions(-)
 create mode 100644 assets/images/receipt-search.svg

diff --git a/assets/images/receipt-search.svg b/assets/images/receipt-search.svg
new file mode 100644
index 000000000000..bbf36cf9b1df
--- /dev/null
+++ b/assets/images/receipt-search.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20"><path d="M3 1.82c0-.36.44-.54.69-.28l.77.81c.16.17.42.17.58 0l1.17-1.23c.16-.17.42-.17.58 0l1.17 1.23c.16.17.42.17.58 0l1.17-1.23c.16-.17.42-.17.58 0l1.17 1.23c.16.17.42.17.58 0l1.17-1.23c.16-.17.42-.17.58 0l1.17 1.23c.16.17.42.17.58 0l.77-.81c.25-.26.69-.08.69.28v5.24c0 .38-.52.57-.8.32a6.05 6.05 0 0 0-4.03-1.54c-3.38 0-6.12 2.79-6.12 6.24 0 2.08.74 3.12 1.47 4.16.2.28.4.56.58.86.09.15.07.34-.05.47l-1.26 1.32c-.16.17-.42.17-.58 0l-1.17-1.23a.394.394 0 0 0-.58 0l-.77.81a.4.4 0 0 1-.69-.28z"/><path fill-rule="evenodd" d="M12.08 16.16c.76 0 1.48-.21 2.09-.58l3.12 3.12 1.41-1.41-3.12-3.12c.37-.61.58-1.33.58-2.09 0-2.25-1.83-4.08-4.08-4.08S8 9.83 8 12.08s1.83 4.08 4.08 4.08m0-2c1.15 0 2.08-.93 2.08-2.08S13.23 10 12.08 10 10 10.93 10 12.08s.93 2.08 2.08 2.08"/></svg>
\ No newline at end of file
diff --git a/src/components/Icon/chunks/expensify-icons.chunk.ts b/src/components/Icon/chunks/expensify-icons.chunk.ts
index 821fb37ef966..38558ace6f6d 100644
--- a/src/components/Icon/chunks/expensify-icons.chunk.ts
+++ b/src/components/Icon/chunks/expensify-icons.chunk.ts
@@ -204,6 +204,7 @@ import ReceiptMultiple from '@assets/images/receipt-multiple.svg';
 import ReceiptPlaceholderPlus from '@assets/images/receipt-placeholder-plus.svg';
 import ReceiptPlus from '@assets/images/receipt-plus.svg';
 import ReceiptScan from '@assets/images/receipt-scan.svg';
+import ReceiptSearch from '@assets/images/receipt-search.svg';
 import ReceiptSlash from '@assets/images/receipt-slash.svg';
 import Receipt from '@assets/images/receipt.svg';
 import RemoveMembers from '@assets/images/remove-members.svg';
@@ -444,6 +445,7 @@ const Expensicons = {
     ReceiptPlaceholderPlus,
     ReceiptPlus,
     ReceiptScan,
+    ReceiptSearch,
     ReceiptSlash,
     RemoveMembers,
     ReportCopy,
diff --git a/src/pages/home/ForYouSection/index.tsx b/src/pages/home/ForYouSection/index.tsx
index f4f7d537ffd7..9e275e365a79 100644
--- a/src/pages/home/ForYouSection/index.tsx
+++ b/src/pages/home/ForYouSection/index.tsx
@@ -11,6 +11,7 @@ import useThemeStyles from '@hooks/useThemeStyles';
 import Navigation from '@libs/Navigation/Navigation';
 import {buildQueryStringFromFilterFormValues} from '@libs/SearchQueryUtils';
 import type {SkeletonSpanReasonAttributes} from '@libs/telemetry/useSkeletonSpan';
+import colors from '@styles/theme/colors';
 import CONST from '@src/CONST';
 import ONYXKEYS from '@src/ONYXKEYS';
 import ROUTES from '@src/ROUTES';
@@ -31,7 +32,7 @@ function ForYouSection() {
     const [singleReportIDs = EMPTY_TODOS_SINGLE_REPORT_IDS] = useOnyx(ONYXKEYS.DERIVED.TODOS, {selector: todosSingleReportIDsSelector});
     const [flaggedExpensesReview = EMPTY_FLAGGED_EXPENSES_REVIEW] = useOnyx(ONYXKEYS.DERIVED.FLAGGED_EXPENSES, {selector: flaggedExpensesReviewSelector});
 
-    const icons = useMemoizedLazyExpensifyIcons(['Exclamation', 'MoneyBag', 'Send', 'ThumbsUp', 'Export']);
+    const icons = useMemoizedLazyExpensifyIcons(['ReceiptSearch', 'MoneyBag', 'Send', 'ThumbsUp', 'Export']);
 
     const submitCount = reportCounts?.[CONST.SEARCH.SEARCH_KEYS.SUBMIT] ?? 0;
     const approveCount = reportCounts?.[CONST.SEARCH.SEARCH_KEYS.APPROVE] ?? 0;
@@ -88,9 +89,12 @@ function ForYouSection() {
                 {
                     key: 'reviewExpenses',
                     count: flaggedExpensesCount,
-                    icon: icons.Exclamation,
+                    icon: icons.ReceiptSearch,
+                    iconBackgroundColor: colors.tangerine100,
+                    iconFill: colors.tangerine500,
                     translationKey: 'homePage.forYouSection.reviewExpenses' as const,
                     handler: createReviewExpensesHandler(flaggedExpensesReview.firstReportID),
+                    buttonProps: {danger: true} as const,
                 },
                 {
                     key: 'submit',
@@ -137,9 +141,9 @@ function ForYouSection() {
             exportCount,
             flaggedExpensesCount,
             flaggedExpensesReview.firstReportID,
-            icons.Exclamation,
             icons.Export,
             icons.MoneyBag,
+            icons.ReceiptSearch,
             icons.Send,
             icons.ThumbsUp,
             payCount,
@@ -150,16 +154,16 @@ function ForYouSection() {
 
     const renderTodoItems = () => (
         <View style={styles.getForYouSectionContainerStyle(shouldUseNarrowLayout)}>
-            {todoItems.map(({key, count, icon, translationKey, handler}) => (
+            {todoItems.map(({key, count, icon, iconBackgroundColor, iconFill, translationKey, handler, buttonProps}) => (
                 <BaseWidgetItem
                     key={key}
                     icon={icon}
-                    iconBackgroundColor={theme.widgetIconBG}
-                    iconFill={theme.widgetIconFill}
+                    iconBackgroundColor={iconBackgroundColor ?? theme.widgetIconBG}
+                    iconFill={iconFill ?? theme.widgetIconFill}
                     title={translate(translationKey, {count})}
                     ctaText={translate('homePage.forYouSection.begin')}
                     onCtaPress={handler}
-                    buttonProps={{success: true}}
+                    buttonProps={buttonProps ?? {success: true}}
                 />
             ))}
         </View>
diff --git a/tests/ui/ForYouSectionTest.tsx b/tests/ui/ForYouSectionTest.tsx
index 02792c2de4c5..196df710f2be 100644
--- a/tests/ui/ForYouSectionTest.tsx
+++ b/tests/ui/ForYouSectionTest.tsx
@@ -44,7 +44,7 @@ jest.mock('@hooks/useThemeStyles', () =>
 
 jest.mock('@hooks/useTheme', () => jest.fn(() => ({})));
 
-const EXCLAMATION_ASSET = {testID: 'exclamation-icon'};
+const RECEIPT_SEARCH_ASSET = {testID: 'receipt-search-icon'};
 
 jest.mock('@hooks/useLazyAsset', () => ({
     useMemoizedLazyExpensifyIcons: jest.fn(() => ({
@@ -52,7 +52,7 @@ jest.mock('@hooks/useLazyAsset', () => ({
         Send: null,
         ThumbsUp: null,
         Export: null,
-        Exclamation: EXCLAMATION_ASSET,
+        ReceiptSearch: RECEIPT_SEARCH_ASSET,
     })),
     useMemoizedLazyIllustrations: jest.fn(() => ({
         ThumbsUpStars: null,
@@ -226,7 +226,7 @@ describe('ForYouSection', () => {
             expect(titleOrder).toEqual([getChildren(reviewTitle), getChildren(submitTitle), getChildren(approveTitle), getChildren(payTitle), getChildren(exportTitle)]);
         });
 
-        it('exposes a Begin CTA and uses the Exclamation icon asset', async () => {
+        it('exposes a Begin CTA and uses the ReceiptSearch icon asset', async () => {
             await act(async () => {
                 await Onyx.set(ONYXKEYS.DERIVED.TODOS, BASE_TODOS);
                 await Onyx.set(ONYXKEYS.DERIVED.FLAGGED_EXPENSES, {
@@ -240,9 +240,9 @@ describe('ForYouSection', () => {
 
             expect(screen.getByText('Begin')).toBeOnTheScreen();
 
-            // The Exclamation asset should be passed as the `icon` prop on at least one BaseWidgetItem.
-            // We look for any rendered element whose `icon` prop is the EXCLAMATION_ASSET reference.
-            const matchingNodes = unsafeRoot.findAll((node) => node.props && (node.props as {icon?: unknown}).icon === EXCLAMATION_ASSET);
+            // The ReceiptSearch asset should be passed as the `icon` prop on at least one BaseWidgetItem.
+            // We look for any rendered element whose `icon` prop is the RECEIPT_SEARCH_ASSET reference.
+            const matchingNodes = unsafeRoot.findAll((node) => node.props && (node.props as {icon?: unknown}).icon === RECEIPT_SEARCH_ASSET);
             expect(matchingNodes.length).toBeGreaterThan(0);
         });
     });

From a85f0f3f12b8cadc9daf425be77a675c37420357 Mon Sep 17 00:00:00 2001
From: Youssef Lourayad <youssef@expensify.com>
Date: Mon, 1 Jun 2026 14:28:34 +0000
Subject: [PATCH 078/435] Translations update

---
 src/languages/de.ts      |  8 ++------
 src/languages/es.ts      | 12 ++++--------
 src/languages/fr.ts      | 16 ++++++----------
 src/languages/it.ts      | 14 +++++---------
 src/languages/ja.ts      | 10 +++-------
 src/languages/nl.ts      | 10 +++-------
 src/languages/pl.ts      | 10 +++-------
 src/languages/pt-BR.ts   |  8 ++------
 src/languages/zh-hans.ts |  8 ++------
 9 files changed, 30 insertions(+), 66 deletions(-)

diff --git a/src/languages/de.ts b/src/languages/de.ts
index 6ffbda993d8d..a006bca102bc 100644
--- a/src/languages/de.ts
+++ b/src/languages/de.ts
@@ -2892,13 +2892,9 @@ ${amount} für ${merchant} – ${date}`,
     focusModeUpdateModal: {
         title: 'Willkommen im #Fokusmodus!',
         prompt: (priorityModePageUrl: string) =>
-            `Behalte den Überblick, indem du nur ungelesene Chats oder Chats siehst, die deine Aufmerksamkeit benötigen. Keine Sorge, du kannst das jederzeit in den <a href="${priorityModePageUrl}">Einstellungen</a> ändern.`,
-    },
-    inboxTabs: {
-        all: 'All',
-        todo: 'To-dos',
-        unread: 'Unread',
+            `Behalten Sie den Überblick, indem Sie nur ungelesene Chats oder Chats anzeigen, die Ihre Aufmerksamkeit erfordern. Keine Sorge, Sie können dies jederzeit in den <a href="${priorityModePageUrl}">Einstellungen</a> ändern.`,
     },
+    inboxTabs: {all: 'Alle', todo: 'To-dos', unread: 'Ungelesen'},
     reportDetailsPage: {
         inWorkspace: (policyName: string) => `in ${policyName}`,
         generatingPDF: 'PDF erstellen',
diff --git a/src/languages/es.ts b/src/languages/es.ts
index a5f734aeade3..75d8450d23d7 100644
--- a/src/languages/es.ts
+++ b/src/languages/es.ts
@@ -2769,15 +2769,11 @@ ${amount} para ${merchant} - ${date}`,
         },
     },
     focusModeUpdateModal: {
-        title: '¡Bienvenido al modo #concentración!',
-        prompt: (priorityModePageUrl) =>
-            `Mantente al tanto de todo viendo sólo los chats no leídos o los que necesitan tu atención. No te preocupes, puedes cambiar el ajuste en cualquier momento desde la <a href="${priorityModePageUrl}">configuración</a>.`,
-    },
-    inboxTabs: {
-        all: 'All',
-        todo: 'To-dos',
-        unread: 'Unread',
+        title: '¡Bienvenido al modo #focus!',
+        prompt: (priorityModePageUrl: string) =>
+            `Mantente al tanto de todo viendo solo los chats sin leer o los chats que necesitan tu atención. No te preocupes, puedes cambiar esto en cualquier momento en los <a href="${priorityModePageUrl}">ajustes</a>.`,
     },
+    inboxTabs: {all: 'Todo', todo: 'Tareas pendientes', unread: 'Sin leer'},
     reportDetailsPage: {
         inWorkspace: (policyName) => `en ${policyName}`,
         generatingPDF: 'Generar PDF',
diff --git a/src/languages/fr.ts b/src/languages/fr.ts
index 75089caf711c..f193a2ddae59 100644
--- a/src/languages/fr.ts
+++ b/src/languages/fr.ts
@@ -2814,9 +2814,9 @@ ${amount} pour ${merchant} - ${date}`,
         title: 'Modifier l’agent',
         agentName: 'Nom de l’agent',
         instructions: 'Écrire des instructions personnalisées',
-        chatWithAgent: 'Discuter avec l\u2019agent',
+        chatWithAgent: 'Discuter avec l’agent',
         copilotIntoAccount: 'Copilote dans le compte',
-        deleteAgent: 'Supprimer l\u2019agent',
+        deleteAgent: 'Supprimer l’agent',
         deleteAgentTitle: 'Supprimer l’agent ?',
         deleteAgentMessage: 'Voulez-vous vraiment supprimer cet agent ? Cette action est irréversible.',
     },
@@ -2898,15 +2898,11 @@ ${amount} pour ${merchant} - ${date}`,
         },
     },
     focusModeUpdateModal: {
-        title: 'Bienvenue en mode #focus !',
+        title: 'Bienvenue dans le mode #focus !',
         prompt: (priorityModePageUrl: string) =>
-            `Gardez le contrôle en affichant uniquement les discussions non lues ou celles qui nécessitent votre attention. Ne vous inquiétez pas, vous pouvez modifier ce paramètre à tout moment dans les <a href="${priorityModePageUrl}">paramètres</a>.`,
-    },
-    inboxTabs: {
-        all: 'All',
-        todo: 'To-dos',
-        unread: 'Unread',
+            `Gardez le contrôle en n’affichant que les discussions non lues ou celles qui nécessitent votre attention. Ne vous inquiétez pas, vous pouvez modifier ce réglage à tout moment dans les <a href="${priorityModePageUrl}">paramètres</a>.`,
     },
+    inboxTabs: {all: 'Tout', todo: 'Tâches à faire', unread: 'Non lu'},
     reportDetailsPage: {
         inWorkspace: (policyName: string) => `dans ${policyName}`,
         generatingPDF: 'Générer le PDF',
@@ -2989,7 +2985,7 @@ ${amount} pour ${merchant} - ${date}`,
         phoneOrEmail: 'Téléphone ou e-mail',
         error: {
             agentSignInBlocked:
-                'Les comptes d\u2019agent ne permettent pas de se connecter directement. Pour utiliser un agent, connectez-vous avec votre propre compte et accédez-y via Copilot.',
+                'Les comptes d’agent ne permettent pas de se connecter directement. Pour utiliser un agent, connectez-vous avec votre propre compte et accédez-y via Copilot.',
             invalidFormatEmailLogin: 'L’adresse e-mail saisie est invalide. Veuillez corriger le format et réessayer.',
         },
         cannotGetAccountDetails: 'Impossible de récupérer les détails du compte. Veuillez essayer de vous reconnecter.',
diff --git a/src/languages/it.ts b/src/languages/it.ts
index b3262b4dc363..a28298ae0973 100644
--- a/src/languages/it.ts
+++ b/src/languages/it.ts
@@ -2802,8 +2802,8 @@ ${amount} per ${merchant} - ${date}`,
         title: 'Modifica agente',
         agentName: 'Nome agente',
         instructions: 'Scrivi istruzioni personalizzate',
-        chatWithAgent: 'Chatta con l\u2019agente',
-        copilotIntoAccount: 'Copilot nell\u2019account',
+        chatWithAgent: 'Chatta con l’agente',
+        copilotIntoAccount: 'Copilot nell’account',
         deleteAgent: 'Elimina agente',
         deleteAgentTitle: 'Eliminare agente?',
         deleteAgentMessage: 'Sei sicuro di voler eliminare questo agente? Questa azione non può essere annullata.',
@@ -2886,15 +2886,11 @@ ${amount} per ${merchant} - ${date}`,
         },
     },
     focusModeUpdateModal: {
-        title: 'Benvenuto/a nella modalità #focus!',
+        title: 'Benvenuto nella modalità #focus!',
         prompt: (priorityModePageUrl: string) =>
-            `Resta sempre aggiornato vedendo solo le chat non lette o quelle che richiedono la tua attenzione. Non preoccuparti, puoi modificare questa impostazione in qualsiasi momento nelle <a href="${priorityModePageUrl}">impostazioni</a>.`,
-    },
-    inboxTabs: {
-        all: 'All',
-        todo: 'To-dos',
-        unread: 'Unread',
+            `Tieniti sempre aggiornato vedendo solo le chat non lette o quelle che richiedono la tua attenzione. Non preoccuparti, puoi cambiare questa impostazione in qualsiasi momento nelle <a href="${priorityModePageUrl}">impostazioni</a>.`,
     },
+    inboxTabs: {all: 'Tutto', todo: 'Attività da fare', unread: 'Non letti'},
     reportDetailsPage: {
         inWorkspace: (policyName: string) => `in ${policyName}`,
         generatingPDF: 'Genera PDF',
diff --git a/src/languages/ja.ts b/src/languages/ja.ts
index 5d612b92f598..dc575c058d53 100644
--- a/src/languages/ja.ts
+++ b/src/languages/ja.ts
@@ -2862,15 +2862,11 @@ ${date} の ${merchant} への ${amount}`,
         },
     },
     focusModeUpdateModal: {
-        title: '#focusモードへようこそ！',
+        title: '#focus モードへようこそ！',
         prompt: (priorityModePageUrl: string) =>
-            `未読のチャットや対応が必要なチャットだけを表示して、常に状況を把握しましょう。いつでも<a href="${priorityModePageUrl}">設定</a>から変更できます。`,
-    },
-    inboxTabs: {
-        all: 'All',
-        todo: 'To-dos',
-        unread: 'Unread',
+            `未読のチャットや対応が必要なチャットだけを表示して、状況を常に把握しましょう。<a href="${priorityModePageUrl}">設定</a>から、いつでもこの設定を変更できます。`,
     },
+    inboxTabs: {all: 'すべて', todo: 'To-do リスト', unread: '未読'},
     reportDetailsPage: {
         inWorkspace: (policyName: string) => `${policyName} 内`,
         generatingPDF: 'PDFを生成',
diff --git a/src/languages/nl.ts b/src/languages/nl.ts
index 9797bfd35fde..fb26f2494b1b 100644
--- a/src/languages/nl.ts
+++ b/src/languages/nl.ts
@@ -2883,15 +2883,11 @@ ${amount} voor ${merchant} - ${date}`,
         },
     },
     focusModeUpdateModal: {
-        title: 'Welkom bij de #focus-modus!',
+        title: 'Welkom in de #focus-modus!',
         prompt: (priorityModePageUrl: string) =>
-            `Houd het overzicht door alleen ongelezen chats of chats die je aandacht nodig hebben te zien. Geen zorgen, je kunt dit op elk moment wijzigen in de <a href="${priorityModePageUrl}">instellingen</a>.`,
-    },
-    inboxTabs: {
-        all: 'All',
-        todo: 'To-dos',
-        unread: 'Unread',
+            `Blijf alles bij door alleen ongelezen chats of chats te zien die je aandacht nodig hebben. Geen zorgen, je kunt dit op elk moment wijzigen in de <a href="${priorityModePageUrl}">instellingen</a>.`,
     },
+    inboxTabs: {all: 'Alles', todo: 'To-do’s', unread: 'Ongelezen'},
     reportDetailsPage: {
         inWorkspace: (policyName: string) => `in ${policyName}`,
         generatingPDF: 'PDF genereren',
diff --git a/src/languages/pl.ts b/src/languages/pl.ts
index b3d149e4a055..4d982df7ad57 100644
--- a/src/languages/pl.ts
+++ b/src/languages/pl.ts
@@ -2877,15 +2877,11 @@ ${amount} dla ${merchant} - ${date}`,
         },
     },
     focusModeUpdateModal: {
-        title: 'Witamy w trybie #focus!',
+        title: 'Witaj w trybie #focus!',
         prompt: (priorityModePageUrl: string) =>
-            `Miej wszystko pod kontrolą, wyświetlając tylko nieprzeczytane czaty lub czaty wymagające Twojej uwagi. Nie martw się, możesz to zmienić w dowolnym momencie w <a href="${priorityModePageUrl}">ustawieniach</a>.`,
-    },
-    inboxTabs: {
-        all: 'All',
-        todo: 'To-dos',
-        unread: 'Unread',
+            `Bądź na bieżąco, pokazując tylko nieprzeczytane czaty lub czaty wymagające twojej uwagi. Spokojnie, możesz to zmienić w każdej chwili w <a href="${priorityModePageUrl}">ustawieniach</a>.`,
     },
+    inboxTabs: {all: 'Wszystkie', todo: 'Zadania', unread: 'Nieprzeczytane'},
     reportDetailsPage: {
         inWorkspace: (policyName: string) => `w ${policyName}`,
         generatingPDF: 'Wygeneruj PDF',
diff --git a/src/languages/pt-BR.ts b/src/languages/pt-BR.ts
index fb2c6aeec2b0..a87b31515b8b 100644
--- a/src/languages/pt-BR.ts
+++ b/src/languages/pt-BR.ts
@@ -2879,13 +2879,9 @@ ${amount} para ${merchant} - ${date}`,
     focusModeUpdateModal: {
         title: 'Bem-vindo ao modo #focus!',
         prompt: (priorityModePageUrl: string) =>
-            `Mantenha tudo sob controle vendo apenas os chats não lidos ou que precisam da sua atenção. Não se preocupe, você pode alterar isso a qualquer momento em <a href="${priorityModePageUrl}">configurações</a>.`,
-    },
-    inboxTabs: {
-        all: 'All',
-        todo: 'To-dos',
-        unread: 'Unread',
+            `Fique por dentro de tudo vendo apenas os chats não lidos ou que precisam da sua atenção. Não se preocupe, você pode mudar isso a qualquer momento em <a href="${priorityModePageUrl}">configurações</a>.`,
     },
+    inboxTabs: {all: 'Tudo', todo: 'Tarefas', unread: 'Não lidas'},
     reportDetailsPage: {
         inWorkspace: (policyName: string) => `em ${policyName}`,
         generatingPDF: 'Gerar PDF',
diff --git a/src/languages/zh-hans.ts b/src/languages/zh-hans.ts
index 2ee02c1d7e3f..ed45e36029f5 100644
--- a/src/languages/zh-hans.ts
+++ b/src/languages/zh-hans.ts
@@ -2806,13 +2806,9 @@ ${amount}，商户：${merchant} - 日期：${date}`,
     },
     focusModeUpdateModal: {
         title: '欢迎进入 #focus 模式！',
-        prompt: (priorityModePageUrl: string) => `通过仅查看未读聊天或需要你关注的聊天来随时掌握进展。别担心，你可以随时在<a href="${priorityModePageUrl}">设置</a>中更改此项。`,
-    },
-    inboxTabs: {
-        all: 'All',
-        todo: 'To-dos',
-        unread: 'Unread',
+        prompt: (priorityModePageUrl: string) => `只查看未读或需要你关注的聊天，时刻掌握最新进展。别担心，你随时可以在<a href="${priorityModePageUrl}">设置</a>中更改此项。`,
     },
+    inboxTabs: {all: '全部', todo: '待办事项', unread: '未读'},
     reportDetailsPage: {
         inWorkspace: (policyName: string) => `在 ${policyName} 中`,
         generatingPDF: '生成 PDF',

From f69688b16412101bd5348476efebb494b592dd5c Mon Sep 17 00:00:00 2001
From: krishna2323 <belivethatkg@gmail.com>
Date: Mon, 1 Jun 2026 20:54:21 +0530
Subject: [PATCH 079/435] fix: Remove header border-bottom when expanded on
 narrow screens, fix children container gap

Signed-off-by: krishna2323 <belivethatkg@gmail.com>
---
 src/components/Search/SearchList/ListItem/GroupHeader.tsx | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/components/Search/SearchList/ListItem/GroupHeader.tsx b/src/components/Search/SearchList/ListItem/GroupHeader.tsx
index 0e14042e1169..a7e766651e57 100644
--- a/src/components/Search/SearchList/ListItem/GroupHeader.tsx
+++ b/src/components/Search/SearchList/ListItem/GroupHeader.tsx
@@ -424,7 +424,7 @@ function GroupHeader({
                         : [
                               isFirstItem && [styles.tableTopRadius, styles.overflowHidden],
                               isLastItemCollapsed && [styles.tableBottomRadius, styles.overflowHidden],
-                              !isLastItemCollapsed && StyleUtils.getSelectedBorderBottomStyle(isItemSelected),
+                              !isLastItemCollapsed && !isExpanded && StyleUtils.getSelectedBorderBottomStyle(isItemSelected),
                           ],
                 ]}
             >

From a09c8e269062e651f7a27bb5a38f136b6d5be5f8 Mon Sep 17 00:00:00 2001
From: krishna2323 <belivethatkg@gmail.com>
Date: Mon, 1 Jun 2026 21:10:13 +0530
Subject: [PATCH 080/435] Scope sticky header changes to large screen width
 only, revert narrow-screen regressions

Signed-off-by: krishna2323 <belivethatkg@gmail.com>
---
 .../ListItem/TransactionGroupListItem.tsx     | 24 ++++++++++---------
 src/components/Search/SearchList/index.tsx    | 24 ++++++++++---------
 2 files changed, 26 insertions(+), 22 deletions(-)

diff --git a/src/components/Search/SearchList/ListItem/TransactionGroupListItem.tsx b/src/components/Search/SearchList/ListItem/TransactionGroupListItem.tsx
index f8fdcde1b50d..72d8fd1657da 100644
--- a/src/components/Search/SearchList/ListItem/TransactionGroupListItem.tsx
+++ b/src/components/Search/SearchList/ListItem/TransactionGroupListItem.tsx
@@ -164,7 +164,9 @@ function TransactionGroupListItem<TItem extends ListItem>({
     const isSelectAllChecked = isEmptyReportSelected || (selectedItemsLength === transactionsWithoutPendingDelete.length && transactionsWithoutPendingDelete.length > 0);
     const isIndeterminate = selectedItemsLength > 0 && selectedItemsLength !== transactionsWithoutPendingDelete.length;
 
+    // Currently only the transaction report groups have transactions where the empty view makes sense
     const shouldDisplayEmptyView = isEmpty && isExpenseReportType;
+    const isDisabledOrEmpty = isEmpty || isDisabled;
 
     const refreshTransactions = () => {
         if (!groupItem.transactionsQueryJSON) {
@@ -276,7 +278,7 @@ function TransactionGroupListItem<TItem extends ListItem>({
     };
 
     const onPress = (event?: ModifiedMouseEvent) => {
-        if (isExpenseReportType) {
+        if (isExpenseReportType || transactions.length === 0) {
             onSelectRow(item, transactionPreviewData, event);
         }
         if (!isExpenseReportType) {
@@ -311,7 +313,7 @@ function TransactionGroupListItem<TItem extends ListItem>({
                 <MemberListItemHeader
                     member={groupItem as TransactionMemberGroupListItemType}
                     onCheckboxPress={handleSelectionButtonPress}
-                    isDisabled={isDisabled}
+                    isDisabled={isDisabledOrEmpty}
                     columns={columns}
                     canSelectMultiple={canSelectMultiple}
                     isSelectAllChecked={isSelectAllChecked}
@@ -325,7 +327,7 @@ function TransactionGroupListItem<TItem extends ListItem>({
                 <CardListItemHeader
                     card={groupItem as TransactionCardGroupListItemType}
                     onCheckboxPress={handleSelectionButtonPress}
-                    isDisabled={isDisabled}
+                    isDisabled={isDisabledOrEmpty}
                     columns={columns}
                     isFocused={isFocused}
                     canSelectMultiple={canSelectMultiple}
@@ -339,7 +341,7 @@ function TransactionGroupListItem<TItem extends ListItem>({
                 <WithdrawalIDListItemHeader
                     withdrawalID={groupItem as TransactionWithdrawalIDGroupListItemType}
                     onCheckboxPress={handleSelectionButtonPress}
-                    isDisabled={isDisabled}
+                    isDisabled={isDisabledOrEmpty}
                     columns={columns}
                     canSelectMultiple={canSelectMultiple}
                     isSelectAllChecked={isSelectAllChecked}
@@ -352,7 +354,7 @@ function TransactionGroupListItem<TItem extends ListItem>({
                 <CategoryListItemHeader
                     category={groupItem as TransactionCategoryGroupListItemType}
                     onCheckboxPress={handleSelectionButtonPress}
-                    isDisabled={isDisabled}
+                    isDisabled={isDisabledOrEmpty}
                     columns={columns}
                     canSelectMultiple={canSelectMultiple}
                     isSelectAllChecked={isSelectAllChecked}
@@ -365,7 +367,7 @@ function TransactionGroupListItem<TItem extends ListItem>({
                 <MerchantListItemHeader
                     merchant={groupItem as TransactionMerchantGroupListItemType}
                     onCheckboxPress={handleSelectionButtonPress}
-                    isDisabled={isDisabled}
+                    isDisabled={isDisabledOrEmpty}
                     columns={columns}
                     canSelectMultiple={canSelectMultiple}
                     isSelectAllChecked={isSelectAllChecked}
@@ -378,7 +380,7 @@ function TransactionGroupListItem<TItem extends ListItem>({
                 <TagListItemHeader
                     tag={groupItem as TransactionTagGroupListItemType}
                     onCheckboxPress={handleSelectionButtonPress}
-                    isDisabled={isDisabled}
+                    isDisabled={isDisabledOrEmpty}
                     columns={columns}
                     canSelectMultiple={canSelectMultiple}
                     isSelectAllChecked={isSelectAllChecked}
@@ -391,7 +393,7 @@ function TransactionGroupListItem<TItem extends ListItem>({
                 <MonthListItemHeader
                     month={groupItem as TransactionMonthGroupListItemType}
                     onCheckboxPress={handleSelectionButtonPress}
-                    isDisabled={isDisabled}
+                    isDisabled={isDisabledOrEmpty}
                     columns={columns}
                     canSelectMultiple={canSelectMultiple}
                     isSelectAllChecked={isSelectAllChecked}
@@ -404,7 +406,7 @@ function TransactionGroupListItem<TItem extends ListItem>({
                 <WeekListItemHeader
                     week={groupItem as TransactionWeekGroupListItemType}
                     onCheckboxPress={handleSelectionButtonPress}
-                    isDisabled={isDisabled}
+                    isDisabled={isDisabledOrEmpty}
                     columns={columns}
                     canSelectMultiple={canSelectMultiple}
                     isSelectAllChecked={isSelectAllChecked}
@@ -417,7 +419,7 @@ function TransactionGroupListItem<TItem extends ListItem>({
                 <YearListItemHeader
                     year={groupItem as TransactionYearGroupListItemType}
                     onCheckboxPress={handleSelectionButtonPress}
-                    isDisabled={isDisabled}
+                    isDisabled={isDisabledOrEmpty}
                     columns={columns}
                     canSelectMultiple={canSelectMultiple}
                     isSelectAllChecked={isSelectAllChecked}
@@ -430,7 +432,7 @@ function TransactionGroupListItem<TItem extends ListItem>({
                 <QuarterListItemHeader
                     quarter={groupItem as TransactionQuarterGroupListItemType}
                     onCheckboxPress={handleSelectionButtonPress}
-                    isDisabled={isDisabled}
+                    isDisabled={isDisabledOrEmpty}
                     columns={columns}
                     canSelectMultiple={canSelectMultiple}
                     isSelectAllChecked={isSelectAllChecked}
diff --git a/src/components/Search/SearchList/index.tsx b/src/components/Search/SearchList/index.tsx
index 9f09905b37ec..1d2f1a26336e 100644
--- a/src/components/Search/SearchList/index.tsx
+++ b/src/components/Search/SearchList/index.tsx
@@ -236,11 +236,11 @@ function SearchList({
         return data;
     }, [data, groupBy, type]);
     const emptyReports = useMemo(() => {
-        if (isTransactionGroupListItemArray(data)) {
-            return data.filter((item) => item.transactions.length === 0 && item.keyForList);
+        if (type === CONST.SEARCH.DATA_TYPES.EXPENSE_REPORT && isTransactionGroupListItemArray(data)) {
+            return data.filter((item) => item.transactions.length === 0);
         }
         return [];
-    }, [data]);
+    }, [data, type]);
 
     const selectedItemsLength = useMemo(() => {
         const selectedTransactionsCount = flattenedItems.reduce((acc, item) => {
@@ -248,7 +248,7 @@ function SearchList({
             return acc + (isTransactionSelected ? 1 : 0);
         }, 0);
 
-        if (isTransactionGroupListItemArray(data)) {
+        if (type === CONST.SEARCH.DATA_TYPES.EXPENSE_REPORT && isTransactionGroupListItemArray(data)) {
             const selectedEmptyReports = emptyReports.reduce((acc, item) => {
                 const isEmptyReportSelected = !!(item.keyForList && selectedTransactions[item.keyForList]?.isSelected);
                 return acc + (isEmptyReportSelected ? 1 : 0);
@@ -258,10 +258,10 @@ function SearchList({
         }
 
         return selectedTransactionsCount;
-    }, [flattenedItems, data, emptyReports, selectedTransactions]);
+    }, [flattenedItems, type, data, emptyReports, selectedTransactions]);
 
     const totalItems = useMemo(() => {
-        if (isTransactionGroupListItemArray(data)) {
+        if (type === CONST.SEARCH.DATA_TYPES.EXPENSE_REPORT && isTransactionGroupListItemArray(data)) {
             const selectableEmptyReports = emptyReports.filter((item) => item.pendingAction !== CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE);
             const selectableTransactions = flattenedItems.filter((item) => {
                 if ('pendingAction' in item) {
@@ -279,7 +279,7 @@ function SearchList({
             return true;
         });
         return selectableTransactions.length;
-    }, [data, flattenedItems, emptyReports]);
+    }, [data, type, flattenedItems, emptyReports]);
 
     const {translate} = useLocalize();
     const {isOffline} = useNetwork();
@@ -313,15 +313,17 @@ function SearchList({
         });
     }, []);
 
+    const shouldSplitGroups = isGroupByActive && isLargeScreenWidth;
+
     const {splitData: listData, stickyHeaderIndices} = useMemo(() => {
-        if (!isGroupByActive) {
+        if (!shouldSplitGroups) {
             return {splitData: data, stickyHeaderIndices: undefined};
         }
         return splitGroupsIntoPairs(data);
-    }, [data, isGroupByActive]);
+    }, [data, shouldSplitGroups]);
 
     const getItemType = useMemo(() => {
-        if (!isGroupByActive) {
+        if (!shouldSplitGroups) {
             return undefined;
         }
         return (item: SearchListItem) => {
@@ -330,7 +332,7 @@ function SearchList({
             }
             return 'default';
         };
-    }, [isGroupByActive]);
+    }, [shouldSplitGroups]);
 
     const [lastPaymentMethod] = useOnyx(ONYXKEYS.NVP_LAST_PAYMENT_METHOD);
     const [personalPolicyID] = useOnyx(ONYXKEYS.PERSONAL_POLICY_ID);

From cbafec93556aab2533ea7135a69c3352bdee8a68 Mon Sep 17 00:00:00 2001
From: jayeshmangwani <jayeshmangwani@gmail.com>
Date: Mon, 1 Jun 2026 21:12:03 +0530
Subject: [PATCH 081/435] added mark as done button when expense on hold

---
 src/hooks/useLifecycleActions.tsx          | 5 ++++-
 src/hooks/useSelectionModeReportActions.ts | 7 +++++--
 2 files changed, 9 insertions(+), 3 deletions(-)

diff --git a/src/hooks/useLifecycleActions.tsx b/src/hooks/useLifecycleActions.tsx
index d53d292ee079..796ba9475e63 100644
--- a/src/hooks/useLifecycleActions.tsx
+++ b/src/hooks/useLifecycleActions.tsx
@@ -1,4 +1,5 @@
 import {delegateEmailSelector} from '@selectors/Account';
+import {isTrackIntentUserSelector} from '@selectors/Onboarding';
 import React from 'react';
 import {useDelegateNoAccessActions, useDelegateNoAccessState} from '@components/DelegateNoAccessModalProvider';
 import type {ActionHandledType} from '@components/Modal/Global/HoldMenuModalWrapper';
@@ -18,6 +19,7 @@ import {
     isExported as isExportedUtils,
     isReportOwner,
     shouldBlockSubmitDueToStrictPolicyRules,
+    shouldShowMarkAsDone,
 } from '@libs/ReportUtils';
 import {hasAnyPendingRTERViolation as hasAnyPendingRTERViolationTransactionUtils, hasOnlyPendingCardTransactions, showPendingCardTransactionsBlockModal} from '@libs/TransactionUtils';
 import {cancelPayment, markReportPaymentReceived} from '@userActions/IOU/PayMoneyRequest';
@@ -71,6 +73,7 @@ function useLifecycleActions({reportID, startApprovedAnimation, startAnimation,
     const [amountOwed] = useOnyx(ONYXKEYS.NVP_PRIVATE_AMOUNT_OWED);
     const [ownerBillingGracePeriodEnd] = useOnyx(ONYXKEYS.NVP_PRIVATE_OWNER_BILLING_GRACE_PERIOD_END);
     const [delegateEmail] = useOnyx(ONYXKEYS.ACCOUNT, {selector: delegateEmailSelector});
+    const [isTrackIntentUser] = useOnyx(ONYXKEYS.NVP_INTRO_SELECTED, {selector: isTrackIntentUserSelector});
 
     const {reportActions: unfilteredReportActions} = usePaginatedReportActions(moneyRequestReport?.reportID);
     const reportActions = getFilteredReportActionsForReportView(unfilteredReportActions);
@@ -228,7 +231,7 @@ function useLifecycleActions({reportID, startApprovedAnimation, startAnimation,
     const actions: Record<string, SecondaryActionEntry> = {
         [CONST.REPORT.SECONDARY_ACTIONS.SUBMIT]: {
             value: CONST.REPORT.SECONDARY_ACTIONS.SUBMIT,
-            text: translate('common.submit'),
+            text: shouldShowMarkAsDone({policy, report: moneyRequestReport, isTrackIntentUser}) ? translate('common.markAsDone') : translate('common.submit'),
             icon: expensifyIcons.Send,
             sentryLabel: CONST.SENTRY_LABEL.MORE_MENU.SUBMIT,
             onSelected: () => {
diff --git a/src/hooks/useSelectionModeReportActions.ts b/src/hooks/useSelectionModeReportActions.ts
index 6da23083973c..e549dcc77f34 100644
--- a/src/hooks/useSelectionModeReportActions.ts
+++ b/src/hooks/useSelectionModeReportActions.ts
@@ -1,5 +1,5 @@
 import {delegateEmailSelector, isUserValidatedSelector} from '@selectors/Account';
-import {hasSeenTourSelector} from '@selectors/Onboarding';
+import {hasSeenTourSelector, isTrackIntentUserSelector} from '@selectors/Onboarding';
 import truncate from 'lodash/truncate';
 import {useContext, useEffect, useRef, useState} from 'react';
 // eslint-disable-next-line no-restricted-imports
@@ -38,6 +38,7 @@ import {
     isIOUReport as isIOUReportUtil,
     isReportOwner,
     shouldBlockSubmitDueToStrictPolicyRules,
+    shouldShowMarkAsDone,
 } from '@libs/ReportUtils';
 import {hasAnyPendingRTERViolation as hasAnyPendingRTERViolationTransactionUtils, hasOnlyPendingCardTransactions, showPendingCardTransactionsBlockModal} from '@libs/TransactionUtils';
 import {markPendingRTERTransactionsAsCash} from '@userActions/Transaction';
@@ -127,6 +128,8 @@ function useSelectionModeReportActions({
     const [invoiceReceiverPolicy] = useOnyx(
         `${ONYXKEYS.COLLECTION.POLICY}${chatReport?.invoiceReceiver && 'policyID' in chatReport.invoiceReceiver ? chatReport.invoiceReceiver.policyID : undefined}`,
     );
+    const [isTrackIntentUser] = useOnyx(ONYXKEYS.NVP_INTRO_SELECTED, {selector: isTrackIntentUserSelector});
+
     const existingB2BInvoiceReport = useParticipantsInvoiceReport(activePolicyID, CONST.REPORT.INVOICE_RECEIVER_TYPE.BUSINESS, chatReport?.policyID);
     const activeAdminPolicies = useActiveAdminPolicies();
     const lastWorkspaceNumber = useLastWorkspaceNumber();
@@ -513,7 +516,7 @@ function useSelectionModeReportActions({
         let idx = 0;
         if (hasSubmitAction && !shouldBlockSubmit) {
             actions[idx++] = {
-                text: translate('common.submit'),
+                text: shouldShowMarkAsDone({policy, report, isTrackIntentUser}) ? translate('common.markAsDone') : translate('common.submit'),
                 icon: expensifyIcons.Send,
                 value: CONST.REPORT.PRIMARY_ACTIONS.SUBMIT,
                 onSelected: handleSubmitReport,

From 1b932192e5b0475b984fdb816c921d356e5b6322 Mon Sep 17 00:00:00 2001
From: krishna2323 <belivethatkg@gmail.com>
Date: Mon, 1 Jun 2026 21:29:10 +0530
Subject: [PATCH 082/435] fix: Align GroupHeader and GroupChildrenContainer
 behavior with main's TransactionGroupListItem

Signed-off-by: krishna2323 <belivethatkg@gmail.com>
---
 .../ListItem/GroupChildrenContainer.tsx       | 12 +++++-
 .../SearchList/ListItem/GroupHeader.tsx       | 41 +++++++++++++++----
 src/components/Search/SearchList/index.tsx    |  5 ++-
 3 files changed, 47 insertions(+), 11 deletions(-)

diff --git a/src/components/Search/SearchList/ListItem/GroupChildrenContainer.tsx b/src/components/Search/SearchList/ListItem/GroupChildrenContainer.tsx
index 29a1465de78c..3159b9f60adb 100644
--- a/src/components/Search/SearchList/ListItem/GroupChildrenContainer.tsx
+++ b/src/components/Search/SearchList/ListItem/GroupChildrenContainer.tsx
@@ -40,6 +40,7 @@ type GroupChildrenContainerProps = {
     nonPersonalAndWorkspaceCards?: CardList;
     onUndelete?: (transaction: Transaction) => void;
     isLastItem?: boolean;
+    newTransactionID?: string;
 };
 
 function GroupChildrenContainer({
@@ -55,6 +56,7 @@ function GroupChildrenContainer({
     nonPersonalAndWorkspaceCards,
     onUndelete,
     isLastItem,
+    newTransactionID,
 }: GroupChildrenContainerProps) {
     const theme = useTheme();
     const styles = useThemeStyles();
@@ -135,6 +137,14 @@ function GroupChildrenContainer({
         });
     };
 
+    useEffect(() => {
+        if (!newTransactionID || !isExpanded) {
+            return;
+        }
+        refreshTransactions();
+        // eslint-disable-next-line react-hooks/exhaustive-deps
+    }, [newTransactionID, isExpanded]);
+
     useEffect(() => {
         if (!isExpanded || isExpenseReportType) {
             return;
@@ -193,7 +203,7 @@ function GroupChildrenContainer({
     }
 
     const onExpandedRowLongPress = (transaction: TransactionListItemType) => {
-        onLongPressRow?.(transaction, transactions);
+        onLongPressRow?.(transaction as unknown as SearchListItem);
     };
 
     // Animation: replicate AnimatedCollapsible's height animation pattern
diff --git a/src/components/Search/SearchList/ListItem/GroupHeader.tsx b/src/components/Search/SearchList/ListItem/GroupHeader.tsx
index a7e766651e57..1eb010e96132 100644
--- a/src/components/Search/SearchList/ListItem/GroupHeader.tsx
+++ b/src/components/Search/SearchList/ListItem/GroupHeader.tsx
@@ -1,5 +1,6 @@
-import React, {useState} from 'react';
+import React, {useRef, useState} from 'react';
 import {View} from 'react-native';
+import type {NativeSyntheticEvent} from 'react-native';
 import type {OnyxEntry} from 'react-native-onyx';
 // eslint-disable-next-line no-restricted-imports
 import {useOnyx as originalUseOnyx} from 'react-native-onyx';
@@ -13,12 +14,14 @@ import {PressableWithFeedback} from '@components/Pressable';
 import {useSearchSelectionContext} from '@components/Search/SearchContext';
 import SearchTableHeader from '@components/Search/SearchTableHeader';
 import type {SearchColumnType, SearchGroupBy} from '@components/Search/types';
+import type {ExtendedTargetedEvent} from '@components/SelectionList/ListItem/types';
 import useAnimatedHighlightStyle from '@hooks/useAnimatedHighlightStyle';
 import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails';
 import {useMemoizedLazyExpensifyIcons} from '@hooks/useLazyAsset';
 import useOnyx from '@hooks/useOnyx';
 import useResponsiveLayout from '@hooks/useResponsiveLayout';
 import useStyleUtils from '@hooks/useStyleUtils';
+import useSyncFocus from '@hooks/useSyncFocus';
 import useTheme from '@hooks/useTheme';
 import useThemeStyles from '@hooks/useThemeStyles';
 import type {TransactionPreviewData} from '@libs/actions/Search';
@@ -26,6 +29,7 @@ import getNonEmptyStringOnyxID from '@libs/getNonEmptyStringOnyxID';
 import type {ModifiedMouseEvent} from '@libs/Navigation/helpers/openInternalRouteInNewTab';
 import {getColumnsToShow} from '@libs/SearchUIUtils';
 import {isDeletedTransaction} from '@libs/TransactionUtils';
+import variables from '@styles/variables';
 import CONST from '@src/CONST';
 import ONYXKEYS from '@src/ONYXKEYS';
 import {columnsSelector} from '@src/selectors/AdvancedSearchFiltersForm';
@@ -70,8 +74,10 @@ type GroupHeaderProps = SearchListActionProps & {
     isExpanded: boolean;
     onToggle: () => void;
     onSelectRow: (item: SearchListItem, transactionPreviewData?: TransactionPreviewData, event?: ModifiedMouseEvent) => void;
-    onCheckboxPress: (item: GroupHeaderItemType) => void;
+    onCheckboxPress: (item: GroupHeaderItemType, itemTransactions?: TransactionListItemType[]) => void;
     onLongPressRow?: (item: SearchListItem, itemTransactions?: TransactionListItemType[]) => void;
+    onFocus?: (event: NativeSyntheticEvent<ExtendedTargetedEvent>) => void;
+    shouldSyncFocus?: boolean;
     isFocused?: boolean;
     isFirstItem: boolean;
     isLastItem: boolean;
@@ -88,6 +94,8 @@ function GroupHeader({
     onSelectRow,
     onCheckboxPress,
     onLongPressRow,
+    onFocus,
+    shouldSyncFocus,
     isFocused,
     isFirstItem,
     isLastItem,
@@ -182,7 +190,8 @@ function GroupHeader({
     const isEmptyReportSelected = isEmpty && item?.keyForList && selectedTransactions[item.keyForList]?.isSelected;
     const isSelectAllChecked = isEmptyReportSelected || (selectedItemsLength === transactionsWithoutPendingDelete.length && transactionsWithoutPendingDelete.length > 0);
     const isIndeterminate = selectedItemsLength > 0 && selectedItemsLength !== transactionsWithoutPendingDelete.length;
-    const isDisabledOrEmpty = isEmpty;
+    const isDisabled = item.pendingAction === CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE;
+    const isDisabledOrEmpty = isEmpty || isDisabled;
 
     const isItemSelected = isSelectAllChecked || item?.isSelected;
 
@@ -194,7 +203,7 @@ function GroupHeader({
     });
 
     const handleSelectionButtonPress = () => {
-        onCheckboxPress(item);
+        onCheckboxPress(item, isExpenseReportType ? undefined : groupItem.transactions);
     };
 
     const pendingAction =
@@ -214,7 +223,7 @@ function GroupHeader({
                     report={groupItem as TransactionReportGroupListItemType}
                     onSelectRow={handleSelectRow}
                     onCheckboxPress={handleSelectionButtonPress}
-                    isDisabled={isDisabledOrEmpty}
+                    isDisabled={isDisabled}
                     isFocused={isFocused}
                     canSelectMultiple={canSelectMultiple}
                     isSelectAllChecked={isSelectAllChecked}
@@ -373,19 +382,25 @@ function GroupHeader({
     };
 
     const isLastItemCollapsed = isLastItem && !isExpanded && !isSubHeaderRendered;
+    const pressableRef = useRef<View>(null);
+
+    useSyncFocus(pressableRef, !!isFocused, shouldSyncFocus);
 
     const pressableStyle = [
         styles.transactionGroupListItemStyle,
         isLargeScreenWidth && {
+            ...styles.tableRowHeight,
             borderRadius: 0,
+            paddingVertical: variables.tableGroupRowPaddingVertical,
             ...(isLastItemCollapsed ? styles.tableBottomRadius : {}),
         },
         isItemSelected && styles.activeComponentBG,
-        {minHeight: 0},
     ];
 
+    const shouldDisplayEmptyView = isEmpty && isExpenseReportType;
+
     const handlePress = (event?: ModifiedMouseEvent) => {
-        if (isExpenseReportType) {
+        if (isExpenseReportType || isEmpty) {
             onSelectRow(item, transactionPreviewData, event);
         }
         if (!isExpenseReportType) {
@@ -400,9 +415,10 @@ function GroupHeader({
     return (
         <OfflineWithFeedback pendingAction={pendingAction}>
             <PressableWithFeedback
+                ref={pressableRef}
                 onPress={handlePress}
                 onLongPress={handleLongPress}
-                disabled={false}
+                disabled={isDisabled && !isItemSelected}
                 sentryLabel={CONST.SENTRY_LABEL.SEARCH.TRANSACTION_GROUP_LIST_ITEM}
                 accessibilityLabel={item.text ?? ''}
                 role={getButtonRole(true)}
@@ -411,6 +427,7 @@ function GroupHeader({
                 dataSet={{[CONST.SELECTION_SCRAPER_HIDDEN_ELEMENT]: true, [CONST.INNER_BOX_SHADOW_ELEMENT]: false}}
                 onMouseDown={(e) => e.preventDefault()}
                 id={item.keyForList ?? ''}
+                onFocus={onFocus}
                 style={[
                     pressableStyle,
                     isFocused && StyleUtils.getItemBackgroundColorStyle(!!isItemSelected, !!isFocused, !!item.isDisabled, theme.activeComponentBG, theme.hoverComponentBG),
@@ -434,7 +451,13 @@ function GroupHeader({
                             <View style={styles.flex1}>{renderHeader(hovered)}</View>
                             {isLargeScreenWidth && (
                                 <PressableWithFeedback
-                                    onPress={onToggle}
+                                    onPress={() => {
+                                        if (isEmpty && !shouldDisplayEmptyView) {
+                                            handlePress();
+                                            return;
+                                        }
+                                        onToggle();
+                                    }}
                                     style={[styles.p3Half, styles.justifyContentCenter, styles.alignItemsCenter, styles.pv2]}
                                     accessibilityRole={CONST.ROLE.BUTTON}
                                     accessibilityLabel={isExpanded ? CONST.ACCESSIBILITY_LABELS.COLLAPSE : CONST.ACCESSIBILITY_LABELS.EXPAND}
diff --git a/src/components/Search/SearchList/index.tsx b/src/components/Search/SearchList/index.tsx
index 1d2f1a26336e..1a1ad0ae80da 100644
--- a/src/components/Search/SearchList/index.tsx
+++ b/src/components/Search/SearchList/index.tsx
@@ -482,8 +482,9 @@ function SearchList({
                         isExpanded={expandedGroups.has(originalKey)}
                         onToggle={() => onToggleGroup(originalKey)}
                         onSelectRow={onSelectRow}
-                        onCheckboxPress={(val) => onCheckboxPress(val as SearchListItem)}
+                        onCheckboxPress={(val, itemTransactions) => onCheckboxPress(val as SearchListItem, itemTransactions)}
                         onLongPressRow={isMobileSelectionModeEnabled ? handleLongPressRowInMobileSelectionMode : handleLongPressRow}
+                        onFocus={onFocus}
                         isFocused={isItemFocused}
                         isFirstItem={index === firstVisibleIndex}
                         isLastItem={index + 1 >= lastVisibleIndex && !ListFooterComponent}
@@ -499,6 +500,7 @@ function SearchList({
             if ('listItemType' in item && (item as GroupChildrenContainerItemType).listItemType === 'children_container') {
                 const containerItem = item as GroupChildrenContainerItemType;
                 const originalKey = (item.keyForList ?? '').replace('children_', '');
+                const containerNewTransactionID = item.keyForList ? newTransactionIDByItemKey.get(originalKey) : undefined;
                 return (
                     <GroupChildrenContainer
                         item={containerItem}
@@ -513,6 +515,7 @@ function SearchList({
                         nonPersonalAndWorkspaceCards={nonPersonalAndWorkspaceCards}
                         onUndelete={handleUndelete}
                         isLastItem={index === lastVisibleIndex && !ListFooterComponent}
+                        newTransactionID={containerNewTransactionID}
                     />
                 );
             }

From 2b6d025f969837de6896efad3e4a8b2f146a1c27 Mon Sep 17 00:00:00 2001
From: krishna2323 <belivethatkg@gmail.com>
Date: Mon, 1 Jun 2026 21:51:52 +0530
Subject: [PATCH 083/435] perf: Optimize sticky group headers by deferring
 expensive work to expanded state

Signed-off-by: krishna2323 <belivethatkg@gmail.com>
---
 .../ListItem/GroupChildrenContainer.tsx       | 215 ++---------
 .../ListItem/GroupChildrenContent.tsx         | 251 +++++++++++++
 .../SearchList/ListItem/GroupHeader.tsx       | 336 +++++++++---------
 src/components/Search/SearchList/index.tsx    |  16 +
 4 files changed, 457 insertions(+), 361 deletions(-)
 create mode 100644 src/components/Search/SearchList/ListItem/GroupChildrenContent.tsx

diff --git a/src/components/Search/SearchList/ListItem/GroupChildrenContainer.tsx b/src/components/Search/SearchList/ListItem/GroupChildrenContainer.tsx
index 3159b9f60adb..104b5e91ba35 100644
--- a/src/components/Search/SearchList/ListItem/GroupChildrenContainer.tsx
+++ b/src/components/Search/SearchList/ListItem/GroupChildrenContainer.tsx
@@ -1,31 +1,19 @@
-import {useIsFocused} from '@react-navigation/native';
 import React, {useEffect, useState} from 'react';
 import {View} from 'react-native';
+import type {OnyxCollection, OnyxEntry} from 'react-native-onyx';
 import Animated, {useAnimatedStyle, useDerivedValue, useSharedValue, withTiming} from 'react-native-reanimated';
 import {scheduleOnRN} from 'react-native-worklets';
 import {easing} from '@components/Modal/ReanimatedModal/utils';
-import {useSearchSelectionContext} from '@components/Search/SearchContext';
 import type {SearchColumnType, SearchGroupBy} from '@components/Search/types';
-import useActionLoadingReportIDs from '@hooks/useActionLoadingReportIDs';
-import {useCurrencyListActions} from '@hooks/useCurrencyList';
-import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails';
-import useLocalize from '@hooks/useLocalize';
-import useNetwork from '@hooks/useNetwork';
-import useOnyx from '@hooks/useOnyx';
 import useResponsiveLayout from '@hooks/useResponsiveLayout';
 import useTheme from '@hooks/useTheme';
 import useThemeStyles from '@hooks/useThemeStyles';
-import {search} from '@libs/actions/Search';
 import type {TransactionPreviewData} from '@libs/actions/Search';
 import type {ModifiedMouseEvent} from '@libs/Navigation/helpers/openInternalRouteInNewTab';
-import {getSections} from '@libs/SearchUIUtils';
-import {mergeProhibitedViolations, shouldShowViolation} from '@libs/TransactionUtils';
-import CONST from '@src/CONST';
-import ONYXKEYS from '@src/ONYXKEYS';
-import type {CardList, Transaction, TransactionViolation, TransactionViolations} from '@src/types/onyx';
+import type {BankAccountList, CardFeeds, CardList, ReportMetadata, Transaction} from '@src/types/onyx';
 import type {SearchDataTypes} from '@src/types/onyx/SearchResults';
-import TransactionGroupListExpandedItem from './TransactionGroupListExpanded';
-import type {GroupChildrenContainerItemType, SearchListItem, TransactionGroupListItemType, TransactionListItemType} from './types';
+import GroupChildrenContent from './GroupChildrenContent';
+import type {GroupChildrenContainerItemType, SearchListItem, TransactionListItemType} from './types';
 
 type GroupChildrenContainerProps = {
     item: GroupChildrenContainerItemType;
@@ -41,6 +29,10 @@ type GroupChildrenContainerProps = {
     onUndelete?: (transaction: Transaction) => void;
     isLastItem?: boolean;
     newTransactionID?: string;
+    allReportMetadata?: OnyxCollection<ReportMetadata>;
+    bankAccountList?: OnyxEntry<BankAccountList>;
+    cardFeeds?: OnyxCollection<CardFeeds>;
+    conciergeReportID?: string;
 };
 
 function GroupChildrenContainer({
@@ -57,161 +49,23 @@ function GroupChildrenContainer({
     onUndelete,
     isLastItem,
     newTransactionID,
+    allReportMetadata,
+    bankAccountList,
+    cardFeeds,
+    conciergeReportID,
 }: GroupChildrenContainerProps) {
     const theme = useTheme();
     const styles = useThemeStyles();
-    const {translate, formatPhoneNumber} = useLocalize();
-    const {selectedTransactions} = useSearchSelectionContext();
-    const currentUserDetails = useCurrentUserPersonalDetails();
-    const isScreenFocused = useIsFocused();
-    const {convertToDisplayString} = useCurrencyListActions();
-    const {isOffline} = useNetwork();
     const {isLargeScreenWidth} = useResponsiveLayout();
 
-    const groupItem = item as unknown as TransactionGroupListItemType;
-    const isExpenseReportType = searchType === CONST.SEARCH.DATA_TYPES.EXPENSE_REPORT;
-
-    const selectedTransactionIDsSet = new Set(Object.keys(selectedTransactions));
-    const [transactionsSnapshot] = useOnyx(`${ONYXKEYS.COLLECTION.SNAPSHOT}${groupItem.transactionsQueryJSON?.hash}`);
-    const [transactionsVisibleLimit, setTransactionsVisibleLimit] = useState(CONST.TRANSACTION.RESULTS_PAGE_SIZE as number);
-    const isActionLoadingSet = useActionLoadingReportIDs();
-    const [allReportMetadata] = useOnyx(ONYXKEYS.COLLECTION.REPORT_METADATA);
-    const [bankAccountList] = useOnyx(ONYXKEYS.BANK_ACCOUNT_LIST);
-    const [cardFeeds] = useOnyx(ONYXKEYS.COLLECTION.SHARED_NVP_PRIVATE_DOMAIN_MEMBER);
-    const [conciergeReportID] = useOnyx(ONYXKEYS.CONCIERGE_REPORT_ID);
-
-    let transactions: TransactionListItemType[];
-    if (isExpenseReportType) {
-        transactions = groupItem.transactions;
-    } else if (!transactionsSnapshot?.data) {
-        transactions = [];
-    } else {
-        const [sectionData] = getSections({
-            type: CONST.SEARCH.DATA_TYPES.EXPENSE,
-            data: transactionsSnapshot?.data,
-            currentAccountID: currentUserDetails.accountID,
-            currentUserEmail: currentUserDetails.email ?? '',
-            translate,
-            formatPhoneNumber,
-            bankAccountList,
-            isActionLoadingSet,
-            allReportMetadata,
-            cardFeeds,
-            conciergeReportID,
-            convertToDisplayString,
-        }) as [TransactionListItemType[], number, boolean];
-        transactions = sectionData.map((transactionItem) => ({
-            ...transactionItem,
-            isSelected: selectedTransactionIDsSet.has(transactionItem.transactionID),
-        }));
-    }
-
-    const isEmpty = transactions.length === 0;
-    const shouldDisplayEmptyView = isEmpty && isExpenseReportType;
-
-    const refreshTransactions = () => {
-        if (!groupItem.transactionsQueryJSON) {
-            return;
-        }
-        search({
-            queryJSON: groupItem.transactionsQueryJSON,
-            searchKey: undefined,
-            offset: 0,
-            shouldCalculateTotals: false,
-            isLoading: !!transactionsSnapshot?.search?.isLoading,
-            isOffline,
-        });
-    };
-
-    const searchTransactions = (pageSize = 0) => {
-        if (!groupItem.transactionsQueryJSON) {
-            return;
-        }
-        search({
-            queryJSON: groupItem.transactionsQueryJSON,
-            searchKey: undefined,
-            offset: (transactionsSnapshot?.search?.offset ?? 0) + pageSize,
-            shouldCalculateTotals: false,
-            isLoading: !!transactionsSnapshot?.search?.isLoading,
-            isOffline,
-        });
-    };
-
-    useEffect(() => {
-        if (!newTransactionID || !isExpanded) {
-            return;
-        }
-        refreshTransactions();
-        // eslint-disable-next-line react-hooks/exhaustive-deps
-    }, [newTransactionID, isExpanded]);
-
-    useEffect(() => {
-        if (!isExpanded || isExpenseReportType) {
-            return;
-        }
-        refreshTransactions();
-        // eslint-disable-next-line react-hooks/exhaustive-deps
-    }, [isExpanded]);
-
-    const wasScreenFocusedRef = React.useRef(isScreenFocused);
-    useEffect(() => {
-        const didReturnToScreen = wasScreenFocusedRef.current === false && isScreenFocused === true;
-        wasScreenFocusedRef.current = isScreenFocused;
-        if (!didReturnToScreen || !isExpanded || isExpenseReportType) {
-            return;
-        }
-        refreshTransactions();
-        // eslint-disable-next-line react-hooks/exhaustive-deps
-    }, [isScreenFocused]);
-
-    const snapshotData = transactionsSnapshot?.data;
-    const groupViolations: Record<string, TransactionViolations | undefined> = {};
-    if (snapshotData) {
-        for (const [key, value] of Object.entries(snapshotData)) {
-            if (key.startsWith(ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS)) {
-                groupViolations[key] = value as TransactionViolations;
-            }
-        }
-    }
-
-    const filteredViolations: Record<string, TransactionViolation[]> = {};
-    if (snapshotData) {
-        for (const key of Object.keys(snapshotData)) {
-            if (!key.startsWith(ONYXKEYS.COLLECTION.TRANSACTION)) {
-                continue;
-            }
-            const snapshotTransaction = snapshotData[key as keyof typeof snapshotData] as Transaction;
-            if (!snapshotTransaction || typeof snapshotTransaction !== 'object' || !('transactionID' in snapshotTransaction) || !('reportID' in snapshotTransaction)) {
-                continue;
-            }
-
-            const report = snapshotData[`${ONYXKEYS.COLLECTION.REPORT}${snapshotTransaction.reportID}`];
-            const policy = snapshotData[`${ONYXKEYS.COLLECTION.POLICY}${report?.policyID}`];
-
-            if (report && policy) {
-                const transactionViolations = groupViolations[`${ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS}${snapshotTransaction.transactionID}`];
-                if (transactionViolations) {
-                    const merged = mergeProhibitedViolations(
-                        transactionViolations.filter((violation) => shouldShowViolation(report, policy, violation.name, currentUserDetails?.email ?? '', true, snapshotTransaction)),
-                    );
-                    if (merged.length > 0) {
-                        filteredViolations[`${ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS}${snapshotTransaction.transactionID}`] = merged;
-                    }
-                }
-            }
-        }
-    }
-
-    const onExpandedRowLongPress = (transaction: TransactionListItemType) => {
-        onLongPressRow?.(transaction as unknown as SearchListItem);
-    };
-
-    // Animation: replicate AnimatedCollapsible's height animation pattern
     const contentHeight = useSharedValue(0);
     const hasExpanded = useSharedValue(isExpanded);
     const [isRendered, setIsRendered] = useState(isExpanded);
 
-    hasExpanded.set(isExpanded);
+    useEffect(() => {
+        hasExpanded.set(isExpanded);
+    }, [isExpanded, hasExpanded]);
+
     if (isExpanded && !isRendered) {
         setIsRendered(true);
     }
@@ -248,7 +102,7 @@ function GroupChildrenContainer({
     return (
         <View style={[styles.mh5, {backgroundColor: theme.highlightBG}, isLastItem && [styles.tableBottomRadius, styles.overflowHidden]]}>
             <Animated.View style={contentAnimatedStyle}>
-                {isExpanded || isRendered ? (
+                {(isExpanded || isRendered) && (
                     <Animated.View
                         style={[styles.stickToTop, {paddingBottom: 4}]}
                         onLayout={(e) => {
@@ -263,33 +117,26 @@ function GroupChildrenContainer({
                                 <View style={styles.borderBottom} />
                             </View>
                         )}
-                        <TransactionGroupListExpandedItem
-                            showTooltip
+                        <GroupChildrenContent
+                            item={item}
+                            isExpanded={isExpanded}
+                            groupBy={groupBy}
+                            searchType={searchType}
+                            columns={columns}
                             canSelectMultiple={canSelectMultiple}
-                            onSelectionButtonPress={onCheckboxPress}
                             onSelectRow={onSelectRow}
-                            columns={columns}
-                            groupBy={groupBy}
-                            accountID={currentUserDetails.accountID}
-                            isOffline={isOffline}
-                            violations={filteredViolations}
-                            transactions={transactions}
-                            transactionsVisibleLimit={transactionsVisibleLimit}
-                            setTransactionsVisibleLimit={setTransactionsVisibleLimit}
-                            isEmpty={isEmpty}
-                            shouldDisplayEmptyView={shouldDisplayEmptyView}
-                            isExpenseReportType={isExpenseReportType}
-                            transactionsSnapshot={transactionsSnapshot}
-                            transactionsQueryJSON={groupItem.transactionsQueryJSON}
-                            searchTransactions={searchTransactions}
-                            isInSingleTransactionReport={groupItem.transactions.length === 1}
-                            onLongPress={onExpandedRowLongPress}
+                            onCheckboxPress={onCheckboxPress}
+                            onLongPressRow={onLongPressRow}
                             nonPersonalAndWorkspaceCards={nonPersonalAndWorkspaceCards}
                             onUndelete={onUndelete}
-                            hideSearchTableHeader
+                            newTransactionID={newTransactionID}
+                            allReportMetadata={allReportMetadata}
+                            bankAccountList={bankAccountList}
+                            cardFeeds={cardFeeds}
+                            conciergeReportID={conciergeReportID}
                         />
                     </Animated.View>
-                ) : null}
+                )}
             </Animated.View>
         </View>
     );
diff --git a/src/components/Search/SearchList/ListItem/GroupChildrenContent.tsx b/src/components/Search/SearchList/ListItem/GroupChildrenContent.tsx
new file mode 100644
index 000000000000..8ab547e70d44
--- /dev/null
+++ b/src/components/Search/SearchList/ListItem/GroupChildrenContent.tsx
@@ -0,0 +1,251 @@
+import {useIsFocused} from '@react-navigation/native';
+import React, {useEffect, useMemo, useState} from 'react';
+import type {OnyxCollection, OnyxEntry} from 'react-native-onyx';
+import {useSearchSelectionContext} from '@components/Search/SearchContext';
+import type {SearchColumnType, SearchGroupBy} from '@components/Search/types';
+import useActionLoadingReportIDs from '@hooks/useActionLoadingReportIDs';
+import {useCurrencyListActions} from '@hooks/useCurrencyList';
+import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails';
+import useLocalize from '@hooks/useLocalize';
+import useNetwork from '@hooks/useNetwork';
+import useOnyx from '@hooks/useOnyx';
+import {search} from '@libs/actions/Search';
+import type {TransactionPreviewData} from '@libs/actions/Search';
+import type {ModifiedMouseEvent} from '@libs/Navigation/helpers/openInternalRouteInNewTab';
+import {getSections} from '@libs/SearchUIUtils';
+import {mergeProhibitedViolations, shouldShowViolation} from '@libs/TransactionUtils';
+import CONST from '@src/CONST';
+import ONYXKEYS from '@src/ONYXKEYS';
+import type {BankAccountList, CardFeeds, CardList, ReportMetadata, Transaction, TransactionViolation, TransactionViolations} from '@src/types/onyx';
+import type {SearchDataTypes} from '@src/types/onyx/SearchResults';
+import TransactionGroupListExpandedItem from './TransactionGroupListExpanded';
+import type {GroupChildrenContainerItemType, SearchListItem, TransactionGroupListItemType, TransactionListItemType} from './types';
+
+type GroupChildrenContentProps = {
+    item: GroupChildrenContainerItemType;
+    isExpanded: boolean;
+    groupBy?: SearchGroupBy;
+    searchType?: SearchDataTypes;
+    columns?: SearchColumnType[];
+    canSelectMultiple: boolean;
+    onSelectRow: (item: SearchListItem, transactionPreviewData?: TransactionPreviewData, event?: ModifiedMouseEvent) => void;
+    onCheckboxPress: (item: SearchListItem, itemTransactions?: TransactionListItemType[]) => void;
+    onLongPressRow?: (item: SearchListItem, itemTransactions?: TransactionListItemType[]) => void;
+    nonPersonalAndWorkspaceCards?: CardList;
+    onUndelete?: (transaction: Transaction) => void;
+    newTransactionID?: string;
+    allReportMetadata?: OnyxCollection<ReportMetadata>;
+    bankAccountList?: OnyxEntry<BankAccountList>;
+    cardFeeds?: OnyxCollection<CardFeeds>;
+    conciergeReportID?: string;
+};
+
+function GroupChildrenContent({
+    item,
+    isExpanded,
+    groupBy,
+    searchType,
+    columns,
+    canSelectMultiple,
+    onSelectRow,
+    onCheckboxPress,
+    onLongPressRow,
+    nonPersonalAndWorkspaceCards,
+    onUndelete,
+    newTransactionID,
+    allReportMetadata,
+    bankAccountList,
+    cardFeeds,
+    conciergeReportID,
+}: GroupChildrenContentProps) {
+    const {translate, formatPhoneNumber} = useLocalize();
+    const {selectedTransactions} = useSearchSelectionContext();
+    const currentUserDetails = useCurrentUserPersonalDetails();
+    const isScreenFocused = useIsFocused();
+    const {convertToDisplayString} = useCurrencyListActions();
+    const {isOffline} = useNetwork();
+
+    const groupItem = item as unknown as TransactionGroupListItemType;
+    const isExpenseReportType = searchType === CONST.SEARCH.DATA_TYPES.EXPENSE_REPORT;
+
+    const [transactionsSnapshot] = useOnyx(`${ONYXKEYS.COLLECTION.SNAPSHOT}${groupItem.transactionsQueryJSON?.hash}`);
+    const [transactionsVisibleLimit, setTransactionsVisibleLimit] = useState(CONST.TRANSACTION.RESULTS_PAGE_SIZE as number);
+    const isActionLoadingSet = useActionLoadingReportIDs();
+    const snapshotData = transactionsSnapshot?.data;
+
+    const selectedTransactionIDsSet = useMemo(() => new Set(Object.keys(selectedTransactions)), [selectedTransactions]);
+
+    const transactions: TransactionListItemType[] = useMemo(() => {
+        if (isExpenseReportType) {
+            return groupItem.transactions;
+        }
+        if (!snapshotData) {
+            return [];
+        }
+        const [sectionData] = getSections({
+            type: CONST.SEARCH.DATA_TYPES.EXPENSE,
+            data: snapshotData,
+            currentAccountID: currentUserDetails.accountID,
+            currentUserEmail: currentUserDetails.email ?? '',
+            translate,
+            formatPhoneNumber,
+            bankAccountList,
+            isActionLoadingSet,
+            allReportMetadata,
+            cardFeeds,
+            conciergeReportID,
+            convertToDisplayString,
+        }) as [TransactionListItemType[], number, boolean];
+        return sectionData.map((transactionItem) => ({
+            ...transactionItem,
+            isSelected: selectedTransactionIDsSet.has(transactionItem.transactionID),
+        }));
+    }, [
+        isExpenseReportType,
+        groupItem.transactions,
+        snapshotData,
+        currentUserDetails.accountID,
+        currentUserDetails.email,
+        translate,
+        formatPhoneNumber,
+        bankAccountList,
+        isActionLoadingSet,
+        allReportMetadata,
+        cardFeeds,
+        conciergeReportID,
+        convertToDisplayString,
+        selectedTransactionIDsSet,
+    ]);
+
+    const isEmpty = transactions.length === 0;
+    const shouldDisplayEmptyView = isEmpty && isExpenseReportType;
+
+    const refreshTransactions = () => {
+        if (!groupItem.transactionsQueryJSON) {
+            return;
+        }
+        search({
+            queryJSON: groupItem.transactionsQueryJSON,
+            searchKey: undefined,
+            offset: 0,
+            shouldCalculateTotals: false,
+            isLoading: !!transactionsSnapshot?.search?.isLoading,
+            isOffline,
+        });
+    };
+
+    const searchTransactions = (pageSize = 0) => {
+        if (!groupItem.transactionsQueryJSON) {
+            return;
+        }
+        search({
+            queryJSON: groupItem.transactionsQueryJSON,
+            searchKey: undefined,
+            offset: (transactionsSnapshot?.search?.offset ?? 0) + pageSize,
+            shouldCalculateTotals: false,
+            isLoading: !!transactionsSnapshot?.search?.isLoading,
+            isOffline,
+        });
+    };
+
+    useEffect(() => {
+        if (!newTransactionID || !isExpanded) {
+            return;
+        }
+        refreshTransactions();
+        // eslint-disable-next-line react-hooks/exhaustive-deps
+    }, [newTransactionID, isExpanded]);
+
+    useEffect(() => {
+        if (!isExpanded || isExpenseReportType) {
+            return;
+        }
+        refreshTransactions();
+        // eslint-disable-next-line react-hooks/exhaustive-deps
+    }, [isExpanded]);
+
+    const wasScreenFocusedRef = React.useRef(isScreenFocused);
+    useEffect(() => {
+        const didReturnToScreen = wasScreenFocusedRef.current === false && isScreenFocused === true;
+        wasScreenFocusedRef.current = isScreenFocused;
+        if (!didReturnToScreen || !isExpanded || isExpenseReportType) {
+            return;
+        }
+        refreshTransactions();
+        // eslint-disable-next-line react-hooks/exhaustive-deps
+    }, [isScreenFocused]);
+
+    const filteredViolations: Record<string, TransactionViolation[]> = useMemo(() => {
+        if (!snapshotData) {
+            return {};
+        }
+
+        const groupViolations: Record<string, TransactionViolations | undefined> = {};
+        for (const [key, value] of Object.entries(snapshotData)) {
+            if (key.startsWith(ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS)) {
+                groupViolations[key] = value as TransactionViolations;
+            }
+        }
+
+        const result: Record<string, TransactionViolation[]> = {};
+        for (const key of Object.keys(snapshotData)) {
+            if (!key.startsWith(ONYXKEYS.COLLECTION.TRANSACTION)) {
+                continue;
+            }
+            const snapshotTransaction = snapshotData[key as keyof typeof snapshotData] as Transaction;
+            if (!snapshotTransaction || typeof snapshotTransaction !== 'object' || !('transactionID' in snapshotTransaction) || !('reportID' in snapshotTransaction)) {
+                continue;
+            }
+
+            const report = snapshotData[`${ONYXKEYS.COLLECTION.REPORT}${snapshotTransaction.reportID}`];
+            const policy = snapshotData[`${ONYXKEYS.COLLECTION.POLICY}${report?.policyID}`];
+
+            if (report && policy) {
+                const transactionViolations = groupViolations[`${ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS}${snapshotTransaction.transactionID}`];
+                if (transactionViolations) {
+                    const merged = mergeProhibitedViolations(
+                        transactionViolations.filter((violation) => shouldShowViolation(report, policy, violation.name, currentUserDetails?.email ?? '', true, snapshotTransaction)),
+                    );
+                    if (merged.length > 0) {
+                        result[`${ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS}${snapshotTransaction.transactionID}`] = merged;
+                    }
+                }
+            }
+        }
+        return result;
+    }, [snapshotData, currentUserDetails.email]);
+
+    const onExpandedRowLongPress = (transaction: TransactionListItemType) => {
+        onLongPressRow?.(transaction as unknown as SearchListItem);
+    };
+
+    return (
+        <TransactionGroupListExpandedItem
+            showTooltip
+            canSelectMultiple={canSelectMultiple}
+            onSelectionButtonPress={onCheckboxPress}
+            onSelectRow={onSelectRow}
+            columns={columns}
+            groupBy={groupBy}
+            accountID={currentUserDetails.accountID}
+            isOffline={isOffline}
+            violations={filteredViolations}
+            transactions={transactions}
+            transactionsVisibleLimit={transactionsVisibleLimit}
+            setTransactionsVisibleLimit={setTransactionsVisibleLimit}
+            isEmpty={isEmpty}
+            shouldDisplayEmptyView={shouldDisplayEmptyView}
+            isExpenseReportType={isExpenseReportType}
+            transactionsSnapshot={transactionsSnapshot}
+            transactionsQueryJSON={groupItem.transactionsQueryJSON}
+            searchTransactions={searchTransactions}
+            isInSingleTransactionReport={groupItem.transactions.length === 1}
+            onLongPress={onExpandedRowLongPress}
+            nonPersonalAndWorkspaceCards={nonPersonalAndWorkspaceCards}
+            onUndelete={onUndelete}
+            hideSearchTableHeader
+        />
+    );
+}
+
+export default GroupChildrenContent;
diff --git a/src/components/Search/SearchList/ListItem/GroupHeader.tsx b/src/components/Search/SearchList/ListItem/GroupHeader.tsx
index 1eb010e96132..a4b54edd3c12 100644
--- a/src/components/Search/SearchList/ListItem/GroupHeader.tsx
+++ b/src/components/Search/SearchList/ListItem/GroupHeader.tsx
@@ -1,4 +1,4 @@
-import React, {useRef, useState} from 'react';
+import React, {useEffect, useMemo, useRef, useState} from 'react';
 import {View} from 'react-native';
 import type {NativeSyntheticEvent} from 'react-native';
 import type {OnyxEntry} from 'react-native-onyx';
@@ -13,7 +13,7 @@ import OfflineWithFeedback from '@components/OfflineWithFeedback';
 import {PressableWithFeedback} from '@components/Pressable';
 import {useSearchSelectionContext} from '@components/Search/SearchContext';
 import SearchTableHeader from '@components/Search/SearchTableHeader';
-import type {SearchColumnType, SearchGroupBy} from '@components/Search/types';
+import type {SearchColumnType, SearchCustomColumnIds, SearchGroupBy} from '@components/Search/types';
 import type {ExtendedTargetedEvent} from '@components/SelectionList/ListItem/types';
 import useAnimatedHighlightStyle from '@hooks/useAnimatedHighlightStyle';
 import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails';
@@ -32,7 +32,6 @@ import {isDeletedTransaction} from '@libs/TransactionUtils';
 import variables from '@styles/variables';
 import CONST from '@src/CONST';
 import ONYXKEYS from '@src/ONYXKEYS';
-import {columnsSelector} from '@src/selectors/AdvancedSearchFiltersForm';
 import type {ReportAction, ReportActions} from '@src/types/onyx';
 import type {SearchDataTypes} from '@src/types/onyx/SearchResults';
 import CardListItemHeader from './CardListItemHeader';
@@ -81,6 +80,7 @@ type GroupHeaderProps = SearchListActionProps & {
     isFocused?: boolean;
     isFirstItem: boolean;
     isLastItem: boolean;
+    visibleColumns?: SearchCustomColumnIds[];
 };
 
 function GroupHeader({
@@ -103,6 +103,7 @@ function GroupHeader({
     personalPolicyID,
     userBillingGracePeriodEnds,
     ownerBillingGracePeriodEnd,
+    visibleColumns,
 }: GroupHeaderProps) {
     const theme = useTheme();
     const styles = useThemeStyles();
@@ -116,50 +117,77 @@ function GroupHeader({
     const isExpenseReportType = searchType === CONST.SEARCH.DATA_TYPES.EXPENSE_REPORT;
 
     const oneTransactionItem = groupItem.isOneTransactionReport ? groupItem.transactions.at(0) : undefined;
-    const [parentReport] = originalUseOnyx(`${ONYXKEYS.COLLECTION.REPORT}${getNonEmptyStringOnyxID(oneTransactionItem?.reportID)}`);
-    const [oneTransactionThreadReport] = originalUseOnyx(`${ONYXKEYS.COLLECTION.REPORT}${oneTransactionItem?.reportAction?.childReportID}`);
-    const [oneTransaction] = originalUseOnyx(`${ONYXKEYS.COLLECTION.TRANSACTION}${getNonEmptyStringOnyxID(oneTransactionItem?.transactionID)}`);
+    const oneTransactionReportID = getNonEmptyStringOnyxID(oneTransactionItem?.reportID);
+    const oneTransactionID = getNonEmptyStringOnyxID(oneTransactionItem?.transactionID);
+    const oneTransactionChildReportID = oneTransactionItem?.reportAction?.childReportID;
+    const [parentReport] = originalUseOnyx(`${ONYXKEYS.COLLECTION.REPORT}${oneTransactionReportID}`);
+    const [oneTransactionThreadReport] = originalUseOnyx(`${ONYXKEYS.COLLECTION.REPORT}${oneTransactionChildReportID}`);
+    const [oneTransaction] = originalUseOnyx(`${ONYXKEYS.COLLECTION.TRANSACTION}${oneTransactionID}`);
     const parentReportActionSelector = (reportActions: OnyxEntry<ReportActions>): OnyxEntry<ReportAction> => reportActions?.[`${oneTransactionItem?.reportAction?.reportActionID}`];
-    const [parentReportAction] = originalUseOnyx(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${getNonEmptyStringOnyxID(oneTransactionItem?.reportID)}`, {selector: parentReportActionSelector}, [
-        oneTransactionItem,
-    ]);
-    const transactionPreviewData: TransactionPreviewData = {
-        hasParentReport: !!parentReport,
-        hasTransaction: !!oneTransaction,
-        hasParentReportAction: !!parentReportAction,
-        hasTransactionThreadReport: !!oneTransactionThreadReport,
-    };
+    const [parentReportAction] = originalUseOnyx(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${oneTransactionReportID}`, {selector: parentReportActionSelector}, [oneTransactionItem]);
+    const transactionPreviewData: TransactionPreviewData = useMemo(
+        () => ({
+            hasParentReport: !!parentReport,
+            hasTransaction: !!oneTransaction,
+            hasParentReportAction: !!parentReportAction,
+            hasTransactionThreadReport: !!oneTransactionThreadReport,
+        }),
+        [parentReport, oneTransaction, parentReportAction, oneTransactionThreadReport],
+    );
 
-    // Compute sub-header columns (same logic as TransactionGroupListExpanded)
     const [transactionsSnapshot] = useOnyx(`${ONYXKEYS.COLLECTION.SNAPSHOT}${groupItem.transactionsQueryJSON?.hash}`);
-    const [visibleColumns] = useOnyx(ONYXKEYS.FORMS.SEARCH_ADVANCED_FILTERS_FORM, {selector: columnsSelector});
+    const snapshotData = transactionsSnapshot?.data;
+    const snapshotSearchType = transactionsSnapshot?.search.type;
 
-    let subHeaderColumns = columns ?? [];
-    if (!isExpenseReportType) {
-        if (!transactionsSnapshot?.data) {
-            subHeaderColumns = [];
-        } else {
-            subHeaderColumns = getColumnsToShow({
-                currentAccountID: currentUserDetails.accountID,
-                data: transactionsSnapshot?.data,
-                visibleColumns,
-                type: transactionsSnapshot?.search.type,
-            });
+    const subHeaderColumns = useMemo(() => {
+        if (isExpenseReportType) {
+            return columns ?? [];
         }
-    }
+        if (!snapshotData) {
+            return [];
+        }
+        return getColumnsToShow({
+            currentAccountID: currentUserDetails.accountID,
+            data: snapshotData,
+            visibleColumns,
+            type: snapshotSearchType,
+        });
+    }, [isExpenseReportType, columns, snapshotData, snapshotSearchType, currentUserDetails.accountID, visibleColumns]);
 
-    // Compute sub-header column widths from transactions
-    const isSubHeaderAmountColumnWide = groupItem.transactions.some((transaction) => transaction.isAmountColumnWide);
-    const isSubHeaderTaxAmountColumnWide = groupItem.transactions.some((transaction) => transaction.isTaxAmountColumnWide);
-    const shouldSubHeaderShowYear = groupItem.transactions.some((transaction) => transaction.shouldShowYear);
-    const isSubHeaderActionColumnWide = groupItem.transactions.some((transaction) => !!transaction.isActionColumnWide || isDeletedTransaction(transaction));
+    const {isSubHeaderAmountColumnWide, isSubHeaderTaxAmountColumnWide, shouldSubHeaderShowYear, isSubHeaderActionColumnWide} = useMemo(() => {
+        let amountWide = false;
+        let taxWide = false;
+        let showYear = false;
+        let actionWide = false;
+        for (const transaction of groupItem.transactions) {
+            if (transaction.isAmountColumnWide) {
+                amountWide = true;
+            }
+            if (transaction.isTaxAmountColumnWide) {
+                taxWide = true;
+            }
+            if (transaction.shouldShowYear) {
+                showYear = true;
+            }
+            if (transaction.isActionColumnWide || isDeletedTransaction(transaction)) {
+                actionWide = true;
+            }
+            if (amountWide && taxWide && showYear && actionWide) {
+                break;
+            }
+        }
+        return {isSubHeaderAmountColumnWide: amountWide, isSubHeaderTaxAmountColumnWide: taxWide, shouldSubHeaderShowYear: showYear, isSubHeaderActionColumnWide: actionWide};
+    }, [groupItem.transactions]);
 
     // Animated sub-header (SearchTableHeader) height
     const subHeaderHeight = useSharedValue(0);
     const hasExpanded = useSharedValue(isExpanded);
     const [isSubHeaderRendered, setIsSubHeaderRendered] = useState(isExpanded);
 
-    hasExpanded.set(isExpanded);
+    useEffect(() => {
+        hasExpanded.set(isExpanded);
+    }, [isExpanded, hasExpanded]);
+
     if (isExpanded && !isSubHeaderRendered) {
         setIsSubHeaderRendered(true);
     }
@@ -182,17 +210,20 @@ function GroupHeader({
         overflow: 'hidden' as const,
     }));
 
-    const selectedTransactionIDs = Object.keys(selectedTransactions);
-    const selectedTransactionIDsSet = new Set(selectedTransactionIDs);
-    const selectedItemsLength = groupItem.transactions.reduce((acc, transaction) => (selectedTransactionIDsSet.has(transaction.transactionID) ? acc + 1 : acc), 0);
-    const transactionsWithoutPendingDelete = groupItem.transactions.filter((transaction) => transaction.pendingAction !== CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE);
     const isEmpty = groupItem.transactions.length === 0;
-    const isEmptyReportSelected = isEmpty && item?.keyForList && selectedTransactions[item.keyForList]?.isSelected;
-    const isSelectAllChecked = isEmptyReportSelected || (selectedItemsLength === transactionsWithoutPendingDelete.length && transactionsWithoutPendingDelete.length > 0);
-    const isIndeterminate = selectedItemsLength > 0 && selectedItemsLength !== transactionsWithoutPendingDelete.length;
     const isDisabled = item.pendingAction === CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE;
     const isDisabledOrEmpty = isEmpty || isDisabled;
 
+    const {isSelectAllChecked, isIndeterminate} = useMemo(() => {
+        const selectedTransactionIDsSet = new Set(Object.keys(selectedTransactions));
+        const filteredTransactions = groupItem.transactions.filter((transaction) => transaction.pendingAction !== CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE);
+        const selectedCount = groupItem.transactions.reduce((acc, transaction) => (selectedTransactionIDsSet.has(transaction.transactionID) ? acc + 1 : acc), 0);
+        const isEmptyReportSelected = isEmpty && item?.keyForList && selectedTransactions[item.keyForList]?.isSelected;
+        const allChecked = !!isEmptyReportSelected || (selectedCount === filteredTransactions.length && filteredTransactions.length > 0);
+        const indeterminate = selectedCount > 0 && selectedCount !== filteredTransactions.length;
+        return {isSelectAllChecked: allChecked, isIndeterminate: indeterminate};
+    }, [selectedTransactions, groupItem.transactions, isEmpty, item?.keyForList]);
+
     const isItemSelected = isSelectAllChecked || item?.isSelected;
 
     const animatedHighlightStyle = useAnimatedHighlightStyle({
@@ -243,142 +274,93 @@ function GroupHeader({
             return null;
         }
 
-        const headers: Record<SearchGroupBy, React.JSX.Element> = {
-            [CONST.SEARCH.GROUP_BY.FROM]: (
-                <MemberListItemHeader
-                    member={groupItem as TransactionMemberGroupListItemType}
-                    onCheckboxPress={handleSelectionButtonPress}
-                    isDisabled={isDisabledOrEmpty}
-                    columns={columns}
-                    canSelectMultiple={canSelectMultiple}
-                    isSelectAllChecked={isSelectAllChecked}
-                    isIndeterminate={isIndeterminate}
-                    onDownArrowClick={onToggle}
-                    isExpanded={isExpanded}
-                    isLargeScreenWidth={isLargeScreenWidth}
-                />
-            ),
-            [CONST.SEARCH.GROUP_BY.CARD]: (
-                <CardListItemHeader
-                    card={groupItem as TransactionCardGroupListItemType}
-                    onCheckboxPress={handleSelectionButtonPress}
-                    isDisabled={isDisabledOrEmpty}
-                    columns={columns}
-                    canSelectMultiple={canSelectMultiple}
-                    isSelectAllChecked={isSelectAllChecked}
-                    isIndeterminate={isIndeterminate}
-                    onDownArrowClick={onToggle}
-                    isExpanded={isExpanded}
-                    isFocused={isFocused}
-                />
-            ),
-            [CONST.SEARCH.GROUP_BY.WITHDRAWAL_ID]: (
-                <WithdrawalIDListItemHeader
-                    withdrawalID={groupItem as TransactionWithdrawalIDGroupListItemType}
-                    onCheckboxPress={handleSelectionButtonPress}
-                    isDisabled={isDisabledOrEmpty}
-                    columns={columns}
-                    canSelectMultiple={canSelectMultiple}
-                    isSelectAllChecked={isSelectAllChecked}
-                    isIndeterminate={isIndeterminate}
-                    onDownArrowClick={onToggle}
-                    isExpanded={isExpanded}
-                />
-            ),
-            [CONST.SEARCH.GROUP_BY.CATEGORY]: (
-                <CategoryListItemHeader
-                    category={groupItem as TransactionCategoryGroupListItemType}
-                    onCheckboxPress={handleSelectionButtonPress}
-                    isDisabled={isDisabledOrEmpty}
-                    columns={columns}
-                    canSelectMultiple={canSelectMultiple}
-                    isSelectAllChecked={isSelectAllChecked}
-                    isIndeterminate={isIndeterminate}
-                    onDownArrowClick={onToggle}
-                    isExpanded={isExpanded}
-                />
-            ),
-            [CONST.SEARCH.GROUP_BY.MERCHANT]: (
-                <MerchantListItemHeader
-                    merchant={groupItem as TransactionMerchantGroupListItemType}
-                    onCheckboxPress={handleSelectionButtonPress}
-                    isDisabled={isDisabledOrEmpty}
-                    columns={columns}
-                    canSelectMultiple={canSelectMultiple}
-                    isSelectAllChecked={isSelectAllChecked}
-                    isIndeterminate={isIndeterminate}
-                    onDownArrowClick={onToggle}
-                    isExpanded={isExpanded}
-                />
-            ),
-            [CONST.SEARCH.GROUP_BY.TAG]: (
-                <TagListItemHeader
-                    tag={groupItem as TransactionTagGroupListItemType}
-                    onCheckboxPress={handleSelectionButtonPress}
-                    isDisabled={isDisabledOrEmpty}
-                    columns={columns}
-                    canSelectMultiple={canSelectMultiple}
-                    isSelectAllChecked={isSelectAllChecked}
-                    isIndeterminate={isIndeterminate}
-                    onDownArrowClick={onToggle}
-                    isExpanded={isExpanded}
-                />
-            ),
-            [CONST.SEARCH.GROUP_BY.MONTH]: (
-                <MonthListItemHeader
-                    month={groupItem as TransactionMonthGroupListItemType}
-                    onCheckboxPress={handleSelectionButtonPress}
-                    isDisabled={isDisabledOrEmpty}
-                    columns={columns}
-                    canSelectMultiple={canSelectMultiple}
-                    isSelectAllChecked={isSelectAllChecked}
-                    isIndeterminate={isIndeterminate}
-                    onDownArrowClick={onToggle}
-                    isExpanded={isExpanded}
-                />
-            ),
-            [CONST.SEARCH.GROUP_BY.WEEK]: (
-                <WeekListItemHeader
-                    week={groupItem as TransactionWeekGroupListItemType}
-                    onCheckboxPress={handleSelectionButtonPress}
-                    isDisabled={isDisabledOrEmpty}
-                    columns={columns}
-                    canSelectMultiple={canSelectMultiple}
-                    isSelectAllChecked={isSelectAllChecked}
-                    isIndeterminate={isIndeterminate}
-                    onDownArrowClick={onToggle}
-                    isExpanded={isExpanded}
-                />
-            ),
-            [CONST.SEARCH.GROUP_BY.YEAR]: (
-                <YearListItemHeader
-                    year={groupItem as TransactionYearGroupListItemType}
-                    onCheckboxPress={handleSelectionButtonPress}
-                    isDisabled={isDisabledOrEmpty}
-                    columns={columns}
-                    canSelectMultiple={canSelectMultiple}
-                    isSelectAllChecked={isSelectAllChecked}
-                    isIndeterminate={isIndeterminate}
-                    onDownArrowClick={onToggle}
-                    isExpanded={isExpanded}
-                />
-            ),
-            [CONST.SEARCH.GROUP_BY.QUARTER]: (
-                <QuarterListItemHeader
-                    quarter={groupItem as TransactionQuarterGroupListItemType}
-                    onCheckboxPress={handleSelectionButtonPress}
-                    isDisabled={isDisabledOrEmpty}
-                    columns={columns}
-                    canSelectMultiple={canSelectMultiple}
-                    isSelectAllChecked={isSelectAllChecked}
-                    isIndeterminate={isIndeterminate}
-                    onDownArrowClick={onToggle}
-                    isExpanded={isExpanded}
-                />
-            ),
-        };
+        const commonProps = {
+            onCheckboxPress: handleSelectionButtonPress,
+            isDisabled: isDisabledOrEmpty,
+            columns,
+            canSelectMultiple,
+            isSelectAllChecked,
+            isIndeterminate,
+            onDownArrowClick: onToggle,
+            isExpanded,
+        } as const;
 
-        return headers[groupBy];
+        switch (groupBy) {
+            case CONST.SEARCH.GROUP_BY.FROM:
+                return (
+                    <MemberListItemHeader
+                        member={groupItem as TransactionMemberGroupListItemType}
+                        {...commonProps}
+                        isLargeScreenWidth={isLargeScreenWidth}
+                    />
+                );
+            case CONST.SEARCH.GROUP_BY.CARD:
+                return (
+                    <CardListItemHeader
+                        card={groupItem as TransactionCardGroupListItemType}
+                        {...commonProps}
+                        isFocused={isFocused}
+                    />
+                );
+            case CONST.SEARCH.GROUP_BY.WITHDRAWAL_ID:
+                return (
+                    <WithdrawalIDListItemHeader
+                        withdrawalID={groupItem as TransactionWithdrawalIDGroupListItemType}
+                        {...commonProps}
+                    />
+                );
+            case CONST.SEARCH.GROUP_BY.CATEGORY:
+                return (
+                    <CategoryListItemHeader
+                        category={groupItem as TransactionCategoryGroupListItemType}
+                        {...commonProps}
+                    />
+                );
+            case CONST.SEARCH.GROUP_BY.MERCHANT:
+                return (
+                    <MerchantListItemHeader
+                        merchant={groupItem as TransactionMerchantGroupListItemType}
+                        {...commonProps}
+                    />
+                );
+            case CONST.SEARCH.GROUP_BY.TAG:
+                return (
+                    <TagListItemHeader
+                        tag={groupItem as TransactionTagGroupListItemType}
+                        {...commonProps}
+                    />
+                );
+            case CONST.SEARCH.GROUP_BY.MONTH:
+                return (
+                    <MonthListItemHeader
+                        month={groupItem as TransactionMonthGroupListItemType}
+                        {...commonProps}
+                    />
+                );
+            case CONST.SEARCH.GROUP_BY.WEEK:
+                return (
+                    <WeekListItemHeader
+                        week={groupItem as TransactionWeekGroupListItemType}
+                        {...commonProps}
+                    />
+                );
+            case CONST.SEARCH.GROUP_BY.YEAR:
+                return (
+                    <YearListItemHeader
+                        year={groupItem as TransactionYearGroupListItemType}
+                        {...commonProps}
+                    />
+                );
+            case CONST.SEARCH.GROUP_BY.QUARTER:
+                return (
+                    <QuarterListItemHeader
+                        quarter={groupItem as TransactionQuarterGroupListItemType}
+                        {...commonProps}
+                    />
+                );
+            default:
+                return null;
+        }
     };
 
     const isLastItemCollapsed = isLastItem && !isExpanded && !isSubHeaderRendered;
diff --git a/src/components/Search/SearchList/index.tsx b/src/components/Search/SearchList/index.tsx
index 1a1ad0ae80da..17f425704bd7 100644
--- a/src/components/Search/SearchList/index.tsx
+++ b/src/components/Search/SearchList/index.tsx
@@ -33,6 +33,7 @@ import variables from '@styles/variables';
 import type {TransactionPreviewData} from '@userActions/Search';
 import CONST from '@src/CONST';
 import ONYXKEYS from '@src/ONYXKEYS';
+import {columnsSelector} from '@src/selectors/AdvancedSearchFiltersForm';
 import type {CardList, Transaction} from '@src/types/onyx';
 import BaseSearchList from './BaseSearchList';
 import type ChatListItem from './ListItem/ChatListItem';
@@ -338,6 +339,11 @@ function SearchList({
     const [personalPolicyID] = useOnyx(ONYXKEYS.PERSONAL_POLICY_ID);
     const [userBillingGracePeriodEnds] = useOnyx(ONYXKEYS.COLLECTION.SHARED_NVP_PRIVATE_USER_BILLING_GRACE_PERIOD_END);
     const [ownerBillingGracePeriodEnd] = useOnyx(ONYXKEYS.NVP_PRIVATE_OWNER_BILLING_GRACE_PERIOD_END);
+    const [visibleColumns] = useOnyx(ONYXKEYS.FORMS.SEARCH_ADVANCED_FILTERS_FORM, {selector: columnsSelector});
+    const [allReportMetadata] = useOnyx(ONYXKEYS.COLLECTION.REPORT_METADATA);
+    const [bankAccountList] = useOnyx(ONYXKEYS.BANK_ACCOUNT_LIST);
+    const [cardFeeds] = useOnyx(ONYXKEYS.COLLECTION.SHARED_NVP_PRIVATE_DOMAIN_MEMBER);
+    const [conciergeReportID] = useOnyx(ONYXKEYS.CONCIERGE_REPORT_ID);
     const undeleteTransactions = useUndeleteTransactions();
 
     const handleUndelete = (transaction: Transaction) => undeleteTransactions([transaction]);
@@ -492,6 +498,7 @@ function SearchList({
                         personalPolicyID={personalPolicyID}
                         userBillingGracePeriodEnds={userBillingGracePeriodEnds}
                         ownerBillingGracePeriodEnd={ownerBillingGracePeriodEnd}
+                        visibleColumns={visibleColumns}
                     />
                 );
             }
@@ -516,6 +523,10 @@ function SearchList({
                         onUndelete={handleUndelete}
                         isLastItem={index === lastVisibleIndex && !ListFooterComponent}
                         newTransactionID={containerNewTransactionID}
+                        allReportMetadata={allReportMetadata}
+                        bankAccountList={bankAccountList}
+                        cardFeeds={cardFeeds}
+                        conciergeReportID={conciergeReportID}
                     />
                 );
             }
@@ -591,6 +602,11 @@ function SearchList({
             lastVisibleIndex,
             expandedGroups,
             onToggleGroup,
+            allReportMetadata,
+            bankAccountList,
+            cardFeeds,
+            conciergeReportID,
+            visibleColumns,
         ],
     );
 

From 288c0a09545000af2b24a20963be31a61ec774fd Mon Sep 17 00:00:00 2001
From: Adam Grzybowski <adam.grzybowski@swmansion.com>
Date: Mon, 1 Jun 2026 18:53:35 +0200
Subject: [PATCH 084/435] Open transaction thread with review carousel from
 review expenses row

---
 .../MoneyRequestReportTransactionList.tsx     |  55 ++-------
 src/hooks/useNavigateToTransactionThread.ts   |  92 ++++++++++++++
 src/pages/home/ForYouSection/index.tsx        |  21 +---
 .../ForYouSection/useReviewFlaggedExpenses.ts |  52 ++++++++
 src/selectors/Todos.ts                        |  17 ++-
 tests/ui/ForYouSectionTest.tsx                | 116 ++++++++----------
 6 files changed, 227 insertions(+), 126 deletions(-)
 create mode 100644 src/hooks/useNavigateToTransactionThread.ts
 create mode 100644 src/pages/home/ForYouSection/useReviewFlaggedExpenses.ts

diff --git a/src/components/MoneyRequestReportView/MoneyRequestReportTransactionList.tsx b/src/components/MoneyRequestReportView/MoneyRequestReportTransactionList.tsx
index 06671b17d07f..d2df0138c1e8 100644
--- a/src/components/MoneyRequestReportView/MoneyRequestReportTransactionList.tsx
+++ b/src/components/MoneyRequestReportView/MoneyRequestReportTransactionList.tsx
@@ -20,7 +20,6 @@ import SelectionList from '@components/SelectionList';
 import SingleSelectListItem from '@components/SelectionList/ListItem/SingleSelectListItem';
 import SearchRowSkeleton from '@components/Skeletons/SearchRowSkeleton';
 import Text from '@components/Text';
-import {useWideRHPActions} from '@components/WideRHPContextProvider';
 import useCopySelectionHelper from '@hooks/useCopySelectionHelper';
 import {useCurrencyListActions} from '@hooks/useCurrencyList';
 import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails';
@@ -28,6 +27,7 @@ import useHandleSelectionMode from '@hooks/useHandleSelectionMode';
 import {useMemoizedLazyExpensifyIcons} from '@hooks/useLazyAsset';
 import useLocalize from '@hooks/useLocalize';
 import useMobileSelectionMode from '@hooks/useMobileSelectionMode';
+import useNavigateToTransactionThread from '@hooks/useNavigateToTransactionThread';
 import useNetwork from '@hooks/useNetwork';
 import useOnyx from '@hooks/useOnyx';
 import useReportIsArchived from '@hooks/useReportIsArchived';
@@ -38,14 +38,12 @@ import useTheme from '@hooks/useTheme';
 import useThemeStyles from '@hooks/useThemeStyles';
 import useWindowDimensions from '@hooks/useWindowDimensions';
 import {turnOnMobileSelectionMode} from '@libs/actions/MobileSelectionMode';
-import {setOptimisticTransactionThread} from '@libs/actions/Report';
 import {getReportLayoutGroupBy, setReportLayoutGroupBy} from '@libs/actions/ReportLayout';
 import {clearActiveTransactionIDs, setActiveTransactionIDs} from '@libs/actions/TransactionThreadNavigation';
 import {resolveTransactionCardFields} from '@libs/CardUtils';
 import {hasNonReimbursableTransactions, isBillableEnabledOnPolicy} from '@libs/MoneyRequestReportUtils';
 import {navigationRef} from '@libs/Navigation/Navigation';
 import {isPolicyTaxEnabled} from '@libs/PolicyUtils';
-import {getIOUActionForTransactionID} from '@libs/ReportActionsUtils';
 import {groupTransactionsByCategory, groupTransactionsByTag} from '@libs/ReportLayoutUtils';
 import {
     canAddTransaction,
@@ -67,9 +65,7 @@ import {getTransactionPendingAction, isTransactionPendingDelete, shouldShowExpen
 import shouldShowTransactionYear from '@libs/TransactionUtils/shouldShowTransactionYear';
 import isReportOpenInSuperWideRHP from '@navigation/helpers/isReportOpenInSuperWideRHP';
 import Navigation from '@navigation/Navigation';
-import type {ReportsSplitNavigatorParamList} from '@navigation/types';
 import variables from '@styles/variables';
-import {createTransactionThreadReport} from '@userActions/Report';
 import CONST from '@src/CONST';
 import type {TranslationPaths} from '@src/languages/types';
 import NAVIGATORS from '@src/NAVIGATORS';
@@ -123,8 +119,6 @@ type TransactionWithOptionalHighlight = OnyxTypes.Transaction & {
     shouldBeHighlighted?: boolean;
 };
 
-type ReportScreenNavigationProps = ReportsSplitNavigatorParamList[typeof SCREENS.REPORT];
-
 type SortedTransactions = {
     sortBy: SortableColumnName;
     sortOrder: SortOrder;
@@ -152,7 +146,7 @@ function MoneyRequestReportTransactionList({
     // eslint-disable-next-line rulesdir/prefer-shouldUseNarrowLayout-instead-of-isSmallScreenWidth
     const {isSmallScreenWidth, isMediumScreenWidth, isInLandscapeMode} = useResponsiveLayout();
     const {shouldUseNarrowLayout} = useResponsiveLayoutOnWideRHP();
-    const {markReportIDAsExpense} = useWideRHPActions();
+    const navigateToTransactionThread = useNavigateToTransactionThread();
     const [isModalVisible, setIsModalVisible] = useState(false);
     const [selectedTransactionID, setSelectedTransactionID] = useState<string>('');
     const {reportPendingAction} = getReportOfflinePendingActionAndErrors(report);
@@ -177,8 +171,6 @@ function MoneyRequestReportTransactionList({
     const [reportLayoutGroupBy] = useOnyx(ONYXKEYS.NVP_REPORT_LAYOUT_GROUP_BY);
     const [amountOwed] = useOnyx(ONYXKEYS.NVP_PRIVATE_AMOUNT_OWED);
     const [reportDetailsColumns] = useOnyx(ONYXKEYS.NVP_REPORT_DETAILS_COLUMNS);
-    const [introSelected] = useOnyx(ONYXKEYS.NVP_INTRO_SELECTED);
-    const [betas] = useOnyx(ONYXKEYS.BETAS);
     const [nonPersonalAndWorkspaceCards] = useOnyx(ONYXKEYS.DERIVED.NON_PERSONAL_AND_WORKSPACE_CARD_LIST);
     const [cardList] = useOnyx(ONYXKEYS.CARD_LIST);
     const [draftTransactionIDs] = useOnyx(ONYXKEYS.COLLECTION.TRANSACTION_DRAFT, {selector: validTransactionDraftIDsSelector});
@@ -464,44 +456,15 @@ function MoneyRequestReportTransactionList({
      */
     const navigateToTransaction = useCallback(
         (activeTransactionID: string) => {
-            const iouAction = getIOUActionForTransactionID(reportActions, activeTransactionID);
-            const backTo = Navigation.getActiveRoute();
-            let reportIDToNavigate = iouAction?.childReportID;
-
-            const routeParams = {
-                reportID: reportIDToNavigate,
-                backTo,
-            } as ReportScreenNavigationProps;
-
-            if (!reportIDToNavigate) {
-                const transaction = sortedTransactions.find((t) => t.transactionID === activeTransactionID);
-                const transactionThreadReport = createTransactionThreadReport({
-                    introSelected,
-                    currentUserLogin: currentUserDetails.email ?? '',
-                    currentUserAccountID: currentUserDetails.accountID,
-                    betas,
-                    iouReport: report,
-                    iouReportAction: iouAction,
-                    transaction,
-                });
-                if (transactionThreadReport) {
-                    reportIDToNavigate = transactionThreadReport.reportID;
-                    routeParams.reportID = reportIDToNavigate;
-                }
-            } else {
-                setOptimisticTransactionThread(reportIDToNavigate, report?.reportID, iouAction?.reportActionID, report?.policyID);
-            }
-
-            // Single transaction report will open in RHP, and we need to find every other report ID for the rest of transactions
-            // to display prev/next arrows in RHP for navigation - use visual order from grouped transactions
-            setActiveTransactionIDs(visualOrderTransactionIDs).then(() => {
-                if (reportIDToNavigate) {
-                    markReportIDAsExpense(reportIDToNavigate);
-                }
-                Navigation.navigate(ROUTES.SEARCH_REPORT.getRoute(routeParams));
+            navigateToTransactionThread({
+                transactionID: activeTransactionID,
+                reportActions,
+                report,
+                transaction: sortedTransactions.find((t) => t.transactionID === activeTransactionID),
+                siblingTransactionIDs: visualOrderTransactionIDs,
             });
         },
-        [reportActions, visualOrderTransactionIDs, sortedTransactions, report, markReportIDAsExpense, introSelected, betas, currentUserDetails.email, currentUserDetails.accountID],
+        [navigateToTransactionThread, reportActions, sortedTransactions, report, visualOrderTransactionIDs],
     );
 
     const {amountColumnSize, dateColumnSize, taxAmountColumnSize} = useMemo(() => {
diff --git a/src/hooks/useNavigateToTransactionThread.ts b/src/hooks/useNavigateToTransactionThread.ts
new file mode 100644
index 000000000000..f6678e419216
--- /dev/null
+++ b/src/hooks/useNavigateToTransactionThread.ts
@@ -0,0 +1,92 @@
+import {useCallback} from 'react';
+import type {OnyxEntry} from 'react-native-onyx';
+import {useWideRHPActions} from '@components/WideRHPContextProvider';
+import {createTransactionThreadReport, setOptimisticTransactionThread} from '@libs/actions/Report';
+import {setActiveTransactionIDs} from '@libs/actions/TransactionThreadNavigation';
+import Navigation from '@libs/Navigation/Navigation';
+import {getIOUActionForTransactionID} from '@libs/ReportActionsUtils';
+import ONYXKEYS from '@src/ONYXKEYS';
+import ROUTES from '@src/ROUTES';
+import type {Report, ReportAction, Transaction} from '@src/types/onyx';
+import useCurrentUserPersonalDetails from './useCurrentUserPersonalDetails';
+import useOnyx from './useOnyx';
+
+type NavigateToTransactionThreadParams = {
+    /** The transaction whose thread should be opened */
+    transactionID: string;
+
+    /** Report actions of the parent (IOU/expense) report, used to resolve the IOU action and its thread */
+    reportActions: ReportAction[];
+
+    /** The parent (IOU/expense) report that owns the transaction */
+    report: OnyxEntry<Report>;
+
+    /** The transaction being opened, used to build the thread optimistically when it doesn't exist yet */
+    transaction: OnyxEntry<Transaction>;
+
+    /** Ordered list of sibling transaction IDs used to drive the prev/next carousel in the thread RHP */
+    siblingTransactionIDs: string[];
+
+    /** Route to return to when navigating back; defaults to the current active route */
+    backTo?: string;
+};
+
+/**
+ * Shared navigation algorithm for opening a transaction thread (single-expense RHP view with the
+ * prev/next carousel). It resolves the IOU action's `childReportID`, creates the thread optimistically
+ * when it doesn't exist yet, seeds the sibling transaction IDs for the carousel, and navigates to the
+ * SEARCH_REPORT route.
+ *
+ * Callers are responsible for gathering their own `reportActions`, `report`, `transaction`, and
+ * `siblingTransactionIDs` because the data sources differ per screen.
+ */
+function useNavigateToTransactionThread() {
+    const {markReportIDAsExpense} = useWideRHPActions();
+    const currentUserDetails = useCurrentUserPersonalDetails();
+    const [introSelected] = useOnyx(ONYXKEYS.NVP_INTRO_SELECTED);
+    const [betas] = useOnyx(ONYXKEYS.BETAS);
+
+    return useCallback(
+        ({transactionID, reportActions, report, transaction, siblingTransactionIDs, backTo}: NavigateToTransactionThreadParams) => {
+            const iouAction = getIOUActionForTransactionID(reportActions, transactionID);
+            const resolvedBackTo = backTo ?? Navigation.getActiveRoute();
+            let reportIDToNavigate = iouAction?.childReportID;
+
+            const routeParams: {reportID: string | undefined; reportActionID?: string; backTo?: string} = {
+                reportID: reportIDToNavigate,
+                backTo: resolvedBackTo,
+            };
+
+            if (!reportIDToNavigate) {
+                const transactionThreadReport = createTransactionThreadReport({
+                    introSelected,
+                    currentUserLogin: currentUserDetails.email ?? '',
+                    currentUserAccountID: currentUserDetails.accountID,
+                    betas,
+                    iouReport: report,
+                    iouReportAction: iouAction,
+                    transaction,
+                });
+                if (transactionThreadReport) {
+                    reportIDToNavigate = transactionThreadReport.reportID;
+                    routeParams.reportID = reportIDToNavigate;
+                }
+            } else {
+                setOptimisticTransactionThread(reportIDToNavigate, report?.reportID, iouAction?.reportActionID, report?.policyID);
+            }
+
+            // Single transaction report opens in RHP. We seed every sibling transaction ID so the RHP can
+            // display prev/next arrows for navigation between expenses.
+            setActiveTransactionIDs(siblingTransactionIDs).then(() => {
+                if (reportIDToNavigate) {
+                    markReportIDAsExpense(reportIDToNavigate);
+                }
+                Navigation.navigate(ROUTES.SEARCH_REPORT.getRoute(routeParams));
+            });
+        },
+        [markReportIDAsExpense, introSelected, betas, currentUserDetails.email, currentUserDetails.accountID],
+    );
+}
+
+export default useNavigateToTransactionThread;
+export type {NavigateToTransactionThreadParams};
diff --git a/src/pages/home/ForYouSection/index.tsx b/src/pages/home/ForYouSection/index.tsx
index 9e275e365a79..8062d2706f9a 100644
--- a/src/pages/home/ForYouSection/index.tsx
+++ b/src/pages/home/ForYouSection/index.tsx
@@ -16,9 +16,10 @@ import CONST from '@src/CONST';
 import ONYXKEYS from '@src/ONYXKEYS';
 import ROUTES from '@src/ROUTES';
 import {accountIDSelector} from '@src/selectors/Session';
-import todosReportCountsSelector, {EMPTY_FLAGGED_EXPENSES_REVIEW, EMPTY_TODOS_SINGLE_REPORT_IDS, flaggedExpensesReviewSelector, todosSingleReportIDsSelector} from '@src/selectors/Todos';
+import todosReportCountsSelector, {EMPTY_TODOS_SINGLE_REPORT_IDS, todosSingleReportIDsSelector} from '@src/selectors/Todos';
 import EmptyState from './EmptyState';
 import ForYouSkeleton from './ForYouSkeleton';
+import useReviewFlaggedExpenses from './useReviewFlaggedExpenses';
 
 function ForYouSection() {
     const styles = useThemeStyles();
@@ -30,7 +31,7 @@ function ForYouSection() {
     const [isLoadingReportData = false] = useOnyx(ONYXKEYS.IS_LOADING_REPORT_DATA);
     const [reportCounts = CONST.EMPTY_TODOS_REPORT_COUNTS] = useOnyx(ONYXKEYS.DERIVED.TODOS, {selector: todosReportCountsSelector});
     const [singleReportIDs = EMPTY_TODOS_SINGLE_REPORT_IDS] = useOnyx(ONYXKEYS.DERIVED.TODOS, {selector: todosSingleReportIDsSelector});
-    const [flaggedExpensesReview = EMPTY_FLAGGED_EXPENSES_REVIEW] = useOnyx(ONYXKEYS.DERIVED.FLAGGED_EXPENSES, {selector: flaggedExpensesReviewSelector});
+    const {count: flaggedExpensesCount, reviewExpenses} = useReviewFlaggedExpenses();
 
     const icons = useMemoizedLazyExpensifyIcons(['ReceiptSearch', 'MoneyBag', 'Send', 'ThumbsUp', 'Export']);
 
@@ -38,7 +39,6 @@ function ForYouSection() {
     const approveCount = reportCounts?.[CONST.SEARCH.SEARCH_KEYS.APPROVE] ?? 0;
     const payCount = reportCounts?.[CONST.SEARCH.SEARCH_KEYS.PAY] ?? 0;
     const exportCount = reportCounts?.[CONST.SEARCH.SEARCH_KEYS.EXPORT] ?? 0;
-    const flaggedExpensesCount = flaggedExpensesReview.count;
 
     const hasAnyTodos = flaggedExpensesCount > 0 || submitCount > 0 || approveCount > 0 || payCount > 0 || exportCount > 0;
 
@@ -73,16 +73,6 @@ function ForYouSection() {
         [navigateToReport],
     );
 
-    const createReviewExpensesHandler = useCallback(
-        (firstReportID: string | undefined) => () => {
-            if (!firstReportID) {
-                return;
-            }
-            navigateToReport(firstReportID);
-        },
-        [navigateToReport],
-    );
-
     const todoItems = useMemo(
         () =>
             [
@@ -93,7 +83,7 @@ function ForYouSection() {
                     iconBackgroundColor: colors.tangerine100,
                     iconFill: colors.tangerine500,
                     translationKey: 'homePage.forYouSection.reviewExpenses' as const,
-                    handler: createReviewExpensesHandler(flaggedExpensesReview.firstReportID),
+                    handler: reviewExpenses,
                     buttonProps: {danger: true} as const,
                 },
                 {
@@ -137,10 +127,9 @@ function ForYouSection() {
             accountID,
             approveCount,
             createNavigationHandler,
-            createReviewExpensesHandler,
+            reviewExpenses,
             exportCount,
             flaggedExpensesCount,
-            flaggedExpensesReview.firstReportID,
             icons.Export,
             icons.MoneyBag,
             icons.ReceiptSearch,
diff --git a/src/pages/home/ForYouSection/useReviewFlaggedExpenses.ts b/src/pages/home/ForYouSection/useReviewFlaggedExpenses.ts
new file mode 100644
index 000000000000..c04331a02291
--- /dev/null
+++ b/src/pages/home/ForYouSection/useReviewFlaggedExpenses.ts
@@ -0,0 +1,52 @@
+import {useCallback} from 'react';
+import useNavigateToTransactionThread from '@hooks/useNavigateToTransactionThread';
+import useOnyx from '@hooks/useOnyx';
+import getNonEmptyStringOnyxID from '@libs/getNonEmptyStringOnyxID';
+import ONYXKEYS from '@src/ONYXKEYS';
+import ROUTES from '@src/ROUTES';
+import {EMPTY_FLAGGED_EXPENSES_REVIEW, flaggedExpensesReviewSelector} from '@src/selectors/Todos';
+
+type ReviewFlaggedExpenses = {
+    /** Number of flagged expenses awaiting review, used to decide whether to render the review row */
+    count: number;
+
+    /** Opens the first flagged expense's transaction thread with the full set of flagged expenses as the review carousel */
+    reviewExpenses: () => void;
+};
+
+/**
+ * Encapsulates the data plumbing for the "Review X expenses" row in the For You section: it reads the
+ * flagged-expenses review summary plus the first flagged expense's report, report actions, and transaction,
+ * and exposes a bound handler that navigates to the transaction thread (single-expense RHP + review carousel).
+ */
+function useReviewFlaggedExpenses(): ReviewFlaggedExpenses {
+    const [review = EMPTY_FLAGGED_EXPENSES_REVIEW] = useOnyx(ONYXKEYS.DERIVED.FLAGGED_EXPENSES, {selector: flaggedExpensesReviewSelector});
+
+    // Load the first flagged expense's parent report, its actions, and the transaction itself so the shared
+    // navigation hook can resolve (or optimistically create) the transaction thread.
+    const [firstFlaggedReport] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${getNonEmptyStringOnyxID(review.firstReportID)}`);
+    const [firstFlaggedReportActions] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${getNonEmptyStringOnyxID(review.firstReportID)}`);
+    const [firstFlaggedTransaction] = useOnyx(`${ONYXKEYS.COLLECTION.TRANSACTION}${getNonEmptyStringOnyxID(review.firstTransactionID)}`);
+
+    const navigateToTransactionThread = useNavigateToTransactionThread();
+
+    const reviewExpenses = useCallback(() => {
+        const {firstTransactionID, firstReportID, transactionIDs} = review;
+        if (!firstTransactionID || !firstReportID) {
+            return;
+        }
+        navigateToTransactionThread({
+            transactionID: firstTransactionID,
+            reportActions: Object.values(firstFlaggedReportActions ?? {}),
+            report: firstFlaggedReport,
+            transaction: firstFlaggedTransaction,
+            siblingTransactionIDs: transactionIDs,
+            backTo: ROUTES.HOME,
+        });
+    }, [review, firstFlaggedReportActions, firstFlaggedReport, firstFlaggedTransaction, navigateToTransactionThread]);
+
+    return {count: review.count, reviewExpenses};
+}
+
+export default useReviewFlaggedExpenses;
+export type {ReviewFlaggedExpenses};
diff --git a/src/selectors/Todos.ts b/src/selectors/Todos.ts
index 84ff216de5c0..e0e8eb3565ad 100644
--- a/src/selectors/Todos.ts
+++ b/src/selectors/Todos.ts
@@ -73,12 +73,15 @@ type FlaggedExpensesReview = {
     firstTransactionID: string | undefined;
     /** Parent report ID of the first flagged expense */
     firstReportID: string | undefined;
+    /** Ordered list of every flagged transaction ID, used to drive the prev/next review carousel */
+    transactionIDs: string[];
 };
 
 const EMPTY_FLAGGED_EXPENSES_REVIEW: FlaggedExpensesReview = Object.freeze({
     count: 0,
     firstTransactionID: undefined,
     firstReportID: undefined,
+    transactionIDs: [],
 }) as FlaggedExpensesReview;
 
 // Manual memoization mirrors `todosSingleReportIDsSelector`: ForYouSection's useMemo dependency
@@ -94,13 +97,25 @@ const flaggedExpensesReviewSelector = (flaggedExpensesValue: OnyxEntry<FlaggedEx
     }
 
     const first = flaggedExpenses.at(0);
+    const transactionIDs = flaggedExpenses.map((flaggedExpense) => flaggedExpense.transactionID);
     const newValue: FlaggedExpensesReview = {
         count: flaggedExpenses.length,
         firstTransactionID: first?.transactionID,
         firstReportID: first?.reportID,
+        transactionIDs,
     };
 
-    if (shallowEqual(previousFlaggedExpensesReview, newValue)) {
+    // shallowEqual would always report a difference because `transactionIDs` is a fresh array each call,
+    // so we compare the scalar fields shallowly and the IDs element-by-element to preserve referential stability.
+    const previousTransactionIDs = previousFlaggedExpensesReview.transactionIDs;
+    const areTransactionIDsEqual =
+        previousTransactionIDs.length === transactionIDs.length && previousTransactionIDs.every((transactionID, index) => transactionID === transactionIDs.at(index));
+    if (
+        previousFlaggedExpensesReview.count === newValue.count &&
+        previousFlaggedExpensesReview.firstTransactionID === newValue.firstTransactionID &&
+        previousFlaggedExpensesReview.firstReportID === newValue.firstReportID &&
+        areTransactionIDsEqual
+    ) {
         return previousFlaggedExpensesReview;
     }
 
diff --git a/tests/ui/ForYouSectionTest.tsx b/tests/ui/ForYouSectionTest.tsx
index 196df710f2be..14877cc43c75 100644
--- a/tests/ui/ForYouSectionTest.tsx
+++ b/tests/ui/ForYouSectionTest.tsx
@@ -4,6 +4,7 @@ import Onyx from 'react-native-onyx';
 import useResponsiveLayout from '@hooks/useResponsiveLayout';
 import Navigation from '@libs/Navigation/Navigation';
 import ForYouSection from '@pages/home/ForYouSection';
+import CONST from '@src/CONST';
 import ONYXKEYS from '@src/ONYXKEYS';
 import ROUTES from '@src/ROUTES';
 import type {FlaggedExpensesDerivedValue, TodosDerivedValue} from '@src/types/onyx';
@@ -17,6 +18,9 @@ jest.mock('@libs/Navigation/Navigation', () => ({
 
 jest.mock('@hooks/useResponsiveLayout', () => jest.fn());
 
+const mockNavigateToTransactionThread = jest.fn();
+jest.mock('@hooks/useNavigateToTransactionThread', () => jest.fn(() => mockNavigateToTransactionThread));
+
 jest.mock('@hooks/useLocalize', () =>
     jest.fn(() => ({
         translate: jest.fn((key: string, params?: Record<string, unknown>) => {
@@ -248,81 +252,67 @@ describe('ForYouSection', () => {
     });
 
     describe('review row navigation', () => {
-        describe('wide layout', () => {
-            it('navigates to EXPENSE_REPORT_RHP with the first flagged expense parent report and backTo=HOME', async () => {
-                await act(async () => {
-                    await Onyx.set(ONYXKEYS.DERIVED.TODOS, BASE_TODOS);
-                    await Onyx.set(ONYXKEYS.DERIVED.FLAGGED_EXPENSES, {
-                        flaggedExpenses: [
-                            {transactionID: 't1', reportID: 'r1'},
-                            {transactionID: 't2', reportID: 'r2'},
-                        ],
-                    });
+        it('delegates to useNavigateToTransactionThread with the first flagged expense and all sibling transaction IDs', async () => {
+            await act(async () => {
+                await Onyx.set(ONYXKEYS.DERIVED.TODOS, BASE_TODOS);
+                await Onyx.set(ONYXKEYS.DERIVED.FLAGGED_EXPENSES, {
+                    flaggedExpenses: [
+                        {transactionID: 't1', reportID: 'r1'},
+                        {transactionID: 't2', reportID: 'r2'},
+                    ],
                 });
-                await waitForBatchedUpdatesWithAct();
-
-                renderForYouSection();
-                await waitForBatchedUpdatesWithAct();
-
-                pressFirstBeginButton();
-
-                expect(mockNavigate).toHaveBeenCalledTimes(1);
-                expect(mockNavigate).toHaveBeenCalledWith(ROUTES.EXPENSE_REPORT_RHP.getRoute({reportID: 'r1', backTo: ROUTES.HOME}));
-            });
-
-            it('still uses the per-report RHP route when only one expense is flagged', async () => {
-                await act(async () => {
-                    await Onyx.set(ONYXKEYS.DERIVED.TODOS, BASE_TODOS);
-                    await Onyx.set(ONYXKEYS.DERIVED.FLAGGED_EXPENSES, {
-                        flaggedExpenses: [{transactionID: 't1', reportID: 'rOnly'}],
-                    });
+                await Onyx.set(`${ONYXKEYS.COLLECTION.REPORT}r1`, {reportID: 'r1'});
+                await Onyx.set(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}r1`, {
+                    action1: {
+                        reportActionID: 'action1',
+                        actionName: CONST.REPORT.ACTIONS.TYPE.IOU,
+                        childReportID: 'thread-r1',
+                        message: {IOUTransactionID: 't1'},
+                    },
                 });
-                await waitForBatchedUpdatesWithAct();
+                await Onyx.set(`${ONYXKEYS.COLLECTION.TRANSACTION}t1`, {transactionID: 't1', reportID: 'r1'});
+            });
+            await waitForBatchedUpdatesWithAct();
 
-                renderForYouSection();
-                await waitForBatchedUpdatesWithAct();
+            renderForYouSection();
+            await waitForBatchedUpdatesWithAct();
 
-                pressFirstBeginButton();
+            pressFirstBeginButton();
 
-                expect(mockNavigate).toHaveBeenCalledTimes(1);
-                expect(mockNavigate).toHaveBeenCalledWith(ROUTES.EXPENSE_REPORT_RHP.getRoute({reportID: 'rOnly', backTo: ROUTES.HOME}));
-            });
+            expect(mockNavigateToTransactionThread).toHaveBeenCalledTimes(1);
+            expect(mockNavigateToTransactionThread).toHaveBeenCalledWith(
+                expect.objectContaining({
+                    transactionID: 't1',
+                    report: expect.objectContaining({reportID: 'r1'}),
+                    transaction: expect.objectContaining({transactionID: 't1'}),
+                    reportActions: expect.arrayContaining([expect.objectContaining({reportActionID: 'action1', childReportID: 'thread-r1'})]),
+                    siblingTransactionIDs: ['t1', 't2'],
+                    backTo: ROUTES.HOME,
+                }),
+            );
+            // The standard report routes should not be used for the review row anymore.
+            expect(mockNavigate).not.toHaveBeenCalled();
         });
 
-        describe('narrow layout', () => {
-            beforeEach(() => {
-                mockUseResponsiveLayout.mockReturnValue({
-                    shouldUseNarrowLayout: true,
-                    isSmallScreenWidth: true,
-                    isInNarrowPaneModal: false,
-                    isExtraSmallScreenHeight: false,
-                    isMediumScreenWidth: false,
-                    isLargeScreenWidth: false,
-                    isExtraLargeScreenWidth: false,
-                    isExtraSmallScreenWidth: false,
-                    isSmallScreen: true,
-                    onboardingIsMediumOrLargerScreenWidth: false,
-                    isInLandscapeMode: false,
+        it('does not call the hook when there is no flagged transaction or report', async () => {
+            await act(async () => {
+                await Onyx.set(ONYXKEYS.DERIVED.TODOS, BASE_TODOS);
+                // count > 0 keeps the row rendered, but the first transaction/report are missing
+                await Onyx.set(ONYXKEYS.DERIVED.FLAGGED_EXPENSES, {
+                    flaggedExpenses: [{transactionID: '', reportID: ''}],
                 });
             });
+            await waitForBatchedUpdatesWithAct();
 
-            it('navigates to REPORT_WITH_ID with the first flagged expense parent report and backTo=HOME', async () => {
-                await act(async () => {
-                    await Onyx.set(ONYXKEYS.DERIVED.TODOS, BASE_TODOS);
-                    await Onyx.set(ONYXKEYS.DERIVED.FLAGGED_EXPENSES, {
-                        flaggedExpenses: [{transactionID: 't1', reportID: 'rNarrow'}],
-                    });
-                });
-                await waitForBatchedUpdatesWithAct();
-
-                renderForYouSection();
-                await waitForBatchedUpdatesWithAct();
+            renderForYouSection();
+            await waitForBatchedUpdatesWithAct();
 
-                pressFirstBeginButton();
+            const beginButton = screen.queryByText('Begin');
+            if (beginButton) {
+                fireEvent.press(beginButton);
+            }
 
-                expect(mockNavigate).toHaveBeenCalledTimes(1);
-                expect(mockNavigate).toHaveBeenCalledWith(ROUTES.REPORT_WITH_ID.getRoute('rNarrow', undefined, undefined, ROUTES.HOME));
-            });
+            expect(mockNavigateToTransactionThread).not.toHaveBeenCalled();
         });
     });
 

From bb880dcc4d57f368f009a71ca369f4a352261aa2 Mon Sep 17 00:00:00 2001
From: krishna2323 <belivethatkg@gmail.com>
Date: Mon, 1 Jun 2026 22:33:44 +0530
Subject: [PATCH 085/435] =?UTF-8?q?fix:=20Polish=20sticky=20group=20header?=
 =?UTF-8?q?=20styling=20=E2=80=94=20border=20timing,=20selection=20highlig?=
 =?UTF-8?q?ht,=20and=20padding?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Signed-off-by: krishna2323 <belivethatkg@gmail.com>
---
 .../ListItem/GroupChildrenContainer.tsx       |  9 +--
 .../ListItem/GroupChildrenContent.tsx         | 62 +++++++++++--------
 .../SearchList/ListItem/GroupHeader.tsx       |  4 +-
 src/components/Search/SearchList/index.tsx    |  3 +
 4 files changed, 44 insertions(+), 34 deletions(-)

diff --git a/src/components/Search/SearchList/ListItem/GroupChildrenContainer.tsx b/src/components/Search/SearchList/ListItem/GroupChildrenContainer.tsx
index 104b5e91ba35..46378225b91e 100644
--- a/src/components/Search/SearchList/ListItem/GroupChildrenContainer.tsx
+++ b/src/components/Search/SearchList/ListItem/GroupChildrenContainer.tsx
@@ -28,6 +28,7 @@ type GroupChildrenContainerProps = {
     nonPersonalAndWorkspaceCards?: CardList;
     onUndelete?: (transaction: Transaction) => void;
     isLastItem?: boolean;
+    isSelected?: boolean;
     newTransactionID?: string;
     allReportMetadata?: OnyxCollection<ReportMetadata>;
     bankAccountList?: OnyxEntry<BankAccountList>;
@@ -48,6 +49,7 @@ function GroupChildrenContainer({
     nonPersonalAndWorkspaceCards,
     onUndelete,
     isLastItem,
+    isSelected,
     newTransactionID,
     allReportMetadata,
     bankAccountList,
@@ -100,7 +102,7 @@ function GroupChildrenContainer({
     }
 
     return (
-        <View style={[styles.mh5, {backgroundColor: theme.highlightBG}, isLastItem && [styles.tableBottomRadius, styles.overflowHidden]]}>
+        <View style={[styles.mh5, {backgroundColor: isSelected ? theme.activeComponentBG : theme.highlightBG}, isLastItem && [styles.tableBottomRadius, styles.overflowHidden]]}>
             <Animated.View style={contentAnimatedStyle}>
                 {(isExpanded || isRendered) && (
                     <Animated.View
@@ -112,11 +114,6 @@ function GroupChildrenContainer({
                             }
                         }}
                     >
-                        {!isLargeScreenWidth && (
-                            <View style={styles.ph3}>
-                                <View style={styles.borderBottom} />
-                            </View>
-                        )}
                         <GroupChildrenContent
                             item={item}
                             isExpanded={isExpanded}
diff --git a/src/components/Search/SearchList/ListItem/GroupChildrenContent.tsx b/src/components/Search/SearchList/ListItem/GroupChildrenContent.tsx
index 8ab547e70d44..1ee4273dbd8c 100644
--- a/src/components/Search/SearchList/ListItem/GroupChildrenContent.tsx
+++ b/src/components/Search/SearchList/ListItem/GroupChildrenContent.tsx
@@ -1,5 +1,6 @@
 import {useIsFocused} from '@react-navigation/native';
 import React, {useEffect, useMemo, useState} from 'react';
+import {View} from 'react-native';
 import type {OnyxCollection, OnyxEntry} from 'react-native-onyx';
 import {useSearchSelectionContext} from '@components/Search/SearchContext';
 import type {SearchColumnType, SearchGroupBy} from '@components/Search/types';
@@ -9,6 +10,8 @@ import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails'
 import useLocalize from '@hooks/useLocalize';
 import useNetwork from '@hooks/useNetwork';
 import useOnyx from '@hooks/useOnyx';
+import useResponsiveLayout from '@hooks/useResponsiveLayout';
+import useThemeStyles from '@hooks/useThemeStyles';
 import {search} from '@libs/actions/Search';
 import type {TransactionPreviewData} from '@libs/actions/Search';
 import type {ModifiedMouseEvent} from '@libs/Navigation/helpers/openInternalRouteInNewTab';
@@ -64,6 +67,8 @@ function GroupChildrenContent({
     const isScreenFocused = useIsFocused();
     const {convertToDisplayString} = useCurrencyListActions();
     const {isOffline} = useNetwork();
+    const styles = useThemeStyles();
+    const {isLargeScreenWidth} = useResponsiveLayout();
 
     const groupItem = item as unknown as TransactionGroupListItemType;
     const isExpenseReportType = searchType === CONST.SEARCH.DATA_TYPES.EXPENSE_REPORT;
@@ -220,31 +225,38 @@ function GroupChildrenContent({
     };
 
     return (
-        <TransactionGroupListExpandedItem
-            showTooltip
-            canSelectMultiple={canSelectMultiple}
-            onSelectionButtonPress={onCheckboxPress}
-            onSelectRow={onSelectRow}
-            columns={columns}
-            groupBy={groupBy}
-            accountID={currentUserDetails.accountID}
-            isOffline={isOffline}
-            violations={filteredViolations}
-            transactions={transactions}
-            transactionsVisibleLimit={transactionsVisibleLimit}
-            setTransactionsVisibleLimit={setTransactionsVisibleLimit}
-            isEmpty={isEmpty}
-            shouldDisplayEmptyView={shouldDisplayEmptyView}
-            isExpenseReportType={isExpenseReportType}
-            transactionsSnapshot={transactionsSnapshot}
-            transactionsQueryJSON={groupItem.transactionsQueryJSON}
-            searchTransactions={searchTransactions}
-            isInSingleTransactionReport={groupItem.transactions.length === 1}
-            onLongPress={onExpandedRowLongPress}
-            nonPersonalAndWorkspaceCards={nonPersonalAndWorkspaceCards}
-            onUndelete={onUndelete}
-            hideSearchTableHeader
-        />
+        <>
+            {isLargeScreenWidth && !isEmpty && (
+                <View style={styles.ph3}>
+                    <View style={styles.borderBottom} />
+                </View>
+            )}
+            <TransactionGroupListExpandedItem
+                showTooltip
+                canSelectMultiple={canSelectMultiple}
+                onSelectionButtonPress={onCheckboxPress}
+                onSelectRow={onSelectRow}
+                columns={columns}
+                groupBy={groupBy}
+                accountID={currentUserDetails.accountID}
+                isOffline={isOffline}
+                violations={filteredViolations}
+                transactions={transactions}
+                transactionsVisibleLimit={transactionsVisibleLimit}
+                setTransactionsVisibleLimit={setTransactionsVisibleLimit}
+                isEmpty={isEmpty}
+                shouldDisplayEmptyView={shouldDisplayEmptyView}
+                isExpenseReportType={isExpenseReportType}
+                transactionsSnapshot={transactionsSnapshot}
+                transactionsQueryJSON={groupItem.transactionsQueryJSON}
+                searchTransactions={searchTransactions}
+                isInSingleTransactionReport={groupItem.transactions.length === 1}
+                onLongPress={onExpandedRowLongPress}
+                nonPersonalAndWorkspaceCards={nonPersonalAndWorkspaceCards}
+                onUndelete={onUndelete}
+                hideSearchTableHeader
+            />
+        </>
     );
 }
 
diff --git a/src/components/Search/SearchList/ListItem/GroupHeader.tsx b/src/components/Search/SearchList/ListItem/GroupHeader.tsx
index a4b54edd3c12..f2e6eff765a1 100644
--- a/src/components/Search/SearchList/ListItem/GroupHeader.tsx
+++ b/src/components/Search/SearchList/ListItem/GroupHeader.tsx
@@ -373,7 +373,6 @@ function GroupHeader({
         isLargeScreenWidth && {
             ...styles.tableRowHeight,
             borderRadius: 0,
-            paddingVertical: variables.tableGroupRowPaddingVertical,
             ...(isLastItemCollapsed ? styles.tableBottomRadius : {}),
         },
         isItemSelected && styles.activeComponentBG,
@@ -456,7 +455,7 @@ function GroupHeader({
                                 </PressableWithFeedback>
                             )}
                         </View>
-                        {isLargeScreenWidth && (
+                        {isLargeScreenWidth && subHeaderColumns.length > 0 && (
                             <Animated.View style={subHeaderAnimatedStyle}>
                                 {(isExpanded || isSubHeaderRendered) && (
                                     <View
@@ -488,7 +487,6 @@ function GroupHeader({
                                                 isActionColumnWide={isSubHeaderActionColumnWide}
                                             />
                                         </View>
-                                        <View style={[StyleUtils.getSelectedBorderBottomStyle(isItemSelected), styles.ml3, styles.mr3, {marginBottom: 1}]} />
                                     </View>
                                 )}
                             </Animated.View>
diff --git a/src/components/Search/SearchList/index.tsx b/src/components/Search/SearchList/index.tsx
index 17f425704bd7..6c59676e305f 100644
--- a/src/components/Search/SearchList/index.tsx
+++ b/src/components/Search/SearchList/index.tsx
@@ -508,10 +508,13 @@ function SearchList({
                 const containerItem = item as GroupChildrenContainerItemType;
                 const originalKey = (item.keyForList ?? '').replace('children_', '');
                 const containerNewTransactionID = item.keyForList ? newTransactionIDByItemKey.get(originalKey) : undefined;
+                const isContainerSelected =
+                    !!containerItem.isSelected || (containerItem.transactions.length > 0 && containerItem.transactions.every((t) => selectedTransactions[t.transactionID]?.isSelected));
                 return (
                     <GroupChildrenContainer
                         item={containerItem}
                         isExpanded={expandedGroups.has(originalKey)}
+                        isSelected={isContainerSelected}
                         groupBy={groupBy}
                         searchType={type}
                         columns={columns}

From 7ff6727fee47a9ea961821cca087a3798826a3ed Mon Sep 17 00:00:00 2001
From: Adam Grzybowski <adam.grzybowski@swmansion.com>
Date: Mon, 1 Jun 2026 19:05:09 +0200
Subject: [PATCH 086/435] Fix cspell errors by renaming reflaggedResult to
 reFlaggedResult

---
 tests/unit/OnyxDerived/flaggedExpensesTest.ts | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/tests/unit/OnyxDerived/flaggedExpensesTest.ts b/tests/unit/OnyxDerived/flaggedExpensesTest.ts
index 4b59525f2d10..fdb04dfc6cde 100644
--- a/tests/unit/OnyxDerived/flaggedExpensesTest.ts
+++ b/tests/unit/OnyxDerived/flaggedExpensesTest.ts
@@ -218,7 +218,7 @@ describe('flaggedExpenses derived value', () => {
             const clearedResult = compute([buildReports(report), buildTransactions(transaction), buildViolations({t1: []}), createSession()], emptyContext);
             expect(clearedResult.flaggedExpenses).toEqual([]);
 
-            const reflaggedResult = compute(
+            const reFlaggedResult = compute(
                 [
                     buildReports(report),
                     buildTransactions(transaction),
@@ -229,8 +229,8 @@ describe('flaggedExpenses derived value', () => {
                 ],
                 emptyContext,
             );
-            expect(reflaggedResult.flaggedExpenses).toHaveLength(1);
-            expect(reflaggedResult.flaggedExpenses.at(0)?.transactionID).toBe('t1');
+            expect(reFlaggedResult.flaggedExpenses).toHaveLength(1);
+            expect(reFlaggedResult.flaggedExpenses.at(0)?.transactionID).toBe('t1');
         });
 
         it('excludes flagged transactions on expense reports the current user does not own', () => {

From 843a169b7ac36bcc8a67a73cf04cb5d1eb8519ff Mon Sep 17 00:00:00 2001
From: sumo_slonik <jakub.nowakowski@swmansion.com>
Date: Mon, 1 Jun 2026 13:01:31 +0200
Subject: [PATCH 087/435] Hide rooms the user has left from the workspace rooms
 list

Leaving a room optimistically closes it (statusNum CLOSED) and strips its
reportID. The workspace rooms list still showed the closed room because
policyChatRoomsSelector only filtered by policy, chat type, and archival,
so tapping the row navigated to a "not here" page.

Skip closed reports in policyChatRoomsSelector. This covers the offline
leave case and the online optimistic window, without hiding unjoined rooms
(still open) or workspace rooms the admin left (only notification hidden).

Fixes #92031
---
 src/selectors/Report.ts          |  5 ++++-
 tests/unit/ReportSelectorTest.ts | 16 ++++++++++++++++
 2 files changed, 20 insertions(+), 1 deletion(-)

diff --git a/src/selectors/Report.ts b/src/selectors/Report.ts
index 10eaff2be776..ddca749392b0 100644
--- a/src/selectors/Report.ts
+++ b/src/selectors/Report.ts
@@ -1,7 +1,7 @@
 import type {OnyxCollection, OnyxEntry} from 'react-native-onyx';
 import type {TupleToUnion, ValueOf} from 'type-fest';
 import {getOriginalMessage, isClosedAction} from '@libs/ReportActionsUtils';
-import {canShowReportRecipientLocalTime, getPolicyIDsWithEmptyReportsForAccount, isChatRoom, isOpenExpenseReport, isPolicyExpenseChat, isThread} from '@libs/ReportUtils';
+import {canShowReportRecipientLocalTime, getPolicyIDsWithEmptyReportsForAccount, isChatRoom, isClosedReport, isOpenExpenseReport, isPolicyExpenseChat, isThread} from '@libs/ReportUtils';
 import type {ArchivedReportsIDSet} from '@libs/SearchUIUtils';
 import CONST from '@src/CONST';
 import ONYXKEYS from '@src/ONYXKEYS';
@@ -58,6 +58,9 @@ const policyChatRoomsSelector =
             if (!isChatRoom(report) && !isPolicyExpenseChat(report)) {
                 continue;
             }
+            if (isClosedReport(report)) {
+                continue;
+            }
             if (archivedReportsIdSet.has(`${ONYXKEYS.COLLECTION.REPORT_NAME_VALUE_PAIRS}${report.reportID}`)) {
                 continue;
             }
diff --git a/tests/unit/ReportSelectorTest.ts b/tests/unit/ReportSelectorTest.ts
index fdcc0123aa53..4483e14d2bb1 100644
--- a/tests/unit/ReportSelectorTest.ts
+++ b/tests/unit/ReportSelectorTest.ts
@@ -80,4 +80,20 @@ describe('policyChatRoomsSelector', () => {
         const result = policyChatRoomsSelector(policyID, archivedSet)(reports);
         expect(result).toEqual([policyAdmins]);
     });
+
+    it('excludes rooms the user has left (closed reports)', () => {
+        const leftRoom = {
+            reportID: '1',
+            policyID,
+            chatType: CONST.REPORT.CHAT_TYPE.POLICY_ROOM,
+            statusNum: CONST.REPORT.STATUS_NUM.CLOSED,
+            stateNum: CONST.REPORT.STATE_NUM.APPROVED,
+        } as Report;
+        const reports = {
+            [`${REPORT_KEY_PREFIX}1`]: leftRoom,
+            [`${REPORT_KEY_PREFIX}2`]: policyAdmins,
+        };
+        const result = policyChatRoomsSelector(policyID, emptyArchivedSet)(reports);
+        expect(result).toEqual([policyAdmins]);
+    });
 });

From 751d7fcbc6976deea196024ec6220c6df7fdb67f Mon Sep 17 00:00:00 2001
From: Adam Grzybowski <adam.grzybowski@swmansion.com>
Date: Tue, 2 Jun 2026 13:38:32 +0200
Subject: [PATCH 088/435] Remove redundant useCallback in
 useNavigateToTransactionThread

---
 src/hooks/useNavigateToTransactionThread.ts | 70 ++++++++++-----------
 1 file changed, 33 insertions(+), 37 deletions(-)

diff --git a/src/hooks/useNavigateToTransactionThread.ts b/src/hooks/useNavigateToTransactionThread.ts
index f6678e419216..df7b648d48ab 100644
--- a/src/hooks/useNavigateToTransactionThread.ts
+++ b/src/hooks/useNavigateToTransactionThread.ts
@@ -1,4 +1,3 @@
-import {useCallback} from 'react';
 import type {OnyxEntry} from 'react-native-onyx';
 import {useWideRHPActions} from '@components/WideRHPContextProvider';
 import {createTransactionThreadReport, setOptimisticTransactionThread} from '@libs/actions/Report';
@@ -46,46 +45,43 @@ function useNavigateToTransactionThread() {
     const [introSelected] = useOnyx(ONYXKEYS.NVP_INTRO_SELECTED);
     const [betas] = useOnyx(ONYXKEYS.BETAS);
 
-    return useCallback(
-        ({transactionID, reportActions, report, transaction, siblingTransactionIDs, backTo}: NavigateToTransactionThreadParams) => {
-            const iouAction = getIOUActionForTransactionID(reportActions, transactionID);
-            const resolvedBackTo = backTo ?? Navigation.getActiveRoute();
-            let reportIDToNavigate = iouAction?.childReportID;
+    return ({transactionID, reportActions, report, transaction, siblingTransactionIDs, backTo}: NavigateToTransactionThreadParams) => {
+        const iouAction = getIOUActionForTransactionID(reportActions, transactionID);
+        const resolvedBackTo = backTo ?? Navigation.getActiveRoute();
+        let reportIDToNavigate = iouAction?.childReportID;
 
-            const routeParams: {reportID: string | undefined; reportActionID?: string; backTo?: string} = {
-                reportID: reportIDToNavigate,
-                backTo: resolvedBackTo,
-            };
+        const routeParams: {reportID: string | undefined; reportActionID?: string; backTo?: string} = {
+            reportID: reportIDToNavigate,
+            backTo: resolvedBackTo,
+        };
 
-            if (!reportIDToNavigate) {
-                const transactionThreadReport = createTransactionThreadReport({
-                    introSelected,
-                    currentUserLogin: currentUserDetails.email ?? '',
-                    currentUserAccountID: currentUserDetails.accountID,
-                    betas,
-                    iouReport: report,
-                    iouReportAction: iouAction,
-                    transaction,
-                });
-                if (transactionThreadReport) {
-                    reportIDToNavigate = transactionThreadReport.reportID;
-                    routeParams.reportID = reportIDToNavigate;
-                }
-            } else {
-                setOptimisticTransactionThread(reportIDToNavigate, report?.reportID, iouAction?.reportActionID, report?.policyID);
+        if (!reportIDToNavigate) {
+            const transactionThreadReport = createTransactionThreadReport({
+                introSelected,
+                currentUserLogin: currentUserDetails.email ?? '',
+                currentUserAccountID: currentUserDetails.accountID,
+                betas,
+                iouReport: report,
+                iouReportAction: iouAction,
+                transaction,
+            });
+            if (transactionThreadReport) {
+                reportIDToNavigate = transactionThreadReport.reportID;
+                routeParams.reportID = reportIDToNavigate;
             }
+        } else {
+            setOptimisticTransactionThread(reportIDToNavigate, report?.reportID, iouAction?.reportActionID, report?.policyID);
+        }
 
-            // Single transaction report opens in RHP. We seed every sibling transaction ID so the RHP can
-            // display prev/next arrows for navigation between expenses.
-            setActiveTransactionIDs(siblingTransactionIDs).then(() => {
-                if (reportIDToNavigate) {
-                    markReportIDAsExpense(reportIDToNavigate);
-                }
-                Navigation.navigate(ROUTES.SEARCH_REPORT.getRoute(routeParams));
-            });
-        },
-        [markReportIDAsExpense, introSelected, betas, currentUserDetails.email, currentUserDetails.accountID],
-    );
+        // Single transaction report opens in RHP. We seed every sibling transaction ID so the RHP can
+        // display prev/next arrows for navigation between expenses.
+        setActiveTransactionIDs(siblingTransactionIDs).then(() => {
+            if (reportIDToNavigate) {
+                markReportIDAsExpense(reportIDToNavigate);
+            }
+            Navigation.navigate(ROUTES.SEARCH_REPORT.getRoute(routeParams));
+        });
+    };
 }
 
 export default useNavigateToTransactionThread;

From adfb3804c658d752d9744965e9f58d33753dbac1 Mon Sep 17 00:00:00 2001
From: Adam Grzybowski <adam.grzybowski@swmansion.com>
Date: Tue, 2 Jun 2026 13:46:17 +0200
Subject: [PATCH 089/435] Gate notice/warning violations on showInReview in
 flaggedExpenses

---
 .../actions/OnyxDerived/configs/flaggedExpenses.ts | 10 ++++++++--
 tests/unit/OnyxDerived/flaggedExpensesTest.ts      | 14 ++++++++++++++
 2 files changed, 22 insertions(+), 2 deletions(-)

diff --git a/src/libs/actions/OnyxDerived/configs/flaggedExpenses.ts b/src/libs/actions/OnyxDerived/configs/flaggedExpenses.ts
index e555f50f3107..3f2163b3979d 100644
--- a/src/libs/actions/OnyxDerived/configs/flaggedExpenses.ts
+++ b/src/libs/actions/OnyxDerived/configs/flaggedExpenses.ts
@@ -30,8 +30,11 @@ function isCurrentUserOpenExpenseReport(report: Report | null | undefined, curre
 
 /**
  * Returns true when the given violation list has at least one entry that should surface in the
- * `Review X expenses` row: a transaction-level violation that the user can act on. Violations
- * marked `showInReview === false` and report-field violations (`fieldRequired`) are excluded.
+ * `Review X expenses` row: a transaction-level violation that the user can act on. Entries marked
+ * `showInReview === false` and report-field violations (`fieldRequired`) are excluded. `notice`/
+ * `warning` types only count when `showInReview` is explicitly true (omitting it is not enough),
+ * mirroring the review-visibility logic in `SearchUIUtils.hasVisibleViolations`; real `violation`
+ * types remain actionable.
  */
 function hasReviewableViolation(violations: TransactionViolations | null | undefined): boolean {
     if (!violations || violations.length === 0) {
@@ -48,6 +51,9 @@ function hasReviewableViolation(violations: TransactionViolations | null | undef
         if (violation.name === CONST.REPORT_VIOLATIONS.FIELD_REQUIRED) {
             return false;
         }
+        if (violation.type === CONST.VIOLATION_TYPES.NOTICE || violation.type === CONST.VIOLATION_TYPES.WARNING) {
+            return violation.showInReview === true;
+        }
         return true;
     });
 }
diff --git a/tests/unit/OnyxDerived/flaggedExpensesTest.ts b/tests/unit/OnyxDerived/flaggedExpensesTest.ts
index fdb04dfc6cde..c2316893628c 100644
--- a/tests/unit/OnyxDerived/flaggedExpensesTest.ts
+++ b/tests/unit/OnyxDerived/flaggedExpensesTest.ts
@@ -140,6 +140,20 @@ describe('flaggedExpenses derived value', () => {
 
             expect(result.flaggedExpenses).toEqual([]);
         });
+
+        it('excludes warning/notice violations unless showInReview is explicitly true', () => {
+            const report = createExpenseReport('r1');
+            const transactions = [createTransaction('tWarn', 'r1'), createTransaction('tNotice', 'r1'), createTransaction('tShown', 'r1')];
+            const violations = buildViolations({
+                tWarn: [{type: CONST.VIOLATION_TYPES.WARNING, name: CONST.VIOLATIONS.RTER}],
+                tNotice: [{type: CONST.VIOLATION_TYPES.NOTICE, name: CONST.VIOLATIONS.RECEIPT_REQUIRED}],
+                tShown: [{type: CONST.VIOLATION_TYPES.WARNING, name: CONST.VIOLATIONS.RTER, showInReview: true}],
+            });
+
+            const result = compute([buildReports(report), buildTransactions(...transactions), violations, createSession()], emptyContext);
+
+            expect(result.flaggedExpenses).toEqual([{transactionID: 'tShown', reportID: 'r1'}]);
+        });
     });
 
     describe('Draft-report scope and resolution', () => {

From ad4792ed538e9b9c0c3441c0dca68c2d236f52cb Mon Sep 17 00:00:00 2001
From: krishna2323 <belivethatkg@gmail.com>
Date: Tue, 2 Jun 2026 17:43:32 +0530
Subject: [PATCH 090/435] fix: Translate scroll indices and preserve original
 keys for split group items

Signed-off-by: krishna2323 <belivethatkg@gmail.com>
---
 src/components/Search/SearchList/index.tsx | 28 +++++++++++++++-------
 1 file changed, 20 insertions(+), 8 deletions(-)

diff --git a/src/components/Search/SearchList/index.tsx b/src/components/Search/SearchList/index.tsx
index 6c59676e305f..5b76abec3b9f 100644
--- a/src/components/Search/SearchList/index.tsx
+++ b/src/components/Search/SearchList/index.tsx
@@ -441,16 +441,21 @@ function SearchList({
                 return;
             }
 
-            // Don't scroll while a cell is being edited
-            // as it can cause unwanted scrolling when the edit is dismissed
-            // See: https://github.com/Expensify/App/pull/83127#issuecomment-4064533155
             if (isEditingCell || wasRecentlyEditingCell) {
                 return;
             }
 
-            listRef.current.scrollToIndex({index, animated, viewOffset: -variables.contentHeaderHeight});
+            let targetIndex = index;
+            if (shouldSplitGroups && item.keyForList) {
+                const splitIndex = listData.findIndex((li) => li.keyForList === `header_${item.keyForList}` || li.keyForList === item.keyForList);
+                if (splitIndex !== -1) {
+                    targetIndex = splitIndex;
+                }
+            }
+
+            listRef.current.scrollToIndex({index: targetIndex, animated, viewOffset: -variables.contentHeaderHeight});
         },
-        [data, isEditingCell, wasRecentlyEditingCell],
+        [data, isEditingCell, wasRecentlyEditingCell, shouldSplitGroups, listData],
     );
 
     useFocusEffect(
@@ -487,9 +492,16 @@ function SearchList({
                         canSelectMultiple={canSelectMultiple}
                         isExpanded={expandedGroups.has(originalKey)}
                         onToggle={() => onToggleGroup(originalKey)}
-                        onSelectRow={onSelectRow}
-                        onCheckboxPress={(val, itemTransactions) => onCheckboxPress(val as SearchListItem, itemTransactions)}
-                        onLongPressRow={isMobileSelectionModeEnabled ? handleLongPressRowInMobileSelectionMode : handleLongPressRow}
+                        onSelectRow={(rowItem, previewData, event) => onSelectRow({...rowItem, keyForList: originalKey}, previewData, event)}
+                        onCheckboxPress={(val, itemTransactions) => onCheckboxPress({...val, keyForList: originalKey} as SearchListItem, itemTransactions)}
+                        onLongPressRow={(rowItem, itemTransactions) => {
+                            const fixedItem = {...rowItem, keyForList: originalKey} as SearchListItem;
+                            if (isMobileSelectionModeEnabled) {
+                                handleLongPressRowInMobileSelectionMode(fixedItem, itemTransactions);
+                            } else {
+                                handleLongPressRow(fixedItem, itemTransactions);
+                            }
+                        }}
                         onFocus={onFocus}
                         isFocused={isItemFocused}
                         isFirstItem={index === firstVisibleIndex}

From b4285d8f82cec0a8062eea95042b40edb85495ac Mon Sep 17 00:00:00 2001
From: Adam Horodyski <ad.horodyski@gmail.com>
Date: Tue, 2 Jun 2026 14:25:51 +0200
Subject: [PATCH 091/435] SequentialQueue: resolve isReadyPromise on follower
 tabs; fix test typos

Address PR review feedback:
- push() arms isReadyPromise pending in its sync prelude, but flush()
  returns early on non-leader clients before resolving it, hanging
  waitForIdle() forever on follower tabs. Resolve it in the
  !isClientTheLeader() branch, mirroring the empty-queue fix.
- Fix "rance condition" -> "race condition" and remove duplicated word
  in two test descriptions.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
---
 src/libs/Network/SequentialQueue.ts | 4 ++++
 tests/unit/SequentialQueueTest.ts   | 6 +++---
 2 files changed, 7 insertions(+), 3 deletions(-)

diff --git a/src/libs/Network/SequentialQueue.ts b/src/libs/Network/SequentialQueue.ts
index 5253764a3679..e04b0df38b34 100644
--- a/src/libs/Network/SequentialQueue.ts
+++ b/src/libs/Network/SequentialQueue.ts
@@ -357,6 +357,10 @@ function flush(shouldResetPromise = true) {
             persistedRequestsLength,
             hasOngoingRequest: !!currentOngoingRequest,
         });
+        // push() may have marked isReadyPromise pending in its sync prelude. Followers never
+        // process the queue, so resolve here — otherwise READs parked on waitForIdle() would
+        // hang forever on this tab after any write.
+        resolveIsReadyPromise?.();
         return;
     }
 
diff --git a/tests/unit/SequentialQueueTest.ts b/tests/unit/SequentialQueueTest.ts
index 5f258a226f43..f53a0e91bba0 100644
--- a/tests/unit/SequentialQueueTest.ts
+++ b/tests/unit/SequentialQueueTest.ts
@@ -123,7 +123,7 @@ describe('SequentialQueue', () => {
         }
     });
 
-    it('should replace request request in queue while a similar one is ongoing', async () => {
+    it('should replace request in queue while a similar one is ongoing', async () => {
         const mockedFetch = global.fetch as ReturnType<typeof TestHelper.getGlobalFetchMock> & {pause: () => void; resume: () => Promise<void>};
         mockedFetch.pause();
         try {
@@ -163,7 +163,7 @@ describe('SequentialQueue', () => {
         }
     });
 
-    it('should replace request request in queue while a similar one is ongoing and keep the same index', async () => {
+    it('should replace request in queue while a similar one is ongoing and keep the same index', async () => {
         const mockedFetch = global.fetch as ReturnType<typeof TestHelper.getGlobalFetchMock> & {pause: () => void; resume: () => Promise<void>};
         mockedFetch.pause();
         try {
@@ -199,7 +199,7 @@ describe('SequentialQueue', () => {
         }
     });
 
-    // need to test a rance condition between processing the next request and then pushing a new request with conflict resolver
+    // need to test a race condition between processing the next request and then pushing a new request with conflict resolver
     it('should resolve the conflict and replace the correct request in the queue while a new request is picked up after unpausing', async () => {
         SequentialQueue.pause();
         for (let i = 0; i < 5; i++) {

From 44cf02a201c5dcc298529d806342a166df351d57 Mon Sep 17 00:00:00 2001
From: krishna2323 <belivethatkg@gmail.com>
Date: Tue, 2 Jun 2026 18:03:04 +0530
Subject: [PATCH 092/435] fix: Make children container border selection-aware
 to stay visible when group is selected

Signed-off-by: krishna2323 <belivethatkg@gmail.com>
---
 .../Search/SearchList/ListItem/GroupChildrenContainer.tsx   | 1 +
 .../Search/SearchList/ListItem/GroupChildrenContent.tsx     | 6 +++++-
 2 files changed, 6 insertions(+), 1 deletion(-)

diff --git a/src/components/Search/SearchList/ListItem/GroupChildrenContainer.tsx b/src/components/Search/SearchList/ListItem/GroupChildrenContainer.tsx
index 46378225b91e..46e1e7294934 100644
--- a/src/components/Search/SearchList/ListItem/GroupChildrenContainer.tsx
+++ b/src/components/Search/SearchList/ListItem/GroupChildrenContainer.tsx
@@ -117,6 +117,7 @@ function GroupChildrenContainer({
                         <GroupChildrenContent
                             item={item}
                             isExpanded={isExpanded}
+                            isSelected={isSelected}
                             groupBy={groupBy}
                             searchType={searchType}
                             columns={columns}
diff --git a/src/components/Search/SearchList/ListItem/GroupChildrenContent.tsx b/src/components/Search/SearchList/ListItem/GroupChildrenContent.tsx
index 1ee4273dbd8c..2565b6f70c39 100644
--- a/src/components/Search/SearchList/ListItem/GroupChildrenContent.tsx
+++ b/src/components/Search/SearchList/ListItem/GroupChildrenContent.tsx
@@ -11,6 +11,7 @@ import useLocalize from '@hooks/useLocalize';
 import useNetwork from '@hooks/useNetwork';
 import useOnyx from '@hooks/useOnyx';
 import useResponsiveLayout from '@hooks/useResponsiveLayout';
+import useStyleUtils from '@hooks/useStyleUtils';
 import useThemeStyles from '@hooks/useThemeStyles';
 import {search} from '@libs/actions/Search';
 import type {TransactionPreviewData} from '@libs/actions/Search';
@@ -27,6 +28,7 @@ import type {GroupChildrenContainerItemType, SearchListItem, TransactionGroupLis
 type GroupChildrenContentProps = {
     item: GroupChildrenContainerItemType;
     isExpanded: boolean;
+    isSelected?: boolean;
     groupBy?: SearchGroupBy;
     searchType?: SearchDataTypes;
     columns?: SearchColumnType[];
@@ -56,6 +58,7 @@ function GroupChildrenContent({
     nonPersonalAndWorkspaceCards,
     onUndelete,
     newTransactionID,
+    isSelected,
     allReportMetadata,
     bankAccountList,
     cardFeeds,
@@ -68,6 +71,7 @@ function GroupChildrenContent({
     const {convertToDisplayString} = useCurrencyListActions();
     const {isOffline} = useNetwork();
     const styles = useThemeStyles();
+    const StyleUtils = useStyleUtils();
     const {isLargeScreenWidth} = useResponsiveLayout();
 
     const groupItem = item as unknown as TransactionGroupListItemType;
@@ -228,7 +232,7 @@ function GroupChildrenContent({
         <>
             {isLargeScreenWidth && !isEmpty && (
                 <View style={styles.ph3}>
-                    <View style={styles.borderBottom} />
+                    <View style={StyleUtils.getSelectedBorderBottomStyle(isSelected)} />
                 </View>
             )}
             <TransactionGroupListExpandedItem

From 367558d9619eca8263573c9e90a7734a69ed3a66 Mon Sep 17 00:00:00 2001
From: jayeshmangwani <jayeshmangwani@gmail.com>
Date: Tue, 2 Jun 2026 18:07:33 +0530
Subject: [PATCH 093/435] fixed inconsistent report name between 'Submitted'
 and 'Marked as done' when replying in a thread

---
 src/libs/ReportNameUtils.ts | 21 +++++++++++++++++++++
 1 file changed, 21 insertions(+)

diff --git a/src/libs/ReportNameUtils.ts b/src/libs/ReportNameUtils.ts
index e533b73e3099..1cdb9f5b8d7a 100644
--- a/src/libs/ReportNameUtils.ts
+++ b/src/libs/ReportNameUtils.ts
@@ -8,6 +8,7 @@ import type {LocaleContextProps, LocalizedTranslate} from '@components/LocaleCon
 import CONST from '@src/CONST';
 import ONYXKEYS from '@src/ONYXKEYS';
 import type {
+    IntroSelected,
     PersonalDetails,
     PersonalDetailsList,
     Policy,
@@ -27,6 +28,7 @@ import {formatPhoneNumber as formatPhoneNumberPhoneUtils} from './LocalePhoneNum
 import {translateLocal} from './Localize';
 // eslint-disable-next-line import/no-cycle
 import {getForReportAction, getMovedReportID} from './ModifiedExpenseMessage';
+import isTrackOnboardingChoice from './OnboardingUtils';
 import Parser from './Parser';
 import {getDisplayNameOrDefault} from './PersonalDetailsUtils';
 import {getCleanedTagName, isPolicyAdmin, isPolicyFieldListEmpty} from './PolicyUtils';
@@ -161,6 +163,7 @@ import {
     isThread,
     isTripRoom,
     isUserCreatedPolicyRoom,
+    shouldShowMarkAsDone,
 } from './ReportUtils';
 
 type ComputeReportName = {
@@ -189,6 +192,15 @@ Onyx.connect({
     },
 });
 
+let introSelected: OnyxEntry<IntroSelected>;
+// eslint-disable-next-line rulesdir/no-onyx-connect -- NextStepUtils is a pure utility called from action files that cannot use hooks
+Onyx.connect({
+    key: ONYXKEYS.NVP_INTRO_SELECTED,
+    callback: (value) => {
+        introSelected = value;
+    },
+});
+
 function generateArchivedReportName(reportName: string): string {
     return `${reportName} (${translateLocal('common.archived')}) `;
 }
@@ -433,6 +445,15 @@ function computeReportNameBasedOnReportAction(
         if (harvesting) {
             return Parser.htmlToText(translate('iou.automaticallySubmitted'));
         }
+        if (
+            shouldShowMarkAsDone({
+                isTrackIntentUser: isTrackOnboardingChoice(introSelected?.choice),
+                policy: reportPolicy,
+                report: parentReport,
+            })
+        ) {
+            return translate('iou.markedAsDone', getOriginalMessage(parentReportAction)?.message);
+        }
         return translate('iou.submitted', getOriginalMessage(parentReportAction)?.message);
     }
 

From 600c296af4d3bf030dde09d7c894c4c9e56bd43a Mon Sep 17 00:00:00 2001
From: Youssef Lourayad <youssef@expensify.com>
Date: Tue, 2 Jun 2026 12:39:37 +0000
Subject: [PATCH 094/435] Use regular sized tabs

---
 src/components/TabSelector/TabLabel.tsx        | 11 +++--------
 src/components/TabSelector/TabSelectorBase.tsx |  4 +---
 src/components/TabSelector/TabSelectorItem.tsx |  3 ---
 src/components/TabSelector/types.ts            | 10 +---------
 src/pages/inbox/sidebar/InboxTabSelector.tsx   |  1 -
 src/styles/index.ts                            | 15 ---------------
 6 files changed, 5 insertions(+), 39 deletions(-)

diff --git a/src/components/TabSelector/TabLabel.tsx b/src/components/TabSelector/TabLabel.tsx
index c00d939cdb44..e47490b89f38 100644
--- a/src/components/TabSelector/TabLabel.tsx
+++ b/src/components/TabSelector/TabLabel.tsx
@@ -5,7 +5,6 @@ import type {StyleProp, TextStyle} from 'react-native';
 import Text from '@components/Text';
 import useThemeStyles from '@hooks/useThemeStyles';
 import variables from '@styles/variables';
-import type {TabSelectorSize} from './types';
 
 type TabLabelProps = {
     /** Title of the tab */
@@ -22,20 +21,16 @@ type TabLabelProps = {
 
     /** Text style */
     textStyle?: StyleProp<TextStyle>;
-
-    /** Size variant */
-    size?: TabSelectorSize;
 };
 
-function TabLabel({title = '', activeOpacity = 0, inactiveOpacity = 1, hasIcon = false, textStyle, size}: TabLabelProps) {
+function TabLabel({title = '', activeOpacity = 0, inactiveOpacity = 1, hasIcon = false, textStyle}: TabLabelProps) {
     const styles = useThemeStyles();
-    const smallTextStyle = size === 'small' ? styles.tabTextSmall : undefined;
     return (
         <View style={{maxWidth: variables.tabSelectorMaxTabLabelWidth}}>
             <Animated.View style={[{opacity: activeOpacity}]}>
                 <Text
                     numberOfLines={1}
-                    style={[styles.tabText(true, hasIcon), smallTextStyle, textStyle]}
+                    style={[styles.tabText(true, hasIcon), textStyle]}
                 >
                     {title}
                 </Text>
@@ -43,7 +38,7 @@ function TabLabel({title = '', activeOpacity = 0, inactiveOpacity = 1, hasIcon =
             <Animated.View style={[StyleSheet.absoluteFill, {opacity: inactiveOpacity}]}>
                 <Text
                     numberOfLines={1}
-                    style={[styles.tabText(false, hasIcon), smallTextStyle, textStyle]}
+                    style={[styles.tabText(false, hasIcon), textStyle]}
                 >
                     {title}
                 </Text>
diff --git a/src/components/TabSelector/TabSelectorBase.tsx b/src/components/TabSelector/TabSelectorBase.tsx
index 03b89482707c..f9b456c150fd 100644
--- a/src/components/TabSelector/TabSelectorBase.tsx
+++ b/src/components/TabSelector/TabSelectorBase.tsx
@@ -26,7 +26,6 @@ function TabSelectorBase({
     position,
     shouldShowLabelWhenInactive = true,
     equalWidth = false,
-    size,
     shouldShowProductTrainingTooltip = false,
     renderProductTrainingTooltip,
 }: TabSelectorBaseProps) {
@@ -64,7 +63,7 @@ function TabSelectorBase({
             }}
             ref={containerRef}
             style={styles.scrollableTabSelector}
-            contentContainerStyle={[styles.tabSelectorContentContainer, size === 'small' && styles.tabSelectorContentContainerSmall]}
+            contentContainerStyle={styles.tabSelectorContentContainer}
             horizontal
             showsHorizontalScrollIndicator={false}
             keyboardShouldPersistTaps="handled"
@@ -123,7 +122,6 @@ function TabSelectorBase({
                         shouldShowProductTrainingTooltip={shouldShowProductTrainingTooltip}
                         renderProductTrainingTooltip={renderProductTrainingTooltip}
                         equalWidth={equalWidth}
-                        size={size}
                         badgeText={tab.badgeText}
                         isBadgeCondensed={tab.isBadgeCondensed}
                         badgeStyles={tab.badgeStyles}
diff --git a/src/components/TabSelector/TabSelectorItem.tsx b/src/components/TabSelector/TabSelectorItem.tsx
index 7723d8722750..f99ff4889ed8 100644
--- a/src/components/TabSelector/TabSelectorItem.tsx
+++ b/src/components/TabSelector/TabSelectorItem.tsx
@@ -34,7 +34,6 @@ function TabSelectorItem({
     shouldShowProductTrainingTooltip = false,
     renderProductTrainingTooltip,
     equalWidth = false,
-    size,
     badgeText,
     isBadgeCondensed = false,
     badgeStyles,
@@ -61,7 +60,6 @@ function TabSelectorItem({
             accessibilityRole={CONST.ROLE.TAB}
             style={[
                 styles.tabSelectorButton,
-                size === 'small' && styles.tabSelectorButtonSmall,
                 styles.tabBackground(isHovered, isActive, isDisabled, backgroundColor),
                 styles.userSelectNone,
                 isOfflineWithPendingAction ? styles.offlineFeedbackPending : undefined,
@@ -93,7 +91,6 @@ function TabSelectorItem({
                     activeOpacity={styles.tabOpacity(isDisabled, isHovered, isActive, activeOpacity, inactiveOpacity).opacity}
                     inactiveOpacity={styles.tabOpacity(isDisabled, isHovered, isActive, inactiveOpacity, activeOpacity).opacity}
                     hasIcon={!!icon}
-                    size={size}
                 />
             )}
             {!!badgeText && (
diff --git a/src/components/TabSelector/types.ts b/src/components/TabSelector/types.ts
index 813525bbc8ce..fe0092815357 100644
--- a/src/components/TabSelector/types.ts
+++ b/src/components/TabSelector/types.ts
@@ -58,8 +58,6 @@ type TabSelectorBaseItem = WithSentryLabel & {
     pendingAction?: PendingAction;
 };
 
-type TabSelectorSize = 'default' | 'small';
-
 type TabSelectorBaseProps = {
     /** Tabs to render. */
     tabs: TabSelectorBaseItem[];
@@ -85,9 +83,6 @@ type TabSelectorBaseProps = {
     /** Whether tabs should have equal width. */
     equalWidth?: boolean;
 
-    /** Size variant for the tabs. 'small' uses a compact 28px height. */
-    size?: TabSelectorSize;
-
     /** Determines whether the product training tooltip should be displayed to the user. */
     shouldShowProductTrainingTooltip?: boolean;
 
@@ -132,9 +127,6 @@ type TabSelectorItemProps = WithSentryLabel & {
     /** Whether tabs should have equal width */
     equalWidth?: boolean;
 
-    /** Size variant for the tabs. */
-    size?: TabSelectorSize;
-
     /** Determines whether the product training tooltip should be displayed to the user. */
     shouldShowProductTrainingTooltip?: boolean;
 
@@ -202,4 +194,4 @@ type BackgroundColor = Animated.AnimatedInterpolation<string> | string;
 
 type Opacity = 1 | 0 | Animated.AnimatedInterpolation<number>;
 
-export type {TabSelectorProps, BackgroundColor, GetBackgroundColorConfig, Opacity, GetOpacityConfig, TabSelectorBaseProps, TabSelectorBaseItem, TabSelectorItemProps, TabSelectorSize};
+export type {TabSelectorProps, BackgroundColor, GetBackgroundColorConfig, Opacity, GetOpacityConfig, TabSelectorBaseProps, TabSelectorBaseItem, TabSelectorItemProps};
diff --git a/src/pages/inbox/sidebar/InboxTabSelector.tsx b/src/pages/inbox/sidebar/InboxTabSelector.tsx
index 294a5dd3a2fb..8b22b909f140 100644
--- a/src/pages/inbox/sidebar/InboxTabSelector.tsx
+++ b/src/pages/inbox/sidebar/InboxTabSelector.tsx
@@ -45,7 +45,6 @@ function InboxTabSelector() {
                     tabs={tabs}
                     activeTabKey={activeTab}
                     onTabPress={(key) => setActiveTab(key as ValueOf<typeof CONST.INBOX_TAB>)}
-                    size="small"
                     equalWidth
                 />
             </View>
diff --git a/src/styles/index.ts b/src/styles/index.ts
index bfed7d38289a..61dfc4816cec 100644
--- a/src/styles/index.ts
+++ b/src/styles/index.ts
@@ -4456,11 +4456,6 @@ const staticStyles = (theme: ThemeColors) =>
             scrollMarginInline: variables.tabSelectorScrollMarginInline,
         },
 
-        tabSelectorButtonSmall: {
-            height: variables.componentSizeSmall,
-            paddingHorizontal: 12,
-        },
-
         tabSelector: {
             flexDirection: 'row',
             paddingHorizontal: 20,
@@ -4473,16 +4468,6 @@ const staticStyles = (theme: ThemeColors) =>
             paddingHorizontal: 20,
         },
 
-        tabSelectorContentContainerSmall: {
-            paddingTop: 0,
-            paddingBottom: 0,
-        },
-
-        tabTextSmall: {
-            fontSize: variables.fontSizeSmall,
-            lineHeight: 16,
-        },
-
         inboxTabBadge: {
             minWidth: 18,
             height: 16,

From 9b8417ed46c45b44b8ef741ba61e0135b867d44a Mon Sep 17 00:00:00 2001
From: krishna2323 <belivethatkg@gmail.com>
Date: Tue, 2 Jun 2026 18:13:27 +0530
Subject: [PATCH 095/435] Move sub-header border into sticky area and fix
 unused variable lint errors

Signed-off-by: krishna2323 <belivethatkg@gmail.com>
---
 .../ListItem/GroupChildrenContainer.tsx       |  3 -
 .../ListItem/GroupChildrenContent.tsx         | 66 +++++++------------
 .../SearchList/ListItem/GroupHeader.tsx       |  4 +-
 3 files changed, 28 insertions(+), 45 deletions(-)

diff --git a/src/components/Search/SearchList/ListItem/GroupChildrenContainer.tsx b/src/components/Search/SearchList/ListItem/GroupChildrenContainer.tsx
index 46e1e7294934..747d655dffa0 100644
--- a/src/components/Search/SearchList/ListItem/GroupChildrenContainer.tsx
+++ b/src/components/Search/SearchList/ListItem/GroupChildrenContainer.tsx
@@ -5,7 +5,6 @@ import Animated, {useAnimatedStyle, useDerivedValue, useSharedValue, withTiming}
 import {scheduleOnRN} from 'react-native-worklets';
 import {easing} from '@components/Modal/ReanimatedModal/utils';
 import type {SearchColumnType, SearchGroupBy} from '@components/Search/types';
-import useResponsiveLayout from '@hooks/useResponsiveLayout';
 import useTheme from '@hooks/useTheme';
 import useThemeStyles from '@hooks/useThemeStyles';
 import type {TransactionPreviewData} from '@libs/actions/Search';
@@ -58,7 +57,6 @@ function GroupChildrenContainer({
 }: GroupChildrenContainerProps) {
     const theme = useTheme();
     const styles = useThemeStyles();
-    const {isLargeScreenWidth} = useResponsiveLayout();
 
     const contentHeight = useSharedValue(0);
     const hasExpanded = useSharedValue(isExpanded);
@@ -117,7 +115,6 @@ function GroupChildrenContainer({
                         <GroupChildrenContent
                             item={item}
                             isExpanded={isExpanded}
-                            isSelected={isSelected}
                             groupBy={groupBy}
                             searchType={searchType}
                             columns={columns}
diff --git a/src/components/Search/SearchList/ListItem/GroupChildrenContent.tsx b/src/components/Search/SearchList/ListItem/GroupChildrenContent.tsx
index 2565b6f70c39..8ab547e70d44 100644
--- a/src/components/Search/SearchList/ListItem/GroupChildrenContent.tsx
+++ b/src/components/Search/SearchList/ListItem/GroupChildrenContent.tsx
@@ -1,6 +1,5 @@
 import {useIsFocused} from '@react-navigation/native';
 import React, {useEffect, useMemo, useState} from 'react';
-import {View} from 'react-native';
 import type {OnyxCollection, OnyxEntry} from 'react-native-onyx';
 import {useSearchSelectionContext} from '@components/Search/SearchContext';
 import type {SearchColumnType, SearchGroupBy} from '@components/Search/types';
@@ -10,9 +9,6 @@ import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails'
 import useLocalize from '@hooks/useLocalize';
 import useNetwork from '@hooks/useNetwork';
 import useOnyx from '@hooks/useOnyx';
-import useResponsiveLayout from '@hooks/useResponsiveLayout';
-import useStyleUtils from '@hooks/useStyleUtils';
-import useThemeStyles from '@hooks/useThemeStyles';
 import {search} from '@libs/actions/Search';
 import type {TransactionPreviewData} from '@libs/actions/Search';
 import type {ModifiedMouseEvent} from '@libs/Navigation/helpers/openInternalRouteInNewTab';
@@ -28,7 +24,6 @@ import type {GroupChildrenContainerItemType, SearchListItem, TransactionGroupLis
 type GroupChildrenContentProps = {
     item: GroupChildrenContainerItemType;
     isExpanded: boolean;
-    isSelected?: boolean;
     groupBy?: SearchGroupBy;
     searchType?: SearchDataTypes;
     columns?: SearchColumnType[];
@@ -58,7 +53,6 @@ function GroupChildrenContent({
     nonPersonalAndWorkspaceCards,
     onUndelete,
     newTransactionID,
-    isSelected,
     allReportMetadata,
     bankAccountList,
     cardFeeds,
@@ -70,9 +64,6 @@ function GroupChildrenContent({
     const isScreenFocused = useIsFocused();
     const {convertToDisplayString} = useCurrencyListActions();
     const {isOffline} = useNetwork();
-    const styles = useThemeStyles();
-    const StyleUtils = useStyleUtils();
-    const {isLargeScreenWidth} = useResponsiveLayout();
 
     const groupItem = item as unknown as TransactionGroupListItemType;
     const isExpenseReportType = searchType === CONST.SEARCH.DATA_TYPES.EXPENSE_REPORT;
@@ -229,38 +220,31 @@ function GroupChildrenContent({
     };
 
     return (
-        <>
-            {isLargeScreenWidth && !isEmpty && (
-                <View style={styles.ph3}>
-                    <View style={StyleUtils.getSelectedBorderBottomStyle(isSelected)} />
-                </View>
-            )}
-            <TransactionGroupListExpandedItem
-                showTooltip
-                canSelectMultiple={canSelectMultiple}
-                onSelectionButtonPress={onCheckboxPress}
-                onSelectRow={onSelectRow}
-                columns={columns}
-                groupBy={groupBy}
-                accountID={currentUserDetails.accountID}
-                isOffline={isOffline}
-                violations={filteredViolations}
-                transactions={transactions}
-                transactionsVisibleLimit={transactionsVisibleLimit}
-                setTransactionsVisibleLimit={setTransactionsVisibleLimit}
-                isEmpty={isEmpty}
-                shouldDisplayEmptyView={shouldDisplayEmptyView}
-                isExpenseReportType={isExpenseReportType}
-                transactionsSnapshot={transactionsSnapshot}
-                transactionsQueryJSON={groupItem.transactionsQueryJSON}
-                searchTransactions={searchTransactions}
-                isInSingleTransactionReport={groupItem.transactions.length === 1}
-                onLongPress={onExpandedRowLongPress}
-                nonPersonalAndWorkspaceCards={nonPersonalAndWorkspaceCards}
-                onUndelete={onUndelete}
-                hideSearchTableHeader
-            />
-        </>
+        <TransactionGroupListExpandedItem
+            showTooltip
+            canSelectMultiple={canSelectMultiple}
+            onSelectionButtonPress={onCheckboxPress}
+            onSelectRow={onSelectRow}
+            columns={columns}
+            groupBy={groupBy}
+            accountID={currentUserDetails.accountID}
+            isOffline={isOffline}
+            violations={filteredViolations}
+            transactions={transactions}
+            transactionsVisibleLimit={transactionsVisibleLimit}
+            setTransactionsVisibleLimit={setTransactionsVisibleLimit}
+            isEmpty={isEmpty}
+            shouldDisplayEmptyView={shouldDisplayEmptyView}
+            isExpenseReportType={isExpenseReportType}
+            transactionsSnapshot={transactionsSnapshot}
+            transactionsQueryJSON={groupItem.transactionsQueryJSON}
+            searchTransactions={searchTransactions}
+            isInSingleTransactionReport={groupItem.transactions.length === 1}
+            onLongPress={onExpandedRowLongPress}
+            nonPersonalAndWorkspaceCards={nonPersonalAndWorkspaceCards}
+            onUndelete={onUndelete}
+            hideSearchTableHeader
+        />
     );
 }
 
diff --git a/src/components/Search/SearchList/ListItem/GroupHeader.tsx b/src/components/Search/SearchList/ListItem/GroupHeader.tsx
index f2e6eff765a1..7f1d2077a1e2 100644
--- a/src/components/Search/SearchList/ListItem/GroupHeader.tsx
+++ b/src/components/Search/SearchList/ListItem/GroupHeader.tsx
@@ -29,7 +29,6 @@ import getNonEmptyStringOnyxID from '@libs/getNonEmptyStringOnyxID';
 import type {ModifiedMouseEvent} from '@libs/Navigation/helpers/openInternalRouteInNewTab';
 import {getColumnsToShow} from '@libs/SearchUIUtils';
 import {isDeletedTransaction} from '@libs/TransactionUtils';
-import variables from '@styles/variables';
 import CONST from '@src/CONST';
 import ONYXKEYS from '@src/ONYXKEYS';
 import type {ReportAction, ReportActions} from '@src/types/onyx';
@@ -487,6 +486,9 @@ function GroupHeader({
                                                 isActionColumnWide={isSubHeaderActionColumnWide}
                                             />
                                         </View>
+                                        <View style={styles.ph3}>
+                                            <View style={StyleUtils.getSelectedBorderBottomStyle(isItemSelected)} />
+                                        </View>
                                     </View>
                                 )}
                             </Animated.View>

From 903e5ed27599e413bde84a44797e9b9563717be2 Mon Sep 17 00:00:00 2001
From: krishna2323 <belivethatkg@gmail.com>
Date: Tue, 2 Jun 2026 18:35:58 +0530
Subject: [PATCH 096/435] Address PR review: extract shared animation hook, fix
 magic numbers, and enable group selection

Signed-off-by: krishna2323 <belivethatkg@gmail.com>
---
 .../ListItem/GroupChildrenContainer.tsx       | 55 ++-----------------
 .../ListItem/GroupChildrenContent.tsx         |  3 +
 .../SearchList/ListItem/GroupHeader.tsx       | 48 +++-------------
 src/hooks/useExpandCollapseAnimation.ts       | 51 +++++++++++++++++
 4 files changed, 67 insertions(+), 90 deletions(-)
 create mode 100644 src/hooks/useExpandCollapseAnimation.ts

diff --git a/src/components/Search/SearchList/ListItem/GroupChildrenContainer.tsx b/src/components/Search/SearchList/ListItem/GroupChildrenContainer.tsx
index 747d655dffa0..904a2f98152d 100644
--- a/src/components/Search/SearchList/ListItem/GroupChildrenContainer.tsx
+++ b/src/components/Search/SearchList/ListItem/GroupChildrenContainer.tsx
@@ -1,10 +1,8 @@
-import React, {useEffect, useState} from 'react';
 import {View} from 'react-native';
 import type {OnyxCollection, OnyxEntry} from 'react-native-onyx';
-import Animated, {useAnimatedStyle, useDerivedValue, useSharedValue, withTiming} from 'react-native-reanimated';
-import {scheduleOnRN} from 'react-native-worklets';
-import {easing} from '@components/Modal/ReanimatedModal/utils';
+import Animated from 'react-native-reanimated';
 import type {SearchColumnType, SearchGroupBy} from '@components/Search/types';
+import useExpandCollapseAnimation from '@hooks/useExpandCollapseAnimation';
 import useTheme from '@hooks/useTheme';
 import useThemeStyles from '@hooks/useThemeStyles';
 import type {TransactionPreviewData} from '@libs/actions/Search';
@@ -57,43 +55,7 @@ function GroupChildrenContainer({
 }: GroupChildrenContainerProps) {
     const theme = useTheme();
     const styles = useThemeStyles();
-
-    const contentHeight = useSharedValue(0);
-    const hasExpanded = useSharedValue(isExpanded);
-    const [isRendered, setIsRendered] = useState(isExpanded);
-
-    useEffect(() => {
-        hasExpanded.set(isExpanded);
-    }, [isExpanded, hasExpanded]);
-
-    if (isExpanded && !isRendered) {
-        setIsRendered(true);
-    }
-
-    const animatedHeight = useDerivedValue(() => {
-        if (!contentHeight.get()) {
-            return 0;
-        }
-        const target = hasExpanded.get() ? contentHeight.get() : 0;
-        return withTiming(target, {duration: 300, easing}, (finished) => {
-            if (!finished || target) {
-                return;
-            }
-            scheduleOnRN(setIsRendered, false);
-        });
-    }, []);
-
-    const animatedOpacity = useDerivedValue(() => {
-        if (!contentHeight.get()) {
-            return 0;
-        }
-        return withTiming(hasExpanded.get() ? 1 : 0, {duration: 300, easing});
-    });
-
-    const contentAnimatedStyle = useAnimatedStyle(() => ({
-        height: animatedHeight.get(),
-        opacity: animatedOpacity.get(),
-    }));
+    const {isRendered, animatedStyle, onLayout} = useExpandCollapseAnimation(isExpanded);
 
     if (!isExpanded && !isRendered) {
         return null;
@@ -101,16 +63,11 @@ function GroupChildrenContainer({
 
     return (
         <View style={[styles.mh5, {backgroundColor: isSelected ? theme.activeComponentBG : theme.highlightBG}, isLastItem && [styles.tableBottomRadius, styles.overflowHidden]]}>
-            <Animated.View style={contentAnimatedStyle}>
+            <Animated.View style={animatedStyle}>
                 {(isExpanded || isRendered) && (
                     <Animated.View
-                        style={[styles.stickToTop, {paddingBottom: 4}]}
-                        onLayout={(e) => {
-                            const height = e.nativeEvent.layout.height;
-                            if (height) {
-                                contentHeight.set(height);
-                            }
-                        }}
+                        style={[styles.stickToTop, styles.pb1]}
+                        onLayout={onLayout}
                     >
                         <GroupChildrenContent
                             item={item}
diff --git a/src/components/Search/SearchList/ListItem/GroupChildrenContent.tsx b/src/components/Search/SearchList/ListItem/GroupChildrenContent.tsx
index 8ab547e70d44..a32eb57fb567 100644
--- a/src/components/Search/SearchList/ListItem/GroupChildrenContent.tsx
+++ b/src/components/Search/SearchList/ListItem/GroupChildrenContent.tsx
@@ -153,6 +153,7 @@ function GroupChildrenContent({
             return;
         }
         refreshTransactions();
+        // Only refresh when a new transaction is created in this group — refreshTransactions is excluded to avoid infinite loops
         // eslint-disable-next-line react-hooks/exhaustive-deps
     }, [newTransactionID, isExpanded]);
 
@@ -161,6 +162,7 @@ function GroupChildrenContent({
             return;
         }
         refreshTransactions();
+        // Only fetch on expand — refreshTransactions and isExpenseReportType are excluded to prevent re-fetching on every render
         // eslint-disable-next-line react-hooks/exhaustive-deps
     }, [isExpanded]);
 
@@ -172,6 +174,7 @@ function GroupChildrenContent({
             return;
         }
         refreshTransactions();
+        // Only refresh when returning to this screen while expanded — other deps excluded to avoid redundant fetches
         // eslint-disable-next-line react-hooks/exhaustive-deps
     }, [isScreenFocused]);
 
diff --git a/src/components/Search/SearchList/ListItem/GroupHeader.tsx b/src/components/Search/SearchList/ListItem/GroupHeader.tsx
index 7f1d2077a1e2..32119c97fdac 100644
--- a/src/components/Search/SearchList/ListItem/GroupHeader.tsx
+++ b/src/components/Search/SearchList/ListItem/GroupHeader.tsx
@@ -1,14 +1,12 @@
-import React, {useEffect, useMemo, useRef, useState} from 'react';
+import React, {useMemo, useRef} from 'react';
 import {View} from 'react-native';
 import type {NativeSyntheticEvent} from 'react-native';
 import type {OnyxEntry} from 'react-native-onyx';
 // eslint-disable-next-line no-restricted-imports
 import {useOnyx as originalUseOnyx} from 'react-native-onyx';
-import Animated, {useAnimatedStyle, useDerivedValue, useSharedValue, withTiming} from 'react-native-reanimated';
-import {scheduleOnRN} from 'react-native-worklets';
+import Animated from 'react-native-reanimated';
 import {getButtonRole} from '@components/Button/utils';
 import Icon from '@components/Icon';
-import {easing} from '@components/Modal/ReanimatedModal/utils';
 import OfflineWithFeedback from '@components/OfflineWithFeedback';
 import {PressableWithFeedback} from '@components/Pressable';
 import {useSearchSelectionContext} from '@components/Search/SearchContext';
@@ -17,6 +15,7 @@ import type {SearchColumnType, SearchCustomColumnIds, SearchGroupBy} from '@comp
 import type {ExtendedTargetedEvent} from '@components/SelectionList/ListItem/types';
 import useAnimatedHighlightStyle from '@hooks/useAnimatedHighlightStyle';
 import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails';
+import useExpandCollapseAnimation from '@hooks/useExpandCollapseAnimation';
 import {useMemoizedLazyExpensifyIcons} from '@hooks/useLazyAsset';
 import useOnyx from '@hooks/useOnyx';
 import useResponsiveLayout from '@hooks/useResponsiveLayout';
@@ -178,38 +177,10 @@ function GroupHeader({
         return {isSubHeaderAmountColumnWide: amountWide, isSubHeaderTaxAmountColumnWide: taxWide, shouldSubHeaderShowYear: showYear, isSubHeaderActionColumnWide: actionWide};
     }, [groupItem.transactions]);
 
-    // Animated sub-header (SearchTableHeader) height
-    const subHeaderHeight = useSharedValue(0);
-    const hasExpanded = useSharedValue(isExpanded);
-    const [isSubHeaderRendered, setIsSubHeaderRendered] = useState(isExpanded);
+    const {isRendered: isSubHeaderRendered, animatedStyle: subHeaderAnimatedStyle, onLayout: onSubHeaderLayout} = useExpandCollapseAnimation(isExpanded);
 
-    useEffect(() => {
-        hasExpanded.set(isExpanded);
-    }, [isExpanded, hasExpanded]);
-
-    if (isExpanded && !isSubHeaderRendered) {
-        setIsSubHeaderRendered(true);
-    }
-
-    const animatedSubHeaderHeight = useDerivedValue(() => {
-        if (!subHeaderHeight.get()) {
-            return 0;
-        }
-        const target = hasExpanded.get() ? subHeaderHeight.get() : 0;
-        return withTiming(target, {duration: 300, easing}, (finished) => {
-            if (!finished || target) {
-                return;
-            }
-            scheduleOnRN(setIsSubHeaderRendered, false);
-        });
-    }, []);
-
-    const subHeaderAnimatedStyle = useAnimatedStyle(() => ({
-        height: animatedSubHeaderHeight.get(),
-        overflow: 'hidden' as const,
-    }));
-
-    const isEmpty = groupItem.transactions.length === 0;
+    const hasSnapshotTransactions = !isExpenseReportType && !!snapshotData && Object.keys(snapshotData).some((key) => key.startsWith(ONYXKEYS.COLLECTION.TRANSACTION));
+    const isEmpty = groupItem.transactions.length === 0 && !hasSnapshotTransactions;
     const isDisabled = item.pendingAction === CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE;
     const isDisabledOrEmpty = isEmpty || isDisabled;
 
@@ -459,12 +430,7 @@ function GroupHeader({
                                 {(isExpanded || isSubHeaderRendered) && (
                                     <View
                                         style={styles.stickToTop}
-                                        onLayout={(e) => {
-                                            const height = e.nativeEvent.layout.height;
-                                            if (height) {
-                                                subHeaderHeight.set(height);
-                                            }
-                                        }}
+                                        onLayout={onSubHeaderLayout}
                                     >
                                         <View style={[styles.ph3, styles.pb1]}>
                                             <View style={[styles.borderBottom, styles.borderNone]} />
diff --git a/src/hooks/useExpandCollapseAnimation.ts b/src/hooks/useExpandCollapseAnimation.ts
new file mode 100644
index 000000000000..fb65c937c416
--- /dev/null
+++ b/src/hooks/useExpandCollapseAnimation.ts
@@ -0,0 +1,51 @@
+import {useEffect, useState} from 'react';
+import type {LayoutChangeEvent} from 'react-native';
+import {useAnimatedStyle, useDerivedValue, useSharedValue, withTiming} from 'react-native-reanimated';
+import {scheduleOnRN} from 'react-native-worklets';
+import {easing} from '@components/Modal/ReanimatedModal/utils';
+
+const EXPAND_COLLAPSE_DURATION = 300;
+
+function useExpandCollapseAnimation(isExpanded: boolean) {
+    const contentHeight = useSharedValue(0);
+    const hasExpanded = useSharedValue(isExpanded);
+    const [isRendered, setIsRendered] = useState(isExpanded);
+
+    useEffect(() => {
+        hasExpanded.set(isExpanded);
+    }, [isExpanded, hasExpanded]);
+
+    if (isExpanded && !isRendered) {
+        setIsRendered(true);
+    }
+
+    const animatedHeight = useDerivedValue(() => {
+        if (!contentHeight.get()) {
+            return 0;
+        }
+        const target = hasExpanded.get() ? contentHeight.get() : 0;
+        return withTiming(target, {duration: EXPAND_COLLAPSE_DURATION, easing}, (finished) => {
+            if (!finished || target) {
+                return;
+            }
+            scheduleOnRN(setIsRendered, false);
+        });
+    }, []);
+
+    const animatedStyle = useAnimatedStyle(() => ({
+        height: animatedHeight.get(),
+        overflow: 'hidden' as const,
+    }));
+
+    const onLayout = (e: LayoutChangeEvent) => {
+        const height = e.nativeEvent.layout.height;
+        if (height) {
+            contentHeight.set(height);
+        }
+    };
+
+    return {isRendered, animatedStyle, onLayout};
+}
+
+export default useExpandCollapseAnimation;
+export {EXPAND_COLLAPSE_DURATION};

From 335c5bfe6630f570a4b33272cfeaecef555a5782 Mon Sep 17 00:00:00 2001
From: krishna2323 <belivethatkg@gmail.com>
Date: Tue, 2 Jun 2026 18:37:42 +0530
Subject: [PATCH 097/435] add react import.

Signed-off-by: krishna2323 <belivethatkg@gmail.com>
---
 .../Search/SearchList/ListItem/GroupChildrenContainer.tsx        | 1 +
 1 file changed, 1 insertion(+)

diff --git a/src/components/Search/SearchList/ListItem/GroupChildrenContainer.tsx b/src/components/Search/SearchList/ListItem/GroupChildrenContainer.tsx
index 904a2f98152d..26a297e7db98 100644
--- a/src/components/Search/SearchList/ListItem/GroupChildrenContainer.tsx
+++ b/src/components/Search/SearchList/ListItem/GroupChildrenContainer.tsx
@@ -1,3 +1,4 @@
+import React from 'react';
 import {View} from 'react-native';
 import type {OnyxCollection, OnyxEntry} from 'react-native-onyx';
 import Animated from 'react-native-reanimated';

From 319d8f03b3c33b2a7a431521df90f6201553bd81 Mon Sep 17 00:00:00 2001
From: Rayane <77965000+rayane-d@users.noreply.github.com>
Date: Tue, 2 Jun 2026 14:09:47 +0100
Subject: [PATCH 098/435] add translations

---
 src/languages/de.ts      | 3 +++
 src/languages/es.ts      | 5 +++--
 src/languages/fr.ts      | 3 +++
 src/languages/it.ts      | 3 +++
 src/languages/ja.ts      | 3 +++
 src/languages/nl.ts      | 3 +++
 src/languages/pl.ts      | 3 +++
 src/languages/pt-BR.ts   | 3 +++
 src/languages/zh-hans.ts | 3 +++
 9 files changed, 27 insertions(+), 2 deletions(-)

diff --git a/src/languages/de.ts b/src/languages/de.ts
index c5b42c1bd063..a8e83809cd3d 100644
--- a/src/languages/de.ts
+++ b/src/languages/de.ts
@@ -7870,6 +7870,9 @@ Fügen Sie weitere Ausgabelimits hinzu, um den Cashflow Ihres Unternehmens zu sc
                 composeFromCards: ({content, cards}: {content: string; cards: string}) => `${content} von ${cards}`,
             },
         },
+        updatedCategoryTaxRate: ({categoryName, oldTax, newTax}: {categoryName: string; oldTax: string; newTax: string}) => {
+            return `hat den Standardsteuersatz der Kategorie „${categoryName}“ auf „${newTax}“ geändert (zuvor „${oldTax}“)`;
+        },
     },
     roomMembersPage: {
         memberNotFound: 'Mitglied nicht gefunden.',
diff --git a/src/languages/es.ts b/src/languages/es.ts
index a0f138ef3474..3ee10acad8af 100644
--- a/src/languages/es.ts
+++ b/src/languages/es.ts
@@ -7581,8 +7581,9 @@ ${amount} para ${merchant} - ${date}`,
         updatedAutoPayApprovedReportsLimit: ({oldLimit, newLimit}: {oldLimit: string; newLimit: string}) =>
             `cambió el umbral de autopago de informes aprobados a "${newLimit}" (previamente "${oldLimit}")`,
         removedAutoPayApprovedReportsLimit: 'eliminó el umbral de autopago de informes aprobados',
-        updatedCategoryTaxRate: ({categoryName, oldTax, newTax}: {categoryName: string; oldTax: string; newTax: string}) =>
-            `actualizó la tasa de impuesto predeterminada de la categoría "${categoryName}" a "${newTax}" (previamente "${oldTax}")`,
+        updatedCategoryTaxRate: ({categoryName, oldTax, newTax}: {categoryName: string; oldTax: string; newTax: string}) => {
+            return `cambió la tasa de impuesto predeterminada de la categoría "${categoryName}" a "${newTax}" (previamente "${oldTax}")`;
+        },
         changedDefaultApprover: ({newApprover, previousApprover}: {newApprover: string; previousApprover?: string}) =>
             previousApprover ? `cambió el aprobador predeterminado a ${newApprover} (anteriormente ${previousApprover})` : `cambió el aprobador predeterminado a ${newApprover}`,
         changedSubmitsToApprover: ({
diff --git a/src/languages/fr.ts b/src/languages/fr.ts
index 2dc27d7b1f83..17187256c81c 100644
--- a/src/languages/fr.ts
+++ b/src/languages/fr.ts
@@ -7904,6 +7904,9 @@ Ajoutez davantage de règles de dépenses pour protéger la trésorerie de l’e
                 composeFromCards: ({content, cards}: {content: string; cards: string}) => `${content} de ${cards}`,
             },
         },
+        updatedCategoryTaxRate: ({categoryName, oldTax, newTax}: {categoryName: string; oldTax: string; newTax: string}) => {
+            return `a modifié le taux de taxe par défaut de la catégorie « ${categoryName} » en « ${newTax} » (auparavant « ${oldTax} »)`;
+        },
     },
     roomMembersPage: {
         memberNotFound: 'Membre introuvable.',
diff --git a/src/languages/it.ts b/src/languages/it.ts
index 7099cd2bf4d1..053389ffb29a 100644
--- a/src/languages/it.ts
+++ b/src/languages/it.ts
@@ -7859,6 +7859,9 @@ Aggiungi altre regole di spesa per proteggere il flusso di cassa aziendale.`,
                 composeFromCards: ({content, cards}: {content: string; cards: string}) => `${content} da ${cards}`,
             },
         },
+        updatedCategoryTaxRate: ({categoryName, oldTax, newTax}: {categoryName: string; oldTax: string; newTax: string}) => {
+            return `ha cambiato l’aliquota fiscale predefinita della categoria "${categoryName}" in "${newTax}" (in precedenza "${oldTax}")`;
+        },
     },
     roomMembersPage: {
         memberNotFound: 'Membro non trovato.',
diff --git a/src/languages/ja.ts b/src/languages/ja.ts
index 11fda2fd0715..7cf53b4c1ee6 100644
--- a/src/languages/ja.ts
+++ b/src/languages/ja.ts
@@ -7768,6 +7768,9 @@ ${reportName}
                 composeFromCards: ({content, cards}: {content: string; cards: string}) => `${cards} からの ${content}`,
             },
         },
+        updatedCategoryTaxRate: ({categoryName, oldTax, newTax}: {categoryName: string; oldTax: string; newTax: string}) => {
+            return `「${categoryName}」カテゴリのデフォルト税率を「${newTax}」に変更しました（以前は「${oldTax}」）`;
+        },
     },
     roomMembersPage: {
         memberNotFound: 'メンバーが見つかりません。',
diff --git a/src/languages/nl.ts b/src/languages/nl.ts
index d6c80fc5622f..0c8dca0a4430 100644
--- a/src/languages/nl.ts
+++ b/src/languages/nl.ts
@@ -7829,6 +7829,9 @@ er bestedingsregels toe om de kasstroom van het bedrijf te beschermen.`,
                 composeFromCards: ({content, cards}: {content: string; cards: string}) => `${content} van ${cards}`,
             },
         },
+        updatedCategoryTaxRate: ({categoryName, oldTax, newTax}: {categoryName: string; oldTax: string; newTax: string}) => {
+            return `heeft het standaardbelastingtarief van de categorie "${categoryName}" gewijzigd naar "${newTax}" (voorheen "${oldTax}")`;
+        },
     },
     roomMembersPage: {
         memberNotFound: 'Lid niet gevonden.',
diff --git a/src/languages/pl.ts b/src/languages/pl.ts
index 82e7399524dd..c939e2ea1b06 100644
--- a/src/languages/pl.ts
+++ b/src/languages/pl.ts
@@ -7818,6 +7818,9 @@ Dodaj więcej zasad wydatków, żeby chronić płynność finansową firmy.`,
                 composeFromCards: ({content, cards}: {content: string; cards: string}) => `${content} z ${cards}`,
             },
         },
+        updatedCategoryTaxRate: ({categoryName, oldTax, newTax}: {categoryName: string; oldTax: string; newTax: string}) => {
+            return `zmienił(a) domyślną stawkę podatku dla kategorii „${categoryName}” na „${newTax}” (wcześniej „${oldTax}”)`;
+        },
     },
     roomMembersPage: {
         memberNotFound: 'Nie znaleziono członka.',
diff --git a/src/languages/pt-BR.ts b/src/languages/pt-BR.ts
index 14b51f00ff9f..2b9b208d03a5 100644
--- a/src/languages/pt-BR.ts
+++ b/src/languages/pt-BR.ts
@@ -7821,6 +7821,9 @@ Adicione mais regras de gasto para proteger o fluxo de caixa da empresa.`,
                 composeFromCards: ({content, cards}: {content: string; cards: string}) => `${content} de ${cards}`,
             },
         },
+        updatedCategoryTaxRate: ({categoryName, oldTax, newTax}: {categoryName: string; oldTax: string; newTax: string}) => {
+            return `alterou a alíquota de imposto padrão da categoria "${categoryName}" para "${newTax}" (antes "${oldTax}")`;
+        },
     },
     roomMembersPage: {
         memberNotFound: 'Membro não encontrado.',
diff --git a/src/languages/zh-hans.ts b/src/languages/zh-hans.ts
index 42c93935eb44..023c0314546c 100644
--- a/src/languages/zh-hans.ts
+++ b/src/languages/zh-hans.ts
@@ -7619,6 +7619,9 @@ ${reportName}
                 composeFromCards: ({content, cards}: {content: string; cards: string}) => `来自 ${cards} 的 ${content}`,
             },
         },
+        updatedCategoryTaxRate: ({categoryName, oldTax, newTax}: {categoryName: string; oldTax: string; newTax: string}) => {
+            return `将“${categoryName}”类别的默认税率更改为“${newTax}”（之前为“${oldTax}”）`;
+        },
     },
     roomMembersPage: {
         memberNotFound: '未找到成员。',

From 773ce9fc5a8a56f8aae0f95c9d3d08e357f983ce Mon Sep 17 00:00:00 2001
From: jayeshmangwani <jayeshmangwani@gmail.com>
Date: Tue, 2 Jun 2026 19:01:26 +0530
Subject: [PATCH 099/435] Bulk selection: show "Mark as done" only if all
 selected transactions are eligible; hide action button for mixed selections

---
 src/hooks/useSearchBulkActions.ts | 38 ++++++++++++++++++++++++-------
 1 file changed, 30 insertions(+), 8 deletions(-)

diff --git a/src/hooks/useSearchBulkActions.ts b/src/hooks/useSearchBulkActions.ts
index 16508bc0a20c..c8cd7ef0a8db 100644
--- a/src/hooks/useSearchBulkActions.ts
+++ b/src/hooks/useSearchBulkActions.ts
@@ -52,6 +52,7 @@ import {
     isInvoiceReport,
     isIOUReport as isIOUReportUtil,
     isSelfDM,
+    shouldShowMarkAsDone,
 } from '@libs/ReportUtils';
 import {buildSearchQueryJSON, buildSearchQueryString, serializeQueryJSONForBackend} from '@libs/SearchQueryUtils';
 import {getSelectedGroupFilterEntry, navigateToSearchRHP, shouldShowDeleteOption} from '@libs/SearchUIUtils';
@@ -1100,6 +1101,33 @@ function useSearchBulkActions({queryJSON}: UseSearchBulkActionsParams) {
         });
     }, [isExpenseReportType, defaultExpensePolicy, selectedReports, accountID]);
 
+    const allReportsShouldMarkAsDone = useMemo(
+        () =>
+            selectedReports.every((report) => {
+                const fullReport = currentSearchResults?.data?.[`${ONYXKEYS.COLLECTION.REPORT}${report.reportID}`];
+
+                return shouldShowMarkAsDone({
+                    isTrackIntentUser,
+                    report: fullReport,
+                    policy: policies?.[`${ONYXKEYS.COLLECTION.POLICY}${report.policyID}`],
+                });
+            }),
+        [selectedReports, shouldShowMarkAsDone],
+    );
+    const noReportsShouldMarkAsDone = useMemo(
+        () =>
+            selectedReports.every((report) => {
+                const fullReport = currentSearchResults?.data?.[`${ONYXKEYS.COLLECTION.REPORT}${report.reportID}`];
+
+                return !shouldShowMarkAsDone({
+                    isTrackIntentUser,
+                    report: fullReport,
+                    policy: policies?.[`${ONYXKEYS.COLLECTION.POLICY}${report.policyID}`],
+                });
+            }),
+        [selectedReports, shouldShowMarkAsDone],
+    );
+
     const headerButtonsOptions = useMemo(() => {
         if (selectedTransactionsKeys.length === 0 || status == null || !hash) {
             return CONST.EMPTY_ARRAY as unknown as Array<DropdownOption<SearchHeaderOptionValue>>;
@@ -1436,19 +1464,13 @@ function useSearchBulkActions({queryJSON}: UseSearchBulkActionsParams) {
             (selectedReports.length
                 ? selectedReports.every((report) => report.allActions.includes(CONST.SEARCH.ACTION_TYPES.SUBMIT)) &&
                   // Disable for mixed selections: all must be the same submit type
-                  (isTrackIntentUser
-                      ? selectedReports.every((report) => isSubmitAndClose(policies?.[`${ONYXKEYS.COLLECTION.POLICY}${report.policyID}`])) ||
-                        selectedReports.every((report) => !isSubmitAndClose(policies?.[`${ONYXKEYS.COLLECTION.POLICY}${report.policyID}`]))
-                      : true)
+                  (isTrackIntentUser ? allReportsShouldMarkAsDone || noReportsShouldMarkAsDone : true)
                 : selectedTransactionsKeys.every((id) => selectedTransactions[id].action === CONST.SEARCH.ACTION_TYPES.SUBMIT));
 
         if (shouldShowSubmitOption) {
             options.push({
                 icon: expensifyIcons.Send,
-                text:
-                    isTrackIntentUser && selectedReports.length > 0 && selectedReports.every((report) => isSubmitAndClose(policies?.[`${ONYXKEYS.COLLECTION.POLICY}${report.policyID}`]))
-                        ? translate('common.markAsDone')
-                        : translate('common.submit'),
+                text: selectedReports.length > 0 && allReportsShouldMarkAsDone ? translate('common.markAsDone') : translate('common.submit'),
                 value: CONST.SEARCH.BULK_ACTION_TYPES.SUBMIT,
                 shouldCloseModalOnSelect: true,
                 onSelected: () => {

From 35feb10fbacd6f5d12d35bf4760c119bfe896c24 Mon Sep 17 00:00:00 2001
From: Youssef Lourayad <youssef@expensify.com>
Date: Tue, 2 Jun 2026 14:15:21 +0000
Subject: [PATCH 100/435] Adjust styles

---
 src/pages/inbox/sidebar/InboxTabSelector.tsx | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/pages/inbox/sidebar/InboxTabSelector.tsx b/src/pages/inbox/sidebar/InboxTabSelector.tsx
index 8b22b909f140..bc5856afa956 100644
--- a/src/pages/inbox/sidebar/InboxTabSelector.tsx
+++ b/src/pages/inbox/sidebar/InboxTabSelector.tsx
@@ -40,7 +40,7 @@ function InboxTabSelector() {
 
     return (
         <TabSelectorContextProvider activeTabKey={activeTab}>
-            <View style={styles.mb2}>
+            <View style={[styles.pt1, styles.mb1]}>
                 <TabSelectorBase
                     tabs={tabs}
                     activeTabKey={activeTab}

From f2c14045c2756bb55fd880efa6d0cb5f4c4c6466 Mon Sep 17 00:00:00 2001
From: Youssef Lourayad <youssef@expensify.com>
Date: Tue, 2 Jun 2026 14:17:20 +0000
Subject: [PATCH 101/435] Remove unused type

---
 src/types/onyx/InboxTab.ts | 7 -------
 1 file changed, 7 deletions(-)
 delete mode 100644 src/types/onyx/InboxTab.ts

diff --git a/src/types/onyx/InboxTab.ts b/src/types/onyx/InboxTab.ts
deleted file mode 100644
index 3fc35c106b39..000000000000
--- a/src/types/onyx/InboxTab.ts
+++ /dev/null
@@ -1,7 +0,0 @@
-import type {ValueOf} from 'type-fest';
-import type CONST from '@src/CONST';
-
-/** The active Inbox tab filter (All, To-do, or Unread) */
-type InboxTab = ValueOf<typeof CONST.INBOX_TAB>;
-
-export default InboxTab;

From 5155cb2ea03e80690be4be8bdb0165522074bddf Mon Sep 17 00:00:00 2001
From: Adam Horodyski <ad.horodyski@gmail.com>
Date: Tue, 2 Jun 2026 17:58:50 +0200
Subject: [PATCH 102/435] SequentialQueue: resolve isReadyPromise if push()
 goes offline during persist
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

If the network flips offline while push() awaits the Onyx disk write, the sync
prelude has already parked waitForIdle() callers via setIsReadyPromisePending(),
but the subsequent flush(false) early-returns on its offline guard without
resolving isReadyPromise — leaving READs hung until an unrelated reconnect drains
the queue. Re-check isOfflineNetwork() after the await and resolve/return,
matching flush()'s existing offline-resolves-readiness behavior.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
---
 src/libs/Network/SequentialQueue.ts | 12 ++++++++++
 tests/unit/SequentialQueueTest.ts   | 36 +++++++++++++++++++++++++++++
 2 files changed, 48 insertions(+)

diff --git a/src/libs/Network/SequentialQueue.ts b/src/libs/Network/SequentialQueue.ts
index e04b0df38b34..8009166745a5 100644
--- a/src/libs/Network/SequentialQueue.ts
+++ b/src/libs/Network/SequentialQueue.ts
@@ -586,6 +586,18 @@ async function push<TKey extends OnyxKey>(newRequest: OnyxRequest<TKey>): Promis
     // a process kill in that window would lose the request on next launch.
     await persistencePromise;
 
+    // The network may have flipped offline while we awaited the disk write. flush() would
+    // early-return on its offline check without resolving isReadyPromise, leaving READs parked
+    // on waitForIdle() until an unrelated reconnect drains the queue. Resolve here so READs
+    // proceed — consistent with flush() resolving isReadyPromise when offline.
+    if (isOfflineNetwork()) {
+        Log.info('[SequentialQueue] Went offline during persist — resolving isReadyPromise without flushing', false, {
+            command: newRequest.command,
+        });
+        resolveIsReadyPromise?.();
+        return;
+    }
+
     if (isSequentialQueueRunning) {
         Log.info('[SequentialQueue] Queue is running. Will flush when the current request is finished.', false, {
             command: newRequest.command,
diff --git a/tests/unit/SequentialQueueTest.ts b/tests/unit/SequentialQueueTest.ts
index f53a0e91bba0..5082928796fe 100644
--- a/tests/unit/SequentialQueueTest.ts
+++ b/tests/unit/SequentialQueueTest.ts
@@ -1,5 +1,6 @@
 import Onyx from 'react-native-onyx';
 import type {OnyxKey, OnyxUpdate} from 'react-native-onyx';
+import * as NetworkState from '@libs/NetworkState';
 import {clear as clearPersistedRequests, getAll, getLength, getOngoingRequest, updateOngoingRequest} from '@userActions/PersistedRequests';
 import CONST from '@src/CONST';
 import ONYXKEYS from '@src/ONYXKEYS';
@@ -38,6 +39,41 @@ describe('SequentialQueue', () => {
         expect(getLength()).toBe(2);
     });
 
+    it('should resolve waitForIdle without flushing when the network goes offline during persist', async () => {
+        // push()'s sync prelude marks isReadyPromise pending while online, then awaits the disk
+        // write. If the network flips offline during that await, flush() would early-return on its
+        // offline guard without resolving isReadyPromise — leaving waitForIdle() (READs) hung until
+        // an unrelated reconnect. push() must instead resolve isReadyPromise and skip flushing.
+        const offlineSpy = jest.spyOn(NetworkState, 'getIsOffline').mockReturnValue(false);
+        let timeoutId: ReturnType<typeof setTimeout> | undefined;
+        try {
+            // Kick off the push while "online": the synchronous prelude runs up to `await persistencePromise`.
+            const pushPromise = SequentialQueue.push(request);
+
+            // Flip offline while the awaited disk write is still pending.
+            offlineSpy.mockReturnValue(true);
+
+            await pushPromise;
+
+            // The request is still persisted — not flushed, not dropped.
+            expect(getLength()).toBe(1);
+
+            // waitForIdle() must resolve rather than hang.
+            const idleOrTimeout = await Promise.race([
+                SequentialQueue.waitForIdle().then(() => 'resolved' as const),
+                new Promise<'timeout'>((resolve) => {
+                    timeoutId = setTimeout(() => resolve('timeout'), 1000);
+                }),
+            ]);
+            expect(idleOrTimeout).toBe('resolved');
+        } finally {
+            if (timeoutId) {
+                clearTimeout(timeoutId);
+            }
+            offlineSpy.mockRestore();
+        }
+    });
+
     it('should push two requests with conflict resolution and replace', async () => {
         // Pause the queue so `process()` does not consume the first request before
         // the conflict resolver runs. Under persist-before-fire `push()` is async,

From 5ab1b65be031a522f3c66d1b21ab903d3169c4a6 Mon Sep 17 00:00:00 2001
From: Youssef Lourayad <youssef@expensify.com>
Date: Wed, 3 Jun 2026 00:10:14 +0000
Subject: [PATCH 103/435] Reduce bottom padding

---
 src/components/TabSelector/TabSelectorBase.tsx | 3 ++-
 src/components/TabSelector/types.ts            | 3 +++
 src/pages/inbox/sidebar/InboxTabSelector.tsx   | 3 ++-
 3 files changed, 7 insertions(+), 2 deletions(-)

diff --git a/src/components/TabSelector/TabSelectorBase.tsx b/src/components/TabSelector/TabSelectorBase.tsx
index f9b456c150fd..bae90ce0a59c 100644
--- a/src/components/TabSelector/TabSelectorBase.tsx
+++ b/src/components/TabSelector/TabSelectorBase.tsx
@@ -26,6 +26,7 @@ function TabSelectorBase({
     position,
     shouldShowLabelWhenInactive = true,
     equalWidth = false,
+    contentContainerStyles,
     shouldShowProductTrainingTooltip = false,
     renderProductTrainingTooltip,
 }: TabSelectorBaseProps) {
@@ -63,7 +64,7 @@ function TabSelectorBase({
             }}
             ref={containerRef}
             style={styles.scrollableTabSelector}
-            contentContainerStyle={styles.tabSelectorContentContainer}
+            contentContainerStyle={[styles.tabSelectorContentContainer, contentContainerStyles]}
             horizontal
             showsHorizontalScrollIndicator={false}
             keyboardShouldPersistTaps="handled"
diff --git a/src/components/TabSelector/types.ts b/src/components/TabSelector/types.ts
index fe0092815357..23e6f94e4317 100644
--- a/src/components/TabSelector/types.ts
+++ b/src/components/TabSelector/types.ts
@@ -83,6 +83,9 @@ type TabSelectorBaseProps = {
     /** Whether tabs should have equal width. */
     equalWidth?: boolean;
 
+    /** Additional styles for the tabs' scroll content container. */
+    contentContainerStyles?: StyleProp<ViewStyle>;
+
     /** Determines whether the product training tooltip should be displayed to the user. */
     shouldShowProductTrainingTooltip?: boolean;
 
diff --git a/src/pages/inbox/sidebar/InboxTabSelector.tsx b/src/pages/inbox/sidebar/InboxTabSelector.tsx
index bc5856afa956..6e80677cfbfe 100644
--- a/src/pages/inbox/sidebar/InboxTabSelector.tsx
+++ b/src/pages/inbox/sidebar/InboxTabSelector.tsx
@@ -40,12 +40,13 @@ function InboxTabSelector() {
 
     return (
         <TabSelectorContextProvider activeTabKey={activeTab}>
-            <View style={[styles.pt1, styles.mb1]}>
+            <View style={styles.pt1}>
                 <TabSelectorBase
                     tabs={tabs}
                     activeTabKey={activeTab}
                     onTabPress={(key) => setActiveTab(key as ValueOf<typeof CONST.INBOX_TAB>)}
                     equalWidth
+                    contentContainerStyles={styles.pb1}
                 />
             </View>
         </TabSelectorContextProvider>

From 8cd8c698fb09e086ea77577f426760e680289623 Mon Sep 17 00:00:00 2001
From: Youssef Lourayad <youssef@expensify.com>
Date: Wed, 3 Jun 2026 00:15:19 +0000
Subject: [PATCH 104/435] Increase gap size between text and badge

---
 src/styles/index.ts | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/styles/index.ts b/src/styles/index.ts
index ae4ce584aa13..8367adf255eb 100644
--- a/src/styles/index.ts
+++ b/src/styles/index.ts
@@ -4471,7 +4471,7 @@ const staticStyles = (theme: ThemeColors) =>
         inboxTabBadge: {
             minWidth: 18,
             height: 16,
-            marginLeft: 4,
+            marginLeft: 8,
             justifyContent: 'center',
         },
 

From 958b6c0981137e6730125fc7d469adc9a4d41e82 Mon Sep 17 00:00:00 2001
From: jayeshmangwani <jayeshmangwani@gmail.com>
Date: Wed, 3 Jun 2026 12:46:36 +0530
Subject: [PATCH 105/435] changed the optimisticNextStep strings for
 track-intent users to show the 'Mark as done' text where applicable

---
 src/libs/NextStepUtils.ts | 15 +++++++++------
 1 file changed, 9 insertions(+), 6 deletions(-)

diff --git a/src/libs/NextStepUtils.ts b/src/libs/NextStepUtils.ts
index a7bdb39b3bda..5dd4edace9c0 100644
--- a/src/libs/NextStepUtils.ts
+++ b/src/libs/NextStepUtils.ts
@@ -602,6 +602,7 @@ function buildNextStepNew(params: BuildNextStepNewParams): ReportNextStepDepreca
                 break;
             }
             if (isReopen) {
+                const shouldShowMarkAsDoneCopy = shouldShowMarkAsDone({isTrackIntentUser: isTrackOnboardingChoice(introSelected?.choice), report, policy});
                 optimisticNextStep = {
                     type,
                     icon: CONST.NEXT_STEP.ICONS.HOURGLASS,
@@ -618,16 +619,17 @@ function buildNextStepNew(params: BuildNextStepNewParams): ReportNextStepDepreca
                             text: ' to ',
                         },
                         {
-                            text: 'submit',
+                            text: shouldShowMarkAsDoneCopy ? 'mark this as done' : 'submit',
                         },
                         {
-                            text: ' %expenses.',
+                            text: shouldShowMarkAsDoneCopy ? '.' : ' %expenses.',
                         },
                     ],
                 };
                 break;
             }
 
+            const shouldShowMarkAsDoneCopy = shouldShowMarkAsDone({isTrackIntentUser: isTrackOnboardingChoice(introSelected?.choice), report, policy});
             // Self review
             optimisticNextStep = {
                 type,
@@ -645,10 +647,10 @@ function buildNextStepNew(params: BuildNextStepNewParams): ReportNextStepDepreca
                         text: ' to ',
                     },
                     {
-                        text: hasTransactions ? 'submit' : 'add',
+                        text: shouldShowMarkAsDoneCopy ? 'mark this as done' : 'submit',
                     },
                     {
-                        text: ' %expenses.',
+                        text: shouldShowMarkAsDoneCopy ? '.' : ' %expenses.',
                     },
                 ],
             };
@@ -709,6 +711,7 @@ function buildNextStepNew(params: BuildNextStepNewParams): ReportNextStepDepreca
 
             // Manual submission
             if (hasTransactions && !policy?.harvesting?.enabled) {
+                const shouldShowMarkAsDoneCopy = shouldShowMarkAsDone({isTrackIntentUser: isTrackOnboardingChoice(introSelected?.choice), report, policy});
                 optimisticNextStep.message = [
                     {
                         text: 'Waiting for ',
@@ -722,10 +725,10 @@ function buildNextStepNew(params: BuildNextStepNewParams): ReportNextStepDepreca
                         text: ' to ',
                     },
                     {
-                        text: 'submit',
+                        text: shouldShowMarkAsDoneCopy ? 'mark this as done' : 'submit',
                     },
                     {
-                        text: ' %expenses.',
+                        text: shouldShowMarkAsDoneCopy ? '.' : ' %expenses.',
                     },
                 ];
             }

From 6315c15377c59b46d77cd8bb17f1dc8495fb28d5 Mon Sep 17 00:00:00 2001
From: Adam Grzybowski <adam.grzybowski@swmansion.com>
Date: Wed, 3 Jun 2026 11:47:40 +0200
Subject: [PATCH 106/435] Add translations

---
 src/languages/de.ts      | 1 +
 src/languages/es.ts      | 1 +
 src/languages/fr.ts      | 1 +
 src/languages/it.ts      | 1 +
 src/languages/ja.ts      | 1 +
 src/languages/nl.ts      | 1 +
 src/languages/pl.ts      | 1 +
 src/languages/pt-BR.ts   | 1 +
 src/languages/zh-hans.ts | 1 +
 9 files changed, 9 insertions(+)

diff --git a/src/languages/de.ts b/src/languages/de.ts
index 9a5d43843811..5f16a3ad188c 100644
--- a/src/languages/de.ts
+++ b/src/languages/de.ts
@@ -1005,6 +1005,7 @@ const translations: TranslationDeepObject<typeof en> = {
                 f1FlagsTitle: 'Alles erledigt',
                 f1FlagsDescription: 'Sie haben alle offenen Aufgaben abgeschlossen.',
             },
+            reviewExpenses: ({count}: {count: number}) => `Überprüfen Sie ${count} ${count === 1 ? 'Ausgabe' : 'Spesen'}`,
         },
         upcomingTravel: 'Bevorstehende Reisen',
         upcomingTravelSection: {
diff --git a/src/languages/es.ts b/src/languages/es.ts
index 9ed06f7e346a..471f0899f1a7 100644
--- a/src/languages/es.ts
+++ b/src/languages/es.ts
@@ -985,6 +985,7 @@ const translations: TranslationDeepObject<typeof en> = {
                 f1FlagsTitle: 'Todo al día',
                 f1FlagsDescription: 'Has completado todas las tareas pendientes.',
             },
+            reviewExpenses: ({count}: {count: number}) => `Revisa ${count} ${count === 1 ? 'gasto' : 'gastos'}`,
         },
         gettingStartedSection: {
             title: 'Primeros pasos',
diff --git a/src/languages/fr.ts b/src/languages/fr.ts
index b6b2a7801543..a4d1fd03f3c4 100644
--- a/src/languages/fr.ts
+++ b/src/languages/fr.ts
@@ -1008,6 +1008,7 @@ const translations: TranslationDeepObject<typeof en> = {
                 f1FlagsTitle: 'Tout est à jour',
                 f1FlagsDescription: 'Vous avez terminé toutes les tâches en cours.',
             },
+            reviewExpenses: ({count}: {count: number}) => `Examiner ${count} ${count === 1 ? 'dépense' : 'dépenses'}`,
         },
         upcomingTravel: 'Voyages à venir',
         upcomingTravelSection: {
diff --git a/src/languages/it.ts b/src/languages/it.ts
index 705ae2ec94d0..d18c7039ba51 100644
--- a/src/languages/it.ts
+++ b/src/languages/it.ts
@@ -1006,6 +1006,7 @@ const translations: TranslationDeepObject<typeof en> = {
                 f1FlagsTitle: 'Tutto a posto',
                 f1FlagsDescription: 'Hai completato tutte le attività in sospeso.',
             },
+            reviewExpenses: ({count}: {count: number}) => `Esamina ${count} ${count === 1 ? 'spesa' : 'spese'}`,
         },
         upcomingTravel: 'Prossimi viaggi',
         upcomingTravelSection: {
diff --git a/src/languages/ja.ts b/src/languages/ja.ts
index 22dff1932990..230674aef9a9 100644
--- a/src/languages/ja.ts
+++ b/src/languages/ja.ts
@@ -989,6 +989,7 @@ const translations: TranslationDeepObject<typeof en> = {
                 f1FlagsTitle: 'すべて確認済みです',
                 f1FlagsDescription: 'すべての未処理の To-do が完了しました。',
             },
+            reviewExpenses: ({count}: {count: number}) => `${count} 件の${count === 1 ? '経費' : '経費'}を確認`,
         },
         upcomingTravel: '今後の出張',
         upcomingTravelSection: {
diff --git a/src/languages/nl.ts b/src/languages/nl.ts
index b6f95c44ed34..477ce90bbae6 100644
--- a/src/languages/nl.ts
+++ b/src/languages/nl.ts
@@ -1004,6 +1004,7 @@ const translations: TranslationDeepObject<typeof en> = {
                 f1FlagsTitle: 'Helemaal bij',
                 f1FlagsDescription: "Je hebt alle openstaande to-do's afgerond.",
             },
+            reviewExpenses: ({count}: {count: number}) => `Beoordeel ${count} ${count === 1 ? 'uitgave' : 'uitgaven'}`,
         },
         upcomingTravel: 'Aankomende reizen',
         upcomingTravelSection: {
diff --git a/src/languages/pl.ts b/src/languages/pl.ts
index 1fe87f4ec8c4..75b68ef80900 100644
--- a/src/languages/pl.ts
+++ b/src/languages/pl.ts
@@ -1006,6 +1006,7 @@ const translations: TranslationDeepObject<typeof en> = {
                 f1FlagsTitle: 'Wszystko nadrobione',
                 f1FlagsDescription: 'Ukończyłeś wszystkie zaległe zadania.',
             },
+            reviewExpenses: ({count}: {count: number}) => `Przejrzyj ${count} ${count === 1 ? 'wydatek' : 'wydatki'}`,
         },
         upcomingTravel: 'Nadchodząca podróż',
         upcomingTravelSection: {
diff --git a/src/languages/pt-BR.ts b/src/languages/pt-BR.ts
index 394be17dc887..5fb2e3a69dfb 100644
--- a/src/languages/pt-BR.ts
+++ b/src/languages/pt-BR.ts
@@ -1004,6 +1004,7 @@ const translations: TranslationDeepObject<typeof en> = {
                 f1FlagsTitle: 'Tudo em dia',
                 f1FlagsDescription: 'Você concluiu todas as tarefas pendentes.',
             },
+            reviewExpenses: ({count}: {count: number}) => `Revisar ${count} ${count === 1 ? 'despesa' : 'despesas'}`,
         },
         upcomingTravel: 'Próximas viagens',
         upcomingTravelSection: {
diff --git a/src/languages/zh-hans.ts b/src/languages/zh-hans.ts
index 8013eff5912d..afe96f3cd947 100644
--- a/src/languages/zh-hans.ts
+++ b/src/languages/zh-hans.ts
@@ -972,6 +972,7 @@ const translations: TranslationDeepObject<typeof en> = {
                 f1FlagsTitle: '全部完成',
                 f1FlagsDescription: '你已完成所有未完成的待办事项。',
             },
+            reviewExpenses: ({count}: {count: number}) => `审核 ${count} ${count === 1 ? '费用' : '费用'}`,
         },
         upcomingTravel: '即将出行',
         upcomingTravelSection: {

From 3da501cba6674ebf2621db3eba027c817a1f1a7b Mon Sep 17 00:00:00 2001
From: Adam Grzybowski <adam.grzybowski@swmansion.com>
Date: Wed, 3 Jun 2026 12:45:49 +0200
Subject: [PATCH 107/435] Remove unused type exports flagged by knip

---
 src/hooks/useNavigateToTransactionThread.ts              | 1 -
 src/pages/home/ForYouSection/useReviewFlaggedExpenses.ts | 1 -
 src/selectors/Todos.ts                                   | 1 -
 3 files changed, 3 deletions(-)

diff --git a/src/hooks/useNavigateToTransactionThread.ts b/src/hooks/useNavigateToTransactionThread.ts
index df7b648d48ab..914a27ffdc4d 100644
--- a/src/hooks/useNavigateToTransactionThread.ts
+++ b/src/hooks/useNavigateToTransactionThread.ts
@@ -85,4 +85,3 @@ function useNavigateToTransactionThread() {
 }
 
 export default useNavigateToTransactionThread;
-export type {NavigateToTransactionThreadParams};
diff --git a/src/pages/home/ForYouSection/useReviewFlaggedExpenses.ts b/src/pages/home/ForYouSection/useReviewFlaggedExpenses.ts
index c04331a02291..3957511ad012 100644
--- a/src/pages/home/ForYouSection/useReviewFlaggedExpenses.ts
+++ b/src/pages/home/ForYouSection/useReviewFlaggedExpenses.ts
@@ -49,4 +49,3 @@ function useReviewFlaggedExpenses(): ReviewFlaggedExpenses {
 }
 
 export default useReviewFlaggedExpenses;
-export type {ReviewFlaggedExpenses};
diff --git a/src/selectors/Todos.ts b/src/selectors/Todos.ts
index e0e8eb3565ad..b0a628f1ed5a 100644
--- a/src/selectors/Todos.ts
+++ b/src/selectors/Todos.ts
@@ -125,4 +125,3 @@ const flaggedExpensesReviewSelector = (flaggedExpensesValue: OnyxEntry<FlaggedEx
 
 export default todosReportCountsSelector;
 export {EMPTY_FLAGGED_EXPENSES_REVIEW, EMPTY_TODOS_SINGLE_REPORT_IDS, flaggedExpensesReviewSelector, todosSingleReportIDsSelector};
-export type {FlaggedExpensesReview};

From 919037f79cef221ca3fc39e27f6cd5a9ec2c96a4 Mon Sep 17 00:00:00 2001
From: Rayane <77965000+rayane-d@users.noreply.github.com>
Date: Wed, 3 Jun 2026 12:30:00 +0100
Subject: [PATCH 108/435] fix conflicts

---
 src/libs/OptionsListUtils/index.ts   |  1 +
 src/libs/ReportNameUtils.ts          |  1 +
 tests/unit/ReportActionsUtilsTest.ts | 35 ++++++++++++++++------------
 3 files changed, 22 insertions(+), 15 deletions(-)

diff --git a/src/libs/OptionsListUtils/index.ts b/src/libs/OptionsListUtils/index.ts
index af427f991d61..055aab7553c8 100644
--- a/src/libs/OptionsListUtils/index.ts
+++ b/src/libs/OptionsListUtils/index.ts
@@ -929,6 +929,7 @@ function getLastMessageTextForReport({
     }
     if (isActionOfType(lastReportAction, CONST.REPORT.ACTIONS.TYPE.POLICY_CHANGE_LOG.UPDATE_CATEGORY_TAX_RATE)) {
         lastMessageTextFromReport = getCategoryTaxRateMessage(translate, lastReportAction);
+    }
     if (isActionOfType(lastReportAction, CONST.REPORT.ACTIONS.TYPE.POLICY_CHANGE_LOG.UPDATE_MCC_GROUP_CATEGORY)) {
         lastMessageTextFromReport = getMccGroupCategoryMessage(translate, lastReportAction);
     }
diff --git a/src/libs/ReportNameUtils.ts b/src/libs/ReportNameUtils.ts
index 67b3ccb9c4b7..31cd193a187b 100644
--- a/src/libs/ReportNameUtils.ts
+++ b/src/libs/ReportNameUtils.ts
@@ -586,6 +586,7 @@ function computeReportNameBasedOnReportAction(
     }
     if (isActionOfType(parentReportAction, CONST.REPORT.ACTIONS.TYPE.POLICY_CHANGE_LOG.UPDATE_CATEGORY_TAX_RATE)) {
         return getCategoryTaxRateMessage(translate, parentReportAction);
+    }
     if (isActionOfType(parentReportAction, CONST.REPORT.ACTIONS.TYPE.POLICY_CHANGE_LOG.UPDATE_MCC_GROUP_CATEGORY)) {
         return getMccGroupCategoryMessage(translate, parentReportAction);
     }
diff --git a/tests/unit/ReportActionsUtilsTest.ts b/tests/unit/ReportActionsUtilsTest.ts
index 308517fe054f..c6436bc7c5bc 100644
--- a/tests/unit/ReportActionsUtilsTest.ts
+++ b/tests/unit/ReportActionsUtilsTest.ts
@@ -4519,39 +4519,44 @@ describe('ReportActionsUtils', () => {
                 },
                 message: [],
             } as ReportAction;
+
             const result = getCategoryTaxRateMessage(translateLocal, action);
             expect(result).toBe('changed the "Office Supplies" category default tax rate to "Tax Rate 1 (5%)" (previously "Tax Exempt (0%)")');
         });
 
-    describe('getMccGroupCategoryMessage', () => {
-        it('should render the friendly MCC group label that the emitter already resolved', () => {
+        it('should drop the parens on the side with an empty percentage (e.g. previous tax was deleted)', () => {
             const action = {
-                actionName: CONST.REPORT.ACTIONS.TYPE.POLICY_CHANGE_LOG.UPDATE_MCC_GROUP_CATEGORY,
+                actionName: CONST.REPORT.ACTIONS.TYPE.POLICY_CHANGE_LOG.UPDATE_CATEGORY_TAX_RATE,
                 reportActionID: '1',
                 created: '',
                 originalMessage: {
-                    mccGroupName: 'Airlines',
-                    oldCategory: 'Insurance',
-                    newCategory: 'Travel',
+                    categoryName: 'Office Supplies',
+                    oldTaxName: 'Deleted Tax Rate',
+                    oldTaxPercentage: '',
+                    newTaxName: 'Tax Rate 1',
+                    newTaxPercentage: '5%',
                 },
                 message: [],
             } as ReportAction;
 
-            const result = getMccGroupCategoryMessage(translateLocal, action);
-            expect(result).toBe('changed the default spend category for "Airlines" to "Travel" (previously "Insurance")');
+            const result = getCategoryTaxRateMessage(translateLocal, action);
+            expect(result).toBe('changed the "Office Supplies" category default tax rate to "Tax Rate 1 (5%)" (previously "Deleted Tax Rate")');
         });
+    });
 
-        it('should drop the parens on the side with an empty percentage (e.g. previous tax was deleted)', () => {
+    describe('getMccGroupCategoryMessage', () => {
+        it('should render the friendly MCC group label that the emitter already resolved', () => {
             const action = {
-                actionName: CONST.REPORT.ACTIONS.TYPE.POLICY_CHANGE_LOG.UPDATE_CATEGORY_TAX_RATE,
+                actionName: CONST.REPORT.ACTIONS.TYPE.POLICY_CHANGE_LOG.UPDATE_MCC_GROUP_CATEGORY,
                 reportActionID: '1',
                 created: '',
                 originalMessage: {
-                    categoryName: 'Office Supplies',
-                    oldTaxName: 'Deleted Tax Rate',
-                    oldTaxPercentage: '',
-                    newTaxName: 'Tax Rate 1',
-                    newTaxPercentage: '5%',
+                    mccGroupName: 'Airlines',
+                    oldCategory: 'Insurance',
+                    newCategory: 'Travel',
+                },
+                message: [],
+            } as ReportAction;
 
             const result = getMccGroupCategoryMessage(translateLocal, action);
             expect(result).toBe('changed the default spend category for "Airlines" to "Travel" (previously "Insurance")');

From 9b0e834ac27ef7632fd1d6a4f015363b092f92ca Mon Sep 17 00:00:00 2001
From: Rayane <77965000+rayane-d@users.noreply.github.com>
Date: Wed, 3 Jun 2026 12:31:49 +0100
Subject: [PATCH 109/435] prettier

---
 tests/unit/OptionsListUtilsTest.tsx | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/tests/unit/OptionsListUtilsTest.tsx b/tests/unit/OptionsListUtilsTest.tsx
index cd355ecc31f3..35f5ae357473 100644
--- a/tests/unit/OptionsListUtilsTest.tsx
+++ b/tests/unit/OptionsListUtilsTest.tsx
@@ -5350,7 +5350,7 @@ describe('OptionsListUtils', () => {
                         mccGroupName: 'Airlines',
                         oldCategory: 'Insurance',
                         newCategory: 'Travel',
-                    currentUserLogin: CURRENT_USER_EMAIL,
+                        currentUserLogin: CURRENT_USER_EMAIL,
                     },
                 };
                 await Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${report.reportID}`, {

From 2d05e4ded81105ead9c737fdb462898fe30d4f6a Mon Sep 17 00:00:00 2001
From: jayeshmangwani <jayeshmangwani@gmail.com>
Date: Wed, 3 Jun 2026 17:13:44 +0530
Subject: [PATCH 110/435] fixed lint and tests

---
 src/hooks/useSearchBulkActions.ts |   8 +-
 src/libs/NextStepUtils.ts         | 258 +++++++++++++++---------------
 2 files changed, 133 insertions(+), 133 deletions(-)

diff --git a/src/hooks/useSearchBulkActions.ts b/src/hooks/useSearchBulkActions.ts
index c8cd7ef0a8db..bbb51135a680 100644
--- a/src/hooks/useSearchBulkActions.ts
+++ b/src/hooks/useSearchBulkActions.ts
@@ -37,7 +37,7 @@ import {setNameValuePair} from '@libs/actions/User';
 import {getTransactionsAndReportsFromSearch} from '@libs/MergeTransactionUtils';
 import Navigation from '@libs/Navigation/Navigation';
 import {getLoginByAccountID} from '@libs/PersonalDetailsUtils';
-import {getConnectedIntegration, isSubmitAndClose} from '@libs/PolicyUtils';
+import {getConnectedIntegration} from '@libs/PolicyUtils';
 import {getSecondaryExportReportActions, isMergeActionForSelectedTransactions} from '@libs/ReportSecondaryActionUtils';
 import {
     canEditMultipleTransactions,
@@ -1112,7 +1112,7 @@ function useSearchBulkActions({queryJSON}: UseSearchBulkActionsParams) {
                     policy: policies?.[`${ONYXKEYS.COLLECTION.POLICY}${report.policyID}`],
                 });
             }),
-        [selectedReports, shouldShowMarkAsDone],
+        [selectedReports, currentSearchResults?.data, isTrackIntentUser, policies],
     );
     const noReportsShouldMarkAsDone = useMemo(
         () =>
@@ -1125,7 +1125,7 @@ function useSearchBulkActions({queryJSON}: UseSearchBulkActionsParams) {
                     policy: policies?.[`${ONYXKEYS.COLLECTION.POLICY}${report.policyID}`],
                 });
             }),
-        [selectedReports, shouldShowMarkAsDone],
+        [selectedReports, currentSearchResults?.data, isTrackIntentUser, policies],
     );
 
     const headerButtonsOptions = useMemo(() => {
@@ -1470,7 +1470,7 @@ function useSearchBulkActions({queryJSON}: UseSearchBulkActionsParams) {
         if (shouldShowSubmitOption) {
             options.push({
                 icon: expensifyIcons.Send,
-                text: selectedReports.length > 0 && allReportsShouldMarkAsDone ? translate('common.markAsDone') : translate('common.submit'),
+                text: allReportsShouldMarkAsDone ? translate('common.markAsDone') : translate('common.submit'),
                 value: CONST.SEARCH.BULK_ACTION_TYPES.SUBMIT,
                 shouldCloseModalOnSelect: true,
                 onSelected: () => {
diff --git a/src/libs/NextStepUtils.ts b/src/libs/NextStepUtils.ts
index 5dd4edace9c0..388e29decaee 100644
--- a/src/libs/NextStepUtils.ts
+++ b/src/libs/NextStepUtils.ts
@@ -558,13 +558,86 @@ function buildNextStepNew(params: BuildNextStepNewParams): ReportNextStepDepreca
     switch (predictedNextStatus) {
         // Generates an optimistic nextStep once a report has been opened
         case CONST.REPORT.STATUS_NUM.OPEN:
-            if (isRejectedReport) {
+            {
+                const shouldShowMarkAsDoneCopy = shouldShowMarkAsDone({isTrackIntentUser: isTrackOnboardingChoice(introSelected?.choice), report, policy});
+
+                if (isRejectedReport) {
+                    optimisticNextStep = {
+                        type,
+                        icon: CONST.NEXT_STEP.ICONS.HOURGLASS,
+                        message: [
+                            {
+                                text: 'This report was rejected. Waiting on ',
+                            },
+                            {
+                                text: `${ownerDisplayName}`,
+                                type: 'strong',
+                                clickToCopyText: ownerAccountID === currentUserAccountIDParam ? currentUserEmailParam : '',
+                            },
+                            {
+                                text: ' to fix the issues and manually resubmit.',
+                            },
+                        ],
+                    };
+                    break;
+                }
+                if ((isASAPSubmitBetaEnabled && hasViolations && isInstantSubmitEnabled) || shouldFixViolations) {
+                    optimisticNextStep = {
+                        type,
+                        icon: CONST.NEXT_STEP.ICONS.HOURGLASS,
+                        message: [
+                            {
+                                text: 'Waiting for ',
+                            },
+                            {
+                                text: `${ownerDisplayName}`,
+                                type: 'strong',
+                                clickToCopyText: ownerAccountID === currentUserAccountIDParam ? currentUserEmailParam : '',
+                            },
+                            {
+                                text: ' to ',
+                            },
+                            {
+                                text: 'fix the issues',
+                            },
+                        ],
+                    };
+                    break;
+                }
+                if (isReopen) {
+                    optimisticNextStep = {
+                        type,
+                        icon: CONST.NEXT_STEP.ICONS.HOURGLASS,
+                        message: [
+                            {
+                                text: 'Waiting for ',
+                            },
+                            {
+                                text: `${ownerDisplayName}`,
+                                type: 'strong',
+                                clickToCopyText: ownerAccountID === currentUserAccountIDParam ? currentUserEmailParam : '',
+                            },
+                            {
+                                text: ' to ',
+                            },
+                            {
+                                text: shouldShowMarkAsDoneCopy ? 'mark this as done' : 'submit',
+                            },
+                            {
+                                text: shouldShowMarkAsDoneCopy ? '.' : ' %expenses.',
+                            },
+                        ],
+                    };
+                    break;
+                }
+
+                // Self review
                 optimisticNextStep = {
                     type,
                     icon: CONST.NEXT_STEP.ICONS.HOURGLASS,
                     message: [
                         {
-                            text: 'This report was rejected. Waiting on ',
+                            text: 'Waiting for ',
                         },
                         {
                             text: `${ownerDisplayName}`,
@@ -572,17 +645,20 @@ function buildNextStepNew(params: BuildNextStepNewParams): ReportNextStepDepreca
                             clickToCopyText: ownerAccountID === currentUserAccountIDParam ? currentUserEmailParam : '',
                         },
                         {
-                            text: ' to fix the issues and manually resubmit.',
+                            text: ' to ',
+                        },
+                        {
+                            text: hasTransactions ? (shouldShowMarkAsDoneCopy ? 'mark this as done' : 'submit') : 'add',
+                        },
+                        {
+                            text: shouldShowMarkAsDoneCopy ? '.' : ' %expenses.',
                         },
                     ],
                 };
-                break;
-            }
-            if ((isASAPSubmitBetaEnabled && hasViolations && isInstantSubmitEnabled) || shouldFixViolations) {
-                optimisticNextStep = {
-                    type,
-                    icon: CONST.NEXT_STEP.ICONS.HOURGLASS,
-                    message: [
+
+                // Scheduled submit enabled
+                if (policy?.harvesting?.enabled && hasTransactions) {
+                    optimisticNextStep.message = [
                         {
                             text: 'Waiting for ',
                         },
@@ -592,21 +668,51 @@ function buildNextStepNew(params: BuildNextStepNewParams): ReportNextStepDepreca
                             clickToCopyText: ownerAccountID === currentUserAccountIDParam ? currentUserEmailParam : '',
                         },
                         {
-                            text: ' to ',
+                            text: `'s`,
+                            type: 'strong',
                         },
                         {
-                            text: 'fix the issues',
+                            text: ' %expenses to automatically submit',
                         },
-                    ],
-                };
-                break;
-            }
-            if (isReopen) {
-                const shouldShowMarkAsDoneCopy = shouldShowMarkAsDone({isTrackIntentUser: isTrackOnboardingChoice(introSelected?.choice), report, policy});
-                optimisticNextStep = {
-                    type,
-                    icon: CONST.NEXT_STEP.ICONS.HOURGLASS,
-                    message: [
+                    ];
+                    let harvestingSuffix = '';
+
+                    if (autoReportingFrequency) {
+                        const currentDate = new Date();
+                        let autoSubmissionDate = '';
+                        let monthlyText = '';
+
+                        if (policy?.autoReportingOffset === CONST.POLICY.AUTO_REPORTING_OFFSET.LAST_DAY_OF_MONTH) {
+                            monthlyText = 'on the last day of the month';
+                        } else if (policy?.autoReportingOffset === CONST.POLICY.AUTO_REPORTING_OFFSET.LAST_BUSINESS_DAY_OF_MONTH) {
+                            monthlyText = 'on the last business day of the month';
+                        } else if (policy?.autoReportingOffset !== undefined) {
+                            autoSubmissionDate = format(setDate(currentDate, policy?.autoReportingOffset), CONST.DATE.ORDINAL_DAY_OF_MONTH);
+                        }
+
+                        const harvestingSuffixes: Record<DeepValueOf<typeof CONST.POLICY.AUTO_REPORTING_FREQUENCIES>, string> = {
+                            [CONST.POLICY.AUTO_REPORTING_FREQUENCIES.IMMEDIATE]: 'later today',
+                            [CONST.POLICY.AUTO_REPORTING_FREQUENCIES.WEEKLY]: 'on Sunday',
+                            [CONST.POLICY.AUTO_REPORTING_FREQUENCIES.SEMI_MONTHLY]: 'on the 1st and 16th of each month',
+                            [CONST.POLICY.AUTO_REPORTING_FREQUENCIES.MONTHLY]: autoSubmissionDate ? `on the ${autoSubmissionDate} of each month` : monthlyText,
+                            [CONST.POLICY.AUTO_REPORTING_FREQUENCIES.TRIP]: 'at the end of their trip',
+                            [CONST.POLICY.AUTO_REPORTING_FREQUENCIES.INSTANT]: '',
+                            [CONST.POLICY.AUTO_REPORTING_FREQUENCIES.MANUAL]: '',
+                        };
+
+                        if (harvestingSuffixes[autoReportingFrequency]) {
+                            harvestingSuffix = `${harvestingSuffixes[autoReportingFrequency]}`;
+                        }
+                    }
+
+                    optimisticNextStep.message.push({
+                        text: ` ${harvestingSuffix}`,
+                    });
+                }
+
+                // Manual submission
+                if (hasTransactions && !policy?.harvesting?.enabled) {
+                    optimisticNextStep.message = [
                         {
                             text: 'Waiting for ',
                         },
@@ -624,115 +730,9 @@ function buildNextStepNew(params: BuildNextStepNewParams): ReportNextStepDepreca
                         {
                             text: shouldShowMarkAsDoneCopy ? '.' : ' %expenses.',
                         },
-                    ],
-                };
-                break;
-            }
-
-            const shouldShowMarkAsDoneCopy = shouldShowMarkAsDone({isTrackIntentUser: isTrackOnboardingChoice(introSelected?.choice), report, policy});
-            // Self review
-            optimisticNextStep = {
-                type,
-                icon: CONST.NEXT_STEP.ICONS.HOURGLASS,
-                message: [
-                    {
-                        text: 'Waiting for ',
-                    },
-                    {
-                        text: `${ownerDisplayName}`,
-                        type: 'strong',
-                        clickToCopyText: ownerAccountID === currentUserAccountIDParam ? currentUserEmailParam : '',
-                    },
-                    {
-                        text: ' to ',
-                    },
-                    {
-                        text: shouldShowMarkAsDoneCopy ? 'mark this as done' : 'submit',
-                    },
-                    {
-                        text: shouldShowMarkAsDoneCopy ? '.' : ' %expenses.',
-                    },
-                ],
-            };
-
-            // Scheduled submit enabled
-            if (policy?.harvesting?.enabled && hasTransactions) {
-                optimisticNextStep.message = [
-                    {
-                        text: 'Waiting for ',
-                    },
-                    {
-                        text: `${ownerDisplayName}`,
-                        type: 'strong',
-                        clickToCopyText: ownerAccountID === currentUserAccountIDParam ? currentUserEmailParam : '',
-                    },
-                    {
-                        text: `'s`,
-                        type: 'strong',
-                    },
-                    {
-                        text: ' %expenses to automatically submit',
-                    },
-                ];
-                let harvestingSuffix = '';
-
-                if (autoReportingFrequency) {
-                    const currentDate = new Date();
-                    let autoSubmissionDate = '';
-                    let monthlyText = '';
-
-                    if (policy?.autoReportingOffset === CONST.POLICY.AUTO_REPORTING_OFFSET.LAST_DAY_OF_MONTH) {
-                        monthlyText = 'on the last day of the month';
-                    } else if (policy?.autoReportingOffset === CONST.POLICY.AUTO_REPORTING_OFFSET.LAST_BUSINESS_DAY_OF_MONTH) {
-                        monthlyText = 'on the last business day of the month';
-                    } else if (policy?.autoReportingOffset !== undefined) {
-                        autoSubmissionDate = format(setDate(currentDate, policy?.autoReportingOffset), CONST.DATE.ORDINAL_DAY_OF_MONTH);
-                    }
-
-                    const harvestingSuffixes: Record<DeepValueOf<typeof CONST.POLICY.AUTO_REPORTING_FREQUENCIES>, string> = {
-                        [CONST.POLICY.AUTO_REPORTING_FREQUENCIES.IMMEDIATE]: 'later today',
-                        [CONST.POLICY.AUTO_REPORTING_FREQUENCIES.WEEKLY]: 'on Sunday',
-                        [CONST.POLICY.AUTO_REPORTING_FREQUENCIES.SEMI_MONTHLY]: 'on the 1st and 16th of each month',
-                        [CONST.POLICY.AUTO_REPORTING_FREQUENCIES.MONTHLY]: autoSubmissionDate ? `on the ${autoSubmissionDate} of each month` : monthlyText,
-                        [CONST.POLICY.AUTO_REPORTING_FREQUENCIES.TRIP]: 'at the end of their trip',
-                        [CONST.POLICY.AUTO_REPORTING_FREQUENCIES.INSTANT]: '',
-                        [CONST.POLICY.AUTO_REPORTING_FREQUENCIES.MANUAL]: '',
-                    };
-
-                    if (harvestingSuffixes[autoReportingFrequency]) {
-                        harvestingSuffix = `${harvestingSuffixes[autoReportingFrequency]}`;
-                    }
+                    ];
                 }
-
-                optimisticNextStep.message.push({
-                    text: ` ${harvestingSuffix}`,
-                });
             }
-
-            // Manual submission
-            if (hasTransactions && !policy?.harvesting?.enabled) {
-                const shouldShowMarkAsDoneCopy = shouldShowMarkAsDone({isTrackIntentUser: isTrackOnboardingChoice(introSelected?.choice), report, policy});
-                optimisticNextStep.message = [
-                    {
-                        text: 'Waiting for ',
-                    },
-                    {
-                        text: `${ownerDisplayName}`,
-                        type: 'strong',
-                        clickToCopyText: ownerAccountID === currentUserAccountIDParam ? currentUserEmailParam : '',
-                    },
-                    {
-                        text: ' to ',
-                    },
-                    {
-                        text: shouldShowMarkAsDoneCopy ? 'mark this as done' : 'submit',
-                    },
-                    {
-                        text: shouldShowMarkAsDoneCopy ? '.' : ' %expenses.',
-                    },
-                ];
-            }
-
             break;
 
         // Generates an optimistic nextStep once a report has been submitted

From 36df8978bf5204421bb63fd99452ac1723549a74 Mon Sep 17 00:00:00 2001
From: jayeshmangwani <jayeshmangwani@gmail.com>
Date: Wed, 3 Jun 2026 17:38:39 +0530
Subject: [PATCH 111/435] fixed lint

---
 src/libs/NextStepUtils.ts | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/src/libs/NextStepUtils.ts b/src/libs/NextStepUtils.ts
index 388e29decaee..05bce90666c4 100644
--- a/src/libs/NextStepUtils.ts
+++ b/src/libs/NextStepUtils.ts
@@ -632,6 +632,10 @@ function buildNextStepNew(params: BuildNextStepNewParams): ReportNextStepDepreca
                 }
 
                 // Self review
+                let actionText = 'add';
+                if (hasTransactions) {
+                    actionText = shouldShowMarkAsDoneCopy ? 'mark this as done' : 'submit';
+                }
                 optimisticNextStep = {
                     type,
                     icon: CONST.NEXT_STEP.ICONS.HOURGLASS,
@@ -648,7 +652,7 @@ function buildNextStepNew(params: BuildNextStepNewParams): ReportNextStepDepreca
                             text: ' to ',
                         },
                         {
-                            text: hasTransactions ? (shouldShowMarkAsDoneCopy ? 'mark this as done' : 'submit') : 'add',
+                            text: actionText,
                         },
                         {
                             text: shouldShowMarkAsDoneCopy ? '.' : ' %expenses.',

From 01de44529e327636c07a7dbac250746e615d79a5 Mon Sep 17 00:00:00 2001
From: krishna2323 <belivethatkg@gmail.com>
Date: Wed, 3 Jun 2026 18:44:00 +0530
Subject: [PATCH 112/435] Fix jelly scrolling by only applying sticky headers
 to expanded groups

Signed-off-by: krishna2323 <belivethatkg@gmail.com>
---
 src/components/Search/SearchList/index.tsx | 10 ++++++++--
 1 file changed, 8 insertions(+), 2 deletions(-)

diff --git a/src/components/Search/SearchList/index.tsx b/src/components/Search/SearchList/index.tsx
index 5b76abec3b9f..54b192f085a0 100644
--- a/src/components/Search/SearchList/index.tsx
+++ b/src/components/Search/SearchList/index.tsx
@@ -320,8 +320,14 @@ function SearchList({
         if (!shouldSplitGroups) {
             return {splitData: data, stickyHeaderIndices: undefined};
         }
-        return splitGroupsIntoPairs(data);
-    }, [data, shouldSplitGroups]);
+        const {splitData, stickyHeaderIndices: allIndices} = splitGroupsIntoPairs(data);
+        const activeIndices = allIndices.filter((idx) => {
+            const item = splitData.at(idx);
+            const originalKey = item?.keyForList?.replace('header_', '') ?? '';
+            return expandedGroups.has(originalKey);
+        });
+        return {splitData, stickyHeaderIndices: activeIndices.length > 0 ? activeIndices : undefined};
+    }, [data, shouldSplitGroups, expandedGroups]);
 
     const getItemType = useMemo(() => {
         if (!shouldSplitGroups) {

From bfca90f4beb1ba6cf608eb47ab361916311cab85 Mon Sep 17 00:00:00 2001
From: Youssef Lourayad <youssef@expensify.com>
Date: Wed, 3 Jun 2026 23:19:24 +0000
Subject: [PATCH 113/435] Address comments and fix bug

---
 src/hooks/useSidebarOrderedReports.tsx       | 63 ++++++++++++++++----
 src/pages/inbox/sidebar/SidebarLinks.tsx     |  6 +-
 src/pages/inbox/sidebar/SidebarLinksData.tsx |  4 +-
 3 files changed, 59 insertions(+), 14 deletions(-)

diff --git a/src/hooks/useSidebarOrderedReports.tsx b/src/hooks/useSidebarOrderedReports.tsx
index a49ac761f681..d0361fc74c60 100644
--- a/src/hooks/useSidebarOrderedReports.tsx
+++ b/src/hooks/useSidebarOrderedReports.tsx
@@ -29,7 +29,9 @@ type SidebarOrderedReportsContextProviderProps = {
 };
 
 type SidebarOrderedReportsStateContextValue = {
-    orderedReports: OnyxTypes.Report[];
+    /** The reports rendered in the LHN for the active Inbox tab (a filtered subset of orderedReportIDs). */
+    filteredReports: OnyxTypes.Report[];
+    /** All ordered LHN report IDs, unfiltered by the active Inbox tab. Used for total counts (e.g. focus-mode switch) and brick road. */
     orderedReportIDs: string[];
     currentReportID: string | undefined;
     chatTabBrickRoad: BrickRoad;
@@ -40,12 +42,13 @@ type SidebarOrderedReportsStateContextValue = {
 type SidebarOrderedReportsActionsContextValue = {
     clearLHNCache: () => void;
     setActiveTab: (tab: ValueOf<typeof CONST.INBOX_TAB>) => void;
+    setStickyReportID: (reportID: string) => void;
 };
 
 type ReportsToDisplayInLHN = Record<string, OnyxTypes.Report & {hasErrorsOtherThanFailedReceipt?: boolean; requiresAttention?: boolean; isUnreadReport?: boolean}>;
 
 const SidebarOrderedReportsStateContext = createContext<SidebarOrderedReportsStateContextValue>({
-    orderedReports: [],
+    filteredReports: [],
     orderedReportIDs: [],
     currentReportID: '',
     chatTabBrickRoad: undefined,
@@ -59,6 +62,7 @@ const SidebarOrderedReportsStateContext = createContext<SidebarOrderedReportsSta
 const SidebarOrderedReportsActionsContext = createContext<SidebarOrderedReportsActionsContextValue>({
     clearLHNCache: () => {},
     setActiveTab: () => {},
+    setStickyReportID: () => {},
 });
 
 const policyMapper = (policy: OnyxEntry<OnyxTypes.Policy>): PartialPolicyForSidebar =>
@@ -291,9 +295,31 @@ function SidebarOrderedReportsContextProvider({
 
     const orderedReportIDs = useMemo(() => getOrderedReportIDs(), [getOrderedReportIDs]);
 
-    // Narrow the ordered reports down to the ones belonging to the active Inbox tab. The "All" tab
+    // When a report is opened from the To-do/Unread tab (see setStickyReportID), we remember it so it
+    // stays visible after viewing it removes it from the tab (e.g. it gets read). It's only set on a
+    // non-All tab, so opening a chat from the All tab never makes it appear under Unread/To-do.
+    const [stickyReport, setStickyReport] = useState<{reportID: string; tab: ValueOf<typeof CONST.INBOX_TAB>} | undefined>(undefined);
+
+    // Narrow the ordered reports down to the ones belonging to the active Inbox tab, plus the sticky
+    // report (kept visible while it's the one being viewed on the tab it was opened from). The "All" tab
     // returns everything (still honoring Most Recent / Focus mode from the ordering above).
-    const filteredReportIDs = useMemo(() => SidebarUtils.filterReportsForInboxTab(orderedReportIDs, reportsToDisplayInLHN, activeTab), [orderedReportIDs, reportsToDisplayInLHN, activeTab]);
+    const stickyReportID = stickyReport?.reportID;
+    const stickyReportTab = stickyReport?.tab;
+    const filteredReportIDs = useMemo(() => {
+        const base = SidebarUtils.filterReportsForInboxTab(orderedReportIDs, reportsToDisplayInLHN, activeTab);
+        if (
+            activeTab === CONST.INBOX_TAB.ALL ||
+            !stickyReportID ||
+            stickyReportTab !== activeTab ||
+            stickyReportID !== derivedCurrentReportID ||
+            base.includes(stickyReportID) ||
+            !orderedReportIDs.includes(stickyReportID)
+        ) {
+            return base;
+        }
+        const baseSet = new Set(base);
+        return orderedReportIDs.filter((reportID) => baseSet.has(reportID) || reportID === stickyReportID);
+    }, [orderedReportIDs, reportsToDisplayInLHN, activeTab, stickyReportTab, stickyReportID, derivedCurrentReportID]);
 
     // The count shown in each tab's badge, derived from the full "All" set (not the currently filtered view).
     const inboxTabCounts = useMemo(() => SidebarUtils.getInboxTabCounts(orderedReportIDs, reportsToDisplayInLHN), [orderedReportIDs, reportsToDisplayInLHN]);
@@ -309,7 +335,7 @@ function SidebarOrderedReportsContextProvider({
         [chatReports],
     );
 
-    const orderedReports = useMemo(() => getOrderedReports(filteredReportIDs), [getOrderedReports, filteredReportIDs]);
+    const filteredReports = useMemo(() => getOrderedReports(filteredReportIDs), [getOrderedReports, filteredReportIDs]);
 
     const clearLHNCache = useCallback(() => {
         Log.info('[useSidebarOrderedReports] Clearing sidebar cache manually via debug modal');
@@ -319,8 +345,23 @@ function SidebarOrderedReportsContextProvider({
 
     const setActiveTab = useCallback((tab: ValueOf<typeof CONST.INBOX_TAB>) => {
         setInboxTab(tab);
+
+        // The sticky report is scoped to the tab it was opened from, so reset it when switching tabs.
+        setStickyReport(undefined);
     }, []);
 
+    // Called when a report is opened from the LHN. On the To-do/Unread tabs we remember it so it stays
+    // visible after viewing it removes it from the tab. On the All tab we keep nothing sticky.
+    const setStickyReportID = useCallback(
+        (reportID: string) => {
+            if (activeTab === CONST.INBOX_TAB.ALL) {
+                return;
+            }
+            setStickyReport({reportID, tab: activeTab});
+        },
+        [activeTab],
+    );
+
     const stateValue: SidebarOrderedReportsStateContextValue = useMemo(() => {
         // We need to make sure the current report is in the list of reports, but we do not want
         // to have to re-generate the list every time the currentReportID changes. To do that
@@ -342,8 +383,8 @@ function SidebarOrderedReportsContextProvider({
             const updatedFilteredIDs = SidebarUtils.filterReportsForInboxTab(updatedReportIDs, reportsToDisplayInLHN, activeTab);
             const updatedReports = getOrderedReports(updatedFilteredIDs);
             return {
-                orderedReports: updatedReports,
-                orderedReportIDs: updatedFilteredIDs,
+                filteredReports: updatedReports,
+                orderedReportIDs: updatedReportIDs,
                 currentReportID: derivedCurrentReportID,
                 chatTabBrickRoad: getChatTabBrickRoad(updatedReportIDs, reportAttributes),
                 activeTab,
@@ -352,8 +393,8 @@ function SidebarOrderedReportsContextProvider({
         }
 
         return {
-            orderedReports,
-            orderedReportIDs: filteredReportIDs,
+            filteredReports,
+            orderedReportIDs,
             currentReportID: derivedCurrentReportID,
             chatTabBrickRoad: getChatTabBrickRoad(orderedReportIDs, reportAttributes),
             activeTab,
@@ -366,14 +407,14 @@ function SidebarOrderedReportsContextProvider({
         derivedCurrentReportID,
         shouldUseNarrowLayout,
         getOrderedReports,
-        orderedReports,
+        filteredReports,
         reportAttributes,
         activeTab,
         inboxTabCounts,
         reportsToDisplayInLHN,
     ]);
 
-    const actionsValue: SidebarOrderedReportsActionsContextValue = useMemo(() => ({clearLHNCache, setActiveTab}), [clearLHNCache, setActiveTab]);
+    const actionsValue: SidebarOrderedReportsActionsContextValue = useMemo(() => ({clearLHNCache, setActiveTab, setStickyReportID}), [clearLHNCache, setActiveTab, setStickyReportID]);
 
     useEffect(() => {
         const hookExecutionDuration = performance.now() - hookStartTime.current;
diff --git a/src/pages/inbox/sidebar/SidebarLinks.tsx b/src/pages/inbox/sidebar/SidebarLinks.tsx
index a367a114ca02..46e379148e9d 100644
--- a/src/pages/inbox/sidebar/SidebarLinks.tsx
+++ b/src/pages/inbox/sidebar/SidebarLinks.tsx
@@ -8,6 +8,7 @@ import LHNOptionsList from '@components/LHNOptionsList/LHNOptionsList';
 import OptionsListSkeletonView from '@components/OptionsListSkeletonView';
 import useOnyx from '@hooks/useOnyx';
 import useResponsiveLayout from '@hooks/useResponsiveLayout';
+import {useSidebarOrderedReportsActions} from '@hooks/useSidebarOrderedReports';
 import useStyleUtils from '@hooks/useStyleUtils';
 import useThemeStyles from '@hooks/useThemeStyles';
 import {setSidebarLoaded} from '@libs/actions/App';
@@ -39,6 +40,7 @@ function SidebarLinks({insets, optionListItems, priorityMode = CONST.PRIORITY_MO
     const styles = useThemeStyles();
     const StyleUtils = useStyleUtils();
     const {shouldUseNarrowLayout} = useResponsiveLayout();
+    const {setStickyReportID} = useSidebarOrderedReportsActions();
     const [isLoadingReportData = true] = useOnyx(ONYXKEYS.IS_LOADING_REPORT_DATA);
 
     useEffect(() => {
@@ -69,9 +71,11 @@ function SidebarLinks({insets, optionListItems, priorityMode = CONST.PRIORITY_MO
                 cancelSpan(`${CONST.TELEMETRY.SPAN_OPEN_REPORT}_${option.reportID}`);
                 return;
             }
+            // Keep this report visible in the active To-do/Unread tab even after opening it marks it read.
+            setStickyReportID(option.reportID);
             Navigation.navigate(ROUTES.REPORT_WITH_ID.getRoute(option.reportID, actionTargetReportActionID));
         },
-        [shouldUseNarrowLayout, isActiveReport],
+        [shouldUseNarrowLayout, isActiveReport, setStickyReportID],
     );
 
     const viewMode = priorityMode === CONST.PRIORITY_MODE.GSD ? CONST.OPTION_MODE.COMPACT : CONST.OPTION_MODE.DEFAULT;
diff --git a/src/pages/inbox/sidebar/SidebarLinksData.tsx b/src/pages/inbox/sidebar/SidebarLinksData.tsx
index 1c4879c15884..f6cac99bfaae 100644
--- a/src/pages/inbox/sidebar/SidebarLinksData.tsx
+++ b/src/pages/inbox/sidebar/SidebarLinksData.tsx
@@ -23,7 +23,7 @@ function SidebarLinksData({insets}: SidebarLinksDataProps) {
     const {translate} = useLocalize();
     const [priorityMode = CONST.PRIORITY_MODE.DEFAULT] = useOnyx(ONYXKEYS.NVP_PRIORITY_MODE);
 
-    const {orderedReports, currentReportID} = useSidebarOrderedReportsState('SidebarLinksData');
+    const {filteredReports, currentReportID} = useSidebarOrderedReportsState('SidebarLinksData');
 
     const currentReportIDRef = useRef(currentReportID);
     currentReportIDRef.current = currentReportID;
@@ -80,7 +80,7 @@ function SidebarLinksData({insets}: SidebarLinksDataProps) {
                 priorityMode={priorityMode ?? CONST.PRIORITY_MODE.DEFAULT}
                 // Data props:
                 isActiveReport={isActiveReport}
-                optionListItems={orderedReports}
+                optionListItems={filteredReports}
             />
         </View>
     );

From be8fdad3131cd155023298a1277e2f75f0007b83 Mon Sep 17 00:00:00 2001
From: Youssef Lourayad <youssef@expensify.com>
Date: Thu, 4 Jun 2026 00:02:35 +0000
Subject: [PATCH 114/435] Fix empty view flashing briefly when opening the only
 unread/todo report

---
 src/hooks/useSidebarOrderedReports.tsx | 30 +++++++++++++-------------
 1 file changed, 15 insertions(+), 15 deletions(-)

diff --git a/src/hooks/useSidebarOrderedReports.tsx b/src/hooks/useSidebarOrderedReports.tsx
index d0361fc74c60..c15e52fe29ae 100644
--- a/src/hooks/useSidebarOrderedReports.tsx
+++ b/src/hooks/useSidebarOrderedReports.tsx
@@ -300,26 +300,22 @@ function SidebarOrderedReportsContextProvider({
     // non-All tab, so opening a chat from the All tab never makes it appear under Unread/To-do.
     const [stickyReport, setStickyReport] = useState<{reportID: string; tab: ValueOf<typeof CONST.INBOX_TAB>} | undefined>(undefined);
 
-    // Narrow the ordered reports down to the ones belonging to the active Inbox tab, plus the sticky
-    // report (kept visible while it's the one being viewed on the tab it was opened from). The "All" tab
-    // returns everything (still honoring Most Recent / Focus mode from the ordering above).
+    // The reports for the active tab, plus the sticky report opened from it (kept visible even after it's read).
     const stickyReportID = stickyReport?.reportID;
     const stickyReportTab = stickyReport?.tab;
     const filteredReportIDs = useMemo(() => {
-        const base = SidebarUtils.filterReportsForInboxTab(orderedReportIDs, reportsToDisplayInLHN, activeTab);
-        if (
-            activeTab === CONST.INBOX_TAB.ALL ||
-            !stickyReportID ||
-            stickyReportTab !== activeTab ||
-            stickyReportID !== derivedCurrentReportID ||
-            base.includes(stickyReportID) ||
-            !orderedReportIDs.includes(stickyReportID)
-        ) {
-            return base;
+        const baseFilteredReportIDs = SidebarUtils.filterReportsForInboxTab(orderedReportIDs, reportsToDisplayInLHN, activeTab);
+        if (activeTab === CONST.INBOX_TAB.ALL || !stickyReportID || stickyReportTab !== activeTab || baseFilteredReportIDs.includes(stickyReportID)) {
+            return baseFilteredReportIDs;
+        }
+        if (!orderedReportIDs.includes(stickyReportID)) {
+            // While opening the report, reading it can briefly drop it from the LHN set entirely (before
+            // navigation marks it as the focused report). Keep it at the top so the list doesn't flash empty.
+            return [stickyReportID, ...baseFilteredReportIDs];
         }
-        const baseSet = new Set(base);
+        const baseSet = new Set(baseFilteredReportIDs);
         return orderedReportIDs.filter((reportID) => baseSet.has(reportID) || reportID === stickyReportID);
-    }, [orderedReportIDs, reportsToDisplayInLHN, activeTab, stickyReportTab, stickyReportID, derivedCurrentReportID]);
+    }, [orderedReportIDs, reportsToDisplayInLHN, activeTab, stickyReportTab, stickyReportID]);
 
     // The count shown in each tab's badge, derived from the full "All" set (not the currently filtered view).
     const inboxTabCounts = useMemo(() => SidebarUtils.getInboxTabCounts(orderedReportIDs, reportsToDisplayInLHN), [orderedReportIDs, reportsToDisplayInLHN]);
@@ -373,7 +369,11 @@ function SidebarOrderedReportsContextProvider({
         // requirement for web. Consider a case, where we have report with expenses and we click on
         // any expense, a new LHN item is added in the list and is visible on web. But on mobile, we
         // just navigate to the screen with expense details, so there seems no point to execute this logic on mobile.
+        // Only the "All" tab force-regenerates to surface the current report. On the To-do/Unread tabs the
+        // sticky-aware filteredReportIDs already keeps the opened report visible, and re-filtering here
+        // (without the sticky report) would briefly empty the list while opening it.
         if (
+            activeTab === CONST.INBOX_TAB.ALL &&
             (!shouldUseNarrowLayout || filteredReportIDs.length === 0) &&
             derivedCurrentReportID &&
             derivedCurrentReportID !== '-1' &&

From 40e0df07ad41c0a0220b8b5db15691e3fb8f1de1 Mon Sep 17 00:00:00 2001
From: Bernhard Owen Josephus <bernhard.josephus@gmail.com>
Date: Thu, 4 Jun 2026 11:51:58 +0800
Subject: [PATCH 115/435] import it correctly

---
 tests/actions/IOU/RequestMoneyTest.ts | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/tests/actions/IOU/RequestMoneyTest.ts b/tests/actions/IOU/RequestMoneyTest.ts
index 6041c90d8dbf..ce19c65f88df 100644
--- a/tests/actions/IOU/RequestMoneyTest.ts
+++ b/tests/actions/IOU/RequestMoneyTest.ts
@@ -6,7 +6,8 @@ import type {SearchQueryJSON, SearchStatus} from '@components/Search/types';
 import {clearAllRelatedReportActionErrors} from '@libs/actions/ClearReportActionErrors';
 import {requestMoney, trackExpense} from '@libs/actions/IOU/TrackExpense';
 import initOnyxDerivedValues from '@libs/actions/OnyxDerived';
-import {deleteReport, notifyNewAction} from '@libs/actions/Report';
+import {notifyNewAction} from '@libs/actions/Report';
+import deleteReport from '@libs/actions/Report/DeleteReport';
 import {subscribeToUserEvents} from '@libs/actions/User';
 import type {ApiCommand} from '@libs/API/types';
 import {WRITE_COMMANDS} from '@libs/API/types';

From 3191137154a2426ecac4e4582e201f0718542e36 Mon Sep 17 00:00:00 2001
From: "daledah (via MelvinBot)" <infra+melvinbot@expensify.com>
Date: Thu, 4 Jun 2026 07:55:17 +0000
Subject: [PATCH 116/435] Fix: show "Personal card" for personal cards in
 group-by-card feed name

Personal card groups on the Spend page rendered as "Deleted feed" because
getCardSections resolved every group's feed via getFeedNameForDisplay, a
company-feed helper. Detection requires the card's fundID, so the grouped
section builders now receive the unfiltered PERSONAL_AND_WORKSPACE_CARD_LIST
and label personal cards via isPersonalCard.

Co-authored-by: daledah <daledah@users.noreply.github.com>
---
 src/components/Search/index.tsx        |  5 +-
 src/hooks/useSearchSections.ts         |  4 +-
 src/libs/SearchUIUtils.ts              | 30 ++++++-----
 tests/unit/Search/SearchUIUtilsTest.ts | 69 ++++++++++++++++++++++++++
 4 files changed, 91 insertions(+), 17 deletions(-)

diff --git a/src/components/Search/index.tsx b/src/components/Search/index.tsx
index 483a43c9177d..f4d0a071d3cf 100644
--- a/src/components/Search/index.tsx
+++ b/src/components/Search/index.tsx
@@ -310,6 +310,7 @@ function Search({
     const [visibleColumns] = useOnyx(ONYXKEYS.FORMS.SEARCH_ADVANCED_FILTERS_FORM, {selector: columnsSelector});
     const [customCardNames] = useOnyx(ONYXKEYS.NVP_EXPENSIFY_COMPANY_CARDS_CUSTOM_NAMES);
     const [nonPersonalAndWorkspaceCards] = useOnyx(ONYXKEYS.DERIVED.NON_PERSONAL_AND_WORKSPACE_CARD_LIST);
+    const [personalAndWorkspaceCards] = useOnyx(ONYXKEYS.DERIVED.PERSONAL_AND_WORKSPACE_CARD_LIST);
     const [conciergeReportID] = useOnyx(ONYXKEYS.CONCIERGE_REPORT_ID);
 
     const {
@@ -563,7 +564,7 @@ function Search({
             queryJSON,
             isActionLoadingSet,
             cardFeeds,
-            cardList: nonPersonalAndWorkspaceCards,
+            cardList: personalAndWorkspaceCards,
             isOffline,
             allTransactionViolations: violations,
             customCardNames,
@@ -599,7 +600,7 @@ function Search({
         email,
         isActionLoadingSet,
         cardFeeds,
-        nonPersonalAndWorkspaceCards,
+        personalAndWorkspaceCards,
         policies,
         bankAccountList,
         violations,
diff --git a/src/hooks/useSearchSections.ts b/src/hooks/useSearchSections.ts
index 005350c36ebe..9c9dab2ccf8e 100644
--- a/src/hooks/useSearchSections.ts
+++ b/src/hooks/useSearchSections.ts
@@ -31,7 +31,7 @@ function useSearchSections(): UseSearchSectionsResult {
     });
 
     const [cardFeeds] = useOnyx(ONYXKEYS.COLLECTION.SHARED_NVP_PRIVATE_DOMAIN_MEMBER);
-    const [nonPersonalAndWorkspaceCards] = useOnyx(ONYXKEYS.DERIVED.NON_PERSONAL_AND_WORKSPACE_CARD_LIST);
+    const [personalAndWorkspaceCards] = useOnyx(ONYXKEYS.DERIVED.PERSONAL_AND_WORKSPACE_CARD_LIST);
     const [bankAccountList] = useOnyx(ONYXKEYS.BANK_ACCOUNT_LIST);
     const [allReportMetadata] = useOnyx(ONYXKEYS.COLLECTION.REPORT_METADATA);
 
@@ -62,7 +62,7 @@ function useSearchSections(): UseSearchSectionsResult {
             archivedReportsIDList: archivedReportsIdSet,
             isActionLoadingSet,
             cardFeeds,
-            cardList: nonPersonalAndWorkspaceCards,
+            cardList: personalAndWorkspaceCards,
             allReportMetadata,
             conciergeReportID,
             reportAttributesDerivedValue,
diff --git a/src/libs/SearchUIUtils.ts b/src/libs/SearchUIUtils.ts
index 23f4632a5a04..af27a1566363 100644
--- a/src/libs/SearchUIUtils.ts
+++ b/src/libs/SearchUIUtils.ts
@@ -100,7 +100,7 @@ import {setOptimisticDataForTransactionThreadPreview} from './actions/Search';
 import {convertAttendeesToArray} from './AttendeeUtils';
 import type {CardFeedForDisplay} from './CardFeedUtils';
 import {getCardFeedsForDisplay} from './CardFeedUtils';
-import {getCardDescriptionForSearchTable, getFeedNameForDisplay} from './CardUtils';
+import {getCardDescriptionForSearchTable, getFeedNameForDisplay, isPersonalCard} from './CardUtils';
 import {getDecodedCategoryName} from './CategoryUtils';
 import DateUtils from './DateUtils';
 import interceptAnonymousUser from './interceptAnonymousUser';
@@ -3180,6 +3180,7 @@ function getCardSections(
                 formattedCardName = formattedCardNameWithDotAndLastFour(formattedCardName, cardGroup.lastFourPAN);
             }
 
+            const card = cardList?.[cardGroup.cardID];
             cardSections[key] = {
                 groupedBy: CONST.SEARCH.GROUP_BY.CARD,
                 transactions: [],
@@ -3187,18 +3188,21 @@ function getCardSections(
                 ...personalDetails,
                 ...cardGroup,
                 formattedCardName,
-                formattedFeedName: getFeedNameForDisplay(
-                    translate,
-                    cardGroup.bank as OnyxTypes.CompanyCardFeed,
-                    cardFeeds,
-                    cardList?.[cardGroup.cardID]?.fundID
-                        ? cardFeeds?.[`${ONYXKEYS.COLLECTION.SHARED_NVP_PRIVATE_DOMAIN_MEMBER}${cardList[cardGroup.cardID].fundID}`]?.settings?.companyCardNicknames?.[
-                              cardGroup.bank as OnyxTypes.CompanyCardFeed
-                          ]
-                        : undefined,
-                    true,
-                    cardGroup?.feedCountry,
-                ),
+                formattedFeedName:
+                    card && isPersonalCard(card)
+                        ? translate('cardTransactions.personalCard')
+                        : getFeedNameForDisplay(
+                              translate,
+                              cardGroup.bank as OnyxTypes.CompanyCardFeed,
+                              cardFeeds,
+                              card?.fundID
+                                  ? cardFeeds?.[`${ONYXKEYS.COLLECTION.SHARED_NVP_PRIVATE_DOMAIN_MEMBER}${card.fundID}`]?.settings?.companyCardNicknames?.[
+                                        cardGroup.bank as OnyxTypes.CompanyCardFeed
+                                    ]
+                                  : undefined,
+                              true,
+                              cardGroup?.feedCountry,
+                          ),
                 keyForList: key,
             };
         }
diff --git a/tests/unit/Search/SearchUIUtilsTest.ts b/tests/unit/Search/SearchUIUtilsTest.ts
index aef1cd3863a9..48070daf6e90 100644
--- a/tests/unit/Search/SearchUIUtilsTest.ts
+++ b/tests/unit/Search/SearchUIUtilsTest.ts
@@ -3065,6 +3065,75 @@ describe('SearchUIUtils', () => {
             ).toStrictEqual(transactionCardGroupListItems);
         });
 
+        it('should label personal card groups as "Personal card" while keeping "Deleted feed" for removed company feeds', () => {
+            const personalCardID = 40404040;
+            const csvPersonalCardID = 50505050;
+            const deletedFeedCardID = 60606060;
+
+            const data: OnyxTypes.SearchResults['data'] = {
+                personalDetailsList: {},
+                [`${CONST.SEARCH.GROUP_PREFIX}${personalCardID}` as const]: {
+                    accountID: adminAccountID,
+                    bank: CONST.PERSONAL_CARDS.BANK_NAME.CHASE,
+                    cardID: personalCardID,
+                    cardName: 'Personal Chase',
+                    count: 1,
+                    currency: 'USD',
+                    lastFourPAN: '1111',
+                    total: 10,
+                },
+                [`${CONST.SEARCH.GROUP_PREFIX}${csvPersonalCardID}` as const]: {
+                    accountID: adminAccountID,
+                    bank: CONST.PERSONAL_CARDS.BANK_NAME.CSV,
+                    cardID: csvPersonalCardID,
+                    cardName: 'CSV import',
+                    count: 1,
+                    currency: 'USD',
+                    lastFourPAN: '2222',
+                    total: 20,
+                },
+                [`${CONST.SEARCH.GROUP_PREFIX}${deletedFeedCardID}` as const]: {
+                    accountID: adminAccountID,
+                    bank: CONST.BANK_NAMES.CITIBANK,
+                    cardID: deletedFeedCardID,
+                    cardName: 'Removed company card',
+                    count: 1,
+                    currency: 'USD',
+                    lastFourPAN: '3333',
+                    total: 30,
+                },
+            };
+
+            // Personal cards have no fundID; the deleted company feed card keeps its fundID so it is not personal.
+            const cardList = {
+                [personalCardID]: {cardID: personalCardID, bank: CONST.PERSONAL_CARDS.BANK_NAME.CHASE},
+                [csvPersonalCardID]: {cardID: csvPersonalCardID, bank: CONST.PERSONAL_CARDS.BANK_NAME.CSV, fundID: '123'},
+                [deletedFeedCardID]: {cardID: deletedFeedCardID, bank: CONST.BANK_NAMES.CITIBANK, fundID: '456'},
+            } as unknown as OnyxTypes.CardList;
+
+            const [sections] = SearchUIUtils.getSections({
+                type: CONST.SEARCH.DATA_TYPES.EXPENSE,
+                data,
+                currentAccountID: adminAccountID,
+                currentUserEmail: '',
+                translate: translateLocal,
+                formatPhoneNumber,
+                bankAccountList: {},
+                groupBy: CONST.SEARCH.GROUP_BY.CARD,
+                cardFeeds: {},
+                cardList,
+                allReportMetadata: {},
+                conciergeReportID: undefined,
+                convertToDisplayString,
+            }) as [TransactionCardGroupListItemType[], number, boolean];
+
+            const feedNameByCardID = new Map(sections.map((section) => [section.cardID, section.formattedFeedName]));
+
+            expect(feedNameByCardID.get(personalCardID)).toBe('Personal card');
+            expect(feedNameByCardID.get(csvPersonalCardID)).toBe('Personal card');
+            expect(feedNameByCardID.get(deletedFeedCardID)).toBe('Deleted feed');
+        });
+
         it('should return getWithdrawalIDSections result when type is EXPENSE and groupBy is withdrawal-id', () => {
             expect(
                 SearchUIUtils.getSections({

From 75d0314f97af307362234d4229c5b5445a7b3386 Mon Sep 17 00:00:00 2001
From: Jack Senyitko <jsenyitko@expensify.com>
Date: Thu, 4 Jun 2026 09:29:23 -0400
Subject: [PATCH 117/435] remove prod gate

---
 .../SpendRules/SpendRulesSection.tsx          | 24 ++++++++-----------
 .../Wallet/ExpensifyCardPage/index.tsx        |  5 ++--
 2 files changed, 12 insertions(+), 17 deletions(-)

diff --git a/src/components/SpendRules/SpendRulesSection.tsx b/src/components/SpendRules/SpendRulesSection.tsx
index 9a2ac9ac433f..2d4eecb4231a 100644
--- a/src/components/SpendRules/SpendRulesSection.tsx
+++ b/src/components/SpendRules/SpendRulesSection.tsx
@@ -11,7 +11,6 @@ import Section from '@components/Section';
 import Text from '@components/Text';
 import useConfirmModal from '@hooks/useConfirmModal';
 import useDefaultFundID from '@hooks/useDefaultFundID';
-import useEnvironment from '@hooks/useEnvironment';
 import useExpensifyCardRules from '@hooks/useExpensifyCardRulesList';
 import {useMemoizedLazyExpensifyIcons, useMemoizedLazyIllustrations} from '@hooks/useLazyAsset';
 import useLocalize from '@hooks/useLocalize';
@@ -43,7 +42,6 @@ function SpendRulesSection({policyID}: SpendRulesSectionProps) {
     const expensifyIcons = useMemoizedLazyExpensifyIcons(['Lock', 'Plus']);
     const {showConfirmModal} = useConfirmModal();
     const illustrations = useMemoizedLazyIllustrations(['ExpensifyCardProtectionIllustration']);
-    const {isProduction} = useEnvironment();
     const {isOffline} = useNetwork();
     const defaultFundID = useDefaultFundID(policyID);
     const [expensifyCardSettings] = useOnyx(`${ONYXKEYS.COLLECTION.PRIVATE_EXPENSIFY_CARD_SETTINGS}${defaultFundID}`);
@@ -218,18 +216,16 @@ function SpendRulesSection({policyID}: SpendRulesSectionProps) {
                     </OfflineWithFeedback>
                 ))
             )}
-            {!isProduction && (
-                <MenuItem
-                    title={translate('workspace.rules.spendRules.addSpendRule')}
-                    titleStyle={styles.textStrong}
-                    icon={expensifyIcons.Plus}
-                    iconHeight={20}
-                    iconWidth={20}
-                    style={[styles.sectionMenuItemTopDescription, styles.mt6, styles.mbn3]}
-                    onPress={() => Navigation.navigate(ROUTES.RULES_SPEND_NEW.getRoute(policyID))}
-                    sentryLabel={CONST.SENTRY_LABEL.WORKSPACE.RULES.ADD_SPEND_RULE}
-                />
-            )}
+            <MenuItem
+                title={translate('workspace.rules.spendRules.addSpendRule')}
+                titleStyle={styles.textStrong}
+                icon={expensifyIcons.Plus}
+                iconHeight={20}
+                iconWidth={20}
+                style={[styles.sectionMenuItemTopDescription, styles.mt6, styles.mbn3]}
+                onPress={() => Navigation.navigate(ROUTES.RULES_SPEND_NEW.getRoute(policyID))}
+                sentryLabel={CONST.SENTRY_LABEL.WORKSPACE.RULES.ADD_SPEND_RULE}
+            />
         </Section>
     );
 }
diff --git a/src/pages/settings/Wallet/ExpensifyCardPage/index.tsx b/src/pages/settings/Wallet/ExpensifyCardPage/index.tsx
index 7935ea811a28..22185e9e015f 100644
--- a/src/pages/settings/Wallet/ExpensifyCardPage/index.tsx
+++ b/src/pages/settings/Wallet/ExpensifyCardPage/index.tsx
@@ -90,7 +90,6 @@ function getLimitTypeTranslationKeys(limitType: ValueOf<typeof CONST.EXPENSIFY_C
 }
 
 function ExpensifyCardPage({route}: ExpensifyCardPageProps) {
-    const {isProduction} = useEnvironment();
     const {cardID} = route.params;
     const {convertToDisplayString} = useCurrencyListActions();
     const [account] = useOnyx(ONYXKEYS.ACCOUNT);
@@ -211,8 +210,8 @@ function ExpensifyCardPage({route}: ExpensifyCardPageProps) {
     );
     const shouldShowReportVirtualCardFraudRows = !isSignedInAsDelegate && virtualCards.length > 0;
     const shouldShowReportTravelCardFraudRows = !isSignedInAsDelegate && isTravelCard(cardList?.[cardID]) && travelCards.length > 0;
-    const shouldShowSpendRulesSummary = !isProduction && isWorkspaceAdmin && spendRulesSummary.length > 0;
-    const shouldShowEditSpendRules = !isProduction && isWorkspaceAdmin;
+    const shouldShowEditSpendRules = isWorkspaceAdmin;
+    const shouldShowSpendRulesSummary = isWorkspaceAdmin && spendRulesSummary.length > 0;
     const shouldShowActionRows =
         shouldShowReportVirtualCardFraudRows || shouldShowReportTravelCardFraudRows || shouldShowReportLostCardButton || shouldShowSpendRulesSummary || shouldShowEditSpendRules;
     const shouldShowPhysicalCardFooterButton =

From 87734ef921800a38678f0449f546a98f933e1c6c Mon Sep 17 00:00:00 2001
From: Jack Senyitko <jsenyitko@expensify.com>
Date: Thu, 4 Jun 2026 09:31:00 -0400
Subject: [PATCH 118/435] remove other locks

---
 .../expensifyCard/WorkspaceExpensifyCardDetailsPage.tsx       | 4 ++--
 .../expensifyCard/issueNew/spendRules/SetSpendRulesStep.tsx   | 2 +-
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/src/pages/workspace/expensifyCard/WorkspaceExpensifyCardDetailsPage.tsx b/src/pages/workspace/expensifyCard/WorkspaceExpensifyCardDetailsPage.tsx
index 5bf4bf534824..d417818a47cf 100644
--- a/src/pages/workspace/expensifyCard/WorkspaceExpensifyCardDetailsPage.tsx
+++ b/src/pages/workspace/expensifyCard/WorkspaceExpensifyCardDetailsPage.tsx
@@ -344,7 +344,7 @@ function WorkspaceExpensifyCardDetailsPage({route}: WorkspaceExpensifyCardDetail
                         interactive={false}
                         titleStyle={styles.walletCardNumber}
                     />
-                    {!isProduction && spendRulesSummary.length > 0 && (
+                    {spendRulesSummary.length > 0 && (
                         <MenuItemWithTopDescription
                             interactive={false}
                             description={translate('cardPage.spendRules')}
@@ -381,7 +381,7 @@ function WorkspaceExpensifyCardDetailsPage({route}: WorkspaceExpensifyCardDetail
                     </OfflineWithFeedback>
 
                     <View style={styles.mt6}>
-                        {!isProduction && isAdmin && (
+                        {isAdmin && (
                             <MenuItem
                                 icon={expensifyIcons.CreditCardLock}
                                 title={translate('cardPage.editSpendRules')}
diff --git a/src/pages/workspace/expensifyCard/issueNew/spendRules/SetSpendRulesStep.tsx b/src/pages/workspace/expensifyCard/issueNew/spendRules/SetSpendRulesStep.tsx
index de4390f202db..12d272ae36b0 100644
--- a/src/pages/workspace/expensifyCard/issueNew/spendRules/SetSpendRulesStep.tsx
+++ b/src/pages/workspace/expensifyCard/issueNew/spendRules/SetSpendRulesStep.tsx
@@ -59,7 +59,7 @@ function SetSpendRulesStep({policyID, stepNames, startStepIndex}: SetSpendRulesS
     const isEditing = issueNewCard?.isEditing;
     const currencyCode = issueNewCard?.data?.currency ?? CONST.CURRENCY.USD;
     const isVirtualCard = issueNewCard?.data?.cardType === CONST.EXPENSIFY_CARD.CARD_TYPE.VIRTUAL;
-    const isSpendRuleVisible = !isProduction && isPolicyFeatureEnabled(policy, CONST.POLICY.MORE_FEATURES.ARE_RULES_ENABLED);
+    const isSpendRuleVisible = isPolicyFeatureEnabled(policy, CONST.POLICY.MORE_FEATURES.ARE_RULES_ENABLED);
 
     const spendRuleID = issueNewCard?.data?.spendRuleID;
     const spendRuleForm = issueNewCard?.data.spendRuleValue ?? {};

From ea54b5c6ab2fca3f8c26f9b2ae1c210389941b27 Mon Sep 17 00:00:00 2001
From: Jack Senyitko <jsenyitko@expensify.com>
Date: Thu, 4 Jun 2026 09:32:49 -0400
Subject: [PATCH 119/435] fix https://github.com/Expensify/App/issues/92391

---
 .../workspace/expensifyCard/issueNew/ConfirmationStep.tsx     | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/src/pages/workspace/expensifyCard/issueNew/ConfirmationStep.tsx b/src/pages/workspace/expensifyCard/issueNew/ConfirmationStep.tsx
index 941d256b7622..698fc8bf462b 100644
--- a/src/pages/workspace/expensifyCard/issueNew/ConfirmationStep.tsx
+++ b/src/pages/workspace/expensifyCard/issueNew/ConfirmationStep.tsx
@@ -20,6 +20,7 @@ import {getTranslationKeyForLimitType} from '@libs/CardUtils';
 import {convertToShortDisplayString} from '@libs/CurrencyUtils';
 import {getLatestErrorMessage} from '@libs/ErrorUtils';
 import {getUserNameByEmail} from '@libs/PersonalDetailsUtils';
+import {isPolicyFeatureEnabled} from '@libs/PolicyUtils';
 import createDynamicRoute from '@navigation/helpers/dynamicRoutesUtils/createDynamicRoute';
 import Navigation from '@navigation/Navigation';
 import CONST from '@src/CONST';
@@ -53,6 +54,7 @@ function ConfirmationStep({policyID, stepNames, startStepIndex}: ConfirmationSte
     const isSuccessful = issueNewCard?.isSuccessful;
     const hasApprovalError = !!policy?.errorFields?.approvalMode;
     const isSpendRuleApplied = !!issueNewCard?.data.spendRuleEnabled;
+    const areRulesEnabled = isPolicyFeatureEnabled(policy, CONST.POLICY.MORE_FEATURES.ARE_RULES_ENABLED);
     const isAddApprovalEnabled = policy?.approvalMode !== CONST.POLICY.APPROVAL_MODE.OPTIONAL && !hasApprovalError;
     const shouldDisableSubmitButton = !isAddApprovalEnabled && data?.limitType === CONST.EXPENSIFY_CARD.LIMIT_TYPES.SMART;
     const personalDetails = usePersonalDetails();
@@ -206,7 +208,7 @@ function ConfirmationStep({policyID, stepNames, startStepIndex}: ConfirmationSte
                         onPress={() => editStep(CONST.EXPENSIFY_CARD.STEP.SPEND_RULES)}
                     />
                 )}
-                {isSpendRuleApplied && (
+                {isSpendRuleApplied && areRulesEnabled && (
                     <MenuItemWithTopDescription
                         description={translate('common.restrictions')}
                         title={cardRuleRestrictionsTitle}

From 4b4d0675ed25d12afa1e762b08808edd0dab975a Mon Sep 17 00:00:00 2001
From: Jack Senyitko <jsenyitko@expensify.com>
Date: Thu, 4 Jun 2026 09:42:26 -0400
Subject: [PATCH 120/435] remove other locks

---
 .../workspace/expensifyCard/issueNew/CardNameStep.tsx     | 8 +++-----
 .../workspace/expensifyCard/issueNew/LimitTypeStep.tsx    | 8 +++-----
 2 files changed, 6 insertions(+), 10 deletions(-)

diff --git a/src/pages/workspace/expensifyCard/issueNew/CardNameStep.tsx b/src/pages/workspace/expensifyCard/issueNew/CardNameStep.tsx
index 4ac929ff30b8..aa353727b596 100644
--- a/src/pages/workspace/expensifyCard/issueNew/CardNameStep.tsx
+++ b/src/pages/workspace/expensifyCard/issueNew/CardNameStep.tsx
@@ -6,7 +6,6 @@ import InteractiveStepWrapper from '@components/InteractiveStepWrapper';
 import Text from '@components/Text';
 import TextInput from '@components/TextInput';
 import useAutoFocusInput from '@hooks/useAutoFocusInput';
-import useEnvironment from '@hooks/useEnvironment';
 import useIsInLandscapeMode from '@hooks/useIsInLandscapeMode';
 import useLocalize from '@hooks/useLocalize';
 import useOnyx from '@hooks/useOnyx';
@@ -36,7 +35,6 @@ type CardNameStepProps = {
 function CardNameStep({policyID, stepNames, startStepIndex}: CardNameStepProps) {
     const styles = useThemeStyles();
     const {translate} = useLocalize();
-    const {isProduction} = useEnvironment();
     const {inputCallbackRef} = useAutoFocusInput();
     const isInLandscapeMode = useIsInLandscapeMode();
 
@@ -46,7 +44,7 @@ function CardNameStep({policyID, stepNames, startStepIndex}: CardNameStepProps)
     const isEditing = issueNewCard?.isEditing;
     const data = issueNewCard?.data;
     const isVirtualCard = data?.cardType === CONST.EXPENSIFY_CARD.CARD_TYPE.VIRTUAL;
-    const isSpendRuleAvailable = !isProduction && isPolicyFeatureEnabled(policy, CONST.POLICY.MORE_FEATURES.ARE_RULES_ENABLED);
+    const areSpendRulesAvailable = isPolicyFeatureEnabled(policy, CONST.POLICY.MORE_FEATURES.ARE_RULES_ENABLED);
 
     const userName = getUserNameByEmail(data?.assigneeEmail ?? '', 'firstName');
     const defaultCardTitle = !isVirtualCard ? getDefaultCardName(userName) : '';
@@ -84,14 +82,14 @@ function CardNameStep({policyID, stepNames, startStepIndex}: CardNameStepProps)
                 setIssueNewCardStepAndData({step: CONST.EXPENSIFY_CARD.STEP.CONFIRMATION, isEditing: false, policyID});
                 return;
             }
-            if (isVirtualCard || isSpendRuleAvailable) {
+            if (isVirtualCard || areSpendRulesAvailable) {
                 setIssueNewCardStepAndData({step: CONST.EXPENSIFY_CARD.STEP.SPEND_RULES, policyID});
                 return;
             }
 
             setIssueNewCardStepAndData({step: CONST.EXPENSIFY_CARD.STEP.LIMIT_TYPE, policyID});
         });
-    }, [isEditing, isSpendRuleAvailable, isVirtualCard, policyID]);
+    }, [isEditing, areSpendRulesAvailable, isVirtualCard, policyID]);
 
     return (
         <InteractiveStepWrapper
diff --git a/src/pages/workspace/expensifyCard/issueNew/LimitTypeStep.tsx b/src/pages/workspace/expensifyCard/issueNew/LimitTypeStep.tsx
index 4e1b4f7cbf8d..9a0d269cb92b 100644
--- a/src/pages/workspace/expensifyCard/issueNew/LimitTypeStep.tsx
+++ b/src/pages/workspace/expensifyCard/issueNew/LimitTypeStep.tsx
@@ -8,7 +8,6 @@ import type {FormInputErrors, FormOnyxValues, FormRef} from '@components/Form/ty
 import InteractiveStepWrapper from '@components/InteractiveStepWrapper';
 import Text from '@components/Text';
 import ValuePicker from '@components/ValuePicker';
-import useEnvironment from '@hooks/useEnvironment';
 import useLocalize from '@hooks/useLocalize';
 import useOnyx from '@hooks/useOnyx';
 import useThemeStyles from '@hooks/useThemeStyles';
@@ -38,7 +37,6 @@ type LimitTypeStepProps = {
 function LimitTypeStep({policy, stepNames, startStepIndex}: LimitTypeStepProps) {
     const styles = useThemeStyles();
     const {translate} = useLocalize();
-    const {isProduction} = useEnvironment();
 
     const policyID = policy?.id;
     const formRef = useRef<FormRef | null>(null);
@@ -50,17 +48,17 @@ function LimitTypeStep({policy, stepNames, startStepIndex}: LimitTypeStepProps)
     const [typeSelected, setTypeSelected] = useState(issueNewCard?.data?.limitType ?? defaultType);
 
     const isEditing = issueNewCard?.isEditing;
-    const isSpendRuleAvailable = !isProduction && isPolicyFeatureEnabled(policy, CONST.POLICY.MORE_FEATURES.ARE_RULES_ENABLED);
+    const areSpendRulesAvailable = isPolicyFeatureEnabled(policy, CONST.POLICY.MORE_FEATURES.ARE_RULES_ENABLED);
 
     const nextStep = useMemo(() => {
         if (isEditing) {
             return CONST.EXPENSIFY_CARD.STEP.CONFIRMATION;
         }
-        if (isSpendRuleAvailable || issueNewCard?.data.cardType === CONST.EXPENSIFY_CARD.CARD_TYPE.VIRTUAL) {
+        if (areSpendRulesAvailable || issueNewCard?.data.cardType === CONST.EXPENSIFY_CARD.CARD_TYPE.VIRTUAL) {
             return CONST.EXPENSIFY_CARD.STEP.SPEND_RULES;
         }
         return CONST.EXPENSIFY_CARD.STEP.CARD_NAME;
-    }, [isSpendRuleAvailable, isEditing, issueNewCard?.data.cardType]);
+    }, [areSpendRulesAvailable, isEditing, issueNewCard?.data.cardType]);
 
     const onInputFocus = useCallback(() => {
         formRef.current?.scrollToEnd();

From a901b0e84f7930bef4fd00238b09c2422641bbbd Mon Sep 17 00:00:00 2001
From: krishna2323 <belivethatkg@gmail.com>
Date: Thu, 4 Jun 2026 20:43:04 +0530
Subject: [PATCH 121/435] add missing useCallback dep, remove stale
 allReportMetadata usage, unexport unused constant

Signed-off-by: krishna2323 <belivethatkg@gmail.com>
---
 .../Search/SearchList/ListItem/GroupChildrenContainer.tsx   | 5 +----
 .../Search/SearchList/ListItem/GroupChildrenContent.tsx     | 6 +-----
 src/components/Search/SearchList/index.tsx                  | 4 +---
 src/hooks/useExpandCollapseAnimation.ts                     | 1 -
 4 files changed, 3 insertions(+), 13 deletions(-)

diff --git a/src/components/Search/SearchList/ListItem/GroupChildrenContainer.tsx b/src/components/Search/SearchList/ListItem/GroupChildrenContainer.tsx
index 26a297e7db98..0f8e38da4f3c 100644
--- a/src/components/Search/SearchList/ListItem/GroupChildrenContainer.tsx
+++ b/src/components/Search/SearchList/ListItem/GroupChildrenContainer.tsx
@@ -8,7 +8,7 @@ import useTheme from '@hooks/useTheme';
 import useThemeStyles from '@hooks/useThemeStyles';
 import type {TransactionPreviewData} from '@libs/actions/Search';
 import type {ModifiedMouseEvent} from '@libs/Navigation/helpers/openInternalRouteInNewTab';
-import type {BankAccountList, CardFeeds, CardList, ReportMetadata, Transaction} from '@src/types/onyx';
+import type {BankAccountList, CardFeeds, CardList, Transaction} from '@src/types/onyx';
 import type {SearchDataTypes} from '@src/types/onyx/SearchResults';
 import GroupChildrenContent from './GroupChildrenContent';
 import type {GroupChildrenContainerItemType, SearchListItem, TransactionListItemType} from './types';
@@ -28,7 +28,6 @@ type GroupChildrenContainerProps = {
     isLastItem?: boolean;
     isSelected?: boolean;
     newTransactionID?: string;
-    allReportMetadata?: OnyxCollection<ReportMetadata>;
     bankAccountList?: OnyxEntry<BankAccountList>;
     cardFeeds?: OnyxCollection<CardFeeds>;
     conciergeReportID?: string;
@@ -49,7 +48,6 @@ function GroupChildrenContainer({
     isLastItem,
     isSelected,
     newTransactionID,
-    allReportMetadata,
     bankAccountList,
     cardFeeds,
     conciergeReportID,
@@ -83,7 +81,6 @@ function GroupChildrenContainer({
                             nonPersonalAndWorkspaceCards={nonPersonalAndWorkspaceCards}
                             onUndelete={onUndelete}
                             newTransactionID={newTransactionID}
-                            allReportMetadata={allReportMetadata}
                             bankAccountList={bankAccountList}
                             cardFeeds={cardFeeds}
                             conciergeReportID={conciergeReportID}
diff --git a/src/components/Search/SearchList/ListItem/GroupChildrenContent.tsx b/src/components/Search/SearchList/ListItem/GroupChildrenContent.tsx
index a32eb57fb567..99440c1026eb 100644
--- a/src/components/Search/SearchList/ListItem/GroupChildrenContent.tsx
+++ b/src/components/Search/SearchList/ListItem/GroupChildrenContent.tsx
@@ -16,7 +16,7 @@ import {getSections} from '@libs/SearchUIUtils';
 import {mergeProhibitedViolations, shouldShowViolation} from '@libs/TransactionUtils';
 import CONST from '@src/CONST';
 import ONYXKEYS from '@src/ONYXKEYS';
-import type {BankAccountList, CardFeeds, CardList, ReportMetadata, Transaction, TransactionViolation, TransactionViolations} from '@src/types/onyx';
+import type {BankAccountList, CardFeeds, CardList, Transaction, TransactionViolation, TransactionViolations} from '@src/types/onyx';
 import type {SearchDataTypes} from '@src/types/onyx/SearchResults';
 import TransactionGroupListExpandedItem from './TransactionGroupListExpanded';
 import type {GroupChildrenContainerItemType, SearchListItem, TransactionGroupListItemType, TransactionListItemType} from './types';
@@ -34,7 +34,6 @@ type GroupChildrenContentProps = {
     nonPersonalAndWorkspaceCards?: CardList;
     onUndelete?: (transaction: Transaction) => void;
     newTransactionID?: string;
-    allReportMetadata?: OnyxCollection<ReportMetadata>;
     bankAccountList?: OnyxEntry<BankAccountList>;
     cardFeeds?: OnyxCollection<CardFeeds>;
     conciergeReportID?: string;
@@ -53,7 +52,6 @@ function GroupChildrenContent({
     nonPersonalAndWorkspaceCards,
     onUndelete,
     newTransactionID,
-    allReportMetadata,
     bankAccountList,
     cardFeeds,
     conciergeReportID,
@@ -91,7 +89,6 @@ function GroupChildrenContent({
             formatPhoneNumber,
             bankAccountList,
             isActionLoadingSet,
-            allReportMetadata,
             cardFeeds,
             conciergeReportID,
             convertToDisplayString,
@@ -110,7 +107,6 @@ function GroupChildrenContent({
         formatPhoneNumber,
         bankAccountList,
         isActionLoadingSet,
-        allReportMetadata,
         cardFeeds,
         conciergeReportID,
         convertToDisplayString,
diff --git a/src/components/Search/SearchList/index.tsx b/src/components/Search/SearchList/index.tsx
index 940c44a1480d..96e1c3d6bb77 100644
--- a/src/components/Search/SearchList/index.tsx
+++ b/src/components/Search/SearchList/index.tsx
@@ -346,7 +346,6 @@ function SearchList({
     const [userBillingGracePeriodEnds] = useOnyx(ONYXKEYS.COLLECTION.SHARED_NVP_PRIVATE_USER_BILLING_GRACE_PERIOD_END);
     const [ownerBillingGracePeriodEnd] = useOnyx(ONYXKEYS.NVP_PRIVATE_OWNER_BILLING_GRACE_PERIOD_END);
     const [visibleColumns] = useOnyx(ONYXKEYS.FORMS.SEARCH_ADVANCED_FILTERS_FORM, {selector: columnsSelector});
-    const [allReportMetadata] = useOnyx(ONYXKEYS.COLLECTION.REPORT_METADATA);
     const [bankAccountList] = useOnyx(ONYXKEYS.BANK_ACCOUNT_LIST);
     const [cardFeeds] = useOnyx(ONYXKEYS.COLLECTION.SHARED_NVP_PRIVATE_DOMAIN_MEMBER);
     const [conciergeReportID] = useOnyx(ONYXKEYS.CONCIERGE_REPORT_ID);
@@ -544,7 +543,6 @@ function SearchList({
                         onUndelete={handleUndelete}
                         isLastItem={index === lastVisibleIndex && !ListFooterComponent}
                         newTransactionID={containerNewTransactionID}
-                        allReportMetadata={allReportMetadata}
                         bankAccountList={bankAccountList}
                         cardFeeds={cardFeeds}
                         conciergeReportID={conciergeReportID}
@@ -621,11 +619,11 @@ function SearchList({
             lastVisibleIndex,
             expandedGroups,
             onToggleGroup,
-            allReportMetadata,
             bankAccountList,
             cardFeeds,
             conciergeReportID,
             visibleColumns,
+            selectedTransactions,
         ],
     );
 
diff --git a/src/hooks/useExpandCollapseAnimation.ts b/src/hooks/useExpandCollapseAnimation.ts
index fb65c937c416..101fbf05d7ad 100644
--- a/src/hooks/useExpandCollapseAnimation.ts
+++ b/src/hooks/useExpandCollapseAnimation.ts
@@ -48,4 +48,3 @@ function useExpandCollapseAnimation(isExpanded: boolean) {
 }
 
 export default useExpandCollapseAnimation;
-export {EXPAND_COLLAPSE_DURATION};

From c74da45d643f3141fc1f09301d83971159fa1974 Mon Sep 17 00:00:00 2001
From: krishna2323 <belivethatkg@gmail.com>
Date: Thu, 4 Jun 2026 20:51:31 +0530
Subject: [PATCH 122/435] Fix group header arrow icon size to 20px to match
 design

Signed-off-by: krishna2323 <belivethatkg@gmail.com>
---
 src/components/Search/SearchList/ListItem/GroupHeader.tsx | 1 -
 1 file changed, 1 deletion(-)

diff --git a/src/components/Search/SearchList/ListItem/GroupHeader.tsx b/src/components/Search/SearchList/ListItem/GroupHeader.tsx
index 32119c97fdac..5fffd11ffb01 100644
--- a/src/components/Search/SearchList/ListItem/GroupHeader.tsx
+++ b/src/components/Search/SearchList/ListItem/GroupHeader.tsx
@@ -419,7 +419,6 @@ function GroupHeader({
                                             src={isExpanded ? expensifyIcons.UpArrow : expensifyIcons.DownArrow}
                                             fill={theme.icon}
                                             additionalStyles={!arrowHovered && styles.opacitySemiTransparent}
-                                            small
                                         />
                                     )}
                                 </PressableWithFeedback>

From e5411567673b21f80676896fcb73e3cd822b6e00 Mon Sep 17 00:00:00 2001
From: "Carlos Alvarez (via MelvinBot)" <infra+melvinbot@expensify.com>
Date: Thu, 4 Jun 2026 17:29:03 +0000
Subject: [PATCH 123/435] Only cap recent attendees in display when there is no
 active search

When searching, surface every matching recent attendee instead of slicing to
the display cap, so matches beyond the top 5 don't disappear from the list
(they're all excluded from "Contacts").

Co-authored-by: Carlos Alvarez <cead22@users.noreply.github.com>
---
 src/libs/OptionsListUtils/index.ts  |  4 +++-
 tests/unit/OptionsListUtilsTest.tsx | 35 +++++++++++++++++++++++++++++
 2 files changed, 38 insertions(+), 1 deletion(-)

diff --git a/src/libs/OptionsListUtils/index.ts b/src/libs/OptionsListUtils/index.ts
index e96137578b7a..e7fb13d22529 100644
--- a/src/libs/OptionsListUtils/index.ts
+++ b/src/libs/OptionsListUtils/index.ts
@@ -2570,7 +2570,9 @@ function getValidOptions(
         });
         recentReportOptions = filterReports(recentAttendees as SearchOptionData[], searchTerms) as Array<SearchOption<Report>>;
 
-        if (maxRecentReportElements) {
+        // Only cap the recent attendees when there's no active search. During a search we surface every match, since
+        // all recent attendees are excluded from "Contacts" and capped-off matches would otherwise vanish from the list.
+        if (maxRecentReportElements && searchTerms.length === 0) {
             recentReportOptions = recentReportOptions.slice(0, maxRecentReportElements);
         }
     }
diff --git a/tests/unit/OptionsListUtilsTest.tsx b/tests/unit/OptionsListUtilsTest.tsx
index 17144d330e87..5bcd7b3049d9 100644
--- a/tests/unit/OptionsListUtilsTest.tsx
+++ b/tests/unit/OptionsListUtilsTest.tsx
@@ -7579,6 +7579,41 @@ describe('OptionsListUtils', () => {
         });
     });
 
+    describe('getValidOptions() with recentAttendees', () => {
+        const recentAttendees = Array.from({length: 8}, (_, index) => ({
+            login: `john${index}@example.com`,
+            text: `John ${index}`,
+            accountID: 1000 + index,
+        }));
+
+        it('caps recent attendees to maxRecentReportElements when there is no search term', () => {
+            // When we call getValidOptions with more recent attendees than the display cap and no search term
+            const results = getValidOptions({reports: [], personalDetails: []}, allPolicies, {}, loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL, undefined, {
+                includeRecentReports: false,
+                recentAttendees,
+                maxRecentReportElements: 5,
+                sortedActions: undefined,
+            });
+
+            // Then only the first 5 recent attendees are shown
+            expect(results.recentReports.length).toBe(5);
+        });
+
+        it('shows all matching recent attendees beyond the cap when there is a search term', () => {
+            // When we call getValidOptions with a search term that matches all recent attendees
+            const results = getValidOptions({reports: [], personalDetails: []}, allPolicies, {}, loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL, undefined, {
+                includeRecentReports: false,
+                recentAttendees,
+                maxRecentReportElements: 5,
+                searchString: 'john',
+                sortedActions: undefined,
+            });
+
+            // Then all matching recent attendees are shown, not just the first 5
+            expect(results.recentReports.length).toBe(8);
+        });
+    });
+
     describe('policy parameter passing', () => {
         it('createOptionList should accept policiesCollection parameter', () => {
             const result = createOptionList(PERSONAL_DETAILS, EMPTY_PRIVATE_IS_ARCHIVED_MAP, REPORTS, allPolicies, MOCK_REPORT_ATTRIBUTES_DERIVED);

From 06ea7e258124c8a4c16d58d25f49e642c76c0d4c Mon Sep 17 00:00:00 2001
From: "Carlos Alvarez (via MelvinBot)" <infra+melvinbot@expensify.com>
Date: Thu, 4 Jun 2026 17:50:08 +0000
Subject: [PATCH 124/435] Adapt recentAttendees tests to OptionsResult return
 type from main

getValidOptions now returns OptionsResult ({options, hasMore}) after the
refactor on main, so destructure .options to access recentReports.

Co-authored-by: Carlos Alvarez <cead22@users.noreply.github.com>
---
 tests/unit/OptionsListUtilsTest.tsx | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/tests/unit/OptionsListUtilsTest.tsx b/tests/unit/OptionsListUtilsTest.tsx
index 12cdd2689384..c2837824e626 100644
--- a/tests/unit/OptionsListUtilsTest.tsx
+++ b/tests/unit/OptionsListUtilsTest.tsx
@@ -7676,7 +7676,7 @@ describe('OptionsListUtils', () => {
 
         it('caps recent attendees to maxRecentReportElements when there is no search term', () => {
             // When we call getValidOptions with more recent attendees than the display cap and no search term
-            const results = getValidOptions({reports: [], personalDetails: []}, allPolicies, {}, loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL, undefined, {
+            const {options: results} = getValidOptions({reports: [], personalDetails: []}, allPolicies, {}, loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL, undefined, {
                 includeRecentReports: false,
                 recentAttendees,
                 maxRecentReportElements: 5,
@@ -7689,7 +7689,7 @@ describe('OptionsListUtils', () => {
 
         it('shows all matching recent attendees beyond the cap when there is a search term', () => {
             // When we call getValidOptions with a search term that matches all recent attendees
-            const results = getValidOptions({reports: [], personalDetails: []}, allPolicies, {}, loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL, undefined, {
+            const {options: results} = getValidOptions({reports: [], personalDetails: []}, allPolicies, {}, loginList, CURRENT_USER_ACCOUNT_ID, CURRENT_USER_EMAIL, undefined, {
                 includeRecentReports: false,
                 recentAttendees,
                 maxRecentReportElements: 5,

From 7afa1ab788d6ca1178bc9e613bfc0b04ab2b8c86 Mon Sep 17 00:00:00 2001
From: Youssef Lourayad <youssef@expensify.com>
Date: Thu, 4 Jun 2026 21:40:44 +0000
Subject: [PATCH 125/435] Address comment

---
 src/libs/SidebarUtils.ts | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/src/libs/SidebarUtils.ts b/src/libs/SidebarUtils.ts
index 2ef287ce2357..2848d3984d74 100644
--- a/src/libs/SidebarUtils.ts
+++ b/src/libs/SidebarUtils.ts
@@ -1502,7 +1502,9 @@ function getRoomWelcomeMessage(
  * Computed once while building the LHN report set (which is cached/incremental) so the tab filter only reads a flag.
  */
 function getIsUnreadReportForInboxTab(report: Report, isReportArchived: boolean): boolean {
-    return isUnread(report, undefined, isReportArchived) && getReportNotificationPreference(report) !== CONST.REPORT.NOTIFICATION_PREFERENCE.MUTE;
+    // The `lastActorAccountID` guard matches getOptionData: it keeps chats whose only visible message was
+    // deleted out of the Unread tab even though isUnread() can still be true (lastVisibleActionCreated isn't reset).
+    return isUnread(report, undefined, isReportArchived) && !!report.lastActorAccountID && getReportNotificationPreference(report) !== CONST.REPORT.NOTIFICATION_PREFERENCE.MUTE;
 }
 
 /** Whether a report belongs in the "To-do" Inbox tab: it has an outstanding GBR (requiresAttention) or RBR (errors). */

From 273c8ac6205423db63020b104b53534d2040aab9 Mon Sep 17 00:00:00 2001
From: ShridharGoel <35566748+ShridharGoel@users.noreply.github.com>
Date: Fri, 5 Jun 2026 03:51:39 +0530
Subject: [PATCH 126/435] Add Card Admin workspace access

---
 src/CONST/index.ts                            |   1 +
 .../WorkspaceCompanyCardsTableRow.tsx         |  16 +-
 .../WorkspaceCompanyCardsTable/index.tsx      |   1 +
 src/components/WorkspaceMemberRoleList.tsx    |  20 ++-
 src/hooks/useIsAllowedToIssueCompanyCard.ts   |   9 +-
 src/languages/de.ts                           |   8 +-
 src/languages/en.ts                           |  12 +-
 src/languages/es.ts                           |   8 +-
 src/languages/fr.ts                           |   8 +-
 src/languages/it.ts                           |   8 +-
 src/languages/ja.ts                           |   8 +-
 src/languages/nl.ts                           |   8 +-
 src/languages/pl.ts                           |   8 +-
 src/languages/pt-BR.ts                        |   8 +-
 src/languages/zh-hans.ts                      |   9 +-
 src/libs/PolicyUtils.ts                       |   7 +-
 src/libs/ReportActionsUtils.ts                |  10 +-
 src/libs/actions/OnyxUpdates.ts               |  58 +++++++-
 src/libs/actions/Policy/Member.ts             |  14 +-
 .../workspace/AccessOrNotFoundWrapper.tsx     |  11 +-
 src/pages/workspace/MemberRightIcon.tsx       |  13 +-
 src/pages/workspace/WorkspaceMembersPage.tsx  |  23 ++-
 .../workspace/WorkspacePageWithSections.tsx   |   9 +-
 .../BrokenCardFeedConnectionPage.tsx          |  21 ++-
 .../RefreshCardFeedConnectionPage.tsx         |  21 ++-
 ...kspaceCompanyCardAccountSelectCardPage.tsx |  80 +++++-----
 .../WorkspaceCompanyCardAddWorkEmailPage.tsx  |   2 +
 .../WorkspaceCompanyCardEditCardNamePage.tsx  |   2 +
 ...ompanyCardEditTransactionStartDatePage.tsx |   2 +
 .../WorkspaceCompanyCardFeedSelectorPage.tsx  |   1 +
 ...spaceCompanyCardStatementCloseDatePage.tsx |   2 +
 .../WorkspaceCompanyCardsPage.tsx             |   1 +
 ...kspaceCompanyCardsSettingsFeedNamePage.tsx |   2 +
 .../WorkspaceCompanyCardsSettingsPage.tsx     |   2 +
 ...WorkspaceCompanyCardsVerifyAccountPage.tsx |  31 ++--
 .../WorkspaceVerifyWorkAccountPage.tsx        |  20 ++-
 .../addNew/CompanyCardLayoutNamePage.tsx      |   2 +
 .../CompanyCardsImportSpreadsheetPage.tsx     |   2 +
 .../addNew/CompanyCardsImportedPage.tsx       |   2 +
 .../addNew/DynamicAddNewCardPage.tsx          |   2 +
 .../companyCards/assignCard/AssigneeStep.tsx  |  48 +++---
 .../companyCards/assignCard/CardNameStep.tsx  |   2 +
 .../assignCard/CardSelectionStep.tsx          |  90 ++++++------
 .../assignCard/ConfirmationStep.tsx           | 138 +++++++++---------
 .../assignCard/InviteNewMemberStep.tsx        |  46 +++---
 .../assignCard/TransactionStartDateStep.tsx   | 134 +++++++++--------
 .../DynamicExpensifyCardLimitPage.tsx         |   2 +
 .../DynamicExpensifyCardLimitTypePage.tsx     |   2 +
 .../DynamicExpensifyCardNamePage.tsx          |   2 +
 .../DynamicWorkspaceSettlementAccountPage.tsx |   2 +
 .../WorkspaceCardSettingsPage.tsx             |   2 +
 ...WorkspaceExpensifyCardAddWorkEmailPage.tsx |   2 +
 .../WorkspaceExpensifyCardBankAccounts.tsx    |   8 +-
 ...WorkspaceExpensifyCardFeedSelectorPage.tsx |   2 +-
 .../WorkspaceExpensifyCardListPage.tsx        |   2 +-
 .../WorkspaceExpensifyCardPageEmptyState.tsx  |  18 ++-
 ...paceExpensifyCardVerifyWorkAccountPage.tsx |  20 ++-
 .../WorkspaceSettlementFrequencyPage.tsx      |   2 +
 .../issueNew/DynamicIssueNewCardPage.tsx      |   3 +-
 .../IssueNewCardConfirmMagicCodePage.tsx      |  30 ++--
 .../spendRules/SpendRuleCategoryPage.tsx      |  17 ++-
 .../spendRules/SpendRuleMaxAmountPage.tsx     |  18 ++-
 .../spendRules/SpendRuleMerchantEditPage.tsx  |  25 +++-
 .../spendRules/SpendRuleMerchantsPage.tsx     |  20 ++-
 .../spendRules/SpendRuleSelectionPage.tsx     |   2 +
 .../workspace/members/ImportedMembersPage.tsx |  13 +-
 66 files changed, 736 insertions(+), 386 deletions(-)

diff --git a/src/CONST/index.ts b/src/CONST/index.ts
index c4b8f0f4677b..d561af4e8754 100644
--- a/src/CONST/index.ts
+++ b/src/CONST/index.ts
@@ -3877,6 +3877,7 @@ const CONST = {
             MAKE_MEMBER: 'makeMember',
             MAKE_ADMIN: 'makeAdmin',
             MAKE_AUDITOR: 'makeAuditor',
+            MAKE_CARD_ADMIN: 'makeCardAdmin',
         },
         BULK_ACTION_TYPES: {
             DELETE: 'delete',
diff --git a/src/components/Tables/WorkspaceCompanyCardsTable/WorkspaceCompanyCardsTableRow.tsx b/src/components/Tables/WorkspaceCompanyCardsTable/WorkspaceCompanyCardsTableRow.tsx
index 2f7c2bedf281..edb4d53d2fb3 100644
--- a/src/components/Tables/WorkspaceCompanyCardsTable/WorkspaceCompanyCardsTableRow.tsx
+++ b/src/components/Tables/WorkspaceCompanyCardsTable/WorkspaceCompanyCardsTableRow.tsx
@@ -12,7 +12,7 @@ import useLocalize from '@hooks/useLocalize';
 import useNetwork from '@hooks/useNetwork';
 import useTheme from '@hooks/useTheme';
 import useThemeStyles from '@hooks/useThemeStyles';
-import {formatMaskedCardName, getCardFeedWithDomainID} from '@libs/CardUtils';
+import {formatMaskedCardName} from '@libs/CardUtils';
 import Navigation from '@libs/Navigation/Navigation';
 import type {SkeletonSpanReasonAttributes} from '@libs/telemetry/useSkeletonSpan';
 import variables from '@styles/variables';
@@ -43,6 +43,9 @@ type WorkspaceCompanyCardTableRowProps = {
     /** Policy ID */
     policyID: string;
 
+    /** Selected card feed */
+    feedName?: CompanyCardFeedWithDomainID;
+
     /** Card feed icon element */
     CardFeedIcon?: React.ReactNode;
 
@@ -69,6 +72,7 @@ type WorkspaceCompanyCardTableRowProps = {
 function WorkspaceCompanyCardTableRow({
     item,
     policyID,
+    feedName,
     CardFeedIcon,
     shouldUseNarrowTableLayout,
     rowIndex,
@@ -106,7 +110,7 @@ function WorkspaceCompanyCardTableRow({
         ? {width: variables.cardAvatarWidth, height: variables.cardAvatarHeight}
         : {width: variables.cardAvatarWidthSmall, height: variables.cardAvatarHeightSmall};
 
-    const canOpenCardDetails = !!assignedCard?.accountID && !!assignedCard?.fundID && assignedCard?.cardID !== undefined;
+    const canOpenCardDetails = !!assignedCard?.accountID && assignedCard?.cardID !== undefined && !!feedName;
     const canAssignCard = !isAssigned && canWriteCompanyCards && !isAssigningCardDisabled;
     const canPressRow = canOpenCardDetails || canAssignCard;
 
@@ -120,14 +124,12 @@ function WorkspaceCompanyCardTableRow({
             return;
         }
 
-        const {cardID, fundID} = assignedCard;
-        if (!canOpenCardDetails || cardID === undefined || !fundID) {
+        const {cardID} = assignedCard;
+        if (!canOpenCardDetails || cardID === undefined || !feedName) {
             return;
         }
 
-        const feedName = getCardFeedWithDomainID(assignedCard?.bank as CompanyCardFeed, fundID);
-
-        return Navigation.navigate(ROUTES.WORKSPACE_COMPANY_CARD_DETAILS.getRoute(policyID, feedName as CompanyCardFeedWithDomainID, cardID.toString()));
+        return Navigation.navigate(ROUTES.WORKSPACE_COMPANY_CARD_DETAILS.getRoute(policyID, feedName, cardID.toString()));
     };
 
     return (
diff --git a/src/components/Tables/WorkspaceCompanyCardsTable/index.tsx b/src/components/Tables/WorkspaceCompanyCardsTable/index.tsx
index b56af8ba7bc5..d9de508cbdb6 100644
--- a/src/components/Tables/WorkspaceCompanyCardsTable/index.tsx
+++ b/src/components/Tables/WorkspaceCompanyCardsTable/index.tsx
@@ -293,6 +293,7 @@ function WorkspaceCompanyCardsTable({
             item={item}
             rowIndex={index}
             policyID={policyID ?? String(CONST.DEFAULT_NUMBER_ID)}
+            feedName={feedName}
             CardFeedIcon={cardFeedIcon}
             onAssignCard={onAssignCard}
             isAssigningCardDisabled={isAssigningCardDisabled}
diff --git a/src/components/WorkspaceMemberRoleList.tsx b/src/components/WorkspaceMemberRoleList.tsx
index 801a8698faba..1e361fa19b79 100644
--- a/src/components/WorkspaceMemberRoleList.tsx
+++ b/src/components/WorkspaceMemberRoleList.tsx
@@ -40,18 +40,25 @@ function WorkspaceMemberRoleList({role, policy, navigateBackTo = undefined, isLo
     const workspaceRoles: ListItemType[] = [
         {
             value: CONST.POLICY.ROLE.ADMIN,
-            text: translate('common.admin'),
+            text: translate('workspace.common.roleName', CONST.POLICY.ROLE.ADMIN),
             alternateText: translate('workspace.common.adminAlternateText'),
             isSelected: role === CONST.POLICY.ROLE.ADMIN,
             keyForList: CONST.POLICY.ROLE.ADMIN,
         },
         {
             value: CONST.POLICY.ROLE.AUDITOR,
-            text: translate('common.auditor'),
+            text: translate('workspace.common.roleName', CONST.POLICY.ROLE.AUDITOR),
             alternateText: translate('workspace.common.auditorAlternateText'),
             isSelected: role === CONST.POLICY.ROLE.AUDITOR,
             keyForList: CONST.POLICY.ROLE.AUDITOR,
         },
+        {
+            value: CONST.POLICY.ROLE.CARD_ADMIN,
+            text: translate('workspace.common.roleName', CONST.POLICY.ROLE.CARD_ADMIN),
+            alternateText: translate('workspace.common.cardAdminAlternateText'),
+            isSelected: role === CONST.POLICY.ROLE.CARD_ADMIN,
+            keyForList: CONST.POLICY.ROLE.CARD_ADMIN,
+        },
         {
             value: CONST.POLICY.ROLE.USER,
             text: translate('common.member'),
@@ -64,12 +71,15 @@ function WorkspaceMemberRoleList({role, policy, navigateBackTo = undefined, isLo
     const isPolicyControl = isControlPolicy(policy);
     // Only strict admins can assign the ADMIN role. Editors (e.g. Submit workspace owners) can
     // invite/manage members but must not be able to escalate anyone to admin.
-    const canAssignAdminRole = isPolicyAdmin(policy, currentUserEmail);
+    const canAssignElevatedRoles = isPolicyAdmin(policy, currentUserEmail);
     const availableRoleItems: ListItemType[] = workspaceRoles.filter((item) => {
-        if (item.value === CONST.POLICY.ROLE.AUDITOR && !isPolicyControl) {
+        if (item.value === CONST.POLICY.ROLE.AUDITOR && (!isPolicyControl || !canAssignElevatedRoles)) {
+            return false;
+        }
+        if (item.value === CONST.POLICY.ROLE.CARD_ADMIN && (!isPolicyControl || !canAssignElevatedRoles)) {
             return false;
         }
-        if (item.value === CONST.POLICY.ROLE.ADMIN && !canAssignAdminRole) {
+        if (item.value === CONST.POLICY.ROLE.ADMIN && !canAssignElevatedRoles) {
             return false;
         }
         return true;
diff --git a/src/hooks/useIsAllowedToIssueCompanyCard.ts b/src/hooks/useIsAllowedToIssueCompanyCard.ts
index 87db7fae7b69..e9f35646cd93 100644
--- a/src/hooks/useIsAllowedToIssueCompanyCard.ts
+++ b/src/hooks/useIsAllowedToIssueCompanyCard.ts
@@ -1,5 +1,6 @@
 import {getCompanyFeeds, getSelectedFeed} from '@libs/CardUtils';
-import {isPolicyAdmin as isPolicyAdminPolicyUtils} from '@libs/PolicyUtils';
+import {canMemberWrite} from '@libs/PolicyUtils';
+import CONST from '@src/CONST';
 import ONYXKEYS from '@src/ONYXKEYS';
 import {isAdminSelector} from '@src/selectors/Domain';
 import useCardFeeds from './useCardFeeds';
@@ -8,10 +9,10 @@ import useOnyx from './useOnyx';
 import usePolicy from './usePolicy';
 
 function useIsAllowedToIssueCompanyCard({policyID}: {policyID?: string}) {
-    const {accountID: currentUserAccountID} = useCurrentUserPersonalDetails();
+    const {accountID: currentUserAccountID, login: currentUserLogin = ''} = useCurrentUserPersonalDetails();
     const [lastSelectedFeed] = useOnyx(`${ONYXKEYS.COLLECTION.LAST_SELECTED_FEED}${policyID}`);
     const policy = usePolicy(policyID);
-    const isPolicyAdmin = isPolicyAdminPolicyUtils(policy);
+    const canWriteCompanyCards = canMemberWrite(policy, currentUserLogin, CONST.POLICY.POLICY_FEATURE.COMPANY_CARDS);
 
     const [cardFeeds] = useCardFeeds(policyID);
     const companyCards = getCompanyFeeds(cardFeeds);
@@ -21,7 +22,7 @@ function useIsAllowedToIssueCompanyCard({policyID}: {policyID?: string}) {
     const [domain] = useOnyx(`${ONYXKEYS.COLLECTION.DOMAIN}${selectedFeedData?.domainID}`);
 
     if (selectedFeedData?.domainID === policy?.policyAccountID || (policyID && selectedFeedData?.linkedPolicyIDs?.some((id) => id.toUpperCase() === policyID.toUpperCase()))) {
-        return isPolicyAdmin;
+        return canWriteCompanyCards;
     }
 
     return isAdminSelector(currentUserAccountID)(domain);
diff --git a/src/languages/de.ts b/src/languages/de.ts
index 4aab5fbe808d..d7ff4e0b49d5 100644
--- a/src/languages/de.ts
+++ b/src/languages/de.ts
@@ -4373,7 +4373,7 @@ ${amount} für ${merchant} – ${date}`,
             roleName: (role?: string) => {
                 switch (role) {
                     case CONST.POLICY.ROLE.ADMIN:
-                        return 'Admin';
+                        return 'Workspace-Admin';
                     case CONST.POLICY.ROLE.AUDITOR:
                         return 'Prüfer';
                     case CONST.POLICY.ROLE.CARD_ADMIN:
@@ -6190,6 +6190,10 @@ _Für ausführlichere Anweisungen [besuchen Sie unsere Hilfeseite](${CONST.NETSU
                 one: 'Zum Prüfer machen',
                 other: 'Prüfende hinzufügen',
             }),
+            makeCardAdmin: () => ({
+                one: 'Zum Kartenadministrator machen',
+                other: 'Zu Kartenadministratoren machen',
+            }),
             selectAll: 'Alle auswählen',
             error: {
                 genericAdd: 'Beim Hinzufügen dieses Workspace-Mitglieds ist ein Problem aufgetreten',
@@ -8390,7 +8394,7 @@ Fügen Sie weitere Ausgabelimits hinzu, um den Cashflow Ihres Unternehmens zu sc
                 plaidBalanceFailure: ({maskedAccountNumber, walletRoute}: {maskedAccountNumber: string; walletRoute: string}) =>
                     `Die Plaid-Verbindung zu Ihrem Geschäftskonto ist unterbrochen. Bitte <a href='${walletRoute}'>verbinden Sie Ihr Bankkonto ${maskedAccountNumber} erneut</a>, damit Sie Ihre Expensify Karten weiterhin verwenden können.`,
                 addEmployee: (email: string, role: string, didJoinPolicy?: boolean) =>
-                    didJoinPolicy ? `${email} ist über den Arbeitsbereichs-Einladungslink beigetreten` : `${email} als ${role === 'member' ? 'a' : 'an'} ${role} hinzugefügt`,
+                    didJoinPolicy ? `${email} ist über den Arbeitsbereichs-Einladungslink beigetreten` : `${email} mit der Rolle ${role} hinzugefügt`,
                 updateRole: ({email, currentRole, newRole}: UpdateRoleParams) => `hat die Rolle von ${email} in ${newRole} geändert (zuvor ${currentRole})`,
                 updatedCustomField1: (email: string, newValue: string, previousValue: string) => {
                     if (!newValue) {
diff --git a/src/languages/en.ts b/src/languages/en.ts
index 156c2c6b3695..e22b1dadd73f 100644
--- a/src/languages/en.ts
+++ b/src/languages/en.ts
@@ -4471,7 +4471,7 @@ const translations = {
             roleName: (role?: string) => {
                 switch (role) {
                     case CONST.POLICY.ROLE.ADMIN:
-                        return 'Admin';
+                        return 'Workspace Admin';
                     case CONST.POLICY.ROLE.AUDITOR:
                         return 'Auditor';
                     case CONST.POLICY.ROLE.CARD_ADMIN:
@@ -6237,6 +6237,10 @@ const translations = {
                 one: 'Make auditor',
                 other: 'Make auditors',
             }),
+            makeCardAdmin: () => ({
+                one: 'Make Card Admin',
+                other: 'Make Card Admins',
+            }),
             selectAll: 'Select all',
             error: {
                 genericAdd: 'There was a problem adding this workspace member',
@@ -8429,8 +8433,10 @@ const translations = {
                     `The ${feedName} connection is broken. To restore card imports, <a href='${workspaceCompanyCardRoute}'>log into your bank</a>.`,
                 plaidBalanceFailure: ({maskedAccountNumber, walletRoute}: {maskedAccountNumber: string; walletRoute: string}) =>
                     `the Plaid connection to your business bank account is broken. Please <a href='${walletRoute}'>reconnect your bank account ${maskedAccountNumber}</a> so you can continue to use your Expensify Cards.`,
-                addEmployee: (email: string, role: string, didJoinPolicy?: boolean) =>
-                    didJoinPolicy ? `${email} joined via the workspace invite link` : `added ${email} as ${role === 'member' ? 'a' : 'an'} ${role}`,
+                addEmployee: (email: string, role: string, didJoinPolicy?: boolean) => {
+                    const article = role === 'Auditor' ? 'an' : 'a';
+                    return didJoinPolicy ? `${email} joined via the workspace invite link` : `added ${email} as ${article} ${role}`;
+                },
                 updateRole: ({email, currentRole, newRole}: UpdateRoleParams) => `updated the role of ${email} to ${newRole} (previously ${currentRole})`,
                 updatedCustomField1: (email: string, newValue: string, previousValue: string) => {
                     if (!newValue) {
diff --git a/src/languages/es.ts b/src/languages/es.ts
index 12fc795dbcd6..76564e84e065 100644
--- a/src/languages/es.ts
+++ b/src/languages/es.ts
@@ -4262,7 +4262,7 @@ ${amount} para ${merchant} - ${date}`,
             roleName: (role?: string) => {
                 switch (role) {
                     case CONST.POLICY.ROLE.ADMIN:
-                        return 'Administrador';
+                        return 'Administrador del espacio de trabajo';
                     case CONST.POLICY.ROLE.AUDITOR:
                         return 'Auditor';
                     case CONST.POLICY.ROLE.CARD_ADMIN:
@@ -6027,6 +6027,10 @@ ${amount} para ${merchant} - ${date}`,
                 one: 'Convertir en auditor',
                 other: 'Convertir en auditores',
             }),
+            makeCardAdmin: () => ({
+                one: 'Convertir en administrador de tarjeta',
+                other: 'Convertir en administradores de tarjeta',
+            }),
             selectAll: 'Seleccionar todo',
             error: {
                 genericAdd: 'Ha ocurrido un problema al añadir el miembro al espacio de trabajo',
@@ -8182,7 +8186,7 @@ ${amount} para ${merchant} - ${date}`,
                 plaidBalanceFailure: ({maskedAccountNumber, walletRoute}: {maskedAccountNumber: string; walletRoute: string}) =>
                     `la conexión Plaid con tu cuenta bancaria de empresa está rota. Por favor, <a href='${walletRoute}'>reconecta tu cuenta bancaria ${maskedAccountNumber}</a> para poder seguir usando tus Tarjetas Expensify.`,
                 addEmployee: (email: string, role: string, didJoinPolicy?: boolean) =>
-                    didJoinPolicy ? `${email} se unió mediante el enlace de invitación del espacio de trabajo` : `se añadió ${email} como ${role === 'member' ? 'a' : 'a un'} ${role}`,
+                    didJoinPolicy ? `${email} se unió mediante el enlace de invitación del espacio de trabajo` : `se añadió ${email} con el rol ${role}`,
                 updateRole: ({email, currentRole, newRole}) => `actualizó el rol ${email} a ${newRole} (previamente ${currentRole})`,
                 updatedCustomField1: (email, newValue, previousValue) => {
                     if (!newValue) {
diff --git a/src/languages/fr.ts b/src/languages/fr.ts
index e1924676e2c2..b7ae5f664b65 100644
--- a/src/languages/fr.ts
+++ b/src/languages/fr.ts
@@ -4385,7 +4385,7 @@ ${amount} pour ${merchant} - ${date}`,
             roleName: (role?: string) => {
                 switch (role) {
                     case CONST.POLICY.ROLE.ADMIN:
-                        return 'Administrateur';
+                        return 'Administrateur de l’espace de travail';
                     case CONST.POLICY.ROLE.AUDITOR:
                         return 'Auditeur';
                     case CONST.POLICY.ROLE.CARD_ADMIN:
@@ -6215,6 +6215,10 @@ _Pour des instructions plus détaillées, [visitez notre site d’aide](${CONST.
                 one: 'Nommer auditeur',
                 other: 'Créer des auditeurs',
             }),
+            makeCardAdmin: () => ({
+                one: 'Nommer administrateur de carte',
+                other: 'Nommer des administrateurs de carte',
+            }),
             selectAll: 'Tout sélectionner',
             error: {
                 genericAdd: 'Un problème est survenu lors de l’ajout de ce membre de l’espace de travail',
@@ -8424,7 +8428,7 @@ Ajoutez davantage de règles de dépenses pour protéger la trésorerie de l’e
                 plaidBalanceFailure: ({maskedAccountNumber, walletRoute}: {maskedAccountNumber: string; walletRoute: string}) =>
                     `la connexion Plaid à votre compte bancaire professionnel est rompue. Veuillez <a href='${walletRoute}'>reconnecter votre compte bancaire ${maskedAccountNumber}</a> afin de pouvoir continuer à utiliser vos Cartes Expensify.`,
                 addEmployee: (email: string, role: string, didJoinPolicy?: boolean) =>
-                    didJoinPolicy ? `${email} a rejoint via le lien d’invitation de l’espace de travail` : `a ajouté ${email} en tant que ${role === 'member' ? 'a' : 'un'} ${role}`,
+                    didJoinPolicy ? `${email} a rejoint via le lien d’invitation de l’espace de travail` : `a ajouté ${email} avec le rôle ${role}`,
                 updateRole: ({email, currentRole, newRole}: UpdateRoleParams) => `a mis à jour le rôle de ${email} en ${newRole} (précédemment ${currentRole})`,
                 updatedCustomField1: (email: string, newValue: string, previousValue: string) => {
                     if (!newValue) {
diff --git a/src/languages/it.ts b/src/languages/it.ts
index b74810e139e7..02a3bcd7dd0a 100644
--- a/src/languages/it.ts
+++ b/src/languages/it.ts
@@ -4359,7 +4359,7 @@ ${amount} per ${merchant} - ${date}`,
             roleName: (role?: string) => {
                 switch (role) {
                     case CONST.POLICY.ROLE.ADMIN:
-                        return 'Amministratore';
+                        return 'Amministratore dello spazio di lavoro';
                     case CONST.POLICY.ROLE.AUDITOR:
                         return 'Revisore';
                     case CONST.POLICY.ROLE.CARD_ADMIN:
@@ -6178,6 +6178,10 @@ _Per istruzioni più dettagliate, [visita il nostro sito di assistenza](${CONST.
                 one: 'Rendi revisore',
                 other: 'Crea revisori',
             }),
+            makeCardAdmin: () => ({
+                one: 'Rendi amministratore carta',
+                other: 'Rendi amministratori carta',
+            }),
             selectAll: 'Seleziona tutto',
             error: {
                 genericAdd: "Si è verificato un problema nell'aggiungere questo membro dello spazio di lavoro",
@@ -8379,7 +8383,7 @@ Aggiungi altre regole di spesa per proteggere il flusso di cassa aziendale.`,
                 plaidBalanceFailure: ({maskedAccountNumber, walletRoute}: {maskedAccountNumber: string; walletRoute: string}) =>
                     `la connessione Plaid al conto bancario della tua azienda non funziona. Per favore, <a href='${walletRoute}'>ricollega il conto bancario ${maskedAccountNumber}</a> così puoi continuare a usare le tue Carte Expensify.`,
                 addEmployee: (email: string, role: string, didJoinPolicy?: boolean) =>
-                    didJoinPolicy ? `${email} si è unito tramite il link di invito allo spazio di lavoro` : `ha aggiunto ${email} come ${role === 'member' ? 'a' : 'un'} ${role}`,
+                    didJoinPolicy ? `${email} si è unito tramite il link di invito allo spazio di lavoro` : `ha aggiunto ${email} con il ruolo ${role}`,
                 updateRole: ({email, currentRole, newRole}: UpdateRoleParams) => `ha aggiornato il ruolo di ${email} a ${newRole} (in precedenza ${currentRole})`,
                 updatedCustomField1: (email: string, newValue: string, previousValue: string) => {
                     if (!newValue) {
diff --git a/src/languages/ja.ts b/src/languages/ja.ts
index b001b3c7cfd5..2f6b83460010 100644
--- a/src/languages/ja.ts
+++ b/src/languages/ja.ts
@@ -4327,7 +4327,7 @@ ${integrationName === CONST.ONBOARDING_ACCOUNTING_MAPPING.other ? 'あなたの'
             roleName: (role?: string) => {
                 switch (role) {
                     case CONST.POLICY.ROLE.ADMIN:
-                        return '管理者';
+                        return 'ワークスペース管理者';
                     case CONST.POLICY.ROLE.AUDITOR:
                         return '監査担当者';
                     case CONST.POLICY.ROLE.CARD_ADMIN:
@@ -6105,6 +6105,10 @@ _詳しい手順については、[ヘルプサイトをご覧ください](${CO
                 one: '監査担当者に設定',
                 other: '監査担当者を作成',
             }),
+            makeCardAdmin: () => ({
+                one: 'カード管理者に設定',
+                other: 'カード管理者に設定',
+            }),
             selectAll: 'すべて選択',
             error: {
                 genericAdd: 'このワークスペースメンバーを追加する際に問題が発生しました',
@@ -8269,7 +8273,7 @@ ${reportName}
                 plaidBalanceFailure: ({maskedAccountNumber, walletRoute}: {maskedAccountNumber: string; walletRoute: string}) =>
                     `Plaid によるビジネス銀行口座との接続が切断されています。Expensify カードを引き続きご利用いただくために、<a href='${walletRoute}'>銀行口座 ${maskedAccountNumber} を再接続</a>してください。`,
                 addEmployee: (email: string, role: string, didJoinPolicy?: boolean) =>
-                    didJoinPolicy ? `${email} さんがワークスペースの招待リンクから参加しました` : `${role === 'member' ? 'a' : '1つの'} ${role} として ${email} を追加しました`,
+                    didJoinPolicy ? `${email} さんがワークスペースの招待リンクから参加しました` : `${email} を ${role} として追加しました`,
                 updateRole: ({email, currentRole, newRole}: UpdateRoleParams) => `${email} のロールを ${currentRole} から ${newRole} に更新しました`,
                 updatedCustomField1: (email: string, newValue: string, previousValue: string) => {
                     if (!newValue) {
diff --git a/src/languages/nl.ts b/src/languages/nl.ts
index ddd96d1d7e65..7cafed87c7f4 100644
--- a/src/languages/nl.ts
+++ b/src/languages/nl.ts
@@ -4355,7 +4355,7 @@ ${amount} voor ${merchant} - ${date}`,
             roleName: (role?: string) => {
                 switch (role) {
                     case CONST.POLICY.ROLE.ADMIN:
-                        return 'Beheer';
+                        return 'Werkruimtebeheerder';
                     case CONST.POLICY.ROLE.AUDITOR:
                         return 'Auditor';
                     case CONST.POLICY.ROLE.CARD_ADMIN:
@@ -6157,6 +6157,10 @@ _Voor meer gedetailleerde instructies, [bezoek onze help-site](${CONST.NETSUITE_
                 one: 'Auditeur maken',
                 other: 'Auditors aanmaken',
             }),
+            makeCardAdmin: () => ({
+                one: 'Kaartbeheerder maken',
+                other: 'Kaartbeheerders maken',
+            }),
             selectAll: 'Alles selecteren',
             error: {
                 genericAdd: 'Er is een probleem opgetreden bij het toevoegen van dit werkruimtelid',
@@ -8347,7 +8351,7 @@ er bestedingsregels toe om de kasstroom van het bedrijf te beschermen.`,
                 plaidBalanceFailure: ({maskedAccountNumber, walletRoute}: {maskedAccountNumber: string; walletRoute: string}) =>
                     `de Plaid-verbinding met je zakelijke bankrekening is verbroken. <a href='${walletRoute}'>Verbind je bankrekening ${maskedAccountNumber} opnieuw</a> zodat je je Expensify Kaarten kunt blijven gebruiken.`,
                 addEmployee: (email: string, role: string, didJoinPolicy?: boolean) =>
-                    didJoinPolicy ? `${email} is via de werkruimte-uitnodigingslink lid geworden` : `heeft ${email} toegevoegd als ${role === 'member' ? 'een' : 'een'} ${role}`,
+                    didJoinPolicy ? `${email} is via de werkruimte-uitnodigingslink lid geworden` : `heeft ${email} toegevoegd met de rol ${role}`,
                 updateRole: ({email, currentRole, newRole}: UpdateRoleParams) => `heeft de rol van ${email} bijgewerkt naar ${newRole} (voorheen ${currentRole})`,
                 updatedCustomField1: (email: string, newValue: string, previousValue: string) => {
                     if (!newValue) {
diff --git a/src/languages/pl.ts b/src/languages/pl.ts
index 4d73d8b074ee..b008fc16b44d 100644
--- a/src/languages/pl.ts
+++ b/src/languages/pl.ts
@@ -4347,7 +4347,7 @@ ${amount} dla ${merchant} - ${date}`,
             roleName: (role?: string) => {
                 switch (role) {
                     case CONST.POLICY.ROLE.ADMIN:
-                        return 'Administrator';
+                        return 'Administrator przestrzeni roboczej';
                     case CONST.POLICY.ROLE.AUDITOR:
                         return 'Audytor';
                     case CONST.POLICY.ROLE.CARD_ADMIN:
@@ -6152,6 +6152,10 @@ _Aby uzyskać bardziej szczegółowe instrukcje, [odwiedź naszą stronę pomocy
                 one: 'Ustaw jako audytora',
                 other: 'Utwórz audytorów',
             }),
+            makeCardAdmin: () => ({
+                one: 'Ustaw jako administratora kart',
+                other: 'Ustaw jako administratorów kart',
+            }),
             selectAll: 'Zaznacz wszystko',
             error: {
                 genericAdd: 'Wystąpił problem z dodaniem tego członka przestrzeni roboczej',
@@ -8338,7 +8342,7 @@ Dodaj więcej zasad wydatków, żeby chronić płynność finansową firmy.`,
                 plaidBalanceFailure: ({maskedAccountNumber, walletRoute}: {maskedAccountNumber: string; walletRoute: string}) =>
                     `połączenie Plaid z twoim firmowym kontem bankowym jest przerwane. Proszę, <a href='${walletRoute}'>połącz ponownie swoje konto bankowe ${maskedAccountNumber}</a>, aby móc dalej używać Kart Expensify.`,
                 addEmployee: (email: string, role: string, didJoinPolicy?: boolean) =>
-                    didJoinPolicy ? `${email} dołączył(a) przez link z zaproszeniem do przestrzeni roboczej` : `dodano ${email} jako ${role === 'member' ? 'a' : 'jeden'} ${role}`,
+                    didJoinPolicy ? `${email} dołączył(a) przez link z zaproszeniem do przestrzeni roboczej` : `dodano ${email} z rolą ${role}`,
                 updateRole: ({email, currentRole, newRole}: UpdateRoleParams) => `zaktualizowano rolę użytkownika ${email} na ${newRole} (wcześniej ${currentRole})`,
                 updatedCustomField1: (email: string, newValue: string, previousValue: string) => {
                     if (!newValue) {
diff --git a/src/languages/pt-BR.ts b/src/languages/pt-BR.ts
index b1b7653c6e71..a21c2013366b 100644
--- a/src/languages/pt-BR.ts
+++ b/src/languages/pt-BR.ts
@@ -4348,7 +4348,7 @@ ${amount} para ${merchant} - ${date}`,
             roleName: (role?: string) => {
                 switch (role) {
                     case CONST.POLICY.ROLE.ADMIN:
-                        return 'Admin';
+                        return 'Admin do workspace';
                     case CONST.POLICY.ROLE.AUDITOR:
                         return 'Auditor';
                     case CONST.POLICY.ROLE.CARD_ADMIN:
@@ -6156,6 +6156,10 @@ _Para instruções mais detalhadas, [visite nossa central de ajuda](${CONST.NETS
                 one: 'Tornar auditor',
                 other: 'Tornar auditores',
             }),
+            makeCardAdmin: () => ({
+                one: 'Tornar admin do cartão',
+                other: 'Tornar admins do cartão',
+            }),
             selectAll: 'Selecionar tudo',
             error: {
                 genericAdd: 'Ocorreu um problema ao adicionar este membro do workspace',
@@ -8341,7 +8345,7 @@ Adicione mais regras de gasto para proteger o fluxo de caixa da empresa.`,
                 plaidBalanceFailure: ({maskedAccountNumber, walletRoute}: {maskedAccountNumber: string; walletRoute: string}) =>
                     `a conexão Plaid com a sua conta bancária empresarial foi interrompida. Por favor, <a href='${walletRoute}'>reconecte sua conta bancária ${maskedAccountNumber}</a> para continuar usando seus Cartões Expensify.`,
                 addEmployee: (email: string, role: string, didJoinPolicy?: boolean) =>
-                    didJoinPolicy ? `${email} entrou pelo link de convite do workspace` : `adicionou ${email} como ${role === 'member' ? 'a' : 'um'} ${role}`,
+                    didJoinPolicy ? `${email} entrou pelo link de convite do workspace` : `adicionou ${email} com a função ${role}`,
                 updateRole: ({email, currentRole, newRole}: UpdateRoleParams) => `atualizou a função de ${email} para ${newRole} (anteriormente ${currentRole})`,
                 updatedCustomField1: (email: string, newValue: string, previousValue: string) => {
                     if (!newValue) {
diff --git a/src/languages/zh-hans.ts b/src/languages/zh-hans.ts
index 4d017ea5a363..f3c9c4d94245 100644
--- a/src/languages/zh-hans.ts
+++ b/src/languages/zh-hans.ts
@@ -4251,7 +4251,7 @@ ${amount}，商户：${merchant} - 日期：${date}`,
             roleName: (role?: string) => {
                 switch (role) {
                     case CONST.POLICY.ROLE.ADMIN:
-                        return '管理员';
+                        return '工作区管理员';
                     case CONST.POLICY.ROLE.AUDITOR:
                         return '审计员';
                     case CONST.POLICY.ROLE.CARD_ADMIN:
@@ -5997,6 +5997,10 @@ _如需更详细的说明，请[访问我们的帮助网站](${CONST.NETSUITE_IM
                 one: '设为审计员',
                 other: '创建审计员',
             }),
+            makeCardAdmin: () => ({
+                one: '设为卡片管理员',
+                other: '设为卡片管理员',
+            }),
             selectAll: '全选',
             error: {
                 genericAdd: '添加此工作区成员时出现问题',
@@ -8108,8 +8112,7 @@ ${reportName}
                     `${feedName} 连接已中断。要恢复银行卡导入，请<a href='${workspaceCompanyCardRoute}'>登录您的银行账户</a>。`,
                 plaidBalanceFailure: ({maskedAccountNumber, walletRoute}: {maskedAccountNumber: string; walletRoute: string}) =>
                     `您与企业银行账户的 Plaid 连接已中断。请<a href='${walletRoute}'>重新连接您的银行账户 ${maskedAccountNumber}</a>，以便继续使用 Expensify 卡。`,
-                addEmployee: (email: string, role: string, didJoinPolicy?: boolean) =>
-                    didJoinPolicy ? `${email} 通过工作区邀请链接加入` : `已将 ${email} 添加为 ${role === 'member' ? '一个' : '一个'} 的 ${role}`,
+                addEmployee: (email: string, role: string, didJoinPolicy?: boolean) => (didJoinPolicy ? `${email} 通过工作区邀请链接加入` : `已将 ${email} 添加为 ${role}`),
                 updateRole: ({email, currentRole, newRole}: UpdateRoleParams) => `已将 ${email} 的角色更新为 ${newRole}（先前为 ${currentRole}）`,
                 updatedCustomField1: (email: string, newValue: string, previousValue: string) => {
                     if (!newValue) {
diff --git a/src/libs/PolicyUtils.ts b/src/libs/PolicyUtils.ts
index 288f8bb1e12f..c4d547e09c14 100644
--- a/src/libs/PolicyUtils.ts
+++ b/src/libs/PolicyUtils.ts
@@ -203,6 +203,10 @@ function canMemberWrite(policy: OnyxInputOrEntry<Policy>, login: string, feature
     return hasPolicyFeaturePermission(policy, login, feature, CONST.POLICY.POLICY_FEATURE_ACCESS.WRITE);
 }
 
+function isPolicyCardAdmin(policy: OnyxInputOrEntry<Policy>, login: string): boolean {
+    return canMemberWrite(policy, login, CONST.POLICY.POLICY_FEATURE.EXPENSIFY_CARD);
+}
+
 /**
  * Checks if we have any errors stored within the policy?.employeeList. Determines whether we should show a red brick road error or not.
  */
@@ -2562,6 +2566,7 @@ export {
     canAccessSubmitWorkspaceFeatures,
     getRulesDocumentSourceURL,
     isSubmitPolicy,
+    isPolicyCardAdmin,
 };
 
-export type {MemberEmailsToAccountIDs, PolicyFeature};
+export type {MemberEmailsToAccountIDs, PolicyFeature, PolicyFeatureAccess};
diff --git a/src/libs/ReportActionsUtils.ts b/src/libs/ReportActionsUtils.ts
index 4b34fbaca017..bc3cad2ac032 100644
--- a/src/libs/ReportActionsUtils.ts
+++ b/src/libs/ReportActionsUtils.ts
@@ -2807,7 +2807,7 @@ function getPolicyChangeLogAddEmployeeMessage(translate: LocalizedTranslate, rep
 
     const originalMessage = getOriginalMessage(reportAction);
     const email = originalMessage?.email ?? '';
-    const role = translate('workspace.common.roleName', originalMessage?.role ?? '').toLowerCase();
+    const role = translate('workspace.common.roleName', originalMessage?.role ?? '');
     const formattedEmail = formatPhoneNumber(email);
     return translate('report.actions.type.addEmployee', formattedEmail, role, originalMessage?.didJoinPolicy);
 }
@@ -2830,8 +2830,8 @@ function buildPolicyChangeLogUpdateEmployeeSingleFieldMessage(translate: Localiz
         return translate(translationKey, email, stringNewValue, stringOldValue);
     }
 
-    const newRole = translate('workspace.common.roleName', stringNewValue).toLowerCase();
-    const oldRole = translate('workspace.common.roleName', stringOldValue).toLowerCase();
+    const newRole = translate('workspace.common.roleName', stringNewValue);
+    const oldRole = translate('workspace.common.roleName', stringOldValue);
     return translate('report.actions.type.updateRole', {email, newRole, currentRole: oldRole});
 }
 
@@ -3776,7 +3776,7 @@ function getPolicyChangeLogDeleteMemberMessage(translate: LocalizedTranslate, re
     }
     const originalMessage = getOriginalMessage(reportAction);
     const email = formatPhoneNumber(originalMessage?.email ?? '');
-    const role = translate('workspace.common.roleName', originalMessage?.role ?? '').toLowerCase();
+    const role = translate('workspace.common.roleName', originalMessage?.role ?? '');
     return translate('report.actions.type.removeMember', email, role);
 }
 
@@ -3971,7 +3971,7 @@ function getActionableCardFraudAlertMessage(
 function getDemotedFromWorkspaceMessage(translate: LocalizedTranslate, reportAction: OnyxEntry<ReportAction<typeof CONST.REPORT.ACTIONS.TYPE.DEMOTED_FROM_WORKSPACE>>) {
     const originalMessage = getOriginalMessage(reportAction);
     const policyName = originalMessage?.policyName ?? translate('workspace.common.workspace');
-    const oldRole = translate('workspace.common.roleName', originalMessage?.oldRole).toLowerCase();
+    const oldRole = translate('workspace.common.roleName', originalMessage?.oldRole);
     return translate('workspaceActions.demotedFromWorkspace', policyName, oldRole);
 }
 
diff --git a/src/libs/actions/OnyxUpdates.ts b/src/libs/actions/OnyxUpdates.ts
index 47df0ee60635..5318c4388b67 100644
--- a/src/libs/actions/OnyxUpdates.ts
+++ b/src/libs/actions/OnyxUpdates.ts
@@ -28,6 +28,52 @@ let pusherEventsPromise = Promise.resolve();
 
 let airshipEventsPromise = Promise.resolve();
 
+// The microsecond-keyed Errors shape produced by getMicroSecondOnyxErrorWithTranslationKey
+// and getMicroSecondOnyxErrorWithMessage: Record<string, string | null>. We deliberately
+// skip other "errors" shapes (arrays, {translationKey: ...} objects, etc.).
+function isMicroSecondErrorsShape(value: unknown): value is Record<string, string | null> {
+    if (!value || typeof value !== 'object' || Array.isArray(value)) {
+        return false;
+    }
+    const entries = Object.values(value as Record<string, unknown>);
+    if (entries.length === 0) {
+        return false;
+    }
+    return entries.every((v) => v === null || typeof v === 'string');
+}
+
+function substituteBackendMessage(node: unknown, message: string): unknown {
+    if (!node || typeof node !== 'object') {
+        return node;
+    }
+    if (Array.isArray(node)) {
+        return node.map((item) => substituteBackendMessage(item, message));
+    }
+    const result: Record<string, unknown> = {};
+    for (const [key, value] of Object.entries(node as Record<string, unknown>)) {
+        if (key === 'errors' && isMicroSecondErrorsShape(value)) {
+            const replaced: Record<string, string | null> = {};
+            for (const [microKey, microValue] of Object.entries(value)) {
+                // Preserve null entries (which clear a previous error); only substitute string values.
+                replaced[microKey] = microValue === null ? null : message;
+            }
+            result[key] = replaced;
+        } else {
+            result[key] = substituteBackendMessage(value, message);
+        }
+    }
+    return result;
+}
+
+function applyBackendMessageToFailureData<TKey extends OnyxKey>(failureData: Array<OnyxUpdate<TKey>>, message: string): Array<OnyxUpdate<TKey>> {
+    return failureData.map((entry) => {
+        if (!entry || typeof entry !== 'object' || !('value' in entry) || !entry.value || typeof entry.value !== 'object') {
+            return entry;
+        }
+        return {...entry, value: substituteBackendMessage(entry.value, message) as typeof entry.value};
+    });
+}
+
 function applyHTTPSOnyxUpdates<TKey extends OnyxKey>(request: Request<TKey>, response: Response<TKey>, lastUpdateID: number) {
     Log.info('[OnyxUpdateManager] Applying https update', false, {lastUpdateID});
     // For most requests we can immediately update Onyx. For write requests we queue the updates and apply them after the sequential queue has flushed to prevent a replay effect in
@@ -62,7 +108,17 @@ function applyHTTPSOnyxUpdates<TKey extends OnyxKey>(request: Request<TKey>, res
                     requestData: request.data,
                 });
 
-                return updateHandler(request.failureData);
+                // jsonCode 666 (EXP_ERROR) is the backend's "ExpError with a user-facing message" contract.
+                // Substitute the hardcoded translation-key string baked into request.failureData with the
+                // backend's response.message so the actual reason renders in the existing RedBrickRoad UI
+                // for every command routed through API.write — not just the handful that bypass the
+                // sequential queue via makeRequestWithSideEffects.
+                const failureDataToApply =
+                    response.jsonCode === CONST.JSON_CODE.EXP_ERROR && typeof response.message === 'string' && response.message.length > 0
+                        ? applyBackendMessageToFailureData(request.failureData, response.message)
+                        : request.failureData;
+
+                return updateHandler(failureDataToApply);
             }
             return Promise.resolve();
         })
diff --git a/src/libs/actions/Policy/Member.ts b/src/libs/actions/Policy/Member.ts
index 426365762f9d..48e1b7a06cb5 100644
--- a/src/libs/actions/Policy/Member.ts
+++ b/src/libs/actions/Policy/Member.ts
@@ -45,6 +45,10 @@ type WorkspaceMembersRoleData = {
     role: ValueOf<typeof CONST.POLICY.ROLE>;
 };
 
+function isPolicyAdminsRoomRole(role: string | undefined): boolean {
+    return role === CONST.POLICY.ROLE.ADMIN || role === CONST.POLICY.ROLE.AUDITOR || role === CONST.POLICY.ROLE.CARD_ADMIN;
+}
+
 let allReportActions: OnyxCollection<ReportActions>;
 Onyx.connect({
     key: ONYXKEYS.COLLECTION.REPORT_ACTIONS,
@@ -349,7 +353,7 @@ function removeMembers(policy: OnyxEntry<Policy>, selectedMemberEmails: string[]
         selectedMemberEmails
             .filter((login) => {
                 const role = login ? policy?.employeeList?.[login]?.role : '';
-                return role === CONST.POLICY.ROLE.ADMIN || role === CONST.POLICY.ROLE.AUDITOR;
+                return isPolicyAdminsRoomRole(role);
             })
             .map((login) => policyMemberEmailsToAccountIDs[login]),
     );
@@ -643,7 +647,7 @@ function buildUpdateWorkspaceMembersRoleOnyxData(policy: OnyxEntry<Policy>, sele
     if (adminRoom) {
         const failureDataParticipants: Record<number, Participant | null> = {...adminRoom.participants};
         const optimisticParticipants: Record<number, Participant | null> = {};
-        if (newRole === CONST.POLICY.ROLE.ADMIN || newRole === CONST.POLICY.ROLE.AUDITOR) {
+        if (isPolicyAdminsRoomRole(newRole)) {
             for (const accountID of selectedMemberAccountIDs) {
                 if (adminRoom?.participants?.[accountID]) {
                     continue;
@@ -810,11 +814,7 @@ function buildAddMembersToWorkspaceOnyxData(
     const newPersonalDetailsOnyxData = PersonalDetailsUtils.getPersonalDetailsOnyxDataForOptimisticUsers(newLogins, newAccountIDs, formatPhoneNumber);
 
     const announceRoomMembers = buildRoomMembersOnyxData(CONST.REPORT.CHAT_TYPE.POLICY_ANNOUNCE, policyID, accountIDs);
-    const adminRoomMembers = buildRoomMembersOnyxData(
-        CONST.REPORT.CHAT_TYPE.POLICY_ADMINS,
-        policyID,
-        role === CONST.POLICY.ROLE.ADMIN || role === CONST.POLICY.ROLE.AUDITOR ? accountIDs : [],
-    );
+    const adminRoomMembers = buildRoomMembersOnyxData(CONST.REPORT.CHAT_TYPE.POLICY_ADMINS, policyID, isPolicyAdminsRoomRole(role) ? accountIDs : []);
     const optimisticAnnounceChat = ReportUtils.buildOptimisticAnnounceChat(policyID, [...policyMemberAccountIDs, ...accountIDs], currentUser.accountID);
     const announceRoomChat = optimisticAnnounceChat.announceChatData;
 
diff --git a/src/pages/workspace/AccessOrNotFoundWrapper.tsx b/src/pages/workspace/AccessOrNotFoundWrapper.tsx
index 0fa296a87b49..7284fc46f81f 100644
--- a/src/pages/workspace/AccessOrNotFoundWrapper.tsx
+++ b/src/pages/workspace/AccessOrNotFoundWrapper.tsx
@@ -18,13 +18,14 @@ import Navigation from '@libs/Navigation/Navigation';
 import {
     canEditWorkspaceSettings,
     canMemberRead,
+    canMemberWrite,
     canSendInvoice,
     isControlPolicy,
     isGroupPolicy,
     isPolicyAccessible,
     isPolicyFeatureEnabled as isPolicyFeatureEnabledUtil,
 } from '@libs/PolicyUtils';
-import type {PolicyFeature} from '@libs/PolicyUtils';
+import type {PolicyFeature, PolicyFeatureAccess} from '@libs/PolicyUtils';
 import {canCreateRequest} from '@libs/ReportUtils';
 import type {SkeletonSpanReasonAttributes} from '@libs/telemetry/useSkeletonSpan';
 import NotFoundPage from '@pages/ErrorPage/NotFoundPage';
@@ -105,6 +106,9 @@ type AccessOrNotFoundWrapperProps = {
     /** Policy feature permission needed to access the page */
     policyFeature?: PolicyFeature;
 
+    /** Required policy feature access level */
+    policyFeatureAccess?: PolicyFeatureAccess;
+
     /** Props for customizing fallback pages */
     fullPageNotFoundViewProps?: FullPageNotFoundViewProps;
 
@@ -154,6 +158,7 @@ function AccessOrNotFoundWrapper({
     allPolicies,
     featureName,
     policyFeature,
+    policyFeatureAccess = CONST.POLICY.POLICY_FEATURE_ACCESS.READ,
     ...props
 }: AccessOrNotFoundWrapperProps) {
     const [report] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${reportID}`);
@@ -197,7 +202,8 @@ function AccessOrNotFoundWrapper({
     }, true);
     let hasAccessToPolicyFeature = true;
     if (policyFeature) {
-        hasAccessToPolicyFeature = canMemberRead(policy, login, policyFeature);
+        hasAccessToPolicyFeature =
+            policyFeatureAccess === CONST.POLICY.POLICY_FEATURE_ACCESS.WRITE ? canMemberWrite(policy, login, policyFeature) : canMemberRead(policy, login, policyFeature);
     }
 
     const isPolicyNotAccessible = !isPolicyAccessible(policy, login);
@@ -206,6 +212,7 @@ function AccessOrNotFoundWrapper({
     //  - workspace central-pane usages where an RHP overlay makes `isFocused` false but the Workspaces tab is still active.
     const shouldShowNotFoundPage =
         (isFocused || isWorkspacesTabFocused) && ((!isMoneyRequest && !isFromGlobalCreate && isPolicyNotAccessible) || !isPageAccessible || !hasAccessToPolicyFeature || shouldBeBlocked);
+
     // We only update the feature state if it isn't pending.
     // This is because the feature state changes several times during the creation of a workspace, while we are waiting for a response from the backend.
     // Without this, we can be unexpectedly navigated to the More Features page.
diff --git a/src/pages/workspace/MemberRightIcon.tsx b/src/pages/workspace/MemberRightIcon.tsx
index 647161c3b587..ebe0c11a1aa4 100644
--- a/src/pages/workspace/MemberRightIcon.tsx
+++ b/src/pages/workspace/MemberRightIcon.tsx
@@ -5,7 +5,6 @@ import {useListItemFocus} from '@components/SelectionList/ListItemFocusContext';
 import useLocalize from '@hooks/useLocalize';
 import useThemeStyles from '@hooks/useThemeStyles';
 import CONST from '@src/CONST';
-import type {TranslationPaths} from '@src/languages/types';
 
 type MemberRightIconProps = {
     owner?: string;
@@ -19,18 +18,16 @@ export default function MemberRightIcon({role, owner, login, badgeStyles}: Membe
     const styles = useThemeStyles();
     const {isFocused} = useListItemFocus();
 
-    let badgeText: TranslationPaths | undefined;
+    let badgeText = '';
     if (owner && owner === login) {
-        badgeText = 'common.owner';
-    } else if (role === CONST.POLICY.ROLE.ADMIN) {
-        badgeText = 'common.admin';
-    } else if (role === CONST.POLICY.ROLE.AUDITOR) {
-        badgeText = 'common.auditor';
+        badgeText = translate('common.owner');
+    } else if (role === CONST.POLICY.ROLE.ADMIN || role === CONST.POLICY.ROLE.AUDITOR || role === CONST.POLICY.ROLE.CARD_ADMIN) {
+        badgeText = translate('workspace.common.roleName', role);
     }
     if (badgeText) {
         return (
             <Badge
-                text={translate(badgeText)}
+                text={badgeText}
                 badgeStyles={[isFocused && styles.badgeDefaultActive, badgeStyles]}
             />
         );
diff --git a/src/pages/workspace/WorkspaceMembersPage.tsx b/src/pages/workspace/WorkspaceMembersPage.tsx
index 6ae64c3fab70..dacdf88c6499 100644
--- a/src/pages/workspace/WorkspaceMembersPage.tsx
+++ b/src/pages/workspace/WorkspaceMembersPage.tsx
@@ -75,6 +75,7 @@ import {
     isExpensifyTeam,
     isPaidGroupPolicy,
     isPolicyApprover,
+    isPolicyAdmin as isStrictPolicyAdmin,
 } from '@libs/PolicyUtils';
 import {getDisplayNameForParticipant} from '@libs/ReportUtils';
 import tokenizedSearch from '@libs/tokenizedSearch';
@@ -410,6 +411,7 @@ function WorkspaceMembersPage({personalDetails, route, policy}: WorkspaceMembers
 
     const policyOwner = policy?.owner;
     const currentUserLogin = currentUserPersonalDetails.login;
+    const canAssignElevatedRoles = isStrictPolicyAdmin(policy, currentUserLogin);
     const invitedPrimaryToSecondaryLogins = useMemo(() => invertObject(policy?.primaryLoginsInvited ?? {}), [policy?.primaryLoginsInvited]);
     const isControlPolicyWithWideLayout = !shouldUseNarrowLayout && isControlPolicy(policy);
 
@@ -456,10 +458,8 @@ function WorkspaceMembersPage({personalDetails, route, policy}: WorkspaceMembers
             let roleBadgeText = '';
             if (policy?.owner === details.login) {
                 roleBadgeText = translate('common.owner');
-            } else if (policyEmployee.role === CONST.POLICY.ROLE.ADMIN) {
-                roleBadgeText = translate('common.admin');
-            } else if (policyEmployee.role === CONST.POLICY.ROLE.AUDITOR) {
-                roleBadgeText = translate('common.auditor');
+            } else if (policyEmployee.role === CONST.POLICY.ROLE.ADMIN || policyEmployee.role === CONST.POLICY.ROLE.AUDITOR || policyEmployee.role === CONST.POLICY.ROLE.CARD_ADMIN) {
+                roleBadgeText = translate('workspace.common.roleName', policyEmployee.role);
             }
             const memberName = formatPhoneNumber(getDisplayNameOrDefault(details));
             const memberEmail = formatPhoneNumber(details?.login ?? '');
@@ -823,8 +823,15 @@ function WorkspaceMembersPage({personalDetails, route, policy}: WorkspaceMembers
             icon: icons.UserEye,
             onSelected: () => changeUserRole(CONST.POLICY.ROLE.AUDITOR),
         };
+        const cardAdminOption = {
+            text: translate('workspace.people.makeCardAdmin', {count: selectedEmployees.length}),
+            value: CONST.POLICY.MEMBERS_BULK_ACTION_TYPES.MAKE_CARD_ADMIN,
+            icon: icons.MakeAdmin,
+            onSelected: () => changeUserRole(CONST.POLICY.ROLE.CARD_ADMIN),
+        };
 
         const hasAtLeastOneNonAuditorRole = selectedEmployeesRoles.some((role) => role !== CONST.POLICY.ROLE.AUDITOR);
+        const hasAtLeastOneNonCardAdminRole = selectedEmployeesRoles.some((role) => role !== CONST.POLICY.ROLE.CARD_ADMIN);
         const hasAtLeastOneNonMemberRole = selectedEmployeesRoles.some((role) => role !== CONST.POLICY.ROLE.USER);
         const hasAtLeastOneNonAdminRole = selectedEmployeesRoles.some((role) => role !== CONST.POLICY.ROLE.ADMIN);
         const isReimbursementEnabled = policy?.reimbursementChoice === CONST.POLICY.REIMBURSEMENT_CHOICES.REIMBURSEMENT_YES;
@@ -834,14 +841,18 @@ function WorkspaceMembersPage({personalDetails, route, policy}: WorkspaceMembers
             options.push(memberOption);
         }
 
-        if (hasAtLeastOneNonAdminRole) {
+        if (hasAtLeastOneNonAdminRole && canAssignElevatedRoles) {
             options.push(adminOption);
         }
 
-        if (hasAtLeastOneNonAuditorRole && isControlPolicy(policy) && !hasAtLeastOnePayer) {
+        if (hasAtLeastOneNonAuditorRole && isControlPolicy(policy) && !hasAtLeastOnePayer && canAssignElevatedRoles) {
             options.push(auditorOption);
         }
 
+        if (hasAtLeastOneNonCardAdminRole && isControlPolicy(policy) && !hasAtLeastOnePayer && canAssignElevatedRoles) {
+            options.push(cardAdminOption);
+        }
+
         return options;
     };
 
diff --git a/src/pages/workspace/WorkspacePageWithSections.tsx b/src/pages/workspace/WorkspacePageWithSections.tsx
index 25c7633b29d0..cc656814e44e 100644
--- a/src/pages/workspace/WorkspacePageWithSections.tsx
+++ b/src/pages/workspace/WorkspacePageWithSections.tsx
@@ -1,5 +1,4 @@
 import {useIsFocused} from '@react-navigation/native';
-import {emailSelector} from '@selectors/Session';
 import type {ReactNode} from 'react';
 import React, {useEffect, useMemo} from 'react';
 import {View} from 'react-native';
@@ -11,6 +10,7 @@ import type HeaderWithBackButtonProps from '@components/HeaderWithBackButton/typ
 import ScreenWrapper from '@components/ScreenWrapper';
 import ScrollViewWithContext from '@components/ScrollViewWithContext';
 import useAndroidBackButtonHandler from '@hooks/useAndroidBackButtonHandler';
+import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails';
 import useIsWorkspacesTabFocused from '@hooks/useIsWorkspacesTabFocused';
 import useNetwork from '@hooks/useNetwork';
 import useOnyx from '@hooks/useOnyx';
@@ -146,9 +146,7 @@ function WorkspacePageWithSections({
 
     const [account] = useOnyx(ONYXKEYS.ACCOUNT);
     const [reimbursementAccount = CONST.REIMBURSEMENT_ACCOUNT.DEFAULT_DATA] = useOnyx(ONYXKEYS.REIMBURSEMENT_ACCOUNT);
-    const [currentUserLogin] = useOnyx(ONYXKEYS.SESSION, {
-        selector: emailSelector,
-    });
+    const {login: currentUserLogin = ''} = useCurrentUserPersonalDetails();
 
     const isLoading = isPageLoading ? true : !shouldSkipVBBACall && (reimbursementAccount?.isLoading ?? false);
     const isUsingECard = account?.isUsingExpensifyCard ?? false;
@@ -188,7 +186,8 @@ function WorkspacePageWithSections({
         // We check isPendingDelete and prevIsPendingDelete to prevent the NotFound view from showing right after we delete the workspace
         const canShowPage = hasAccessToPolicyFeature ?? (canEditWorkspaceSettings(policy, currentUserLogin) || shouldShowNonAdmin);
 
-        return (!isEmptyObject(policy) && !canShowPage) || (!shouldShowPolicy && !(isPendingDelete && !prevIsPendingDelete));
+        const shouldShowPolicyOrFeature = hasAccessToPolicyFeature ?? shouldShowPolicy;
+        return (!isEmptyObject(policy) && !canShowPage) || (!shouldShowPolicyOrFeature && !(isPendingDelete && !prevIsPendingDelete));
         // eslint-disable-next-line react-hooks/exhaustive-deps
     }, [currentUserLogin, hasAccessToPolicyFeature, isWorkspacesTabFocused, policy, shouldShowNonAdmin, shouldShowPolicy]);
 
diff --git a/src/pages/workspace/companyCards/BrokenCardFeedConnectionPage.tsx b/src/pages/workspace/companyCards/BrokenCardFeedConnectionPage.tsx
index 9f0521319dbb..07cd89160dcc 100644
--- a/src/pages/workspace/companyCards/BrokenCardFeedConnectionPage.tsx
+++ b/src/pages/workspace/companyCards/BrokenCardFeedConnectionPage.tsx
@@ -4,6 +4,7 @@ import useOnyx from '@hooks/useOnyx';
 import type {PlatformStackScreenProps} from '@libs/Navigation/PlatformStackNavigation/types';
 import type {SettingsNavigatorParamList} from '@navigation/types';
 import LoadingPage from '@pages/LoadingPage';
+import AccessOrNotFoundWrapper from '@pages/workspace/AccessOrNotFoundWrapper';
 import type {WithPolicyAndFullscreenLoadingProps} from '@pages/workspace/withPolicyAndFullscreenLoading';
 import withPolicyAndFullscreenLoading from '@pages/workspace/withPolicyAndFullscreenLoading';
 import {clearAssignCardStepAndData} from '@userActions/CompanyCards';
@@ -31,24 +32,38 @@ function BrokenCardFeedConnectionPage({route, policy}: BrokenCardFeedConnectionP
         };
     }, []);
 
+    let content: React.ReactNode;
     switch (currentStep) {
         case CONST.COMPANY_CARD.STEP.BANK_CONNECTION:
-            return (
+            content = (
                 <BankConnection
                     policyID={policyID}
                     feed={feed}
                 />
             );
+            break;
         case CONST.COMPANY_CARD.STEP.PLAID_CONNECTION:
-            return (
+            content = (
                 <PlaidConnectionStep
                     feed={feed}
                     policyID={policyID}
                 />
             );
+            break;
         default:
-            return <LoadingPage title={translate('workspace.companyCards.assignCard')} />;
+            content = <LoadingPage title={translate('workspace.companyCards.assignCard')} />;
     }
+
+    return (
+        <AccessOrNotFoundWrapper
+            policyID={policyID}
+            featureName={CONST.POLICY.MORE_FEATURES.ARE_COMPANY_CARDS_ENABLED}
+            policyFeature={CONST.POLICY.POLICY_FEATURE.COMPANY_CARDS}
+            policyFeatureAccess={CONST.POLICY.POLICY_FEATURE_ACCESS.WRITE}
+        >
+            {content}
+        </AccessOrNotFoundWrapper>
+    );
 }
 
 export default withPolicyAndFullscreenLoading(BrokenCardFeedConnectionPage);
diff --git a/src/pages/workspace/companyCards/RefreshCardFeedConnectionPage.tsx b/src/pages/workspace/companyCards/RefreshCardFeedConnectionPage.tsx
index 057600c27d6d..6d9420875626 100644
--- a/src/pages/workspace/companyCards/RefreshCardFeedConnectionPage.tsx
+++ b/src/pages/workspace/companyCards/RefreshCardFeedConnectionPage.tsx
@@ -9,6 +9,7 @@ import type {PlatformStackScreenProps} from '@libs/Navigation/PlatformStackNavig
 import type {SettingsNavigatorParamList} from '@navigation/types';
 import NotFoundPage from '@pages/ErrorPage/NotFoundPage';
 import LoadingPage from '@pages/LoadingPage';
+import AccessOrNotFoundWrapper from '@pages/workspace/AccessOrNotFoundWrapper';
 import type {WithPolicyAndFullscreenLoadingProps} from '@pages/workspace/withPolicyAndFullscreenLoading';
 import withPolicyAndFullscreenLoading from '@pages/workspace/withPolicyAndFullscreenLoading';
 import {clearAssignCardStepAndData} from '@userActions/CompanyCards';
@@ -63,26 +64,40 @@ function RefreshCardFeedConnectionPage({route, policy}: RefreshCardFeedConnectio
         return <NotFoundPage />;
     }
 
+    let content: React.ReactNode;
     switch (currentStep) {
         case CONST.COMPANY_CARD.STEP.BANK_CONNECTION:
-            return (
+            content = (
                 <BankConnection
                     policyID={policyID}
                     feed={feed}
                     title={title}
                 />
             );
+            break;
         case CONST.COMPANY_CARD.STEP.PLAID_CONNECTION:
-            return (
+            content = (
                 <PlaidConnectionStep
                     feed={feed}
                     policyID={policyID}
                     title={title}
                 />
             );
+            break;
         default:
-            return <LoadingPage title={title} />;
+            content = <LoadingPage title={title} />;
     }
+
+    return (
+        <AccessOrNotFoundWrapper
+            policyID={policyID}
+            featureName={CONST.POLICY.MORE_FEATURES.ARE_COMPANY_CARDS_ENABLED}
+            policyFeature={CONST.POLICY.POLICY_FEATURE.COMPANY_CARDS}
+            policyFeatureAccess={CONST.POLICY.POLICY_FEATURE_ACCESS.WRITE}
+        >
+            {content}
+        </AccessOrNotFoundWrapper>
+    );
 }
 
 export default withPolicyAndFullscreenLoading(RefreshCardFeedConnectionPage);
diff --git a/src/pages/workspace/companyCards/WorkspaceCompanyCardAccountSelectCardPage.tsx b/src/pages/workspace/companyCards/WorkspaceCompanyCardAccountSelectCardPage.tsx
index abb505728f62..b3b7ca054585 100644
--- a/src/pages/workspace/companyCards/WorkspaceCompanyCardAccountSelectCardPage.tsx
+++ b/src/pages/workspace/companyCards/WorkspaceCompanyCardAccountSelectCardPage.tsx
@@ -19,6 +19,7 @@ import {getConnectedIntegration, getCurrentConnectionName} from '@libs/PolicyUti
 import tokenizedSearch from '@libs/tokenizedSearch';
 import Navigation from '@navigation/Navigation';
 import type {SettingsNavigatorParamList} from '@navigation/types';
+import AccessOrNotFoundWrapper from '@pages/workspace/AccessOrNotFoundWrapper';
 import variables from '@styles/variables';
 import CONST from '@src/CONST';
 import ROUTES from '@src/ROUTES';
@@ -80,44 +81,51 @@ function WorkspaceCompanyCardAccountSelectCardPage({route}: WorkspaceCompanyCard
     };
 
     return (
-        <SelectionScreen
+        <AccessOrNotFoundWrapper
             policyID={policyID}
-            headerContent={
-                <View style={[styles.mh5, styles.mb3]}>
-                    {!!exportMenuItem?.description && (
-                        <View style={[styles.renderHTML, styles.flexRow]}>
-                            <RenderHTML
-                                html={
-                                    isXeroConnection
-                                        ? translate('workspace.moreFeatures.companyCards.integrationExportTitleXero', exportMenuItem.description)
-                                        : translate(
-                                              'workspace.moreFeatures.companyCards.integrationExportTitle',
-                                              exportMenuItem.description,
-                                              `${environmentURL}/${exportMenuItem.exportPageLink}`,
-                                          )
-                                }
-                            />
-                        </View>
-                    )}
-                </View>
-            }
             featureName={CONST.POLICY.MORE_FEATURES.ARE_COMPANY_CARDS_ENABLED}
-            displayName="WorkspaceCompanyCardAccountSelectCardPage"
-            data={searchedListOptions ?? []}
-            textInputOptions={{
-                label: translate('common.search'),
-                value: searchText,
-                onChangeText: setSearchText,
-            }}
-            onSelectRow={updateExportAccount}
-            initiallyFocusedOptionKey={exportMenuItem?.data?.find((mode) => mode.isSelected)?.keyForList}
-            onBackButtonPress={() => Navigation.goBack(ROUTES.WORKSPACE_COMPANY_CARD_DETAILS.getRoute(policyID, feed, cardID, backTo))}
-            headerTitleAlreadyTranslated={exportMenuItem?.description}
-            listEmptyContent={listEmptyContent}
-            connectionName={connectedIntegration}
-            shouldShowTextInput={shouldShowTextInput}
-            isRowMultilineSupported
-        />
+            policyFeature={CONST.POLICY.POLICY_FEATURE.COMPANY_CARDS}
+            policyFeatureAccess={CONST.POLICY.POLICY_FEATURE_ACCESS.WRITE}
+        >
+            <SelectionScreen
+                policyID={policyID}
+                headerContent={
+                    <View style={[styles.mh5, styles.mb3]}>
+                        {!!exportMenuItem?.description && (
+                            <View style={[styles.renderHTML, styles.flexRow]}>
+                                <RenderHTML
+                                    html={
+                                        isXeroConnection
+                                            ? translate('workspace.moreFeatures.companyCards.integrationExportTitleXero', exportMenuItem.description)
+                                            : translate(
+                                                  'workspace.moreFeatures.companyCards.integrationExportTitle',
+                                                  exportMenuItem.description,
+                                                  `${environmentURL}/${exportMenuItem.exportPageLink}`,
+                                              )
+                                    }
+                                />
+                            </View>
+                        )}
+                    </View>
+                }
+                featureName={CONST.POLICY.MORE_FEATURES.ARE_COMPANY_CARDS_ENABLED}
+                displayName="WorkspaceCompanyCardAccountSelectCardPage"
+                data={searchedListOptions ?? []}
+                textInputOptions={{
+                    label: translate('common.search'),
+                    value: searchText,
+                    onChangeText: setSearchText,
+                }}
+                onSelectRow={updateExportAccount}
+                initiallyFocusedOptionKey={exportMenuItem?.data?.find((mode) => mode.isSelected)?.keyForList}
+                onBackButtonPress={() => Navigation.goBack(ROUTES.WORKSPACE_COMPANY_CARD_DETAILS.getRoute(policyID, feed, cardID, backTo))}
+                headerTitleAlreadyTranslated={exportMenuItem?.description}
+                listEmptyContent={listEmptyContent}
+                connectionName={connectedIntegration}
+                shouldShowTextInput={shouldShowTextInput}
+                isRowMultilineSupported
+            />
+        </AccessOrNotFoundWrapper>
     );
 }
 
diff --git a/src/pages/workspace/companyCards/WorkspaceCompanyCardAddWorkEmailPage.tsx b/src/pages/workspace/companyCards/WorkspaceCompanyCardAddWorkEmailPage.tsx
index fd77b2a8cd57..34f0719b98d3 100644
--- a/src/pages/workspace/companyCards/WorkspaceCompanyCardAddWorkEmailPage.tsx
+++ b/src/pages/workspace/companyCards/WorkspaceCompanyCardAddWorkEmailPage.tsx
@@ -131,6 +131,8 @@ function WorkspaceCompanyCardAddWorkEmailPage({route}: WorkspaceCompanyCardAddWo
         <AccessOrNotFoundWrapper
             policyID={policyID}
             featureName={CONST.POLICY.MORE_FEATURES.ARE_COMPANY_CARDS_ENABLED}
+            policyFeature={CONST.POLICY.POLICY_FEATURE.COMPANY_CARDS}
+            policyFeatureAccess={CONST.POLICY.POLICY_FEATURE_ACCESS.WRITE}
         >
             <ScreenWrapper
                 testID="WorkspaceCompanyCardAddWorkEmailPage"
diff --git a/src/pages/workspace/companyCards/WorkspaceCompanyCardEditCardNamePage.tsx b/src/pages/workspace/companyCards/WorkspaceCompanyCardEditCardNamePage.tsx
index ce47ff93d8c9..293d4aac3f07 100644
--- a/src/pages/workspace/companyCards/WorkspaceCompanyCardEditCardNamePage.tsx
+++ b/src/pages/workspace/companyCards/WorkspaceCompanyCardEditCardNamePage.tsx
@@ -67,6 +67,8 @@ function WorkspaceCompanyCardEditCardNamePage({route}: WorkspaceCompanyCardEditC
         <AccessOrNotFoundWrapper
             policyID={policyID}
             featureName={CONST.POLICY.MORE_FEATURES.ARE_COMPANY_CARDS_ENABLED}
+            policyFeature={CONST.POLICY.POLICY_FEATURE.COMPANY_CARDS}
+            policyFeatureAccess={CONST.POLICY.POLICY_FEATURE_ACCESS.WRITE}
         >
             <ScreenWrapper
                 testID="WorkspaceCompanyCardEditCardNamePage"
diff --git a/src/pages/workspace/companyCards/WorkspaceCompanyCardEditTransactionStartDatePage.tsx b/src/pages/workspace/companyCards/WorkspaceCompanyCardEditTransactionStartDatePage.tsx
index f34586778f38..d52a671534de 100644
--- a/src/pages/workspace/companyCards/WorkspaceCompanyCardEditTransactionStartDatePage.tsx
+++ b/src/pages/workspace/companyCards/WorkspaceCompanyCardEditTransactionStartDatePage.tsx
@@ -103,6 +103,8 @@ function WorkspaceCompanyCardEditTransactionStartDatePage({route}: WorkspaceComp
         <AccessOrNotFoundWrapper
             policyID={policyID}
             featureName={CONST.POLICY.MORE_FEATURES.ARE_COMPANY_CARDS_ENABLED}
+            policyFeature={CONST.POLICY.POLICY_FEATURE.COMPANY_CARDS}
+            policyFeatureAccess={CONST.POLICY.POLICY_FEATURE_ACCESS.WRITE}
         >
             <ScreenWrapper
                 testID="WorkspaceCompanyCardEditTransactionStartDatePage"
diff --git a/src/pages/workspace/companyCards/WorkspaceCompanyCardFeedSelectorPage.tsx b/src/pages/workspace/companyCards/WorkspaceCompanyCardFeedSelectorPage.tsx
index 743050d350de..abfe04ae4c06 100644
--- a/src/pages/workspace/companyCards/WorkspaceCompanyCardFeedSelectorPage.tsx
+++ b/src/pages/workspace/companyCards/WorkspaceCompanyCardFeedSelectorPage.tsx
@@ -203,6 +203,7 @@ function WorkspaceCompanyCardFeedSelectorPage({route}: WorkspaceCompanyCardFeedS
         <AccessOrNotFoundWrapper
             policyID={policyID}
             featureName={CONST.POLICY.MORE_FEATURES.ARE_COMPANY_CARDS_ENABLED}
+            policyFeature={CONST.POLICY.POLICY_FEATURE.COMPANY_CARDS}
         >
             <ScreenWrapper
                 testID="WorkspaceCompanyCardFeedSelectorPage"
diff --git a/src/pages/workspace/companyCards/WorkspaceCompanyCardStatementCloseDatePage.tsx b/src/pages/workspace/companyCards/WorkspaceCompanyCardStatementCloseDatePage.tsx
index 1f2b82456a83..fa6685bcde00 100644
--- a/src/pages/workspace/companyCards/WorkspaceCompanyCardStatementCloseDatePage.tsx
+++ b/src/pages/workspace/companyCards/WorkspaceCompanyCardStatementCloseDatePage.tsx
@@ -87,6 +87,8 @@ function WorkspaceCompanyCardStatementCloseDatePage({
             accessVariants={[CONST.POLICY.ACCESS_VARIANTS.ADMIN, CONST.POLICY.ACCESS_VARIANTS.PAID]}
             policyID={policyID}
             featureName={CONST.POLICY.MORE_FEATURES.ARE_COMPANY_CARDS_ENABLED}
+            policyFeature={CONST.POLICY.POLICY_FEATURE.COMPANY_CARDS}
+            policyFeatureAccess={CONST.POLICY.POLICY_FEATURE_ACCESS.WRITE}
         >
             <WorkspaceCompanyCardStatementCloseDateSelectionList
                 confirmText={translate('common.apply')}
diff --git a/src/pages/workspace/companyCards/WorkspaceCompanyCardsPage.tsx b/src/pages/workspace/companyCards/WorkspaceCompanyCardsPage.tsx
index 044a1a613957..c071ae83d01f 100644
--- a/src/pages/workspace/companyCards/WorkspaceCompanyCardsPage.tsx
+++ b/src/pages/workspace/companyCards/WorkspaceCompanyCardsPage.tsx
@@ -95,6 +95,7 @@ function WorkspaceCompanyCardsPage({route}: WorkspaceCompanyCardsPageProps) {
         <AccessOrNotFoundWrapper
             policyID={route.params.policyID}
             featureName={CONST.POLICY.MORE_FEATURES.ARE_COMPANY_CARDS_ENABLED}
+            policyFeature={CONST.POLICY.POLICY_FEATURE.COMPANY_CARDS}
         >
             <WorkspacePageWithSections
                 icon={memoizedIllustrations.CompanyCard}
diff --git a/src/pages/workspace/companyCards/WorkspaceCompanyCardsSettingsFeedNamePage.tsx b/src/pages/workspace/companyCards/WorkspaceCompanyCardsSettingsFeedNamePage.tsx
index ab0c42e05133..87eaa44385de 100644
--- a/src/pages/workspace/companyCards/WorkspaceCompanyCardsSettingsFeedNamePage.tsx
+++ b/src/pages/workspace/companyCards/WorkspaceCompanyCardsSettingsFeedNamePage.tsx
@@ -87,6 +87,8 @@ function WorkspaceCompanyCardsSettingsFeedNamePage({
             accessVariants={[CONST.POLICY.ACCESS_VARIANTS.ADMIN, CONST.POLICY.ACCESS_VARIANTS.PAID]}
             policyID={policyID}
             featureName={CONST.POLICY.MORE_FEATURES.ARE_COMPANY_CARDS_ENABLED}
+            policyFeature={CONST.POLICY.POLICY_FEATURE.COMPANY_CARDS}
+            policyFeatureAccess={CONST.POLICY.POLICY_FEATURE_ACCESS.WRITE}
         >
             <ScreenWrapper
                 enableEdgeToEdgeBottomSafeAreaPadding
diff --git a/src/pages/workspace/companyCards/WorkspaceCompanyCardsSettingsPage.tsx b/src/pages/workspace/companyCards/WorkspaceCompanyCardsSettingsPage.tsx
index a6732e803c67..f24112ad1715 100644
--- a/src/pages/workspace/companyCards/WorkspaceCompanyCardsSettingsPage.tsx
+++ b/src/pages/workspace/companyCards/WorkspaceCompanyCardsSettingsPage.tsx
@@ -129,6 +129,8 @@ function WorkspaceCompanyCardsSettingsPage({
         <AccessOrNotFoundWrapper
             policyID={policyID}
             featureName={CONST.POLICY.MORE_FEATURES.ARE_COMPANY_CARDS_ENABLED}
+            policyFeature={CONST.POLICY.POLICY_FEATURE.COMPANY_CARDS}
+            policyFeatureAccess={CONST.POLICY.POLICY_FEATURE_ACCESS.WRITE}
         >
             <ScreenWrapper
                 testID="WorkspaceCompanyCardsSettingsPage"
diff --git a/src/pages/workspace/companyCards/WorkspaceCompanyCardsVerifyAccountPage.tsx b/src/pages/workspace/companyCards/WorkspaceCompanyCardsVerifyAccountPage.tsx
index aed9124e79ff..7b93829c536d 100644
--- a/src/pages/workspace/companyCards/WorkspaceCompanyCardsVerifyAccountPage.tsx
+++ b/src/pages/workspace/companyCards/WorkspaceCompanyCardsVerifyAccountPage.tsx
@@ -6,7 +6,9 @@ import createDynamicRoute from '@libs/Navigation/helpers/dynamicRoutesUtils/crea
 import type {PlatformStackScreenProps} from '@libs/Navigation/PlatformStackNavigation/types';
 import type {SettingsNavigatorParamList} from '@navigation/types';
 import VerifyAccountPageBase from '@pages/settings/VerifyAccountPageBase';
+import AccessOrNotFoundWrapper from '@pages/workspace/AccessOrNotFoundWrapper';
 import {clearAddNewCardFlow, seedCardFeedRefresh} from '@userActions/CompanyCards';
+import CONST from '@src/CONST';
 import ONYXKEYS from '@src/ONYXKEYS';
 import ROUTES, {DYNAMIC_ROUTES} from '@src/ROUTES';
 import type SCREENS from '@src/SCREENS';
@@ -29,23 +31,30 @@ function WorkspaceCompanyCardsVerifyAccountPage({route}: WorkspaceCompanyCardsVe
         seedCardFeedRefresh(feed, policy?.outputCurrency, currencyList, countryByIp);
     };
 
-    if (feed) {
-        return (
-            <VerifyAccountPageBase
-                navigateBackTo={companyCardsRoute}
-                navigateForwardTo={ROUTES.WORKSPACE_COMPANY_CARDS_REFRESH_CARD_FEED_CONNECTION.getRoute(policyID, feed)}
-                onValidationSuccess={onRefreshValidationSuccess}
-            />
-        );
-    }
-
-    return (
+    const content = feed ? (
+        <VerifyAccountPageBase
+            navigateBackTo={companyCardsRoute}
+            navigateForwardTo={ROUTES.WORKSPACE_COMPANY_CARDS_REFRESH_CARD_FEED_CONNECTION.getRoute(policyID, feed)}
+            onValidationSuccess={onRefreshValidationSuccess}
+        />
+    ) : (
         <VerifyAccountPageBase
             navigateBackTo={companyCardsRoute}
             navigateForwardTo={createDynamicRoute(DYNAMIC_ROUTES.WORKSPACE_COMPANY_CARDS_ADD_NEW.path, companyCardsRoute)}
             onValidationSuccess={clearAddNewCardFlow}
         />
     );
+
+    return (
+        <AccessOrNotFoundWrapper
+            policyID={policyID}
+            featureName={CONST.POLICY.MORE_FEATURES.ARE_COMPANY_CARDS_ENABLED}
+            policyFeature={CONST.POLICY.POLICY_FEATURE.COMPANY_CARDS}
+            policyFeatureAccess={CONST.POLICY.POLICY_FEATURE_ACCESS.WRITE}
+        >
+            {content}
+        </AccessOrNotFoundWrapper>
+    );
 }
 
 export default WorkspaceCompanyCardsVerifyAccountPage;
diff --git a/src/pages/workspace/companyCards/WorkspaceVerifyWorkAccountPage.tsx b/src/pages/workspace/companyCards/WorkspaceVerifyWorkAccountPage.tsx
index 86061d66cfef..33ae575f57a7 100644
--- a/src/pages/workspace/companyCards/WorkspaceVerifyWorkAccountPage.tsx
+++ b/src/pages/workspace/companyCards/WorkspaceVerifyWorkAccountPage.tsx
@@ -10,6 +10,7 @@ import {getMicroSecondOnyxErrorWithTranslationKey} from '@libs/ErrorUtils';
 import Navigation from '@navigation/Navigation';
 import type {PlatformStackScreenProps} from '@navigation/PlatformStackNavigation/types';
 import type {SettingsNavigatorParamList} from '@navigation/types';
+import AccessOrNotFoundWrapper from '@pages/workspace/AccessOrNotFoundWrapper';
 import {updateSelectedFeed} from '@userActions/Card';
 import {linkCardFeedToPolicy} from '@userActions/CompanyCards';
 import {clearGetAccessiblePoliciesErrors, getAccessiblePolicies} from '@userActions/Policy/Policy';
@@ -23,7 +24,9 @@ import type {Errors} from '@src/types/onyx/OnyxCommon';
 
 type WorkspaceVerifyWorkAccountPageProps = PlatformStackScreenProps<SettingsNavigatorParamList, typeof SCREENS.WORKSPACE.COMPANY_CARD_VERIFY_WORK_EMAIL>;
 
-function WorkspaceVerifyWorkAccountPage({route}: WorkspaceVerifyWorkAccountPageProps) {
+type WorkspaceVerifyWorkAccountPageContentProps = Pick<WorkspaceVerifyWorkAccountPageProps, 'route'>;
+
+function WorkspaceVerifyWorkAccountPageContent({route}: WorkspaceVerifyWorkAccountPageContentProps) {
     const {policyID, feed} = route.params;
     const {translate} = useLocalize();
     const [loginList] = useOnyx(ONYXKEYS.LOGIN_LIST);
@@ -91,4 +94,19 @@ function WorkspaceVerifyWorkAccountPage({route}: WorkspaceVerifyWorkAccountPageP
     );
 }
 
+function WorkspaceVerifyWorkAccountPage({route}: WorkspaceVerifyWorkAccountPageProps) {
+    const {policyID} = route.params;
+
+    return (
+        <AccessOrNotFoundWrapper
+            policyID={policyID}
+            featureName={CONST.POLICY.MORE_FEATURES.ARE_COMPANY_CARDS_ENABLED}
+            policyFeature={CONST.POLICY.POLICY_FEATURE.COMPANY_CARDS}
+            policyFeatureAccess={CONST.POLICY.POLICY_FEATURE_ACCESS.WRITE}
+        >
+            <WorkspaceVerifyWorkAccountPageContent route={route} />
+        </AccessOrNotFoundWrapper>
+    );
+}
+
 export default WorkspaceVerifyWorkAccountPage;
diff --git a/src/pages/workspace/companyCards/addNew/CompanyCardLayoutNamePage.tsx b/src/pages/workspace/companyCards/addNew/CompanyCardLayoutNamePage.tsx
index 8b9a9ac66b9b..cca766cf9543 100644
--- a/src/pages/workspace/companyCards/addNew/CompanyCardLayoutNamePage.tsx
+++ b/src/pages/workspace/companyCards/addNew/CompanyCardLayoutNamePage.tsx
@@ -57,6 +57,8 @@ function CompanyCardLayoutNamePage({route}: CompanyCardLayoutNamePageProps) {
         <AccessOrNotFoundWrapper
             policyID={policyID}
             featureName={CONST.POLICY.MORE_FEATURES.ARE_COMPANY_CARDS_ENABLED}
+            policyFeature={CONST.POLICY.POLICY_FEATURE.COMPANY_CARDS}
+            policyFeatureAccess={CONST.POLICY.POLICY_FEATURE_ACCESS.WRITE}
         >
             <ScreenWrapper
                 testID="CompanyCardLayoutNamePage"
diff --git a/src/pages/workspace/companyCards/addNew/CompanyCardsImportSpreadsheetPage.tsx b/src/pages/workspace/companyCards/addNew/CompanyCardsImportSpreadsheetPage.tsx
index f4c1162e02a8..24b014264d59 100644
--- a/src/pages/workspace/companyCards/addNew/CompanyCardsImportSpreadsheetPage.tsx
+++ b/src/pages/workspace/companyCards/addNew/CompanyCardsImportSpreadsheetPage.tsx
@@ -29,6 +29,8 @@ function CompanyCardsImportSpreadsheetPage({route}: CompanyCardsImportSpreadshee
         <AccessOrNotFoundWrapper
             policyID={policyID}
             featureName={CONST.POLICY.MORE_FEATURES.ARE_COMPANY_CARDS_ENABLED}
+            policyFeature={CONST.POLICY.POLICY_FEATURE.COMPANY_CARDS}
+            policyFeatureAccess={CONST.POLICY.POLICY_FEATURE_ACCESS.WRITE}
             fullPageNotFoundViewProps={{subtitleKey: isEmptyObject(policy) ? undefined : 'workspace.common.notAuthorized', onLinkPress: goBackFromInvalidPolicy}}
         >
             <ImportSpreadsheet
diff --git a/src/pages/workspace/companyCards/addNew/CompanyCardsImportedPage.tsx b/src/pages/workspace/companyCards/addNew/CompanyCardsImportedPage.tsx
index ea2bee8bca0c..6ebd47e10c25 100644
--- a/src/pages/workspace/companyCards/addNew/CompanyCardsImportedPage.tsx
+++ b/src/pages/workspace/companyCards/addNew/CompanyCardsImportedPage.tsx
@@ -168,6 +168,8 @@ function CompanyCardsImportedPage({route}: CompanyCardsImportedPageProps) {
         <AccessOrNotFoundWrapper
             policyID={policyID}
             featureName={CONST.POLICY.MORE_FEATURES.ARE_COMPANY_CARDS_ENABLED}
+            policyFeature={CONST.POLICY.POLICY_FEATURE.COMPANY_CARDS}
+            policyFeatureAccess={CONST.POLICY.POLICY_FEATURE_ACCESS.WRITE}
             fullPageNotFoundViewProps={{subtitleKey: isEmptyObject(policy) ? undefined : 'workspace.common.notAuthorized', onLinkPress: goBackFromInvalidPolicy}}
         >
             <ScreenWrapper
diff --git a/src/pages/workspace/companyCards/addNew/DynamicAddNewCardPage.tsx b/src/pages/workspace/companyCards/addNew/DynamicAddNewCardPage.tsx
index e64232757587..15655931ad8f 100644
--- a/src/pages/workspace/companyCards/addNew/DynamicAddNewCardPage.tsx
+++ b/src/pages/workspace/companyCards/addNew/DynamicAddNewCardPage.tsx
@@ -144,6 +144,8 @@ function DynamicAddNewCardPage({policy}: WithPolicyAndFullscreenLoadingProps) {
             policyID={policyID}
             accessVariants={[CONST.POLICY.ACCESS_VARIANTS.ADMIN, CONST.POLICY.ACCESS_VARIANTS.PAID]}
             featureName={CONST.POLICY.MORE_FEATURES.ARE_COMPANY_CARDS_ENABLED}
+            policyFeature={CONST.POLICY.POLICY_FEATURE.COMPANY_CARDS}
+            policyFeatureAccess={CONST.POLICY.POLICY_FEATURE_ACCESS.WRITE}
         >
             <View style={styles.flex1}>{CurrentStep}</View>
             <ConfirmModal
diff --git a/src/pages/workspace/companyCards/assignCard/AssigneeStep.tsx b/src/pages/workspace/companyCards/assignCard/AssigneeStep.tsx
index 08562711e7ba..7d0c34c9abd4 100644
--- a/src/pages/workspace/companyCards/assignCard/AssigneeStep.tsx
+++ b/src/pages/workspace/companyCards/assignCard/AssigneeStep.tsx
@@ -23,6 +23,7 @@ import {getPersonalDetailByEmail} from '@libs/PersonalDetailsUtils';
 import {filterGuideAndAccountManager, getGuideAndAccountManagerInfo, getIneligibleInvitees, isDeletedPolicyEmployee} from '@libs/PolicyUtils';
 import tokenizedSearch from '@libs/tokenizedSearch';
 import Navigation from '@navigation/Navigation';
+import AccessOrNotFoundWrapper from '@pages/workspace/AccessOrNotFoundWrapper';
 import {setAssignCardStepAndData} from '@userActions/CompanyCards';
 import CONST from '@src/CONST';
 import ONYXKEYS from '@src/ONYXKEYS';
@@ -218,27 +219,34 @@ function AssigneeStep({route}: AssigneeStepProps) {
     };
 
     return (
-        <InteractiveStepWrapper
-            wrapperID="AssigneeStep"
-            handleBackButtonPress={handleBackButtonPress}
-            headerTitle={translate('workspace.companyCards.assignCard')}
-            enableEdgeToEdgeBottomSafeAreaPadding
-            onEntryTransitionEnd={() => setDidScreenTransitionEnd(true)}
+        <AccessOrNotFoundWrapper
+            policyID={policyID}
+            featureName={CONST.POLICY.MORE_FEATURES.ARE_COMPANY_CARDS_ENABLED}
+            policyFeature={CONST.POLICY.POLICY_FEATURE.COMPANY_CARDS}
+            policyFeatureAccess={CONST.POLICY.POLICY_FEATURE_ACCESS.WRITE}
         >
-            <Text style={[styles.textHeadlineLineHeightXXL, styles.ph5, styles.mv3]}>{translate('workspace.companyCards.chooseTheCardholder')}</Text>
-            <SelectionList
-                data={assignees}
-                onSelectRow={submit}
-                ListItem={UserListItem}
-                textInputOptions={textInputOptions}
-                initiallyFocusedItemKey={assignCard?.cardToAssign?.email}
-                shouldShowLoadingPlaceholder={!areOptionsInitialized}
-                isLoadingNewOptions={!!isSearchingForReports}
-                disableMaintainingScrollPosition
-                shouldUpdateFocusedIndex
-                addBottomSafeAreaPadding
-            />
-        </InteractiveStepWrapper>
+            <InteractiveStepWrapper
+                wrapperID="AssigneeStep"
+                handleBackButtonPress={handleBackButtonPress}
+                headerTitle={translate('workspace.companyCards.assignCard')}
+                enableEdgeToEdgeBottomSafeAreaPadding
+                onEntryTransitionEnd={() => setDidScreenTransitionEnd(true)}
+            >
+                <Text style={[styles.textHeadlineLineHeightXXL, styles.ph5, styles.mv3]}>{translate('workspace.companyCards.chooseTheCardholder')}</Text>
+                <SelectionList
+                    data={assignees}
+                    onSelectRow={submit}
+                    ListItem={UserListItem}
+                    textInputOptions={textInputOptions}
+                    initiallyFocusedItemKey={assignCard?.cardToAssign?.email}
+                    shouldShowLoadingPlaceholder={!areOptionsInitialized}
+                    isLoadingNewOptions={!!isSearchingForReports}
+                    disableMaintainingScrollPosition
+                    shouldUpdateFocusedIndex
+                    addBottomSafeAreaPadding
+                />
+            </InteractiveStepWrapper>
+        </AccessOrNotFoundWrapper>
     );
 }
 
diff --git a/src/pages/workspace/companyCards/assignCard/CardNameStep.tsx b/src/pages/workspace/companyCards/assignCard/CardNameStep.tsx
index bf887fdb72d1..e51e31590196 100644
--- a/src/pages/workspace/companyCards/assignCard/CardNameStep.tsx
+++ b/src/pages/workspace/companyCards/assignCard/CardNameStep.tsx
@@ -59,6 +59,8 @@ function CardNameStep({route}: CardNameStepProps) {
         <AccessOrNotFoundWrapper
             policyID={policyID}
             featureName={CONST.POLICY.MORE_FEATURES.ARE_COMPANY_CARDS_ENABLED}
+            policyFeature={CONST.POLICY.POLICY_FEATURE.COMPANY_CARDS}
+            policyFeatureAccess={CONST.POLICY.POLICY_FEATURE_ACCESS.WRITE}
         >
             <ScreenWrapper
                 testID="CardNameStep"
diff --git a/src/pages/workspace/companyCards/assignCard/CardSelectionStep.tsx b/src/pages/workspace/companyCards/assignCard/CardSelectionStep.tsx
index 39317e2e5612..ef2f2827f757 100644
--- a/src/pages/workspace/companyCards/assignCard/CardSelectionStep.tsx
+++ b/src/pages/workspace/companyCards/assignCard/CardSelectionStep.tsx
@@ -26,6 +26,7 @@ import type {PlatformStackScreenProps} from '@libs/Navigation/PlatformStackNavig
 import type {SettingsNavigatorParamList} from '@libs/Navigation/types';
 import {getPersonalDetailByEmail} from '@libs/PersonalDetailsUtils';
 import tokenizedSearch from '@libs/tokenizedSearch';
+import AccessOrNotFoundWrapper from '@pages/workspace/AccessOrNotFoundWrapper';
 import variables from '@styles/variables';
 import CONST from '@src/CONST';
 import ONYXKEYS from '@src/ONYXKEYS';
@@ -152,49 +153,56 @@ function CardSelectionStep({route}: CardSelectionStepProps) {
     );
 
     return (
-        <InteractiveStepWrapper
-            wrapperID="CardSelectionStep"
-            handleBackButtonPress={handleBackButtonPress}
-            headerTitle={translate('workspace.companyCards.assignCard')}
-            headerSubtitle={assigneeDisplayName}
-            enableEdgeToEdgeBottomSafeAreaPadding
+        <AccessOrNotFoundWrapper
+            policyID={policyID}
+            featureName={CONST.POLICY.MORE_FEATURES.ARE_COMPANY_CARDS_ENABLED}
+            policyFeature={CONST.POLICY.POLICY_FEATURE.COMPANY_CARDS}
+            policyFeatureAccess={CONST.POLICY.POLICY_FEATURE_ACCESS.WRITE}
         >
-            {!cardListOptions.length ? (
-                <View style={[styles.flex1, styles.justifyContentCenter, styles.alignItemsCenter, styles.ph5, styles.mb9, safeAreaPaddingBottomStyle]}>
-                    <Icon
-                        src={lazyIllustrations.BrokenMagnifyingGlass}
-                        width={116}
-                        height={168}
-                    />
-                    <Text style={[styles.textHeadlineLineHeightXXL, styles.mt3]}>{translate('workspace.companyCards.noActiveCards')}</Text>
-                    <View style={[styles.renderHTML, styles.flexRow, styles.ph5, styles.mv3]}>
-                        <RenderHTML html={translate('workspace.companyCards.somethingMightBeBroken')} />
-                    </View>
-                </View>
-            ) : (
-                <SelectionList
-                    data={searchedListOptions}
-                    ListItem={SingleSelectListItem}
-                    onSelectRow={({value}) => handleSelectCard(value)}
-                    initiallyFocusedItemKey={cardSelected}
-                    textInputOptions={textInputOptions}
-                    customListHeaderContent={customListHeader}
-                    shouldScrollToFocusedIndex={false}
-                    shouldShowListEmptyContent={false}
-                    addBottomSafeAreaPadding
-                    shouldUpdateFocusedIndex
-                    footerContent={
-                        <FormAlertWithSubmitButton
-                            buttonText={translate(isEditing ? 'common.confirm' : 'common.next')}
-                            onSubmit={submit}
-                            isAlertVisible={shouldShowError}
-                            containerStyles={[!shouldShowError && styles.mt5]}
-                            message={translate('common.error.pleaseSelectOne')}
+            <InteractiveStepWrapper
+                wrapperID="CardSelectionStep"
+                handleBackButtonPress={handleBackButtonPress}
+                headerTitle={translate('workspace.companyCards.assignCard')}
+                headerSubtitle={assigneeDisplayName}
+                enableEdgeToEdgeBottomSafeAreaPadding
+            >
+                {!cardListOptions.length ? (
+                    <View style={[styles.flex1, styles.justifyContentCenter, styles.alignItemsCenter, styles.ph5, styles.mb9, safeAreaPaddingBottomStyle]}>
+                        <Icon
+                            src={lazyIllustrations.BrokenMagnifyingGlass}
+                            width={116}
+                            height={168}
                         />
-                    }
-                />
-            )}
-        </InteractiveStepWrapper>
+                        <Text style={[styles.textHeadlineLineHeightXXL, styles.mt3]}>{translate('workspace.companyCards.noActiveCards')}</Text>
+                        <View style={[styles.renderHTML, styles.flexRow, styles.ph5, styles.mv3]}>
+                            <RenderHTML html={translate('workspace.companyCards.somethingMightBeBroken')} />
+                        </View>
+                    </View>
+                ) : (
+                    <SelectionList
+                        data={searchedListOptions}
+                        ListItem={SingleSelectListItem}
+                        onSelectRow={({value}) => handleSelectCard(value)}
+                        initiallyFocusedItemKey={cardSelected}
+                        textInputOptions={textInputOptions}
+                        customListHeaderContent={customListHeader}
+                        shouldScrollToFocusedIndex={false}
+                        shouldShowListEmptyContent={false}
+                        addBottomSafeAreaPadding
+                        shouldUpdateFocusedIndex
+                        footerContent={
+                            <FormAlertWithSubmitButton
+                                buttonText={translate(isEditing ? 'common.confirm' : 'common.next')}
+                                onSubmit={submit}
+                                isAlertVisible={shouldShowError}
+                                containerStyles={[!shouldShowError && styles.mt5]}
+                                message={translate('common.error.pleaseSelectOne')}
+                            />
+                        }
+                    />
+                )}
+            </InteractiveStepWrapper>
+        </AccessOrNotFoundWrapper>
     );
 }
 
diff --git a/src/pages/workspace/companyCards/assignCard/ConfirmationStep.tsx b/src/pages/workspace/companyCards/assignCard/ConfirmationStep.tsx
index 94aea6e9811f..ee38f613697f 100644
--- a/src/pages/workspace/companyCards/assignCard/ConfirmationStep.tsx
+++ b/src/pages/workspace/companyCards/assignCard/ConfirmationStep.tsx
@@ -25,6 +25,7 @@ import type {SettingsNavigatorParamList} from '@libs/Navigation/types';
 import {getPersonalDetailByEmail} from '@libs/PersonalDetailsUtils';
 import {getDefaultAvatarURL} from '@libs/UserAvatarUtils';
 import Navigation from '@navigation/Navigation';
+import AccessOrNotFoundWrapper from '@pages/workspace/AccessOrNotFoundWrapper';
 import {
     assignWorkspaceCompanyCard,
     clearAssignCardErrors as clearAssignCardErrorsAction,
@@ -152,73 +153,80 @@ function ConfirmationStep({route}: ConfirmationStepProps) {
     };
 
     return (
-        <InteractiveStepWrapper
-            wrapperID="ConfirmationStep"
-            handleBackButtonPress={handleBackButtonPress}
-            headerTitle={translate('workspace.companyCards.assignCard')}
-            enableEdgeToEdgeBottomSafeAreaPadding
-            shouldShowOfflineIndicatorInWideScreen
+        <AccessOrNotFoundWrapper
+            policyID={policyID}
+            featureName={CONST.POLICY.MORE_FEATURES.ARE_COMPANY_CARDS_ENABLED}
+            policyFeature={CONST.POLICY.POLICY_FEATURE.COMPANY_CARDS}
+            policyFeatureAccess={CONST.POLICY.POLICY_FEATURE_ACCESS.WRITE}
         >
-            <ScrollView
-                style={styles.pt0}
-                contentContainerStyle={styles.flexGrow1}
-                addBottomSafeAreaPadding
+            <InteractiveStepWrapper
+                wrapperID="ConfirmationStep"
+                handleBackButtonPress={handleBackButtonPress}
+                headerTitle={translate('workspace.companyCards.assignCard')}
+                enableEdgeToEdgeBottomSafeAreaPadding
+                shouldShowOfflineIndicatorInWideScreen
             >
-                <Text style={[styles.textHeadlineLineHeightXXL, styles.ph5, styles.mt3]}>{translate('workspace.companyCards.letsDoubleCheck')}</Text>
-                <Text style={[styles.textSupporting, styles.ph5, styles.mv3]}>{translate('workspace.companyCards.confirmationDescription')}</Text>
-                <MenuItemWithTopDescription
-                    description={translate('workspace.companyCards.card')}
-                    title={maskCardNumber(cardToAssign?.cardName ?? '', cardToAssign?.bankName)}
-                    interactive={false}
-                />
-                <View style={[styles.optionsListSectionHeader, styles.justifyContentCenter]}>
-                    <Text style={[styles.ph5, styles.textLabelSupporting]}>{translate('common.to')}</Text>
-                </View>
-                <MenuItem
-                    title={cardholderName}
-                    description={cardholderEmail}
-                    icon={cardholder?.avatar ?? getDefaultAvatarURL({accountID: cardholderAccountID ?? CONST.DEFAULT_NUMBER_ID})}
-                    iconType={CONST.ICON_TYPE_AVATAR}
-                    shouldShowRightIcon
-                    onPress={() => editStep(CONST.COMPANY_CARD.STEP.ASSIGNEE)}
-                />
-                <MenuItemWithTopDescription
-                    description={translate('workspace.moreFeatures.companyCards.transactionStartDate')}
-                    title={
-                        cardToAssign?.dateOption === CONST.COMPANY_CARD.TRANSACTION_START_DATE_OPTIONS.FROM_BEGINNING
-                            ? translate('workspace.companyCards.fromTheBeginning')
-                            : cardToAssign?.startDate
-                    }
-                    shouldShowRightIcon
-                    onPress={() => editStep(CONST.COMPANY_CARD.STEP.TRANSACTION_START_DATE)}
-                />
-                <MenuItemWithTopDescription
-                    description={translate('workspace.companyCards.cardName')}
-                    title={cardToAssign?.customCardName}
-                    shouldShowRightIcon
-                    onPress={() => editStep(CONST.COMPANY_CARD.STEP.CARD_NAME)}
-                />
-                <View style={[styles.mh5, styles.pb5, styles.mt3, styles.flexGrow1, styles.justifyContentEnd]}>
-                    <OfflineWithFeedback
-                        shouldDisplayErrorAbove
-                        errors={assignCard?.errors ?? cardError}
-                        onClose={clearAssignCardErrors}
-                        errorRowStyles={styles.mv2}
-                    >
-                        <Button
-                            isDisabled={isOffline}
-                            success
-                            large
-                            isLoading={assignCard?.isAssigning}
-                            style={styles.w100}
-                            onPress={submit}
-                            testID={CONST.ASSIGN_CARD_BUTTON_TEST_ID}
-                            text={translate('workspace.companyCards.assignCard')}
-                        />
-                    </OfflineWithFeedback>
-                </View>
-            </ScrollView>
-        </InteractiveStepWrapper>
+                <ScrollView
+                    style={styles.pt0}
+                    contentContainerStyle={styles.flexGrow1}
+                    addBottomSafeAreaPadding
+                >
+                    <Text style={[styles.textHeadlineLineHeightXXL, styles.ph5, styles.mt3]}>{translate('workspace.companyCards.letsDoubleCheck')}</Text>
+                    <Text style={[styles.textSupporting, styles.ph5, styles.mv3]}>{translate('workspace.companyCards.confirmationDescription')}</Text>
+                    <MenuItemWithTopDescription
+                        description={translate('workspace.companyCards.card')}
+                        title={maskCardNumber(cardToAssign?.cardName ?? '', cardToAssign?.bankName)}
+                        interactive={false}
+                    />
+                    <View style={[styles.optionsListSectionHeader, styles.justifyContentCenter]}>
+                        <Text style={[styles.ph5, styles.textLabelSupporting]}>{translate('common.to')}</Text>
+                    </View>
+                    <MenuItem
+                        title={cardholderName}
+                        description={cardholderEmail}
+                        icon={cardholder?.avatar ?? getDefaultAvatarURL({accountID: cardholderAccountID ?? CONST.DEFAULT_NUMBER_ID})}
+                        iconType={CONST.ICON_TYPE_AVATAR}
+                        shouldShowRightIcon
+                        onPress={() => editStep(CONST.COMPANY_CARD.STEP.ASSIGNEE)}
+                    />
+                    <MenuItemWithTopDescription
+                        description={translate('workspace.moreFeatures.companyCards.transactionStartDate')}
+                        title={
+                            cardToAssign?.dateOption === CONST.COMPANY_CARD.TRANSACTION_START_DATE_OPTIONS.FROM_BEGINNING
+                                ? translate('workspace.companyCards.fromTheBeginning')
+                                : cardToAssign?.startDate
+                        }
+                        shouldShowRightIcon
+                        onPress={() => editStep(CONST.COMPANY_CARD.STEP.TRANSACTION_START_DATE)}
+                    />
+                    <MenuItemWithTopDescription
+                        description={translate('workspace.companyCards.cardName')}
+                        title={cardToAssign?.customCardName}
+                        shouldShowRightIcon
+                        onPress={() => editStep(CONST.COMPANY_CARD.STEP.CARD_NAME)}
+                    />
+                    <View style={[styles.mh5, styles.pb5, styles.mt3, styles.flexGrow1, styles.justifyContentEnd]}>
+                        <OfflineWithFeedback
+                            shouldDisplayErrorAbove
+                            errors={assignCard?.errors ?? cardError}
+                            onClose={clearAssignCardErrors}
+                            errorRowStyles={styles.mv2}
+                        >
+                            <Button
+                                isDisabled={isOffline}
+                                success
+                                large
+                                isLoading={assignCard?.isAssigning}
+                                style={styles.w100}
+                                onPress={submit}
+                                testID={CONST.ASSIGN_CARD_BUTTON_TEST_ID}
+                                text={translate('workspace.companyCards.assignCard')}
+                            />
+                        </OfflineWithFeedback>
+                    </View>
+                </ScrollView>
+            </InteractiveStepWrapper>
+        </AccessOrNotFoundWrapper>
     );
 }
 
diff --git a/src/pages/workspace/companyCards/assignCard/InviteNewMemberStep.tsx b/src/pages/workspace/companyCards/assignCard/InviteNewMemberStep.tsx
index d1165da8a869..928b2a3836dc 100644
--- a/src/pages/workspace/companyCards/assignCard/InviteNewMemberStep.tsx
+++ b/src/pages/workspace/companyCards/assignCard/InviteNewMemberStep.tsx
@@ -11,6 +11,7 @@ import {getCardAssignmentDateOption, getCardAssignmentStartDate, getDefaultCardN
 import type {PlatformStackScreenProps} from '@libs/Navigation/PlatformStackNavigation/types';
 import type {SettingsNavigatorParamList} from '@libs/Navigation/types';
 import Navigation from '@navigation/Navigation';
+import AccessOrNotFoundWrapper from '@pages/workspace/AccessOrNotFoundWrapper';
 import WorkspaceInviteMessageComponent from '@pages/workspace/members/WorkspaceInviteMessageComponent';
 import {setAssignCardStepAndData} from '@userActions/CompanyCards';
 import {clearInviteDraft} from '@userActions/Policy/Member';
@@ -104,26 +105,33 @@ function InviteNewMemberStep({route, currentUserPersonalDetails}: InviteeNewMemb
     }, [assignCard?.cardToAssign?.invitingMemberEmail, policy?.employeeList, goToNextStep, assignCard?.cardToAssign?.invitingMemberAccountID, policyID]);
 
     return (
-        <InteractiveStepWrapper
-            wrapperID="InviteNewMemberStep"
-            shouldEnablePickerAvoiding={false}
-            shouldEnableMaxHeight
-            headerTitle={translate('workspace.companyCards.assignCard')}
-            handleBackButtonPress={handleBackButtonPress}
-            enableEdgeToEdgeBottomSafeAreaPadding
+        <AccessOrNotFoundWrapper
+            policyID={policyID}
+            featureName={CONST.POLICY.MORE_FEATURES.ARE_COMPANY_CARDS_ENABLED}
+            policyFeature={CONST.POLICY.POLICY_FEATURE.COMPANY_CARDS}
+            policyFeatureAccess={CONST.POLICY.POLICY_FEATURE_ACCESS.WRITE}
         >
-            <WorkspaceInviteMessageComponent
-                policy={policy}
-                policyID={policyID}
-                backTo={undefined}
-                currentUserPersonalDetails={currentUserPersonalDetails}
-                shouldShowBackButton={false}
-                isInviteNewMemberStep
-                goToNextStep={goToNextStep}
-                shouldShowTooltip={false}
-                shouldShowMemberNames={false}
-            />
-        </InteractiveStepWrapper>
+            <InteractiveStepWrapper
+                wrapperID="InviteNewMemberStep"
+                shouldEnablePickerAvoiding={false}
+                shouldEnableMaxHeight
+                headerTitle={translate('workspace.companyCards.assignCard')}
+                handleBackButtonPress={handleBackButtonPress}
+                enableEdgeToEdgeBottomSafeAreaPadding
+            >
+                <WorkspaceInviteMessageComponent
+                    policy={policy}
+                    policyID={policyID}
+                    backTo={undefined}
+                    currentUserPersonalDetails={currentUserPersonalDetails}
+                    shouldShowBackButton={false}
+                    isInviteNewMemberStep
+                    goToNextStep={goToNextStep}
+                    shouldShowTooltip={false}
+                    shouldShowMemberNames={false}
+                />
+            </InteractiveStepWrapper>
+        </AccessOrNotFoundWrapper>
     );
 }
 
diff --git a/src/pages/workspace/companyCards/assignCard/TransactionStartDateStep.tsx b/src/pages/workspace/companyCards/assignCard/TransactionStartDateStep.tsx
index 62a0ed9646c0..aca7c2ada910 100644
--- a/src/pages/workspace/companyCards/assignCard/TransactionStartDateStep.tsx
+++ b/src/pages/workspace/companyCards/assignCard/TransactionStartDateStep.tsx
@@ -11,15 +11,22 @@ import Text from '@components/Text';
 import useLocalize from '@hooks/useLocalize';
 import useOnyx from '@hooks/useOnyx';
 import useThemeStyles from '@hooks/useThemeStyles';
+import type {PlatformStackScreenProps} from '@libs/Navigation/PlatformStackNavigation/types';
+import type {SettingsNavigatorParamList} from '@libs/Navigation/types';
 import type {SkeletonSpanReasonAttributes} from '@libs/telemetry/useSkeletonSpan';
 import {isRequiredFulfilled} from '@libs/ValidationUtils';
 import Navigation from '@navigation/Navigation';
+import AccessOrNotFoundWrapper from '@pages/workspace/AccessOrNotFoundWrapper';
 import {setAssignCardStepAndData} from '@userActions/CompanyCards';
 import CONST from '@src/CONST';
 import ONYXKEYS from '@src/ONYXKEYS';
+import type SCREENS from '@src/SCREENS';
 import isLoadingOnyxValue from '@src/types/utils/isLoadingOnyxValue';
 
-function TransactionStartDateStep() {
+type TransactionStartDateStepProps = PlatformStackScreenProps<SettingsNavigatorParamList, typeof SCREENS.WORKSPACE.COMPANY_CARDS_ASSIGN_CARD_TRANSACTION_START_DATE>;
+
+function TransactionStartDateStep({route}: TransactionStartDateStepProps) {
+    const policyID = route.params.policyID;
     const {translate} = useLocalize();
     const styles = useThemeStyles();
 
@@ -90,66 +97,73 @@ function TransactionStartDateStep() {
     };
 
     return (
-        <InteractiveStepWrapper
-            wrapperID="TransactionStartDateStep"
-            handleBackButtonPress={handleBackButtonPress}
-            headerTitle={translate('workspace.companyCards.assignCard')}
-            enableEdgeToEdgeBottomSafeAreaPadding
+        <AccessOrNotFoundWrapper
+            policyID={policyID}
+            featureName={CONST.POLICY.MORE_FEATURES.ARE_COMPANY_CARDS_ENABLED}
+            policyFeature={CONST.POLICY.POLICY_FEATURE.COMPANY_CARDS}
+            policyFeatureAccess={CONST.POLICY.POLICY_FEATURE_ACCESS.WRITE}
         >
-            {isLoading ? (
-                <ActivityIndicator
-                    size={CONST.ACTIVITY_INDICATOR_SIZE.LARGE}
-                    style={styles.h100}
-                    reasonAttributes={activityReasonAttributes}
-                />
-            ) : (
-                <>
-                    <Text style={[styles.textSupporting, styles.ph5, styles.mv3]}>{translate('workspace.companyCards.startDateDescription')}</Text>
-                    <View style={styles.flex1}>
-                        <SelectionList
-                            ListItem={SingleSelectListItem}
-                            onSelectRow={({value}) => handleSelectDateOption(value)}
-                            data={dateOptions}
-                            shouldSingleExecuteRowSelect
-                            initiallyFocusedItemKey={dateOptionSelected}
-                            shouldUpdateFocusedIndex
-                            addBottomSafeAreaPadding
-                            footerContent={
-                                <Button
-                                    success
-                                    large
-                                    pressOnEnter
-                                    text={translate(isEditing ? 'common.save' : 'common.next')}
-                                    onPress={submit}
-                                />
-                            }
-                            listFooterContent={
-                                dateOptionSelected === CONST.COMPANY_CARD.TRANSACTION_START_DATE_OPTIONS.CUSTOM ? (
-                                    <View style={[styles.ph5]}>
-                                        <DatePicker
-                                            inputID=""
-                                            value={startDate}
-                                            label={translate('iou.startDate')}
-                                            onInputChange={(value) => {
-                                                if (!isRequiredFulfilled(value)) {
-                                                    setErrorText(translate('common.error.fieldRequired'));
-                                                } else {
-                                                    setErrorText('');
-                                                }
-                                                setLocalStartDate(value);
-                                            }}
-                                            minDate={CONST.CALENDAR_PICKER.MIN_DATE}
-                                            maxDate={new Date()}
-                                            errorText={errorText}
-                                        />
-                                    </View>
-                                ) : null
-                            }
-                        />
-                    </View>
-                </>
-            )}
-        </InteractiveStepWrapper>
+            <InteractiveStepWrapper
+                wrapperID="TransactionStartDateStep"
+                handleBackButtonPress={handleBackButtonPress}
+                headerTitle={translate('workspace.companyCards.assignCard')}
+                enableEdgeToEdgeBottomSafeAreaPadding
+            >
+                {isLoading ? (
+                    <ActivityIndicator
+                        size={CONST.ACTIVITY_INDICATOR_SIZE.LARGE}
+                        style={styles.h100}
+                        reasonAttributes={activityReasonAttributes}
+                    />
+                ) : (
+                    <>
+                        <Text style={[styles.textSupporting, styles.ph5, styles.mv3]}>{translate('workspace.companyCards.startDateDescription')}</Text>
+                        <View style={styles.flex1}>
+                            <SelectionList
+                                ListItem={SingleSelectListItem}
+                                onSelectRow={({value}) => handleSelectDateOption(value)}
+                                data={dateOptions}
+                                shouldSingleExecuteRowSelect
+                                initiallyFocusedItemKey={dateOptionSelected}
+                                shouldUpdateFocusedIndex
+                                addBottomSafeAreaPadding
+                                footerContent={
+                                    <Button
+                                        success
+                                        large
+                                        pressOnEnter
+                                        text={translate(isEditing ? 'common.save' : 'common.next')}
+                                        onPress={submit}
+                                    />
+                                }
+                                listFooterContent={
+                                    dateOptionSelected === CONST.COMPANY_CARD.TRANSACTION_START_DATE_OPTIONS.CUSTOM ? (
+                                        <View style={[styles.ph5]}>
+                                            <DatePicker
+                                                inputID=""
+                                                value={startDate}
+                                                label={translate('iou.startDate')}
+                                                onInputChange={(value) => {
+                                                    if (!isRequiredFulfilled(value)) {
+                                                        setErrorText(translate('common.error.fieldRequired'));
+                                                    } else {
+                                                        setErrorText('');
+                                                    }
+                                                    setLocalStartDate(value);
+                                                }}
+                                                minDate={CONST.CALENDAR_PICKER.MIN_DATE}
+                                                maxDate={new Date()}
+                                                errorText={errorText}
+                                            />
+                                        </View>
+                                    ) : null
+                                }
+                            />
+                        </View>
+                    </>
+                )}
+            </InteractiveStepWrapper>
+        </AccessOrNotFoundWrapper>
     );
 }
 
diff --git a/src/pages/workspace/expensifyCard/DynamicExpensifyCardLimitPage.tsx b/src/pages/workspace/expensifyCard/DynamicExpensifyCardLimitPage.tsx
index 0bf95d3a8088..bc147e051d1b 100644
--- a/src/pages/workspace/expensifyCard/DynamicExpensifyCardLimitPage.tsx
+++ b/src/pages/workspace/expensifyCard/DynamicExpensifyCardLimitPage.tsx
@@ -124,6 +124,8 @@ function DynamicExpensifyCardLimitPage({route}: DynamicExpensifyCardLimitPagePro
             accessVariants={[CONST.POLICY.ACCESS_VARIANTS.ADMIN, CONST.POLICY.ACCESS_VARIANTS.PAID]}
             policyID={policyID}
             featureName={CONST.POLICY.MORE_FEATURES.ARE_EXPENSIFY_CARDS_ENABLED}
+            policyFeature={CONST.POLICY.POLICY_FEATURE.EXPENSIFY_CARD}
+            policyFeatureAccess={CONST.POLICY.POLICY_FEATURE_ACCESS.WRITE}
         >
             <ScreenWrapper
                 testID="DynamicExpensifyCardLimitPage"
diff --git a/src/pages/workspace/expensifyCard/DynamicExpensifyCardLimitTypePage.tsx b/src/pages/workspace/expensifyCard/DynamicExpensifyCardLimitTypePage.tsx
index 6a6dea91a04e..4ae64c0d84e5 100644
--- a/src/pages/workspace/expensifyCard/DynamicExpensifyCardLimitTypePage.tsx
+++ b/src/pages/workspace/expensifyCard/DynamicExpensifyCardLimitTypePage.tsx
@@ -207,6 +207,8 @@ function DynamicExpensifyCardLimitTypePage({route}: WorkspaceEditCardLimitTypePa
             accessVariants={[CONST.POLICY.ACCESS_VARIANTS.ADMIN, CONST.POLICY.ACCESS_VARIANTS.PAID]}
             policyID={policyID}
             featureName={CONST.POLICY.MORE_FEATURES.ARE_EXPENSIFY_CARDS_ENABLED}
+            policyFeature={CONST.POLICY.POLICY_FEATURE.EXPENSIFY_CARD}
+            policyFeatureAccess={CONST.POLICY.POLICY_FEATURE_ACCESS.WRITE}
         >
             <ScreenWrapper
                 testID="WorkspaceEditCardLimitTypePage"
diff --git a/src/pages/workspace/expensifyCard/DynamicExpensifyCardNamePage.tsx b/src/pages/workspace/expensifyCard/DynamicExpensifyCardNamePage.tsx
index 93ce3f1365e3..f52022df5c45 100644
--- a/src/pages/workspace/expensifyCard/DynamicExpensifyCardNamePage.tsx
+++ b/src/pages/workspace/expensifyCard/DynamicExpensifyCardNamePage.tsx
@@ -64,6 +64,8 @@ function DynamicExpensifyCardNamePage({route}: DynamicExpensifyCardNamePageProps
             accessVariants={[CONST.POLICY.ACCESS_VARIANTS.ADMIN, CONST.POLICY.ACCESS_VARIANTS.PAID]}
             policyID={policyID}
             featureName={CONST.POLICY.MORE_FEATURES.ARE_EXPENSIFY_CARDS_ENABLED}
+            policyFeature={CONST.POLICY.POLICY_FEATURE.EXPENSIFY_CARD}
+            policyFeatureAccess={CONST.POLICY.POLICY_FEATURE_ACCESS.WRITE}
         >
             <ScreenWrapper
                 testID="WorkspaceEditCardNamePage"
diff --git a/src/pages/workspace/expensifyCard/DynamicWorkspaceSettlementAccountPage.tsx b/src/pages/workspace/expensifyCard/DynamicWorkspaceSettlementAccountPage.tsx
index 470233636381..4244ad087ca3 100644
--- a/src/pages/workspace/expensifyCard/DynamicWorkspaceSettlementAccountPage.tsx
+++ b/src/pages/workspace/expensifyCard/DynamicWorkspaceSettlementAccountPage.tsx
@@ -149,6 +149,8 @@ function DynamicWorkspaceSettlementAccountPage({route}: WorkspaceSettlementAccou
             accessVariants={[CONST.POLICY.ACCESS_VARIANTS.ADMIN, CONST.POLICY.ACCESS_VARIANTS.PAID]}
             policyID={policyID}
             featureName={CONST.POLICY.MORE_FEATURES.ARE_EXPENSIFY_CARDS_ENABLED}
+            policyFeature={CONST.POLICY.POLICY_FEATURE.EXPENSIFY_CARD}
+            policyFeatureAccess={CONST.POLICY.POLICY_FEATURE_ACCESS.WRITE}
         >
             <ScreenWrapper
                 testID="WorkspaceSettlementAccountPage"
diff --git a/src/pages/workspace/expensifyCard/WorkspaceCardSettingsPage.tsx b/src/pages/workspace/expensifyCard/WorkspaceCardSettingsPage.tsx
index 799909b471ea..dc7b2d0ef641 100644
--- a/src/pages/workspace/expensifyCard/WorkspaceCardSettingsPage.tsx
+++ b/src/pages/workspace/expensifyCard/WorkspaceCardSettingsPage.tsx
@@ -55,6 +55,8 @@ function WorkspaceCardSettingsPage({route}: WorkspaceCardSettingsPageProps) {
             accessVariants={[CONST.POLICY.ACCESS_VARIANTS.ADMIN, CONST.POLICY.ACCESS_VARIANTS.PAID]}
             policyID={policyID}
             featureName={CONST.POLICY.MORE_FEATURES.ARE_EXPENSIFY_CARDS_ENABLED}
+            policyFeature={CONST.POLICY.POLICY_FEATURE.EXPENSIFY_CARD}
+            policyFeatureAccess={CONST.POLICY.POLICY_FEATURE_ACCESS.WRITE}
         >
             <ScreenWrapper
                 testID="WorkspaceCardSettingsPage"
diff --git a/src/pages/workspace/expensifyCard/WorkspaceExpensifyCardAddWorkEmailPage.tsx b/src/pages/workspace/expensifyCard/WorkspaceExpensifyCardAddWorkEmailPage.tsx
index 0122e26cadfb..006eda5b3914 100644
--- a/src/pages/workspace/expensifyCard/WorkspaceExpensifyCardAddWorkEmailPage.tsx
+++ b/src/pages/workspace/expensifyCard/WorkspaceExpensifyCardAddWorkEmailPage.tsx
@@ -122,6 +122,8 @@ function WorkspaceExpensifyCardAddWorkEmailPage({route}: WorkspaceExpensifyCardA
         <AccessOrNotFoundWrapper
             policyID={policyID}
             featureName={CONST.POLICY.MORE_FEATURES.ARE_EXPENSIFY_CARDS_ENABLED}
+            policyFeature={CONST.POLICY.POLICY_FEATURE.EXPENSIFY_CARD}
+            policyFeatureAccess={CONST.POLICY.POLICY_FEATURE_ACCESS.WRITE}
         >
             <ScreenWrapper
                 testID="WorkspaceExpensifyCardAddWorkEmailPage"
diff --git a/src/pages/workspace/expensifyCard/WorkspaceExpensifyCardBankAccounts.tsx b/src/pages/workspace/expensifyCard/WorkspaceExpensifyCardBankAccounts.tsx
index 1b2d2afb3f38..21d8334abff9 100644
--- a/src/pages/workspace/expensifyCard/WorkspaceExpensifyCardBankAccounts.tsx
+++ b/src/pages/workspace/expensifyCard/WorkspaceExpensifyCardBankAccounts.tsx
@@ -8,7 +8,6 @@ import getBankIcon from '@components/Icon/BankIcons';
 import MenuItem from '@components/MenuItem';
 import ScreenWrapper from '@components/ScreenWrapper';
 import Text from '@components/Text';
-import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails';
 import useDefaultFundID from '@hooks/useDefaultFundID';
 import useExpensifyCardUkEuSupported from '@hooks/useExpensifyCardUkEuSupported';
 import {useMemoizedLazyExpensifyIcons} from '@hooks/useLazyAsset';
@@ -20,7 +19,6 @@ import {getLastFourDigits} from '@libs/BankAccountUtils';
 import {getEligibleBankAccountsForCard, getEligibleBankAccountsForUkEuCard} from '@libs/CardUtils';
 import createDynamicRoute from '@libs/Navigation/helpers/dynamicRoutesUtils/createDynamicRoute';
 import type {PlatformStackScreenProps} from '@libs/Navigation/PlatformStackNavigation/types';
-import {canMemberWrite} from '@libs/PolicyUtils';
 import Navigation from '@navigation/Navigation';
 import type {SettingsNavigatorParamList} from '@navigation/types';
 import AccessOrNotFoundWrapper from '@pages/workspace/AccessOrNotFoundWrapper';
@@ -41,8 +39,6 @@ function WorkspaceExpensifyCardBankAccounts({route}: WorkspaceExpensifyCardBankA
 
     const policyID = route?.params?.policyID;
     const policy = usePolicy(policyID);
-    const {login: currentUserLogin = ''} = useCurrentUserPersonalDetails();
-    const canWriteExpensifyCard = canMemberWrite(policy, currentUserLogin, CONST.POLICY.POLICY_FEATURE.EXPENSIFY_CARD);
 
     const isUkEuCurrencySupported = useExpensifyCardUkEuSupported(policyID);
 
@@ -122,7 +118,7 @@ function WorkspaceExpensifyCardBankAccounts({route}: WorkspaceExpensifyCardBankA
         }
         setIssueNewCardStepAndData({policyID, isChangeAssigneeDisabled: false});
         Navigation.dismissModal();
-        Navigation.navigate(createDynamicRoute(DYNAMIC_ROUTES.WORKSPACE_EXPENSIFY_CARD_ISSUE_NEW.path));
+        Navigation.navigate(createDynamicRoute(DYNAMIC_ROUTES.WORKSPACE_EXPENSIFY_CARD_ISSUE_NEW.path, ROUTES.WORKSPACE_EXPENSIFY_CARD.getRoute(policyID)));
     };
 
     const getHeaderButtonText = () => {
@@ -143,7 +139,7 @@ function WorkspaceExpensifyCardBankAccounts({route}: WorkspaceExpensifyCardBankA
             policyID={policyID}
             featureName={CONST.POLICY.MORE_FEATURES.ARE_EXPENSIFY_CARDS_ENABLED}
             policyFeature={CONST.POLICY.POLICY_FEATURE.EXPENSIFY_CARD}
-            shouldBeBlocked={!canWriteExpensifyCard}
+            policyFeatureAccess={CONST.POLICY.POLICY_FEATURE_ACCESS.WRITE}
         >
             <ScreenWrapper
                 testID="WorkspaceExpensifyCardBankAccounts"
diff --git a/src/pages/workspace/expensifyCard/WorkspaceExpensifyCardFeedSelectorPage.tsx b/src/pages/workspace/expensifyCard/WorkspaceExpensifyCardFeedSelectorPage.tsx
index 8c00528d2363..28e3c44ee351 100644
--- a/src/pages/workspace/expensifyCard/WorkspaceExpensifyCardFeedSelectorPage.tsx
+++ b/src/pages/workspace/expensifyCard/WorkspaceExpensifyCardFeedSelectorPage.tsx
@@ -104,7 +104,7 @@ function WorkspaceExpensifyCardFeedSelectorPage({route}: WorkspaceExpensifyCardF
         }
         updateSelectedExpensifyCardFeed(issueCardFundID, policyID);
         setIssueNewCardStepAndData({policyID, isChangeAssigneeDisabled: false});
-        Navigation.navigate(createDynamicRoute(DYNAMIC_ROUTES.WORKSPACE_EXPENSIFY_CARD_ISSUE_NEW.path));
+        Navigation.navigate(createDynamicRoute(DYNAMIC_ROUTES.WORKSPACE_EXPENSIFY_CARD_ISSUE_NEW.path, ROUTES.WORKSPACE_EXPENSIFY_CARD.getRoute(policyID)));
     };
 
     /** When there is no primary feed for this workspace, mirror empty-state flow: bank account / new program setup (same as WORKSPACE_EXPENSIFY_CARD_BANK_ACCOUNT). */
diff --git a/src/pages/workspace/expensifyCard/WorkspaceExpensifyCardListPage.tsx b/src/pages/workspace/expensifyCard/WorkspaceExpensifyCardListPage.tsx
index 2f63dd030ea9..f4b03d004015 100644
--- a/src/pages/workspace/expensifyCard/WorkspaceExpensifyCardListPage.tsx
+++ b/src/pages/workspace/expensifyCard/WorkspaceExpensifyCardListPage.tsx
@@ -165,7 +165,7 @@ function WorkspaceExpensifyCardListPage({route, cardsList, fundID}: WorkspaceExp
             return;
         }
         setIssueNewCardStepAndData({policyID, isChangeAssigneeDisabled: false});
-        Navigation.navigate(createDynamicRoute(DYNAMIC_ROUTES.WORKSPACE_EXPENSIFY_CARD_ISSUE_NEW.path));
+        Navigation.navigate(createDynamicRoute(DYNAMIC_ROUTES.WORKSPACE_EXPENSIFY_CARD_ISSUE_NEW.path, ROUTES.WORKSPACE_EXPENSIFY_CARD.getRoute(policyID)));
     };
     const secondaryActions = canWriteExpensifyCard
         ? [
diff --git a/src/pages/workspace/expensifyCard/WorkspaceExpensifyCardPageEmptyState.tsx b/src/pages/workspace/expensifyCard/WorkspaceExpensifyCardPageEmptyState.tsx
index d90179f83ca4..1dedcb23d1b0 100644
--- a/src/pages/workspace/expensifyCard/WorkspaceExpensifyCardPageEmptyState.tsx
+++ b/src/pages/workspace/expensifyCard/WorkspaceExpensifyCardPageEmptyState.tsx
@@ -7,6 +7,7 @@ import {useLockedAccountActions, useLockedAccountState} from '@components/Locked
 import {ModalActions} from '@components/Modal/Global/ModalContext';
 import Text from '@components/Text';
 import useConfirmModal from '@hooks/useConfirmModal';
+import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails';
 import useExpensifyCardUkEuSupported from '@hooks/useExpensifyCardUkEuSupported';
 import {useMemoizedLazyIllustrations} from '@hooks/useLazyAsset';
 import useLocalize from '@hooks/useLocalize';
@@ -21,6 +22,7 @@ import {getEligibleBankAccountsForCard, getEligibleBankAccountsForUkEuCard} from
 import createDynamicRoute from '@libs/Navigation/helpers/dynamicRoutesUtils/createDynamicRoute';
 import type {PlatformStackScreenProps} from '@libs/Navigation/PlatformStackNavigation/types';
 import type {WorkspaceSplitNavigatorParamList} from '@libs/Navigation/types';
+import {canEditWorkspaceSettings} from '@libs/PolicyUtils';
 import {hasInProgressUSDVBBA} from '@libs/ReimbursementAccountUtils';
 import Navigation from '@navigation/Navigation';
 import type {WithPolicyAndFullscreenLoadingProps} from '@pages/workspace/withPolicyAndFullscreenLoading';
@@ -52,6 +54,7 @@ function WorkspaceExpensifyCardPageEmptyState({route, policy}: WorkspaceExpensif
     const {isAccountLocked} = useLockedAccountState();
     const {showLockedAccountModal} = useLockedAccountActions();
     const {canWrite: canWriteExpensifyCard, showReadOnlyModal} = usePolicyFeatureWriteAccess(policy, CONST.POLICY.POLICY_FEATURE.EXPENSIFY_CARD);
+    const {login: currentUserLogin = ''} = useCurrentUserPersonalDetails();
 
     // Dismiss the "Update to USD" modal if the currency changes to USD externally (e.g. from another device)
     const isCurrencyModalOpen = useRef(false);
@@ -67,9 +70,12 @@ function WorkspaceExpensifyCardPageEmptyState({route, policy}: WorkspaceExpensif
     const isUkEuCurrencySupported = useExpensifyCardUkEuSupported(policy?.id);
 
     const eligibleBankAccounts = isUkEuCurrencySupported ? getEligibleBankAccountsForUkEuCard(bankAccountList, policy?.outputCurrency) : getEligibleBankAccountsForCard(bankAccountList);
+    const shouldStartBankAccountSetup = !eligibleBankAccounts.length || isSetupUnfinished;
+    const canStartBankAccountSetup = canEditWorkspaceSettings(policy, currentUserLogin);
+    const shouldDisableCTA = !canWriteExpensifyCard || (shouldStartBankAccountSetup && !canStartBankAccountSetup);
 
     const startFlow = () => {
-        if (!eligibleBankAccounts.length || isSetupUnfinished) {
+        if (shouldStartBankAccountSetup) {
             Navigation.navigate(
                 ROUTES.BANK_ACCOUNT_WITH_STEP_TO_OPEN.getRoute({
                     policyID: policy?.id,
@@ -78,7 +84,7 @@ function WorkspaceExpensifyCardPageEmptyState({route, policy}: WorkspaceExpensif
             );
         } else if (policy?.id) {
             clearIssueNewCardFormData();
-            Navigation.navigate(createDynamicRoute(DYNAMIC_ROUTES.WORKSPACE_EXPENSIFY_CARD_SELECT_FEED.path));
+            Navigation.navigate(createDynamicRoute(DYNAMIC_ROUTES.WORKSPACE_EXPENSIFY_CARD_SELECT_FEED.path, ROUTES.WORKSPACE_EXPENSIFY_CARD.getRoute(policy.id)));
         }
     };
 
@@ -137,6 +143,10 @@ function WorkspaceExpensifyCardPageEmptyState({route, policy}: WorkspaceExpensif
                             showReadOnlyModal();
                             return;
                         }
+                        if (shouldStartBankAccountSetup && !canStartBankAccountSetup) {
+                            showReadOnlyModal();
+                            return;
+                        }
                         if (isDelegateAccessRestricted) {
                             showDelegateNoAccessModal();
                             return;
@@ -155,8 +165,8 @@ function WorkspaceExpensifyCardPageEmptyState({route, policy}: WorkspaceExpensif
                     illustration={illustrations.ExpensifyCardIllustration}
                     illustrationStyle={styles.expensifyCardIllustrationContainer}
                     titleStyles={styles.textHeadlineH1}
-                    buttonInnerStyles={!canWriteExpensifyCard ? styles.buttonOpacityDisabled : undefined}
-                    buttonHoverStyles={!canWriteExpensifyCard ? styles.buttonOpacityDisabled : undefined}
+                    buttonInnerStyles={shouldDisableCTA ? styles.buttonOpacityDisabled : undefined}
+                    buttonHoverStyles={shouldDisableCTA ? styles.buttonOpacityDisabled : undefined}
                 />
             </View>
             <View style={[shouldUseNarrowLayout ? styles.workspaceSectionMobile : styles.workspaceSection]}>
diff --git a/src/pages/workspace/expensifyCard/WorkspaceExpensifyCardVerifyWorkAccountPage.tsx b/src/pages/workspace/expensifyCard/WorkspaceExpensifyCardVerifyWorkAccountPage.tsx
index a67522e5d04f..9ba5f375b570 100644
--- a/src/pages/workspace/expensifyCard/WorkspaceExpensifyCardVerifyWorkAccountPage.tsx
+++ b/src/pages/workspace/expensifyCard/WorkspaceExpensifyCardVerifyWorkAccountPage.tsx
@@ -8,6 +8,7 @@ import {getMicroSecondOnyxErrorWithTranslationKey} from '@libs/ErrorUtils';
 import Navigation from '@navigation/Navigation';
 import type {PlatformStackScreenProps} from '@navigation/PlatformStackNavigation/types';
 import type {SettingsNavigatorParamList} from '@navigation/types';
+import AccessOrNotFoundWrapper from '@pages/workspace/AccessOrNotFoundWrapper';
 import {linkCardFeedToPolicy} from '@userActions/CompanyCards';
 import {clearGetAccessiblePoliciesErrors, getAccessiblePolicies} from '@userActions/Policy/Policy';
 import {resendValidateCode} from '@userActions/User';
@@ -19,7 +20,9 @@ import type {Errors} from '@src/types/onyx/OnyxCommon';
 
 type WorkspaceExpensifyCardVerifyWorkAccountPageProps = PlatformStackScreenProps<SettingsNavigatorParamList, typeof SCREENS.WORKSPACE.EXPENSIFY_CARD_VERIFY_WORK_EMAIL>;
 
-function WorkspaceExpensifyCardVerifyWorkAccountPage({route}: WorkspaceExpensifyCardVerifyWorkAccountPageProps) {
+type WorkspaceExpensifyCardVerifyWorkAccountPageContentProps = Pick<WorkspaceExpensifyCardVerifyWorkAccountPageProps, 'route'>;
+
+function WorkspaceExpensifyCardVerifyWorkAccountPageContent({route}: WorkspaceExpensifyCardVerifyWorkAccountPageContentProps) {
     const {policyID, fundID} = route.params;
     const {translate} = useLocalize();
     const [loginList] = useOnyx(ONYXKEYS.LOGIN_LIST);
@@ -77,4 +80,19 @@ function WorkspaceExpensifyCardVerifyWorkAccountPage({route}: WorkspaceExpensify
     );
 }
 
+function WorkspaceExpensifyCardVerifyWorkAccountPage({route}: WorkspaceExpensifyCardVerifyWorkAccountPageProps) {
+    const {policyID} = route.params;
+
+    return (
+        <AccessOrNotFoundWrapper
+            policyID={policyID}
+            featureName={CONST.POLICY.MORE_FEATURES.ARE_EXPENSIFY_CARDS_ENABLED}
+            policyFeature={CONST.POLICY.POLICY_FEATURE.EXPENSIFY_CARD}
+            policyFeatureAccess={CONST.POLICY.POLICY_FEATURE_ACCESS.WRITE}
+        >
+            <WorkspaceExpensifyCardVerifyWorkAccountPageContent route={route} />
+        </AccessOrNotFoundWrapper>
+    );
+}
+
 export default WorkspaceExpensifyCardVerifyWorkAccountPage;
diff --git a/src/pages/workspace/expensifyCard/WorkspaceSettlementFrequencyPage.tsx b/src/pages/workspace/expensifyCard/WorkspaceSettlementFrequencyPage.tsx
index 73e009e2da25..1d3dcbf85d13 100644
--- a/src/pages/workspace/expensifyCard/WorkspaceSettlementFrequencyPage.tsx
+++ b/src/pages/workspace/expensifyCard/WorkspaceSettlementFrequencyPage.tsx
@@ -73,6 +73,8 @@ function WorkspaceSettlementFrequencyPage({route}: WorkspaceSettlementFrequencyP
             policyID={policyID}
             shouldBeBlocked={isSettlementFrequencyBlocked}
             featureName={CONST.POLICY.MORE_FEATURES.ARE_EXPENSIFY_CARDS_ENABLED}
+            policyFeature={CONST.POLICY.POLICY_FEATURE.EXPENSIFY_CARD}
+            policyFeatureAccess={CONST.POLICY.POLICY_FEATURE_ACCESS.WRITE}
         >
             <ScreenWrapper
                 testID="WorkspaceSettlementFrequencyPage"
diff --git a/src/pages/workspace/expensifyCard/issueNew/DynamicIssueNewCardPage.tsx b/src/pages/workspace/expensifyCard/issueNew/DynamicIssueNewCardPage.tsx
index 69cb37a518d4..ae712023367f 100644
--- a/src/pages/workspace/expensifyCard/issueNew/DynamicIssueNewCardPage.tsx
+++ b/src/pages/workspace/expensifyCard/issueNew/DynamicIssueNewCardPage.tsx
@@ -147,9 +147,10 @@ function DynamicIssueNewCardPage({policy, route}: IssueNewCardPageProps) {
 
     return (
         <AccessOrNotFoundWrapper
-            accessVariants={[CONST.POLICY.ACCESS_VARIANTS.ADMIN, CONST.POLICY.ACCESS_VARIANTS.PAID]}
             policyID={policyID}
             featureName={CONST.POLICY.MORE_FEATURES.ARE_EXPENSIFY_CARDS_ENABLED}
+            policyFeature={CONST.POLICY.POLICY_FEATURE.EXPENSIFY_CARD}
+            policyFeatureAccess={CONST.POLICY.POLICY_FEATURE_ACCESS.WRITE}
         >
             {getCurrentStep()}
         </AccessOrNotFoundWrapper>
diff --git a/src/pages/workspace/expensifyCard/issueNew/IssueNewCardConfirmMagicCodePage.tsx b/src/pages/workspace/expensifyCard/issueNew/IssueNewCardConfirmMagicCodePage.tsx
index 727338e86a6f..2c15aad2bdb8 100644
--- a/src/pages/workspace/expensifyCard/issueNew/IssueNewCardConfirmMagicCodePage.tsx
+++ b/src/pages/workspace/expensifyCard/issueNew/IssueNewCardConfirmMagicCodePage.tsx
@@ -13,6 +13,7 @@ import {getLatestErrorMessageField} from '@libs/ErrorUtils';
 import Navigation from '@libs/Navigation/Navigation';
 import type {PlatformStackScreenProps} from '@libs/Navigation/PlatformStackNavigation/types';
 import type {SettingsNavigatorParamList} from '@libs/Navigation/types';
+import AccessOrNotFoundWrapper from '@pages/workspace/AccessOrNotFoundWrapper';
 import CONST from '@src/CONST';
 import ONYXKEYS from '@src/ONYXKEYS';
 import type {Route} from '@src/ROUTES';
@@ -68,17 +69,24 @@ function IssueNewCardConfirmMagicCodePage({route}: IssueNewCardConfirmMagicCodeP
     }, [backPath]);
 
     return (
-        <ValidateCodeActionContent
-            isLoading={issueNewCard?.isLoading}
-            title={translate('cardPage.validateCardTitle')}
-            descriptionPrimary={translate('cardPage.enterMagicCode', primaryLogin)}
-            sendValidateCode={() => requestValidateCodeAction()}
-            validateCodeActionErrorField={data?.cardType === CONST.EXPENSIFY_CARD.CARD_TYPE.PHYSICAL ? 'createExpensifyCard' : 'createAdminIssuedVirtualCard'}
-            handleSubmitForm={handleSubmit}
-            validateError={validateError}
-            clearError={() => clearIssueNewCardError(policyID)}
-            onClose={handleClose}
-        />
+        <AccessOrNotFoundWrapper
+            policyID={policyID}
+            featureName={CONST.POLICY.MORE_FEATURES.ARE_EXPENSIFY_CARDS_ENABLED}
+            policyFeature={CONST.POLICY.POLICY_FEATURE.EXPENSIFY_CARD}
+            policyFeatureAccess={CONST.POLICY.POLICY_FEATURE_ACCESS.WRITE}
+        >
+            <ValidateCodeActionContent
+                isLoading={issueNewCard?.isLoading}
+                title={translate('cardPage.validateCardTitle')}
+                descriptionPrimary={translate('cardPage.enterMagicCode', primaryLogin)}
+                sendValidateCode={() => requestValidateCodeAction()}
+                validateCodeActionErrorField={data?.cardType === CONST.EXPENSIFY_CARD.CARD_TYPE.PHYSICAL ? 'createExpensifyCard' : 'createAdminIssuedVirtualCard'}
+                handleSubmitForm={handleSubmit}
+                validateError={validateError}
+                clearError={() => clearIssueNewCardError(policyID)}
+                onClose={handleClose}
+            />
+        </AccessOrNotFoundWrapper>
     );
 }
 
diff --git a/src/pages/workspace/expensifyCard/issueNew/spendRules/SpendRuleCategoryPage.tsx b/src/pages/workspace/expensifyCard/issueNew/spendRules/SpendRuleCategoryPage.tsx
index d86618d85ce9..c5350c8dfb20 100644
--- a/src/pages/workspace/expensifyCard/issueNew/spendRules/SpendRuleCategoryPage.tsx
+++ b/src/pages/workspace/expensifyCard/issueNew/spendRules/SpendRuleCategoryPage.tsx
@@ -4,6 +4,8 @@ import useOnyx from '@hooks/useOnyx';
 import {setIssueNewCardData} from '@libs/actions/Card';
 import type {PlatformStackScreenProps} from '@libs/Navigation/PlatformStackNavigation/types';
 import type {SettingsNavigatorParamList} from '@libs/Navigation/types';
+import AccessOrNotFoundWrapper from '@pages/workspace/AccessOrNotFoundWrapper';
+import CONST from '@src/CONST';
 import ONYXKEYS from '@src/ONYXKEYS';
 import type SCREENS from '@src/SCREENS';
 import type {SpendRuleCategory} from '@src/types/form/SpendRuleForm';
@@ -21,9 +23,16 @@ export default function SpendRuleCategoryEditPage({route}: SpendRuleCategoryEdit
     };
 
     return (
-        <SpendRuleCategoryBase
-            categories={categories}
-            onCategoriesChange={handleCategoriesChange}
-        />
+        <AccessOrNotFoundWrapper
+            policyID={policyID}
+            featureName={CONST.POLICY.MORE_FEATURES.ARE_EXPENSIFY_CARDS_ENABLED}
+            policyFeature={CONST.POLICY.POLICY_FEATURE.EXPENSIFY_CARD}
+            policyFeatureAccess={CONST.POLICY.POLICY_FEATURE_ACCESS.WRITE}
+        >
+            <SpendRuleCategoryBase
+                categories={categories}
+                onCategoriesChange={handleCategoriesChange}
+            />
+        </AccessOrNotFoundWrapper>
     );
 }
diff --git a/src/pages/workspace/expensifyCard/issueNew/spendRules/SpendRuleMaxAmountPage.tsx b/src/pages/workspace/expensifyCard/issueNew/spendRules/SpendRuleMaxAmountPage.tsx
index be76686b73a6..88d78a083ba4 100644
--- a/src/pages/workspace/expensifyCard/issueNew/spendRules/SpendRuleMaxAmountPage.tsx
+++ b/src/pages/workspace/expensifyCard/issueNew/spendRules/SpendRuleMaxAmountPage.tsx
@@ -4,6 +4,7 @@ import useOnyx from '@hooks/useOnyx';
 import {setIssueNewCardData} from '@libs/actions/Card';
 import type {PlatformStackScreenProps} from '@libs/Navigation/PlatformStackNavigation/types';
 import type {SettingsNavigatorParamList} from '@libs/Navigation/types';
+import AccessOrNotFoundWrapper from '@pages/workspace/AccessOrNotFoundWrapper';
 import CONST from '@src/CONST';
 import ONYXKEYS from '@src/ONYXKEYS';
 import type SCREENS from '@src/SCREENS';
@@ -22,11 +23,18 @@ export default function SpendRuleMaxAmountPage({route}: SpendRuleMaxAmountPagePr
     };
 
     return (
-        <SpendRuleMaxAmountBase
+        <AccessOrNotFoundWrapper
             policyID={policyID}
-            maxAmount={defaultValue}
-            currencyCode={selectedCurrency}
-            onMaxAmountChange={handleMaxAmountChange}
-        />
+            featureName={CONST.POLICY.MORE_FEATURES.ARE_EXPENSIFY_CARDS_ENABLED}
+            policyFeature={CONST.POLICY.POLICY_FEATURE.EXPENSIFY_CARD}
+            policyFeatureAccess={CONST.POLICY.POLICY_FEATURE_ACCESS.WRITE}
+        >
+            <SpendRuleMaxAmountBase
+                policyID={policyID}
+                maxAmount={defaultValue}
+                currencyCode={selectedCurrency}
+                onMaxAmountChange={handleMaxAmountChange}
+            />
+        </AccessOrNotFoundWrapper>
     );
 }
diff --git a/src/pages/workspace/expensifyCard/issueNew/spendRules/SpendRuleMerchantEditPage.tsx b/src/pages/workspace/expensifyCard/issueNew/spendRules/SpendRuleMerchantEditPage.tsx
index 2f1811b53616..1f6e28b424fd 100644
--- a/src/pages/workspace/expensifyCard/issueNew/spendRules/SpendRuleMerchantEditPage.tsx
+++ b/src/pages/workspace/expensifyCard/issueNew/spendRules/SpendRuleMerchantEditPage.tsx
@@ -4,6 +4,8 @@ import useOnyx from '@hooks/useOnyx';
 import {setIssueNewCardData} from '@libs/actions/Card';
 import type {PlatformStackScreenProps} from '@libs/Navigation/PlatformStackNavigation/types';
 import type {SettingsNavigatorParamList} from '@libs/Navigation/types';
+import AccessOrNotFoundWrapper from '@pages/workspace/AccessOrNotFoundWrapper';
+import CONST from '@src/CONST';
 import ONYXKEYS from '@src/ONYXKEYS';
 import type SCREENS from '@src/SCREENS';
 
@@ -17,14 +19,21 @@ export default function SpendRuleMerchantEditPage({route}: SpendRuleMerchantEdit
     const merchantMatchTypes = issueNewCardForm?.data.spendRuleValue?.merchantMatchTypes ?? [];
 
     return (
-        <SpendRuleMerchantEditBase
+        <AccessOrNotFoundWrapper
             policyID={policyID}
-            merchantIndex={merchantIndex}
-            merchantMatchTypes={merchantMatchTypes}
-            merchantNames={merchantNames}
-            onMerchantDataChange={(newMerchantNames, newMerchantMatchTypes) => {
-                setIssueNewCardData(policyID, {spendRuleValue: {merchantNames: newMerchantNames, merchantMatchTypes: newMerchantMatchTypes}});
-            }}
-        />
+            featureName={CONST.POLICY.MORE_FEATURES.ARE_EXPENSIFY_CARDS_ENABLED}
+            policyFeature={CONST.POLICY.POLICY_FEATURE.EXPENSIFY_CARD}
+            policyFeatureAccess={CONST.POLICY.POLICY_FEATURE_ACCESS.WRITE}
+        >
+            <SpendRuleMerchantEditBase
+                policyID={policyID}
+                merchantIndex={merchantIndex}
+                merchantMatchTypes={merchantMatchTypes}
+                merchantNames={merchantNames}
+                onMerchantDataChange={(newMerchantNames, newMerchantMatchTypes) => {
+                    setIssueNewCardData(policyID, {spendRuleValue: {merchantNames: newMerchantNames, merchantMatchTypes: newMerchantMatchTypes}});
+                }}
+            />
+        </AccessOrNotFoundWrapper>
     );
 }
diff --git a/src/pages/workspace/expensifyCard/issueNew/spendRules/SpendRuleMerchantsPage.tsx b/src/pages/workspace/expensifyCard/issueNew/spendRules/SpendRuleMerchantsPage.tsx
index 0a2dfe21423d..de812a119d02 100644
--- a/src/pages/workspace/expensifyCard/issueNew/spendRules/SpendRuleMerchantsPage.tsx
+++ b/src/pages/workspace/expensifyCard/issueNew/spendRules/SpendRuleMerchantsPage.tsx
@@ -4,6 +4,7 @@ import useOnyx from '@hooks/useOnyx';
 import createDynamicRoute from '@libs/Navigation/helpers/dynamicRoutesUtils/createDynamicRoute';
 import type {PlatformStackScreenProps} from '@libs/Navigation/PlatformStackNavigation/types';
 import type {SettingsNavigatorParamList} from '@libs/Navigation/types';
+import AccessOrNotFoundWrapper from '@pages/workspace/AccessOrNotFoundWrapper';
 import CONST from '@src/CONST';
 import ONYXKEYS from '@src/ONYXKEYS';
 import {DYNAMIC_ROUTES} from '@src/ROUTES';
@@ -20,12 +21,19 @@ export default function SpendRuleMerchantsPage({route}: SpendRuleMerchantsPagePr
     const restrictionAction = issueNewCardForm?.data.spendRuleValue?.restrictionAction ?? CONST.SPEND_RULES.ACTION.ALLOW;
 
     return (
-        <SpendRuleMerchantsBase
+        <AccessOrNotFoundWrapper
             policyID={policyID}
-            action={restrictionAction}
-            merchantNames={merchantNames}
-            merchantMatchTypes={merchantMatchTypes}
-            getEditMerchantRoute={(merchantIndex) => createDynamicRoute(DYNAMIC_ROUTES.WORKSPACE_EXPENSIFY_CARD_ISSUE_NEW_SPEND_RULE_MERCHANT_EDIT.getRoute(merchantIndex))}
-        />
+            featureName={CONST.POLICY.MORE_FEATURES.ARE_EXPENSIFY_CARDS_ENABLED}
+            policyFeature={CONST.POLICY.POLICY_FEATURE.EXPENSIFY_CARD}
+            policyFeatureAccess={CONST.POLICY.POLICY_FEATURE_ACCESS.WRITE}
+        >
+            <SpendRuleMerchantsBase
+                policyID={policyID}
+                action={restrictionAction}
+                merchantNames={merchantNames}
+                merchantMatchTypes={merchantMatchTypes}
+                getEditMerchantRoute={(merchantIndex) => createDynamicRoute(DYNAMIC_ROUTES.WORKSPACE_EXPENSIFY_CARD_ISSUE_NEW_SPEND_RULE_MERCHANT_EDIT.getRoute(merchantIndex))}
+            />
+        </AccessOrNotFoundWrapper>
     );
 }
diff --git a/src/pages/workspace/expensifyCard/issueNew/spendRules/SpendRuleSelectionPage.tsx b/src/pages/workspace/expensifyCard/issueNew/spendRules/SpendRuleSelectionPage.tsx
index 77441cf1f5ca..79b5ca17a581 100644
--- a/src/pages/workspace/expensifyCard/issueNew/spendRules/SpendRuleSelectionPage.tsx
+++ b/src/pages/workspace/expensifyCard/issueNew/spendRules/SpendRuleSelectionPage.tsx
@@ -112,6 +112,8 @@ function SpendRuleSelectionPage({route}: SpendRuleSelectionPageProps) {
         <AccessOrNotFoundWrapper
             policyID={policyID}
             featureName={CONST.POLICY.MORE_FEATURES.ARE_EXPENSIFY_CARDS_ENABLED}
+            policyFeature={CONST.POLICY.POLICY_FEATURE.EXPENSIFY_CARD}
+            policyFeatureAccess={CONST.POLICY.POLICY_FEATURE_ACCESS.WRITE}
         >
             <ScreenWrapper
                 testID="SpendRuleSelectionPage"
diff --git a/src/pages/workspace/members/ImportedMembersPage.tsx b/src/pages/workspace/members/ImportedMembersPage.tsx
index 1cc0d57d8a14..df1f9cc00ecc 100644
--- a/src/pages/workspace/members/ImportedMembersPage.tsx
+++ b/src/pages/workspace/members/ImportedMembersPage.tsx
@@ -94,14 +94,15 @@ function ImportedMembersPage({route}: ImportedMembersPageProps) {
         const columns = Object.values(spreadsheet?.columns ?? {});
 
         const membersRolesColumn = columns.findIndex((column) => column === CONST.CSV_IMPORT_COLUMNS.ROLE);
-        const hasAuditorRole =
+        const hasControlPolicyOnlyRole =
             membersRolesColumn !== -1 &&
-            spreadsheet?.data
-                ?.at(membersRolesColumn)
-                ?.some((role, index) => (containsHeader ? spreadsheet?.data?.at(membersRolesColumn)?.at(index + 1) : (role ?? '')) === CONST.POLICY.ROLE.AUDITOR);
+            spreadsheet?.data?.at(membersRolesColumn)?.some((role, index) => {
+                const memberRole = containsHeader ? spreadsheet?.data?.at(membersRolesColumn)?.at(index + 1) : (role ?? '');
+                return memberRole === CONST.POLICY.ROLE.AUDITOR || memberRole === CONST.POLICY.ROLE.CARD_ADMIN;
+            });
 
-        if (hasAuditorRole && !isControlPolicy(policy)) {
-            Navigation.navigate(ROUTES.WORKSPACE_UPGRADE.getRoute(route.params.policyID, CONST.UPGRADE_FEATURE_INTRO_MAPPING.auditor.alias, Navigation.getActiveRoute()));
+        if (hasControlPolicyOnlyRole && !isControlPolicy(policy)) {
+            Navigation.navigate(ROUTES.WORKSPACE_UPGRADE.getRoute(route.params.policyID, CONST.UPGRADE_FEATURE_INTRO_MAPPING.roles.alias, Navigation.getActiveRoute()));
             return;
         }
 

From bb6afdd1ffb3bed870453d00b75e6bc302d97abb Mon Sep 17 00:00:00 2001
From: Rayane <77965000+rayane-d@users.noreply.github.com>
Date: Fri, 5 Jun 2026 02:07:31 +0100
Subject: [PATCH 127/435] fix type error

---
 tests/unit/OptionsListUtilsTest.tsx | 1 -
 1 file changed, 1 deletion(-)

diff --git a/tests/unit/OptionsListUtilsTest.tsx b/tests/unit/OptionsListUtilsTest.tsx
index 35f5ae357473..f647d84e8a41 100644
--- a/tests/unit/OptionsListUtilsTest.tsx
+++ b/tests/unit/OptionsListUtilsTest.tsx
@@ -5350,7 +5350,6 @@ describe('OptionsListUtils', () => {
                         mccGroupName: 'Airlines',
                         oldCategory: 'Insurance',
                         newCategory: 'Travel',
-                        currentUserLogin: CURRENT_USER_EMAIL,
                     },
                 };
                 await Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${report.reportID}`, {

From 1afabf3f9ede0cb37d8cdd9df16c3463e8239937 Mon Sep 17 00:00:00 2001
From: ShridharGoel <35566748+ShridharGoel@users.noreply.github.com>
Date: Fri, 5 Jun 2026 10:27:34 +0530
Subject: [PATCH 128/435] Remove unrelated Onyx updates change

---
 src/libs/actions/OnyxUpdates.ts | 58 +--------------------------------
 1 file changed, 1 insertion(+), 57 deletions(-)

diff --git a/src/libs/actions/OnyxUpdates.ts b/src/libs/actions/OnyxUpdates.ts
index 5318c4388b67..47df0ee60635 100644
--- a/src/libs/actions/OnyxUpdates.ts
+++ b/src/libs/actions/OnyxUpdates.ts
@@ -28,52 +28,6 @@ let pusherEventsPromise = Promise.resolve();
 
 let airshipEventsPromise = Promise.resolve();
 
-// The microsecond-keyed Errors shape produced by getMicroSecondOnyxErrorWithTranslationKey
-// and getMicroSecondOnyxErrorWithMessage: Record<string, string | null>. We deliberately
-// skip other "errors" shapes (arrays, {translationKey: ...} objects, etc.).
-function isMicroSecondErrorsShape(value: unknown): value is Record<string, string | null> {
-    if (!value || typeof value !== 'object' || Array.isArray(value)) {
-        return false;
-    }
-    const entries = Object.values(value as Record<string, unknown>);
-    if (entries.length === 0) {
-        return false;
-    }
-    return entries.every((v) => v === null || typeof v === 'string');
-}
-
-function substituteBackendMessage(node: unknown, message: string): unknown {
-    if (!node || typeof node !== 'object') {
-        return node;
-    }
-    if (Array.isArray(node)) {
-        return node.map((item) => substituteBackendMessage(item, message));
-    }
-    const result: Record<string, unknown> = {};
-    for (const [key, value] of Object.entries(node as Record<string, unknown>)) {
-        if (key === 'errors' && isMicroSecondErrorsShape(value)) {
-            const replaced: Record<string, string | null> = {};
-            for (const [microKey, microValue] of Object.entries(value)) {
-                // Preserve null entries (which clear a previous error); only substitute string values.
-                replaced[microKey] = microValue === null ? null : message;
-            }
-            result[key] = replaced;
-        } else {
-            result[key] = substituteBackendMessage(value, message);
-        }
-    }
-    return result;
-}
-
-function applyBackendMessageToFailureData<TKey extends OnyxKey>(failureData: Array<OnyxUpdate<TKey>>, message: string): Array<OnyxUpdate<TKey>> {
-    return failureData.map((entry) => {
-        if (!entry || typeof entry !== 'object' || !('value' in entry) || !entry.value || typeof entry.value !== 'object') {
-            return entry;
-        }
-        return {...entry, value: substituteBackendMessage(entry.value, message) as typeof entry.value};
-    });
-}
-
 function applyHTTPSOnyxUpdates<TKey extends OnyxKey>(request: Request<TKey>, response: Response<TKey>, lastUpdateID: number) {
     Log.info('[OnyxUpdateManager] Applying https update', false, {lastUpdateID});
     // For most requests we can immediately update Onyx. For write requests we queue the updates and apply them after the sequential queue has flushed to prevent a replay effect in
@@ -108,17 +62,7 @@ function applyHTTPSOnyxUpdates<TKey extends OnyxKey>(request: Request<TKey>, res
                     requestData: request.data,
                 });
 
-                // jsonCode 666 (EXP_ERROR) is the backend's "ExpError with a user-facing message" contract.
-                // Substitute the hardcoded translation-key string baked into request.failureData with the
-                // backend's response.message so the actual reason renders in the existing RedBrickRoad UI
-                // for every command routed through API.write — not just the handful that bypass the
-                // sequential queue via makeRequestWithSideEffects.
-                const failureDataToApply =
-                    response.jsonCode === CONST.JSON_CODE.EXP_ERROR && typeof response.message === 'string' && response.message.length > 0
-                        ? applyBackendMessageToFailureData(request.failureData, response.message)
-                        : request.failureData;
-
-                return updateHandler(failureDataToApply);
+                return updateHandler(request.failureData);
             }
             return Promise.resolve();
         })

From a47ceeb1c22b3aa318bf69b0739c4ff735ca9d51 Mon Sep 17 00:00:00 2001
From: ShridharGoel <35566748+ShridharGoel@users.noreply.github.com>
Date: Fri, 5 Jun 2026 10:35:18 +0530
Subject: [PATCH 129/435] Remove unused Card Admin helper

---
 src/libs/PolicyUtils.ts | 5 -----
 1 file changed, 5 deletions(-)

diff --git a/src/libs/PolicyUtils.ts b/src/libs/PolicyUtils.ts
index c4d547e09c14..423644893612 100644
--- a/src/libs/PolicyUtils.ts
+++ b/src/libs/PolicyUtils.ts
@@ -203,10 +203,6 @@ function canMemberWrite(policy: OnyxInputOrEntry<Policy>, login: string, feature
     return hasPolicyFeaturePermission(policy, login, feature, CONST.POLICY.POLICY_FEATURE_ACCESS.WRITE);
 }
 
-function isPolicyCardAdmin(policy: OnyxInputOrEntry<Policy>, login: string): boolean {
-    return canMemberWrite(policy, login, CONST.POLICY.POLICY_FEATURE.EXPENSIFY_CARD);
-}
-
 /**
  * Checks if we have any errors stored within the policy?.employeeList. Determines whether we should show a red brick road error or not.
  */
@@ -2566,7 +2562,6 @@ export {
     canAccessSubmitWorkspaceFeatures,
     getRulesDocumentSourceURL,
     isSubmitPolicy,
-    isPolicyCardAdmin,
 };
 
 export type {MemberEmailsToAccountIDs, PolicyFeature, PolicyFeatureAccess};

From a8640ab9b3fa1b7517743d15c4962731575d5fa4 Mon Sep 17 00:00:00 2001
From: ShridharGoel <35566748+ShridharGoel@users.noreply.github.com>
Date: Fri, 5 Jun 2026 10:40:46 +0530
Subject: [PATCH 130/435] Fix refresh card feed connection test

---
 tests/unit/RefreshCardFeedConnectionPageTest.tsx | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/tests/unit/RefreshCardFeedConnectionPageTest.tsx b/tests/unit/RefreshCardFeedConnectionPageTest.tsx
index 8796f542a701..44141978541f 100644
--- a/tests/unit/RefreshCardFeedConnectionPageTest.tsx
+++ b/tests/unit/RefreshCardFeedConnectionPageTest.tsx
@@ -10,6 +10,11 @@ import waitForBatchedUpdates from '../utils/waitForBatchedUpdates';
 // Bypass the HOC and render the inner component directly
 jest.mock('@pages/workspace/withPolicyAndFullscreenLoading', () => (Component: React.ComponentType) => Component);
 
+jest.mock('@pages/workspace/AccessOrNotFoundWrapper', () => ({
+    __esModule: true,
+    default: ({children}: {children: React.ReactNode}) => children,
+}));
+
 const mockCloseRHPFlow = jest.fn();
 
 jest.mock('@hooks/useCardFeeds', () => ({

From ccbdacef183b3c4d172e9ddff8a95b574f068e1f Mon Sep 17 00:00:00 2001
From: ShridharGoel <35566748+ShridharGoel@users.noreply.github.com>
Date: Fri, 5 Jun 2026 10:42:24 +0530
Subject: [PATCH 131/435] Restore lowercase role changelog text

---
 src/languages/en.ts            |  2 +-
 src/libs/ReportActionsUtils.ts | 10 +++++-----
 2 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/src/languages/en.ts b/src/languages/en.ts
index e22b1dadd73f..d3ec03c53514 100644
--- a/src/languages/en.ts
+++ b/src/languages/en.ts
@@ -8434,7 +8434,7 @@ const translations = {
                 plaidBalanceFailure: ({maskedAccountNumber, walletRoute}: {maskedAccountNumber: string; walletRoute: string}) =>
                     `the Plaid connection to your business bank account is broken. Please <a href='${walletRoute}'>reconnect your bank account ${maskedAccountNumber}</a> so you can continue to use your Expensify Cards.`,
                 addEmployee: (email: string, role: string, didJoinPolicy?: boolean) => {
-                    const article = role === 'Auditor' ? 'an' : 'a';
+                    const article = role.toLowerCase() === 'auditor' ? 'an' : 'a';
                     return didJoinPolicy ? `${email} joined via the workspace invite link` : `added ${email} as ${article} ${role}`;
                 },
                 updateRole: ({email, currentRole, newRole}: UpdateRoleParams) => `updated the role of ${email} to ${newRole} (previously ${currentRole})`,
diff --git a/src/libs/ReportActionsUtils.ts b/src/libs/ReportActionsUtils.ts
index bc3cad2ac032..4b34fbaca017 100644
--- a/src/libs/ReportActionsUtils.ts
+++ b/src/libs/ReportActionsUtils.ts
@@ -2807,7 +2807,7 @@ function getPolicyChangeLogAddEmployeeMessage(translate: LocalizedTranslate, rep
 
     const originalMessage = getOriginalMessage(reportAction);
     const email = originalMessage?.email ?? '';
-    const role = translate('workspace.common.roleName', originalMessage?.role ?? '');
+    const role = translate('workspace.common.roleName', originalMessage?.role ?? '').toLowerCase();
     const formattedEmail = formatPhoneNumber(email);
     return translate('report.actions.type.addEmployee', formattedEmail, role, originalMessage?.didJoinPolicy);
 }
@@ -2830,8 +2830,8 @@ function buildPolicyChangeLogUpdateEmployeeSingleFieldMessage(translate: Localiz
         return translate(translationKey, email, stringNewValue, stringOldValue);
     }
 
-    const newRole = translate('workspace.common.roleName', stringNewValue);
-    const oldRole = translate('workspace.common.roleName', stringOldValue);
+    const newRole = translate('workspace.common.roleName', stringNewValue).toLowerCase();
+    const oldRole = translate('workspace.common.roleName', stringOldValue).toLowerCase();
     return translate('report.actions.type.updateRole', {email, newRole, currentRole: oldRole});
 }
 
@@ -3776,7 +3776,7 @@ function getPolicyChangeLogDeleteMemberMessage(translate: LocalizedTranslate, re
     }
     const originalMessage = getOriginalMessage(reportAction);
     const email = formatPhoneNumber(originalMessage?.email ?? '');
-    const role = translate('workspace.common.roleName', originalMessage?.role ?? '');
+    const role = translate('workspace.common.roleName', originalMessage?.role ?? '').toLowerCase();
     return translate('report.actions.type.removeMember', email, role);
 }
 
@@ -3971,7 +3971,7 @@ function getActionableCardFraudAlertMessage(
 function getDemotedFromWorkspaceMessage(translate: LocalizedTranslate, reportAction: OnyxEntry<ReportAction<typeof CONST.REPORT.ACTIONS.TYPE.DEMOTED_FROM_WORKSPACE>>) {
     const originalMessage = getOriginalMessage(reportAction);
     const policyName = originalMessage?.policyName ?? translate('workspace.common.workspace');
-    const oldRole = translate('workspace.common.roleName', originalMessage?.oldRole);
+    const oldRole = translate('workspace.common.roleName', originalMessage?.oldRole).toLowerCase();
     return translate('workspaceActions.demotedFromWorkspace', policyName, oldRole);
 }
 

From 5a52aad3d0bcde72b26938848604f6386713e30e Mon Sep 17 00:00:00 2001
From: ShridharGoel <35566748+ShridharGoel@users.noreply.github.com>
Date: Fri, 5 Jun 2026 10:51:15 +0530
Subject: [PATCH 132/435] Revert non-English role translations

---
 src/languages/de.ts      | 8 ++------
 src/languages/es.ts      | 8 ++------
 src/languages/fr.ts      | 8 ++------
 src/languages/it.ts      | 8 ++------
 src/languages/ja.ts      | 8 ++------
 src/languages/nl.ts      | 8 ++------
 src/languages/pl.ts      | 8 ++------
 src/languages/pt-BR.ts   | 8 ++------
 src/languages/zh-hans.ts | 9 +++------
 9 files changed, 19 insertions(+), 54 deletions(-)

diff --git a/src/languages/de.ts b/src/languages/de.ts
index d7ff4e0b49d5..4aab5fbe808d 100644
--- a/src/languages/de.ts
+++ b/src/languages/de.ts
@@ -4373,7 +4373,7 @@ ${amount} für ${merchant} – ${date}`,
             roleName: (role?: string) => {
                 switch (role) {
                     case CONST.POLICY.ROLE.ADMIN:
-                        return 'Workspace-Admin';
+                        return 'Admin';
                     case CONST.POLICY.ROLE.AUDITOR:
                         return 'Prüfer';
                     case CONST.POLICY.ROLE.CARD_ADMIN:
@@ -6190,10 +6190,6 @@ _Für ausführlichere Anweisungen [besuchen Sie unsere Hilfeseite](${CONST.NETSU
                 one: 'Zum Prüfer machen',
                 other: 'Prüfende hinzufügen',
             }),
-            makeCardAdmin: () => ({
-                one: 'Zum Kartenadministrator machen',
-                other: 'Zu Kartenadministratoren machen',
-            }),
             selectAll: 'Alle auswählen',
             error: {
                 genericAdd: 'Beim Hinzufügen dieses Workspace-Mitglieds ist ein Problem aufgetreten',
@@ -8394,7 +8390,7 @@ Fügen Sie weitere Ausgabelimits hinzu, um den Cashflow Ihres Unternehmens zu sc
                 plaidBalanceFailure: ({maskedAccountNumber, walletRoute}: {maskedAccountNumber: string; walletRoute: string}) =>
                     `Die Plaid-Verbindung zu Ihrem Geschäftskonto ist unterbrochen. Bitte <a href='${walletRoute}'>verbinden Sie Ihr Bankkonto ${maskedAccountNumber} erneut</a>, damit Sie Ihre Expensify Karten weiterhin verwenden können.`,
                 addEmployee: (email: string, role: string, didJoinPolicy?: boolean) =>
-                    didJoinPolicy ? `${email} ist über den Arbeitsbereichs-Einladungslink beigetreten` : `${email} mit der Rolle ${role} hinzugefügt`,
+                    didJoinPolicy ? `${email} ist über den Arbeitsbereichs-Einladungslink beigetreten` : `${email} als ${role === 'member' ? 'a' : 'an'} ${role} hinzugefügt`,
                 updateRole: ({email, currentRole, newRole}: UpdateRoleParams) => `hat die Rolle von ${email} in ${newRole} geändert (zuvor ${currentRole})`,
                 updatedCustomField1: (email: string, newValue: string, previousValue: string) => {
                     if (!newValue) {
diff --git a/src/languages/es.ts b/src/languages/es.ts
index 76564e84e065..12fc795dbcd6 100644
--- a/src/languages/es.ts
+++ b/src/languages/es.ts
@@ -4262,7 +4262,7 @@ ${amount} para ${merchant} - ${date}`,
             roleName: (role?: string) => {
                 switch (role) {
                     case CONST.POLICY.ROLE.ADMIN:
-                        return 'Administrador del espacio de trabajo';
+                        return 'Administrador';
                     case CONST.POLICY.ROLE.AUDITOR:
                         return 'Auditor';
                     case CONST.POLICY.ROLE.CARD_ADMIN:
@@ -6027,10 +6027,6 @@ ${amount} para ${merchant} - ${date}`,
                 one: 'Convertir en auditor',
                 other: 'Convertir en auditores',
             }),
-            makeCardAdmin: () => ({
-                one: 'Convertir en administrador de tarjeta',
-                other: 'Convertir en administradores de tarjeta',
-            }),
             selectAll: 'Seleccionar todo',
             error: {
                 genericAdd: 'Ha ocurrido un problema al añadir el miembro al espacio de trabajo',
@@ -8186,7 +8182,7 @@ ${amount} para ${merchant} - ${date}`,
                 plaidBalanceFailure: ({maskedAccountNumber, walletRoute}: {maskedAccountNumber: string; walletRoute: string}) =>
                     `la conexión Plaid con tu cuenta bancaria de empresa está rota. Por favor, <a href='${walletRoute}'>reconecta tu cuenta bancaria ${maskedAccountNumber}</a> para poder seguir usando tus Tarjetas Expensify.`,
                 addEmployee: (email: string, role: string, didJoinPolicy?: boolean) =>
-                    didJoinPolicy ? `${email} se unió mediante el enlace de invitación del espacio de trabajo` : `se añadió ${email} con el rol ${role}`,
+                    didJoinPolicy ? `${email} se unió mediante el enlace de invitación del espacio de trabajo` : `se añadió ${email} como ${role === 'member' ? 'a' : 'a un'} ${role}`,
                 updateRole: ({email, currentRole, newRole}) => `actualizó el rol ${email} a ${newRole} (previamente ${currentRole})`,
                 updatedCustomField1: (email, newValue, previousValue) => {
                     if (!newValue) {
diff --git a/src/languages/fr.ts b/src/languages/fr.ts
index b7ae5f664b65..e1924676e2c2 100644
--- a/src/languages/fr.ts
+++ b/src/languages/fr.ts
@@ -4385,7 +4385,7 @@ ${amount} pour ${merchant} - ${date}`,
             roleName: (role?: string) => {
                 switch (role) {
                     case CONST.POLICY.ROLE.ADMIN:
-                        return 'Administrateur de l’espace de travail';
+                        return 'Administrateur';
                     case CONST.POLICY.ROLE.AUDITOR:
                         return 'Auditeur';
                     case CONST.POLICY.ROLE.CARD_ADMIN:
@@ -6215,10 +6215,6 @@ _Pour des instructions plus détaillées, [visitez notre site d’aide](${CONST.
                 one: 'Nommer auditeur',
                 other: 'Créer des auditeurs',
             }),
-            makeCardAdmin: () => ({
-                one: 'Nommer administrateur de carte',
-                other: 'Nommer des administrateurs de carte',
-            }),
             selectAll: 'Tout sélectionner',
             error: {
                 genericAdd: 'Un problème est survenu lors de l’ajout de ce membre de l’espace de travail',
@@ -8428,7 +8424,7 @@ Ajoutez davantage de règles de dépenses pour protéger la trésorerie de l’e
                 plaidBalanceFailure: ({maskedAccountNumber, walletRoute}: {maskedAccountNumber: string; walletRoute: string}) =>
                     `la connexion Plaid à votre compte bancaire professionnel est rompue. Veuillez <a href='${walletRoute}'>reconnecter votre compte bancaire ${maskedAccountNumber}</a> afin de pouvoir continuer à utiliser vos Cartes Expensify.`,
                 addEmployee: (email: string, role: string, didJoinPolicy?: boolean) =>
-                    didJoinPolicy ? `${email} a rejoint via le lien d’invitation de l’espace de travail` : `a ajouté ${email} avec le rôle ${role}`,
+                    didJoinPolicy ? `${email} a rejoint via le lien d’invitation de l’espace de travail` : `a ajouté ${email} en tant que ${role === 'member' ? 'a' : 'un'} ${role}`,
                 updateRole: ({email, currentRole, newRole}: UpdateRoleParams) => `a mis à jour le rôle de ${email} en ${newRole} (précédemment ${currentRole})`,
                 updatedCustomField1: (email: string, newValue: string, previousValue: string) => {
                     if (!newValue) {
diff --git a/src/languages/it.ts b/src/languages/it.ts
index 02a3bcd7dd0a..b74810e139e7 100644
--- a/src/languages/it.ts
+++ b/src/languages/it.ts
@@ -4359,7 +4359,7 @@ ${amount} per ${merchant} - ${date}`,
             roleName: (role?: string) => {
                 switch (role) {
                     case CONST.POLICY.ROLE.ADMIN:
-                        return 'Amministratore dello spazio di lavoro';
+                        return 'Amministratore';
                     case CONST.POLICY.ROLE.AUDITOR:
                         return 'Revisore';
                     case CONST.POLICY.ROLE.CARD_ADMIN:
@@ -6178,10 +6178,6 @@ _Per istruzioni più dettagliate, [visita il nostro sito di assistenza](${CONST.
                 one: 'Rendi revisore',
                 other: 'Crea revisori',
             }),
-            makeCardAdmin: () => ({
-                one: 'Rendi amministratore carta',
-                other: 'Rendi amministratori carta',
-            }),
             selectAll: 'Seleziona tutto',
             error: {
                 genericAdd: "Si è verificato un problema nell'aggiungere questo membro dello spazio di lavoro",
@@ -8383,7 +8379,7 @@ Aggiungi altre regole di spesa per proteggere il flusso di cassa aziendale.`,
                 plaidBalanceFailure: ({maskedAccountNumber, walletRoute}: {maskedAccountNumber: string; walletRoute: string}) =>
                     `la connessione Plaid al conto bancario della tua azienda non funziona. Per favore, <a href='${walletRoute}'>ricollega il conto bancario ${maskedAccountNumber}</a> così puoi continuare a usare le tue Carte Expensify.`,
                 addEmployee: (email: string, role: string, didJoinPolicy?: boolean) =>
-                    didJoinPolicy ? `${email} si è unito tramite il link di invito allo spazio di lavoro` : `ha aggiunto ${email} con il ruolo ${role}`,
+                    didJoinPolicy ? `${email} si è unito tramite il link di invito allo spazio di lavoro` : `ha aggiunto ${email} come ${role === 'member' ? 'a' : 'un'} ${role}`,
                 updateRole: ({email, currentRole, newRole}: UpdateRoleParams) => `ha aggiornato il ruolo di ${email} a ${newRole} (in precedenza ${currentRole})`,
                 updatedCustomField1: (email: string, newValue: string, previousValue: string) => {
                     if (!newValue) {
diff --git a/src/languages/ja.ts b/src/languages/ja.ts
index 2f6b83460010..b001b3c7cfd5 100644
--- a/src/languages/ja.ts
+++ b/src/languages/ja.ts
@@ -4327,7 +4327,7 @@ ${integrationName === CONST.ONBOARDING_ACCOUNTING_MAPPING.other ? 'あなたの'
             roleName: (role?: string) => {
                 switch (role) {
                     case CONST.POLICY.ROLE.ADMIN:
-                        return 'ワークスペース管理者';
+                        return '管理者';
                     case CONST.POLICY.ROLE.AUDITOR:
                         return '監査担当者';
                     case CONST.POLICY.ROLE.CARD_ADMIN:
@@ -6105,10 +6105,6 @@ _詳しい手順については、[ヘルプサイトをご覧ください](${CO
                 one: '監査担当者に設定',
                 other: '監査担当者を作成',
             }),
-            makeCardAdmin: () => ({
-                one: 'カード管理者に設定',
-                other: 'カード管理者に設定',
-            }),
             selectAll: 'すべて選択',
             error: {
                 genericAdd: 'このワークスペースメンバーを追加する際に問題が発生しました',
@@ -8273,7 +8269,7 @@ ${reportName}
                 plaidBalanceFailure: ({maskedAccountNumber, walletRoute}: {maskedAccountNumber: string; walletRoute: string}) =>
                     `Plaid によるビジネス銀行口座との接続が切断されています。Expensify カードを引き続きご利用いただくために、<a href='${walletRoute}'>銀行口座 ${maskedAccountNumber} を再接続</a>してください。`,
                 addEmployee: (email: string, role: string, didJoinPolicy?: boolean) =>
-                    didJoinPolicy ? `${email} さんがワークスペースの招待リンクから参加しました` : `${email} を ${role} として追加しました`,
+                    didJoinPolicy ? `${email} さんがワークスペースの招待リンクから参加しました` : `${role === 'member' ? 'a' : '1つの'} ${role} として ${email} を追加しました`,
                 updateRole: ({email, currentRole, newRole}: UpdateRoleParams) => `${email} のロールを ${currentRole} から ${newRole} に更新しました`,
                 updatedCustomField1: (email: string, newValue: string, previousValue: string) => {
                     if (!newValue) {
diff --git a/src/languages/nl.ts b/src/languages/nl.ts
index 7cafed87c7f4..ddd96d1d7e65 100644
--- a/src/languages/nl.ts
+++ b/src/languages/nl.ts
@@ -4355,7 +4355,7 @@ ${amount} voor ${merchant} - ${date}`,
             roleName: (role?: string) => {
                 switch (role) {
                     case CONST.POLICY.ROLE.ADMIN:
-                        return 'Werkruimtebeheerder';
+                        return 'Beheer';
                     case CONST.POLICY.ROLE.AUDITOR:
                         return 'Auditor';
                     case CONST.POLICY.ROLE.CARD_ADMIN:
@@ -6157,10 +6157,6 @@ _Voor meer gedetailleerde instructies, [bezoek onze help-site](${CONST.NETSUITE_
                 one: 'Auditeur maken',
                 other: 'Auditors aanmaken',
             }),
-            makeCardAdmin: () => ({
-                one: 'Kaartbeheerder maken',
-                other: 'Kaartbeheerders maken',
-            }),
             selectAll: 'Alles selecteren',
             error: {
                 genericAdd: 'Er is een probleem opgetreden bij het toevoegen van dit werkruimtelid',
@@ -8351,7 +8347,7 @@ er bestedingsregels toe om de kasstroom van het bedrijf te beschermen.`,
                 plaidBalanceFailure: ({maskedAccountNumber, walletRoute}: {maskedAccountNumber: string; walletRoute: string}) =>
                     `de Plaid-verbinding met je zakelijke bankrekening is verbroken. <a href='${walletRoute}'>Verbind je bankrekening ${maskedAccountNumber} opnieuw</a> zodat je je Expensify Kaarten kunt blijven gebruiken.`,
                 addEmployee: (email: string, role: string, didJoinPolicy?: boolean) =>
-                    didJoinPolicy ? `${email} is via de werkruimte-uitnodigingslink lid geworden` : `heeft ${email} toegevoegd met de rol ${role}`,
+                    didJoinPolicy ? `${email} is via de werkruimte-uitnodigingslink lid geworden` : `heeft ${email} toegevoegd als ${role === 'member' ? 'een' : 'een'} ${role}`,
                 updateRole: ({email, currentRole, newRole}: UpdateRoleParams) => `heeft de rol van ${email} bijgewerkt naar ${newRole} (voorheen ${currentRole})`,
                 updatedCustomField1: (email: string, newValue: string, previousValue: string) => {
                     if (!newValue) {
diff --git a/src/languages/pl.ts b/src/languages/pl.ts
index b008fc16b44d..4d73d8b074ee 100644
--- a/src/languages/pl.ts
+++ b/src/languages/pl.ts
@@ -4347,7 +4347,7 @@ ${amount} dla ${merchant} - ${date}`,
             roleName: (role?: string) => {
                 switch (role) {
                     case CONST.POLICY.ROLE.ADMIN:
-                        return 'Administrator przestrzeni roboczej';
+                        return 'Administrator';
                     case CONST.POLICY.ROLE.AUDITOR:
                         return 'Audytor';
                     case CONST.POLICY.ROLE.CARD_ADMIN:
@@ -6152,10 +6152,6 @@ _Aby uzyskać bardziej szczegółowe instrukcje, [odwiedź naszą stronę pomocy
                 one: 'Ustaw jako audytora',
                 other: 'Utwórz audytorów',
             }),
-            makeCardAdmin: () => ({
-                one: 'Ustaw jako administratora kart',
-                other: 'Ustaw jako administratorów kart',
-            }),
             selectAll: 'Zaznacz wszystko',
             error: {
                 genericAdd: 'Wystąpił problem z dodaniem tego członka przestrzeni roboczej',
@@ -8342,7 +8338,7 @@ Dodaj więcej zasad wydatków, żeby chronić płynność finansową firmy.`,
                 plaidBalanceFailure: ({maskedAccountNumber, walletRoute}: {maskedAccountNumber: string; walletRoute: string}) =>
                     `połączenie Plaid z twoim firmowym kontem bankowym jest przerwane. Proszę, <a href='${walletRoute}'>połącz ponownie swoje konto bankowe ${maskedAccountNumber}</a>, aby móc dalej używać Kart Expensify.`,
                 addEmployee: (email: string, role: string, didJoinPolicy?: boolean) =>
-                    didJoinPolicy ? `${email} dołączył(a) przez link z zaproszeniem do przestrzeni roboczej` : `dodano ${email} z rolą ${role}`,
+                    didJoinPolicy ? `${email} dołączył(a) przez link z zaproszeniem do przestrzeni roboczej` : `dodano ${email} jako ${role === 'member' ? 'a' : 'jeden'} ${role}`,
                 updateRole: ({email, currentRole, newRole}: UpdateRoleParams) => `zaktualizowano rolę użytkownika ${email} na ${newRole} (wcześniej ${currentRole})`,
                 updatedCustomField1: (email: string, newValue: string, previousValue: string) => {
                     if (!newValue) {
diff --git a/src/languages/pt-BR.ts b/src/languages/pt-BR.ts
index a21c2013366b..b1b7653c6e71 100644
--- a/src/languages/pt-BR.ts
+++ b/src/languages/pt-BR.ts
@@ -4348,7 +4348,7 @@ ${amount} para ${merchant} - ${date}`,
             roleName: (role?: string) => {
                 switch (role) {
                     case CONST.POLICY.ROLE.ADMIN:
-                        return 'Admin do workspace';
+                        return 'Admin';
                     case CONST.POLICY.ROLE.AUDITOR:
                         return 'Auditor';
                     case CONST.POLICY.ROLE.CARD_ADMIN:
@@ -6156,10 +6156,6 @@ _Para instruções mais detalhadas, [visite nossa central de ajuda](${CONST.NETS
                 one: 'Tornar auditor',
                 other: 'Tornar auditores',
             }),
-            makeCardAdmin: () => ({
-                one: 'Tornar admin do cartão',
-                other: 'Tornar admins do cartão',
-            }),
             selectAll: 'Selecionar tudo',
             error: {
                 genericAdd: 'Ocorreu um problema ao adicionar este membro do workspace',
@@ -8345,7 +8341,7 @@ Adicione mais regras de gasto para proteger o fluxo de caixa da empresa.`,
                 plaidBalanceFailure: ({maskedAccountNumber, walletRoute}: {maskedAccountNumber: string; walletRoute: string}) =>
                     `a conexão Plaid com a sua conta bancária empresarial foi interrompida. Por favor, <a href='${walletRoute}'>reconecte sua conta bancária ${maskedAccountNumber}</a> para continuar usando seus Cartões Expensify.`,
                 addEmployee: (email: string, role: string, didJoinPolicy?: boolean) =>
-                    didJoinPolicy ? `${email} entrou pelo link de convite do workspace` : `adicionou ${email} com a função ${role}`,
+                    didJoinPolicy ? `${email} entrou pelo link de convite do workspace` : `adicionou ${email} como ${role === 'member' ? 'a' : 'um'} ${role}`,
                 updateRole: ({email, currentRole, newRole}: UpdateRoleParams) => `atualizou a função de ${email} para ${newRole} (anteriormente ${currentRole})`,
                 updatedCustomField1: (email: string, newValue: string, previousValue: string) => {
                     if (!newValue) {
diff --git a/src/languages/zh-hans.ts b/src/languages/zh-hans.ts
index f3c9c4d94245..4d017ea5a363 100644
--- a/src/languages/zh-hans.ts
+++ b/src/languages/zh-hans.ts
@@ -4251,7 +4251,7 @@ ${amount}，商户：${merchant} - 日期：${date}`,
             roleName: (role?: string) => {
                 switch (role) {
                     case CONST.POLICY.ROLE.ADMIN:
-                        return '工作区管理员';
+                        return '管理员';
                     case CONST.POLICY.ROLE.AUDITOR:
                         return '审计员';
                     case CONST.POLICY.ROLE.CARD_ADMIN:
@@ -5997,10 +5997,6 @@ _如需更详细的说明，请[访问我们的帮助网站](${CONST.NETSUITE_IM
                 one: '设为审计员',
                 other: '创建审计员',
             }),
-            makeCardAdmin: () => ({
-                one: '设为卡片管理员',
-                other: '设为卡片管理员',
-            }),
             selectAll: '全选',
             error: {
                 genericAdd: '添加此工作区成员时出现问题',
@@ -8112,7 +8108,8 @@ ${reportName}
                     `${feedName} 连接已中断。要恢复银行卡导入，请<a href='${workspaceCompanyCardRoute}'>登录您的银行账户</a>。`,
                 plaidBalanceFailure: ({maskedAccountNumber, walletRoute}: {maskedAccountNumber: string; walletRoute: string}) =>
                     `您与企业银行账户的 Plaid 连接已中断。请<a href='${walletRoute}'>重新连接您的银行账户 ${maskedAccountNumber}</a>，以便继续使用 Expensify 卡。`,
-                addEmployee: (email: string, role: string, didJoinPolicy?: boolean) => (didJoinPolicy ? `${email} 通过工作区邀请链接加入` : `已将 ${email} 添加为 ${role}`),
+                addEmployee: (email: string, role: string, didJoinPolicy?: boolean) =>
+                    didJoinPolicy ? `${email} 通过工作区邀请链接加入` : `已将 ${email} 添加为 ${role === 'member' ? '一个' : '一个'} 的 ${role}`,
                 updateRole: ({email, currentRole, newRole}: UpdateRoleParams) => `已将 ${email} 的角色更新为 ${newRole}（先前为 ${currentRole}）`,
                 updatedCustomField1: (email: string, newValue: string, previousValue: string) => {
                     if (!newValue) {

From 3570a29fa7032047b362210b0a21cce4e5d3e48c Mon Sep 17 00:00:00 2001
From: ShridharGoel <35566748+ShridharGoel@users.noreply.github.com>
Date: Fri, 5 Jun 2026 10:58:19 +0530
Subject: [PATCH 133/435] Rename policy admins room role helper

---
 src/libs/actions/Policy/Member.ts | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/src/libs/actions/Policy/Member.ts b/src/libs/actions/Policy/Member.ts
index 48e1b7a06cb5..575da14418a1 100644
--- a/src/libs/actions/Policy/Member.ts
+++ b/src/libs/actions/Policy/Member.ts
@@ -45,7 +45,7 @@ type WorkspaceMembersRoleData = {
     role: ValueOf<typeof CONST.POLICY.ROLE>;
 };
 
-function isPolicyAdminsRoomRole(role: string | undefined): boolean {
+function shouldBeInPolicyAdminsRoom(role: string | undefined): boolean {
     return role === CONST.POLICY.ROLE.ADMIN || role === CONST.POLICY.ROLE.AUDITOR || role === CONST.POLICY.ROLE.CARD_ADMIN;
 }
 
@@ -353,7 +353,7 @@ function removeMembers(policy: OnyxEntry<Policy>, selectedMemberEmails: string[]
         selectedMemberEmails
             .filter((login) => {
                 const role = login ? policy?.employeeList?.[login]?.role : '';
-                return isPolicyAdminsRoomRole(role);
+                return shouldBeInPolicyAdminsRoom(role);
             })
             .map((login) => policyMemberEmailsToAccountIDs[login]),
     );
@@ -647,7 +647,7 @@ function buildUpdateWorkspaceMembersRoleOnyxData(policy: OnyxEntry<Policy>, sele
     if (adminRoom) {
         const failureDataParticipants: Record<number, Participant | null> = {...adminRoom.participants};
         const optimisticParticipants: Record<number, Participant | null> = {};
-        if (isPolicyAdminsRoomRole(newRole)) {
+        if (shouldBeInPolicyAdminsRoom(newRole)) {
             for (const accountID of selectedMemberAccountIDs) {
                 if (adminRoom?.participants?.[accountID]) {
                     continue;
@@ -814,7 +814,7 @@ function buildAddMembersToWorkspaceOnyxData(
     const newPersonalDetailsOnyxData = PersonalDetailsUtils.getPersonalDetailsOnyxDataForOptimisticUsers(newLogins, newAccountIDs, formatPhoneNumber);
 
     const announceRoomMembers = buildRoomMembersOnyxData(CONST.REPORT.CHAT_TYPE.POLICY_ANNOUNCE, policyID, accountIDs);
-    const adminRoomMembers = buildRoomMembersOnyxData(CONST.REPORT.CHAT_TYPE.POLICY_ADMINS, policyID, isPolicyAdminsRoomRole(role) ? accountIDs : []);
+    const adminRoomMembers = buildRoomMembersOnyxData(CONST.REPORT.CHAT_TYPE.POLICY_ADMINS, policyID, shouldBeInPolicyAdminsRoom(role) ? accountIDs : []);
     const optimisticAnnounceChat = ReportUtils.buildOptimisticAnnounceChat(policyID, [...policyMemberAccountIDs, ...accountIDs], currentUser.accountID);
     const announceRoomChat = optimisticAnnounceChat.announceChatData;
 

From 9d6895f7f1c4ab8492de7d564c55f767fdbcd5ae Mon Sep 17 00:00:00 2001
From: ShridharGoel <35566748+ShridharGoel@users.noreply.github.com>
Date: Fri, 5 Jun 2026 11:12:57 +0530
Subject: [PATCH 134/435] Add translations

---
 src/languages/de.ts      | 13 ++++++++-----
 src/languages/es.ts      |  9 ++++++---
 src/languages/fr.ts      |  9 ++++++---
 src/languages/it.ts      | 13 ++++++++-----
 src/languages/ja.ts      | 11 +++++++----
 src/languages/nl.ts      | 11 +++++++----
 src/languages/pl.ts      |  9 ++++++---
 src/languages/pt-BR.ts   | 15 +++++++++------
 src/languages/zh-hans.ts | 11 +++++++----
 9 files changed, 64 insertions(+), 37 deletions(-)

diff --git a/src/languages/de.ts b/src/languages/de.ts
index 4aab5fbe808d..f168f05d9464 100644
--- a/src/languages/de.ts
+++ b/src/languages/de.ts
@@ -4373,13 +4373,13 @@ ${amount} für ${merchant} – ${date}`,
             roleName: (role?: string) => {
                 switch (role) {
                     case CONST.POLICY.ROLE.ADMIN:
-                        return 'Admin';
+                        return 'Workspace-Administrator';
                     case CONST.POLICY.ROLE.AUDITOR:
                         return 'Prüfer';
                     case CONST.POLICY.ROLE.CARD_ADMIN:
-                        return 'Kartenverwaltung';
+                        return 'Kartenadministrator';
                     case CONST.POLICY.ROLE.PEOPLE_ADMIN:
-                        return 'Personenverwaltung';
+                        return 'Personalverwaltung';
                     case CONST.POLICY.ROLE.PAYMENTS_ADMIN:
                         return 'Zahlungsadministrator';
                     case CONST.POLICY.ROLE.USER:
@@ -6219,6 +6219,7 @@ _Für ausführlichere Anweisungen [besuchen Sie unsere Hilfeseite](${CONST.NETSU
             emptyRoleFilter: {title: 'Keine Mitglieder entsprechen diesem Filter', subtitle: 'Laden Sie ein Mitglied ein oder ändern Sie den Filter oben.'},
             configureHRSync: (providerName: string) => `Synchronisierung mit ${providerName} einrichten.`,
             syncWithHR: (providerName: string) => `Mit ${providerName} synchronisieren`,
+            makeCardAdmin: {one: 'Als Karten-Admin festlegen', other: 'Zu Karten-Admins machen'},
         },
         card: {
             getStartedIssuing: 'Beginne, indem du deine erste virtuelle oder physische Karte ausstellst.',
@@ -8389,8 +8390,10 @@ Fügen Sie weitere Ausgabelimits hinzu, um den Cashflow Ihres Unternehmens zu sc
                     `Die Verbindung für ${feedName} ist unterbrochen. Um Kartenimporte wiederherzustellen, <a href='${workspaceCompanyCardRoute}'>melden Sie sich bei Ihrer Bank an</a>.`,
                 plaidBalanceFailure: ({maskedAccountNumber, walletRoute}: {maskedAccountNumber: string; walletRoute: string}) =>
                     `Die Plaid-Verbindung zu Ihrem Geschäftskonto ist unterbrochen. Bitte <a href='${walletRoute}'>verbinden Sie Ihr Bankkonto ${maskedAccountNumber} erneut</a>, damit Sie Ihre Expensify Karten weiterhin verwenden können.`,
-                addEmployee: (email: string, role: string, didJoinPolicy?: boolean) =>
-                    didJoinPolicy ? `${email} ist über den Arbeitsbereichs-Einladungslink beigetreten` : `${email} als ${role === 'member' ? 'a' : 'an'} ${role} hinzugefügt`,
+                addEmployee: (email: string, role: string, didJoinPolicy?: boolean) => {
+                    const article = role.toLowerCase() === 'auditor' ? 'an' : 'ein';
+                    return didJoinPolicy ? `${email} ist über den Workspace-Einladungslink beigetreten` : `${email} als ${article} ${role} hinzugefügt`;
+                },
                 updateRole: ({email, currentRole, newRole}: UpdateRoleParams) => `hat die Rolle von ${email} in ${newRole} geändert (zuvor ${currentRole})`,
                 updatedCustomField1: (email: string, newValue: string, previousValue: string) => {
                     if (!newValue) {
diff --git a/src/languages/es.ts b/src/languages/es.ts
index 12fc795dbcd6..008b66d1c583 100644
--- a/src/languages/es.ts
+++ b/src/languages/es.ts
@@ -4262,7 +4262,7 @@ ${amount} para ${merchant} - ${date}`,
             roleName: (role?: string) => {
                 switch (role) {
                     case CONST.POLICY.ROLE.ADMIN:
-                        return 'Administrador';
+                        return 'Administrador del espacio de trabajo';
                     case CONST.POLICY.ROLE.AUDITOR:
                         return 'Auditor';
                     case CONST.POLICY.ROLE.CARD_ADMIN:
@@ -6059,6 +6059,7 @@ ${amount} para ${merchant} - ${date}`,
                 `${memberName} tiene un informe en proceso pendiente de acción. Pídele que complete la acción requerida antes de eliminarlo del espacio de trabajo.`,
             configureHRSync: (providerName: string) => `Configura la sincronización de ${providerName}.`,
             syncWithHR: (providerName: string) => `Sincronizar con ${providerName}`,
+            makeCardAdmin: {one: 'Hacer administrador de tarjeta', other: 'Hacer administradores de tarjetas'},
         },
         accounting: {
             settings: 'configuración',
@@ -8181,8 +8182,10 @@ ${amount} para ${merchant} - ${date}`,
                     `La conexión ${feedName} está rota. Para restaurar las importaciones de tarjetas, <a href='${workspaceCompanyCardRoute}'>inicia sesión en tu banco</a>.`,
                 plaidBalanceFailure: ({maskedAccountNumber, walletRoute}: {maskedAccountNumber: string; walletRoute: string}) =>
                     `la conexión Plaid con tu cuenta bancaria de empresa está rota. Por favor, <a href='${walletRoute}'>reconecta tu cuenta bancaria ${maskedAccountNumber}</a> para poder seguir usando tus Tarjetas Expensify.`,
-                addEmployee: (email: string, role: string, didJoinPolicy?: boolean) =>
-                    didJoinPolicy ? `${email} se unió mediante el enlace de invitación del espacio de trabajo` : `se añadió ${email} como ${role === 'member' ? 'a' : 'a un'} ${role}`,
+                addEmployee: (email: string, role: string, didJoinPolicy?: boolean) => {
+                    const article = role.toLowerCase() === 'auditor' ? 'un' : 'a';
+                    return didJoinPolicy ? `${email} se unió a través del enlace de invitación del espacio de trabajo` : `añadió ${email} como ${article} ${role}`;
+                },
                 updateRole: ({email, currentRole, newRole}) => `actualizó el rol ${email} a ${newRole} (previamente ${currentRole})`,
                 updatedCustomField1: (email, newValue, previousValue) => {
                     if (!newValue) {
diff --git a/src/languages/fr.ts b/src/languages/fr.ts
index e1924676e2c2..145f2e877641 100644
--- a/src/languages/fr.ts
+++ b/src/languages/fr.ts
@@ -4385,7 +4385,7 @@ ${amount} pour ${merchant} - ${date}`,
             roleName: (role?: string) => {
                 switch (role) {
                     case CONST.POLICY.ROLE.ADMIN:
-                        return 'Administrateur';
+                        return 'Administrateur d’espace de travail';
                     case CONST.POLICY.ROLE.AUDITOR:
                         return 'Auditeur';
                     case CONST.POLICY.ROLE.CARD_ADMIN:
@@ -6244,6 +6244,7 @@ _Pour des instructions plus détaillées, [visitez notre site d’aide](${CONST.
             emptyRoleFilter: {title: 'Aucun membre ne correspond à ce filtre', subtitle: 'Invitez un membre ou modifiez le filtre ci-dessus.'},
             configureHRSync: (providerName: string) => `Configurer la synchronisation ${providerName}.`,
             syncWithHR: (providerName: string) => `Synchroniser avec ${providerName}`,
+            makeCardAdmin: {one: 'Nommer administrateur de carte', other: 'Nommer des administrateurs de carte'},
         },
         card: {
             getStartedIssuing: 'Commencez par émettre votre première carte virtuelle ou physique.',
@@ -8423,8 +8424,10 @@ Ajoutez davantage de règles de dépenses pour protéger la trésorerie de l’e
                     `La connexion ${feedName} est interrompue. Pour rétablir l’importation des cartes, <a href='${workspaceCompanyCardRoute}'>connectez-vous à votre banque</a>.`,
                 plaidBalanceFailure: ({maskedAccountNumber, walletRoute}: {maskedAccountNumber: string; walletRoute: string}) =>
                     `la connexion Plaid à votre compte bancaire professionnel est rompue. Veuillez <a href='${walletRoute}'>reconnecter votre compte bancaire ${maskedAccountNumber}</a> afin de pouvoir continuer à utiliser vos Cartes Expensify.`,
-                addEmployee: (email: string, role: string, didJoinPolicy?: boolean) =>
-                    didJoinPolicy ? `${email} a rejoint via le lien d’invitation de l’espace de travail` : `a ajouté ${email} en tant que ${role === 'member' ? 'a' : 'un'} ${role}`,
+                addEmployee: (email: string, role: string, didJoinPolicy?: boolean) => {
+                    const article = role.toLowerCase() === 'auditor' ? 'un' : 'un';
+                    return didJoinPolicy ? `${email} a rejoint via le lien d’invitation à l’espace de travail` : `a ajouté ${email} en tant que ${article} ${role}`;
+                },
                 updateRole: ({email, currentRole, newRole}: UpdateRoleParams) => `a mis à jour le rôle de ${email} en ${newRole} (précédemment ${currentRole})`,
                 updatedCustomField1: (email: string, newValue: string, previousValue: string) => {
                     if (!newValue) {
diff --git a/src/languages/it.ts b/src/languages/it.ts
index b74810e139e7..fc3eafb3e330 100644
--- a/src/languages/it.ts
+++ b/src/languages/it.ts
@@ -4359,13 +4359,13 @@ ${amount} per ${merchant} - ${date}`,
             roleName: (role?: string) => {
                 switch (role) {
                     case CONST.POLICY.ROLE.ADMIN:
-                        return 'Amministratore';
+                        return 'Amministratore spazio di lavoro';
                     case CONST.POLICY.ROLE.AUDITOR:
                         return 'Revisore';
                     case CONST.POLICY.ROLE.CARD_ADMIN:
-                        return 'Amministrazione carta';
+                        return 'Amministratore carta';
                     case CONST.POLICY.ROLE.PEOPLE_ADMIN:
-                        return 'Amministrazione persone';
+                        return 'Amministratore persone';
                     case CONST.POLICY.ROLE.PAYMENTS_ADMIN:
                         return 'Amministrazione pagamenti';
                     case CONST.POLICY.ROLE.USER:
@@ -6207,6 +6207,7 @@ _Per istruzioni più dettagliate, [visita il nostro sito di assistenza](${CONST.
             emptyRoleFilter: {title: 'Nessun membro corrisponde a questo filtro', subtitle: 'Invita un membro o modifica il filtro qui sopra.'},
             configureHRSync: (providerName: string) => `Configura la sincronizzazione di ${providerName}.`,
             syncWithHR: (providerName: string) => `Sincronizza con ${providerName}`,
+            makeCardAdmin: {one: 'Rendi amministratore della carta', other: 'Rendi amministratori carta'},
         },
         card: {
             getStartedIssuing: 'Inizia emettendo la tua prima carta virtuale o fisica.',
@@ -8378,8 +8379,10 @@ Aggiungi altre regole di spesa per proteggere il flusso di cassa aziendale.`,
                     `La connessione ${feedName} è interrotta. Per ripristinare le importazioni della carta, <a href='${workspaceCompanyCardRoute}'>accedi alla tua banca</a>.`,
                 plaidBalanceFailure: ({maskedAccountNumber, walletRoute}: {maskedAccountNumber: string; walletRoute: string}) =>
                     `la connessione Plaid al conto bancario della tua azienda non funziona. Per favore, <a href='${walletRoute}'>ricollega il conto bancario ${maskedAccountNumber}</a> così puoi continuare a usare le tue Carte Expensify.`,
-                addEmployee: (email: string, role: string, didJoinPolicy?: boolean) =>
-                    didJoinPolicy ? `${email} si è unito tramite il link di invito allo spazio di lavoro` : `ha aggiunto ${email} come ${role === 'member' ? 'a' : 'un'} ${role}`,
+                addEmployee: (email: string, role: string, didJoinPolicy?: boolean) => {
+                    const article = role.toLowerCase() === 'auditor' ? 'un' : 'a';
+                    return didJoinPolicy ? `${email} si è unito tramite il link di invito dello spazio di lavoro` : `ha aggiunto ${email} come ${article} ${role}`;
+                },
                 updateRole: ({email, currentRole, newRole}: UpdateRoleParams) => `ha aggiornato il ruolo di ${email} a ${newRole} (in precedenza ${currentRole})`,
                 updatedCustomField1: (email: string, newValue: string, previousValue: string) => {
                     if (!newValue) {
diff --git a/src/languages/ja.ts b/src/languages/ja.ts
index b001b3c7cfd5..c4031775101d 100644
--- a/src/languages/ja.ts
+++ b/src/languages/ja.ts
@@ -4327,7 +4327,7 @@ ${integrationName === CONST.ONBOARDING_ACCOUNTING_MAPPING.other ? 'あなたの'
             roleName: (role?: string) => {
                 switch (role) {
                     case CONST.POLICY.ROLE.ADMIN:
-                        return '管理者';
+                        return 'ワークスペース管理者';
                     case CONST.POLICY.ROLE.AUDITOR:
                         return '監査担当者';
                     case CONST.POLICY.ROLE.CARD_ADMIN:
@@ -4335,7 +4335,7 @@ ${integrationName === CONST.ONBOARDING_ACCOUNTING_MAPPING.other ? 'あなたの'
                     case CONST.POLICY.ROLE.PEOPLE_ADMIN:
                         return 'メンバー管理';
                     case CONST.POLICY.ROLE.PAYMENTS_ADMIN:
-                        return '支払管理者';
+                        return '支払い管理者';
                     case CONST.POLICY.ROLE.USER:
                         return 'メンバー';
                     default:
@@ -6134,6 +6134,7 @@ _詳しい手順については、[ヘルプサイトをご覧ください](${CO
             emptyRoleFilter: {title: 'このフィルターに一致するメンバーはいません', subtitle: 'メンバーを招待するか、上のフィルターを変更してください。'},
             configureHRSync: (providerName: string) => `${providerName} の同期を設定します。`,
             syncWithHR: (providerName: string) => `${providerName}と同期`,
+            makeCardAdmin: {one: 'カード管理者にする', other: 'カード管理者を作成'},
         },
         card: {
             getStartedIssuing: 'まずは最初のバーチャルカードまたは物理カードを発行しましょう。',
@@ -8268,8 +8269,10 @@ ${reportName}
                     `${feedName} との接続が切断されています。カードの取引明細の取込を再開するには、<a href='${workspaceCompanyCardRoute}'>銀行にログイン</a>してください。`,
                 plaidBalanceFailure: ({maskedAccountNumber, walletRoute}: {maskedAccountNumber: string; walletRoute: string}) =>
                     `Plaid によるビジネス銀行口座との接続が切断されています。Expensify カードを引き続きご利用いただくために、<a href='${walletRoute}'>銀行口座 ${maskedAccountNumber} を再接続</a>してください。`,
-                addEmployee: (email: string, role: string, didJoinPolicy?: boolean) =>
-                    didJoinPolicy ? `${email} さんがワークスペースの招待リンクから参加しました` : `${role === 'member' ? 'a' : '1つの'} ${role} として ${email} を追加しました`,
+                addEmployee: (email: string, role: string, didJoinPolicy?: boolean) => {
+                    const article = role.toLowerCase() === 'auditor' ? '一つの' : 'a';
+                    return didJoinPolicy ? `${email} さんがワークスペースの招待リンクから参加しました` : `${email} を${article}${role}として追加しました`;
+                },
                 updateRole: ({email, currentRole, newRole}: UpdateRoleParams) => `${email} のロールを ${currentRole} から ${newRole} に更新しました`,
                 updatedCustomField1: (email: string, newValue: string, previousValue: string) => {
                     if (!newValue) {
diff --git a/src/languages/nl.ts b/src/languages/nl.ts
index ddd96d1d7e65..650e7473e522 100644
--- a/src/languages/nl.ts
+++ b/src/languages/nl.ts
@@ -4355,13 +4355,13 @@ ${amount} voor ${merchant} - ${date}`,
             roleName: (role?: string) => {
                 switch (role) {
                     case CONST.POLICY.ROLE.ADMIN:
-                        return 'Beheer';
+                        return 'Beheerder van workspace';
                     case CONST.POLICY.ROLE.AUDITOR:
                         return 'Auditor';
                     case CONST.POLICY.ROLE.CARD_ADMIN:
                         return 'Kaartbeheer';
                     case CONST.POLICY.ROLE.PEOPLE_ADMIN:
-                        return 'Mensenbeheer';
+                        return 'Personenbeheer';
                     case CONST.POLICY.ROLE.PAYMENTS_ADMIN:
                         return 'Beheerder betalingen';
                     case CONST.POLICY.ROLE.USER:
@@ -6186,6 +6186,7 @@ _Voor meer gedetailleerde instructies, [bezoek onze help-site](${CONST.NETSUITE_
             emptyRoleFilter: {title: 'Geen leden komen overeen met dit filter', subtitle: 'Nodig een lid uit of wijzig het filter hierboven.'},
             configureHRSync: (providerName: string) => `Stel ${providerName}-synchronisatie in.`,
             syncWithHR: (providerName: string) => `Synchroniseren met ${providerName}`,
+            makeCardAdmin: {one: 'Kaartbeheerder maken', other: 'Maak kaartbeheerders'},
         },
         card: {
             getStartedIssuing: 'Begin met het uitgeven van je eerste virtuele of fysieke kaart.',
@@ -8346,8 +8347,10 @@ er bestedingsregels toe om de kasstroom van het bedrijf te beschermen.`,
                     `De verbinding met ${feedName} is verbroken. <a href='${workspaceCompanyCardRoute}'>Log in bij je bank</a> om kaartimports te herstellen.`,
                 plaidBalanceFailure: ({maskedAccountNumber, walletRoute}: {maskedAccountNumber: string; walletRoute: string}) =>
                     `de Plaid-verbinding met je zakelijke bankrekening is verbroken. <a href='${walletRoute}'>Verbind je bankrekening ${maskedAccountNumber} opnieuw</a> zodat je je Expensify Kaarten kunt blijven gebruiken.`,
-                addEmployee: (email: string, role: string, didJoinPolicy?: boolean) =>
-                    didJoinPolicy ? `${email} is via de werkruimte-uitnodigingslink lid geworden` : `heeft ${email} toegevoegd als ${role === 'member' ? 'een' : 'een'} ${role}`,
+                addEmployee: (email: string, role: string, didJoinPolicy?: boolean) => {
+                    const article = role.toLowerCase() === 'auditor' ? 'een' : 'een';
+                    return didJoinPolicy ? `${email} is via de werkruimte-uitnodigingslink lid geworden` : `heeft ${email} toegevoegd als ${article} ${role}`;
+                },
                 updateRole: ({email, currentRole, newRole}: UpdateRoleParams) => `heeft de rol van ${email} bijgewerkt naar ${newRole} (voorheen ${currentRole})`,
                 updatedCustomField1: (email: string, newValue: string, previousValue: string) => {
                     if (!newValue) {
diff --git a/src/languages/pl.ts b/src/languages/pl.ts
index 4d73d8b074ee..259a0e4a4996 100644
--- a/src/languages/pl.ts
+++ b/src/languages/pl.ts
@@ -4347,7 +4347,7 @@ ${amount} dla ${merchant} - ${date}`,
             roleName: (role?: string) => {
                 switch (role) {
                     case CONST.POLICY.ROLE.ADMIN:
-                        return 'Administrator';
+                        return 'Administrator przestrzeni roboczej';
                     case CONST.POLICY.ROLE.AUDITOR:
                         return 'Audytor';
                     case CONST.POLICY.ROLE.CARD_ADMIN:
@@ -6181,6 +6181,7 @@ _Aby uzyskać bardziej szczegółowe instrukcje, [odwiedź naszą stronę pomocy
             emptyRoleFilter: {title: 'Żadni członkowie nie pasują do tego filtra', subtitle: 'Zaproś członka lub zmień filtr powyżej.'},
             configureHRSync: (providerName: string) => `Skonfiguruj synchronizację ${providerName}.`,
             syncWithHR: (providerName: string) => `Synchronizuj z ${providerName}`,
+            makeCardAdmin: {one: 'Ustaw jako administratora karty', other: 'Ustaw administratorów kart'},
         },
         card: {
             getStartedIssuing: 'Zacznij od wydania swojej pierwszej wirtualnej lub fizycznej karty.',
@@ -8337,8 +8338,10 @@ Dodaj więcej zasad wydatków, żeby chronić płynność finansową firmy.`,
                     `Połączenie ${feedName} jest przerwane. Aby przywrócić importy kart, <a href='${workspaceCompanyCardRoute}'>zaloguj się do swojego banku</a>.`,
                 plaidBalanceFailure: ({maskedAccountNumber, walletRoute}: {maskedAccountNumber: string; walletRoute: string}) =>
                     `połączenie Plaid z twoim firmowym kontem bankowym jest przerwane. Proszę, <a href='${walletRoute}'>połącz ponownie swoje konto bankowe ${maskedAccountNumber}</a>, aby móc dalej używać Kart Expensify.`,
-                addEmployee: (email: string, role: string, didJoinPolicy?: boolean) =>
-                    didJoinPolicy ? `${email} dołączył(a) przez link z zaproszeniem do przestrzeni roboczej` : `dodano ${email} jako ${role === 'member' ? 'a' : 'jeden'} ${role}`,
+                addEmployee: (email: string, role: string, didJoinPolicy?: boolean) => {
+                    const article = role.toLowerCase() === 'auditor' ? 'jeden' : 'a';
+                    return didJoinPolicy ? `${email} dołączył przez link zaproszenia do przestrzeni roboczej` : `dodano ${email} jako ${article} ${role}`;
+                },
                 updateRole: ({email, currentRole, newRole}: UpdateRoleParams) => `zaktualizowano rolę użytkownika ${email} na ${newRole} (wcześniej ${currentRole})`,
                 updatedCustomField1: (email: string, newValue: string, previousValue: string) => {
                     if (!newValue) {
diff --git a/src/languages/pt-BR.ts b/src/languages/pt-BR.ts
index b1b7653c6e71..38b5892f124b 100644
--- a/src/languages/pt-BR.ts
+++ b/src/languages/pt-BR.ts
@@ -4348,15 +4348,15 @@ ${amount} para ${merchant} - ${date}`,
             roleName: (role?: string) => {
                 switch (role) {
                     case CONST.POLICY.ROLE.ADMIN:
-                        return 'Admin';
+                        return 'Admin do workspace';
                     case CONST.POLICY.ROLE.AUDITOR:
                         return 'Auditor';
                     case CONST.POLICY.ROLE.CARD_ADMIN:
-                        return 'Admin. do Cartão';
+                        return 'Administrador do cartão';
                     case CONST.POLICY.ROLE.PEOPLE_ADMIN:
-                        return 'Administração de pessoas';
+                        return 'Admin de pessoas';
                     case CONST.POLICY.ROLE.PAYMENTS_ADMIN:
-                        return 'Admin de pagamentos';
+                        return 'Administrador de pagamentos';
                     case CONST.POLICY.ROLE.USER:
                         return 'Membro';
                     default:
@@ -6185,6 +6185,7 @@ _Para instruções mais detalhadas, [visite nossa central de ajuda](${CONST.NETS
             emptyRoleFilter: {title: 'Nenhum membro corresponde a este filtro', subtitle: 'Convide um membro ou altere o filtro acima.'},
             configureHRSync: (providerName: string) => `Configurar a sincronização do ${providerName}.`,
             syncWithHR: (providerName: string) => `Sincronizar com ${providerName}`,
+            makeCardAdmin: {one: 'Tornar admin do cartão', other: 'Tornar administradores de cartão'},
         },
         card: {
             getStartedIssuing: 'Comece emitindo seu primeiro cartão virtual ou físico.',
@@ -8340,8 +8341,10 @@ Adicione mais regras de gasto para proteger o fluxo de caixa da empresa.`,
                     `A conexão de ${feedName} está interrompida. Para restaurar as importações do cartão, <a href='${workspaceCompanyCardRoute}'>faça login no seu banco</a>.`,
                 plaidBalanceFailure: ({maskedAccountNumber, walletRoute}: {maskedAccountNumber: string; walletRoute: string}) =>
                     `a conexão Plaid com a sua conta bancária empresarial foi interrompida. Por favor, <a href='${walletRoute}'>reconecte sua conta bancária ${maskedAccountNumber}</a> para continuar usando seus Cartões Expensify.`,
-                addEmployee: (email: string, role: string, didJoinPolicy?: boolean) =>
-                    didJoinPolicy ? `${email} entrou pelo link de convite do workspace` : `adicionou ${email} como ${role === 'member' ? 'a' : 'um'} ${role}`,
+                addEmployee: (email: string, role: string, didJoinPolicy?: boolean) => {
+                    const article = role.toLowerCase() === 'auditor' ? 'um' : 'um';
+                    return didJoinPolicy ? `${email} entrou pelo link de convite do workspace` : `adicionou ${email} como ${article} ${role}`;
+                },
                 updateRole: ({email, currentRole, newRole}: UpdateRoleParams) => `atualizou a função de ${email} para ${newRole} (anteriormente ${currentRole})`,
                 updatedCustomField1: (email: string, newValue: string, previousValue: string) => {
                     if (!newValue) {
diff --git a/src/languages/zh-hans.ts b/src/languages/zh-hans.ts
index 4d017ea5a363..9dc2aa21de5d 100644
--- a/src/languages/zh-hans.ts
+++ b/src/languages/zh-hans.ts
@@ -4251,13 +4251,13 @@ ${amount}，商户：${merchant} - 日期：${date}`,
             roleName: (role?: string) => {
                 switch (role) {
                     case CONST.POLICY.ROLE.ADMIN:
-                        return '管理员';
+                        return '工作区管理员';
                     case CONST.POLICY.ROLE.AUDITOR:
                         return '审计员';
                     case CONST.POLICY.ROLE.CARD_ADMIN:
                         return '卡片管理员';
                     case CONST.POLICY.ROLE.PEOPLE_ADMIN:
-                        return '人员管理';
+                        return '人员管理员';
                     case CONST.POLICY.ROLE.PAYMENTS_ADMIN:
                         return '付款管理员';
                     case CONST.POLICY.ROLE.USER:
@@ -6022,6 +6022,7 @@ _如需更详细的说明，请[访问我们的帮助网站](${CONST.NETSUITE_IM
             emptyRoleFilter: {title: '没有成员符合此筛选条件', subtitle: '邀请成员或更改上方的筛选条件。'},
             configureHRSync: (providerName: string) => `配置 ${providerName} 同步。`,
             syncWithHR: (providerName: string) => `与 ${providerName} 同步`,
+            makeCardAdmin: {one: '设为卡片管理员', other: '设为卡片管理员'},
         },
         card: {
             getStartedIssuing: '从发放您的第一张虚拟卡或实体卡开始使用。',
@@ -8108,8 +8109,10 @@ ${reportName}
                     `${feedName} 连接已中断。要恢复银行卡导入，请<a href='${workspaceCompanyCardRoute}'>登录您的银行账户</a>。`,
                 plaidBalanceFailure: ({maskedAccountNumber, walletRoute}: {maskedAccountNumber: string; walletRoute: string}) =>
                     `您与企业银行账户的 Plaid 连接已中断。请<a href='${walletRoute}'>重新连接您的银行账户 ${maskedAccountNumber}</a>，以便继续使用 Expensify 卡。`,
-                addEmployee: (email: string, role: string, didJoinPolicy?: boolean) =>
-                    didJoinPolicy ? `${email} 通过工作区邀请链接加入` : `已将 ${email} 添加为 ${role === 'member' ? '一个' : '一个'} 的 ${role}`,
+                addEmployee: (email: string, role: string, didJoinPolicy?: boolean) => {
+                    const article = role.toLowerCase() === 'auditor' ? '一' : 'a';
+                    return didJoinPolicy ? `${email} 通过工作区邀请链接加入` : `已将 ${email} 添加为 ${article} ${role}`;
+                },
                 updateRole: ({email, currentRole, newRole}: UpdateRoleParams) => `已将 ${email} 的角色更新为 ${newRole}（先前为 ${currentRole}）`,
                 updatedCustomField1: (email: string, newValue: string, previousValue: string) => {
                     if (!newValue) {

From ebfc289c72f88f4f74883223036354520551d93b Mon Sep 17 00:00:00 2001
From: ShridharGoel <35566748+ShridharGoel@users.noreply.github.com>
Date: Fri, 5 Jun 2026 11:38:20 +0530
Subject: [PATCH 135/435] Revert generated non-English role translations

---
 src/languages/de.ts      | 13 +++++--------
 src/languages/es.ts      |  9 +++------
 src/languages/fr.ts      |  9 +++------
 src/languages/it.ts      | 13 +++++--------
 src/languages/ja.ts      | 11 ++++-------
 src/languages/nl.ts      | 11 ++++-------
 src/languages/pl.ts      |  9 +++------
 src/languages/pt-BR.ts   | 15 ++++++---------
 src/languages/zh-hans.ts | 11 ++++-------
 9 files changed, 37 insertions(+), 64 deletions(-)

diff --git a/src/languages/de.ts b/src/languages/de.ts
index f168f05d9464..4aab5fbe808d 100644
--- a/src/languages/de.ts
+++ b/src/languages/de.ts
@@ -4373,13 +4373,13 @@ ${amount} für ${merchant} – ${date}`,
             roleName: (role?: string) => {
                 switch (role) {
                     case CONST.POLICY.ROLE.ADMIN:
-                        return 'Workspace-Administrator';
+                        return 'Admin';
                     case CONST.POLICY.ROLE.AUDITOR:
                         return 'Prüfer';
                     case CONST.POLICY.ROLE.CARD_ADMIN:
-                        return 'Kartenadministrator';
+                        return 'Kartenverwaltung';
                     case CONST.POLICY.ROLE.PEOPLE_ADMIN:
-                        return 'Personalverwaltung';
+                        return 'Personenverwaltung';
                     case CONST.POLICY.ROLE.PAYMENTS_ADMIN:
                         return 'Zahlungsadministrator';
                     case CONST.POLICY.ROLE.USER:
@@ -6219,7 +6219,6 @@ _Für ausführlichere Anweisungen [besuchen Sie unsere Hilfeseite](${CONST.NETSU
             emptyRoleFilter: {title: 'Keine Mitglieder entsprechen diesem Filter', subtitle: 'Laden Sie ein Mitglied ein oder ändern Sie den Filter oben.'},
             configureHRSync: (providerName: string) => `Synchronisierung mit ${providerName} einrichten.`,
             syncWithHR: (providerName: string) => `Mit ${providerName} synchronisieren`,
-            makeCardAdmin: {one: 'Als Karten-Admin festlegen', other: 'Zu Karten-Admins machen'},
         },
         card: {
             getStartedIssuing: 'Beginne, indem du deine erste virtuelle oder physische Karte ausstellst.',
@@ -8390,10 +8389,8 @@ Fügen Sie weitere Ausgabelimits hinzu, um den Cashflow Ihres Unternehmens zu sc
                     `Die Verbindung für ${feedName} ist unterbrochen. Um Kartenimporte wiederherzustellen, <a href='${workspaceCompanyCardRoute}'>melden Sie sich bei Ihrer Bank an</a>.`,
                 plaidBalanceFailure: ({maskedAccountNumber, walletRoute}: {maskedAccountNumber: string; walletRoute: string}) =>
                     `Die Plaid-Verbindung zu Ihrem Geschäftskonto ist unterbrochen. Bitte <a href='${walletRoute}'>verbinden Sie Ihr Bankkonto ${maskedAccountNumber} erneut</a>, damit Sie Ihre Expensify Karten weiterhin verwenden können.`,
-                addEmployee: (email: string, role: string, didJoinPolicy?: boolean) => {
-                    const article = role.toLowerCase() === 'auditor' ? 'an' : 'ein';
-                    return didJoinPolicy ? `${email} ist über den Workspace-Einladungslink beigetreten` : `${email} als ${article} ${role} hinzugefügt`;
-                },
+                addEmployee: (email: string, role: string, didJoinPolicy?: boolean) =>
+                    didJoinPolicy ? `${email} ist über den Arbeitsbereichs-Einladungslink beigetreten` : `${email} als ${role === 'member' ? 'a' : 'an'} ${role} hinzugefügt`,
                 updateRole: ({email, currentRole, newRole}: UpdateRoleParams) => `hat die Rolle von ${email} in ${newRole} geändert (zuvor ${currentRole})`,
                 updatedCustomField1: (email: string, newValue: string, previousValue: string) => {
                     if (!newValue) {
diff --git a/src/languages/es.ts b/src/languages/es.ts
index 008b66d1c583..12fc795dbcd6 100644
--- a/src/languages/es.ts
+++ b/src/languages/es.ts
@@ -4262,7 +4262,7 @@ ${amount} para ${merchant} - ${date}`,
             roleName: (role?: string) => {
                 switch (role) {
                     case CONST.POLICY.ROLE.ADMIN:
-                        return 'Administrador del espacio de trabajo';
+                        return 'Administrador';
                     case CONST.POLICY.ROLE.AUDITOR:
                         return 'Auditor';
                     case CONST.POLICY.ROLE.CARD_ADMIN:
@@ -6059,7 +6059,6 @@ ${amount} para ${merchant} - ${date}`,
                 `${memberName} tiene un informe en proceso pendiente de acción. Pídele que complete la acción requerida antes de eliminarlo del espacio de trabajo.`,
             configureHRSync: (providerName: string) => `Configura la sincronización de ${providerName}.`,
             syncWithHR: (providerName: string) => `Sincronizar con ${providerName}`,
-            makeCardAdmin: {one: 'Hacer administrador de tarjeta', other: 'Hacer administradores de tarjetas'},
         },
         accounting: {
             settings: 'configuración',
@@ -8182,10 +8181,8 @@ ${amount} para ${merchant} - ${date}`,
                     `La conexión ${feedName} está rota. Para restaurar las importaciones de tarjetas, <a href='${workspaceCompanyCardRoute}'>inicia sesión en tu banco</a>.`,
                 plaidBalanceFailure: ({maskedAccountNumber, walletRoute}: {maskedAccountNumber: string; walletRoute: string}) =>
                     `la conexión Plaid con tu cuenta bancaria de empresa está rota. Por favor, <a href='${walletRoute}'>reconecta tu cuenta bancaria ${maskedAccountNumber}</a> para poder seguir usando tus Tarjetas Expensify.`,
-                addEmployee: (email: string, role: string, didJoinPolicy?: boolean) => {
-                    const article = role.toLowerCase() === 'auditor' ? 'un' : 'a';
-                    return didJoinPolicy ? `${email} se unió a través del enlace de invitación del espacio de trabajo` : `añadió ${email} como ${article} ${role}`;
-                },
+                addEmployee: (email: string, role: string, didJoinPolicy?: boolean) =>
+                    didJoinPolicy ? `${email} se unió mediante el enlace de invitación del espacio de trabajo` : `se añadió ${email} como ${role === 'member' ? 'a' : 'a un'} ${role}`,
                 updateRole: ({email, currentRole, newRole}) => `actualizó el rol ${email} a ${newRole} (previamente ${currentRole})`,
                 updatedCustomField1: (email, newValue, previousValue) => {
                     if (!newValue) {
diff --git a/src/languages/fr.ts b/src/languages/fr.ts
index 145f2e877641..e1924676e2c2 100644
--- a/src/languages/fr.ts
+++ b/src/languages/fr.ts
@@ -4385,7 +4385,7 @@ ${amount} pour ${merchant} - ${date}`,
             roleName: (role?: string) => {
                 switch (role) {
                     case CONST.POLICY.ROLE.ADMIN:
-                        return 'Administrateur d’espace de travail';
+                        return 'Administrateur';
                     case CONST.POLICY.ROLE.AUDITOR:
                         return 'Auditeur';
                     case CONST.POLICY.ROLE.CARD_ADMIN:
@@ -6244,7 +6244,6 @@ _Pour des instructions plus détaillées, [visitez notre site d’aide](${CONST.
             emptyRoleFilter: {title: 'Aucun membre ne correspond à ce filtre', subtitle: 'Invitez un membre ou modifiez le filtre ci-dessus.'},
             configureHRSync: (providerName: string) => `Configurer la synchronisation ${providerName}.`,
             syncWithHR: (providerName: string) => `Synchroniser avec ${providerName}`,
-            makeCardAdmin: {one: 'Nommer administrateur de carte', other: 'Nommer des administrateurs de carte'},
         },
         card: {
             getStartedIssuing: 'Commencez par émettre votre première carte virtuelle ou physique.',
@@ -8424,10 +8423,8 @@ Ajoutez davantage de règles de dépenses pour protéger la trésorerie de l’e
                     `La connexion ${feedName} est interrompue. Pour rétablir l’importation des cartes, <a href='${workspaceCompanyCardRoute}'>connectez-vous à votre banque</a>.`,
                 plaidBalanceFailure: ({maskedAccountNumber, walletRoute}: {maskedAccountNumber: string; walletRoute: string}) =>
                     `la connexion Plaid à votre compte bancaire professionnel est rompue. Veuillez <a href='${walletRoute}'>reconnecter votre compte bancaire ${maskedAccountNumber}</a> afin de pouvoir continuer à utiliser vos Cartes Expensify.`,
-                addEmployee: (email: string, role: string, didJoinPolicy?: boolean) => {
-                    const article = role.toLowerCase() === 'auditor' ? 'un' : 'un';
-                    return didJoinPolicy ? `${email} a rejoint via le lien d’invitation à l’espace de travail` : `a ajouté ${email} en tant que ${article} ${role}`;
-                },
+                addEmployee: (email: string, role: string, didJoinPolicy?: boolean) =>
+                    didJoinPolicy ? `${email} a rejoint via le lien d’invitation de l’espace de travail` : `a ajouté ${email} en tant que ${role === 'member' ? 'a' : 'un'} ${role}`,
                 updateRole: ({email, currentRole, newRole}: UpdateRoleParams) => `a mis à jour le rôle de ${email} en ${newRole} (précédemment ${currentRole})`,
                 updatedCustomField1: (email: string, newValue: string, previousValue: string) => {
                     if (!newValue) {
diff --git a/src/languages/it.ts b/src/languages/it.ts
index fc3eafb3e330..b74810e139e7 100644
--- a/src/languages/it.ts
+++ b/src/languages/it.ts
@@ -4359,13 +4359,13 @@ ${amount} per ${merchant} - ${date}`,
             roleName: (role?: string) => {
                 switch (role) {
                     case CONST.POLICY.ROLE.ADMIN:
-                        return 'Amministratore spazio di lavoro';
+                        return 'Amministratore';
                     case CONST.POLICY.ROLE.AUDITOR:
                         return 'Revisore';
                     case CONST.POLICY.ROLE.CARD_ADMIN:
-                        return 'Amministratore carta';
+                        return 'Amministrazione carta';
                     case CONST.POLICY.ROLE.PEOPLE_ADMIN:
-                        return 'Amministratore persone';
+                        return 'Amministrazione persone';
                     case CONST.POLICY.ROLE.PAYMENTS_ADMIN:
                         return 'Amministrazione pagamenti';
                     case CONST.POLICY.ROLE.USER:
@@ -6207,7 +6207,6 @@ _Per istruzioni più dettagliate, [visita il nostro sito di assistenza](${CONST.
             emptyRoleFilter: {title: 'Nessun membro corrisponde a questo filtro', subtitle: 'Invita un membro o modifica il filtro qui sopra.'},
             configureHRSync: (providerName: string) => `Configura la sincronizzazione di ${providerName}.`,
             syncWithHR: (providerName: string) => `Sincronizza con ${providerName}`,
-            makeCardAdmin: {one: 'Rendi amministratore della carta', other: 'Rendi amministratori carta'},
         },
         card: {
             getStartedIssuing: 'Inizia emettendo la tua prima carta virtuale o fisica.',
@@ -8379,10 +8378,8 @@ Aggiungi altre regole di spesa per proteggere il flusso di cassa aziendale.`,
                     `La connessione ${feedName} è interrotta. Per ripristinare le importazioni della carta, <a href='${workspaceCompanyCardRoute}'>accedi alla tua banca</a>.`,
                 plaidBalanceFailure: ({maskedAccountNumber, walletRoute}: {maskedAccountNumber: string; walletRoute: string}) =>
                     `la connessione Plaid al conto bancario della tua azienda non funziona. Per favore, <a href='${walletRoute}'>ricollega il conto bancario ${maskedAccountNumber}</a> così puoi continuare a usare le tue Carte Expensify.`,
-                addEmployee: (email: string, role: string, didJoinPolicy?: boolean) => {
-                    const article = role.toLowerCase() === 'auditor' ? 'un' : 'a';
-                    return didJoinPolicy ? `${email} si è unito tramite il link di invito dello spazio di lavoro` : `ha aggiunto ${email} come ${article} ${role}`;
-                },
+                addEmployee: (email: string, role: string, didJoinPolicy?: boolean) =>
+                    didJoinPolicy ? `${email} si è unito tramite il link di invito allo spazio di lavoro` : `ha aggiunto ${email} come ${role === 'member' ? 'a' : 'un'} ${role}`,
                 updateRole: ({email, currentRole, newRole}: UpdateRoleParams) => `ha aggiornato il ruolo di ${email} a ${newRole} (in precedenza ${currentRole})`,
                 updatedCustomField1: (email: string, newValue: string, previousValue: string) => {
                     if (!newValue) {
diff --git a/src/languages/ja.ts b/src/languages/ja.ts
index c4031775101d..b001b3c7cfd5 100644
--- a/src/languages/ja.ts
+++ b/src/languages/ja.ts
@@ -4327,7 +4327,7 @@ ${integrationName === CONST.ONBOARDING_ACCOUNTING_MAPPING.other ? 'あなたの'
             roleName: (role?: string) => {
                 switch (role) {
                     case CONST.POLICY.ROLE.ADMIN:
-                        return 'ワークスペース管理者';
+                        return '管理者';
                     case CONST.POLICY.ROLE.AUDITOR:
                         return '監査担当者';
                     case CONST.POLICY.ROLE.CARD_ADMIN:
@@ -4335,7 +4335,7 @@ ${integrationName === CONST.ONBOARDING_ACCOUNTING_MAPPING.other ? 'あなたの'
                     case CONST.POLICY.ROLE.PEOPLE_ADMIN:
                         return 'メンバー管理';
                     case CONST.POLICY.ROLE.PAYMENTS_ADMIN:
-                        return '支払い管理者';
+                        return '支払管理者';
                     case CONST.POLICY.ROLE.USER:
                         return 'メンバー';
                     default:
@@ -6134,7 +6134,6 @@ _詳しい手順については、[ヘルプサイトをご覧ください](${CO
             emptyRoleFilter: {title: 'このフィルターに一致するメンバーはいません', subtitle: 'メンバーを招待するか、上のフィルターを変更してください。'},
             configureHRSync: (providerName: string) => `${providerName} の同期を設定します。`,
             syncWithHR: (providerName: string) => `${providerName}と同期`,
-            makeCardAdmin: {one: 'カード管理者にする', other: 'カード管理者を作成'},
         },
         card: {
             getStartedIssuing: 'まずは最初のバーチャルカードまたは物理カードを発行しましょう。',
@@ -8269,10 +8268,8 @@ ${reportName}
                     `${feedName} との接続が切断されています。カードの取引明細の取込を再開するには、<a href='${workspaceCompanyCardRoute}'>銀行にログイン</a>してください。`,
                 plaidBalanceFailure: ({maskedAccountNumber, walletRoute}: {maskedAccountNumber: string; walletRoute: string}) =>
                     `Plaid によるビジネス銀行口座との接続が切断されています。Expensify カードを引き続きご利用いただくために、<a href='${walletRoute}'>銀行口座 ${maskedAccountNumber} を再接続</a>してください。`,
-                addEmployee: (email: string, role: string, didJoinPolicy?: boolean) => {
-                    const article = role.toLowerCase() === 'auditor' ? '一つの' : 'a';
-                    return didJoinPolicy ? `${email} さんがワークスペースの招待リンクから参加しました` : `${email} を${article}${role}として追加しました`;
-                },
+                addEmployee: (email: string, role: string, didJoinPolicy?: boolean) =>
+                    didJoinPolicy ? `${email} さんがワークスペースの招待リンクから参加しました` : `${role === 'member' ? 'a' : '1つの'} ${role} として ${email} を追加しました`,
                 updateRole: ({email, currentRole, newRole}: UpdateRoleParams) => `${email} のロールを ${currentRole} から ${newRole} に更新しました`,
                 updatedCustomField1: (email: string, newValue: string, previousValue: string) => {
                     if (!newValue) {
diff --git a/src/languages/nl.ts b/src/languages/nl.ts
index 650e7473e522..ddd96d1d7e65 100644
--- a/src/languages/nl.ts
+++ b/src/languages/nl.ts
@@ -4355,13 +4355,13 @@ ${amount} voor ${merchant} - ${date}`,
             roleName: (role?: string) => {
                 switch (role) {
                     case CONST.POLICY.ROLE.ADMIN:
-                        return 'Beheerder van workspace';
+                        return 'Beheer';
                     case CONST.POLICY.ROLE.AUDITOR:
                         return 'Auditor';
                     case CONST.POLICY.ROLE.CARD_ADMIN:
                         return 'Kaartbeheer';
                     case CONST.POLICY.ROLE.PEOPLE_ADMIN:
-                        return 'Personenbeheer';
+                        return 'Mensenbeheer';
                     case CONST.POLICY.ROLE.PAYMENTS_ADMIN:
                         return 'Beheerder betalingen';
                     case CONST.POLICY.ROLE.USER:
@@ -6186,7 +6186,6 @@ _Voor meer gedetailleerde instructies, [bezoek onze help-site](${CONST.NETSUITE_
             emptyRoleFilter: {title: 'Geen leden komen overeen met dit filter', subtitle: 'Nodig een lid uit of wijzig het filter hierboven.'},
             configureHRSync: (providerName: string) => `Stel ${providerName}-synchronisatie in.`,
             syncWithHR: (providerName: string) => `Synchroniseren met ${providerName}`,
-            makeCardAdmin: {one: 'Kaartbeheerder maken', other: 'Maak kaartbeheerders'},
         },
         card: {
             getStartedIssuing: 'Begin met het uitgeven van je eerste virtuele of fysieke kaart.',
@@ -8347,10 +8346,8 @@ er bestedingsregels toe om de kasstroom van het bedrijf te beschermen.`,
                     `De verbinding met ${feedName} is verbroken. <a href='${workspaceCompanyCardRoute}'>Log in bij je bank</a> om kaartimports te herstellen.`,
                 plaidBalanceFailure: ({maskedAccountNumber, walletRoute}: {maskedAccountNumber: string; walletRoute: string}) =>
                     `de Plaid-verbinding met je zakelijke bankrekening is verbroken. <a href='${walletRoute}'>Verbind je bankrekening ${maskedAccountNumber} opnieuw</a> zodat je je Expensify Kaarten kunt blijven gebruiken.`,
-                addEmployee: (email: string, role: string, didJoinPolicy?: boolean) => {
-                    const article = role.toLowerCase() === 'auditor' ? 'een' : 'een';
-                    return didJoinPolicy ? `${email} is via de werkruimte-uitnodigingslink lid geworden` : `heeft ${email} toegevoegd als ${article} ${role}`;
-                },
+                addEmployee: (email: string, role: string, didJoinPolicy?: boolean) =>
+                    didJoinPolicy ? `${email} is via de werkruimte-uitnodigingslink lid geworden` : `heeft ${email} toegevoegd als ${role === 'member' ? 'een' : 'een'} ${role}`,
                 updateRole: ({email, currentRole, newRole}: UpdateRoleParams) => `heeft de rol van ${email} bijgewerkt naar ${newRole} (voorheen ${currentRole})`,
                 updatedCustomField1: (email: string, newValue: string, previousValue: string) => {
                     if (!newValue) {
diff --git a/src/languages/pl.ts b/src/languages/pl.ts
index 259a0e4a4996..4d73d8b074ee 100644
--- a/src/languages/pl.ts
+++ b/src/languages/pl.ts
@@ -4347,7 +4347,7 @@ ${amount} dla ${merchant} - ${date}`,
             roleName: (role?: string) => {
                 switch (role) {
                     case CONST.POLICY.ROLE.ADMIN:
-                        return 'Administrator przestrzeni roboczej';
+                        return 'Administrator';
                     case CONST.POLICY.ROLE.AUDITOR:
                         return 'Audytor';
                     case CONST.POLICY.ROLE.CARD_ADMIN:
@@ -6181,7 +6181,6 @@ _Aby uzyskać bardziej szczegółowe instrukcje, [odwiedź naszą stronę pomocy
             emptyRoleFilter: {title: 'Żadni członkowie nie pasują do tego filtra', subtitle: 'Zaproś członka lub zmień filtr powyżej.'},
             configureHRSync: (providerName: string) => `Skonfiguruj synchronizację ${providerName}.`,
             syncWithHR: (providerName: string) => `Synchronizuj z ${providerName}`,
-            makeCardAdmin: {one: 'Ustaw jako administratora karty', other: 'Ustaw administratorów kart'},
         },
         card: {
             getStartedIssuing: 'Zacznij od wydania swojej pierwszej wirtualnej lub fizycznej karty.',
@@ -8338,10 +8337,8 @@ Dodaj więcej zasad wydatków, żeby chronić płynność finansową firmy.`,
                     `Połączenie ${feedName} jest przerwane. Aby przywrócić importy kart, <a href='${workspaceCompanyCardRoute}'>zaloguj się do swojego banku</a>.`,
                 plaidBalanceFailure: ({maskedAccountNumber, walletRoute}: {maskedAccountNumber: string; walletRoute: string}) =>
                     `połączenie Plaid z twoim firmowym kontem bankowym jest przerwane. Proszę, <a href='${walletRoute}'>połącz ponownie swoje konto bankowe ${maskedAccountNumber}</a>, aby móc dalej używać Kart Expensify.`,
-                addEmployee: (email: string, role: string, didJoinPolicy?: boolean) => {
-                    const article = role.toLowerCase() === 'auditor' ? 'jeden' : 'a';
-                    return didJoinPolicy ? `${email} dołączył przez link zaproszenia do przestrzeni roboczej` : `dodano ${email} jako ${article} ${role}`;
-                },
+                addEmployee: (email: string, role: string, didJoinPolicy?: boolean) =>
+                    didJoinPolicy ? `${email} dołączył(a) przez link z zaproszeniem do przestrzeni roboczej` : `dodano ${email} jako ${role === 'member' ? 'a' : 'jeden'} ${role}`,
                 updateRole: ({email, currentRole, newRole}: UpdateRoleParams) => `zaktualizowano rolę użytkownika ${email} na ${newRole} (wcześniej ${currentRole})`,
                 updatedCustomField1: (email: string, newValue: string, previousValue: string) => {
                     if (!newValue) {
diff --git a/src/languages/pt-BR.ts b/src/languages/pt-BR.ts
index 38b5892f124b..b1b7653c6e71 100644
--- a/src/languages/pt-BR.ts
+++ b/src/languages/pt-BR.ts
@@ -4348,15 +4348,15 @@ ${amount} para ${merchant} - ${date}`,
             roleName: (role?: string) => {
                 switch (role) {
                     case CONST.POLICY.ROLE.ADMIN:
-                        return 'Admin do workspace';
+                        return 'Admin';
                     case CONST.POLICY.ROLE.AUDITOR:
                         return 'Auditor';
                     case CONST.POLICY.ROLE.CARD_ADMIN:
-                        return 'Administrador do cartão';
+                        return 'Admin. do Cartão';
                     case CONST.POLICY.ROLE.PEOPLE_ADMIN:
-                        return 'Admin de pessoas';
+                        return 'Administração de pessoas';
                     case CONST.POLICY.ROLE.PAYMENTS_ADMIN:
-                        return 'Administrador de pagamentos';
+                        return 'Admin de pagamentos';
                     case CONST.POLICY.ROLE.USER:
                         return 'Membro';
                     default:
@@ -6185,7 +6185,6 @@ _Para instruções mais detalhadas, [visite nossa central de ajuda](${CONST.NETS
             emptyRoleFilter: {title: 'Nenhum membro corresponde a este filtro', subtitle: 'Convide um membro ou altere o filtro acima.'},
             configureHRSync: (providerName: string) => `Configurar a sincronização do ${providerName}.`,
             syncWithHR: (providerName: string) => `Sincronizar com ${providerName}`,
-            makeCardAdmin: {one: 'Tornar admin do cartão', other: 'Tornar administradores de cartão'},
         },
         card: {
             getStartedIssuing: 'Comece emitindo seu primeiro cartão virtual ou físico.',
@@ -8341,10 +8340,8 @@ Adicione mais regras de gasto para proteger o fluxo de caixa da empresa.`,
                     `A conexão de ${feedName} está interrompida. Para restaurar as importações do cartão, <a href='${workspaceCompanyCardRoute}'>faça login no seu banco</a>.`,
                 plaidBalanceFailure: ({maskedAccountNumber, walletRoute}: {maskedAccountNumber: string; walletRoute: string}) =>
                     `a conexão Plaid com a sua conta bancária empresarial foi interrompida. Por favor, <a href='${walletRoute}'>reconecte sua conta bancária ${maskedAccountNumber}</a> para continuar usando seus Cartões Expensify.`,
-                addEmployee: (email: string, role: string, didJoinPolicy?: boolean) => {
-                    const article = role.toLowerCase() === 'auditor' ? 'um' : 'um';
-                    return didJoinPolicy ? `${email} entrou pelo link de convite do workspace` : `adicionou ${email} como ${article} ${role}`;
-                },
+                addEmployee: (email: string, role: string, didJoinPolicy?: boolean) =>
+                    didJoinPolicy ? `${email} entrou pelo link de convite do workspace` : `adicionou ${email} como ${role === 'member' ? 'a' : 'um'} ${role}`,
                 updateRole: ({email, currentRole, newRole}: UpdateRoleParams) => `atualizou a função de ${email} para ${newRole} (anteriormente ${currentRole})`,
                 updatedCustomField1: (email: string, newValue: string, previousValue: string) => {
                     if (!newValue) {
diff --git a/src/languages/zh-hans.ts b/src/languages/zh-hans.ts
index 9dc2aa21de5d..4d017ea5a363 100644
--- a/src/languages/zh-hans.ts
+++ b/src/languages/zh-hans.ts
@@ -4251,13 +4251,13 @@ ${amount}，商户：${merchant} - 日期：${date}`,
             roleName: (role?: string) => {
                 switch (role) {
                     case CONST.POLICY.ROLE.ADMIN:
-                        return '工作区管理员';
+                        return '管理员';
                     case CONST.POLICY.ROLE.AUDITOR:
                         return '审计员';
                     case CONST.POLICY.ROLE.CARD_ADMIN:
                         return '卡片管理员';
                     case CONST.POLICY.ROLE.PEOPLE_ADMIN:
-                        return '人员管理员';
+                        return '人员管理';
                     case CONST.POLICY.ROLE.PAYMENTS_ADMIN:
                         return '付款管理员';
                     case CONST.POLICY.ROLE.USER:
@@ -6022,7 +6022,6 @@ _如需更详细的说明，请[访问我们的帮助网站](${CONST.NETSUITE_IM
             emptyRoleFilter: {title: '没有成员符合此筛选条件', subtitle: '邀请成员或更改上方的筛选条件。'},
             configureHRSync: (providerName: string) => `配置 ${providerName} 同步。`,
             syncWithHR: (providerName: string) => `与 ${providerName} 同步`,
-            makeCardAdmin: {one: '设为卡片管理员', other: '设为卡片管理员'},
         },
         card: {
             getStartedIssuing: '从发放您的第一张虚拟卡或实体卡开始使用。',
@@ -8109,10 +8108,8 @@ ${reportName}
                     `${feedName} 连接已中断。要恢复银行卡导入，请<a href='${workspaceCompanyCardRoute}'>登录您的银行账户</a>。`,
                 plaidBalanceFailure: ({maskedAccountNumber, walletRoute}: {maskedAccountNumber: string; walletRoute: string}) =>
                     `您与企业银行账户的 Plaid 连接已中断。请<a href='${walletRoute}'>重新连接您的银行账户 ${maskedAccountNumber}</a>，以便继续使用 Expensify 卡。`,
-                addEmployee: (email: string, role: string, didJoinPolicy?: boolean) => {
-                    const article = role.toLowerCase() === 'auditor' ? '一' : 'a';
-                    return didJoinPolicy ? `${email} 通过工作区邀请链接加入` : `已将 ${email} 添加为 ${article} ${role}`;
-                },
+                addEmployee: (email: string, role: string, didJoinPolicy?: boolean) =>
+                    didJoinPolicy ? `${email} 通过工作区邀请链接加入` : `已将 ${email} 添加为 ${role === 'member' ? '一个' : '一个'} 的 ${role}`,
                 updateRole: ({email, currentRole, newRole}: UpdateRoleParams) => `已将 ${email} 的角色更新为 ${newRole}（先前为 ${currentRole}）`,
                 updatedCustomField1: (email: string, newValue: string, previousValue: string) => {
                     if (!newValue) {

From 9a172d17cd4a14e1053632f5bea2ced49d5fc1e5 Mon Sep 17 00:00:00 2001
From: ShridharGoel <35566748+ShridharGoel@users.noreply.github.com>
Date: Fri, 5 Jun 2026 11:45:12 +0530
Subject: [PATCH 136/435] Restore non-English role translations

---
 src/languages/de.ts      | 13 ++++++++-----
 src/languages/es.ts      |  9 ++++++---
 src/languages/fr.ts      |  9 ++++++---
 src/languages/it.ts      | 13 ++++++++-----
 src/languages/ja.ts      | 11 +++++++----
 src/languages/nl.ts      | 11 +++++++----
 src/languages/pl.ts      |  9 ++++++---
 src/languages/pt-BR.ts   | 15 +++++++++------
 src/languages/zh-hans.ts | 11 +++++++----
 9 files changed, 64 insertions(+), 37 deletions(-)

diff --git a/src/languages/de.ts b/src/languages/de.ts
index 4aab5fbe808d..fc7c9886b7bd 100644
--- a/src/languages/de.ts
+++ b/src/languages/de.ts
@@ -4373,13 +4373,13 @@ ${amount} für ${merchant} – ${date}`,
             roleName: (role?: string) => {
                 switch (role) {
                     case CONST.POLICY.ROLE.ADMIN:
-                        return 'Admin';
+                        return 'Workspace-Administrator';
                     case CONST.POLICY.ROLE.AUDITOR:
                         return 'Prüfer';
                     case CONST.POLICY.ROLE.CARD_ADMIN:
-                        return 'Kartenverwaltung';
+                        return 'Kartenadministrator';
                     case CONST.POLICY.ROLE.PEOPLE_ADMIN:
-                        return 'Personenverwaltung';
+                        return 'Personalverwaltung';
                     case CONST.POLICY.ROLE.PAYMENTS_ADMIN:
                         return 'Zahlungsadministrator';
                     case CONST.POLICY.ROLE.USER:
@@ -6219,6 +6219,7 @@ _Für ausführlichere Anweisungen [besuchen Sie unsere Hilfeseite](${CONST.NETSU
             emptyRoleFilter: {title: 'Keine Mitglieder entsprechen diesem Filter', subtitle: 'Laden Sie ein Mitglied ein oder ändern Sie den Filter oben.'},
             configureHRSync: (providerName: string) => `Synchronisierung mit ${providerName} einrichten.`,
             syncWithHR: (providerName: string) => `Mit ${providerName} synchronisieren`,
+            makeCardAdmin: () => ({one: 'Als Karten-Admin festlegen', other: 'Zu Karten-Admins machen'}),
         },
         card: {
             getStartedIssuing: 'Beginne, indem du deine erste virtuelle oder physische Karte ausstellst.',
@@ -8389,8 +8390,10 @@ Fügen Sie weitere Ausgabelimits hinzu, um den Cashflow Ihres Unternehmens zu sc
                     `Die Verbindung für ${feedName} ist unterbrochen. Um Kartenimporte wiederherzustellen, <a href='${workspaceCompanyCardRoute}'>melden Sie sich bei Ihrer Bank an</a>.`,
                 plaidBalanceFailure: ({maskedAccountNumber, walletRoute}: {maskedAccountNumber: string; walletRoute: string}) =>
                     `Die Plaid-Verbindung zu Ihrem Geschäftskonto ist unterbrochen. Bitte <a href='${walletRoute}'>verbinden Sie Ihr Bankkonto ${maskedAccountNumber} erneut</a>, damit Sie Ihre Expensify Karten weiterhin verwenden können.`,
-                addEmployee: (email: string, role: string, didJoinPolicy?: boolean) =>
-                    didJoinPolicy ? `${email} ist über den Arbeitsbereichs-Einladungslink beigetreten` : `${email} als ${role === 'member' ? 'a' : 'an'} ${role} hinzugefügt`,
+                addEmployee: (email: string, role: string, didJoinPolicy?: boolean) => {
+                    const article = role.toLowerCase() === 'auditor' ? 'an' : 'ein';
+                    return didJoinPolicy ? `${email} ist über den Workspace-Einladungslink beigetreten` : `${email} als ${article} ${role} hinzugefügt`;
+                },
                 updateRole: ({email, currentRole, newRole}: UpdateRoleParams) => `hat die Rolle von ${email} in ${newRole} geändert (zuvor ${currentRole})`,
                 updatedCustomField1: (email: string, newValue: string, previousValue: string) => {
                     if (!newValue) {
diff --git a/src/languages/es.ts b/src/languages/es.ts
index 12fc795dbcd6..fd3b3fc61d12 100644
--- a/src/languages/es.ts
+++ b/src/languages/es.ts
@@ -4262,7 +4262,7 @@ ${amount} para ${merchant} - ${date}`,
             roleName: (role?: string) => {
                 switch (role) {
                     case CONST.POLICY.ROLE.ADMIN:
-                        return 'Administrador';
+                        return 'Administrador del espacio de trabajo';
                     case CONST.POLICY.ROLE.AUDITOR:
                         return 'Auditor';
                     case CONST.POLICY.ROLE.CARD_ADMIN:
@@ -6059,6 +6059,7 @@ ${amount} para ${merchant} - ${date}`,
                 `${memberName} tiene un informe en proceso pendiente de acción. Pídele que complete la acción requerida antes de eliminarlo del espacio de trabajo.`,
             configureHRSync: (providerName: string) => `Configura la sincronización de ${providerName}.`,
             syncWithHR: (providerName: string) => `Sincronizar con ${providerName}`,
+            makeCardAdmin: () => ({one: 'Hacer administrador de tarjeta', other: 'Hacer administradores de tarjetas'}),
         },
         accounting: {
             settings: 'configuración',
@@ -8181,8 +8182,10 @@ ${amount} para ${merchant} - ${date}`,
                     `La conexión ${feedName} está rota. Para restaurar las importaciones de tarjetas, <a href='${workspaceCompanyCardRoute}'>inicia sesión en tu banco</a>.`,
                 plaidBalanceFailure: ({maskedAccountNumber, walletRoute}: {maskedAccountNumber: string; walletRoute: string}) =>
                     `la conexión Plaid con tu cuenta bancaria de empresa está rota. Por favor, <a href='${walletRoute}'>reconecta tu cuenta bancaria ${maskedAccountNumber}</a> para poder seguir usando tus Tarjetas Expensify.`,
-                addEmployee: (email: string, role: string, didJoinPolicy?: boolean) =>
-                    didJoinPolicy ? `${email} se unió mediante el enlace de invitación del espacio de trabajo` : `se añadió ${email} como ${role === 'member' ? 'a' : 'a un'} ${role}`,
+                addEmployee: (email: string, role: string, didJoinPolicy?: boolean) => {
+                    const article = role.toLowerCase() === 'auditor' ? 'un' : 'a';
+                    return didJoinPolicy ? `${email} se unió a través del enlace de invitación del espacio de trabajo` : `añadió ${email} como ${article} ${role}`;
+                },
                 updateRole: ({email, currentRole, newRole}) => `actualizó el rol ${email} a ${newRole} (previamente ${currentRole})`,
                 updatedCustomField1: (email, newValue, previousValue) => {
                     if (!newValue) {
diff --git a/src/languages/fr.ts b/src/languages/fr.ts
index e1924676e2c2..7cb465772904 100644
--- a/src/languages/fr.ts
+++ b/src/languages/fr.ts
@@ -4385,7 +4385,7 @@ ${amount} pour ${merchant} - ${date}`,
             roleName: (role?: string) => {
                 switch (role) {
                     case CONST.POLICY.ROLE.ADMIN:
-                        return 'Administrateur';
+                        return 'Administrateur d’espace de travail';
                     case CONST.POLICY.ROLE.AUDITOR:
                         return 'Auditeur';
                     case CONST.POLICY.ROLE.CARD_ADMIN:
@@ -6244,6 +6244,7 @@ _Pour des instructions plus détaillées, [visitez notre site d’aide](${CONST.
             emptyRoleFilter: {title: 'Aucun membre ne correspond à ce filtre', subtitle: 'Invitez un membre ou modifiez le filtre ci-dessus.'},
             configureHRSync: (providerName: string) => `Configurer la synchronisation ${providerName}.`,
             syncWithHR: (providerName: string) => `Synchroniser avec ${providerName}`,
+            makeCardAdmin: () => ({one: 'Nommer administrateur de carte', other: 'Nommer des administrateurs de carte'}),
         },
         card: {
             getStartedIssuing: 'Commencez par émettre votre première carte virtuelle ou physique.',
@@ -8423,8 +8424,10 @@ Ajoutez davantage de règles de dépenses pour protéger la trésorerie de l’e
                     `La connexion ${feedName} est interrompue. Pour rétablir l’importation des cartes, <a href='${workspaceCompanyCardRoute}'>connectez-vous à votre banque</a>.`,
                 plaidBalanceFailure: ({maskedAccountNumber, walletRoute}: {maskedAccountNumber: string; walletRoute: string}) =>
                     `la connexion Plaid à votre compte bancaire professionnel est rompue. Veuillez <a href='${walletRoute}'>reconnecter votre compte bancaire ${maskedAccountNumber}</a> afin de pouvoir continuer à utiliser vos Cartes Expensify.`,
-                addEmployee: (email: string, role: string, didJoinPolicy?: boolean) =>
-                    didJoinPolicy ? `${email} a rejoint via le lien d’invitation de l’espace de travail` : `a ajouté ${email} en tant que ${role === 'member' ? 'a' : 'un'} ${role}`,
+                addEmployee: (email: string, role: string, didJoinPolicy?: boolean) => {
+                    const article = role.toLowerCase() === 'auditor' ? 'un' : 'un';
+                    return didJoinPolicy ? `${email} a rejoint via le lien d’invitation à l’espace de travail` : `a ajouté ${email} en tant que ${article} ${role}`;
+                },
                 updateRole: ({email, currentRole, newRole}: UpdateRoleParams) => `a mis à jour le rôle de ${email} en ${newRole} (précédemment ${currentRole})`,
                 updatedCustomField1: (email: string, newValue: string, previousValue: string) => {
                     if (!newValue) {
diff --git a/src/languages/it.ts b/src/languages/it.ts
index b74810e139e7..546421749bda 100644
--- a/src/languages/it.ts
+++ b/src/languages/it.ts
@@ -4359,13 +4359,13 @@ ${amount} per ${merchant} - ${date}`,
             roleName: (role?: string) => {
                 switch (role) {
                     case CONST.POLICY.ROLE.ADMIN:
-                        return 'Amministratore';
+                        return 'Amministratore spazio di lavoro';
                     case CONST.POLICY.ROLE.AUDITOR:
                         return 'Revisore';
                     case CONST.POLICY.ROLE.CARD_ADMIN:
-                        return 'Amministrazione carta';
+                        return 'Amministratore carta';
                     case CONST.POLICY.ROLE.PEOPLE_ADMIN:
-                        return 'Amministrazione persone';
+                        return 'Amministratore persone';
                     case CONST.POLICY.ROLE.PAYMENTS_ADMIN:
                         return 'Amministrazione pagamenti';
                     case CONST.POLICY.ROLE.USER:
@@ -6207,6 +6207,7 @@ _Per istruzioni più dettagliate, [visita il nostro sito di assistenza](${CONST.
             emptyRoleFilter: {title: 'Nessun membro corrisponde a questo filtro', subtitle: 'Invita un membro o modifica il filtro qui sopra.'},
             configureHRSync: (providerName: string) => `Configura la sincronizzazione di ${providerName}.`,
             syncWithHR: (providerName: string) => `Sincronizza con ${providerName}`,
+            makeCardAdmin: () => ({one: 'Rendi amministratore della carta', other: 'Rendi amministratori carta'}),
         },
         card: {
             getStartedIssuing: 'Inizia emettendo la tua prima carta virtuale o fisica.',
@@ -8378,8 +8379,10 @@ Aggiungi altre regole di spesa per proteggere il flusso di cassa aziendale.`,
                     `La connessione ${feedName} è interrotta. Per ripristinare le importazioni della carta, <a href='${workspaceCompanyCardRoute}'>accedi alla tua banca</a>.`,
                 plaidBalanceFailure: ({maskedAccountNumber, walletRoute}: {maskedAccountNumber: string; walletRoute: string}) =>
                     `la connessione Plaid al conto bancario della tua azienda non funziona. Per favore, <a href='${walletRoute}'>ricollega il conto bancario ${maskedAccountNumber}</a> così puoi continuare a usare le tue Carte Expensify.`,
-                addEmployee: (email: string, role: string, didJoinPolicy?: boolean) =>
-                    didJoinPolicy ? `${email} si è unito tramite il link di invito allo spazio di lavoro` : `ha aggiunto ${email} come ${role === 'member' ? 'a' : 'un'} ${role}`,
+                addEmployee: (email: string, role: string, didJoinPolicy?: boolean) => {
+                    const article = role.toLowerCase() === 'auditor' ? 'un' : 'a';
+                    return didJoinPolicy ? `${email} si è unito tramite il link di invito dello spazio di lavoro` : `ha aggiunto ${email} come ${article} ${role}`;
+                },
                 updateRole: ({email, currentRole, newRole}: UpdateRoleParams) => `ha aggiornato il ruolo di ${email} a ${newRole} (in precedenza ${currentRole})`,
                 updatedCustomField1: (email: string, newValue: string, previousValue: string) => {
                     if (!newValue) {
diff --git a/src/languages/ja.ts b/src/languages/ja.ts
index b001b3c7cfd5..d097b5f60fc4 100644
--- a/src/languages/ja.ts
+++ b/src/languages/ja.ts
@@ -4327,7 +4327,7 @@ ${integrationName === CONST.ONBOARDING_ACCOUNTING_MAPPING.other ? 'あなたの'
             roleName: (role?: string) => {
                 switch (role) {
                     case CONST.POLICY.ROLE.ADMIN:
-                        return '管理者';
+                        return 'ワークスペース管理者';
                     case CONST.POLICY.ROLE.AUDITOR:
                         return '監査担当者';
                     case CONST.POLICY.ROLE.CARD_ADMIN:
@@ -4335,7 +4335,7 @@ ${integrationName === CONST.ONBOARDING_ACCOUNTING_MAPPING.other ? 'あなたの'
                     case CONST.POLICY.ROLE.PEOPLE_ADMIN:
                         return 'メンバー管理';
                     case CONST.POLICY.ROLE.PAYMENTS_ADMIN:
-                        return '支払管理者';
+                        return '支払い管理者';
                     case CONST.POLICY.ROLE.USER:
                         return 'メンバー';
                     default:
@@ -6134,6 +6134,7 @@ _詳しい手順については、[ヘルプサイトをご覧ください](${CO
             emptyRoleFilter: {title: 'このフィルターに一致するメンバーはいません', subtitle: 'メンバーを招待するか、上のフィルターを変更してください。'},
             configureHRSync: (providerName: string) => `${providerName} の同期を設定します。`,
             syncWithHR: (providerName: string) => `${providerName}と同期`,
+            makeCardAdmin: () => ({one: 'カード管理者にする', other: 'カード管理者を作成'}),
         },
         card: {
             getStartedIssuing: 'まずは最初のバーチャルカードまたは物理カードを発行しましょう。',
@@ -8268,8 +8269,10 @@ ${reportName}
                     `${feedName} との接続が切断されています。カードの取引明細の取込を再開するには、<a href='${workspaceCompanyCardRoute}'>銀行にログイン</a>してください。`,
                 plaidBalanceFailure: ({maskedAccountNumber, walletRoute}: {maskedAccountNumber: string; walletRoute: string}) =>
                     `Plaid によるビジネス銀行口座との接続が切断されています。Expensify カードを引き続きご利用いただくために、<a href='${walletRoute}'>銀行口座 ${maskedAccountNumber} を再接続</a>してください。`,
-                addEmployee: (email: string, role: string, didJoinPolicy?: boolean) =>
-                    didJoinPolicy ? `${email} さんがワークスペースの招待リンクから参加しました` : `${role === 'member' ? 'a' : '1つの'} ${role} として ${email} を追加しました`,
+                addEmployee: (email: string, role: string, didJoinPolicy?: boolean) => {
+                    const article = role.toLowerCase() === 'auditor' ? '一つの' : 'a';
+                    return didJoinPolicy ? `${email} さんがワークスペースの招待リンクから参加しました` : `${email} を${article}${role}として追加しました`;
+                },
                 updateRole: ({email, currentRole, newRole}: UpdateRoleParams) => `${email} のロールを ${currentRole} から ${newRole} に更新しました`,
                 updatedCustomField1: (email: string, newValue: string, previousValue: string) => {
                     if (!newValue) {
diff --git a/src/languages/nl.ts b/src/languages/nl.ts
index ddd96d1d7e65..ac1bbdf9d83f 100644
--- a/src/languages/nl.ts
+++ b/src/languages/nl.ts
@@ -4355,13 +4355,13 @@ ${amount} voor ${merchant} - ${date}`,
             roleName: (role?: string) => {
                 switch (role) {
                     case CONST.POLICY.ROLE.ADMIN:
-                        return 'Beheer';
+                        return 'Beheerder van workspace';
                     case CONST.POLICY.ROLE.AUDITOR:
                         return 'Auditor';
                     case CONST.POLICY.ROLE.CARD_ADMIN:
                         return 'Kaartbeheer';
                     case CONST.POLICY.ROLE.PEOPLE_ADMIN:
-                        return 'Mensenbeheer';
+                        return 'Personenbeheer';
                     case CONST.POLICY.ROLE.PAYMENTS_ADMIN:
                         return 'Beheerder betalingen';
                     case CONST.POLICY.ROLE.USER:
@@ -6186,6 +6186,7 @@ _Voor meer gedetailleerde instructies, [bezoek onze help-site](${CONST.NETSUITE_
             emptyRoleFilter: {title: 'Geen leden komen overeen met dit filter', subtitle: 'Nodig een lid uit of wijzig het filter hierboven.'},
             configureHRSync: (providerName: string) => `Stel ${providerName}-synchronisatie in.`,
             syncWithHR: (providerName: string) => `Synchroniseren met ${providerName}`,
+            makeCardAdmin: () => ({one: 'Kaartbeheerder maken', other: 'Maak kaartbeheerders'}),
         },
         card: {
             getStartedIssuing: 'Begin met het uitgeven van je eerste virtuele of fysieke kaart.',
@@ -8346,8 +8347,10 @@ er bestedingsregels toe om de kasstroom van het bedrijf te beschermen.`,
                     `De verbinding met ${feedName} is verbroken. <a href='${workspaceCompanyCardRoute}'>Log in bij je bank</a> om kaartimports te herstellen.`,
                 plaidBalanceFailure: ({maskedAccountNumber, walletRoute}: {maskedAccountNumber: string; walletRoute: string}) =>
                     `de Plaid-verbinding met je zakelijke bankrekening is verbroken. <a href='${walletRoute}'>Verbind je bankrekening ${maskedAccountNumber} opnieuw</a> zodat je je Expensify Kaarten kunt blijven gebruiken.`,
-                addEmployee: (email: string, role: string, didJoinPolicy?: boolean) =>
-                    didJoinPolicy ? `${email} is via de werkruimte-uitnodigingslink lid geworden` : `heeft ${email} toegevoegd als ${role === 'member' ? 'een' : 'een'} ${role}`,
+                addEmployee: (email: string, role: string, didJoinPolicy?: boolean) => {
+                    const article = role.toLowerCase() === 'auditor' ? 'een' : 'een';
+                    return didJoinPolicy ? `${email} is via de werkruimte-uitnodigingslink lid geworden` : `heeft ${email} toegevoegd als ${article} ${role}`;
+                },
                 updateRole: ({email, currentRole, newRole}: UpdateRoleParams) => `heeft de rol van ${email} bijgewerkt naar ${newRole} (voorheen ${currentRole})`,
                 updatedCustomField1: (email: string, newValue: string, previousValue: string) => {
                     if (!newValue) {
diff --git a/src/languages/pl.ts b/src/languages/pl.ts
index 4d73d8b074ee..b74aca62d868 100644
--- a/src/languages/pl.ts
+++ b/src/languages/pl.ts
@@ -4347,7 +4347,7 @@ ${amount} dla ${merchant} - ${date}`,
             roleName: (role?: string) => {
                 switch (role) {
                     case CONST.POLICY.ROLE.ADMIN:
-                        return 'Administrator';
+                        return 'Administrator przestrzeni roboczej';
                     case CONST.POLICY.ROLE.AUDITOR:
                         return 'Audytor';
                     case CONST.POLICY.ROLE.CARD_ADMIN:
@@ -6181,6 +6181,7 @@ _Aby uzyskać bardziej szczegółowe instrukcje, [odwiedź naszą stronę pomocy
             emptyRoleFilter: {title: 'Żadni członkowie nie pasują do tego filtra', subtitle: 'Zaproś członka lub zmień filtr powyżej.'},
             configureHRSync: (providerName: string) => `Skonfiguruj synchronizację ${providerName}.`,
             syncWithHR: (providerName: string) => `Synchronizuj z ${providerName}`,
+            makeCardAdmin: () => ({one: 'Ustaw jako administratora karty', other: 'Ustaw administratorów kart'}),
         },
         card: {
             getStartedIssuing: 'Zacznij od wydania swojej pierwszej wirtualnej lub fizycznej karty.',
@@ -8337,8 +8338,10 @@ Dodaj więcej zasad wydatków, żeby chronić płynność finansową firmy.`,
                     `Połączenie ${feedName} jest przerwane. Aby przywrócić importy kart, <a href='${workspaceCompanyCardRoute}'>zaloguj się do swojego banku</a>.`,
                 plaidBalanceFailure: ({maskedAccountNumber, walletRoute}: {maskedAccountNumber: string; walletRoute: string}) =>
                     `połączenie Plaid z twoim firmowym kontem bankowym jest przerwane. Proszę, <a href='${walletRoute}'>połącz ponownie swoje konto bankowe ${maskedAccountNumber}</a>, aby móc dalej używać Kart Expensify.`,
-                addEmployee: (email: string, role: string, didJoinPolicy?: boolean) =>
-                    didJoinPolicy ? `${email} dołączył(a) przez link z zaproszeniem do przestrzeni roboczej` : `dodano ${email} jako ${role === 'member' ? 'a' : 'jeden'} ${role}`,
+                addEmployee: (email: string, role: string, didJoinPolicy?: boolean) => {
+                    const article = role.toLowerCase() === 'auditor' ? 'jeden' : 'a';
+                    return didJoinPolicy ? `${email} dołączył przez link zaproszenia do przestrzeni roboczej` : `dodano ${email} jako ${article} ${role}`;
+                },
                 updateRole: ({email, currentRole, newRole}: UpdateRoleParams) => `zaktualizowano rolę użytkownika ${email} na ${newRole} (wcześniej ${currentRole})`,
                 updatedCustomField1: (email: string, newValue: string, previousValue: string) => {
                     if (!newValue) {
diff --git a/src/languages/pt-BR.ts b/src/languages/pt-BR.ts
index b1b7653c6e71..a42acd5d15ab 100644
--- a/src/languages/pt-BR.ts
+++ b/src/languages/pt-BR.ts
@@ -4348,15 +4348,15 @@ ${amount} para ${merchant} - ${date}`,
             roleName: (role?: string) => {
                 switch (role) {
                     case CONST.POLICY.ROLE.ADMIN:
-                        return 'Admin';
+                        return 'Admin do workspace';
                     case CONST.POLICY.ROLE.AUDITOR:
                         return 'Auditor';
                     case CONST.POLICY.ROLE.CARD_ADMIN:
-                        return 'Admin. do Cartão';
+                        return 'Administrador do cartão';
                     case CONST.POLICY.ROLE.PEOPLE_ADMIN:
-                        return 'Administração de pessoas';
+                        return 'Admin de pessoas';
                     case CONST.POLICY.ROLE.PAYMENTS_ADMIN:
-                        return 'Admin de pagamentos';
+                        return 'Administrador de pagamentos';
                     case CONST.POLICY.ROLE.USER:
                         return 'Membro';
                     default:
@@ -6185,6 +6185,7 @@ _Para instruções mais detalhadas, [visite nossa central de ajuda](${CONST.NETS
             emptyRoleFilter: {title: 'Nenhum membro corresponde a este filtro', subtitle: 'Convide um membro ou altere o filtro acima.'},
             configureHRSync: (providerName: string) => `Configurar a sincronização do ${providerName}.`,
             syncWithHR: (providerName: string) => `Sincronizar com ${providerName}`,
+            makeCardAdmin: () => ({one: 'Tornar admin do cartão', other: 'Tornar administradores de cartão'}),
         },
         card: {
             getStartedIssuing: 'Comece emitindo seu primeiro cartão virtual ou físico.',
@@ -8340,8 +8341,10 @@ Adicione mais regras de gasto para proteger o fluxo de caixa da empresa.`,
                     `A conexão de ${feedName} está interrompida. Para restaurar as importações do cartão, <a href='${workspaceCompanyCardRoute}'>faça login no seu banco</a>.`,
                 plaidBalanceFailure: ({maskedAccountNumber, walletRoute}: {maskedAccountNumber: string; walletRoute: string}) =>
                     `a conexão Plaid com a sua conta bancária empresarial foi interrompida. Por favor, <a href='${walletRoute}'>reconecte sua conta bancária ${maskedAccountNumber}</a> para continuar usando seus Cartões Expensify.`,
-                addEmployee: (email: string, role: string, didJoinPolicy?: boolean) =>
-                    didJoinPolicy ? `${email} entrou pelo link de convite do workspace` : `adicionou ${email} como ${role === 'member' ? 'a' : 'um'} ${role}`,
+                addEmployee: (email: string, role: string, didJoinPolicy?: boolean) => {
+                    const article = role.toLowerCase() === 'auditor' ? 'um' : 'um';
+                    return didJoinPolicy ? `${email} entrou pelo link de convite do workspace` : `adicionou ${email} como ${article} ${role}`;
+                },
                 updateRole: ({email, currentRole, newRole}: UpdateRoleParams) => `atualizou a função de ${email} para ${newRole} (anteriormente ${currentRole})`,
                 updatedCustomField1: (email: string, newValue: string, previousValue: string) => {
                     if (!newValue) {
diff --git a/src/languages/zh-hans.ts b/src/languages/zh-hans.ts
index 4d017ea5a363..5a147cf5d8bf 100644
--- a/src/languages/zh-hans.ts
+++ b/src/languages/zh-hans.ts
@@ -4251,13 +4251,13 @@ ${amount}，商户：${merchant} - 日期：${date}`,
             roleName: (role?: string) => {
                 switch (role) {
                     case CONST.POLICY.ROLE.ADMIN:
-                        return '管理员';
+                        return '工作区管理员';
                     case CONST.POLICY.ROLE.AUDITOR:
                         return '审计员';
                     case CONST.POLICY.ROLE.CARD_ADMIN:
                         return '卡片管理员';
                     case CONST.POLICY.ROLE.PEOPLE_ADMIN:
-                        return '人员管理';
+                        return '人员管理员';
                     case CONST.POLICY.ROLE.PAYMENTS_ADMIN:
                         return '付款管理员';
                     case CONST.POLICY.ROLE.USER:
@@ -6022,6 +6022,7 @@ _如需更详细的说明，请[访问我们的帮助网站](${CONST.NETSUITE_IM
             emptyRoleFilter: {title: '没有成员符合此筛选条件', subtitle: '邀请成员或更改上方的筛选条件。'},
             configureHRSync: (providerName: string) => `配置 ${providerName} 同步。`,
             syncWithHR: (providerName: string) => `与 ${providerName} 同步`,
+            makeCardAdmin: () => ({one: '设为卡片管理员', other: '设为卡片管理员'}),
         },
         card: {
             getStartedIssuing: '从发放您的第一张虚拟卡或实体卡开始使用。',
@@ -8108,8 +8109,10 @@ ${reportName}
                     `${feedName} 连接已中断。要恢复银行卡导入，请<a href='${workspaceCompanyCardRoute}'>登录您的银行账户</a>。`,
                 plaidBalanceFailure: ({maskedAccountNumber, walletRoute}: {maskedAccountNumber: string; walletRoute: string}) =>
                     `您与企业银行账户的 Plaid 连接已中断。请<a href='${walletRoute}'>重新连接您的银行账户 ${maskedAccountNumber}</a>，以便继续使用 Expensify 卡。`,
-                addEmployee: (email: string, role: string, didJoinPolicy?: boolean) =>
-                    didJoinPolicy ? `${email} 通过工作区邀请链接加入` : `已将 ${email} 添加为 ${role === 'member' ? '一个' : '一个'} 的 ${role}`,
+                addEmployee: (email: string, role: string, didJoinPolicy?: boolean) => {
+                    const article = role.toLowerCase() === 'auditor' ? '一' : 'a';
+                    return didJoinPolicy ? `${email} 通过工作区邀请链接加入` : `已将 ${email} 添加为 ${article} ${role}`;
+                },
                 updateRole: ({email, currentRole, newRole}: UpdateRoleParams) => `已将 ${email} 的角色更新为 ${newRole}（先前为 ${currentRole}）`,
                 updatedCustomField1: (email: string, newValue: string, previousValue: string) => {
                     if (!newValue) {

From 1866e75891d732d15a1b21e1fbefcd50472a6f16 Mon Sep 17 00:00:00 2001
From: ShridharGoel <35566748+ShridharGoel@users.noreply.github.com>
Date: Fri, 5 Jun 2026 14:10:01 +0530
Subject: [PATCH 137/435] Fix Card Admin spend rule access

---
 .../configuration/SpendRuleMaxAmountBase.tsx  |  5 ++-
 .../SpendRuleMerchantEditBase.tsx             |  5 ++-
 .../configuration/SpendRuleMerchantsBase.tsx  |  5 ++-
 src/hooks/useCanWriteCardSpendRules.ts        | 16 +++++++
 .../WorkspaceCompanyCardFeedSelectorPage.tsx  |  6 ++-
 .../rules/SpendRules/SpendRuleCardPage.tsx    |  5 ++-
 .../SpendRules/SpendRuleCategoryPage.tsx      | 27 +++++++++---
 .../rules/SpendRules/SpendRulePageBase.tsx    | 42 ++++++++++---------
 8 files changed, 80 insertions(+), 31 deletions(-)
 create mode 100644 src/hooks/useCanWriteCardSpendRules.ts

diff --git a/src/components/SpendRules/configuration/SpendRuleMaxAmountBase.tsx b/src/components/SpendRules/configuration/SpendRuleMaxAmountBase.tsx
index 5f1fe84d2679..7c2459c6678e 100644
--- a/src/components/SpendRules/configuration/SpendRuleMaxAmountBase.tsx
+++ b/src/components/SpendRules/configuration/SpendRuleMaxAmountBase.tsx
@@ -8,6 +8,7 @@ import HeaderWithBackButton from '@components/HeaderWithBackButton';
 import ScreenWrapper from '@components/ScreenWrapper';
 import Text from '@components/Text';
 import useAutoFocusInput from '@hooks/useAutoFocusInput';
+import useCanWriteCardSpendRules from '@hooks/useCanWriteCardSpendRules';
 import useLocalize from '@hooks/useLocalize';
 import useThemeStyles from '@hooks/useThemeStyles';
 import Navigation from '@libs/Navigation/Navigation';
@@ -27,6 +28,7 @@ function SpendRuleMaxAmountBase({policyID, maxAmount, currencyCode, onMaxAmountC
     const styles = useThemeStyles();
     const {translate} = useLocalize();
     const {inputCallbackRef} = useAutoFocusInput();
+    const canWriteCardSpendRules = useCanWriteCardSpendRules(policyID);
 
     const goBack = () => {
         Navigation.goBack();
@@ -40,8 +42,9 @@ function SpendRuleMaxAmountBase({policyID, maxAmount, currencyCode, onMaxAmountC
     return (
         <AccessOrNotFoundWrapper
             policyID={policyID}
-            accessVariants={[CONST.POLICY.ACCESS_VARIANTS.ADMIN, CONST.POLICY.ACCESS_VARIANTS.PAID]}
+            accessVariants={[CONST.POLICY.ACCESS_VARIANTS.PAID]}
             featureName={CONST.POLICY.MORE_FEATURES.ARE_RULES_ENABLED}
+            shouldBeBlocked={!canWriteCardSpendRules}
         >
             <ScreenWrapper
                 shouldEnableMaxHeight
diff --git a/src/components/SpendRules/configuration/SpendRuleMerchantEditBase.tsx b/src/components/SpendRules/configuration/SpendRuleMerchantEditBase.tsx
index d033abe52510..5134cf8864ca 100644
--- a/src/components/SpendRules/configuration/SpendRuleMerchantEditBase.tsx
+++ b/src/components/SpendRules/configuration/SpendRuleMerchantEditBase.tsx
@@ -12,6 +12,7 @@ import type {ListItem} from '@components/SelectionList/ListItem/types';
 import Text from '@components/Text';
 import TextInput from '@components/TextInput';
 import useAutoFocusInput from '@hooks/useAutoFocusInput';
+import useCanWriteCardSpendRules from '@hooks/useCanWriteCardSpendRules';
 import useLocalize from '@hooks/useLocalize';
 import useThemeStyles from '@hooks/useThemeStyles';
 import AccessOrNotFoundWrapper from '@pages/workspace/AccessOrNotFoundWrapper';
@@ -37,6 +38,7 @@ function SpendRuleMerchantEditBase({policyID, merchantIndex, merchantMatchTypes,
     const {translate} = useLocalize();
     const styles = useThemeStyles();
     const {inputCallbackRef} = useAutoFocusInput();
+    const canWriteCardSpendRules = useCanWriteCardSpendRules(policyID);
 
     const isNew = merchantIndex === ROUTES.NEW;
     const index = isNew ? -1 : Number(merchantIndex);
@@ -98,7 +100,8 @@ function SpendRuleMerchantEditBase({policyID, merchantIndex, merchantMatchTypes,
         <AccessOrNotFoundWrapper
             policyID={policyID}
             featureName={CONST.POLICY.MORE_FEATURES.ARE_RULES_ENABLED}
-            accessVariants={[CONST.POLICY.ACCESS_VARIANTS.ADMIN, CONST.POLICY.ACCESS_VARIANTS.PAID]}
+            accessVariants={[CONST.POLICY.ACCESS_VARIANTS.PAID]}
+            shouldBeBlocked={!canWriteCardSpendRules}
         >
             <ScreenWrapper
                 testID="SpendRuleMerchantEditPage"
diff --git a/src/components/SpendRules/configuration/SpendRuleMerchantsBase.tsx b/src/components/SpendRules/configuration/SpendRuleMerchantsBase.tsx
index 3db6f730f0b3..4b4da33b62f5 100644
--- a/src/components/SpendRules/configuration/SpendRuleMerchantsBase.tsx
+++ b/src/components/SpendRules/configuration/SpendRuleMerchantsBase.tsx
@@ -8,6 +8,7 @@ import MenuItemWithTopDescription from '@components/MenuItemWithTopDescription';
 import ScreenWrapper from '@components/ScreenWrapper';
 import ScrollView from '@components/ScrollView';
 import {useMemoizedLazyExpensifyIcons, useMemoizedLazyIllustrations} from '@hooks/useLazyAsset';
+import useCanWriteCardSpendRules from '@hooks/useCanWriteCardSpendRules';
 import useLocalize from '@hooks/useLocalize';
 import useThemeStyles from '@hooks/useThemeStyles';
 import Navigation from '@navigation/Navigation';
@@ -29,6 +30,7 @@ function SpendRuleMerchantsBase({policyID, action, merchantMatchTypes, merchantN
     const {translate} = useLocalize();
     const expensifyIcons = useMemoizedLazyExpensifyIcons(['Plus']);
     const illustrations = useMemoizedLazyIllustrations(['FoodTruck']);
+    const canWriteCardSpendRules = useCanWriteCardSpendRules(policyID);
 
     const emptyStateTitle =
         action === CONST.SPEND_RULES.ACTION.BLOCK ? translate('workspace.rules.spendRules.noBlockedMerchants') : translate('workspace.rules.spendRules.noAllowedMerchants');
@@ -52,7 +54,8 @@ function SpendRuleMerchantsBase({policyID, action, merchantMatchTypes, merchantN
         <AccessOrNotFoundWrapper
             policyID={policyID}
             featureName={CONST.POLICY.MORE_FEATURES.ARE_RULES_ENABLED}
-            accessVariants={[CONST.POLICY.ACCESS_VARIANTS.ADMIN, CONST.POLICY.ACCESS_VARIANTS.PAID]}
+            accessVariants={[CONST.POLICY.ACCESS_VARIANTS.PAID]}
+            shouldBeBlocked={!canWriteCardSpendRules}
         >
             <ScreenWrapper
                 testID="SpendRuleMerchantsPage"
diff --git a/src/hooks/useCanWriteCardSpendRules.ts b/src/hooks/useCanWriteCardSpendRules.ts
new file mode 100644
index 000000000000..5ab111fa95db
--- /dev/null
+++ b/src/hooks/useCanWriteCardSpendRules.ts
@@ -0,0 +1,16 @@
+import {canMemberWrite} from '@libs/PolicyUtils';
+import CONST from '@src/CONST';
+import useCurrentUserPersonalDetails from './useCurrentUserPersonalDetails';
+import usePolicy from './usePolicy';
+
+function useCanWriteCardSpendRules(policyID: string | undefined): boolean {
+    const policy = usePolicy(policyID);
+    const {login = ''} = useCurrentUserPersonalDetails();
+
+    return (
+        canMemberWrite(policy, login, CONST.POLICY.POLICY_FEATURE.RULES) ||
+        canMemberWrite(policy, login, CONST.POLICY.POLICY_FEATURE.EXPENSIFY_CARD)
+    );
+}
+
+export default useCanWriteCardSpendRules;
diff --git a/src/pages/workspace/companyCards/WorkspaceCompanyCardFeedSelectorPage.tsx b/src/pages/workspace/companyCards/WorkspaceCompanyCardFeedSelectorPage.tsx
index abfe04ae4c06..619bc32e040b 100644
--- a/src/pages/workspace/companyCards/WorkspaceCompanyCardFeedSelectorPage.tsx
+++ b/src/pages/workspace/companyCards/WorkspaceCompanyCardFeedSelectorPage.tsx
@@ -22,6 +22,7 @@ import useNetwork from '@hooks/useNetwork';
 import useOnyx from '@hooks/useOnyx';
 import useOtherFeedsForFeedSelector from '@hooks/useOtherFeedsForFeedSelector';
 import type {CardFeedListItem} from '@hooks/useOtherFeedsForFeedSelector';
+import usePolicyFeatureWriteAccess from '@hooks/usePolicyFeatureWriteAccess';
 import usePolicy from '@hooks/usePolicy';
 import usePrimaryContactMethod from '@hooks/usePrimaryContactMethod';
 import useThemeIllustrations from '@hooks/useThemeIllustrations';
@@ -62,6 +63,7 @@ function WorkspaceCompanyCardFeedSelectorPage({route}: WorkspaceCompanyCardFeedS
     const illustrations = useThemeIllustrations();
     const companyCardFeedIcons = useCompanyCardFeedIcons();
     const {isBlockedToAddNewFeeds} = useIsBlockedToAddFeed(policyID);
+    const {canWrite: canWriteCompanyCards} = usePolicyFeatureWriteAccess(policy, CONST.POLICY.POLICY_FEATURE.COMPANY_CARDS);
     const icons = useMemoizedLazyExpensifyIcons(['Plus']);
     const [feedWithError, setFeedWithError] = useState<{feed?: string; error?: Errors} | undefined>(undefined);
 
@@ -162,7 +164,7 @@ function WorkspaceCompanyCardFeedSelectorPage({route}: WorkspaceCompanyCardFeedS
         setFeedWithError(undefined);
     };
 
-    const otherMenuItemFeeds = (
+    const otherMenuItemFeeds = canWriteCompanyCards ? (
         <View style={[styles.w100, styles.flexColumn]}>
             <MenuItem
                 title={translate('workspace.companyCards.addCards')}
@@ -197,7 +199,7 @@ function WorkspaceCompanyCardFeedSelectorPage({route}: WorkspaceCompanyCardFeedS
                 </>
             )}
         </View>
-    );
+    ) : null;
 
     return (
         <AccessOrNotFoundWrapper
diff --git a/src/pages/workspace/rules/SpendRules/SpendRuleCardPage.tsx b/src/pages/workspace/rules/SpendRules/SpendRuleCardPage.tsx
index 0094a49c59da..a6db64489632 100644
--- a/src/pages/workspace/rules/SpendRules/SpendRuleCardPage.tsx
+++ b/src/pages/workspace/rules/SpendRules/SpendRuleCardPage.tsx
@@ -12,6 +12,7 @@ import CardListItem from '@components/SelectionList/ListItem/CardListItem';
 import type {AdditionalCardProps} from '@components/SelectionList/ListItem/CardListItem';
 import type {ListItem} from '@components/SelectionList/types';
 import {useCompanyCardFeedIcons} from '@hooks/useCompanyCardIcons';
+import useCanWriteCardSpendRules from '@hooks/useCanWriteCardSpendRules';
 import useDefaultFundID from '@hooks/useDefaultFundID';
 import {useMemoizedLazyIllustrations} from '@hooks/useLazyAsset';
 import useLocalize from '@hooks/useLocalize';
@@ -78,6 +79,7 @@ function SpendRuleCardPage({route}: SpendRuleCardPageProps) {
     const {policyID, ruleID} = route.params;
     const styles = useThemeStyles();
     const {translate, localeCompare} = useLocalize();
+    const canWriteCardSpendRules = useCanWriteCardSpendRules(policyID);
     const defaultFundID = useDefaultFundID(policyID);
     const [countryCode = CONST.DEFAULT_COUNTRY_CODE] = useOnyx(ONYXKEYS.COUNTRY_CODE);
     const [personalDetails] = useOnyx(ONYXKEYS.PERSONAL_DETAILS_LIST);
@@ -193,7 +195,8 @@ function SpendRuleCardPage({route}: SpendRuleCardPageProps) {
         <AccessOrNotFoundWrapper
             policyID={policyID}
             featureName={CONST.POLICY.MORE_FEATURES.ARE_RULES_ENABLED}
-            accessVariants={[CONST.POLICY.ACCESS_VARIANTS.ADMIN, CONST.POLICY.ACCESS_VARIANTS.PAID]}
+            accessVariants={[CONST.POLICY.ACCESS_VARIANTS.PAID]}
+            shouldBeBlocked={!canWriteCardSpendRules}
         >
             {isCardSettingsLoading ? (
                 <FullScreenLoadingIndicator
diff --git a/src/pages/workspace/rules/SpendRules/SpendRuleCategoryPage.tsx b/src/pages/workspace/rules/SpendRules/SpendRuleCategoryPage.tsx
index feb1b4e84b51..05f1ee57725e 100644
--- a/src/pages/workspace/rules/SpendRules/SpendRuleCategoryPage.tsx
+++ b/src/pages/workspace/rules/SpendRules/SpendRuleCategoryPage.tsx
@@ -1,11 +1,21 @@
 import React from 'react';
 import SpendRuleCategoryBase from '@components/SpendRules/configuration/SpendRuleCategoryBase';
+import useCanWriteCardSpendRules from '@hooks/useCanWriteCardSpendRules';
 import useOnyx from '@hooks/useOnyx';
 import {updateDraftSpendRule} from '@libs/actions/User';
+import type {PlatformStackScreenProps} from '@libs/Navigation/PlatformStackNavigation/types';
+import type {SettingsNavigatorParamList} from '@libs/Navigation/types';
+import AccessOrNotFoundWrapper from '@pages/workspace/AccessOrNotFoundWrapper';
+import CONST from '@src/CONST';
 import ONYXKEYS from '@src/ONYXKEYS';
+import type SCREENS from '@src/SCREENS';
 import type {SpendRuleCategory} from '@src/types/form/SpendRuleForm';
 
-function SpendRuleCategoryPage() {
+type SpendRuleCategoryPageProps = PlatformStackScreenProps<SettingsNavigatorParamList, typeof SCREENS.WORKSPACE.RULES_SPEND_CATEGORY>;
+
+function SpendRuleCategoryPage({route}: SpendRuleCategoryPageProps) {
+    const {policyID} = route.params;
+    const canWriteCardSpendRules = useCanWriteCardSpendRules(policyID);
     const [spendRuleForm] = useOnyx(ONYXKEYS.FORMS.SPEND_RULE_FORM);
 
     const onCategoriesChange = (categories: SpendRuleCategory[]) => {
@@ -13,10 +23,17 @@ function SpendRuleCategoryPage() {
     };
 
     return (
-        <SpendRuleCategoryBase
-            categories={spendRuleForm?.categories ?? []}
-            onCategoriesChange={onCategoriesChange}
-        />
+        <AccessOrNotFoundWrapper
+            policyID={policyID}
+            featureName={CONST.POLICY.MORE_FEATURES.ARE_RULES_ENABLED}
+            accessVariants={[CONST.POLICY.ACCESS_VARIANTS.PAID]}
+            shouldBeBlocked={!canWriteCardSpendRules}
+        >
+            <SpendRuleCategoryBase
+                categories={spendRuleForm?.categories ?? []}
+                onCategoriesChange={onCategoriesChange}
+            />
+        </AccessOrNotFoundWrapper>
     );
 }
 
diff --git a/src/pages/workspace/rules/SpendRules/SpendRulePageBase.tsx b/src/pages/workspace/rules/SpendRules/SpendRulePageBase.tsx
index 4c3aa2481c7a..d5b3de6f79df 100644
--- a/src/pages/workspace/rules/SpendRules/SpendRulePageBase.tsx
+++ b/src/pages/workspace/rules/SpendRules/SpendRulePageBase.tsx
@@ -11,6 +11,7 @@ import ScreenWrapper from '@components/ScreenWrapper';
 import ScrollView from '@components/ScrollView';
 import Text from '@components/Text';
 import useConfirmModal from '@hooks/useConfirmModal';
+import useCanWriteCardSpendRules from '@hooks/useCanWriteCardSpendRules';
 import {useCurrencyListActions} from '@hooks/useCurrencyList';
 import useDefaultFundID from '@hooks/useDefaultFundID';
 import useLocalize from '@hooks/useLocalize';
@@ -63,7 +64,8 @@ function SpendRulePageBase({policyID, ruleID, titleKey, testID}: SpendRulePageBa
     const {translate} = useLocalize();
     const {showConfirmModal} = useConfirmModal();
     const policy = usePolicy(policyID);
-    const {canWrite: canWriteRules, showReadOnlyModal} = usePolicyFeatureWriteAccess(policy, CONST.POLICY.POLICY_FEATURE.RULES);
+    const {showReadOnlyModal} = usePolicyFeatureWriteAccess(policy, CONST.POLICY.POLICY_FEATURE.RULES);
+    const canWriteSpendRules = useCanWriteCardSpendRules(policyID);
     const domainAccountID = useDefaultFundID(policyID);
     const [spendRuleForm] = useOnyx(ONYXKEYS.FORMS.SPEND_RULE_FORM);
     const [expensifyCardSettings] = useOnyx(`${ONYXKEYS.COLLECTION.PRIVATE_EXPENSIFY_CARD_SETTINGS}${domainAccountID}`);
@@ -154,7 +156,7 @@ function SpendRulePageBase({policyID, ruleID, titleKey, testID}: SpendRulePageBa
     const errorMessage = getErrorMessage(hasSelectedCards, hasAnyRuleApplied, translate);
 
     const handleSaveRule = () => {
-        if (!canWriteRules) {
+        if (!canWriteSpendRules) {
             return;
         }
         if (errorMessage) {
@@ -173,7 +175,7 @@ function SpendRulePageBase({policyID, ruleID, titleKey, testID}: SpendRulePageBa
     };
 
     const handleDeleteRule = () => {
-        if (!canWriteRules) {
+        if (!canWriteSpendRules) {
             return;
         }
         if (!existingRule) {
@@ -201,7 +203,7 @@ function SpendRulePageBase({policyID, ruleID, titleKey, testID}: SpendRulePageBa
         return <NotFoundPage />;
     }
 
-    if (!isEditing && !!policy && !canWriteRules) {
+    if (!isEditing && !!policy && !canWriteSpendRules) {
         return <NotFoundPage />;
     }
 
@@ -209,8 +211,8 @@ function SpendRulePageBase({policyID, ruleID, titleKey, testID}: SpendRulePageBa
         <AccessOrNotFoundWrapper
             policyID={policyID}
             featureName={CONST.POLICY.MORE_FEATURES.ARE_RULES_ENABLED}
-            accessVariants={[CONST.POLICY.ACCESS_VARIANTS.ADMIN, CONST.POLICY.ACCESS_VARIANTS.PAID]}
-            policyFeature={CONST.POLICY.POLICY_FEATURE.RULES}
+            accessVariants={[CONST.POLICY.ACCESS_VARIANTS.PAID]}
+            shouldBeBlocked={!!policy?.id && !canWriteSpendRules}
         >
             <ScreenWrapper
                 testID={testID}
@@ -223,15 +225,15 @@ function SpendRulePageBase({policyID, ruleID, titleKey, testID}: SpendRulePageBa
                     <MenuItemWithTopDescription
                         description={translate('workspace.rules.spendRules.chooseCards')}
                         onPress={
-                            canWriteRules
+                            canWriteSpendRules
                                 ? () => {
                                       clearError();
                                       navigation.navigate(SCREENS.WORKSPACE.RULES_SPEND_CARD, {policyID, ruleID: currentRuleID});
                                   }
                                 : undefined
                         }
-                        shouldShowRightIcon={canWriteRules}
-                        interactive={canWriteRules}
+                        shouldShowRightIcon={canWriteSpendRules}
+                        interactive={canWriteSpendRules}
                         title={cardsMenuTitle}
                         numberOfLinesTitle={2}
                         titleStyle={styles.flex1}
@@ -242,7 +244,7 @@ function SpendRulePageBase({policyID, ruleID, titleKey, testID}: SpendRulePageBa
                         <SpendRuleRestrictionTypeToggle
                             restrictionAction={restrictionAction}
                             onSelect={(action) => {
-                                if (!canWriteRules) {
+                                if (!canWriteSpendRules) {
                                     showReadOnlyModal();
                                     return;
                                 }
@@ -254,15 +256,15 @@ function SpendRulePageBase({policyID, ruleID, titleKey, testID}: SpendRulePageBa
                     <MenuItemWithTopDescription
                         description={translate('common.merchant')}
                         onPress={
-                            canWriteRules
+                            canWriteSpendRules
                                 ? () => {
                                       clearError();
                                       navigation.navigate(SCREENS.WORKSPACE.RULES_SPEND_MERCHANTS, {policyID, ruleID: currentRuleID});
                                   }
                                 : undefined
                         }
-                        shouldShowRightIcon={canWriteRules}
-                        interactive={canWriteRules}
+                        shouldShowRightIcon={canWriteSpendRules}
+                        interactive={canWriteSpendRules}
                         title={getMerchantMenuTitle(spendRuleForm?.merchantNames)}
                         numberOfLinesTitle={2}
                         titleStyle={styles.flex1}
@@ -271,15 +273,15 @@ function SpendRulePageBase({policyID, ruleID, titleKey, testID}: SpendRulePageBa
                     <MenuItemWithTopDescription
                         description={translate('workspace.rules.spendRules.spendCategory')}
                         onPress={
-                            canWriteRules
+                            canWriteSpendRules
                                 ? () => {
                                       clearError();
                                       navigation.navigate(SCREENS.WORKSPACE.RULES_SPEND_CATEGORY, {policyID, ruleID: currentRuleID});
                                   }
                                 : undefined
                         }
-                        shouldShowRightIcon={canWriteRules}
-                        interactive={canWriteRules}
+                        shouldShowRightIcon={canWriteSpendRules}
+                        interactive={canWriteSpendRules}
                         title={categoriesMenuTitle}
                         numberOfLinesTitle={2}
                         titleStyle={styles.flex1}
@@ -288,7 +290,7 @@ function SpendRulePageBase({policyID, ruleID, titleKey, testID}: SpendRulePageBa
                     <MenuItemWithTopDescription
                         description={translate('workspace.rules.spendRules.maxAmount')}
                         onPress={
-                            canWriteRules
+                            canWriteSpendRules
                                 ? () => {
                                       clearError();
                                       if (!selectedCurrency) {
@@ -299,14 +301,14 @@ function SpendRulePageBase({policyID, ruleID, titleKey, testID}: SpendRulePageBa
                                   }
                                 : undefined
                         }
-                        shouldShowRightIcon={canWriteRules}
-                        interactive={canWriteRules}
+                        shouldShowRightIcon={canWriteSpendRules}
+                        interactive={canWriteSpendRules}
                         title={maxAmountMenuTitle}
                         titleStyle={styles.flex1}
                         sentryLabel={CONST.SENTRY_LABEL.WORKSPACE.RULES.MERCHANT_RULE_SECTION_ITEM}
                     />
                 </ScrollView>
-                {canWriteRules && (
+                {canWriteSpendRules && (
                     <FormAlertWithSubmitButton
                         buttonText={translate('workspace.rules.spendRules.saveRule')}
                         containerStyles={[styles.m4, styles.mb5]}

From da43dcc20547762de5f76b7921d4fe78f41dceb1 Mon Sep 17 00:00:00 2001
From: ShridharGoel <35566748+ShridharGoel@users.noreply.github.com>
Date: Fri, 5 Jun 2026 14:44:03 +0530
Subject: [PATCH 138/435] Prettier fix

---
 .../SpendRules/configuration/SpendRuleMerchantsBase.tsx      | 2 +-
 src/hooks/useCanWriteCardSpendRules.ts                       | 5 +----
 .../companyCards/WorkspaceCompanyCardFeedSelectorPage.tsx    | 2 +-
 src/pages/workspace/rules/SpendRules/SpendRuleCardPage.tsx   | 2 +-
 src/pages/workspace/rules/SpendRules/SpendRulePageBase.tsx   | 2 +-
 5 files changed, 5 insertions(+), 8 deletions(-)

diff --git a/src/components/SpendRules/configuration/SpendRuleMerchantsBase.tsx b/src/components/SpendRules/configuration/SpendRuleMerchantsBase.tsx
index 4b4da33b62f5..36614e27edb5 100644
--- a/src/components/SpendRules/configuration/SpendRuleMerchantsBase.tsx
+++ b/src/components/SpendRules/configuration/SpendRuleMerchantsBase.tsx
@@ -7,8 +7,8 @@ import MenuItem from '@components/MenuItem';
 import MenuItemWithTopDescription from '@components/MenuItemWithTopDescription';
 import ScreenWrapper from '@components/ScreenWrapper';
 import ScrollView from '@components/ScrollView';
-import {useMemoizedLazyExpensifyIcons, useMemoizedLazyIllustrations} from '@hooks/useLazyAsset';
 import useCanWriteCardSpendRules from '@hooks/useCanWriteCardSpendRules';
+import {useMemoizedLazyExpensifyIcons, useMemoizedLazyIllustrations} from '@hooks/useLazyAsset';
 import useLocalize from '@hooks/useLocalize';
 import useThemeStyles from '@hooks/useThemeStyles';
 import Navigation from '@navigation/Navigation';
diff --git a/src/hooks/useCanWriteCardSpendRules.ts b/src/hooks/useCanWriteCardSpendRules.ts
index 5ab111fa95db..242d171b6ecf 100644
--- a/src/hooks/useCanWriteCardSpendRules.ts
+++ b/src/hooks/useCanWriteCardSpendRules.ts
@@ -7,10 +7,7 @@ function useCanWriteCardSpendRules(policyID: string | undefined): boolean {
     const policy = usePolicy(policyID);
     const {login = ''} = useCurrentUserPersonalDetails();
 
-    return (
-        canMemberWrite(policy, login, CONST.POLICY.POLICY_FEATURE.RULES) ||
-        canMemberWrite(policy, login, CONST.POLICY.POLICY_FEATURE.EXPENSIFY_CARD)
-    );
+    return canMemberWrite(policy, login, CONST.POLICY.POLICY_FEATURE.RULES) || canMemberWrite(policy, login, CONST.POLICY.POLICY_FEATURE.EXPENSIFY_CARD);
 }
 
 export default useCanWriteCardSpendRules;
diff --git a/src/pages/workspace/companyCards/WorkspaceCompanyCardFeedSelectorPage.tsx b/src/pages/workspace/companyCards/WorkspaceCompanyCardFeedSelectorPage.tsx
index 619bc32e040b..1b578c3c6aba 100644
--- a/src/pages/workspace/companyCards/WorkspaceCompanyCardFeedSelectorPage.tsx
+++ b/src/pages/workspace/companyCards/WorkspaceCompanyCardFeedSelectorPage.tsx
@@ -22,8 +22,8 @@ import useNetwork from '@hooks/useNetwork';
 import useOnyx from '@hooks/useOnyx';
 import useOtherFeedsForFeedSelector from '@hooks/useOtherFeedsForFeedSelector';
 import type {CardFeedListItem} from '@hooks/useOtherFeedsForFeedSelector';
-import usePolicyFeatureWriteAccess from '@hooks/usePolicyFeatureWriteAccess';
 import usePolicy from '@hooks/usePolicy';
+import usePolicyFeatureWriteAccess from '@hooks/usePolicyFeatureWriteAccess';
 import usePrimaryContactMethod from '@hooks/usePrimaryContactMethod';
 import useThemeIllustrations from '@hooks/useThemeIllustrations';
 import useThemeStyles from '@hooks/useThemeStyles';
diff --git a/src/pages/workspace/rules/SpendRules/SpendRuleCardPage.tsx b/src/pages/workspace/rules/SpendRules/SpendRuleCardPage.tsx
index a6db64489632..e9064ea86fbb 100644
--- a/src/pages/workspace/rules/SpendRules/SpendRuleCardPage.tsx
+++ b/src/pages/workspace/rules/SpendRules/SpendRuleCardPage.tsx
@@ -11,8 +11,8 @@ import SelectionList from '@components/SelectionList';
 import CardListItem from '@components/SelectionList/ListItem/CardListItem';
 import type {AdditionalCardProps} from '@components/SelectionList/ListItem/CardListItem';
 import type {ListItem} from '@components/SelectionList/types';
-import {useCompanyCardFeedIcons} from '@hooks/useCompanyCardIcons';
 import useCanWriteCardSpendRules from '@hooks/useCanWriteCardSpendRules';
+import {useCompanyCardFeedIcons} from '@hooks/useCompanyCardIcons';
 import useDefaultFundID from '@hooks/useDefaultFundID';
 import {useMemoizedLazyIllustrations} from '@hooks/useLazyAsset';
 import useLocalize from '@hooks/useLocalize';
diff --git a/src/pages/workspace/rules/SpendRules/SpendRulePageBase.tsx b/src/pages/workspace/rules/SpendRules/SpendRulePageBase.tsx
index d5b3de6f79df..a3ac7a5e86ca 100644
--- a/src/pages/workspace/rules/SpendRules/SpendRulePageBase.tsx
+++ b/src/pages/workspace/rules/SpendRules/SpendRulePageBase.tsx
@@ -10,8 +10,8 @@ import {ModalActions} from '@components/Modal/Global/ModalContext';
 import ScreenWrapper from '@components/ScreenWrapper';
 import ScrollView from '@components/ScrollView';
 import Text from '@components/Text';
-import useConfirmModal from '@hooks/useConfirmModal';
 import useCanWriteCardSpendRules from '@hooks/useCanWriteCardSpendRules';
+import useConfirmModal from '@hooks/useConfirmModal';
 import {useCurrencyListActions} from '@hooks/useCurrencyList';
 import useDefaultFundID from '@hooks/useDefaultFundID';
 import useLocalize from '@hooks/useLocalize';

From fc53bdfc4b05a81b24a6410d248cfc87ed52a531 Mon Sep 17 00:00:00 2001
From: thelullabyy <182625428+thelullabyy@users.noreply.github.com>
Date: Fri, 5 Jun 2026 04:44:18 -0500
Subject: [PATCH 139/435] feat: R2 PSA: Scaffolding

---
 src/CONST/index.ts                            |   1 -
 src/ROUTES.ts                                 |  35 ++++
 src/SCREENS.ts                                |   3 +
 src/libs/API/types.ts                         |  12 ++
 .../ModalStackNavigators/index.tsx            |   4 +
 .../RELATIONS/WORKSPACE_TO_RHP.ts             |   3 +
 src/libs/Navigation/linkingConfig/config.ts   |   3 +
 src/libs/Navigation/types.ts                  |   9 +
 .../actions/connections/FinancialForce.ts     | 197 ++++++++++++++++++
 .../accounting/PolicyAccountingPage.tsx       |   8 +-
 .../certinia/CertiniaCompanySelectorPage.tsx  |  11 +
 .../export/CertiniaReportExportStatusPage.tsx |  11 +
 .../import/CertiniaTagsMappingPage.tsx        |  11 +
 13 files changed, 301 insertions(+), 7 deletions(-)
 create mode 100644 src/pages/workspace/accounting/certinia/CertiniaCompanySelectorPage.tsx
 create mode 100644 src/pages/workspace/accounting/certinia/export/CertiniaReportExportStatusPage.tsx
 create mode 100644 src/pages/workspace/accounting/certinia/import/CertiniaTagsMappingPage.tsx

diff --git a/src/CONST/index.ts b/src/CONST/index.ts
index c4b8f0f4677b..ed2f6ce72dff 100644
--- a/src/CONST/index.ts
+++ b/src/CONST/index.ts
@@ -988,7 +988,6 @@ const CONST = {
         DATE_BOUND_MILEAGE_RATE: 'dateBoundMileageRate',
         BULK_SUBMIT_APPROVE_PAY: 'bulkSubmitApprovePay',
         WORKSPACE_ROOMS_PAGE: 'workspaceRoomsPage',
-        CERTINIA: 'financialForceNewDot',
         MERGE_HR: 'mergeHRConnections',
         VENDOR_MATCHING: 'vendorMatching',
     },
diff --git a/src/ROUTES.ts b/src/ROUTES.ts
index 54667c8ea303..b00c540abd17 100644
--- a/src/ROUTES.ts
+++ b/src/ROUTES.ts
@@ -218,6 +218,14 @@ const DYNAMIC_ROUTES = {
         path: 'certinia/advanced',
         entryScreens: [SCREENS.WORKSPACE.ACCOUNTING.ROOT],
     },
+    POLICY_ACCOUNTING_CERTINIA_REPORT_EXPORT_STATUS: {
+        path: 'certinia-report-status/select',
+        entryScreens: [SCREENS.WORKSPACE.ACCOUNTING.CERTINIA_EXPORT],
+    },
+    POLICY_ACCOUNTING_CERTINIA_COMPANY_SELECTOR: {
+        path: 'certinia/company',
+        entryScreens: [SCREENS.WORKSPACE.ACCOUNTING.ROOT],
+    },
     POLICY_ACCOUNTING_NETSUITE_EXPORT_EXPENSES_VENDOR_SELECT: {
         path: 'vendor/select',
         entryScreens: [SCREENS.WORKSPACE.ACCOUNTING.DYNAMIC_NETSUITE_EXPORT_EXPENSES],
@@ -3993,6 +4001,33 @@ const ROUTES = {
             return `workspaces/${policyID}/accounting/certinia/advanced` as const;
         },
     },
+    POLICY_ACCOUNTING_CERTINIA_TAGS_MAPPING: {
+        route: 'workspaces/:policyID/accounting/certinia/import/tags-mapping',
+        getRoute: (policyID: string | undefined) => {
+            if (!policyID) {
+                Log.warn('Invalid policyID is used to build the POLICY_ACCOUNTING_CERTINIA_TAGS_MAPPING route');
+            }
+            return `workspaces/${policyID}/accounting/certinia/import/tags-mapping` as const;
+        },
+    },
+    POLICY_ACCOUNTING_CERTINIA_REPORT_EXPORT_STATUS: {
+        route: 'workspaces/:policyID/accounting/certinia/export/report-status',
+        getRoute: (policyID: string | undefined) => {
+            if (!policyID) {
+                Log.warn('Invalid policyID is used to build the POLICY_ACCOUNTING_CERTINIA_REPORT_EXPORT_STATUS route');
+            }
+            return `workspaces/${policyID}/accounting/certinia/export/report-status` as const;
+        },
+    },
+    POLICY_ACCOUNTING_CERTINIA_COMPANY_SELECTOR: {
+        route: 'workspaces/:policyID/accounting/certinia/company',
+        getRoute: (policyID: string | undefined) => {
+            if (!policyID) {
+                Log.warn('Invalid policyID is used to build the POLICY_ACCOUNTING_CERTINIA_COMPANY_SELECTOR route');
+            }
+            return `workspaces/${policyID}/accounting/certinia/company` as const;
+        },
+    },
     ADD_EXISTING_EXPENSE: {
         route: 'search/r/:reportID/add-existing-expense/:backToReport?',
         getRoute: (reportID: string | undefined, backToReport?: string) => `search/r/${reportID}/add-existing-expense/${backToReport ?? ''}` as const,
diff --git a/src/SCREENS.ts b/src/SCREENS.ts
index c638acb5ff76..ccd471a69e3b 100644
--- a/src/SCREENS.ts
+++ b/src/SCREENS.ts
@@ -702,6 +702,9 @@ const SCREENS = {
             CERTINIA_EXPORT_DATE: 'Policy_Accounting_Certinia_Export_Date',
             CERTINIA_DEFAULT_VENDOR: 'Policy_Accounting_Certinia_Default_Vendor',
             CERTINIA_ADVANCED: 'Policy_Accounting_Certinia_Advanced',
+            CERTINIA_TAGS_MAPPING: 'Policy_Accounting_Certinia_Tags_Mapping',
+            CERTINIA_REPORT_EXPORT_STATUS: 'Policy_Accounting_Certinia_Report_Export_Status',
+            CERTINIA_COMPANY_SELECTOR: 'Policy_Accounting_Certinia_Company_Selector',
             CARD_RECONCILIATION: 'Policy_Accounting_Card_Reconciliation',
             CARD_RECONCILIATION_SAGE_INTACCT_AUTO_SYNC: 'Policy_Accounting_Card_Reconciliation_Sage_Intacct_Auto_Sync',
             DYNAMIC_RECONCILIATION_ACCOUNT_SETTINGS: 'Dynamic_Policy_Accounting_Reconciliation_Account_Settings',
diff --git a/src/libs/API/types.ts b/src/libs/API/types.ts
index f307ab6f4b54..177ee5a6efa0 100644
--- a/src/libs/API/types.ts
+++ b/src/libs/API/types.ts
@@ -463,6 +463,12 @@ const WRITE_COMMANDS = {
     UPDATE_FINANCIAL_FORCE_SYNC_TAX: 'UpdateFinancialForceSyncTax',
     UPDATE_FINANCIAL_FORCE_AUTO_SYNC: 'UpdateFinancialForceAutoSync',
     UPDATE_FINANCIAL_FORCE_SYNC_REIMBURSED_REPORTS: 'UpdateFinancialForceSyncReimbursedReports',
+    UPDATE_FINANCIAL_FORCE_PARENT_TAG_MAPPING: 'UpdateFinancialForceParentTagMapping',
+    UPDATE_FINANCIAL_FORCE_SYNC_MILESTONES: 'UpdateFinancialForceSyncMilestones',
+    UPDATE_FINANCIAL_FORCE_REPORT_EXPORT_STATUS: 'UpdateFinancialForceReportExportStatus',
+    UPDATE_FINANCIAL_FORCE_TAX_NON_BILLABLE: 'UpdateFinancialForceTaxNonBillable',
+    UPDATE_FINANCIAL_FORCE_EXPORT_FOREIGN_CURRENCY: 'UpdateFinancialForceExportForeignCurrency',
+    UPDATE_FINANCIAL_FORCE_COMPANY: 'UpdateFinancialForceCompany',
     COPY_EXISTING_POLICY_CONNECTION: 'CopyExistingPolicyConnection',
     UPDATE_SAGE_INTACCT_AUTO_SYNC: 'UpdateSageIntacctAutoSync',
     UPDATE_SAGE_INTACCT_ACCOUNTING_METHOD: 'UpdateSageIntacctAccountingMethod',
@@ -1086,6 +1092,12 @@ type WriteCommandParameters = {
     [WRITE_COMMANDS.UPDATE_FINANCIAL_FORCE_SYNC_TAX]: Parameters.UpdateFinancialForceGenericTypeParams<'enabled', boolean>;
     [WRITE_COMMANDS.UPDATE_FINANCIAL_FORCE_AUTO_SYNC]: Parameters.UpdateFinancialForceGenericTypeParams<'enabled', boolean>;
     [WRITE_COMMANDS.UPDATE_FINANCIAL_FORCE_SYNC_REIMBURSED_REPORTS]: Parameters.UpdateFinancialForceGenericTypeParams<'enabled', boolean>;
+    [WRITE_COMMANDS.UPDATE_FINANCIAL_FORCE_PARENT_TAG_MAPPING]: Parameters.UpdateFinancialForceGenericTypeParams<'parentTagMapping', ValueOf<typeof CONST.CERTINIA_PARENT_TAG_MAPPING>>;
+    [WRITE_COMMANDS.UPDATE_FINANCIAL_FORCE_SYNC_MILESTONES]: Parameters.UpdateFinancialForceGenericTypeParams<'enabled', boolean>;
+    [WRITE_COMMANDS.UPDATE_FINANCIAL_FORCE_REPORT_EXPORT_STATUS]: Parameters.UpdateFinancialForceGenericTypeParams<'reportExportStatus', ValueOf<typeof CONST.CERTINIA_EXPORT_STATUS>>;
+    [WRITE_COMMANDS.UPDATE_FINANCIAL_FORCE_TAX_NON_BILLABLE]: Parameters.UpdateFinancialForceGenericTypeParams<'enabled', boolean>;
+    [WRITE_COMMANDS.UPDATE_FINANCIAL_FORCE_EXPORT_FOREIGN_CURRENCY]: Parameters.UpdateFinancialForceGenericTypeParams<'enabled', boolean>;
+    [WRITE_COMMANDS.UPDATE_FINANCIAL_FORCE_COMPANY]: Parameters.UpdateFinancialForceGenericTypeParams<'companyID', string>;
 
     [WRITE_COMMANDS.UPGRADE_TO_CORPORATE]: Parameters.UpgradeToCorporateParams;
     [WRITE_COMMANDS.DOWNGRADE_TO_TEAM]: Parameters.DowngradeToTeamParams;
diff --git a/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx b/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx
index 751f2b1bb9b4..4cf60a049653 100644
--- a/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx
+++ b/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx
@@ -926,6 +926,9 @@ const SettingsModalStackNavigator = createModalStackNavigator<SettingsNavigatorP
     [SCREENS.WORKSPACE.ACCOUNTING.CERTINIA_EXPORT_DATE]: () => require<ReactComponentModule>('../../../../pages/workspace/accounting/certinia/export/CertiniaExportDatePage').default,
     [SCREENS.WORKSPACE.ACCOUNTING.CERTINIA_DEFAULT_VENDOR]: () => require<ReactComponentModule>('../../../../pages/workspace/accounting/certinia/export/CertiniaDefaultVendorPage').default,
     [SCREENS.WORKSPACE.ACCOUNTING.CERTINIA_ADVANCED]: () => require<ReactComponentModule>('../../../../pages/workspace/accounting/certinia/advanced/CertiniaAdvancedPage').default,
+    [SCREENS.WORKSPACE.ACCOUNTING.CERTINIA_REPORT_EXPORT_STATUS]: () =>
+        require<ReactComponentModule>('../../../../pages/workspace/accounting/certinia/export/CertiniaReportExportStatusPage').default,
+    [SCREENS.WORKSPACE.ACCOUNTING.CERTINIA_COMPANY_SELECTOR]: () => require<ReactComponentModule>('../../../../pages/workspace/accounting/certinia/CertiniaCompanySelectorPage').default,
     [SCREENS.WORKSPACE.ACCOUNTING.CARD_RECONCILIATION]: () => require<ReactComponentModule>('../../../../pages/workspace/accounting/reconciliation/CardReconciliationPage').default,
     [SCREENS.WORKSPACE.ACCOUNTING.CARD_RECONCILIATION_SAGE_INTACCT_AUTO_SYNC]: () =>
         require<ReactComponentModule>('../../../../pages/workspace/accounting/reconciliation/CardReconciliationSageIntacctAutoSyncPage').default,
@@ -1016,6 +1019,7 @@ const SettingsModalStackNavigator = createModalStackNavigator<SettingsNavigatorP
     [SCREENS.WORKSPACE.ACCOUNTING.CERTINIA_IMPORT]: () => require<ReactComponentModule>('../../../../pages/workspace/accounting/certinia/import/CertiniaImportPage').default,
     [SCREENS.WORKSPACE.ACCOUNTING.CERTINIA_DIMENSION_MAPPING]: () =>
         require<ReactComponentModule>('../../../../pages/workspace/accounting/certinia/import/CertiniaDimensionMappingPage').default,
+    [SCREENS.WORKSPACE.ACCOUNTING.CERTINIA_TAGS_MAPPING]: () => require<ReactComponentModule>('../../../../pages/workspace/accounting/certinia/import/CertiniaTagsMappingPage').default,
     [SCREENS.WORKSPACE.ACCOUNTING.SAGE_INTACCT_IMPORT]: () => require<ReactComponentModule>('../../../../pages/workspace/accounting/intacct/import/SageIntacctImportPage').default,
     [SCREENS.WORKSPACE.ACCOUNTING.SAGE_INTACCT_TOGGLE_MAPPING]: () =>
         require<ReactComponentModule>('../../../../pages/workspace/accounting/intacct/import/SageIntacctToggleMappingsPage').default,
diff --git a/src/libs/Navigation/linkingConfig/RELATIONS/WORKSPACE_TO_RHP.ts b/src/libs/Navigation/linkingConfig/RELATIONS/WORKSPACE_TO_RHP.ts
index da3b14f8b528..8dff285716ef 100755
--- a/src/libs/Navigation/linkingConfig/RELATIONS/WORKSPACE_TO_RHP.ts
+++ b/src/libs/Navigation/linkingConfig/RELATIONS/WORKSPACE_TO_RHP.ts
@@ -192,6 +192,9 @@ const WORKSPACE_TO_RHP: Partial<Record<keyof WorkspaceSplitNavigatorParamList, s
         SCREENS.WORKSPACE.ACCOUNTING.CERTINIA_EXPORT_DATE,
         SCREENS.WORKSPACE.ACCOUNTING.CERTINIA_DEFAULT_VENDOR,
         SCREENS.WORKSPACE.ACCOUNTING.CERTINIA_ADVANCED,
+        SCREENS.WORKSPACE.ACCOUNTING.CERTINIA_TAGS_MAPPING,
+        SCREENS.WORKSPACE.ACCOUNTING.CERTINIA_REPORT_EXPORT_STATUS,
+        SCREENS.WORKSPACE.ACCOUNTING.CERTINIA_COMPANY_SELECTOR,
     ],
     [SCREENS.WORKSPACE.TAXES]: [
         SCREENS.WORKSPACE.TAXES_SETTINGS,
diff --git a/src/libs/Navigation/linkingConfig/config.ts b/src/libs/Navigation/linkingConfig/config.ts
index 7607164941c4..47f1cccc9084 100644
--- a/src/libs/Navigation/linkingConfig/config.ts
+++ b/src/libs/Navigation/linkingConfig/config.ts
@@ -819,6 +819,9 @@ const config: LinkingOptions<RootNavigatorParamList>['config'] = {
                         [SCREENS.WORKSPACE.ACCOUNTING.CERTINIA_EXPORT_DATE]: DYNAMIC_ROUTES.POLICY_ACCOUNTING_CERTINIA_EXPORT_DATE.path,
                         [SCREENS.WORKSPACE.ACCOUNTING.CERTINIA_DEFAULT_VENDOR]: DYNAMIC_ROUTES.POLICY_ACCOUNTING_CERTINIA_DEFAULT_VENDOR.path,
                         [SCREENS.WORKSPACE.ACCOUNTING.CERTINIA_ADVANCED]: DYNAMIC_ROUTES.POLICY_ACCOUNTING_CERTINIA_ADVANCED.path,
+                        [SCREENS.WORKSPACE.ACCOUNTING.CERTINIA_TAGS_MAPPING]: {path: ROUTES.POLICY_ACCOUNTING_CERTINIA_TAGS_MAPPING.route},
+                        [SCREENS.WORKSPACE.ACCOUNTING.CERTINIA_REPORT_EXPORT_STATUS]: DYNAMIC_ROUTES.POLICY_ACCOUNTING_CERTINIA_REPORT_EXPORT_STATUS.path,
+                        [SCREENS.WORKSPACE.ACCOUNTING.CERTINIA_COMPANY_SELECTOR]: DYNAMIC_ROUTES.POLICY_ACCOUNTING_CERTINIA_COMPANY_SELECTOR.path,
                         [SCREENS.WORKSPACE.ACCOUNTING.CARD_RECONCILIATION]: {path: ROUTES.WORKSPACE_ACCOUNTING_CARD_RECONCILIATION.route},
                         [SCREENS.WORKSPACE.ACCOUNTING.CARD_RECONCILIATION_SAGE_INTACCT_AUTO_SYNC]: {
                             path: ROUTES.POLICY_ACCOUNTING_CARD_RECONCILIATION_SAGE_INTACCT_AUTO_SYNC.route,
diff --git a/src/libs/Navigation/types.ts b/src/libs/Navigation/types.ts
index 0f8ce85a91dd..e3508ea308db 100644
--- a/src/libs/Navigation/types.ts
+++ b/src/libs/Navigation/types.ts
@@ -1176,6 +1176,15 @@ type SettingsNavigatorParamList = {
     [SCREENS.WORKSPACE.ACCOUNTING.CERTINIA_ADVANCED]: {
         policyID: string;
     };
+    [SCREENS.WORKSPACE.ACCOUNTING.CERTINIA_TAGS_MAPPING]: {
+        policyID: string;
+    };
+    [SCREENS.WORKSPACE.ACCOUNTING.CERTINIA_REPORT_EXPORT_STATUS]: {
+        policyID: string;
+    };
+    [SCREENS.WORKSPACE.ACCOUNTING.CERTINIA_COMPANY_SELECTOR]: {
+        policyID: string;
+    };
     [SCREENS.WORKSPACE.ACCOUNTING.CARD_RECONCILIATION]: {
         policyID: string;
         connection: ValueOf<typeof CONST.POLICY.CONNECTIONS.ROUTE>;
diff --git a/src/libs/actions/connections/FinancialForce.ts b/src/libs/actions/connections/FinancialForce.ts
index ecd6decb87e6..c281c15edbc2 100644
--- a/src/libs/actions/connections/FinancialForce.ts
+++ b/src/libs/actions/connections/FinancialForce.ts
@@ -166,6 +166,84 @@ function prepareOnyxDataForFinancialForceExportUpdate<K extends keyof FinancialF
     return {optimisticData, failureData, successData};
 }
 
+function prepareOnyxDataForFinancialForceAdvancedUpdate<K extends keyof FinancialForceConnectionConfig['advanced']>(
+    policyID: string,
+    settingName: K,
+    settingValue: FinancialForceConnectionConfig['advanced'][K],
+    oldSettingValue?: FinancialForceConnectionConfig['advanced'][K],
+) {
+    const optimisticData: Array<OnyxUpdate<typeof ONYXKEYS.COLLECTION.POLICY>> = [
+        {
+            onyxMethod: Onyx.METHOD.MERGE,
+            key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`,
+            value: {
+                connections: {
+                    [CONST.POLICY.CONNECTIONS.NAME.CERTINIA]: {
+                        config: {
+                            advanced: {
+                                [settingName]: settingValue,
+                            },
+                            pendingFields: {
+                                [settingName]: CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE,
+                            },
+                            errorFields: {
+                                [settingName]: null,
+                            },
+                        },
+                    },
+                },
+            },
+        },
+    ];
+
+    const failureData: Array<OnyxUpdate<typeof ONYXKEYS.COLLECTION.POLICY>> = [
+        {
+            onyxMethod: Onyx.METHOD.MERGE,
+            key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`,
+            value: {
+                connections: {
+                    [CONST.POLICY.CONNECTIONS.NAME.CERTINIA]: {
+                        config: {
+                            advanced: {
+                                [settingName]: oldSettingValue ?? null,
+                            },
+                            pendingFields: {
+                                [settingName]: null,
+                            },
+                            errorFields: {
+                                [settingName]: getMicroSecondOnyxErrorWithTranslationKey('common.genericErrorMessage'),
+                            },
+                        },
+                    },
+                },
+            },
+        },
+    ];
+
+    const successData: Array<OnyxUpdate<typeof ONYXKEYS.COLLECTION.POLICY>> = [
+        {
+            onyxMethod: Onyx.METHOD.MERGE,
+            key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`,
+            value: {
+                connections: {
+                    [CONST.POLICY.CONNECTIONS.NAME.CERTINIA]: {
+                        config: {
+                            pendingFields: {
+                                [settingName]: null,
+                            },
+                            errorFields: {
+                                [settingName]: null,
+                            },
+                        },
+                    },
+                },
+            },
+        },
+    ];
+
+    return {optimisticData, failureData, successData};
+}
+
 function getFinancialForceSetupLink(policyID: string, isSandbox = false) {
     const commandURL = getCommandURL({
         command: READ_COMMANDS.CONNECT_POLICY_TO_FINANCIAL_FORCE,
@@ -420,10 +498,124 @@ function updateFinancialForceSyncReimbursedReports(policyID: string, enabled: bo
     write(WRITE_COMMANDS.UPDATE_FINANCIAL_FORCE_SYNC_REIMBURSED_REPORTS, {policyID, enabled}, {optimisticData, failureData, successData});
 }
 
+function updateFinancialForceParentTagMapping(
+    policyID: string,
+    parentTagMapping: ValueOf<typeof CONST.CERTINIA_PARENT_TAG_MAPPING>,
+    previousValue: ValueOf<typeof CONST.CERTINIA_PARENT_TAG_MAPPING> | null,
+) {
+    const {optimisticData, failureData, successData} = prepareOnyxDataForFinancialForceCodingUpdate(
+        policyID,
+        CONST.CERTINIA_CONFIG.PARENT_TAG_MAPPING,
+        parentTagMapping,
+        previousValue ?? undefined,
+    );
+    write(WRITE_COMMANDS.UPDATE_FINANCIAL_FORCE_PARENT_TAG_MAPPING, {policyID, parentTagMapping}, {optimisticData, failureData, successData});
+}
+
+function updateFinancialForceSyncMilestones(policyID: string, enabled: boolean, previousValue?: boolean) {
+    const {optimisticData, failureData, successData} = prepareOnyxDataForFinancialForceCodingUpdate(policyID, CONST.CERTINIA_CONFIG.SYNC_MILESTONES, enabled, previousValue);
+    write(WRITE_COMMANDS.UPDATE_FINANCIAL_FORCE_SYNC_MILESTONES, {policyID, enabled}, {optimisticData, failureData, successData});
+}
+
+function updateFinancialForceReportExportStatus(policyID: string, status: ValueOf<typeof CONST.CERTINIA_EXPORT_STATUS>, previousStatus: ValueOf<typeof CONST.CERTINIA_EXPORT_STATUS> | null) {
+    const {optimisticData, failureData, successData} = prepareOnyxDataForFinancialForceExportUpdate(
+        policyID,
+        CONST.CERTINIA_CONFIG.REPORT_EXPORT_STATUS,
+        status,
+        previousStatus ?? undefined,
+    );
+    write(WRITE_COMMANDS.UPDATE_FINANCIAL_FORCE_REPORT_EXPORT_STATUS, {policyID, reportExportStatus: status}, {optimisticData, failureData, successData});
+}
+
+function updateFinancialForceTaxNonBillable(policyID: string, enabled: boolean, previousValue?: boolean) {
+    const {optimisticData, failureData, successData} = prepareOnyxDataForFinancialForceAdvancedUpdate(policyID, CONST.CERTINIA_CONFIG.TAX_NON_BILLABLE, enabled, previousValue);
+    write(WRITE_COMMANDS.UPDATE_FINANCIAL_FORCE_TAX_NON_BILLABLE, {policyID, enabled}, {optimisticData, failureData, successData});
+}
+
+function updateFinancialForceExportForeignCurrency(policyID: string, enabled: boolean, previousValue?: boolean) {
+    const {optimisticData, failureData, successData} = prepareOnyxDataForFinancialForceAdvancedUpdate(policyID, CONST.CERTINIA_CONFIG.EXPORT_FOREIGN_CURRENCY, enabled, previousValue);
+    write(WRITE_COMMANDS.UPDATE_FINANCIAL_FORCE_EXPORT_FOREIGN_CURRENCY, {policyID, enabled}, {optimisticData, failureData, successData});
+}
+
+function updateFinancialForceCompany(policyID: string, companyID: string, previousCompanyID: string | null) {
+    const settingName = CONST.CERTINIA_CONFIG.COMPANY;
+    const optimisticData: Array<OnyxUpdate<typeof ONYXKEYS.COLLECTION.POLICY>> = [
+        {
+            onyxMethod: Onyx.METHOD.MERGE,
+            key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`,
+            value: {
+                connections: {
+                    [CONST.POLICY.CONNECTIONS.NAME.CERTINIA]: {
+                        config: {
+                            credentials: {
+                                companyID,
+                            },
+                            pendingFields: {
+                                [settingName]: CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE,
+                            },
+                            errorFields: {
+                                [settingName]: null,
+                            },
+                        },
+                    },
+                },
+            },
+        },
+    ];
+
+    const failureData: Array<OnyxUpdate<typeof ONYXKEYS.COLLECTION.POLICY>> = [
+        {
+            onyxMethod: Onyx.METHOD.MERGE,
+            key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`,
+            value: {
+                connections: {
+                    [CONST.POLICY.CONNECTIONS.NAME.CERTINIA]: {
+                        config: {
+                            credentials: {
+                                companyID: previousCompanyID ?? null,
+                            },
+                            pendingFields: {
+                                [settingName]: null,
+                            },
+                            errorFields: {
+                                [settingName]: getMicroSecondOnyxErrorWithTranslationKey('common.genericErrorMessage'),
+                            },
+                        },
+                    },
+                },
+            },
+        },
+    ];
+
+    const successData: Array<OnyxUpdate<typeof ONYXKEYS.COLLECTION.POLICY>> = [
+        {
+            onyxMethod: Onyx.METHOD.MERGE,
+            key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`,
+            value: {
+                connections: {
+                    [CONST.POLICY.CONNECTIONS.NAME.CERTINIA]: {
+                        config: {
+                            pendingFields: {
+                                [settingName]: null,
+                            },
+                            errorFields: {
+                                [settingName]: null,
+                            },
+                        },
+                    },
+                },
+            },
+        },
+    ];
+
+    write(WRITE_COMMANDS.UPDATE_FINANCIAL_FORCE_COMPANY, {policyID, companyID}, {optimisticData, failureData, successData});
+}
+
 export {
     clearFinancialForceErrorField,
     connectPolicyToFinancialForce,
     updateFinancialForceAutoSync,
+    updateFinancialForceCompany,
     updateFinancialForceDefaultVendor,
     updateFinancialForceDimension1Mapping,
     updateFinancialForceDimension2Mapping,
@@ -431,7 +623,12 @@ export {
     updateFinancialForceDimension4Mapping,
     updateFinancialForceExportDate,
     updateFinancialForceExporter,
+    updateFinancialForceExportForeignCurrency,
     updateFinancialForceExportStatus,
+    updateFinancialForceParentTagMapping,
+    updateFinancialForceReportExportStatus,
+    updateFinancialForceSyncMilestones,
     updateFinancialForceSyncReimbursedReports,
     updateFinancialForceSyncTax,
+    updateFinancialForceTaxNonBillable,
 };
diff --git a/src/pages/workspace/accounting/PolicyAccountingPage.tsx b/src/pages/workspace/accounting/PolicyAccountingPage.tsx
index 33e3dee838f7..767673c8a593 100644
--- a/src/pages/workspace/accounting/PolicyAccountingPage.tsx
+++ b/src/pages/workspace/accounting/PolicyAccountingPage.tsx
@@ -106,11 +106,7 @@ function PolicyAccountingPage({policy}: PolicyAccountingPageProps) {
     const accountingIcons = useMemoizedLazyExpensifyIcons(['IntacctSquare', 'QBOSquare', 'XeroSquare', 'NetSuiteSquare', 'QBDSquare', 'CertiniaSquare']);
     const illustrations = useMemoizedLazyIllustrations(['Accounting']);
 
-    const canUseCertiniaIntegration = isBetaEnabled(CONST.BETAS.CERTINIA) || !!policy?.connections?.financialforce;
-    const accountingIntegrations = useMemo(
-        () => CONST.POLICY.CONNECTIONS.ACCOUNTING_CONNECTION_NAMES.filter((name) => name !== CONST.POLICY.CONNECTIONS.NAME.CERTINIA || canUseCertiniaIntegration),
-        [canUseCertiniaIntegration],
-    );
+    const accountingIntegrations = CONST.POLICY.CONNECTIONS.ACCOUNTING_CONNECTION_NAMES;
     const syncingAccountingIntegration = accountingIntegrations.find((integration) => integration === connectionSyncProgress?.connectionName);
     const connectedIntegration = getConnectedIntegration(policy, accountingIntegrations) ?? syncingAccountingIntegration;
     const hasAccountingConnection = hasAccountingConnections(policy);
@@ -129,7 +125,7 @@ function PolicyAccountingPage({policy}: PolicyAccountingPageProps) {
     );
 
     const hasSyncError = shouldShowSyncError(policy, isSyncInProgress, accountingIntegrations);
-    const hasUnsupportedNDIntegration = !isEmptyObject(policy?.connections) && hasSupportedOnlyOnOldDotIntegration(policy) && !canUseCertiniaIntegration;
+    const hasUnsupportedNDIntegration = !isEmptyObject(policy?.connections) && hasSupportedOnlyOnOldDotIntegration(policy);
 
     const tenants = useMemo(() => getXeroTenants(policy), [policy]);
     const currentXeroOrganization = findCurrentXeroOrganization(tenants, policy?.connections?.xero?.config?.tenantID);
diff --git a/src/pages/workspace/accounting/certinia/CertiniaCompanySelectorPage.tsx b/src/pages/workspace/accounting/certinia/CertiniaCompanySelectorPage.tsx
new file mode 100644
index 000000000000..ba5040f385ab
--- /dev/null
+++ b/src/pages/workspace/accounting/certinia/CertiniaCompanySelectorPage.tsx
@@ -0,0 +1,11 @@
+import React from 'react';
+import NotFoundPage from '@pages/ErrorPage/NotFoundPage';
+
+// Scaffolding placeholder for Release 2 (SRP). The full Company selector UI is implemented in a follow-up issue.
+function CertiniaCompanySelectorPage() {
+    return <NotFoundPage />;
+}
+
+CertiniaCompanySelectorPage.displayName = 'CertiniaCompanySelectorPage';
+
+export default CertiniaCompanySelectorPage;
diff --git a/src/pages/workspace/accounting/certinia/export/CertiniaReportExportStatusPage.tsx b/src/pages/workspace/accounting/certinia/export/CertiniaReportExportStatusPage.tsx
new file mode 100644
index 000000000000..a9b696741dad
--- /dev/null
+++ b/src/pages/workspace/accounting/certinia/export/CertiniaReportExportStatusPage.tsx
@@ -0,0 +1,11 @@
+import React from 'react';
+import NotFoundPage from '@pages/ErrorPage/NotFoundPage';
+
+// Scaffolding placeholder for Release 2 (PSA). The full Expense Report Status selection UI is implemented in a follow-up issue.
+function CertiniaReportExportStatusPage() {
+    return <NotFoundPage />;
+}
+
+CertiniaReportExportStatusPage.displayName = 'CertiniaReportExportStatusPage';
+
+export default CertiniaReportExportStatusPage;
diff --git a/src/pages/workspace/accounting/certinia/import/CertiniaTagsMappingPage.tsx b/src/pages/workspace/accounting/certinia/import/CertiniaTagsMappingPage.tsx
new file mode 100644
index 000000000000..be1ca996d4d7
--- /dev/null
+++ b/src/pages/workspace/accounting/certinia/import/CertiniaTagsMappingPage.tsx
@@ -0,0 +1,11 @@
+import React from 'react';
+import NotFoundPage from '@pages/ErrorPage/NotFoundPage';
+
+// Scaffolding placeholder for Release 2 (PSA). The full Tags Mapping selection UI is implemented in a follow-up issue.
+function CertiniaTagsMappingPage() {
+    return <NotFoundPage />;
+}
+
+CertiniaTagsMappingPage.displayName = 'CertiniaTagsMappingPage';
+
+export default CertiniaTagsMappingPage;

From 087fe9c25502a06d203f96760a714bfdad3f524c Mon Sep 17 00:00:00 2001
From: thelullabyy <182625428+thelullabyy@users.noreply.github.com>
Date: Fri, 5 Jun 2026 04:51:59 -0500
Subject: [PATCH 140/435] fix: keep the beta gate

---
 src/CONST/index.ts                                      | 1 +
 src/pages/workspace/accounting/PolicyAccountingPage.tsx | 8 ++++++--
 2 files changed, 7 insertions(+), 2 deletions(-)

diff --git a/src/CONST/index.ts b/src/CONST/index.ts
index ed2f6ce72dff..c4b8f0f4677b 100644
--- a/src/CONST/index.ts
+++ b/src/CONST/index.ts
@@ -988,6 +988,7 @@ const CONST = {
         DATE_BOUND_MILEAGE_RATE: 'dateBoundMileageRate',
         BULK_SUBMIT_APPROVE_PAY: 'bulkSubmitApprovePay',
         WORKSPACE_ROOMS_PAGE: 'workspaceRoomsPage',
+        CERTINIA: 'financialForceNewDot',
         MERGE_HR: 'mergeHRConnections',
         VENDOR_MATCHING: 'vendorMatching',
     },
diff --git a/src/pages/workspace/accounting/PolicyAccountingPage.tsx b/src/pages/workspace/accounting/PolicyAccountingPage.tsx
index 767673c8a593..33e3dee838f7 100644
--- a/src/pages/workspace/accounting/PolicyAccountingPage.tsx
+++ b/src/pages/workspace/accounting/PolicyAccountingPage.tsx
@@ -106,7 +106,11 @@ function PolicyAccountingPage({policy}: PolicyAccountingPageProps) {
     const accountingIcons = useMemoizedLazyExpensifyIcons(['IntacctSquare', 'QBOSquare', 'XeroSquare', 'NetSuiteSquare', 'QBDSquare', 'CertiniaSquare']);
     const illustrations = useMemoizedLazyIllustrations(['Accounting']);
 
-    const accountingIntegrations = CONST.POLICY.CONNECTIONS.ACCOUNTING_CONNECTION_NAMES;
+    const canUseCertiniaIntegration = isBetaEnabled(CONST.BETAS.CERTINIA) || !!policy?.connections?.financialforce;
+    const accountingIntegrations = useMemo(
+        () => CONST.POLICY.CONNECTIONS.ACCOUNTING_CONNECTION_NAMES.filter((name) => name !== CONST.POLICY.CONNECTIONS.NAME.CERTINIA || canUseCertiniaIntegration),
+        [canUseCertiniaIntegration],
+    );
     const syncingAccountingIntegration = accountingIntegrations.find((integration) => integration === connectionSyncProgress?.connectionName);
     const connectedIntegration = getConnectedIntegration(policy, accountingIntegrations) ?? syncingAccountingIntegration;
     const hasAccountingConnection = hasAccountingConnections(policy);
@@ -125,7 +129,7 @@ function PolicyAccountingPage({policy}: PolicyAccountingPageProps) {
     );
 
     const hasSyncError = shouldShowSyncError(policy, isSyncInProgress, accountingIntegrations);
-    const hasUnsupportedNDIntegration = !isEmptyObject(policy?.connections) && hasSupportedOnlyOnOldDotIntegration(policy);
+    const hasUnsupportedNDIntegration = !isEmptyObject(policy?.connections) && hasSupportedOnlyOnOldDotIntegration(policy) && !canUseCertiniaIntegration;
 
     const tenants = useMemo(() => getXeroTenants(policy), [policy]);
     const currentXeroOrganization = findCurrentXeroOrganization(tenants, policy?.connections?.xero?.config?.tenantID);

From f94bc1183128332a0f97a7b1f6e44968fbdce005 Mon Sep 17 00:00:00 2001
From: jayeshmangwani <jayeshmangwani@gmail.com>
Date: Fri, 5 Jun 2026 17:09:38 +0530
Subject: [PATCH 141/435] revert Mobile-Expensify changes

---
 Mobile-Expensify | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Mobile-Expensify b/Mobile-Expensify
index 59644ae54601..2fafa98308e2 160000
--- a/Mobile-Expensify
+++ b/Mobile-Expensify
@@ -1 +1 @@
-Subproject commit 59644ae546013d4f71729440245cfde4b7a395b6
+Subproject commit 2fafa98308e2e225ead719099a947fbcc89e4141

From ceaf2366aeeb0e8f0137b32ebc44585e726d5c7b Mon Sep 17 00:00:00 2001
From: jayeshmangwani <jayeshmangwani@gmail.com>
Date: Fri, 5 Jun 2026 17:48:21 +0530
Subject: [PATCH 142/435] =?UTF-8?q?Derive=20allReportsShouldMarkAsDone=20f?=
 =?UTF-8?q?rom=20transactions=20when=20selectedReports=20is=20empty?=
 =?UTF-8?q?=EE=81=96=EE=80=BB=EE=83=81=EE=83=BB=EE=83=B9=EE=83=8E?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 src/hooks/useSearchBulkActions.ts | 50 +++++++++++++++++++++++--------
 1 file changed, 38 insertions(+), 12 deletions(-)

diff --git a/src/hooks/useSearchBulkActions.ts b/src/hooks/useSearchBulkActions.ts
index 64ab5151b659..9d476e210bae 100644
--- a/src/hooks/useSearchBulkActions.ts
+++ b/src/hooks/useSearchBulkActions.ts
@@ -1111,9 +1111,9 @@ function useSearchBulkActions({queryJSON}: UseSearchBulkActionsParams) {
         });
     }, [isExpenseReportType, defaultExpensePolicy, selectedReports, accountID]);
 
-    const allReportsShouldMarkAsDone = useMemo(
-        () =>
-            selectedReports.every((report) => {
+    const allReportsShouldMarkAsDone = useMemo(() => {
+        if (selectedReports.length > 0) {
+            return selectedReports.every((report) => {
                 const fullReport = currentSearchResults?.data?.[`${ONYXKEYS.COLLECTION.REPORT}${report.reportID}`];
 
                 return shouldShowMarkAsDone({
@@ -1121,12 +1121,24 @@ function useSearchBulkActions({queryJSON}: UseSearchBulkActionsParams) {
                     report: fullReport,
                     policy: policies?.[`${ONYXKEYS.COLLECTION.POLICY}${report.policyID}`],
                 });
-            }),
-        [selectedReports, currentSearchResults?.data, isTrackIntentUser, policies],
-    );
-    const noReportsShouldMarkAsDone = useMemo(
-        () =>
-            selectedReports.every((report) => {
+            });
+        }
+
+        return Object.values(selectedTransactions).every((transaction) => {
+            const reportID = transaction.reportID;
+            const fullReport = currentSearchResults?.data?.[`${ONYXKEYS.COLLECTION.REPORT}${reportID}`];
+
+            return shouldShowMarkAsDone({
+                isTrackIntentUser,
+                report: fullReport,
+                policy: policies?.[`${ONYXKEYS.COLLECTION.POLICY}${transaction.policyID}`],
+            });
+        });
+    }, [selectedReports, currentSearchResults?.data, isTrackIntentUser, policies, selectedTransactions]);
+
+    const noReportsShouldMarkAsDone = useMemo(() => {
+        if (selectedReports.length > 0) {
+            return selectedReports.every((report) => {
                 const fullReport = currentSearchResults?.data?.[`${ONYXKEYS.COLLECTION.REPORT}${report.reportID}`];
 
                 return !shouldShowMarkAsDone({
@@ -1134,9 +1146,20 @@ function useSearchBulkActions({queryJSON}: UseSearchBulkActionsParams) {
                     report: fullReport,
                     policy: policies?.[`${ONYXKEYS.COLLECTION.POLICY}${report.policyID}`],
                 });
-            }),
-        [selectedReports, currentSearchResults?.data, isTrackIntentUser, policies],
-    );
+            });
+        }
+
+        return Object.values(selectedTransactions).every((transaction) => {
+            const reportID = transaction.reportID;
+            const fullReport = currentSearchResults?.data?.[`${ONYXKEYS.COLLECTION.REPORT}${reportID}`];
+
+            return !shouldShowMarkAsDone({
+                isTrackIntentUser,
+                report: fullReport,
+                policy: policies?.[`${ONYXKEYS.COLLECTION.POLICY}${transaction.policyID}`],
+            });
+        });
+    }, [selectedReports, currentSearchResults?.data, isTrackIntentUser, policies, selectedTransactions]);
 
     const headerButtonsOptions = useMemo(() => {
         if (selectedTransactionsKeys.length === 0 || status == null || !hash) {
@@ -1468,6 +1491,9 @@ function useSearchBulkActions({queryJSON}: UseSearchBulkActionsParams) {
             });
         }
 
+        console.log('Selected Reports for Submit Option', selectedReports);
+        console.log('Selected Transactions for Submit Option', selectedTransactionsKeys);
+
         const shouldShowSubmitOption =
             !isOffline &&
             areSelectedTransactionsIncludedInReports &&

From 35eb6ffcf380b47321634eb862403ae0cd59f36b Mon Sep 17 00:00:00 2001
From: jayeshmangwani <jayeshmangwani@gmail.com>
Date: Fri, 5 Jun 2026 18:26:23 +0530
Subject: [PATCH 143/435] fixed lint: removed consoles

---
 src/hooks/useSearchBulkActions.ts | 7 +++----
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/src/hooks/useSearchBulkActions.ts b/src/hooks/useSearchBulkActions.ts
index 9d476e210bae..330a556f332f 100644
--- a/src/hooks/useSearchBulkActions.ts
+++ b/src/hooks/useSearchBulkActions.ts
@@ -1491,9 +1491,6 @@ function useSearchBulkActions({queryJSON}: UseSearchBulkActionsParams) {
             });
         }
 
-        console.log('Selected Reports for Submit Option', selectedReports);
-        console.log('Selected Transactions for Submit Option', selectedTransactionsKeys);
-
         const shouldShowSubmitOption =
             !isOffline &&
             areSelectedTransactionsIncludedInReports &&
@@ -1501,7 +1498,9 @@ function useSearchBulkActions({queryJSON}: UseSearchBulkActionsParams) {
                 ? selectedReports.every((report) => report.canSubmit) &&
                   // Disable for mixed selections: all must be the same submit type
                   (isTrackIntentUser ? allReportsShouldMarkAsDone || noReportsShouldMarkAsDone : true)
-                : selectedTransactionsKeys.every((id) => selectedTransactions[id].action === CONST.SEARCH.ACTION_TYPES.SUBMIT));
+                : selectedTransactionsKeys.every((id) => selectedTransactions[id].action === CONST.SEARCH.ACTION_TYPES.SUBMIT) &&
+                  // Disable for mixed selections: all must be the same submit type
+                  (isTrackIntentUser ? allReportsShouldMarkAsDone || noReportsShouldMarkAsDone : true));
 
         if (shouldShowSubmitOption) {
             options.push({

From d426a9b7474bf71400fb7c74d76a8d3abc7cf8b8 Mon Sep 17 00:00:00 2001
From: jayeshmangwani <jayeshmangwani@gmail.com>
Date: Fri, 5 Jun 2026 19:17:12 +0530
Subject: [PATCH 144/435] changed shouldShowMarkAsDone return after
 wasSubmittedViaHarvesting

---
 src/libs/NextStepUtils.ts                     |  2 +-
 .../actionContents/ApprovalFlowContent.tsx    | 35 ++++++++++---------
 2 files changed, 19 insertions(+), 18 deletions(-)

diff --git a/src/libs/NextStepUtils.ts b/src/libs/NextStepUtils.ts
index 05bce90666c4..c703d442ddca 100644
--- a/src/libs/NextStepUtils.ts
+++ b/src/libs/NextStepUtils.ts
@@ -655,7 +655,7 @@ function buildNextStepNew(params: BuildNextStepNewParams): ReportNextStepDepreca
                             text: actionText,
                         },
                         {
-                            text: shouldShowMarkAsDoneCopy ? '.' : ' %expenses.',
+                            text: hasTransactions && shouldShowMarkAsDoneCopy ? '.' : ' %expenses.',
                         },
                     ],
                 };
diff --git a/src/pages/inbox/report/actionContents/ApprovalFlowContent.tsx b/src/pages/inbox/report/actionContents/ApprovalFlowContent.tsx
index 131432c4d316..87b9a899e790 100644
--- a/src/pages/inbox/report/actionContents/ApprovalFlowContent.tsx
+++ b/src/pages/inbox/report/actionContents/ApprovalFlowContent.tsx
@@ -42,16 +42,6 @@ function ApprovalFlowContent({action, policyID, reportID, originalReport, isTrac
     if (isActionOfType(action, CONST.REPORT.ACTIONS.TYPE.SUBMITTED) || isActionOfType(action, CONST.REPORT.ACTIONS.TYPE.SUBMITTED_AND_CLOSED) || isMarkAsClosedAction(action)) {
         const wasSubmittedViaHarvesting = !isMarkAsClosedAction(action) ? (getOriginalMessage(action)?.harvesting ?? false) : false;
 
-        if (
-            shouldShowMarkAsDone({
-                isTrackIntentUser,
-                policy,
-                report: originalReport,
-            })
-        ) {
-            return <ReportActionItemBasicMessage message={translate('iou.markedAsDone', getOriginalMessage(action)?.message)} />;
-        }
-
         if (wasSubmittedViaHarvesting) {
             return (
                 <ReportActionItemMessageWithExplain
@@ -72,12 +62,6 @@ function ApprovalFlowContent({action, policyID, reportID, originalReport, isTrac
             return <ReportActionItemBasicMessage message={translate('iou.submitted')} />;
         }
 
-        return <ReportActionItemBasicMessage message={translate('iou.submitted', getOriginalMessage(action)?.message)} />;
-    }
-
-    if (isActionOfType(action, CONST.REPORT.ACTIONS.TYPE.APPROVED)) {
-        const wasAutoApproved = getOriginalMessage(action)?.automaticAction ?? false;
-
         if (
             shouldShowMarkAsDone({
                 isTrackIntentUser,
@@ -85,8 +69,15 @@ function ApprovalFlowContent({action, policyID, reportID, originalReport, isTrac
                 report: originalReport,
             })
         ) {
-            return <ReportActionItemBasicMessage message={translate('iou.markedAsDone')} />;
+            return <ReportActionItemBasicMessage message={translate('iou.markedAsDone', getOriginalMessage(action)?.message)} />;
         }
+
+        return <ReportActionItemBasicMessage message={translate('iou.submitted', getOriginalMessage(action)?.message)} />;
+    }
+
+    if (isActionOfType(action, CONST.REPORT.ACTIONS.TYPE.APPROVED)) {
+        const wasAutoApproved = getOriginalMessage(action)?.automaticAction ?? false;
+
         if (wasAutoApproved) {
             return (
                 <ReportActionItemMessageWithExplain
@@ -102,6 +93,16 @@ function ApprovalFlowContent({action, policyID, reportID, originalReport, isTrac
             return <ReportActionItemBasicMessage message={translate('iou.queuedToApproveViaDEW')} />;
         }
 
+        if (
+            shouldShowMarkAsDone({
+                isTrackIntentUser,
+                policy,
+                report: originalReport,
+            })
+        ) {
+            return <ReportActionItemBasicMessage message={translate('iou.markedAsDone')} />;
+        }
+
         return <ReportActionItemBasicMessage message={translate('iou.approvedMessage')} />;
     }
 

From 138c4b189531a1f29de2e8e0beec32ec5bee0fd0 Mon Sep 17 00:00:00 2001
From: MobileMage <aidelojejoshua@gmail.com>
Date: Fri, 5 Jun 2026 16:56:39 +0100
Subject: [PATCH 145/435] Clean up cross-report duplicates in mergeDuplicates

Group each discarded duplicate by its own source report so the IOU action
soft-delete, transaction-thread teardown, and expense-report total decrement
target the correct REPORT and REPORT_ACTIONS Onyx keys when duplicates live
in different expense reports. Mirrors the per-transaction pattern that
resolveDuplicates already uses.
---
 src/libs/actions/IOU/Duplicate.ts | 132 ++++++++++++++++++++----------
 1 file changed, 87 insertions(+), 45 deletions(-)

diff --git a/src/libs/actions/IOU/Duplicate.ts b/src/libs/actions/IOU/Duplicate.ts
index d6e9a5f5bef8..560d5262e2a1 100644
--- a/src/libs/actions/IOU/Duplicate.ts
+++ b/src/libs/actions/IOU/Duplicate.ts
@@ -209,40 +209,75 @@ function mergeDuplicates({
         };
     });
 
-    const duplicateTransactionTotals = params.transactionIDList.reduce((total, id) => {
-        const duplicateTransaction = allTransactions[`${ONYXKEYS.COLLECTION.TRANSACTION}${id}`];
-        if (!duplicateTransaction) {
-            return total;
-        }
-        return total + duplicateTransaction.amount;
-    }, 0);
-
     const expenseReport = allReports?.[`${ONYXKEYS.COLLECTION.REPORT}${params.reportID}`];
-    const expenseReportOptimisticData: OnyxUpdate<typeof ONYXKEYS.COLLECTION.REPORT> = {
-        onyxMethod: Onyx.METHOD.MERGE,
-        key: `${ONYXKEYS.COLLECTION.REPORT}${params.reportID}`,
-        value: {
-            total: (expenseReport?.total ?? 0) - duplicateTransactionTotals,
-        },
-    };
-    const expenseReportFailureData: OnyxUpdate<typeof ONYXKEYS.COLLECTION.REPORT> = {
-        onyxMethod: Onyx.METHOD.MERGE,
-        key: `${ONYXKEYS.COLLECTION.REPORT}${params.reportID}`,
-        value: {
-            total: expenseReport?.total,
-        },
-    };
 
-    const iouActionsToDelete = params.reportID ? getIOUActionForTransactions(params.transactionIDList, params.reportID) : [];
+    // Group each discarded duplicate by its own source report so cleanup targets the right
+    // REPORT and REPORT_ACTIONS Onyx keys when duplicates live in different expense reports.
+    const allIOUReportActions = getAllReportActionsFromIOU();
+    type DiscardedDuplicate = {
+        iouAction: OnyxTypes.ReportAction<typeof CONST.REPORT.ACTIONS.TYPE.IOU>;
+        sourceReportID: string;
+        amount: number;
+    };
+    const discardedDuplicates: DiscardedDuplicate[] = [];
+    for (const id of params.transactionIDList) {
+        const transaction = allTransactions[`${ONYXKEYS.COLLECTION.TRANSACTION}${id}`];
+        const sourceReportID = transaction?.reportID;
+        if (!sourceReportID) {
+            continue;
+        }
+        const reportActions = allIOUReportActions?.[`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${sourceReportID}`];
+        const iouAction = Object.values(reportActions ?? {}).find((reportAction): reportAction is OnyxTypes.ReportAction<typeof CONST.REPORT.ACTIONS.TYPE.IOU> => {
+            if (!isMoneyRequestAction(reportAction)) {
+                return false;
+            }
+            return getOriginalMessage(reportAction)?.IOUTransactionID === id;
+        });
+        if (!iouAction) {
+            continue;
+        }
+        discardedDuplicates.push({iouAction, sourceReportID, amount: transaction.amount ?? 0});
+    }
+    const iouActionsToDelete = discardedDuplicates.map(({iouAction}) => iouAction);
+
+    const discardedDuplicatesBySourceReport = discardedDuplicates.reduce<Record<string, DiscardedDuplicate[]>>((acc, entry) => {
+        const bucket = acc[entry.sourceReportID];
+        if (bucket) {
+            bucket.push(entry);
+        } else {
+            acc[entry.sourceReportID] = [entry];
+        }
+        return acc;
+    }, {});
 
+    const expenseReportOptimisticData: Array<OnyxUpdate<typeof ONYXKEYS.COLLECTION.REPORT>> = [];
+    const expenseReportFailureData: Array<OnyxUpdate<typeof ONYXKEYS.COLLECTION.REPORT>> = [];
     const deletedTime = DateUtils.getDBTime();
-    const expenseReportActionsOptimisticData: OnyxUpdate<typeof ONYXKEYS.COLLECTION.REPORT_ACTIONS> = {
-        onyxMethod: Onyx.METHOD.MERGE,
-        key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${params.reportID}`,
-        value: iouActionsToDelete.reduce<Record<string, PartialDeep<OnyxTypes.ReportAction<typeof CONST.REPORT.ACTIONS.TYPE.IOU>>>>((val, reportAction) => {
-            const firstMessage = Array.isArray(reportAction.message) ? reportAction.message.at(0) : null;
+    const expenseReportActionsOptimisticData: Array<OnyxUpdate<typeof ONYXKEYS.COLLECTION.REPORT_ACTIONS>> = [];
+    const expenseReportActionsFailureData: Array<OnyxUpdate<typeof ONYXKEYS.COLLECTION.REPORT_ACTIONS>> = [];
+
+    for (const [sourceReportID, entries] of Object.entries(discardedDuplicatesBySourceReport)) {
+        const sourceReport = allReports?.[`${ONYXKEYS.COLLECTION.REPORT}${sourceReportID}`];
+        const sourceDuplicateTotals = entries.reduce((total, entry) => total + entry.amount, 0);
+        expenseReportOptimisticData.push({
+            onyxMethod: Onyx.METHOD.MERGE,
+            key: `${ONYXKEYS.COLLECTION.REPORT}${sourceReportID}`,
+            value: {
+                total: (sourceReport?.total ?? 0) - sourceDuplicateTotals,
+            },
+        });
+        expenseReportFailureData.push({
+            onyxMethod: Onyx.METHOD.MERGE,
+            key: `${ONYXKEYS.COLLECTION.REPORT}${sourceReportID}`,
+            value: {
+                total: sourceReport?.total,
+            },
+        });
+
+        const optimisticActionsValue = entries.reduce<Record<string, PartialDeep<OnyxTypes.ReportAction<typeof CONST.REPORT.ACTIONS.TYPE.IOU>>>>((val, {iouAction}) => {
+            const firstMessage = Array.isArray(iouAction.message) ? iouAction.message.at(0) : null;
             // eslint-disable-next-line no-param-reassign
-            val[reportAction.reportActionID] = {
+            val[iouAction.reportActionID] = {
                 originalMessage: {
                     deleted: deletedTime,
                 },
@@ -252,32 +287,39 @@ function mergeDuplicates({
                             ...firstMessage,
                             deleted: deletedTime,
                         },
-                        ...(Array.isArray(reportAction.message) ? reportAction.message.slice(1) : []),
+                        ...(Array.isArray(iouAction.message) ? iouAction.message.slice(1) : []),
                     ],
                 }),
-                ...(!Array.isArray(reportAction.message) && {
+                ...(!Array.isArray(iouAction.message) && {
                     message: {
                         deleted: deletedTime,
                     },
                 }),
             };
             return val;
-        }, {}),
-    };
-    const expenseReportActionsFailureData: OnyxUpdate<typeof ONYXKEYS.COLLECTION.REPORT_ACTIONS> = {
-        onyxMethod: Onyx.METHOD.MERGE,
-        key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${params.reportID}`,
-        value: iouActionsToDelete.reduce<Record<string, NullishDeep<PartialDeep<OnyxTypes.ReportAction<typeof CONST.REPORT.ACTIONS.TYPE.IOU>>>>>((val, reportAction) => {
+        }, {});
+        expenseReportActionsOptimisticData.push({
+            onyxMethod: Onyx.METHOD.MERGE,
+            key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${sourceReportID}`,
+            value: optimisticActionsValue,
+        });
+
+        const failureActionsValue = entries.reduce<Record<string, NullishDeep<PartialDeep<OnyxTypes.ReportAction<typeof CONST.REPORT.ACTIONS.TYPE.IOU>>>>>((val, {iouAction}) => {
             // eslint-disable-next-line no-param-reassign
-            val[reportAction.reportActionID] = {
+            val[iouAction.reportActionID] = {
                 originalMessage: {
                     deleted: null,
                 },
-                message: reportAction.message,
+                message: iouAction.message,
             };
             return val;
-        }, {}),
-    };
+        }, {});
+        expenseReportActionsFailureData.push({
+            onyxMethod: Onyx.METHOD.MERGE,
+            key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${sourceReportID}`,
+            value: failureActionsValue,
+        });
+    }
 
     const cleanUpTransactionThreadReportsOptimisticData = [];
     const cleanUpTransactionThreadReportsSuccessData = [];
@@ -331,8 +373,8 @@ function mergeDuplicates({
         optimisticTransactionData,
         ...optimisticTransactionDuplicatesData,
         ...optimisticTransactionViolations,
-        expenseReportOptimisticData,
-        expenseReportActionsOptimisticData,
+        ...expenseReportOptimisticData,
+        ...expenseReportActionsOptimisticData,
         optimisticReportActionData,
         ...cleanUpTransactionThreadReportsOptimisticData,
     );
@@ -341,8 +383,8 @@ function mergeDuplicates({
         failureTransactionData,
         ...failureTransactionDuplicatesData,
         ...failureTransactionViolations,
-        expenseReportFailureData,
-        expenseReportActionsFailureData,
+        ...expenseReportFailureData,
+        ...expenseReportActionsFailureData,
         failureReportActionData,
         ...cleanUpTransactionThreadReportsFailureData,
     );

From 455f534a661d47c34b63d07d7e1fa193513e0259 Mon Sep 17 00:00:00 2001
From: krishna2323 <belivethatkg@gmail.com>
Date: Fri, 5 Jun 2026 23:41:37 +0530
Subject: [PATCH 146/435] refactor: reuse GroupChildrenContentProps and remove
 redundant condition

Signed-off-by: krishna2323 <belivethatkg@gmail.com>
---
 .../ListItem/GroupChildrenContainer.tsx       | 71 +++++++------------
 .../ListItem/GroupChildrenContent.tsx         | 27 +------
 .../Search/SearchList/ListItem/types.ts       | 23 ++++++
 3 files changed, 49 insertions(+), 72 deletions(-)

diff --git a/src/components/Search/SearchList/ListItem/GroupChildrenContainer.tsx b/src/components/Search/SearchList/ListItem/GroupChildrenContainer.tsx
index 0f8e38da4f3c..63fa8911d25a 100644
--- a/src/components/Search/SearchList/ListItem/GroupChildrenContainer.tsx
+++ b/src/components/Search/SearchList/ListItem/GroupChildrenContainer.tsx
@@ -1,36 +1,15 @@
 import React from 'react';
 import {View} from 'react-native';
-import type {OnyxCollection, OnyxEntry} from 'react-native-onyx';
 import Animated from 'react-native-reanimated';
-import type {SearchColumnType, SearchGroupBy} from '@components/Search/types';
 import useExpandCollapseAnimation from '@hooks/useExpandCollapseAnimation';
 import useTheme from '@hooks/useTheme';
 import useThemeStyles from '@hooks/useThemeStyles';
-import type {TransactionPreviewData} from '@libs/actions/Search';
-import type {ModifiedMouseEvent} from '@libs/Navigation/helpers/openInternalRouteInNewTab';
-import type {BankAccountList, CardFeeds, CardList, Transaction} from '@src/types/onyx';
-import type {SearchDataTypes} from '@src/types/onyx/SearchResults';
 import GroupChildrenContent from './GroupChildrenContent';
-import type {GroupChildrenContainerItemType, SearchListItem, TransactionListItemType} from './types';
+import type {GroupChildrenContentProps} from './types';
 
-type GroupChildrenContainerProps = {
-    item: GroupChildrenContainerItemType;
-    isExpanded: boolean;
-    groupBy?: SearchGroupBy;
-    searchType?: SearchDataTypes;
-    columns?: SearchColumnType[];
-    canSelectMultiple: boolean;
-    onSelectRow: (item: SearchListItem, transactionPreviewData?: TransactionPreviewData, event?: ModifiedMouseEvent) => void;
-    onCheckboxPress: (item: SearchListItem, itemTransactions?: TransactionListItemType[]) => void;
-    onLongPressRow?: (item: SearchListItem, itemTransactions?: TransactionListItemType[]) => void;
-    nonPersonalAndWorkspaceCards?: CardList;
-    onUndelete?: (transaction: Transaction) => void;
+type GroupChildrenContainerProps = GroupChildrenContentProps & {
     isLastItem?: boolean;
     isSelected?: boolean;
-    newTransactionID?: string;
-    bankAccountList?: OnyxEntry<BankAccountList>;
-    cardFeeds?: OnyxCollection<CardFeeds>;
-    conciergeReportID?: string;
 };
 
 function GroupChildrenContainer({
@@ -63,30 +42,28 @@ function GroupChildrenContainer({
     return (
         <View style={[styles.mh5, {backgroundColor: isSelected ? theme.activeComponentBG : theme.highlightBG}, isLastItem && [styles.tableBottomRadius, styles.overflowHidden]]}>
             <Animated.View style={animatedStyle}>
-                {(isExpanded || isRendered) && (
-                    <Animated.View
-                        style={[styles.stickToTop, styles.pb1]}
-                        onLayout={onLayout}
-                    >
-                        <GroupChildrenContent
-                            item={item}
-                            isExpanded={isExpanded}
-                            groupBy={groupBy}
-                            searchType={searchType}
-                            columns={columns}
-                            canSelectMultiple={canSelectMultiple}
-                            onSelectRow={onSelectRow}
-                            onCheckboxPress={onCheckboxPress}
-                            onLongPressRow={onLongPressRow}
-                            nonPersonalAndWorkspaceCards={nonPersonalAndWorkspaceCards}
-                            onUndelete={onUndelete}
-                            newTransactionID={newTransactionID}
-                            bankAccountList={bankAccountList}
-                            cardFeeds={cardFeeds}
-                            conciergeReportID={conciergeReportID}
-                        />
-                    </Animated.View>
-                )}
+                <Animated.View
+                    style={[styles.stickToTop, styles.pb1]}
+                    onLayout={onLayout}
+                >
+                    <GroupChildrenContent
+                        item={item}
+                        isExpanded={isExpanded}
+                        groupBy={groupBy}
+                        searchType={searchType}
+                        columns={columns}
+                        canSelectMultiple={canSelectMultiple}
+                        onSelectRow={onSelectRow}
+                        onCheckboxPress={onCheckboxPress}
+                        onLongPressRow={onLongPressRow}
+                        nonPersonalAndWorkspaceCards={nonPersonalAndWorkspaceCards}
+                        onUndelete={onUndelete}
+                        newTransactionID={newTransactionID}
+                        bankAccountList={bankAccountList}
+                        cardFeeds={cardFeeds}
+                        conciergeReportID={conciergeReportID}
+                    />
+                </Animated.View>
             </Animated.View>
         </View>
     );
diff --git a/src/components/Search/SearchList/ListItem/GroupChildrenContent.tsx b/src/components/Search/SearchList/ListItem/GroupChildrenContent.tsx
index 99440c1026eb..afd7cde2d870 100644
--- a/src/components/Search/SearchList/ListItem/GroupChildrenContent.tsx
+++ b/src/components/Search/SearchList/ListItem/GroupChildrenContent.tsx
@@ -1,8 +1,6 @@
 import {useIsFocused} from '@react-navigation/native';
 import React, {useEffect, useMemo, useState} from 'react';
-import type {OnyxCollection, OnyxEntry} from 'react-native-onyx';
 import {useSearchSelectionContext} from '@components/Search/SearchContext';
-import type {SearchColumnType, SearchGroupBy} from '@components/Search/types';
 import useActionLoadingReportIDs from '@hooks/useActionLoadingReportIDs';
 import {useCurrencyListActions} from '@hooks/useCurrencyList';
 import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails';
@@ -10,34 +8,13 @@ import useLocalize from '@hooks/useLocalize';
 import useNetwork from '@hooks/useNetwork';
 import useOnyx from '@hooks/useOnyx';
 import {search} from '@libs/actions/Search';
-import type {TransactionPreviewData} from '@libs/actions/Search';
-import type {ModifiedMouseEvent} from '@libs/Navigation/helpers/openInternalRouteInNewTab';
 import {getSections} from '@libs/SearchUIUtils';
 import {mergeProhibitedViolations, shouldShowViolation} from '@libs/TransactionUtils';
 import CONST from '@src/CONST';
 import ONYXKEYS from '@src/ONYXKEYS';
-import type {BankAccountList, CardFeeds, CardList, Transaction, TransactionViolation, TransactionViolations} from '@src/types/onyx';
-import type {SearchDataTypes} from '@src/types/onyx/SearchResults';
+import type {Transaction, TransactionViolation, TransactionViolations} from '@src/types/onyx';
 import TransactionGroupListExpandedItem from './TransactionGroupListExpanded';
-import type {GroupChildrenContainerItemType, SearchListItem, TransactionGroupListItemType, TransactionListItemType} from './types';
-
-type GroupChildrenContentProps = {
-    item: GroupChildrenContainerItemType;
-    isExpanded: boolean;
-    groupBy?: SearchGroupBy;
-    searchType?: SearchDataTypes;
-    columns?: SearchColumnType[];
-    canSelectMultiple: boolean;
-    onSelectRow: (item: SearchListItem, transactionPreviewData?: TransactionPreviewData, event?: ModifiedMouseEvent) => void;
-    onCheckboxPress: (item: SearchListItem, itemTransactions?: TransactionListItemType[]) => void;
-    onLongPressRow?: (item: SearchListItem, itemTransactions?: TransactionListItemType[]) => void;
-    nonPersonalAndWorkspaceCards?: CardList;
-    onUndelete?: (transaction: Transaction) => void;
-    newTransactionID?: string;
-    bankAccountList?: OnyxEntry<BankAccountList>;
-    cardFeeds?: OnyxCollection<CardFeeds>;
-    conciergeReportID?: string;
-};
+import type {GroupChildrenContentProps, SearchListItem, TransactionGroupListItemType, TransactionListItemType} from './types';
 
 function GroupChildrenContent({
     item,
diff --git a/src/components/Search/SearchList/ListItem/types.ts b/src/components/Search/SearchList/ListItem/types.ts
index 7d57fb3a2506..b0c7cd3c498b 100644
--- a/src/components/Search/SearchList/ListItem/types.ts
+++ b/src/components/Search/SearchList/ListItem/types.ts
@@ -3,9 +3,13 @@ import type {ValueOf} from 'type-fest';
 import type {SearchColumnType, SearchGroupBy, SearchQueryJSON} from '@components/Search/types';
 import type {ListItemProps} from '@components/SelectionList/ListItem/types';
 import type {ListItem} from '@components/SelectionList/types';
+import type {TransactionPreviewData} from '@libs/actions/Search';
+import type {ModifiedMouseEvent} from '@libs/Navigation/helpers/openInternalRouteInNewTab';
 import type CONST from '@src/CONST';
 import type {
+    BankAccountList,
     BillingGraceEndPeriod,
+    CardFeeds,
     CardList,
     LastPaymentMethod,
     PersonalDetails,
@@ -489,6 +493,24 @@ type GroupChildrenContainerItemType = TransactionGroupListItemType & {
     listItemType: 'children_container';
 };
 
+type GroupChildrenContentProps = {
+    item: GroupChildrenContainerItemType;
+    isExpanded: boolean;
+    groupBy?: SearchGroupBy;
+    searchType?: SearchDataTypes;
+    columns?: SearchColumnType[];
+    canSelectMultiple: boolean;
+    onSelectRow: (item: SearchListItem, transactionPreviewData?: TransactionPreviewData, event?: ModifiedMouseEvent) => void;
+    onCheckboxPress: (item: SearchListItem, itemTransactions?: TransactionListItemType[]) => void;
+    onLongPressRow?: (item: SearchListItem, itemTransactions?: TransactionListItemType[]) => void;
+    nonPersonalAndWorkspaceCards?: CardList;
+    onUndelete?: (transaction: Transaction) => void;
+    newTransactionID?: string;
+    bankAccountList?: OnyxEntry<BankAccountList>;
+    cardFeeds?: OnyxCollection<CardFeeds>;
+    conciergeReportID?: string;
+};
+
 type UnreportedExpenseListItemType = Transaction & {
     isDisabled: boolean;
     keyForList: string;
@@ -523,4 +545,5 @@ export type {
     UnreportedExpenseListItemType,
     GroupHeaderItemType,
     GroupChildrenContainerItemType,
+    GroupChildrenContentProps,
 };

From 188e0270d9db4f2ef35b97e3e0cdf803c1931dc5 Mon Sep 17 00:00:00 2001
From: krishna2323 <belivethatkg@gmail.com>
Date: Fri, 5 Jun 2026 23:52:10 +0530
Subject: [PATCH 147/435] fix: don't drill into search when clicking empty
 non-expense-report group

Signed-off-by: krishna2323 <belivethatkg@gmail.com>
---
 src/components/Search/SearchList/ListItem/GroupHeader.tsx | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/components/Search/SearchList/ListItem/GroupHeader.tsx b/src/components/Search/SearchList/ListItem/GroupHeader.tsx
index 5fffd11ffb01..a347f77c40ed 100644
--- a/src/components/Search/SearchList/ListItem/GroupHeader.tsx
+++ b/src/components/Search/SearchList/ListItem/GroupHeader.tsx
@@ -351,7 +351,7 @@ function GroupHeader({
     const shouldDisplayEmptyView = isEmpty && isExpenseReportType;
 
     const handlePress = (event?: ModifiedMouseEvent) => {
-        if (isExpenseReportType || isEmpty) {
+        if (isExpenseReportType) {
             onSelectRow(item, transactionPreviewData, event);
         }
         if (!isExpenseReportType) {

From d0263cee695d9035dfe866166cf11ecc253bfd62 Mon Sep 17 00:00:00 2001
From: krishna2323 <belivethatkg@gmail.com>
Date: Sat, 6 Jun 2026 00:02:00 +0530
Subject: [PATCH 148/435] fix: use snapshot transactions for group selection
 and prevent drill-in on empty groups

Signed-off-by: krishna2323 <belivethatkg@gmail.com>
---
 .../SearchList/ListItem/GroupHeader.tsx       | 42 ++++++++++++++++---
 1 file changed, 36 insertions(+), 6 deletions(-)

diff --git a/src/components/Search/SearchList/ListItem/GroupHeader.tsx b/src/components/Search/SearchList/ListItem/GroupHeader.tsx
index a347f77c40ed..40bd7af409a8 100644
--- a/src/components/Search/SearchList/ListItem/GroupHeader.tsx
+++ b/src/components/Search/SearchList/ListItem/GroupHeader.tsx
@@ -184,15 +184,45 @@ function GroupHeader({
     const isDisabled = item.pendingAction === CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE;
     const isDisabledOrEmpty = isEmpty || isDisabled;
 
+    // For non-expense-report groups, children are loaded from the snapshot
+    // rather than groupItem.transactions (which may be empty). Extract
+    // minimal transaction items from the snapshot so selection and
+    // long-press handlers operate on the actual visible children.
+    const effectiveTransactions = useMemo((): TransactionListItemType[] => {
+        if (isExpenseReportType || groupItem.transactions.length > 0) {
+            return groupItem.transactions;
+        }
+        if (!snapshotData) {
+            return [];
+        }
+        const items: TransactionListItemType[] = [];
+        for (const [key, value] of Object.entries(snapshotData)) {
+            if (!key.startsWith(ONYXKEYS.COLLECTION.TRANSACTION)) {
+                continue;
+            }
+            const tx = value as Record<string, unknown>;
+            if (!tx || typeof tx !== 'object' || !('transactionID' in tx)) {
+                continue;
+            }
+            const report = snapshotData[`${ONYXKEYS.COLLECTION.REPORT}${tx.reportID as string}`] as TransactionListItemType['report'];
+            items.push({
+                ...tx,
+                keyForList: tx.transactionID as string,
+                report,
+            } as TransactionListItemType);
+        }
+        return items;
+    }, [isExpenseReportType, groupItem.transactions, snapshotData]);
+
     const {isSelectAllChecked, isIndeterminate} = useMemo(() => {
         const selectedTransactionIDsSet = new Set(Object.keys(selectedTransactions));
-        const filteredTransactions = groupItem.transactions.filter((transaction) => transaction.pendingAction !== CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE);
-        const selectedCount = groupItem.transactions.reduce((acc, transaction) => (selectedTransactionIDsSet.has(transaction.transactionID) ? acc + 1 : acc), 0);
-        const isEmptyReportSelected = isEmpty && item?.keyForList && selectedTransactions[item.keyForList]?.isSelected;
+        const filteredTransactions = effectiveTransactions.filter((transaction) => transaction.pendingAction !== CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE);
+        const selectedCount = effectiveTransactions.reduce((acc, transaction) => (selectedTransactionIDsSet.has(transaction.transactionID) ? acc + 1 : acc), 0);
+        const isEmptyReportSelected = isEmpty && item.keyForList && selectedTransactions[item.keyForList]?.isSelected;
         const allChecked = !!isEmptyReportSelected || (selectedCount === filteredTransactions.length && filteredTransactions.length > 0);
         const indeterminate = selectedCount > 0 && selectedCount !== filteredTransactions.length;
         return {isSelectAllChecked: allChecked, isIndeterminate: indeterminate};
-    }, [selectedTransactions, groupItem.transactions, isEmpty, item?.keyForList]);
+    }, [selectedTransactions, effectiveTransactions, isEmpty, item.keyForList]);
 
     const isItemSelected = isSelectAllChecked || item?.isSelected;
 
@@ -204,7 +234,7 @@ function GroupHeader({
     });
 
     const handleSelectionButtonPress = () => {
-        onCheckboxPress(item, isExpenseReportType ? undefined : groupItem.transactions);
+        onCheckboxPress(item, isExpenseReportType ? undefined : effectiveTransactions);
     };
 
     const pendingAction =
@@ -360,7 +390,7 @@ function GroupHeader({
     };
 
     const handleLongPress = () => {
-        onLongPressRow?.(item, isExpenseReportType ? undefined : groupItem.transactions);
+        onLongPressRow?.(item, isExpenseReportType ? undefined : effectiveTransactions);
     };
 
     return (

From 568b01b535600500f08cd315eaed70a6f521751b Mon Sep 17 00:00:00 2001
From: MobileMage <aidelojejoshua@gmail.com>
Date: Fri, 5 Jun 2026 19:50:05 +0100
Subject: [PATCH 149/435] Redirect post-merge to the kept expense report

---
 src/pages/TransactionDuplicate/Confirmation.tsx | 9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/src/pages/TransactionDuplicate/Confirmation.tsx b/src/pages/TransactionDuplicate/Confirmation.tsx
index ce26ba0a978f..174c8a0d8a69 100644
--- a/src/pages/TransactionDuplicate/Confirmation.tsx
+++ b/src/pages/TransactionDuplicate/Confirmation.tsx
@@ -21,6 +21,7 @@ import useThemeStyles from '@hooks/useThemeStyles';
 import useTransactionsByID from '@hooks/useTransactionsByID';
 import useTransactionThreadReportIDs from '@hooks/useTransactionThreadReportIDs';
 import {mergeDuplicates, resolveDuplicates} from '@libs/actions/IOU/Duplicate';
+import {setDeleteTransactionNavigateBackUrl} from '@libs/actions/Report';
 import getNonEmptyStringOnyxID from '@libs/getNonEmptyStringOnyxID';
 import Navigation from '@libs/Navigation/Navigation';
 import type {PlatformStackRouteProp} from '@libs/Navigation/PlatformStackNavigation/types';
@@ -33,6 +34,7 @@ import * as ReportUtils from '@src/libs/ReportUtils';
 import {generateReportID} from '@src/libs/ReportUtils';
 import * as TransactionUtils from '@src/libs/TransactionUtils';
 import ONYXKEYS from '@src/ONYXKEYS';
+import ROUTES from '@src/ROUTES';
 import type SCREENS from '@src/SCREENS';
 import type {Transaction} from '@src/types/onyx';
 import {isEmptyObject} from '@src/types/utils/EmptyObject';
@@ -102,12 +104,17 @@ function Confirmation() {
     const handleMergeDuplicates = useCallback(() => {
         const transactionThreadReportID = childReportID ?? generateReportID();
         const mergeParams = !childReportID ? {...transactionsMergeParams, transactionThreadReportID} : transactionsMergeParams;
+        // Server deletes the discarded transaction's now-empty expense report on merge and
+        // pushes back a "Report not found" payload for it. Hint the guard and redirect to
+        // the kept transaction's report so the user doesn't land on the discarded one.
+        const keptReportRoute = ROUTES.REPORT_WITH_ID.getRoute(mergeParams.reportID);
+        setDeleteTransactionNavigateBackUrl(keptReportRoute);
         mergeDuplicates({...mergeParams, ...taxData, currentUserAccountID, currentUserLogin: currentUserLogin ?? ''});
         if (isSuperWideRHPDisplayed) {
             Navigation.dismissToSuperWideRHP();
             return;
         }
-        Navigation.dismissModal();
+        Navigation.goBack(keptReportRoute);
     }, [childReportID, transactionsMergeParams, taxData, currentUserAccountID, currentUserLogin, isSuperWideRHPDisplayed]);
 
     const handleResolveDuplicates = useCallback(() => {

From 20a66903de02c13669306f7ecf7f5b356b38cc51 Mon Sep 17 00:00:00 2001
From: Alex Beaman <alexbeaman@expensify.com>
Date: Fri, 5 Jun 2026 13:06:09 -0600
Subject: [PATCH 150/435] HTML-encode vendorName in ConciergeAutoMatchVendor
 action (Codex P2)

The translation 'iou.conciergeAutoMatchedVendor' interpolates vendorName
into an HTML template (`Concierge matched this expense to <strong>${vendorName}</strong>`)
that is rendered by ReportActionItemMessageWithExplain via RenderHTML. A QBO
vendor name containing HTML (e.g. `</strong><a href="...">link</a>`) would be
parsed as markup. Encode the vendor name via Str.htmlEncode at the renderer.
---
 .../actionContents/ConciergeAutoMatchVendorContent.tsx      | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/src/pages/inbox/report/actionContents/ConciergeAutoMatchVendorContent.tsx b/src/pages/inbox/report/actionContents/ConciergeAutoMatchVendorContent.tsx
index a5c9b2fe999e..b01b92338b2e 100644
--- a/src/pages/inbox/report/actionContents/ConciergeAutoMatchVendorContent.tsx
+++ b/src/pages/inbox/report/actionContents/ConciergeAutoMatchVendorContent.tsx
@@ -1,3 +1,4 @@
+import {Str} from 'expensify-common';
 import React from 'react';
 import type {OnyxEntry} from 'react-native-onyx';
 import useLocalize from '@hooks/useLocalize';
@@ -18,7 +19,10 @@ function ConciergeAutoMatchVendorContent({action, originalReport}: ConciergeAuto
     const [childReport] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${getNonEmptyStringOnyxID(action.childReportID)}`);
 
     const originalMessage = getOriginalMessage(action);
-    const vendorName = originalMessage && typeof originalMessage === 'object' && 'vendorName' in originalMessage ? (originalMessage.vendorName ?? '') : '';
+    const rawVendorName = originalMessage && typeof originalMessage === 'object' && 'vendorName' in originalMessage ? (originalMessage.vendorName ?? '') : '';
+
+    // vendorName is interpolated into an HTML translation rendered via RenderHTML, so encode it to prevent QBO vendor names containing HTML from being parsed as markup.
+    const vendorName = Str.htmlEncode(rawVendorName);
     const message = translate('iou.conciergeAutoMatchedVendor', {vendorName});
 
     return (

From ca0131a02eff9f6c33aaa7c2eb92607d11d73563 Mon Sep 17 00:00:00 2001
From: Alex Beaman <alexbeaman@expensify.com>
Date: Fri, 5 Jun 2026 13:12:53 -0600
Subject: [PATCH 151/435] Drop unused export of
 OriginalMessageConciergeAutoMatchVendor (knip)

The type is referenced only inside OriginalMessageMap in this file; nothing
imports it externally, so knip flagged the named re-export. Keep the type
definition (it's load-bearing for the map entry) but drop the unused export.
---
 src/types/onyx/OriginalMessage.ts | 1 -
 1 file changed, 1 deletion(-)

diff --git a/src/types/onyx/OriginalMessage.ts b/src/types/onyx/OriginalMessage.ts
index 3c312aab879c..79aabefc2969 100644
--- a/src/types/onyx/OriginalMessage.ts
+++ b/src/types/onyx/OriginalMessage.ts
@@ -1696,7 +1696,6 @@ export type {
     OriginalMessageChangeLog,
     JoinWorkspaceResolution,
     OriginalMessageModifiedExpense,
-    OriginalMessageConciergeAutoMatchVendor,
     OriginalMessageExportIntegration,
     IssueNewCardOriginalMessage,
     OriginalMessageChangePolicy,

From 237851358d2bb8cb13bfdc6c7dd7d5b7e6659d61 Mon Sep 17 00:00:00 2001
From: MobileMage <aidelojejoshua@gmail.com>
Date: Fri, 5 Jun 2026 22:09:36 +0100
Subject: [PATCH 152/435] Compact cross-report merge cleanup

---
 src/libs/actions/IOU/Duplicate.ts | 117 +++++++-----------------------
 1 file changed, 28 insertions(+), 89 deletions(-)

diff --git a/src/libs/actions/IOU/Duplicate.ts b/src/libs/actions/IOU/Duplicate.ts
index 560d5262e2a1..b6e8394639f3 100644
--- a/src/libs/actions/IOU/Duplicate.ts
+++ b/src/libs/actions/IOU/Duplicate.ts
@@ -211,113 +211,52 @@ function mergeDuplicates({
 
     const expenseReport = allReports?.[`${ONYXKEYS.COLLECTION.REPORT}${params.reportID}`];
 
-    // Group each discarded duplicate by its own source report so cleanup targets the right
-    // REPORT and REPORT_ACTIONS Onyx keys when duplicates live in different expense reports.
-    const allIOUReportActions = getAllReportActionsFromIOU();
-    type DiscardedDuplicate = {
-        iouAction: OnyxTypes.ReportAction<typeof CONST.REPORT.ACTIONS.TYPE.IOU>;
-        sourceReportID: string;
-        amount: number;
-    };
-    const discardedDuplicates: DiscardedDuplicate[] = [];
+    // Group each discarded duplicate's IOU action and amount by its own source report so the
+    // soft-delete MERGE and total decrement target the correct keys when duplicates span reports.
+    const sources = new Map<string, {amount: number; actions: Array<OnyxTypes.ReportAction<typeof CONST.REPORT.ACTIONS.TYPE.IOU>>}>();
     for (const id of params.transactionIDList) {
         const transaction = allTransactions[`${ONYXKEYS.COLLECTION.TRANSACTION}${id}`];
-        const sourceReportID = transaction?.reportID;
-        if (!sourceReportID) {
-            continue;
-        }
-        const reportActions = allIOUReportActions?.[`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${sourceReportID}`];
-        const iouAction = Object.values(reportActions ?? {}).find((reportAction): reportAction is OnyxTypes.ReportAction<typeof CONST.REPORT.ACTIONS.TYPE.IOU> => {
-            if (!isMoneyRequestAction(reportAction)) {
-                return false;
-            }
-            return getOriginalMessage(reportAction)?.IOUTransactionID === id;
-        });
-        if (!iouAction) {
+        if (!transaction?.reportID) {
             continue;
         }
-        discardedDuplicates.push({iouAction, sourceReportID, amount: transaction.amount ?? 0});
+        const entry = sources.get(transaction.reportID) ?? {amount: 0, actions: []};
+        entry.amount += transaction.amount;
+        entry.actions.push(...getIOUActionForTransactions([id], transaction.reportID));
+        sources.set(transaction.reportID, entry);
     }
-    const iouActionsToDelete = discardedDuplicates.map(({iouAction}) => iouAction);
-
-    const discardedDuplicatesBySourceReport = discardedDuplicates.reduce<Record<string, DiscardedDuplicate[]>>((acc, entry) => {
-        const bucket = acc[entry.sourceReportID];
-        if (bucket) {
-            bucket.push(entry);
-        } else {
-            acc[entry.sourceReportID] = [entry];
-        }
-        return acc;
-    }, {});
+    const iouActionsToDelete = [...sources.values()].flatMap(({actions}) => actions);
 
+    const deletedTime = DateUtils.getDBTime();
     const expenseReportOptimisticData: Array<OnyxUpdate<typeof ONYXKEYS.COLLECTION.REPORT>> = [];
     const expenseReportFailureData: Array<OnyxUpdate<typeof ONYXKEYS.COLLECTION.REPORT>> = [];
-    const deletedTime = DateUtils.getDBTime();
     const expenseReportActionsOptimisticData: Array<OnyxUpdate<typeof ONYXKEYS.COLLECTION.REPORT_ACTIONS>> = [];
     const expenseReportActionsFailureData: Array<OnyxUpdate<typeof ONYXKEYS.COLLECTION.REPORT_ACTIONS>> = [];
-
-    for (const [sourceReportID, entries] of Object.entries(discardedDuplicatesBySourceReport)) {
+    for (const [sourceReportID, {amount, actions}] of sources) {
         const sourceReport = allReports?.[`${ONYXKEYS.COLLECTION.REPORT}${sourceReportID}`];
-        const sourceDuplicateTotals = entries.reduce((total, entry) => total + entry.amount, 0);
-        expenseReportOptimisticData.push({
-            onyxMethod: Onyx.METHOD.MERGE,
-            key: `${ONYXKEYS.COLLECTION.REPORT}${sourceReportID}`,
-            value: {
-                total: (sourceReport?.total ?? 0) - sourceDuplicateTotals,
-            },
-        });
-        expenseReportFailureData.push({
-            onyxMethod: Onyx.METHOD.MERGE,
-            key: `${ONYXKEYS.COLLECTION.REPORT}${sourceReportID}`,
-            value: {
-                total: sourceReport?.total,
-            },
-        });
-
-        const optimisticActionsValue = entries.reduce<Record<string, PartialDeep<OnyxTypes.ReportAction<typeof CONST.REPORT.ACTIONS.TYPE.IOU>>>>((val, {iouAction}) => {
-            const firstMessage = Array.isArray(iouAction.message) ? iouAction.message.at(0) : null;
-            // eslint-disable-next-line no-param-reassign
-            val[iouAction.reportActionID] = {
-                originalMessage: {
-                    deleted: deletedTime,
-                },
-                ...(firstMessage && {
-                    message: [
-                        {
-                            ...firstMessage,
-                            deleted: deletedTime,
-                        },
-                        ...(Array.isArray(iouAction.message) ? iouAction.message.slice(1) : []),
-                    ],
-                }),
-                ...(!Array.isArray(iouAction.message) && {
-                    message: {
-                        deleted: deletedTime,
-                    },
-                }),
-            };
-            return val;
-        }, {});
+        expenseReportOptimisticData.push({onyxMethod: Onyx.METHOD.MERGE, key: `${ONYXKEYS.COLLECTION.REPORT}${sourceReportID}`, value: {total: (sourceReport?.total ?? 0) - amount}});
+        expenseReportFailureData.push({onyxMethod: Onyx.METHOD.MERGE, key: `${ONYXKEYS.COLLECTION.REPORT}${sourceReportID}`, value: {total: sourceReport?.total}});
         expenseReportActionsOptimisticData.push({
             onyxMethod: Onyx.METHOD.MERGE,
             key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${sourceReportID}`,
-            value: optimisticActionsValue,
+            value: actions.reduce<Record<string, PartialDeep<OnyxTypes.ReportAction<typeof CONST.REPORT.ACTIONS.TYPE.IOU>>>>((val, reportAction) => {
+                const firstMessage = Array.isArray(reportAction.message) ? reportAction.message.at(0) : null;
+                // eslint-disable-next-line no-param-reassign
+                val[reportAction.reportActionID] = {
+                    originalMessage: {deleted: deletedTime},
+                    ...(firstMessage && {message: [{...firstMessage, deleted: deletedTime}, ...(Array.isArray(reportAction.message) ? reportAction.message.slice(1) : [])]}),
+                    ...(!Array.isArray(reportAction.message) && {message: {deleted: deletedTime}}),
+                };
+                return val;
+            }, {}),
         });
-
-        const failureActionsValue = entries.reduce<Record<string, NullishDeep<PartialDeep<OnyxTypes.ReportAction<typeof CONST.REPORT.ACTIONS.TYPE.IOU>>>>>((val, {iouAction}) => {
-            // eslint-disable-next-line no-param-reassign
-            val[iouAction.reportActionID] = {
-                originalMessage: {
-                    deleted: null,
-                },
-                message: iouAction.message,
-            };
-            return val;
-        }, {});
         expenseReportActionsFailureData.push({
             onyxMethod: Onyx.METHOD.MERGE,
             key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${sourceReportID}`,
-            value: failureActionsValue,
+            value: actions.reduce<Record<string, NullishDeep<PartialDeep<OnyxTypes.ReportAction<typeof CONST.REPORT.ACTIONS.TYPE.IOU>>>>>((val, reportAction) => {
+                // eslint-disable-next-line no-param-reassign
+                val[reportAction.reportActionID] = {originalMessage: {deleted: null}, message: reportAction.message};
+                return val;
+            }, {}),
         });
     }
 

From 473b29daab208b695d7ee7699dd138c86f370d46 Mon Sep 17 00:00:00 2001
From: Alex Beaman <alexbeaman@expensify.com>
Date: Fri, 5 Jun 2026 16:04:18 -0600
Subject: [PATCH 153/435] Block vendor edits on reimbursable expenses in
 IOURequestStepVendor (Codex P2)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

The RHP previously gated only on the workspace feature flag, so a deep link
or stale-open scenario could let updateMoneyRequestVendor fire on a
reimbursable transaction — even though MoneyRequestView intentionally hides
the row in that case. Treat reimbursable as a not-found gate to match the
intended scope (QBO non-reimbursable expenses only).
---
 src/pages/iou/request/step/IOURequestStepVendor.tsx | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/src/pages/iou/request/step/IOURequestStepVendor.tsx b/src/pages/iou/request/step/IOURequestStepVendor.tsx
index 3742ee6e28c0..196782b018a7 100644
--- a/src/pages/iou/request/step/IOURequestStepVendor.tsx
+++ b/src/pages/iou/request/step/IOURequestStepVendor.tsx
@@ -50,6 +50,9 @@ function IOURequestStepVendor({
     });
 
     const isFeatureAvailable = hasVendorFeature(policy, isBetaEnabled(CONST.BETAS.VENDOR_MATCHING));
+
+    // Vendor is scoped to non-reimbursable expenses; block deep-link / stale-open access if the transaction is reimbursable.
+    const isReimbursable = !!transaction?.reimbursable;
     const vendors = useMemo(() => getQBOVendors(policy), [policy]);
     const currentVendorID = transaction?.comment?.vendor?.externalID;
 
@@ -66,7 +69,7 @@ function IOURequestStepVendor({
             }));
     }, [vendors, currentVendorID, searchValue]);
 
-    const shouldShowNotFoundPage = useShowNotFoundPageInIOUStep(action, iouType, reportActionID, report, transaction) || !isFeatureAvailable;
+    const shouldShowNotFoundPage = useShowNotFoundPageInIOUStep(action, iouType, reportActionID, report, transaction) || !isFeatureAvailable || isReimbursable;
 
     const navigateBack = () => {
         Navigation.goBack();

From 6da0f1429c797aa32a7bc0fdf867b526488e80ed Mon Sep 17 00:00:00 2001
From: Alex Beaman <alexbeaman@expensify.com>
Date: Fri, 5 Jun 2026 16:33:08 -0600
Subject: [PATCH 154/435] Add "None" row to vendor selector to clear stale
 vendor (Codex P2)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

When the matched vendor is removed in QBO (or any user wants to undo a
match), the selector previously only listed active vendors — leaving users
unable to resolve an inactiveVendor violation without picking a replacement
that may not exist or may be incorrect.

The Phase 1 updateMoneyRequestVendor action already supports vendorID=''
to clear the vendor and resolve the violation; this exposes that path
through a "None" row at the top of the list, shown only when a vendor is
currently set and the search box is empty (keeps the first-pick and
filtered-search experiences clean). Reuses common.none — no new
translation key needed.
---
 .../iou/request/step/IOURequestStepVendor.tsx   | 17 +++++++++++++++--
 1 file changed, 15 insertions(+), 2 deletions(-)

diff --git a/src/pages/iou/request/step/IOURequestStepVendor.tsx b/src/pages/iou/request/step/IOURequestStepVendor.tsx
index 196782b018a7..c67fa6b663c8 100644
--- a/src/pages/iou/request/step/IOURequestStepVendor.tsx
+++ b/src/pages/iou/request/step/IOURequestStepVendor.tsx
@@ -58,7 +58,7 @@ function IOURequestStepVendor({
 
     const data: VendorListItem[] = useMemo(() => {
         const trimmed = searchValue.trim().toLowerCase();
-        return vendors
+        const vendorRows = vendors
             .filter((vendor) => !trimmed || vendor.name.toLowerCase().includes(trimmed))
             .map((vendor) => ({
                 value: vendor.id,
@@ -67,7 +67,20 @@ function IOURequestStepVendor({
                 isSelected: vendor.id === currentVendorID,
                 searchText: vendor.name,
             }));
-    }, [vendors, currentVendorID, searchValue]);
+
+        // When a vendor is currently set, offer a "None" row so the user can clear a stale (e.g. removed-from-QBO) vendor without picking a replacement, which resolves an inactiveVendor violation. Hidden during search to keep results clean.
+        if (!currentVendorID || trimmed) {
+            return vendorRows;
+        }
+        const clearRow: VendorListItem = {
+            value: '',
+            text: translate('common.none'),
+            keyForList: 'clear-vendor',
+            isSelected: false,
+            searchText: '',
+        };
+        return [clearRow, ...vendorRows];
+    }, [vendors, currentVendorID, searchValue, translate]);
 
     const shouldShowNotFoundPage = useShowNotFoundPageInIOUStep(action, iouType, reportActionID, report, transaction) || !isFeatureAvailable || isReimbursable;
 

From b919c40775ffbfa725236d5862dcd58e89f0f270 Mon Sep 17 00:00:00 2001
From: Rushat Gabhane <rushatgabhane@gmail.com>
Date: Sat, 6 Jun 2026 00:59:35 +0200
Subject: [PATCH 155/435] a11y feat: seperate dismiss button and dont auto open
 the calendar

---
 src/components/DatePicker/index.tsx | 26 +++++++++++++++++---------
 1 file changed, 17 insertions(+), 9 deletions(-)

diff --git a/src/components/DatePicker/index.tsx b/src/components/DatePicker/index.tsx
index c3f813054e2a..89dac63a340a 100644
--- a/src/components/DatePicker/index.tsx
+++ b/src/components/DatePicker/index.tsx
@@ -2,6 +2,7 @@ import {format, setYear} from 'date-fns';
 import React, {useCallback, useEffect, useMemo, useRef, useState} from 'react';
 // eslint-disable-next-line no-restricted-imports
 import {InteractionManager, View} from 'react-native';
+import type {GestureResponderEvent} from 'react-native';
 import TextInput from '@components/TextInput';
 import type {BaseTextInputRef} from '@components/TextInput/BaseTextInput/types';
 import useAccessibilityAnnouncement from '@hooks/useAccessibilityAnnouncement';
@@ -80,13 +81,19 @@ function DatePicker({
         });
     }, [windowHeight]);
 
-    const showDatePickerModal = useCallback(() => {
-        cancelAutoFocus();
-        // Blur the input before showing the modal, so the focus won't be returned after the modal is closed
-        textInputRef.current?.blur();
-        calculatePopoverPosition();
-        setIsModalVisible(true);
-    }, [calculatePopoverPosition, cancelAutoFocus]);
+    const showDatePickerModal = useCallback(
+        (event?: GestureResponderEvent | KeyboardEvent) => {
+            if (event && 'preventDefault' in event) {
+                event.preventDefault();
+            }
+            cancelAutoFocus();
+            // Blur the input before showing the modal, so the focus won't be returned after the modal is closed
+            textInputRef.current?.blur();
+            calculatePopoverPosition();
+            setIsModalVisible(true);
+        },
+        [calculatePopoverPosition, cancelAutoFocus],
+    );
 
     const closeDatePicker = useCallback(() => {
         setIsModalVisible(false);
@@ -148,13 +155,14 @@ function DatePicker({
                     iconContainerStyle={styles.pr0}
                     label={label}
                     accessibilityLabel={label}
-                    role={CONST.ROLE.PRESENTATION}
+                    role={CONST.ROLE.COMBOBOX}
                     value={selectedDate}
                     placeholder={placeholder ?? translate('common.dateFormat')}
                     errorText={errorText}
                     inputStyle={styles.pointerEventsNone}
                     disabled={disabled}
-                    onFocus={showDatePickerModal}
+                    onPress={showDatePickerModal}
+                    onSubmitEditing={() => showDatePickerModal()}
                     textInputContainerStyles={isModalVisible ? styles.borderColorFocus : {}}
                     shouldHideClearButton={shouldHideClearButton}
                     onClearInput={handleClear}

From 7b6b6801f1ace842de99ae4bf766f90a7737b178 Mon Sep 17 00:00:00 2001
From: Rushat Gabhane <rushatgabhane@gmail.com>
Date: Sat, 6 Jun 2026 01:30:22 +0200
Subject: [PATCH 156/435] on number input, open the datepicker

---
 src/components/DatePicker/index.tsx | 15 ++++++++++++++-
 1 file changed, 14 insertions(+), 1 deletion(-)

diff --git a/src/components/DatePicker/index.tsx b/src/components/DatePicker/index.tsx
index 919f46b651db..97a719fc7716 100644
--- a/src/components/DatePicker/index.tsx
+++ b/src/components/DatePicker/index.tsx
@@ -2,7 +2,7 @@ import {format, setYear} from 'date-fns';
 import React, {useCallback, useEffect, useMemo, useRef, useState} from 'react';
 // eslint-disable-next-line no-restricted-imports
 import {InteractionManager, View} from 'react-native';
-import type {GestureResponderEvent} from 'react-native';
+import type {GestureResponderEvent, TextInputKeyPressEvent} from 'react-native';
 import TextInput from '@components/TextInput';
 import type {BaseTextInputRef} from '@components/TextInput/BaseTextInput/types';
 import useAccessibilityAnnouncement from '@hooks/useAccessibilityAnnouncement';
@@ -11,6 +11,7 @@ import {useMemoizedLazyExpensifyIcons} from '@hooks/useLazyAsset';
 import useLocalize from '@hooks/useLocalize';
 import useThemeStyles from '@hooks/useThemeStyles';
 import useWindowDimensions from '@hooks/useWindowDimensions';
+import {isNumeric} from '@libs/ValidationUtils';
 import {setDraftValues} from '@userActions/FormActions';
 import CONST from '@src/CONST';
 import DatePickerModal from './DatePickerModal';
@@ -131,6 +132,17 @@ function DatePicker({
         showDatePickerModal();
     }, [autoFocus, showDatePickerModal]);
 
+    const handleInputKeyPress = useCallback(
+        (event: TextInputKeyPressEvent) => {
+            if (!isNumeric(event.nativeEvent.key)) {
+                return;
+            }
+            event.preventDefault();
+            showDatePickerModal();
+        },
+        [showDatePickerModal],
+    );
+
     const handleDateSelected = (newDate: string) => {
         onTouched?.();
         onInputChange?.(newDate);
@@ -195,6 +207,7 @@ function DatePicker({
                     disabled={disabled}
                     onPress={showDatePickerModal}
                     onSubmitEditing={() => showDatePickerModal()}
+                    onKeyPress={handleInputKeyPress}
                     onFocus={handleInputFocus}
                     textInputContainerStyles={isModalVisible ? styles.borderColorFocus : {}}
                     shouldHideClearButton={shouldHideClearButton}

From 6f2fa59233760402dfdcc72357b6d6939c284cfd Mon Sep 17 00:00:00 2001
From: Youssef Lourayad <youssef@expensify.com>
Date: Fri, 5 Jun 2026 23:47:25 +0000
Subject: [PATCH 157/435] Fix unequal tab width in native

---
 src/components/TabSelector/TabSelectorBase.tsx | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/src/components/TabSelector/TabSelectorBase.tsx b/src/components/TabSelector/TabSelectorBase.tsx
index b5aaab0a130e..7209dc573e51 100644
--- a/src/components/TabSelector/TabSelectorBase.tsx
+++ b/src/components/TabSelector/TabSelectorBase.tsx
@@ -62,7 +62,11 @@ function TabSelectorBase({
             }}
             ref={containerRef}
             style={styles.scrollableTabSelector}
-            contentContainerStyle={[styles.tabSelectorContentContainer, contentContainerStyles]}
+            // On iOS a horizontal ScrollView lays out its content along an unbounded main axis, so flex-1 tabs
+            // (equalWidth) divide their intrinsic content width instead of the viewport. Giving the content
+            // container a definite width lets the flex children split it evenly. Scoped to equalWidth so normal
+            // overflowing/scrollable tab rows are not constrained.
+            contentContainerStyle={[styles.tabSelectorContentContainer, equalWidth && styles.w100, contentContainerStyles]}
             horizontal
             showsHorizontalScrollIndicator={false}
             keyboardShouldPersistTaps="handled"

From 4580d735b12af47ff7f55f945e5bc63b48217ca2 Mon Sep 17 00:00:00 2001
From: MobileMage <aidelojejoshua@gmail.com>
Date: Sat, 6 Jun 2026 00:54:16 +0100
Subject: [PATCH 158/435] Scope merge cleanup accumulator per source report

---
 src/libs/actions/IOU/Duplicate.ts | 43 +++++++++++++++----------------
 1 file changed, 21 insertions(+), 22 deletions(-)

diff --git a/src/libs/actions/IOU/Duplicate.ts b/src/libs/actions/IOU/Duplicate.ts
index b6e8394639f3..257166082f7e 100644
--- a/src/libs/actions/IOU/Duplicate.ts
+++ b/src/libs/actions/IOU/Duplicate.ts
@@ -224,13 +224,14 @@ function mergeDuplicates({
         entry.actions.push(...getIOUActionForTransactions([id], transaction.reportID));
         sources.set(transaction.reportID, entry);
     }
-    const iouActionsToDelete = [...sources.values()].flatMap(({actions}) => actions);
-
     const deletedTime = DateUtils.getDBTime();
     const expenseReportOptimisticData: Array<OnyxUpdate<typeof ONYXKEYS.COLLECTION.REPORT>> = [];
     const expenseReportFailureData: Array<OnyxUpdate<typeof ONYXKEYS.COLLECTION.REPORT>> = [];
     const expenseReportActionsOptimisticData: Array<OnyxUpdate<typeof ONYXKEYS.COLLECTION.REPORT_ACTIONS>> = [];
     const expenseReportActionsFailureData: Array<OnyxUpdate<typeof ONYXKEYS.COLLECTION.REPORT_ACTIONS>> = [];
+    const cleanUpTransactionThreadReportsOptimisticData = [];
+    const cleanUpTransactionThreadReportsSuccessData = [];
+    const cleanUpTransactionThreadReportsFailureData = [];
     for (const [sourceReportID, {amount, actions}] of sources) {
         const sourceReport = allReports?.[`${ONYXKEYS.COLLECTION.REPORT}${sourceReportID}`];
         expenseReportOptimisticData.push({onyxMethod: Onyx.METHOD.MERGE, key: `${ONYXKEYS.COLLECTION.REPORT}${sourceReportID}`, value: {total: (sourceReport?.total ?? 0) - amount}});
@@ -258,27 +259,25 @@ function mergeDuplicates({
                 return val;
             }, {}),
         });
-    }
 
-    const cleanUpTransactionThreadReportsOptimisticData = [];
-    const cleanUpTransactionThreadReportsSuccessData = [];
-    const cleanUpTransactionThreadReportsFailureData = [];
-    let updatedReportPreviewAction;
-    for (const [index, iouAction] of Object.entries(iouActionsToDelete)) {
-        const transactionThreadID = iouAction.childReportID;
-        const shouldDeleteTransactionThread = !!transactionThreadID;
-        const cleanUpTransactionThreadReportOnyxDataForIouAction = getCleanUpTransactionThreadReportOnyxData({
-            transactionThreadID,
-            shouldDeleteTransactionThread,
-            reportAction: iouAction,
-            updatedReportPreviewAction,
-            shouldAddUpdatedReportPreviewActionToOnyxData: Number(index) === iouActionsToDelete.length - 1,
-            currentUserAccountID,
-        });
-        cleanUpTransactionThreadReportsOptimisticData.push(...cleanUpTransactionThreadReportOnyxDataForIouAction.optimisticData);
-        cleanUpTransactionThreadReportsSuccessData.push(...cleanUpTransactionThreadReportOnyxDataForIouAction.successData);
-        cleanUpTransactionThreadReportsFailureData.push(...cleanUpTransactionThreadReportOnyxDataForIouAction.failureData);
-        updatedReportPreviewAction = cleanUpTransactionThreadReportOnyxDataForIouAction.updatedReportPreviewAction;
+        // Reset the report-preview accumulator per source so each source report's chat parent
+        // gets its own flushed update (and we don't leak one source's preview action into another).
+        let updatedReportPreviewAction;
+        for (const [index, iouAction] of actions.entries()) {
+            const transactionThreadID = iouAction.childReportID;
+            const cleanUp = getCleanUpTransactionThreadReportOnyxData({
+                transactionThreadID,
+                shouldDeleteTransactionThread: !!transactionThreadID,
+                reportAction: iouAction,
+                updatedReportPreviewAction,
+                shouldAddUpdatedReportPreviewActionToOnyxData: index === actions.length - 1,
+                currentUserAccountID,
+            });
+            cleanUpTransactionThreadReportsOptimisticData.push(...cleanUp.optimisticData);
+            cleanUpTransactionThreadReportsSuccessData.push(...cleanUp.successData);
+            cleanUpTransactionThreadReportsFailureData.push(...cleanUp.failureData);
+            updatedReportPreviewAction = cleanUp.updatedReportPreviewAction;
+        }
     }
     const optimisticReportAction = buildOptimisticResolvedDuplicatesReportAction();
 

From 8778846310b984cff9783d751de7c8c7b8185743 Mon Sep 17 00:00:00 2001
From: "Christina Dobrzynski (via MelvinBot)" <infra+melvinbot@expensify.com>
Date: Sat, 6 Jun 2026 00:01:42 +0000
Subject: [PATCH 159/435] Update Report suspicious activity copy to clarify
 when to lock an account

Co-authored-by: Christina Dobrzynski <Christinadobrzyn@users.noreply.github.com>
---
 src/languages/en.ts                                 | 10 +++++++---
 .../Security/LockAccount/LockAccountPage.tsx        | 13 +++++++++----
 .../Security/LockAccount/LockAccountPageBase.tsx    |  4 +++-
 3 files changed, 19 insertions(+), 8 deletions(-)

diff --git a/src/languages/en.ts b/src/languages/en.ts
index 0790bc189b09..78c2e1f482e0 100644
--- a/src/languages/en.ts
+++ b/src/languages/en.ts
@@ -2303,12 +2303,16 @@ const translations = {
     lockAccountPage: {
         reportSuspiciousActivity: 'Report suspicious activity',
         lockAccount: 'Lock account',
+        lockMyAccount: 'Lock my account',
         unlockAccount: 'Unlock account',
         unlockTitle: 'We’ve received your request',
         unlockDescription: 'We’ll review the account to verify it’s safe to unlock and reach out via Concierge with any questions.',
-        compromisedDescription:
-            'Notice something off with your account? Reporting it will immediately lock your account, block new Expensify Card transactions, and prevent any account changes.',
-        domainAdminsDescription: 'For domain admins: This also pauses all Expensify Card activity and admin actions across your domain(s).',
+        findYourSituation: 'Most issues don’t require locking your account! Find your situation below:',
+        lostCardOrCharges:
+            '<a href="https://help.expensify.com/articles/expensify-classic/expensify-card/Dispute-Transaction">Lost card or unfamiliar charges</a>: Cancel your card and contact Concierge to dispute unknown transactions.',
+        unauthorizedAccess:
+            '<a href="https://help.expensify.com/articles/expensify-classic/settings/Report-Suspicious-Activity">Unauthorized account access</a>: Lock your account below. This blocks new Expensify Card transactions, card orders, and account changes. If you’re a domain admin, this also pauses all domain-wide card activity and admin actions.',
+        securityTeamFollowUp: 'Our security team will follow up from <a href="mailto:risk@expensify.com">risk@expensify.com</a> after locking.',
         areYouSure: 'Are you sure you want to lock your Expensify account?',
         onceLocked: 'Once locked, your account will be restricted pending an unlock request and a security review',
     },
diff --git a/src/pages/settings/Security/LockAccount/LockAccountPage.tsx b/src/pages/settings/Security/LockAccount/LockAccountPage.tsx
index 8bfee04743fd..798abe7d416c 100644
--- a/src/pages/settings/Security/LockAccount/LockAccountPage.tsx
+++ b/src/pages/settings/Security/LockAccount/LockAccountPage.tsx
@@ -1,4 +1,6 @@
 import React from 'react';
+import {View} from 'react-native';
+import RenderHTML from '@components/RenderHTML';
 import Text from '@components/Text';
 import useLocalize from '@hooks/useLocalize';
 import useThemeStyles from '@hooks/useThemeStyles';
@@ -31,10 +33,12 @@ function LockAccountPage() {
     );
 
     const lockAccountPagePrompt = (
-        <>
-            <Text>{translate('lockAccountPage.compromisedDescription')}</Text>
-            <Text>{translate('lockAccountPage.domainAdminsDescription')}</Text>
-        </>
+        <View style={[styles.renderHTML, styles.gap4]}>
+            <RenderHTML html={translate('lockAccountPage.findYourSituation')} />
+            <RenderHTML html={translate('lockAccountPage.lostCardOrCharges')} />
+            <RenderHTML html={translate('lockAccountPage.unauthorizedAccess')} />
+            <RenderHTML html={translate('lockAccountPage.securityTeamFollowUp')} />
+        </View>
     );
 
     return (
@@ -43,6 +47,7 @@ function LockAccountPage() {
             onBackButtonPress={() => Navigation.goBack()}
             confirmModalPrompt={confirmModalPrompt}
             lockAccountPagePrompt={lockAccountPagePrompt}
+            lockButtonText={translate('lockAccountPage.lockMyAccount')}
             handleLockRequestFinish={handleLockRequestFinish}
         />
     );
diff --git a/src/pages/settings/Security/LockAccount/LockAccountPageBase.tsx b/src/pages/settings/Security/LockAccount/LockAccountPageBase.tsx
index 517746ad183a..bcd062ee8060 100644
--- a/src/pages/settings/Security/LockAccount/LockAccountPageBase.tsx
+++ b/src/pages/settings/Security/LockAccount/LockAccountPageBase.tsx
@@ -21,6 +21,7 @@ type BaseLockAccountComponentProps = {
     domainAccountID?: number;
     domainName?: string;
     accountID?: number;
+    lockButtonText?: string;
 };
 function LockAccountPageBase({
     confirmModalPrompt,
@@ -31,6 +32,7 @@ function LockAccountPageBase({
     domainAccountID,
     domainName,
     accountID,
+    lockButtonText,
 }: BaseLockAccountComponentProps) {
     const {translate} = useLocalize();
     const styles = useThemeStyles();
@@ -72,7 +74,7 @@ function LockAccountPageBase({
             isLoading={isLoading}
             isDisabled={isOffline}
             large
-            text={translate('lockAccountPage.reportSuspiciousActivity')}
+            text={lockButtonText ?? translate('lockAccountPage.reportSuspiciousActivity')}
             style={styles.mt6}
             pressOnEnter
             onPress={handleReportSuspiciousActivity}

From 4c9074fd742ffb986410ca35723a2e03a0bfc3fc Mon Sep 17 00:00:00 2001
From: Rushat Gabhane <rushatgabhane@gmail.com>
Date: Sat, 6 Jun 2026 02:25:48 +0200
Subject: [PATCH 160/435] fix merge

---
 src/components/DatePicker/index.tsx | 46 ++++++++++++++---------------
 1 file changed, 22 insertions(+), 24 deletions(-)

diff --git a/src/components/DatePicker/index.tsx b/src/components/DatePicker/index.tsx
index 97a719fc7716..421b321bbfbe 100644
--- a/src/components/DatePicker/index.tsx
+++ b/src/components/DatePicker/index.tsx
@@ -2,7 +2,7 @@ import {format, setYear} from 'date-fns';
 import React, {useCallback, useEffect, useMemo, useRef, useState} from 'react';
 // eslint-disable-next-line no-restricted-imports
 import {InteractionManager, View} from 'react-native';
-import type {GestureResponderEvent, TextInputKeyPressEvent} from 'react-native';
+import type {TextInputKeyPressEvent} from 'react-native';
 import TextInput from '@components/TextInput';
 import type {BaseTextInputRef} from '@components/TextInput/BaseTextInput/types';
 import useAccessibilityAnnouncement from '@hooks/useAccessibilityAnnouncement';
@@ -93,37 +93,35 @@ function DatePicker({
         [windowHeight],
     );
 
-    const showDatePickerModal = useCallback(
-        (event?: GestureResponderEvent | KeyboardEvent) => {
-            if (event && 'preventDefault' in event) {
-                event.preventDefault();
-            }
-            cancelAutoFocus();
-            // Blur the input before showing the modal, so the focus won't be returned after the modal is closed
-            textInputRef.current?.blur();
+    const showDatePickerModal = useCallback(() => {
+        cancelAutoFocus();
+        // Blur the input before showing the modal, so the focus won't be returned after the modal is closed
+        textInputRef.current?.blur();
+
+        if (!shouldDeferShowUntilPositioned) {
+            calculatePopoverPosition();
+            setIsModalVisible(true);
+            return;
+        }
 
-            if (!shouldDeferShowUntilPositioned) {
-                calculatePopoverPosition();
-                setIsModalVisible(true);
+        openIntentRef.current = true;
+        calculatePopoverPosition(() => {
+            if (!openIntentRef.current) {
                 return;
             }
-
-            openIntentRef.current = true;
-            calculatePopoverPosition(() => {
-                if (!openIntentRef.current) {
-                    return;
-                }
-                setIsModalVisible(true);
-            });
-        },
-        [shouldDeferShowUntilPositioned, calculatePopoverPosition, cancelAutoFocus],
-    );
+            setIsModalVisible(true);
+        });
+    }, [shouldDeferShowUntilPositioned, calculatePopoverPosition, cancelAutoFocus]);
 
     const closeDatePicker = useCallback(() => {
         openIntentRef.current = false;
         setIsModalVisible(false);
     }, []);
 
+    const openDatePickerOnPress = useCallback(() => {
+        showDatePickerModal();
+    }, [showDatePickerModal]);
+
     const handleInputFocus = useCallback(() => {
         if (!autoFocus || hasAutoOpenedRef.current) {
             return;
@@ -205,7 +203,7 @@ function DatePicker({
                     errorText={errorText}
                     inputStyle={styles.pointerEventsNone}
                     disabled={disabled}
-                    onPress={showDatePickerModal}
+                    onPress={openDatePickerOnPress}
                     onSubmitEditing={() => showDatePickerModal()}
                     onKeyPress={handleInputKeyPress}
                     onFocus={handleInputFocus}

From 6873001c38a24bcd76bd92cfa3c9d74ab203c38c Mon Sep 17 00:00:00 2001
From: Rushat Gabhane <rushatgabhane@gmail.com>
Date: Sat, 6 Jun 2026 03:03:22 +0200
Subject: [PATCH 161/435] do not auto open the date picker

---
 src/components/DatePicker/index.tsx | 11 +++--------
 1 file changed, 3 insertions(+), 8 deletions(-)

diff --git a/src/components/DatePicker/index.tsx b/src/components/DatePicker/index.tsx
index 421b321bbfbe..b9d2cc65e89b 100644
--- a/src/components/DatePicker/index.tsx
+++ b/src/components/DatePicker/index.tsx
@@ -119,16 +119,12 @@ function DatePicker({
     }, []);
 
     const openDatePickerOnPress = useCallback(() => {
-        showDatePickerModal();
-    }, [showDatePickerModal]);
-
-    const handleInputFocus = useCallback(() => {
-        if (!autoFocus || hasAutoOpenedRef.current) {
+        if (!shouldDeferShowUntilPositioned) {
             return;
         }
-        hasAutoOpenedRef.current = true;
         showDatePickerModal();
-    }, [autoFocus, showDatePickerModal]);
+    }, [shouldDeferShowUntilPositioned, showDatePickerModal]);
+
 
     const handleInputKeyPress = useCallback(
         (event: TextInputKeyPressEvent) => {
@@ -206,7 +202,6 @@ function DatePicker({
                     onPress={openDatePickerOnPress}
                     onSubmitEditing={() => showDatePickerModal()}
                     onKeyPress={handleInputKeyPress}
-                    onFocus={handleInputFocus}
                     textInputContainerStyles={isModalVisible ? styles.borderColorFocus : {}}
                     shouldHideClearButton={shouldHideClearButton}
                     onClearInput={handleClear}

From 1047f654ec0defbed36069909c5ca1137791a741 Mon Sep 17 00:00:00 2001
From: Rushat Gabhane <rushatgabhane@gmail.com>
Date: Sat, 6 Jun 2026 03:05:49 +0200
Subject: [PATCH 162/435] run prettier

---
 src/components/DatePicker/index.tsx | 1 -
 1 file changed, 1 deletion(-)

diff --git a/src/components/DatePicker/index.tsx b/src/components/DatePicker/index.tsx
index b9d2cc65e89b..9942447c36d7 100644
--- a/src/components/DatePicker/index.tsx
+++ b/src/components/DatePicker/index.tsx
@@ -125,7 +125,6 @@ function DatePicker({
         showDatePickerModal();
     }, [shouldDeferShowUntilPositioned, showDatePickerModal]);
 
-
     const handleInputKeyPress = useCallback(
         (event: TextInputKeyPressEvent) => {
             if (!isNumeric(event.nativeEvent.key)) {

From 84fcf674dc3d19d45874d3d4425a8971c67bee98 Mon Sep 17 00:00:00 2001
From: "Christina Dobrzynski (via MelvinBot)" <infra+melvinbot@expensify.com>
Date: Sat, 6 Jun 2026 01:06:01 +0000
Subject: [PATCH 163/435] Sync non-English translations with new
 lockAccountPage keys

Add lockMyAccount, findYourSituation, lostCardOrCharges, unauthorizedAccess,
and securityTeamFollowUp and remove the obsolete compromisedDescription and
domainAdminsDescription keys so all locales match en.ts, fixing the typecheck
and TranslateTest failures.

Co-authored-by: Christina Dobrzynski <Christinadobrzyn@users.noreply.github.com>
---
 src/languages/de.ts      | 10 +++++++---
 src/languages/es.ts      | 10 +++++++---
 src/languages/fr.ts      | 11 +++++++----
 src/languages/it.ts      | 11 +++++++----
 src/languages/ja.ts      | 10 +++++++---
 src/languages/nl.ts      | 10 +++++++---
 src/languages/pl.ts      | 10 +++++++---
 src/languages/pt-BR.ts   | 10 +++++++---
 src/languages/zh-hans.ts |  9 +++++++--
 9 files changed, 63 insertions(+), 28 deletions(-)

diff --git a/src/languages/de.ts b/src/languages/de.ts
index 32c68c42a5b1..d4ec98d71e98 100644
--- a/src/languages/de.ts
+++ b/src/languages/de.ts
@@ -2224,10 +2224,14 @@ const translations: TranslationDeepObject<typeof en> = {
     lockAccountPage: {
         reportSuspiciousActivity: 'Verdächtige Aktivität melden',
         lockAccount: 'Konto sperren',
+        lockMyAccount: 'Mein Konto sperren',
         unlockAccount: 'Konto entsperren',
-        compromisedDescription:
-            'Ist Ihnen etwas Ungewöhnliches mit Ihrem Konto aufgefallen? Wenn Sie es melden, wird Ihr Konto sofort gesperrt, neue Expensify Karte-Transaktionen werden blockiert und alle Kontenänderungen verhindert.',
-        domainAdminsDescription: 'Für Domain-Admins: Dadurch werden auch alle Aktivitäten der Expensify Karte und alle Administratoraktionen in Ihrer/Ihren Domain(s) pausiert.',
+        findYourSituation: 'Die meisten Probleme erfordern keine Kontosperrung! Finden Sie unten Ihre Situation:',
+        lostCardOrCharges:
+            '<a href="https://help.expensify.com/articles/expensify-classic/expensify-card/Dispute-Transaction">Verlorene Karte oder unbekannte Abbuchungen</a>: Stornieren Sie Ihre Karte und wenden Sie sich an Concierge, um unbekannte Transaktionen anzufechten.',
+        unauthorizedAccess:
+            '<a href="https://help.expensify.com/articles/expensify-classic/settings/Report-Suspicious-Activity">Unbefugter Kontozugriff</a>: Sperren Sie Ihr Konto unten. Dadurch werden neue Expensify Karte-Transaktionen, Kartenbestellungen und Kontenänderungen blockiert. Wenn Sie ein Domain-Admin sind, werden dadurch auch alle domänenweiten Kartenaktivitäten und Administratoraktionen pausiert.',
+        securityTeamFollowUp: 'Unser Sicherheitsteam meldet sich nach der Sperrung von <a href="mailto:risk@expensify.com">risk@expensify.com</a> bei Ihnen.',
         areYouSure: 'Möchtest du dein Expensify-Konto wirklich sperren?',
         onceLocked: 'Sobald Ihr Konto gesperrt ist, wird es eingeschränkt, bis eine Entsperrungsanfrage gestellt und eine Sicherheitsprüfung durchgeführt wurde',
         unlockTitle: 'Wir haben Ihre Anfrage erhalten',
diff --git a/src/languages/es.ts b/src/languages/es.ts
index a776b7479367..572ca5962223 100644
--- a/src/languages/es.ts
+++ b/src/languages/es.ts
@@ -2110,12 +2110,16 @@ const translations: TranslationDeepObject<typeof en> = {
     lockAccountPage: {
         reportSuspiciousActivity: 'Informar de actividad sospechosa',
         lockAccount: 'Bloquear cuenta',
+        lockMyAccount: 'Bloquear mi cuenta',
         unlockAccount: 'Desbloquear cuenta',
         unlockTitle: 'Hemos recibido tu solicitud',
         unlockDescription: 'Revisaremos la cuenta para verificar que sea seguro desbloquearla y nos comunicaremos a través de Concierge si tenemos alguna pregunta.',
-        compromisedDescription:
-            '¿Notas algo extraño en tu cuenta? Informarlo bloqueará tu cuenta de inmediato, detendrá nuevas transacciones con la Tarjeta Expensify y evitará cualquier cambio en la cuenta.',
-        domainAdminsDescription: 'Para administradores de dominio: Esto también detiene toda la actividad de la Tarjeta Expensify y las acciones administrativas en tus dominios.',
+        findYourSituation: '¡La mayoría de los problemas no requieren bloquear tu cuenta! Encuentra tu situación a continuación:',
+        lostCardOrCharges:
+            '<a href="https://help.expensify.com/articles/expensify-classic/expensify-card/Dispute-Transaction">Tarjeta perdida o cargos desconocidos</a>: Cancela tu tarjeta y contacta a Concierge para disputar transacciones desconocidas.',
+        unauthorizedAccess:
+            '<a href="https://help.expensify.com/articles/expensify-classic/settings/Report-Suspicious-Activity">Acceso no autorizado a la cuenta</a>: Bloquea tu cuenta a continuación. Esto bloquea nuevas transacciones con la Tarjeta Expensify, pedidos de tarjetas y cambios en la cuenta. Si eres administrador de dominio, esto también detiene toda la actividad de tarjetas y las acciones administrativas en todo el dominio.',
+        securityTeamFollowUp: 'Nuestro equipo de seguridad se pondrá en contacto desde <a href="mailto:risk@expensify.com">risk@expensify.com</a> después del bloqueo.',
         areYouSure: '¿Estás seguro de que deseas bloquear tu cuenta de Expensify?',
         onceLocked: 'Una vez bloqueada, tu cuenta estará restringida hasta que se solicite el desbloqueo y se realice una revisión de seguridad.',
     },
diff --git a/src/languages/fr.ts b/src/languages/fr.ts
index 7ba2b143d6e2..6fb97dc70042 100644
--- a/src/languages/fr.ts
+++ b/src/languages/fr.ts
@@ -2230,11 +2230,14 @@ const translations: TranslationDeepObject<typeof en> = {
     lockAccountPage: {
         reportSuspiciousActivity: 'Signaler une activité suspecte',
         lockAccount: 'Verrouiller le compte',
+        lockMyAccount: 'Verrouiller mon compte',
         unlockAccount: 'Déverrouiller le compte',
-        compromisedDescription:
-            'Vous remarquez quelque chose d’inhabituel sur votre compte ? Le signaler bloquera immédiatement votre compte, empêchera les nouvelles transactions avec la Carte Expensify et interdira toute modification du compte.',
-        domainAdminsDescription:
-            "Pour les administrateurs de domaine : cela met également en pause toute l'activité de Carte Expensify et toutes les actions d'administration sur l’ensemble de votre (vos) domaine(s).",
+        findYourSituation: 'La plupart des problèmes ne nécessitent pas de verrouiller votre compte ! Trouvez votre situation ci-dessous :',
+        lostCardOrCharges:
+            '<a href="https://help.expensify.com/articles/expensify-classic/expensify-card/Dispute-Transaction">Carte perdue ou frais inconnus</a> : Annulez votre carte et contactez Concierge pour contester les transactions inconnues.',
+        unauthorizedAccess:
+            '<a href="https://help.expensify.com/articles/expensify-classic/settings/Report-Suspicious-Activity">Accès non autorisé au compte</a> : Verrouillez votre compte ci-dessous. Cela bloque les nouvelles transactions avec la Carte Expensify, les commandes de carte et les modifications du compte. Si vous êtes administrateur de domaine, cela met également en pause toute l’activité de carte et toutes les actions d’administration à l’échelle du domaine.',
+        securityTeamFollowUp: 'Notre équipe de sécurité vous contactera depuis <a href="mailto:risk@expensify.com">risk@expensify.com</a> après le verrouillage.',
         areYouSure: 'Voulez-vous vraiment verrouiller votre compte Expensify ?',
         onceLocked: 'Une fois verrouillé, votre compte sera restreint en attendant une demande de déverrouillage et un contrôle de sécurité',
         unlockTitle: 'Nous avons bien reçu votre demande',
diff --git a/src/languages/it.ts b/src/languages/it.ts
index 16c336b978b3..832122317fdc 100644
--- a/src/languages/it.ts
+++ b/src/languages/it.ts
@@ -2222,11 +2222,14 @@ const translations: TranslationDeepObject<typeof en> = {
     lockAccountPage: {
         reportSuspiciousActivity: 'Segnala attività sospetta',
         lockAccount: 'Blocca account',
+        lockMyAccount: 'Blocca il mio account',
         unlockAccount: 'Sblocca conto',
-        compromisedDescription:
-            'Hai notato qualcosa di strano nel tuo account? Segnalarlo bloccherà immediatamente il tuo account, fermerà le nuove transazioni con la Carta Expensify e impedirà qualsiasi modifica all’account.',
-        domainAdminsDescription:
-            'Per gli amministratori di dominio: questo mette in pausa anche tutta l’attività della Carta Expensify e le azioni di amministratore in tutti i tuoi domini.',
+        findYourSituation: 'La maggior parte dei problemi non richiede il blocco del tuo account! Trova la tua situazione qui sotto:',
+        lostCardOrCharges:
+            '<a href="https://help.expensify.com/articles/expensify-classic/expensify-card/Dispute-Transaction">Carta smarrita o addebiti sconosciuti</a>: Annulla la tua carta e contatta Concierge per contestare le transazioni sconosciute.',
+        unauthorizedAccess:
+            '<a href="https://help.expensify.com/articles/expensify-classic/settings/Report-Suspicious-Activity">Accesso non autorizzato all’account</a>: Blocca il tuo account qui sotto. Questo blocca le nuove transazioni con la Carta Expensify, gli ordini di carte e le modifiche all’account. Se sei un amministratore di dominio, questo mette anche in pausa tutta l’attività della carta e le azioni di amministratore in tutto il dominio.',
+        securityTeamFollowUp: 'Il nostro team di sicurezza ti contatterà da <a href="mailto:risk@expensify.com">risk@expensify.com</a> dopo il blocco.',
         areYouSure: 'Sei sicuro di voler bloccare il tuo account Expensify?',
         onceLocked: 'Una volta bloccato, il tuo account sarà limitato in attesa di una richiesta di sblocco e di una revisione di sicurezza',
         unlockTitle: 'Abbiamo ricevuto la tua richiesta',
diff --git a/src/languages/ja.ts b/src/languages/ja.ts
index 2b1a926f2547..520a4bad7003 100644
--- a/src/languages/ja.ts
+++ b/src/languages/ja.ts
@@ -2201,10 +2201,14 @@ const translations: TranslationDeepObject<typeof en> = {
     lockAccountPage: {
         reportSuspiciousActivity: '不審な行為を報告',
         lockAccount: 'アカウントをロック',
+        lockMyAccount: '自分のアカウントをロック',
         unlockAccount: 'アカウントのロック解除',
-        compromisedDescription:
-            'アカウントにおかしな点がありますか？報告すると、すぐにアカウントがロックされ、新しい Expensify カードの取引がブロックされ、アカウントの変更もできなくなります。',
-        domainAdminsDescription: 'ドメイン管理者向け：これにより、ドメイン全体のすべての Expensify カードの利用と管理者による操作も一時停止されます。',
+        findYourSituation: 'ほとんどの問題はアカウントのロックを必要としません。以下からご自身の状況を見つけてください：',
+        lostCardOrCharges:
+            '<a href="https://help.expensify.com/articles/expensify-classic/expensify-card/Dispute-Transaction">カードの紛失または不明な請求</a>：カードをキャンセルし、Conciergeに連絡して不明な取引に異議を申し立ててください。',
+        unauthorizedAccess:
+            '<a href="https://help.expensify.com/articles/expensify-classic/settings/Report-Suspicious-Activity">アカウントへの不正アクセス</a>：以下からアカウントをロックしてください。これにより、新しい Expensify カードの取引、カードの注文、アカウントの変更がブロックされます。ドメイン管理者の場合、ドメイン全体のすべてのカード利用と管理者による操作も一時停止されます。',
+        securityTeamFollowUp: '当社のセキュリティチームがロック後に <a href="mailto:risk@expensify.com">risk@expensify.com</a> からご連絡します。',
         areYouSure: 'Expensify アカウントをロックしてもよろしいですか？',
         onceLocked: 'ロックされると、解除リクエストとセキュリティ審査が完了するまでアカウントは制限されます',
         unlockTitle: 'リクエストを受け付けました',
diff --git a/src/languages/nl.ts b/src/languages/nl.ts
index 58c0c33708d9..5f6f10a0f56f 100644
--- a/src/languages/nl.ts
+++ b/src/languages/nl.ts
@@ -2218,10 +2218,14 @@ const translations: TranslationDeepObject<typeof en> = {
     lockAccountPage: {
         reportSuspiciousActivity: 'Verdachte activiteit melden',
         lockAccount: 'Account vergrendelen',
+        lockMyAccount: 'Mijn account vergrendelen',
         unlockAccount: 'Account ontgrendelen',
-        compromisedDescription:
-            'Val je iets op aan je account? Als je dit meldt, wordt je account onmiddellijk vergrendeld, worden nieuwe Expensify Kaart-transacties geblokkeerd en worden wijzigingen aan je account voorkomen.',
-        domainAdminsDescription: 'Voor domeinbeheerders: dit pauzeert ook alle Expensify Kaart-activiteit en beheerdersacties in je domein(en).',
+        findYourSituation: 'De meeste problemen vereisen geen vergrendeling van je account! Vind hieronder jouw situatie:',
+        lostCardOrCharges:
+            '<a href="https://help.expensify.com/articles/expensify-classic/expensify-card/Dispute-Transaction">Verloren kaart of onbekende kosten</a>: Annuleer je kaart en neem contact op met Concierge om onbekende transacties te betwisten.',
+        unauthorizedAccess:
+            '<a href="https://help.expensify.com/articles/expensify-classic/settings/Report-Suspicious-Activity">Ongeautoriseerde accounttoegang</a>: Vergrendel hieronder je account. Dit blokkeert nieuwe Expensify Kaart-transacties, kaartbestellingen en accountwijzigingen. Als je een domeinbeheerder bent, pauzeert dit ook alle Expensify Kaart-activiteit en beheerdersacties in je hele domein.',
+        securityTeamFollowUp: 'Ons beveiligingsteam neemt na het vergrendelen contact op via <a href="mailto:risk@expensify.com">risk@expensify.com</a>.',
         areYouSure: 'Weet je zeker dat je je Expensify-account wilt vergrendelen?',
         onceLocked: 'Zodra deze wordt vergrendeld, wordt je account beperkt in afwachting van een deblokkeringsverzoek en een beveiligingscontrole',
         unlockTitle: 'We hebben je verzoek ontvangen',
diff --git a/src/languages/pl.ts b/src/languages/pl.ts
index ae2c2b5fa0a2..55b7d9d54a80 100644
--- a/src/languages/pl.ts
+++ b/src/languages/pl.ts
@@ -2218,10 +2218,14 @@ const translations: TranslationDeepObject<typeof en> = {
     lockAccountPage: {
         reportSuspiciousActivity: 'Zgłoś podejrzaną aktywność',
         lockAccount: 'Zablokuj konto',
+        lockMyAccount: 'Zablokuj moje konto',
         unlockAccount: 'Odblokuj konto',
-        compromisedDescription:
-            'Zauważyłeś coś niepokojącego na swoim koncie? Zgłoszenie tego natychmiast zablokuje twoje konto, wstrzyma nowe transakcje Kartą Expensify i uniemożliwi wprowadzanie jakichkolwiek zmian na koncie.',
-        domainAdminsDescription: 'Dla administratorów domen: to również wstrzymuje całą aktywność Kart Expensify i działania administracyjne w twoich domenach.',
+        findYourSituation: 'Większość problemów nie wymaga blokowania konta! Znajdź swoją sytuację poniżej:',
+        lostCardOrCharges:
+            '<a href="https://help.expensify.com/articles/expensify-classic/expensify-card/Dispute-Transaction">Zgubiona karta lub nieznane obciążenia</a>: Anuluj swoją kartę i skontaktuj się z Concierge, aby zakwestionować nieznane transakcje.',
+        unauthorizedAccess:
+            '<a href="https://help.expensify.com/articles/expensify-classic/settings/Report-Suspicious-Activity">Nieautoryzowany dostęp do konta</a>: Zablokuj swoje konto poniżej. Blokuje to nowe transakcje Kartą Expensify, zamówienia kart i zmiany na koncie. Jeśli jesteś administratorem domeny, wstrzymuje to również całą aktywność kart i działania administracyjne w całej domenie.',
+        securityTeamFollowUp: 'Nasz zespół ds. bezpieczeństwa skontaktuje się po zablokowaniu z adresu <a href="mailto:risk@expensify.com">risk@expensify.com</a>.',
         areYouSure: 'Czy na pewno chcesz zablokować swoje konto Expensify?',
         onceLocked: 'Po zablokowaniu Twoje konto będzie ograniczone do czasu złożenia prośby o odblokowanie i przeprowadzenia kontroli bezpieczeństwa',
         unlockTitle: 'Otrzymaliśmy Twoją prośbę',
diff --git a/src/languages/pt-BR.ts b/src/languages/pt-BR.ts
index de0e271772de..7c283cdc84ce 100644
--- a/src/languages/pt-BR.ts
+++ b/src/languages/pt-BR.ts
@@ -2215,10 +2215,14 @@ const translations: TranslationDeepObject<typeof en> = {
     lockAccountPage: {
         reportSuspiciousActivity: 'Denunciar atividade suspeita',
         lockAccount: 'Bloquear conta',
+        lockMyAccount: 'Bloquear minha conta',
         unlockAccount: 'Desbloquear conta',
-        compromisedDescription:
-            'Percebeu algo estranho na sua conta? Ao denunciar, sua conta será imediatamente bloqueada, novas transações com o Cartão Expensify serão impedidas e qualquer alteração na conta será bloqueada.',
-        domainAdminsDescription: 'Para admins de domínio: isso também pausa todas as atividades do Cartão Expensify e ações de administração em todo(s) o(s) seu(s) domínio(s).',
+        findYourSituation: 'A maioria dos problemas não exige o bloqueio da sua conta! Encontre a sua situação abaixo:',
+        lostCardOrCharges:
+            '<a href="https://help.expensify.com/articles/expensify-classic/expensify-card/Dispute-Transaction">Cartão perdido ou cobranças desconhecidas</a>: Cancele seu cartão e entre em contato com o Concierge para contestar transações desconhecidas.',
+        unauthorizedAccess:
+            '<a href="https://help.expensify.com/articles/expensify-classic/settings/Report-Suspicious-Activity">Acesso não autorizado à conta</a>: Bloqueie sua conta abaixo. Isso impede novas transações com o Cartão Expensify, pedidos de cartão e alterações na conta. Se você for um admin de domínio, isso também pausa toda a atividade de cartão e ações de administração em todo o domínio.',
+        securityTeamFollowUp: 'Nossa equipe de segurança entrará em contato pelo <a href="mailto:risk@expensify.com">risk@expensify.com</a> após o bloqueio.',
         areYouSure: 'Tem certeza de que deseja bloquear sua conta Expensify?',
         onceLocked: 'Depois de bloqueada, sua conta ficará restrita até que seja feita uma solicitação de desbloqueio e uma revisão de segurança',
         unlockTitle: 'Recebemos sua solicitação',
diff --git a/src/languages/zh-hans.ts b/src/languages/zh-hans.ts
index 1df8087de864..91a76bddb963 100644
--- a/src/languages/zh-hans.ts
+++ b/src/languages/zh-hans.ts
@@ -2160,9 +2160,14 @@ const translations: TranslationDeepObject<typeof en> = {
     lockAccountPage: {
         reportSuspiciousActivity: '举报可疑活动',
         lockAccount: '锁定账户',
+        lockMyAccount: '锁定我的账户',
         unlockAccount: '解锁账户',
-        compromisedDescription: '发现账户有异常？提交报告后将立即锁定账户、阻止新的 Expensify 卡交易，并禁止任何账户更改。',
-        domainAdminsDescription: '针对域管理员：这也会暂停您所有域中的所有 Expensify 卡活动和管理员操作。',
+        findYourSituation: '大多数问题无需锁定账户！请在下方找到您的情况：',
+        lostCardOrCharges:
+            '<a href="https://help.expensify.com/articles/expensify-classic/expensify-card/Dispute-Transaction">卡片丢失或陌生扣款</a>：取消您的卡片并联系 Concierge 以对未知交易提出争议。',
+        unauthorizedAccess:
+            '<a href="https://help.expensify.com/articles/expensify-classic/settings/Report-Suspicious-Activity">账户未经授权的访问</a>：在下方锁定您的账户。这会阻止新的 Expensify 卡交易、卡片订购和账户更改。如果您是域管理员，这还会暂停整个域中的所有卡活动和管理员操作。',
+        securityTeamFollowUp: '我们的安全团队将在锁定后通过 <a href="mailto:risk@expensify.com">risk@expensify.com</a> 与您联系。',
         areYouSure: '你确定要锁定你的 Expensify 账户吗？',
         onceLocked: '一旦被锁定，您的账户将受到限制，直至提交解锁请求并完成安全审查',
         unlockTitle: '我们已收到您的请求',

From bfef4188e7d4fa4e47b3665e500ee6bdda88949b Mon Sep 17 00:00:00 2001
From: Rushat Gabhane <rushatgabhane@gmail.com>
Date: Sat, 6 Jun 2026 03:46:48 +0200
Subject: [PATCH 164/435] fix lint

---
 src/components/DatePicker/index.tsx | 2 --
 1 file changed, 2 deletions(-)

diff --git a/src/components/DatePicker/index.tsx b/src/components/DatePicker/index.tsx
index 9942447c36d7..b7fb711c1ed1 100644
--- a/src/components/DatePicker/index.tsx
+++ b/src/components/DatePicker/index.tsx
@@ -55,8 +55,6 @@ function DatePicker({
     // Whether the user currently intends the picker to be open. Lets a deferred measurement skip opening if the
     // picker was dismissed before it resolved.
     const openIntentRef = useRef(false);
-    // Whether the initial autoFocus has already opened the picker, so later focuses don't reopen it.
-    const hasAutoOpenedRef = useRef(false);
 
     const {inputCallbackRef: autoFocusCallbackRef, cancelAutoFocus} = useAutoFocusInput();
     const autoFocusCallbackRefRef = useRef(autoFocusCallbackRef);

From 5a7986ff407becd5441e0f164d868e0fe7eba602 Mon Sep 17 00:00:00 2001
From: Stephanie Elliott <31225194+stephanieelliott@users.noreply.github.com>
Date: Fri, 5 Jun 2026 15:48:10 -1000
Subject: [PATCH 165/435] Apply suggestions from code review

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
---
 .../connect-credit-cards/Assign-Company-Cards.md          | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/docs/articles/new-expensify/connect-credit-cards/Assign-Company-Cards.md b/docs/articles/new-expensify/connect-credit-cards/Assign-Company-Cards.md
index 95803e1f2bda..2ce67abacb34 100644
--- a/docs/articles/new-expensify/connect-credit-cards/Assign-Company-Cards.md
+++ b/docs/articles/new-expensify/connect-credit-cards/Assign-Company-Cards.md
@@ -28,15 +28,15 @@ If you haven’t set up a feed yet, learn how to set one up:
 3. Select the card connection name. 
 4. Click **Assign card** on the card you want to assign. 
 5. Enter the assignee's name, email address, or phone number. 
-7. If needed, update the **Transaction start date** to choose the date from which Expensify starts importing transactions for the card.
-8. Click **Assign card** to finalize the assignment.
+6. If needed, update the **Transaction start date** to choose the date from which Expensify starts importing transactions for the card.
+7. Click **Assign card** to finalize the assignment.
 
 ---
 
 ## What happens after you assign company cards
 
  - Posted transactions from the assigned card import automatically into the member's account as expenses.
- - Expensify imports transactions from the Transaction start date onward.
+ - Expensify imports transactions from the **Transaction start date** onward.
  - The imported company card expenses are added to reports and submitted according to Workspace rules.
 
 ---
@@ -57,4 +57,4 @@ No. Only Workspace Admins and their Copilots can assign or reassign company card
 
 ## Can I change the transaction start date on an assigned card?
 
-Yes. You can update the Transaction start date at any time from the assigned card's details. The Transaction start date determines the date from which Expensify imports transactions for the card.
+Yes. You can update the **Transaction start date** at any time from the assigned card's details. The **Transaction start date** determines the date from which Expensify imports transactions for the card.

From 1429c2778924a1b2e9aa026bf14a42d15f0f360b Mon Sep 17 00:00:00 2001
From: Stephanie Elliott <31225194+stephanieelliott@users.noreply.github.com>
Date: Fri, 5 Jun 2026 15:49:12 -1000
Subject: [PATCH 166/435] Update How-to-Export-Expenses.md

---
 .../reports-and-expenses/How-to-Export-Expenses.md              | 2 --
 1 file changed, 2 deletions(-)

diff --git a/docs/articles/new-expensify/reports-and-expenses/How-to-Export-Expenses.md b/docs/articles/new-expensify/reports-and-expenses/How-to-Export-Expenses.md
index 268ff7f1dbf8..b69b1547a41f 100644
--- a/docs/articles/new-expensify/reports-and-expenses/How-to-Export-Expenses.md
+++ b/docs/articles/new-expensify/reports-and-expenses/How-to-Export-Expenses.md
@@ -44,8 +44,6 @@ Expensify offers pre-built export templates, or you can build your own custom ex
    - **All Data - expense level** - One row per expense with all available data fields.
    - **Custom templates** - Any custom template created by you or your Workspace Admin, if available.
 
-**Note:** Currently, it's not possible to build custom export templates on New Expensify, they can only be created on Expensify Classic. However, once built they will be available on New Expensify when exporting expenses. [Learn how to build a custom export template in Expensify Classic](/articles/expensify-classic/spending-insights/Export-Expenses-And-Reports#create-a-custom-export-template).
-
 ## Where do I find the exported file?
 
 For the Basic Export template, the file downloads directly to your device. For all other templates, Concierge sends the file to you in a direct message. Open your Concierge chat in the **Inbox** to find it.

From 1449ac1a64de37ebd84b49faa4a532ab2c4cab92 Mon Sep 17 00:00:00 2001
From: Rushat Gabhane <rushatgabhane@gmail.com>
Date: Sat, 6 Jun 2026 21:57:31 +0200
Subject: [PATCH 167/435] add a11y label to step counter

---
 src/components/InteractiveStepSubHeader.tsx   | 22 +++++++++++--------
 .../InteractiveStepSubPageHeader.tsx          | 15 ++++++++++---
 src/components/InteractiveStepWrapper.tsx     |  1 +
 .../Wallet/AddBankAccount/AddBankAccount.tsx  |  1 +
 .../Wallet/VerifyIdentity/VerifyIdentity.tsx  |  1 +
 .../MissingPersonalDetailsContent.tsx         |  1 +
 .../TransactionDuplicate/ReviewFields.tsx     |  1 +
 .../certinia/CertiniaPrerequisitesPage.tsx    |  3 +++
 .../NetSuiteTokenInputPage.tsx                |  3 +++
 .../NetSuiteImportAddCustomListContent.tsx    |  3 +++
 .../NetSuiteImportAddCustomSegmentContent.tsx |  7 +++++-
 .../assignCard/CardSelectionStep.tsx          |  1 +
 .../InteractiveStepSubHeader.stories.tsx      |  2 ++
 13 files changed, 48 insertions(+), 13 deletions(-)

diff --git a/src/components/InteractiveStepSubHeader.tsx b/src/components/InteractiveStepSubHeader.tsx
index f73b17f9ba41..9afed89c7233 100644
--- a/src/components/InteractiveStepSubHeader.tsx
+++ b/src/components/InteractiveStepSubHeader.tsx
@@ -3,6 +3,7 @@ import React, {useImperativeHandle, useState} from 'react';
 import type {ViewStyle} from 'react-native';
 import {View} from 'react-native';
 import {useMemoizedLazyExpensifyIcons} from '@hooks/useLazyAsset';
+import useLocalize from '@hooks/useLocalize';
 import useThemeStyles from '@hooks/useThemeStyles';
 import colors from '@styles/theme/colors';
 import variables from '@styles/variables';
@@ -21,6 +22,9 @@ type InteractiveStepSubHeaderProps = {
     /** The index of the step to start with */
     startStepIndex?: number;
 
+    /** Description of the current step, appended to its accessibility label */
+    currentStepAccessibilityDescription: string;
+
     /** Reference to the outer element */
     ref?: ForwardedRef<InteractiveStepSubHeaderHandle>;
 };
@@ -39,8 +43,9 @@ type InteractiveStepSubHeaderHandle = {
 const MIN_AMOUNT_FOR_EXPANDING = 3;
 const MIN_AMOUNT_OF_STEPS = 2;
 
-function InteractiveStepSubHeader({stepNames, startStepIndex = 0, onStepSelected, ref}: InteractiveStepSubHeaderProps) {
+function InteractiveStepSubHeader({stepNames, startStepIndex = 0, currentStepAccessibilityDescription, onStepSelected, ref}: InteractiveStepSubHeaderProps) {
     const styles = useThemeStyles();
+    const {translate} = useLocalize();
     const containerWidthStyle: ViewStyle = stepNames.length < MIN_AMOUNT_FOR_EXPANDING ? styles.mnw60 : styles.mnw100;
 
     if (stepNames.length < MIN_AMOUNT_OF_STEPS) {
@@ -68,11 +73,7 @@ function InteractiveStepSubHeader({stepNames, startStepIndex = 0, onStepSelected
     const amountOfUnions = stepNames.length - 1;
 
     return (
-        <View
-            style={[styles.interactiveStepHeaderContainer, containerWidthStyle]}
-            accessible={false}
-            aria-hidden
-        >
+        <View style={[styles.interactiveStepHeaderContainer, containerWidthStyle]}>
             {stepNames.map((stepName, index) => {
                 const isCompletedStep = currentStep > index;
                 const isLockedStep = currentStep < index;
@@ -104,9 +105,12 @@ function InteractiveStepSubHeader({stepNames, startStepIndex = 0, onStepSelected
                             ]}
                             disabled={isLockedStep || !onStepSelected}
                             onPress={moveToStep}
-                            accessible={false}
-                            aria-hidden
-                            role={CONST.ROLE.BUTTON}
+                            role={CONST.ROLE.GROUP}
+                            accessibilityLabel={translate('stepCounter', {
+                                step: index + 1,
+                                total: stepNames.length,
+                                text: currentStep === index ? currentStepAccessibilityDescription : undefined,
+                            })}
                             sentryLabel={CONST.SENTRY_LABEL.INTERACTIVE_STEP_SUB_HEADER.STEP_BUTTON}
                         >
                             {isCompletedStep ? (
diff --git a/src/components/InteractiveStepSubPageHeader.tsx b/src/components/InteractiveStepSubPageHeader.tsx
index 66b5762490c6..0aef9f4b81a0 100644
--- a/src/components/InteractiveStepSubPageHeader.tsx
+++ b/src/components/InteractiveStepSubPageHeader.tsx
@@ -2,6 +2,7 @@ import React from 'react';
 import type {ViewStyle} from 'react-native';
 import {View} from 'react-native';
 import {useMemoizedLazyExpensifyIcons} from '@hooks/useLazyAsset';
+import useLocalize from '@hooks/useLocalize';
 import useThemeStyles from '@hooks/useThemeStyles';
 import colors from '@styles/theme/colors';
 import variables from '@styles/variables';
@@ -17,6 +18,9 @@ type InteractiveStepSubPageHeaderProps = {
     /** Current step index (0-based) */
     currentStepIndex: number;
 
+    /** Description of the current step, appended to its accessibility label */
+    currentStepAccessibilityDescription: string;
+
     /** Function to call when a step is selected */
     onStepSelected?: (stepIndex: number) => void;
 };
@@ -24,8 +28,9 @@ type InteractiveStepSubPageHeaderProps = {
 const MIN_AMOUNT_FOR_EXPANDING = 3;
 const MIN_AMOUNT_OF_STEPS = 2;
 
-function InteractiveStepSubPageHeader({stepNames, currentStepIndex, onStepSelected}: InteractiveStepSubPageHeaderProps) {
+function InteractiveStepSubPageHeader({stepNames, currentStepIndex, currentStepAccessibilityDescription, onStepSelected}: InteractiveStepSubPageHeaderProps) {
     const styles = useThemeStyles();
+    const {translate} = useLocalize();
     const icons = useMemoizedLazyExpensifyIcons(['Checkmark']);
     const containerWidthStyle: ViewStyle = stepNames.length < MIN_AMOUNT_FOR_EXPANDING ? styles.mnw60 : styles.mnw100;
 
@@ -65,8 +70,12 @@ function InteractiveStepSubPageHeader({stepNames, currentStepIndex, onStepSelect
                             disabled={isLockedStep || !onStepSelected}
                             onPress={() => handleStepPress(isLockedStep, index)}
                             accessible
-                            accessibilityLabel={stepName}
-                            role={CONST.ROLE.BUTTON}
+                            role={CONST.ROLE.GROUP}
+                            accessibilityLabel={translate('stepCounter', {
+                                step: index + 1,
+                                total: stepNames.length,
+                                text: currentStepIndex === index ? currentStepAccessibilityDescription : undefined,
+                            })}
                         >
                             {isCompletedStep ? (
                                 <Icon
diff --git a/src/components/InteractiveStepWrapper.tsx b/src/components/InteractiveStepWrapper.tsx
index 29f6b29ab722..7f4999fdc74c 100644
--- a/src/components/InteractiveStepWrapper.tsx
+++ b/src/components/InteractiveStepWrapper.tsx
@@ -116,6 +116,7 @@ function InteractiveStepWrapper({
                         <InteractiveStepSubHeader
                             startStepIndex={startStepIndex}
                             stepNames={stepNames}
+                            currentStepAccessibilityDescription={headerTitle}
                         />
                     </View>
                 )}
diff --git a/src/pages/EnablePayments/Wallet/AddBankAccount/AddBankAccount.tsx b/src/pages/EnablePayments/Wallet/AddBankAccount/AddBankAccount.tsx
index 1902739a7e43..bbdbfae6b36a 100644
--- a/src/pages/EnablePayments/Wallet/AddBankAccount/AddBankAccount.tsx
+++ b/src/pages/EnablePayments/Wallet/AddBankAccount/AddBankAccount.tsx
@@ -99,6 +99,7 @@ function AddBankAccount() {
                             <InteractiveStepSubHeader
                                 startStepIndex={0}
                                 stepNames={CONST.WALLET.STEP_NAMES}
+                                currentStepAccessibilityDescription={translate('bankAccount.addBankAccount')}
                             />
                         </View>
                         <SubStep
diff --git a/src/pages/EnablePayments/Wallet/VerifyIdentity/VerifyIdentity.tsx b/src/pages/EnablePayments/Wallet/VerifyIdentity/VerifyIdentity.tsx
index 6540e2305d2f..1fc05e15a9fe 100644
--- a/src/pages/EnablePayments/Wallet/VerifyIdentity/VerifyIdentity.tsx
+++ b/src/pages/EnablePayments/Wallet/VerifyIdentity/VerifyIdentity.tsx
@@ -63,6 +63,7 @@ function VerifyIdentity() {
                 <InteractiveStepSubHeader
                     startStepIndex={2}
                     stepNames={CONST.WALLET.STEP_NAMES}
+                    currentStepAccessibilityDescription={translate('onfidoStep.verifyIdentity')}
                 />
             </View>
             <FullPageOfflineBlockingView>
diff --git a/src/pages/MissingPersonalDetails/MissingPersonalDetailsContent.tsx b/src/pages/MissingPersonalDetails/MissingPersonalDetailsContent.tsx
index badd7d37fc67..5125a556cbfb 100644
--- a/src/pages/MissingPersonalDetails/MissingPersonalDetailsContent.tsx
+++ b/src/pages/MissingPersonalDetails/MissingPersonalDetailsContent.tsx
@@ -160,6 +160,7 @@ function MissingPersonalDetailsContent({privatePersonalDetails, draftValues, hea
                 <InteractiveStepSubPageHeader
                     stepNames={stepIndexList}
                     currentStepIndex={pageIndex}
+                    currentStepAccessibilityDescription={headerTitle ?? translate('workspace.expensifyCard.addShippingDetails')}
                     onStepSelected={moveTo}
                 />
             </View>
diff --git a/src/pages/TransactionDuplicate/ReviewFields.tsx b/src/pages/TransactionDuplicate/ReviewFields.tsx
index f59f3cc02be5..74fa180f042f 100644
--- a/src/pages/TransactionDuplicate/ReviewFields.tsx
+++ b/src/pages/TransactionDuplicate/ReviewFields.tsx
@@ -70,6 +70,7 @@ function ReviewFields<K extends keyof ReviewDuplicates>({stepNames, label, optio
                     <InteractiveStepSubHeader
                         stepNames={stepNames}
                         startStepIndex={index}
+                        currentStepAccessibilityDescription={label}
                     />
                 </View>
             )}
diff --git a/src/pages/workspace/accounting/certinia/CertiniaPrerequisitesPage.tsx b/src/pages/workspace/accounting/certinia/CertiniaPrerequisitesPage.tsx
index 25dec349ecf4..e450a9aee963 100644
--- a/src/pages/workspace/accounting/certinia/CertiniaPrerequisitesPage.tsx
+++ b/src/pages/workspace/accounting/certinia/CertiniaPrerequisitesPage.tsx
@@ -3,6 +3,7 @@ import {View} from 'react-native';
 import ConnectionLayout from '@components/ConnectionLayout';
 import InteractiveStepSubPageHeader from '@components/InteractiveStepSubPageHeader';
 import useEnvironment from '@hooks/useEnvironment';
+import useLocalize from '@hooks/useLocalize';
 import useOnyx from '@hooks/useOnyx';
 import useSubPage from '@hooks/useSubPage';
 import type {SubPageProps} from '@hooks/useSubPage/types';
@@ -32,6 +33,7 @@ const pages = [
 
 function CertiniaPrerequisitesPage({route}: CertiniaPrerequisitesPageProps) {
     const styles = useThemeStyles();
+    const {translate} = useLocalize();
     const {environmentURL} = useEnvironment();
     const policyID: string = route.params.policyID;
     const [policy] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY}${policyID}`);
@@ -76,6 +78,7 @@ function CertiniaPrerequisitesPage({route}: CertiniaPrerequisitesPageProps) {
                 <InteractiveStepSubPageHeader
                     currentStepIndex={pageIndex}
                     stepNames={CONST.CERTINIA_PREREQUISITES.STEP_INDEX_LIST}
+                    currentStepAccessibilityDescription={translate('workspace.certinia.prerequisites.title')}
                     onStepSelected={moveTo}
                 />
             </View>
diff --git a/src/pages/workspace/accounting/netsuite/NetSuiteTokenInput/NetSuiteTokenInputPage.tsx b/src/pages/workspace/accounting/netsuite/NetSuiteTokenInput/NetSuiteTokenInputPage.tsx
index d07b29ebea61..0171a70b653f 100644
--- a/src/pages/workspace/accounting/netsuite/NetSuiteTokenInput/NetSuiteTokenInputPage.tsx
+++ b/src/pages/workspace/accounting/netsuite/NetSuiteTokenInput/NetSuiteTokenInputPage.tsx
@@ -2,6 +2,7 @@ import React from 'react';
 import {View} from 'react-native';
 import ConnectionLayout from '@components/ConnectionLayout';
 import InteractiveStepSubPageHeader from '@components/InteractiveStepSubPageHeader';
+import useLocalize from '@hooks/useLocalize';
 import useSubPage from '@hooks/useSubPage';
 import useThemeStyles from '@hooks/useThemeStyles';
 import {isAuthenticationError} from '@libs/actions/connections';
@@ -26,6 +27,7 @@ const pages = [
 function NetSuiteTokenInputPage({policy, route}: WithPolicyConnectionsProps) {
     const policyID = policy?.id;
     const styles = useThemeStyles();
+    const {translate} = useLocalize();
 
     const hasAuthError = isAuthenticationError(policy, CONST.POLICY.CONNECTIONS.NAME.NETSUITE);
 
@@ -68,6 +70,7 @@ function NetSuiteTokenInputPage({policy, route}: WithPolicyConnectionsProps) {
                 <InteractiveStepSubPageHeader
                     currentStepIndex={pageIndex}
                     stepNames={CONST.NETSUITE_CONFIG.TOKEN_INPUT.STEP_INDEX_LIST}
+                    currentStepAccessibilityDescription={translate('workspace.netsuite.tokenInput.title')}
                     onStepSelected={moveTo}
                 />
             </View>
diff --git a/src/pages/workspace/accounting/netsuite/import/NetSuiteImportCustomFieldNew/NetSuiteImportAddCustomListContent.tsx b/src/pages/workspace/accounting/netsuite/import/NetSuiteImportCustomFieldNew/NetSuiteImportAddCustomListContent.tsx
index e002af31ce8e..30b43315fe9c 100644
--- a/src/pages/workspace/accounting/netsuite/import/NetSuiteImportCustomFieldNew/NetSuiteImportAddCustomListContent.tsx
+++ b/src/pages/workspace/accounting/netsuite/import/NetSuiteImportCustomFieldNew/NetSuiteImportAddCustomListContent.tsx
@@ -7,6 +7,7 @@ import type {FormRef} from '@components/Form/types';
 import FullScreenLoadingIndicator from '@components/FullscreenLoadingIndicator';
 import InteractiveStepSubPageHeader from '@components/InteractiveStepSubPageHeader';
 import ScreenWrapper from '@components/ScreenWrapper';
+import useLocalize from '@hooks/useLocalize';
 import useSubPage from '@hooks/useSubPage';
 import useThemeStyles from '@hooks/useThemeStyles';
 import Navigation from '@libs/Navigation/Navigation';
@@ -42,6 +43,7 @@ const pages = [
 function NetSuiteImportAddCustomListContent({policy, draftValues, policyIDParam}: NetSuiteImportAddCustomListContentProps) {
     const policyID = policy?.id;
     const styles = useThemeStyles();
+    const {translate} = useLocalize();
     const formRef = useRef<FormRef | null>(null);
 
     const values = useMemo(() => getSubstepValues(draftValues), [draftValues]);
@@ -132,6 +134,7 @@ function NetSuiteImportAddCustomListContent({policy, draftValues, policyIDParam}
                 <InteractiveStepSubPageHeader
                     currentStepIndex={pageIndex}
                     stepNames={CONST.NETSUITE_CONFIG.NETSUITE_ADD_CUSTOM_LIST.STEP_INDEX_LIST}
+                    currentStepAccessibilityDescription={translate('workspace.netsuite.import.importCustomFields.customLists.addText')}
                 />
             </View>
             <View style={[styles.flexGrow1, styles.mt3]}>
diff --git a/src/pages/workspace/accounting/netsuite/import/NetSuiteImportCustomFieldNew/NetSuiteImportAddCustomSegmentContent.tsx b/src/pages/workspace/accounting/netsuite/import/NetSuiteImportCustomFieldNew/NetSuiteImportAddCustomSegmentContent.tsx
index d61b5a76c244..ea27ea1c0f8d 100644
--- a/src/pages/workspace/accounting/netsuite/import/NetSuiteImportCustomFieldNew/NetSuiteImportAddCustomSegmentContent.tsx
+++ b/src/pages/workspace/accounting/netsuite/import/NetSuiteImportCustomFieldNew/NetSuiteImportAddCustomSegmentContent.tsx
@@ -8,6 +8,7 @@ import type {FormRef} from '@components/Form/types';
 import FullScreenLoadingIndicator from '@components/FullscreenLoadingIndicator';
 import InteractiveStepSubPageHeader from '@components/InteractiveStepSubPageHeader';
 import ScreenWrapper from '@components/ScreenWrapper';
+import useLocalize from '@hooks/useLocalize';
 import useSubPage from '@hooks/useSubPage';
 import useThemeStyles from '@hooks/useThemeStyles';
 import Navigation from '@libs/Navigation/Navigation';
@@ -47,6 +48,7 @@ const pages = [
 function NetSuiteImportAddCustomSegmentContent({policy, policyIDParam, draftValues}: NetSuiteImportAddCustomSegmentContentProps) {
     const policyID = policy?.id;
     const styles = useThemeStyles();
+    const {translate} = useLocalize();
     const formRef = useRef<FormRef | null>(null);
 
     const config = policy?.connections?.netsuite?.options?.config;
@@ -120,10 +122,12 @@ function NetSuiteImportAddCustomSegmentContent({policy, policyIDParam, draftValu
         );
     }
 
+    const headerTitle = `workspace.netsuite.import.importCustomFields.customSegments.${customSegmentType ? `addForm.${customSegmentType}AddTitle` : 'addText'}` as TranslationPaths;
+
     return (
         <ConnectionLayout
             displayName="NetSuiteImportAddCustomSegmentContent"
-            headerTitle={`workspace.netsuite.import.importCustomFields.customSegments.${customSegmentType ? `addForm.${customSegmentType}AddTitle` : 'addText'}` as TranslationPaths}
+            headerTitle={headerTitle}
             accessVariants={[CONST.POLICY.ACCESS_VARIANTS.ADMIN, CONST.POLICY.ACCESS_VARIANTS.CONTROL]}
             policyID={policyID}
             featureName={CONST.POLICY.MORE_FEATURES.ARE_CONNECTIONS_ENABLED}
@@ -137,6 +141,7 @@ function NetSuiteImportAddCustomSegmentContent({policy, policyIDParam, draftValu
                 <InteractiveStepSubPageHeader
                     currentStepIndex={pageIndex}
                     stepNames={CONST.NETSUITE_CONFIG.NETSUITE_ADD_CUSTOM_SEGMENT.STEP_INDEX_LIST}
+                    currentStepAccessibilityDescription={translate(headerTitle)}
                 />
             </View>
             <View style={[styles.flex1, styles.mt3]}>
diff --git a/src/pages/workspace/companyCards/assignCard/CardSelectionStep.tsx b/src/pages/workspace/companyCards/assignCard/CardSelectionStep.tsx
index 39317e2e5612..5ba0c12d26ea 100644
--- a/src/pages/workspace/companyCards/assignCard/CardSelectionStep.tsx
+++ b/src/pages/workspace/companyCards/assignCard/CardSelectionStep.tsx
@@ -142,6 +142,7 @@ function CardSelectionStep({route}: CardSelectionStepProps) {
                 <InteractiveStepSubHeader
                     startStepIndex={1}
                     stepNames={CONST.COMPANY_CARD.STEP_NAMES}
+                    currentStepAccessibilityDescription={translate('workspace.companyCards.chooseCard')}
                 />
             </View>
             <Text style={[styles.textHeadlineLineHeightXXL, styles.ph5, styles.mt3]}>{translate('workspace.companyCards.chooseCard')}</Text>
diff --git a/src/stories/InteractiveStepSubHeader.stories.tsx b/src/stories/InteractiveStepSubHeader.stories.tsx
index e3a4e9b77da4..5a9f339ee9ff 100644
--- a/src/stories/InteractiveStepSubHeader.stories.tsx
+++ b/src/stories/InteractiveStepSubHeader.stories.tsx
@@ -43,12 +43,14 @@ const Default: StoryType = Template.bind({});
 Default.args = {
     stepNames: ['Initial', 'Step 1', 'Step 2', 'Step 3'],
     startStepIndex: 1,
+    currentStepAccessibilityDescription: 'Step 1',
     onStepSelected: () => {},
 };
 
 BaseInteractiveStepSubHeader.args = {
     stepNames: ['Initial', 'Step 1', 'Step 2', 'Step 3', 'Confirmation'],
     startStepIndex: 0,
+    currentStepAccessibilityDescription: 'Initial',
     onStepSelected: () => {},
 };
 

From c045f586f3bc262add283d9996d1ea67cbe24368 Mon Sep 17 00:00:00 2001
From: ShridharGoel <35566748+ShridharGoel@users.noreply.github.com>
Date: Sun, 7 Jun 2026 03:04:45 +0530
Subject: [PATCH 168/435] Add card admin member filter

---
 src/languages/de.ts                          | 3 ++-
 src/languages/en.ts                          | 3 ++-
 src/languages/es.ts                          | 3 ++-
 src/languages/fr.ts                          | 3 ++-
 src/languages/it.ts                          | 3 ++-
 src/languages/ja.ts                          | 3 ++-
 src/languages/nl.ts                          | 3 ++-
 src/languages/pl.ts                          | 3 ++-
 src/languages/pt-BR.ts                       | 3 ++-
 src/languages/zh-hans.ts                     | 3 ++-
 src/pages/workspace/WorkspaceMembersPage.tsx | 8 ++++++++
 11 files changed, 28 insertions(+), 10 deletions(-)

diff --git a/src/languages/de.ts b/src/languages/de.ts
index fc7c9886b7bd..d89678f82ab1 100644
--- a/src/languages/de.ts
+++ b/src/languages/de.ts
@@ -6213,7 +6213,8 @@ _Für ausführlichere Anweisungen [besuchen Sie unsere Hilfeseite](${CONST.NETSU
             cannotRemoveUserDueToReport: ({memberName}: {memberName: string}) =>
                 `${memberName} hat einen ausstehenden Bericht in Bearbeitung, zu dem eine Aktion erforderlich ist. Bitte bitten Sie diese Person, die erforderliche Aktion abzuschließen, bevor Sie sie aus dem Workspace entfernen.`,
             allMembers: 'Alle Mitglieder',
-            admins: 'Admins',
+            admins: 'Workspace-Administratoren',
+            cardAdmins: 'Kartenadministratoren',
             approvers: 'Genehmigende',
             auditors: 'Prüfer',
             emptyRoleFilter: {title: 'Keine Mitglieder entsprechen diesem Filter', subtitle: 'Laden Sie ein Mitglied ein oder ändern Sie den Filter oben.'},
diff --git a/src/languages/en.ts b/src/languages/en.ts
index d3ec03c53514..1af55a34f9f5 100644
--- a/src/languages/en.ts
+++ b/src/languages/en.ts
@@ -6253,7 +6253,8 @@ const translations = {
             configureHRSync: (providerName: string) => `Configure ${providerName} sync.`,
             syncWithHR: (providerName: string) => `Sync with ${providerName}`,
             allMembers: 'All members',
-            admins: 'Admins',
+            admins: 'Workspace Admins',
+            cardAdmins: 'Card Admins',
             approvers: 'Approvers',
             auditors: 'Auditors',
             emptyRoleFilter: {
diff --git a/src/languages/es.ts b/src/languages/es.ts
index fd3b3fc61d12..a4921019cbba 100644
--- a/src/languages/es.ts
+++ b/src/languages/es.ts
@@ -6037,7 +6037,8 @@ ${amount} para ${merchant} - ${date}`,
             invitedBySecondaryLogin: (secondaryLogin) => `Agregado por nombre de usuario secundario ${secondaryLogin}.`,
             workspaceMembersCount: (count) => `Total de miembros del espacio de trabajo: ${count}`,
             allMembers: 'Todos los miembros',
-            admins: 'Administradores',
+            admins: 'Administradores del espacio de trabajo',
+            cardAdmins: 'Administradores de tarjetas',
             approvers: 'Aprobadores',
             auditors: 'Auditores',
             emptyRoleFilter: {
diff --git a/src/languages/fr.ts b/src/languages/fr.ts
index 7cb465772904..e5c31ed45109 100644
--- a/src/languages/fr.ts
+++ b/src/languages/fr.ts
@@ -6238,7 +6238,8 @@ _Pour des instructions plus détaillées, [visitez notre site d’aide](${CONST.
             cannotRemoveUserDueToReport: ({memberName}: {memberName: string}) =>
                 `${memberName} a une note de frais en cours de traitement sur laquelle il doit agir. Veuillez lui demander d’effectuer l’action requise avant de le retirer de l’espace de travail.`,
             allMembers: 'Tous les membres',
-            admins: 'Administrateurs',
+            admins: 'Administrateurs de l’espace de travail',
+            cardAdmins: 'Administrateurs de cartes',
             approvers: 'Approbateurs',
             auditors: 'Auditeurs',
             emptyRoleFilter: {title: 'Aucun membre ne correspond à ce filtre', subtitle: 'Invitez un membre ou modifiez le filtre ci-dessus.'},
diff --git a/src/languages/it.ts b/src/languages/it.ts
index 546421749bda..1b21fe81b9e7 100644
--- a/src/languages/it.ts
+++ b/src/languages/it.ts
@@ -6201,7 +6201,8 @@ _Per istruzioni più dettagliate, [visita il nostro sito di assistenza](${CONST.
             cannotRemoveUserDueToReport: ({memberName}: {memberName: string}) =>
                 `${memberName} ha un rapporto in sospeso su cui deve intervenire. Chiedi loro di completare l’azione richiesta prima di rimuoverlə dallo spazio di lavoro.`,
             allMembers: 'Tutti i membri',
-            admins: 'Amministratori',
+            admins: 'Amministratori workspace',
+            cardAdmins: 'Amministratori carte',
             approvers: 'Approvatori',
             auditors: 'Revisori',
             emptyRoleFilter: {title: 'Nessun membro corrisponde a questo filtro', subtitle: 'Invita un membro o modifica il filtro qui sopra.'},
diff --git a/src/languages/ja.ts b/src/languages/ja.ts
index d097b5f60fc4..45dcd7cba9eb 100644
--- a/src/languages/ja.ts
+++ b/src/languages/ja.ts
@@ -6128,7 +6128,8 @@ _詳しい手順については、[ヘルプサイトをご覧ください](${CO
             cannotRemoveUserDueToReport: ({memberName}: {memberName: string}) =>
                 `${memberName} は、対応が必要な未処理のレポートがあります。ワークスペースから削除する前に、必要な対応を完了するよう依頼してください。`,
             allMembers: 'すべてのメンバー',
-            admins: '管理者',
+            admins: 'ワークスペース管理者',
+            cardAdmins: 'カード管理者',
             approvers: '承認者',
             auditors: '監査担当者',
             emptyRoleFilter: {title: 'このフィルターに一致するメンバーはいません', subtitle: 'メンバーを招待するか、上のフィルターを変更してください。'},
diff --git a/src/languages/nl.ts b/src/languages/nl.ts
index ac1bbdf9d83f..9556676643c2 100644
--- a/src/languages/nl.ts
+++ b/src/languages/nl.ts
@@ -6180,7 +6180,8 @@ _Voor meer gedetailleerde instructies, [bezoek onze help-site](${CONST.NETSUITE_
             cannotRemoveUserDueToReport: ({memberName}: {memberName: string}) =>
                 `${memberName} heeft een openstaand rapport in verwerking waarop actie moet worden ondernomen. Vraag hen dit vereiste actiepunt af te ronden voordat je hen uit de workspace verwijdert.`,
             allMembers: 'Alle leden',
-            admins: 'Beheerders',
+            admins: 'Werkruimtebeheerders',
+            cardAdmins: 'Kaartbeheerders',
             approvers: 'Fiatteurs',
             auditors: 'Accountants',
             emptyRoleFilter: {title: 'Geen leden komen overeen met dit filter', subtitle: 'Nodig een lid uit of wijzig het filter hierboven.'},
diff --git a/src/languages/pl.ts b/src/languages/pl.ts
index b74aca62d868..770cc9193ca7 100644
--- a/src/languages/pl.ts
+++ b/src/languages/pl.ts
@@ -6175,7 +6175,8 @@ _Aby uzyskać bardziej szczegółowe instrukcje, [odwiedź naszą stronę pomocy
             cannotRemoveUserDueToReport: ({memberName}: {memberName: string}) =>
                 `${memberName} ma nierozliczony raport w trakcie przetwarzania, który wymaga działania. Poproś tę osobę o wykonanie wymaganej czynności przed jej usunięciem z przestrzeni roboczej.`,
             allMembers: 'Wszyscy członkowie',
-            admins: 'Administratorzy',
+            admins: 'Administratorzy obszaru roboczego',
+            cardAdmins: 'Administratorzy kart',
             approvers: 'Osoby zatwierdzające',
             auditors: 'Audytorzy',
             emptyRoleFilter: {title: 'Żadni członkowie nie pasują do tego filtra', subtitle: 'Zaproś członka lub zmień filtr powyżej.'},
diff --git a/src/languages/pt-BR.ts b/src/languages/pt-BR.ts
index a42acd5d15ab..606a7af69233 100644
--- a/src/languages/pt-BR.ts
+++ b/src/languages/pt-BR.ts
@@ -6179,7 +6179,8 @@ _Para instruções mais detalhadas, [visite nossa central de ajuda](${CONST.NETS
             cannotRemoveUserDueToReport: ({memberName}: {memberName: string}) =>
                 `${memberName} tem um relatório pendente de processamento que requer ação. Peça para que concluam a ação necessária antes de removê-los do workspace.`,
             allMembers: 'Todos os membros',
-            admins: 'Administradores',
+            admins: 'Administradores do workspace',
+            cardAdmins: 'Administradores de cartões',
             approvers: 'Aprovadores',
             auditors: 'Auditores',
             emptyRoleFilter: {title: 'Nenhum membro corresponde a este filtro', subtitle: 'Convide um membro ou altere o filtro acima.'},
diff --git a/src/languages/zh-hans.ts b/src/languages/zh-hans.ts
index 5a147cf5d8bf..25860e592e21 100644
--- a/src/languages/zh-hans.ts
+++ b/src/languages/zh-hans.ts
@@ -6016,7 +6016,8 @@ _如需更详细的说明，请[访问我们的帮助网站](${CONST.NETSUITE_IM
                 `如果您将 ${memberName} 从此工作区中移除，我们会将其技术联系人替换为工作区所有者 ${workspaceOwner}。`,
             cannotRemoveUserDueToReport: ({memberName}: {memberName: string}) => `${memberName} 还有一份待处理报告需要处理。请在将其从工作区中移除之前，先让 TA 完成所需操作。`,
             allMembers: '所有成员',
-            admins: '管理员',
+            admins: '工作区管理员',
+            cardAdmins: '卡管理员',
             approvers: '审批人',
             auditors: '审计员',
             emptyRoleFilter: {title: '没有成员符合此筛选条件', subtitle: '邀请成员或更改上方的筛选条件。'},
diff --git a/src/pages/workspace/WorkspaceMembersPage.tsx b/src/pages/workspace/WorkspaceMembersPage.tsx
index dacdf88c6499..81949b98aebd 100644
--- a/src/pages/workspace/WorkspaceMembersPage.tsx
+++ b/src/pages/workspace/WorkspaceMembersPage.tsx
@@ -115,6 +115,7 @@ type MemberOption = Omit<ListItem, 'accountID' | 'login'> & {
 const WORKSPACE_MEMBER_FILTER_VALUES = {
     ALL: 'all',
     ADMINS: 'admins',
+    CARD_ADMINS: 'cardAdmins',
     APPROVERS: 'approvers',
     AUDITORS: 'auditors',
 } as const;
@@ -563,6 +564,11 @@ function WorkspaceMembersPage({personalDetails, route, policy}: WorkspaceMembers
     ];
 
     if (isControlPolicy(policy)) {
+        roleFilterOptions.push({
+            text: translate('workspace.people.cardAdmins'),
+            value: WORKSPACE_MEMBER_FILTER_VALUES.CARD_ADMINS,
+        });
+
         roleFilterOptions.push({
             text: translate('workspace.people.auditors'),
             value: WORKSPACE_MEMBER_FILTER_VALUES.AUDITORS,
@@ -592,6 +598,8 @@ function WorkspaceMembersPage({personalDetails, route, policy}: WorkspaceMembers
                 return member.login === policy?.owner || employee?.role === CONST.POLICY.ROLE.ADMIN;
             case WORKSPACE_MEMBER_FILTER_VALUES.APPROVERS:
                 return isPolicyApprover(policy, member.login);
+            case WORKSPACE_MEMBER_FILTER_VALUES.CARD_ADMINS:
+                return employee?.role === CONST.POLICY.ROLE.CARD_ADMIN;
             case WORKSPACE_MEMBER_FILTER_VALUES.AUDITORS:
                 return employee?.role === CONST.POLICY.ROLE.AUDITOR;
             default:

From ffa6b50d22211b4049ad8cf6e7e21b455c412d6d Mon Sep 17 00:00:00 2001
From: Alex Beaman <alexbeaman@expensify.com>
Date: Sun, 7 Jun 2026 09:02:21 -0600
Subject: [PATCH 169/435] Wire vendor row offline indicator to its own
 pendingFields key
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

The Vendor row on MoneyRequestView was bound to getPendingFieldAction('comment'),
which tracks pending edits to the transaction description (a separate top-level
field) — so the indicator was both wrong-semantics and never actually firing
(Phase 1's updateMoneyRequestVendor optimistic write didn't set pendingFields
at all).

Fix:
  - updateMoneyRequestVendor now writes pendingFields.vendor = UPDATE in the
    optimistic merge, and clears it via success + failure data. 'vendor' is
    already a valid TransactionPendingFieldsKey because Comment.vendor exists.
  - MoneyRequestView's Vendor row now reads getPendingFieldAction('vendor'),
    matching every other field row's convention.

The previous wiring would have caused false pending indicators on Vendor when
the user edited the description (and vice versa), and gave no offline feedback
on actual vendor edits.
---
 .../ReportActionItem/MoneyRequestView.tsx     |  2 +-
 src/libs/actions/IOU/UpdateMoneyRequest.ts    | 29 +++++++++++++++++--
 2 files changed, 28 insertions(+), 3 deletions(-)

diff --git a/src/components/ReportActionItem/MoneyRequestView.tsx b/src/components/ReportActionItem/MoneyRequestView.tsx
index 8dd34924676c..3d58affe6781 100644
--- a/src/components/ReportActionItem/MoneyRequestView.tsx
+++ b/src/components/ReportActionItem/MoneyRequestView.tsx
@@ -1167,7 +1167,7 @@ function MoneyRequestView({
                     </OfflineWithFeedback>
                 )}
                 {shouldShowVendor && (
-                    <OfflineWithFeedback pendingAction={getPendingFieldAction('comment')}>
+                    <OfflineWithFeedback pendingAction={getPendingFieldAction('vendor')}>
                         <MenuItemWithTopDescription
                             description={translate('common.vendor')}
                             title={transactionVendorName}
diff --git a/src/libs/actions/IOU/UpdateMoneyRequest.ts b/src/libs/actions/IOU/UpdateMoneyRequest.ts
index dca8086ca4be..b0b694be0733 100644
--- a/src/libs/actions/IOU/UpdateMoneyRequest.ts
+++ b/src/libs/actions/IOU/UpdateMoneyRequest.ts
@@ -450,11 +450,36 @@ function updateMoneyRequestVendor(transactionID: string, vendorID: string, trans
                 comment: {
                     vendor: newVendorOptimisticValue,
                 },
+                pendingFields: {
+                    vendor: CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE,
+                },
+            },
+        },
+    ];
+
+    const successData: Array<OnyxUpdate<typeof ONYXKEYS.COLLECTION.TRANSACTION | typeof ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS>> = [
+        {
+            onyxMethod: Onyx.METHOD.MERGE,
+            key: `${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}` as const,
+            value: {
+                pendingFields: {
+                    vendor: null,
+                },
             },
         },
     ];
 
-    const failureData: Array<OnyxUpdate<typeof ONYXKEYS.COLLECTION.TRANSACTION | typeof ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS>> = [];
+    const failureData: Array<OnyxUpdate<typeof ONYXKEYS.COLLECTION.TRANSACTION | typeof ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS>> = [
+        {
+            onyxMethod: Onyx.METHOD.MERGE,
+            key: `${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}` as const,
+            value: {
+                pendingFields: {
+                    vendor: null,
+                },
+            },
+        },
+    ];
 
     // Only roll back the vendor when we have a known prior snapshot. If the transaction isn't passed
     // in AND isn't cached in Onyx yet, we don't know what to restore — writing null here would silently
@@ -501,7 +526,7 @@ function updateMoneyRequestVendor(transactionID: string, vendorID: string, trans
             vendorID,
             isManuallySet: true,
         },
-        {optimisticData, failureData},
+        {optimisticData, successData, failureData},
     );
 }
 

From b4287e74bb57460dcf290946552bfcdf04eb035c Mon Sep 17 00:00:00 2001
From: Alex Beaman <alexbeaman@expensify.com>
Date: Sun, 7 Jun 2026 09:18:34 -0600
Subject: [PATCH 170/435] Extend UpdateMoneyRequestVendorTest for pendingFields
 behavior
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Two existing Phase 1 tests broke when the action started writing
pendingFields.vendor in optimistic/success/failure data — the `.find()`
calls on failureData were matching the new combined entry and hitting
assertions written for the old shape. Update them to the new shape and
add three new tests:

  - pendingFields.vendor = UPDATE in optimisticData
  - pendingFields.vendor = null in successData on server confirm
  - pendingFields.vendor = null in failureData on server reject (even
    when there's no prior vendor snapshot to roll back)

Also collapse the conditional pendingFields-clear and vendor-rollback
into a single merged failureData entry so callers see one rollback per
transaction rather than two same-key entries (cleaner intent + makes
the existing .find()-based assertions valid again).
---
 src/libs/actions/IOU/UpdateMoneyRequest.ts    | 23 +++------
 .../IOUTest/UpdateMoneyRequestVendorTest.ts   | 49 ++++++++++++++++---
 2 files changed, 51 insertions(+), 21 deletions(-)

diff --git a/src/libs/actions/IOU/UpdateMoneyRequest.ts b/src/libs/actions/IOU/UpdateMoneyRequest.ts
index b0b694be0733..7d8ff9edab13 100644
--- a/src/libs/actions/IOU/UpdateMoneyRequest.ts
+++ b/src/libs/actions/IOU/UpdateMoneyRequest.ts
@@ -469,6 +469,9 @@ function updateMoneyRequestVendor(transactionID: string, vendorID: string, trans
         },
     ];
 
+    // Only roll back the vendor when we have a known prior snapshot. If the transaction isn't passed
+    // in AND isn't cached in Onyx yet, we don't know what to restore — writing null here would silently
+    // clear a vendor we don't know about. The next server sync will reconcile.
     const failureData: Array<OnyxUpdate<typeof ONYXKEYS.COLLECTION.TRANSACTION | typeof ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS>> = [
         {
             onyxMethod: Onyx.METHOD.MERGE,
@@ -477,25 +480,15 @@ function updateMoneyRequestVendor(transactionID: string, vendorID: string, trans
                 pendingFields: {
                     vendor: null,
                 },
+                ...(resolvedTransaction && {
+                    comment: {
+                        vendor: previousVendor ?? null,
+                    },
+                }),
             },
         },
     ];
 
-    // Only roll back the vendor when we have a known prior snapshot. If the transaction isn't passed
-    // in AND isn't cached in Onyx yet, we don't know what to restore — writing null here would silently
-    // clear a vendor we don't know about. The next server sync will reconcile.
-    if (resolvedTransaction) {
-        failureData.push({
-            onyxMethod: Onyx.METHOD.MERGE,
-            key: `${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}` as const,
-            value: {
-                comment: {
-                    vendor: previousVendor ?? null,
-                },
-            },
-        });
-    }
-
     // Optimistically clear any existing inactive-vendor violation. This is the user-driven write
     // path: the vendor selector RHP only offers vendors from `getQBOVendors(policy)`, so a user
     // pick is always a valid vendor (resolving the violation); clearing the vendor likewise
diff --git a/tests/actions/IOUTest/UpdateMoneyRequestVendorTest.ts b/tests/actions/IOUTest/UpdateMoneyRequestVendorTest.ts
index 273857b89b8c..8bb237327faf 100644
--- a/tests/actions/IOUTest/UpdateMoneyRequestVendorTest.ts
+++ b/tests/actions/IOUTest/UpdateMoneyRequestVendorTest.ts
@@ -46,7 +46,11 @@ describe('updateMoneyRequestVendor', () => {
         await Onyx.clear();
     });
 
-    type OnyxDataArg = {optimisticData: Array<{key: string; value: unknown}>; failureData: Array<{key: string; value: unknown}>};
+    type OnyxDataArg = {
+        optimisticData: Array<{key: string; value: unknown}>;
+        successData: Array<{key: string; value: unknown}>;
+        failureData: Array<{key: string; value: unknown}>;
+    };
     const getOnyxDataArg = (): OnyxDataArg | undefined => {
         const firstCall = writeSpy.mock.calls.at(0) as unknown[] | undefined;
         return firstCall?.at(2) as OnyxDataArg | undefined;
@@ -110,17 +114,50 @@ describe('updateMoneyRequestVendor', () => {
         updateMoneyRequestVendor(TRANSACTION_ID, 'v-new');
 
         const onyxData = getOnyxDataArg();
-        const vendorRollback = onyxData?.failureData.find((entry) => entry.key === `${ONYXKEYS.COLLECTION.TRANSACTION}${TRANSACTION_ID}`);
-        expect(vendorRollback?.value).toEqual({comment: {vendor: previousVendor}});
+        const transactionFailure = onyxData?.failureData.find((entry) => entry.key === `${ONYXKEYS.COLLECTION.TRANSACTION}${TRANSACTION_ID}`);
+        expect(transactionFailure?.value).toEqual({
+            pendingFields: {vendor: null},
+            comment: {vendor: previousVendor},
+        });
     });
 
     it('omits vendor rollback from failureData when no prior transaction snapshot exists', async () => {
         // No transaction arg + nothing in Onyx — the prior vendor is unknown, so we must not
-        // write `vendor: null` and silently clear whatever the server actually has.
+        // write `vendor: null` and silently clear whatever the server actually has. The
+        // pendingFields-clear entry still runs (so the offline indicator clears on rejection).
+        updateMoneyRequestVendor(TRANSACTION_ID, 'v-new');
+
+        const onyxData = getOnyxDataArg();
+        const transactionFailure = onyxData?.failureData.find((entry) => entry.key === `${ONYXKEYS.COLLECTION.TRANSACTION}${TRANSACTION_ID}`);
+        expect(transactionFailure?.value).toEqual({pendingFields: {vendor: null}});
+    });
+
+    it('writes pendingFields.vendor = UPDATE in optimisticData so the offline indicator surfaces', () => {
+        updateMoneyRequestVendor(TRANSACTION_ID, 'v-new', baseTransaction);
+
+        const onyxData = getOnyxDataArg();
+        const transactionOptimistic = onyxData?.optimisticData.find((entry) => entry.key === `${ONYXKEYS.COLLECTION.TRANSACTION}${TRANSACTION_ID}`);
+        expect(transactionOptimistic?.value).toEqual({
+            comment: {vendor: {externalID: 'v-new', isManuallySet: true}},
+            pendingFields: {vendor: CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE},
+        });
+    });
+
+    it('clears pendingFields.vendor in successData when the server confirms the write', () => {
+        updateMoneyRequestVendor(TRANSACTION_ID, 'v-new', baseTransaction);
+
+        const onyxData = getOnyxDataArg();
+        const transactionSuccess = onyxData?.successData.find((entry) => entry.key === `${ONYXKEYS.COLLECTION.TRANSACTION}${TRANSACTION_ID}`);
+        expect(transactionSuccess?.value).toEqual({pendingFields: {vendor: null}});
+    });
+
+    it('clears pendingFields.vendor in failureData when the server rejects the write', () => {
+        // Even without a prior snapshot to roll the vendor itself back, the pending indicator must
+        // clear on failure — otherwise the row stays stuck in "pending" forever after a server reject.
         updateMoneyRequestVendor(TRANSACTION_ID, 'v-new');
 
         const onyxData = getOnyxDataArg();
-        const vendorRollback = onyxData?.failureData.find((entry) => entry.key === `${ONYXKEYS.COLLECTION.TRANSACTION}${TRANSACTION_ID}`);
-        expect(vendorRollback).toBeUndefined();
+        const transactionFailure = onyxData?.failureData.find((entry) => entry.key === `${ONYXKEYS.COLLECTION.TRANSACTION}${TRANSACTION_ID}`);
+        expect((transactionFailure?.value as {pendingFields?: {vendor: null | string}})?.pendingFields).toEqual({vendor: null});
     });
 });

From dc41b9c6cd1f584c0bc1f99e1b022233b7020e8f Mon Sep 17 00:00:00 2001
From: nabi-ebrahimi <nabi.zarin.work@gmail.com>
Date: Mon, 8 Jun 2026 10:07:28 +0430
Subject: [PATCH 171/435] fix: clean up tracked per diem expense after
 workspace submission

---
 .../parameters/CreatePerDiemRequestParams.ts  |  2 +
 src/libs/actions/IOU/MoneyRequestBuilder.ts   | 72 +++++++-------
 src/libs/actions/IOU/PerDiem.ts               | 53 ++++++++--
 src/libs/actions/IOU/TrackExpense.ts          | 13 +--
 .../IOU/types/TrackedExpenseSubmitParams.ts   | 10 ++
 .../step/confirmation/useExpenseSubmission.ts |  6 ++
 tests/actions/IOU/PerDiemTest.ts              | 96 +++++++++++++++++++
 7 files changed, 200 insertions(+), 52 deletions(-)
 create mode 100644 src/libs/actions/IOU/types/TrackedExpenseSubmitParams.ts

diff --git a/src/libs/API/parameters/CreatePerDiemRequestParams.ts b/src/libs/API/parameters/CreatePerDiemRequestParams.ts
index 77d8aaafc06a..7b41b4909e51 100644
--- a/src/libs/API/parameters/CreatePerDiemRequestParams.ts
+++ b/src/libs/API/parameters/CreatePerDiemRequestParams.ts
@@ -17,6 +17,8 @@ type CreatePerDiemRequestParams = {
     reportActionID: string;
     createdChatReportActionID?: string;
     createdIOUReportActionID?: string;
+    actionableWhisperReportActionID?: string;
+    modifiedExpenseReportActionID?: string;
     reportPreviewReportActionID: string;
     transactionThreadReportID?: string;
     createdReportActionIDForThread: string | undefined;
diff --git a/src/libs/actions/IOU/MoneyRequestBuilder.ts b/src/libs/actions/IOU/MoneyRequestBuilder.ts
index 5def3efdfd77..8de4874841aa 100644
--- a/src/libs/actions/IOU/MoneyRequestBuilder.ts
+++ b/src/libs/actions/IOU/MoneyRequestBuilder.ts
@@ -71,6 +71,7 @@ import type BasePolicyParams from './types/BasePolicyParams';
 import type BaseTransactionParams from './types/BaseTransactionParams';
 import type {CreateTrackExpenseParams} from './types/CreateTrackExpenseParams';
 import type RequestMoneyParticipantParams from './types/RequestMoneyParticipantParams';
+import type TrackedExpenseSubmitParams from './types/TrackedExpenseSubmitParams';
 import type {GPSPoint} from './types/TrackExpenseTransactionParams';
 
 type OneOnOneIOUReport = OnyxTypes.Report | undefined | null;
@@ -110,43 +111,40 @@ type MoneyRequestInformation = {
     reimbursable?: boolean;
 };
 
-type RequestMoneyTransactionParams = Omit<BaseTransactionParams, 'comment'> & {
-    attendees?: Attendee[];
-    actionableWhisperReportActionID?: string;
-    linkedTrackedExpenseReportAction?: OnyxTypes.ReportAction;
-    linkedTrackedExpenseReportID?: string;
-    receipt?: Receipt;
-    waypoints?: WaypointCollection;
-    comment?: string;
-    originalTransactionID?: string;
-    isTestDrive?: boolean;
-    source?: string;
-    pendingAction?: PendingAction;
-    pendingFields?: PendingFields<string>;
-    distance?: number;
-    isLinkedTrackedExpenseReportArchived?: boolean;
-    customUnit?: TransactionCustomUnit;
-    odometerStart?: number;
-    odometerEnd?: number;
-
-    /** Transaction type (e.g., 'time' for time tracking expenses) */
-    type?: ValueOf<typeof CONST.TRANSACTION.TYPE>;
-
-    /** Number of hours for time tracking expenses */
-    count?: number;
-
-    /** Hourly rate in cents. Use convertToBackendAmount() to convert from policy rate (which is stored as a float) */
-    rate?: number;
-
-    /** Unit for time tracking (e.g., 'h' for hours) */
-    unit?: ValueOf<typeof CONST.TIME_TRACKING.UNIT>;
-
-    /** Whether this is a selfDM split transaction */
-    isSelfDMSplit?: boolean;
-
-    /** The selfDM report ID for split transactions */
-    selfDMReportID?: string;
-};
+type RequestMoneyTransactionParams = Omit<BaseTransactionParams, 'comment'> &
+    TrackedExpenseSubmitParams & {
+        attendees?: Attendee[];
+        receipt?: Receipt;
+        waypoints?: WaypointCollection;
+        comment?: string;
+        originalTransactionID?: string;
+        isTestDrive?: boolean;
+        source?: string;
+        pendingAction?: PendingAction;
+        pendingFields?: PendingFields<string>;
+        distance?: number;
+        customUnit?: TransactionCustomUnit;
+        odometerStart?: number;
+        odometerEnd?: number;
+
+        /** Transaction type (e.g., 'time' for time tracking expenses) */
+        type?: ValueOf<typeof CONST.TRANSACTION.TYPE>;
+
+        /** Number of hours for time tracking expenses */
+        count?: number;
+
+        /** Hourly rate in cents. Use convertToBackendAmount() to convert from policy rate (which is stored as a float) */
+        rate?: number;
+
+        /** Unit for time tracking (e.g., 'h' for hours) */
+        unit?: ValueOf<typeof CONST.TIME_TRACKING.UNIT>;
+
+        /** Whether this is a selfDM split transaction */
+        isSelfDMSplit?: boolean;
+
+        /** The selfDM report ID for split transactions */
+        selfDMReportID?: string;
+    };
 
 type RequestMoneyInformation = {
     report: OnyxEntry<OnyxTypes.Report>;
diff --git a/src/libs/actions/IOU/PerDiem.ts b/src/libs/actions/IOU/PerDiem.ts
index 91dd7c02e70e..87a107649857 100644
--- a/src/libs/actions/IOU/PerDiem.ts
+++ b/src/libs/actions/IOU/PerDiem.ts
@@ -9,7 +9,7 @@ import {convertAmountToDisplayString, convertToFrontendAmountAsString} from '@li
 import DateUtils from '@libs/DateUtils';
 import {deferOrExecuteWrite} from '@libs/deferredLayoutWrite';
 import {getMicroSecondOnyxErrorWithTranslationKey} from '@libs/ErrorUtils';
-import {updateIOUOwnerAndTotal} from '@libs/IOUUtils';
+import {getExistingTransactionID, updateIOUOwnerAndTotal} from '@libs/IOUUtils';
 import {formatPhoneNumber} from '@libs/LocalePhoneNumber';
 import {validateAmount} from '@libs/MoneyRequestUtils';
 import Navigation from '@libs/Navigation/Navigation';
@@ -58,9 +58,11 @@ import {
 } from './MoneyRequestBuilder';
 import type {MoneyRequestInformation} from './MoneyRequestBuilder';
 import {highlightTransactionOnSearchRouteIfNeeded} from './NavigationHelpers';
+import {getMoveTrackedExpenseInformation} from './TrackExpense';
 import type BasePolicyParams from './types/BasePolicyParams';
 import type BaseTransactionParams from './types/BaseTransactionParams';
 import type RequestMoneyParticipantParams from './types/RequestMoneyParticipantParams';
+import type TrackedExpenseSubmitParams from './types/TrackedExpenseSubmitParams';
 
 function removeSubrate(transaction: OnyxEntry<OnyxTypes.Transaction>, currentIndex: string) {
     // Index comes from the route params and is a string
@@ -202,11 +204,12 @@ function computeDefaultPerDiemExpenseComment(customUnit: TransactionCustomUnit,
     return subRateComments.join(', ');
 }
 
-type PerDiemExpenseTransactionParams = Omit<BaseTransactionParams, 'amount' | 'merchant' | 'customUnitRateID' | 'taxAmount' | 'taxCode' | 'comment'> & {
-    attendees?: Attendee[];
-    customUnit: TransactionCustomUnit;
-    comment?: string;
-};
+type PerDiemExpenseTransactionParams = Omit<BaseTransactionParams, 'amount' | 'merchant' | 'customUnitRateID' | 'taxAmount' | 'taxCode' | 'comment'> &
+    TrackedExpenseSubmitParams & {
+        attendees?: Attendee[];
+        customUnit: TransactionCustomUnit;
+        comment?: string;
+    };
 
 type RecentlyUsedParams = {
     destinations?: OnyxEntry<OnyxTypes.RecentlyUsedCategories>;
@@ -925,7 +928,20 @@ function submitPerDiemExpense(submitPerDiemExpenseInformation: PerDiemExpenseInf
         optimisticTransactionID,
         delegateAccountID,
     } = submitPerDiemExpenseInformation;
-    const {currency, comment = '', category, tag, created, customUnit, attendees, isFromGlobalCreate} = transactionParams;
+    const {
+        currency,
+        comment = '',
+        category,
+        tag,
+        created,
+        customUnit,
+        attendees,
+        isFromGlobalCreate,
+        actionableWhisperReportActionID,
+        linkedTrackedExpenseReportAction,
+        linkedTrackedExpenseReportID,
+        isLinkedTrackedExpenseReportArchived,
+    } = transactionParams;
 
     if (
         isEmptyObject(policyParams.policy) ||
@@ -988,6 +1004,27 @@ function submitPerDiemExpense(submitPerDiemExpenseInformation: PerDiemExpenseInf
         name: customUnitRate?.name,
     };
 
+    let modifiedExpenseReportActionID: string | undefined;
+    const sourceTransactionID = getExistingTransactionID(linkedTrackedExpenseReportAction);
+
+    if (sourceTransactionID && linkedTrackedExpenseReportAction && linkedTrackedExpenseReportID) {
+        const moveTrackedExpenseInformation = getMoveTrackedExpenseInformation(
+            sourceTransactionID,
+            actionableWhisperReportActionID,
+            linkedTrackedExpenseReportAction,
+            linkedTrackedExpenseReportID,
+            transactionThreadReportID,
+            CONST.IOU.ACTION.SUBMIT,
+            isLinkedTrackedExpenseReportArchived,
+            currentUserAccountIDParam,
+        );
+
+        onyxData.optimisticData?.push(...moveTrackedExpenseInformation.optimisticData);
+        onyxData.successData?.push(...moveTrackedExpenseInformation.successData);
+        onyxData.failureData?.push(...moveTrackedExpenseInformation.failureData);
+        modifiedExpenseReportActionID = moveTrackedExpenseInformation.modifiedExpenseReportActionID;
+    }
+
     const parameters: CreatePerDiemRequestParams = {
         policyID: policyParams.policy.id,
         customUnitID: customUnit.customUnitID,
@@ -1005,6 +1042,8 @@ function submitPerDiemExpense(submitPerDiemExpenseInformation: PerDiemExpenseInf
         reportActionID: iouAction.reportActionID,
         createdChatReportActionID,
         createdIOUReportActionID,
+        actionableWhisperReportActionID,
+        modifiedExpenseReportActionID,
         reportPreviewReportActionID: reportPreviewAction.reportActionID,
         category,
         tag,
diff --git a/src/libs/actions/IOU/TrackExpense.ts b/src/libs/actions/IOU/TrackExpense.ts
index f54ee23eb594..b9815e27221a 100644
--- a/src/libs/actions/IOU/TrackExpense.ts
+++ b/src/libs/actions/IOU/TrackExpense.ts
@@ -1164,10 +1164,9 @@ function getTrackExpenseInformation(params: GetTrackExpenseInformationParams): T
     };
 }
 
-const getConvertTrackedExpenseInformation = (
+const getMoveTrackedExpenseInformation = (
     transactionID: string | undefined,
     actionableWhisperReportActionID: string | undefined,
-    moneyRequestReportID: string | undefined,
     linkedTrackedExpenseReportAction: OnyxTypes.ReportAction,
     linkedTrackedExpenseReportID: string,
     transactionThreadReportID: string | undefined,
@@ -1472,10 +1471,9 @@ function convertTrackedExpenseToRequest(convertTrackedExpenseParams: ConvertTrac
     successData?.push(...(onyxData.successData ?? []));
     failureData?.push(...(onyxData.failureData ?? []));
 
-    const convertTrackedExpenseInformation = getConvertTrackedExpenseInformation(
+    const convertTrackedExpenseInformation = getMoveTrackedExpenseInformation(
         transactionID,
         actionableWhisperReportActionID,
-        iouParams.reportID,
         linkedTrackedExpenseReportAction,
         linkedTrackedExpenseReportID,
         transactionThreadReportID,
@@ -2116,10 +2114,9 @@ function categorizeTrackedExpense(trackedExpenseParams: TrackedExpenseParams) {
         successData: moveTransactionSuccessData,
         failureData: moveTransactionFailureData,
         modifiedExpenseReportActionID,
-    } = getConvertTrackedExpenseInformation(
+    } = getMoveTrackedExpenseInformation(
         transactionID,
         actionableWhisperReportActionID,
-        moneyRequestReportID,
         linkedTrackedExpenseReportAction,
         linkedTrackedExpenseReportID,
         transactionThreadReportID,
@@ -2210,10 +2207,9 @@ function shareTrackedExpense(trackedExpenseParams: TrackedExpenseParams) {
         isLinkedTrackedExpenseReportArchived,
     } = reportInformation;
 
-    const convertTrackedExpenseInformation = getConvertTrackedExpenseInformation(
+    const convertTrackedExpenseInformation = getMoveTrackedExpenseInformation(
         transactionID,
         actionableWhisperReportActionID,
-        moneyRequestReportID,
         linkedTrackedExpenseReportAction,
         linkedTrackedExpenseReportID,
         transactionThreadReportID,
@@ -2829,6 +2825,7 @@ export {
     convertBulkTrackedExpensesToIOU,
     deleteTrackExpense,
     getDeleteTrackExpenseInformation,
+    getMoveTrackedExpenseInformation,
     getNavigationUrlAfterTrackExpenseDelete,
     getTrackExpenseInformation,
     hasManualDistanceOverride,
diff --git a/src/libs/actions/IOU/types/TrackedExpenseSubmitParams.ts b/src/libs/actions/IOU/types/TrackedExpenseSubmitParams.ts
new file mode 100644
index 000000000000..b15fd14f8f1b
--- /dev/null
+++ b/src/libs/actions/IOU/types/TrackedExpenseSubmitParams.ts
@@ -0,0 +1,10 @@
+import type * as OnyxTypes from '@src/types/onyx';
+
+type TrackedExpenseSubmitParams = {
+    actionableWhisperReportActionID?: string;
+    linkedTrackedExpenseReportAction?: OnyxTypes.ReportAction;
+    linkedTrackedExpenseReportID?: string;
+    isLinkedTrackedExpenseReportArchived?: boolean;
+};
+
+export default TrackedExpenseSubmitParams;
diff --git a/src/pages/iou/request/step/confirmation/useExpenseSubmission.ts b/src/pages/iou/request/step/confirmation/useExpenseSubmission.ts
index d6cd49ee0512..c1b60d2dec03 100644
--- a/src/pages/iou/request/step/confirmation/useExpenseSubmission.ts
+++ b/src/pages/iou/request/step/confirmation/useExpenseSubmission.ts
@@ -547,6 +547,8 @@ function useExpenseSubmission(params: UseExpenseSubmissionParams) {
                 existingChatReport,
             );
             const activeReportID = isExpenseReport && Navigation.getTopmostReportId() === report?.reportID ? report?.reportID : chatReportID;
+            const isLinkedTrackedExpenseReportArchived =
+                !!transaction.linkedTrackedExpenseReportID && privateIsArchivedMap[`${ONYXKEYS.COLLECTION.REPORT_NAME_VALUE_PAIRS}${transaction.linkedTrackedExpenseReportID}`];
 
             const result = submitPerDiemExpenseIOUActions({
                 report,
@@ -575,6 +577,10 @@ function useExpenseSubmission(params: UseExpenseSubmissionParams) {
                     billable: transaction.billable,
                     reimbursable: transaction.reimbursable,
                     attendees: transaction.comment?.attendees,
+                    actionableWhisperReportActionID: transaction.actionableWhisperReportActionID,
+                    linkedTrackedExpenseReportAction: transaction.linkedTrackedExpenseReportAction,
+                    linkedTrackedExpenseReportID: transaction.linkedTrackedExpenseReportID,
+                    isLinkedTrackedExpenseReportArchived,
                     isFromGlobalCreate: getIsFromGlobalCreate(transaction),
                 },
                 isASAPSubmitBetaEnabled,
diff --git a/tests/actions/IOU/PerDiemTest.ts b/tests/actions/IOU/PerDiemTest.ts
index e386d908e895..b0ad2860c348 100644
--- a/tests/actions/IOU/PerDiemTest.ts
+++ b/tests/actions/IOU/PerDiemTest.ts
@@ -3,11 +3,15 @@ import type {OnyxCollection, OnyxEntry} from 'react-native-onyx';
 import type {PerDiemExpenseTransactionParams} from '@libs/actions/IOU/PerDiem';
 import {addSubrate, clearSubrates, computePerDiemExpenseAmount, getPerDiemExpenseInformation, removeSubrate, submitPerDiemExpense, updateSubrate} from '@libs/actions/IOU/PerDiem';
 import type RequestMoneyParticipantParams from '@libs/actions/IOU/types/RequestMoneyParticipantParams';
+import * as API from '@libs/API';
+import type {CreatePerDiemRequestParams} from '@libs/API/parameters';
+import {WRITE_COMMANDS} from '@libs/API/types';
 import CONST from '@src/CONST';
 import DateUtils from '@src/libs/DateUtils';
 import ONYXKEYS from '@src/ONYXKEYS';
 import type {PersonalDetailsList, RecentlyUsedTags, Report} from '@src/types/onyx';
 import type {CurrentUserPersonalDetails} from '@src/types/onyx/PersonalDetails';
+import type ReportAction from '@src/types/onyx/ReportAction';
 import type Transaction from '@src/types/onyx/Transaction';
 import type {TransactionCustomUnit} from '@src/types/onyx/Transaction';
 import createPersonalDetails from '../../utils/collections/personalDetails';
@@ -71,6 +75,10 @@ describe('PerDiem', () => {
         return Onyx.clear().then(waitForBatchedUpdates);
     });
 
+    afterEach(() => {
+        jest.restoreAllMocks();
+    });
+
     describe('computePerDiemExpenseAmount', () => {
         it('should compute total amount from subRates', () => {
             const customUnit: TransactionCustomUnit = {
@@ -651,6 +659,94 @@ describe('PerDiem', () => {
     });
 
     describe('submitPerDiemExpense', () => {
+        it('should clean up the linked tracked expense when submitting a per diem from self DM', async () => {
+            const sourceTransactionID = 'tracked-per-diem-transaction';
+            const selfDMReportID = 'self-dm-report';
+            const actionableWhisperReportActionID = 'actionable-whisper-action';
+            const linkedTrackedExpenseReportAction = {
+                actionName: CONST.REPORT.ACTIONS.TYPE.IOU,
+                reportActionID: 'tracked-per-diem-action',
+                childReportID: 'tracked-per-diem-thread',
+                created: DateUtils.getDBTime(),
+                message: [],
+                originalMessage: {
+                    IOUTransactionID: sourceTransactionID,
+                    type: CONST.IOU.REPORT_ACTION_TYPE.TRACK,
+                },
+            } as unknown as ReportAction<typeof CONST.REPORT.ACTIONS.TYPE.IOU>;
+
+            await Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT}${selfDMReportID}`, {
+                reportID: selfDMReportID,
+                type: CONST.REPORT.TYPE.CHAT,
+                chatType: CONST.REPORT.CHAT_TYPE.SELF_DM,
+            });
+            await Onyx.merge(`${ONYXKEYS.COLLECTION.TRANSACTION}${sourceTransactionID}`, {
+                transactionID: sourceTransactionID,
+                reportID: CONST.REPORT.UNREPORTED_REPORT_ID,
+            });
+            await Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${selfDMReportID}`, {
+                [linkedTrackedExpenseReportAction.reportActionID]: linkedTrackedExpenseReportAction,
+            });
+            await waitForBatchedUpdates();
+
+            const writeSpy = jest.spyOn(API, 'write').mockImplementation(jest.fn());
+
+            submitPerDiemExpense({
+                currentUserAccountIDParam: currentUserPersonalDetails.accountID,
+                currentUserEmailParam: currentUserPersonalDetails.login ?? '',
+                hasViolations: false,
+                isASAPSubmitBetaEnabled: false,
+                participantParams: {
+                    payeeEmail: currentUserPersonalDetails.login,
+                    payeeAccountID: currentUserPersonalDetails.accountID,
+                    participant: {},
+                },
+                report: {
+                    reportID: '1',
+                },
+                transactionParams: {
+                    created: DateUtils.getDBTime(),
+                    currency: CONST.CURRENCY.USD,
+                    customUnit: {
+                        customUnitID: 'A',
+                        name: CONST.CUSTOM_UNITS.NAME_PER_DIEM_INTERNATIONAL,
+                        customUnitRateID: 'B',
+                        subRates: [{id: '1', name: 'rate_a', quantity: 1, rate: 2}],
+                        attributes: {dates: {end: '', start: ''}},
+                    },
+                    actionableWhisperReportActionID,
+                    linkedTrackedExpenseReportAction,
+                    linkedTrackedExpenseReportID: selfDMReportID,
+                },
+                policyRecentlyUsedCurrencies: [],
+                policyParams: {
+                    policy: {...createRandomPolicy(1)},
+                },
+                quickAction: undefined,
+                betas: [CONST.BETAS.ALL],
+                personalDetails: {[RORY_ACCOUNT_ID]: {accountID: RORY_ACCOUNT_ID, login: RORY_EMAIL}},
+                conciergeReportID: undefined,
+            });
+
+            const createPerDiemRequestCall = writeSpy.mock.calls.find(([command]) => command === WRITE_COMMANDS.CREATE_PER_DIEM_REQUEST);
+            const parameters = createPerDiemRequestCall?.[1] as CreatePerDiemRequestParams | undefined;
+            const onyxData = createPerDiemRequestCall?.[2];
+            expect(parameters?.actionableWhisperReportActionID).toBe(actionableWhisperReportActionID);
+            expect(typeof parameters?.modifiedExpenseReportActionID).toBe('string');
+            expect(onyxData?.optimisticData).toEqual(
+                expect.arrayContaining([
+                    expect.objectContaining({
+                        key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${selfDMReportID}`,
+                        value: expect.objectContaining({
+                            [linkedTrackedExpenseReportAction.reportActionID]: expect.objectContaining({
+                                originalMessage: {IOUTransactionID: null},
+                            }),
+                        }),
+                    }),
+                ]),
+            );
+        });
+
         it('should update policyRecentlyUsedTags when tag is provided', async () => {
             // Given a transaction with a tag
             const iouReportID = '2';

From f5b812cad58cd2949a36aa684c04e8c7aa4dec5d Mon Sep 17 00:00:00 2001
From: nabi-ebrahimi <nabi.zarin.work@gmail.com>
Date: Mon, 8 Jun 2026 11:04:35 +0430
Subject: [PATCH 172/435] fix: clean up tracked per diem expense after
 workspace submission

---
 src/libs/actions/IOU/TrackExpense.ts | 10 ++--------
 1 file changed, 2 insertions(+), 8 deletions(-)

diff --git a/src/libs/actions/IOU/TrackExpense.ts b/src/libs/actions/IOU/TrackExpense.ts
index b9815e27221a..624ff0b3cf31 100644
--- a/src/libs/actions/IOU/TrackExpense.ts
+++ b/src/libs/actions/IOU/TrackExpense.ts
@@ -2101,14 +2101,8 @@ function categorizeTrackedExpense(trackedExpenseParams: TrackedExpenseParams) {
     const {optimisticData, successData, failureData} = onyxData ?? {};
     const {transactionID} = transactionParams;
     const {isDraftPolicy} = policyParams;
-    const {
-        actionableWhisperReportActionID,
-        moneyRequestReportID,
-        linkedTrackedExpenseReportAction,
-        linkedTrackedExpenseReportID,
-        transactionThreadReportID,
-        isLinkedTrackedExpenseReportArchived,
-    } = reportInformation;
+    const {actionableWhisperReportActionID, linkedTrackedExpenseReportAction, linkedTrackedExpenseReportID, transactionThreadReportID, isLinkedTrackedExpenseReportArchived} =
+        reportInformation;
     const {
         optimisticData: moveTransactionOptimisticData,
         successData: moveTransactionSuccessData,

From 08039e1ce4d2d31745c3a494cce7b85ebbe4c8e8 Mon Sep 17 00:00:00 2001
From: nabi-ebrahimi <nabi.zarin.work@gmail.com>
Date: Mon, 8 Jun 2026 12:13:55 +0430
Subject: [PATCH 173/435] fix: preserve tracked per diem thread during
 submission cleanup

---
 src/libs/actions/IOU/PerDiem.ts  |  3 ++-
 tests/actions/IOU/PerDiemTest.ts | 12 ++++++++++++
 2 files changed, 14 insertions(+), 1 deletion(-)

diff --git a/src/libs/actions/IOU/PerDiem.ts b/src/libs/actions/IOU/PerDiem.ts
index 87a107649857..11045af940aa 100644
--- a/src/libs/actions/IOU/PerDiem.ts
+++ b/src/libs/actions/IOU/PerDiem.ts
@@ -1008,12 +1008,13 @@ function submitPerDiemExpense(submitPerDiemExpenseInformation: PerDiemExpenseInf
     const sourceTransactionID = getExistingTransactionID(linkedTrackedExpenseReportAction);
 
     if (sourceTransactionID && linkedTrackedExpenseReportAction && linkedTrackedExpenseReportID) {
+        const linkedTrackedExpenseThreadReportID = linkedTrackedExpenseReportAction.childReportID ?? transactionThreadReportID;
         const moveTrackedExpenseInformation = getMoveTrackedExpenseInformation(
             sourceTransactionID,
             actionableWhisperReportActionID,
             linkedTrackedExpenseReportAction,
             linkedTrackedExpenseReportID,
-            transactionThreadReportID,
+            linkedTrackedExpenseThreadReportID,
             CONST.IOU.ACTION.SUBMIT,
             isLinkedTrackedExpenseReportArchived,
             currentUserAccountIDParam,
diff --git a/tests/actions/IOU/PerDiemTest.ts b/tests/actions/IOU/PerDiemTest.ts
index b0ad2860c348..8c59ee5b0df0 100644
--- a/tests/actions/IOU/PerDiemTest.ts
+++ b/tests/actions/IOU/PerDiemTest.ts
@@ -733,6 +733,18 @@ describe('PerDiem', () => {
             const onyxData = createPerDiemRequestCall?.[2];
             expect(parameters?.actionableWhisperReportActionID).toBe(actionableWhisperReportActionID);
             expect(typeof parameters?.modifiedExpenseReportActionID).toBe('string');
+            expect(onyxData?.optimisticData).toEqual(
+                expect.arrayContaining([
+                    expect.objectContaining({
+                        key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${linkedTrackedExpenseReportAction.childReportID}`,
+                        value: expect.objectContaining({
+                            [parameters?.modifiedExpenseReportActionID ?? '']: expect.objectContaining({
+                                actionName: CONST.REPORT.ACTIONS.TYPE.MOVED_TRANSACTION,
+                            }),
+                        }),
+                    }),
+                ]),
+            );
             expect(onyxData?.optimisticData).toEqual(
                 expect.arrayContaining([
                     expect.objectContaining({

From 5fa9067b90a8a6c3403ce27672522ad166baa2e3 Mon Sep 17 00:00:00 2001
From: GCyganek <gabrielcyganek@gmail.com>
Date: Mon, 8 Jun 2026 10:42:47 +0200
Subject: [PATCH 174/435] Fix [Sentry: APP-8BM] HybridApp iOS
 NSInvalidArgumentException nil object in RCTNetworking prioritizedHandlers

---
 patches/react-native/details.md               |  8 +++++++
 ...038+fix-nil-BlobModule-crash-APP-8BM.patch | 24 +++++++++++++++++++
 2 files changed, 32 insertions(+)
 create mode 100644 patches/react-native/react-native+0.83.1+038+fix-nil-BlobModule-crash-APP-8BM.patch

diff --git a/patches/react-native/details.md b/patches/react-native/details.md
index 4d5f5e2dc67c..8b66512f6945 100644
--- a/patches/react-native/details.md
+++ b/patches/react-native/details.md
@@ -284,3 +284,11 @@
 - Upstream PR/issue: https://github.com/facebook/react-native/issues/53128
 - E/App issue: https://github.com/Expensify/App/issues/91292
 - PR introducing patch: https://github.com/Expensify/App/pull/91736
+
+
+### [react-native+0.83.1+038+fix-nil-BlobModule-crash-APP-8BM.patch](react-native+0.83.1+038+fix-nil-BlobModule-crash-APP-8BM.patch)
+
+- Reason: Fixes a fatal iOS crash (APP-8BM) in HybridApp where `RCTNetworking`'s default URL-request-handler provider builds its handler list using an Objective-C array literal (`@[...]`) with `[moduleRegistry moduleForName:"BlobModule"]` at index 3. During OldDot↔NewDot bridge transitions, the `__weak _turboModuleRegistry` in `RCTModuleRegistry` is zeroed by ARC at the start of `TurboModuleManager` dealloc — before `[RCTNetworking invalidate]` clears the handler cache — leaving a window where a concurrent in-flight network request calls `prioritizedHandlers`, finds the cache empty, and tries to rebuild it with a nil `BlobModule`. Since `@[…]` compiles to `+[NSArray arrayWithObjects:count:]` which raises `NSInvalidArgumentException` on any nil element, the crash is fatal. The fix replaces the literal with an `NSMutableArray` built from the three always-non-nil handlers (`RCTHTTPRequestHandler`, `RCTDataRequestHandler`, `RCTFileRequestHandler`) and conditionally appends `BlobModule` only when the registry lookup is non-nil, turning a guaranteed crash into a graceful "no blob handler for this window".
+- Upstream PR/issue: 🛑
+- E/App issue: https://github.com/Expensify/App/issues/92413
+- PR introducing patch: -
\ No newline at end of file
diff --git a/patches/react-native/react-native+0.83.1+038+fix-nil-BlobModule-crash-APP-8BM.patch b/patches/react-native/react-native+0.83.1+038+fix-nil-BlobModule-crash-APP-8BM.patch
new file mode 100644
index 000000000000..d0a50ce8c581
--- /dev/null
+++ b/patches/react-native/react-native+0.83.1+038+fix-nil-BlobModule-crash-APP-8BM.patch
@@ -0,0 +1,24 @@
+diff --git a/node_modules/react-native/Libraries/AppDelegate/RCTAppSetupUtils.mm b/node_modules/react-native/Libraries/AppDelegate/RCTAppSetupUtils.mm
+index fabfff3..cefa0fa 100644
+--- a/node_modules/react-native/Libraries/AppDelegate/RCTAppSetupUtils.mm
++++ b/node_modules/react-native/Libraries/AppDelegate/RCTAppSetupUtils.mm
+@@ -103,11 +103,16 @@ void RCTAppSetupPrepareApp(UIApplication *application, BOOL turboModuleEnabled)
+         initWithHandlersProvider:^NSArray<id<RCTURLRequestHandler>> *(RCTModuleRegistry *moduleRegistry) {
+           NSArray *URLRequestHandlerModules =
+               extractModuleConformingToProtocol(moduleRegistry, @protocol(RCTURLRequestHandler));
+-          return [@[
++          NSMutableArray<id<RCTURLRequestHandler>> *defaultHandlers = [NSMutableArray arrayWithObjects:
+             [RCTHTTPRequestHandler new],
+             [RCTDataRequestHandler new],
+             [RCTFileRequestHandler new],
+-            [moduleRegistry moduleForName:"BlobModule"],
+-          ] arrayByAddingObjectsFromArray:URLRequestHandlerModules];
++            nil
++          ];
++          id blobModule = [moduleRegistry moduleForName:"BlobModule"];
++          if (blobModule != nil) {
++            [defaultHandlers addObject:blobModule];
++          }
++          return [defaultHandlers arrayByAddingObjectsFromArray:URLRequestHandlerModules];
+         }];
+   }

From dd4e06ad97eca4422ed1a564cc50044d672c8229 Mon Sep 17 00:00:00 2001
From: nabi-ebrahimi <nabi.zarin.work@gmail.com>
Date: Mon, 8 Jun 2026 13:32:56 +0430
Subject: [PATCH 175/435] fix per diem thread cleanup

---
 tests/actions/IOU/PerDiemTest.ts | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/tests/actions/IOU/PerDiemTest.ts b/tests/actions/IOU/PerDiemTest.ts
index 8c59ee5b0df0..f4043a0fbe83 100644
--- a/tests/actions/IOU/PerDiemTest.ts
+++ b/tests/actions/IOU/PerDiemTest.ts
@@ -733,12 +733,16 @@ describe('PerDiem', () => {
             const onyxData = createPerDiemRequestCall?.[2];
             expect(parameters?.actionableWhisperReportActionID).toBe(actionableWhisperReportActionID);
             expect(typeof parameters?.modifiedExpenseReportActionID).toBe('string');
+            const modifiedExpenseReportActionID = parameters?.modifiedExpenseReportActionID;
+            if (!modifiedExpenseReportActionID) {
+                throw new Error('Expected modifiedExpenseReportActionID to be defined');
+            }
             expect(onyxData?.optimisticData).toEqual(
                 expect.arrayContaining([
                     expect.objectContaining({
                         key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${linkedTrackedExpenseReportAction.childReportID}`,
                         value: expect.objectContaining({
-                            [parameters?.modifiedExpenseReportActionID ?? '']: expect.objectContaining({
+                            [modifiedExpenseReportActionID]: expect.objectContaining({
                                 actionName: CONST.REPORT.ACTIONS.TYPE.MOVED_TRANSACTION,
                             }),
                         }),

From 4978994ae9a04e582b231b827aed381faa52b44c Mon Sep 17 00:00:00 2001
From: "daledah (via MelvinBot)" <infra+melvinbot@expensify.com>
Date: Mon, 8 Jun 2026 10:11:40 +0000
Subject: [PATCH 176/435] Fix: don't mislabel workspace company cards as
 "Personal card" in group-by-card

Workspace company cards from card feeds also lack a fundID, so isPersonalCard
alone misclassified them as personal. Use the non-personal-and-workspace card
list (which keeps company/workspace cards while filtering personal cards out)
as a negative guard so only genuine personal cards get the "Personal card" label.

Co-authored-by: daledah <daledah@users.noreply.github.com>
---
 src/components/Search/index.tsx        |  2 ++
 src/hooks/useSearchSections.ts         |  2 ++
 src/libs/SearchUIUtils.ts              | 38 +++++++++++++++-----------
 tests/unit/Search/SearchUIUtilsTest.ts | 38 ++++++++++++++++++++++++--
 4 files changed, 62 insertions(+), 18 deletions(-)

diff --git a/src/components/Search/index.tsx b/src/components/Search/index.tsx
index 0f659ee3052c..e87eb7c7a84e 100644
--- a/src/components/Search/index.tsx
+++ b/src/components/Search/index.tsx
@@ -557,6 +557,7 @@ function Search({
             isActionLoadingSet,
             cardFeeds,
             cardList: personalAndWorkspaceCards,
+            nonPersonalAndWorkspaceCardList: nonPersonalAndWorkspaceCards,
             isOffline,
             allTransactionViolations: violations,
             customCardNames,
@@ -590,6 +591,7 @@ function Search({
         isActionLoadingSet,
         cardFeeds,
         personalAndWorkspaceCards,
+        nonPersonalAndWorkspaceCards,
         policies,
         bankAccountList,
         violations,
diff --git a/src/hooks/useSearchSections.ts b/src/hooks/useSearchSections.ts
index 118a99c8aee4..efe300e2767c 100644
--- a/src/hooks/useSearchSections.ts
+++ b/src/hooks/useSearchSections.ts
@@ -26,6 +26,7 @@ function useSearchSections(): UseSearchSectionsResult {
 
     const [cardFeeds] = useOnyx(ONYXKEYS.COLLECTION.SHARED_NVP_PRIVATE_DOMAIN_MEMBER);
     const [personalAndWorkspaceCards] = useOnyx(ONYXKEYS.DERIVED.PERSONAL_AND_WORKSPACE_CARD_LIST);
+    const [nonPersonalAndWorkspaceCards] = useOnyx(ONYXKEYS.DERIVED.NON_PERSONAL_AND_WORKSPACE_CARD_LIST);
     const [bankAccountList] = useOnyx(ONYXKEYS.BANK_ACCOUNT_LIST);
 
     const archivedReportsIdSet = useArchivedReportsIdSet();
@@ -54,6 +55,7 @@ function useSearchSections(): UseSearchSectionsResult {
             isActionLoadingSet,
             cardFeeds,
             cardList: personalAndWorkspaceCards,
+            nonPersonalAndWorkspaceCardList: nonPersonalAndWorkspaceCards,
             conciergeReportID,
             convertToDisplayString,
         });
diff --git a/src/libs/SearchUIUtils.ts b/src/libs/SearchUIUtils.ts
index 7b27a50f836d..da307368661a 100644
--- a/src/libs/SearchUIUtils.ts
+++ b/src/libs/SearchUIUtils.ts
@@ -591,6 +591,7 @@ type GetSectionsParams = {
     isOffline?: boolean;
     cardFeeds?: OnyxCollection<OnyxTypes.CardFeeds>;
     cardList?: OnyxEntry<OnyxTypes.CardList>;
+    nonPersonalAndWorkspaceCardList?: OnyxEntry<OnyxTypes.CardList>;
     customCardNames?: Record<number, string>;
     allTransactionViolations?: OnyxCollection<OnyxTypes.TransactionViolation[]>;
     visibleReportActionsData?: OnyxTypes.VisibleReportActionsDerivedValue;
@@ -3185,6 +3186,7 @@ function getCardSections(
     cardFeeds?: OnyxCollection<OnyxTypes.CardFeeds>,
     customCardNames?: Record<number, string>,
     cardList?: OnyxEntry<OnyxTypes.CardList>,
+    nonPersonalAndWorkspaceCardList?: OnyxEntry<OnyxTypes.CardList>,
 ): [TransactionCardGroupListItemType[], number, boolean] {
     const cardSections: Record<string, TransactionCardGroupListItemType> = {};
     const cardDescriptionByCardID = new Map<number, string>();
@@ -3222,6 +3224,10 @@ function getCardSections(
             }
 
             const card = cardList?.[cardGroup.cardID];
+            // A workspace/company card from a card feed can also lack a `fundID`, so `isPersonalCard` alone would misclassify it.
+            // The non-personal card list keeps every company/workspace-feed card while filtering personal cards out, so presence
+            // there means the card is definitively NOT personal.
+            const isPersonal = !!card && isPersonalCard(card) && !nonPersonalAndWorkspaceCardList?.[cardGroup.cardID];
             cardSections[key] = {
                 groupedBy: CONST.SEARCH.GROUP_BY.CARD,
                 transactions: [],
@@ -3229,21 +3235,20 @@ function getCardSections(
                 ...personalDetails,
                 ...cardGroup,
                 formattedCardName,
-                formattedFeedName:
-                    card && isPersonalCard(card)
-                        ? translate('cardTransactions.personalCard')
-                        : getFeedNameForDisplay(
-                              translate,
-                              cardGroup.bank as OnyxTypes.CompanyCardFeed,
-                              cardFeeds,
-                              card?.fundID
-                                  ? cardFeeds?.[`${ONYXKEYS.COLLECTION.SHARED_NVP_PRIVATE_DOMAIN_MEMBER}${card.fundID}`]?.settings?.companyCardNicknames?.[
-                                        cardGroup.bank as OnyxTypes.CompanyCardFeed
-                                    ]
-                                  : undefined,
-                              true,
-                              cardGroup?.feedCountry,
-                          ),
+                formattedFeedName: isPersonal
+                    ? translate('cardTransactions.personalCard')
+                    : getFeedNameForDisplay(
+                          translate,
+                          cardGroup.bank as OnyxTypes.CompanyCardFeed,
+                          cardFeeds,
+                          card?.fundID
+                              ? cardFeeds?.[`${ONYXKEYS.COLLECTION.SHARED_NVP_PRIVATE_DOMAIN_MEMBER}${card.fundID}`]?.settings?.companyCardNicknames?.[
+                                    cardGroup.bank as OnyxTypes.CompanyCardFeed
+                                ]
+                              : undefined,
+                          true,
+                          cardGroup?.feedCountry,
+                      ),
                 keyForList: key,
             };
         }
@@ -3580,6 +3585,7 @@ function getSections({
     isOffline,
     cardFeeds,
     cardList,
+    nonPersonalAndWorkspaceCardList,
     customCardNames,
     allTransactionViolations,
     visibleReportActionsData,
@@ -3622,7 +3628,7 @@ function getSections({
             case CONST.SEARCH.GROUP_BY.FROM:
                 return getMemberSections(data, queryJSON, formatPhoneNumber);
             case CONST.SEARCH.GROUP_BY.CARD:
-                return getCardSections(data, queryJSON, translate, cardFeeds, customCardNames, cardList);
+                return getCardSections(data, queryJSON, translate, cardFeeds, customCardNames, cardList, nonPersonalAndWorkspaceCardList);
             case CONST.SEARCH.GROUP_BY.WITHDRAWAL_ID:
                 return getWithdrawalIDSections(data, queryJSON);
             case CONST.SEARCH.GROUP_BY.CATEGORY:
diff --git a/tests/unit/Search/SearchUIUtilsTest.ts b/tests/unit/Search/SearchUIUtilsTest.ts
index 2329a965e001..b31870059eb6 100644
--- a/tests/unit/Search/SearchUIUtilsTest.ts
+++ b/tests/unit/Search/SearchUIUtilsTest.ts
@@ -3092,10 +3092,11 @@ describe('SearchUIUtils', () => {
             ).toStrictEqual(transactionCardGroupListItems);
         });
 
-        it('should label personal card groups as "Personal card" while keeping "Deleted feed" for removed company feeds', () => {
+        it('should label personal card groups as "Personal card" while keeping company-feed names for company cards and "Deleted feed" for removed feeds', () => {
             const personalCardID = 40404040;
             const csvPersonalCardID = 50505050;
             const deletedFeedCardID = 60606060;
+            const workspaceFeedCardID = 70707070;
 
             const data: OnyxTypes.SearchResults['data'] = {
                 personalDetailsList: {},
@@ -3129,15 +3130,44 @@ describe('SearchUIUtils', () => {
                     lastFourPAN: '3333',
                     total: 30,
                 },
+                [`${CONST.SEARCH.GROUP_PREFIX}${workspaceFeedCardID}` as const]: {
+                    accountID: adminAccountID,
+                    bank: CONST.COMPANY_CARD.FEED_BANK_NAME.VISA,
+                    cardID: workspaceFeedCardID,
+                    cardName: 'Workspace Visa',
+                    count: 1,
+                    currency: 'USD',
+                    lastFourPAN: '4444',
+                    total: 40,
+                },
             };
 
             // Personal cards have no fundID; the deleted company feed card keeps its fundID so it is not personal.
+            // The workspace-feed company card also has no fundID (company-feed cards never carry one), so it must be
+            // distinguished from a personal card via the non-personal card list rather than `isPersonalCard` alone.
             const cardList = {
                 [personalCardID]: {cardID: personalCardID, bank: CONST.PERSONAL_CARDS.BANK_NAME.CHASE},
                 [csvPersonalCardID]: {cardID: csvPersonalCardID, bank: CONST.PERSONAL_CARDS.BANK_NAME.CSV, fundID: '123'},
                 [deletedFeedCardID]: {cardID: deletedFeedCardID, bank: CONST.BANK_NAMES.CITIBANK, fundID: '456'},
+                [workspaceFeedCardID]: {cardID: workspaceFeedCardID, bank: CONST.COMPANY_CARD.FEED_BANK_NAME.VISA},
             } as unknown as OnyxTypes.CardList;
 
+            // The non-personal list keeps every company/workspace-feed card while filtering personal cards out.
+            const nonPersonalAndWorkspaceCardList = {
+                [workspaceFeedCardID]: {cardID: workspaceFeedCardID, bank: CONST.COMPANY_CARD.FEED_BANK_NAME.VISA},
+            } as unknown as OnyxTypes.CardList;
+
+            // The VISA feed exists in the workspace, so it should resolve to a real feed name (not "Deleted feed").
+            const cardFeeds = {
+                policy1: {
+                    settings: {
+                        companyCards: {
+                            [CONST.COMPANY_CARD.FEED_BANK_NAME.VISA]: {} as CustomCardFeedData,
+                        },
+                    },
+                } as OnyxTypes.CardFeeds,
+            };
+
             const [sections] = SearchUIUtils.getSections({
                 type: CONST.SEARCH.DATA_TYPES.EXPENSE,
                 data,
@@ -3147,8 +3177,9 @@ describe('SearchUIUtils', () => {
                 formatPhoneNumber,
                 bankAccountList: {},
                 groupBy: CONST.SEARCH.GROUP_BY.CARD,
-                cardFeeds: {},
+                cardFeeds,
                 cardList,
+                nonPersonalAndWorkspaceCardList,
                 conciergeReportID: undefined,
                 convertToDisplayString,
             }) as [TransactionCardGroupListItemType[], number, boolean];
@@ -3158,6 +3189,9 @@ describe('SearchUIUtils', () => {
             expect(feedNameByCardID.get(personalCardID)).toBe('Personal card');
             expect(feedNameByCardID.get(csvPersonalCardID)).toBe('Personal card');
             expect(feedNameByCardID.get(deletedFeedCardID)).toBe('Deleted feed');
+            // A workspace-feed company card without a fundID must NOT be mislabeled as a personal card.
+            expect(feedNameByCardID.get(workspaceFeedCardID)).not.toBe('Personal card');
+            expect(feedNameByCardID.get(workspaceFeedCardID)).not.toBe('Deleted feed');
         });
 
         it('should return getWithdrawalIDSections result when type is EXPENSE and groupBy is withdrawal-id', () => {

From be7d2ae698d436413650ce0ed4aee40a3b89e6e5 Mon Sep 17 00:00:00 2001
From: bartlomiej obudzinski <bartlomiej.obudzinski@callstack.com>
Date: Mon, 8 Jun 2026 12:42:52 +0200
Subject: [PATCH 177/435] refactor: extract inbox tab span lifecycle hook

---
 src/hooks/useInboxTabSpanLifecycle.ts        | 60 ++++++++++++++++++++
 src/pages/inbox/sidebar/SidebarLinksData.tsx | 43 ++------------
 2 files changed, 64 insertions(+), 39 deletions(-)
 create mode 100644 src/hooks/useInboxTabSpanLifecycle.ts

diff --git a/src/hooks/useInboxTabSpanLifecycle.ts b/src/hooks/useInboxTabSpanLifecycle.ts
new file mode 100644
index 000000000000..9c638f16bbe2
--- /dev/null
+++ b/src/hooks/useInboxTabSpanLifecycle.ts
@@ -0,0 +1,60 @@
+import {useFocusEffect} from '@react-navigation/native';
+import {useCallback, useEffect, useRef} from 'react';
+import {cancelSpan, endSpan, getSpan} from '@libs/telemetry/activeSpans';
+import CONST from '@src/CONST';
+
+/**
+ * Manages the ManualNavigateToInboxTab span lifecycle for the inbox sidebar.
+ *
+ * Three signals are handled:
+ * - onLayout fires on first mount: ends the span (normal path).
+ * - useFocusEffect fires on re-focus when react-freeze has cached the layout: ends the span (warm path).
+ *   The blur cleanup cancels any orphaned span when the user navigates away before layout completes.
+ * - useEffect unmount cleanup cancels the span only if layout never completed AND the active span
+ *   is the same one that was present when this instance mounted (avoids canceling a span started
+ *   by a subsequent tab click).
+ *
+ * Returns `onLayout` to be attached to the sidebar container View.
+ */
+function useInboxTabSpanLifecycle(): () => void {
+    const hasHadFirstLayout = useRef(false);
+    const spanOnMount = useRef(getSpan(CONST.TELEMETRY.SPAN_NAVIGATE_TO_INBOX_TAB));
+
+    const onLayout = useCallback(() => {
+        hasHadFirstLayout.current = true;
+        endSpan(CONST.TELEMETRY.SPAN_NAVIGATE_TO_INBOX_TAB);
+        spanOnMount.current = undefined;
+    }, []);
+
+    // Focus: ends span on re-visits (react-freeze cached layout, onLayout won't fire again).
+    // Blur cleanup: cancels orphaned span when user navigates away before onLayout fires.
+    useFocusEffect(
+        useCallback(() => {
+            if (hasHadFirstLayout.current) {
+                endSpan(CONST.TELEMETRY.SPAN_NAVIGATE_TO_INBOX_TAB);
+            }
+            return () => cancelSpan(CONST.TELEMETRY.SPAN_NAVIGATE_TO_INBOX_TAB);
+        }, []),
+    );
+
+    // Unmount: cancel only if layout never completed AND the active span is
+    // the same one that existed when this instance mounted (avoids canceling
+    // a newer span started by a subsequent tab click).
+    useEffect(
+        () => () => {
+            if (hasHadFirstLayout.current) {
+                return;
+            }
+            const activeSpan = getSpan(CONST.TELEMETRY.SPAN_NAVIGATE_TO_INBOX_TAB);
+            if (activeSpan !== spanOnMount.current) {
+                return;
+            }
+            cancelSpan(CONST.TELEMETRY.SPAN_NAVIGATE_TO_INBOX_TAB);
+        },
+        [],
+    );
+
+    return onLayout;
+}
+
+export default useInboxTabSpanLifecycle;
diff --git a/src/pages/inbox/sidebar/SidebarLinksData.tsx b/src/pages/inbox/sidebar/SidebarLinksData.tsx
index 1c4879c15884..59d2ec758e02 100644
--- a/src/pages/inbox/sidebar/SidebarLinksData.tsx
+++ b/src/pages/inbox/sidebar/SidebarLinksData.tsx
@@ -1,13 +1,13 @@
-import {useFocusEffect, useIsFocused} from '@react-navigation/native';
+import {useIsFocused} from '@react-navigation/native';
 import * as Sentry from '@sentry/react-native';
-import React, {useCallback, useEffect, useRef} from 'react';
+import React, {useCallback, useRef} from 'react';
 import {View} from 'react-native';
 import type {EdgeInsets} from 'react-native-safe-area-context';
+import useInboxTabSpanLifecycle from '@hooks/useInboxTabSpanLifecycle';
 import useLocalize from '@hooks/useLocalize';
 import useOnyx from '@hooks/useOnyx';
 import {useSidebarOrderedReportsState} from '@hooks/useSidebarOrderedReports';
 import useThemeStyles from '@hooks/useThemeStyles';
-import {cancelSpan, endSpan, getSpan} from '@libs/telemetry/activeSpans';
 import CONST from '@src/CONST';
 import ONYXKEYS from '@src/ONYXKEYS';
 import SidebarLinks from './SidebarLinks';
@@ -29,42 +29,7 @@ function SidebarLinksData({insets}: SidebarLinksDataProps) {
     currentReportIDRef.current = currentReportID;
     const isActiveReport = useCallback((reportID: string): boolean => currentReportIDRef.current === reportID, []);
 
-    const hasHadFirstLayout = useRef(false);
-    const spanOnMount = useRef(getSpan(CONST.TELEMETRY.SPAN_NAVIGATE_TO_INBOX_TAB));
-
-    const onLayout = useCallback(() => {
-        hasHadFirstLayout.current = true;
-        endSpan(CONST.TELEMETRY.SPAN_NAVIGATE_TO_INBOX_TAB);
-        spanOnMount.current = undefined;
-    }, []);
-
-    // Focus: ends span on re-visits (react-freeze cached layout, onLayout won't fire again).
-    // Blur cleanup: cancels orphaned span when user navigates away before onLayout fires.
-    useFocusEffect(
-        useCallback(() => {
-            if (hasHadFirstLayout.current) {
-                endSpan(CONST.TELEMETRY.SPAN_NAVIGATE_TO_INBOX_TAB);
-            }
-            return () => cancelSpan(CONST.TELEMETRY.SPAN_NAVIGATE_TO_INBOX_TAB);
-        }, []),
-    );
-
-    // Unmount: cancel only if layout never completed AND the active span is
-    // the same one that existed when this instance mounted (avoids canceling
-    // a newer span started by a subsequent tab click).
-    useEffect(
-        () => () => {
-            if (hasHadFirstLayout.current) {
-                return;
-            }
-            const activeSpan = getSpan(CONST.TELEMETRY.SPAN_NAVIGATE_TO_INBOX_TAB);
-            if (activeSpan !== spanOnMount.current) {
-                return;
-            }
-            cancelSpan(CONST.TELEMETRY.SPAN_NAVIGATE_TO_INBOX_TAB);
-        },
-        [],
-    );
+    const onLayout = useInboxTabSpanLifecycle();
 
     return (
         <View

From 91c820e09b5109b3ba64985041448f274e6a3f53 Mon Sep 17 00:00:00 2001
From: bartlomiej obudzinski <bartlomiej.obudzinski@callstack.com>
Date: Mon, 8 Jun 2026 12:54:59 +0200
Subject: [PATCH 178/435] refactor: extract InboxTabButton with colocated last
 report subs

---
 .../NavigationTabBar/InboxTabButton.tsx       | 144 ++++++++++++++++++
 .../Navigation/NavigationTabBar/index.tsx     | 114 ++------------
 2 files changed, 158 insertions(+), 100 deletions(-)
 create mode 100644 src/components/Navigation/NavigationTabBar/InboxTabButton.tsx

diff --git a/src/components/Navigation/NavigationTabBar/InboxTabButton.tsx b/src/components/Navigation/NavigationTabBar/InboxTabButton.tsx
new file mode 100644
index 000000000000..9c3f3b15fa75
--- /dev/null
+++ b/src/components/Navigation/NavigationTabBar/InboxTabButton.tsx
@@ -0,0 +1,144 @@
+import React, {useMemo} from 'react';
+import type {OnyxEntry} from 'react-native-onyx';
+import type {ValueOf} from 'type-fest';
+import {PressableWithFeedback} from '@components/Pressable';
+import {useMemoizedLazyExpensifyIcons} from '@hooks/useLazyAsset';
+import useLocalize from '@hooks/useLocalize';
+import useOnyx from '@hooks/useOnyx';
+import useRootNavigationState from '@hooks/useRootNavigationState';
+import useThemeStyles from '@hooks/useThemeStyles';
+import Navigation from '@libs/Navigation/Navigation';
+import navigationRef from '@libs/Navigation/navigationRef';
+import {isDeletedAction} from '@libs/ReportActionsUtils';
+import {startSpan} from '@libs/telemetry/activeSpans';
+import type {ReportsSplitNavigatorParamList} from '@navigation/types';
+import CONST from '@src/CONST';
+import NAVIGATORS from '@src/NAVIGATORS';
+import ONYXKEYS from '@src/ONYXKEYS';
+import ROUTES from '@src/ROUTES';
+import SCREENS from '@src/SCREENS';
+import type {Report, ReportActions} from '@src/types/onyx';
+import getLastRoute from './getLastRoute';
+import NAVIGATION_TABS from './NAVIGATION_TABS';
+import TabBarItem from './TabBarItem';
+
+type BrickRoad = ValueOf<typeof CONST.BRICK_ROAD_INDICATOR_STATUS> | undefined;
+
+type InboxTabButtonProps = {
+    selectedTab: ValueOf<typeof NAVIGATION_TABS>;
+    isWideLayout: boolean;
+    statusIndicatorColor: string | undefined;
+    chatTabBrickRoad: BrickRoad;
+};
+
+function doesLastReportExistSelector(report: OnyxEntry<Report>) {
+    return !!report?.reportID;
+}
+
+function makeDoesLastReportActionExistSelector(actionID: string | undefined) {
+    return (reportActions: OnyxEntry<ReportActions>) => {
+        const reportAction = actionID ? reportActions?.[actionID] : undefined;
+        return !!reportAction && !isDeletedAction(reportAction);
+    };
+}
+
+function InboxTabButton({selectedTab, isWideLayout, statusIndicatorColor, chatTabBrickRoad}: InboxTabButtonProps) {
+    const styles = useThemeStyles();
+    const {translate} = useLocalize();
+    const expensifyIcons = useMemoizedLazyExpensifyIcons(['Inbox']);
+
+    const lastReportRouteReportID = useRootNavigationState((rootState) => {
+        if (!rootState) {
+            return undefined;
+        }
+        const route = getLastRoute(rootState, NAVIGATORS.REPORTS_SPLIT_NAVIGATOR, SCREENS.REPORT);
+        return (route?.params as ReportsSplitNavigatorParamList[typeof SCREENS.REPORT])?.reportID;
+    });
+
+    const lastReportRouteReportActionID = useRootNavigationState((rootState) => {
+        if (!rootState) {
+            return undefined;
+        }
+        const route = getLastRoute(rootState, NAVIGATORS.REPORTS_SPLIT_NAVIGATOR, SCREENS.REPORT);
+        return (route?.params as ReportsSplitNavigatorParamList[typeof SCREENS.REPORT])?.reportActionID;
+    });
+
+    const [doesLastReportExist] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${lastReportRouteReportID}`, {selector: doesLastReportExistSelector}, [lastReportRouteReportID]);
+
+    // useMemo factory: the selector needs lastReportRouteReportActionID from closure, so parameterless is not feasible
+    const doesLastReportActionExistSelector = useMemo(() => makeDoesLastReportActionExistSelector(lastReportRouteReportActionID), [lastReportRouteReportActionID]);
+    const [doesLastReportActionExist] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${lastReportRouteReportID}`, {selector: doesLastReportActionExistSelector}, [lastReportRouteReportID]);
+
+    const inboxAccessibilityState = {selected: selectedTab === NAVIGATION_TABS.INBOX};
+
+    const navigateToChats = () => {
+        if (selectedTab === NAVIGATION_TABS.INBOX) {
+            return;
+        }
+
+        startSpan(CONST.TELEMETRY.SPAN_NAVIGATE_TO_INBOX_TAB, {
+            name: CONST.TELEMETRY.SPAN_NAVIGATE_TO_INBOX_TAB,
+            op: CONST.TELEMETRY.SPAN_NAVIGATE_TO_INBOX_TAB,
+        });
+
+        if (isWideLayout && doesLastReportExist) {
+            // Fetch route params on-demand to avoid storing the full route object in render-time state
+            const rootState = navigationRef.getRootState();
+            const lastRoute = rootState ? getLastRoute(rootState, NAVIGATORS.REPORTS_SPLIT_NAVIGATOR, SCREENS.REPORT) : undefined;
+            if (lastRoute) {
+                const {reportID, reportActionID, referrer, backTo} = lastRoute.params as ReportsSplitNavigatorParamList[typeof SCREENS.REPORT];
+                Navigation.navigate(ROUTES.REPORT_WITH_ID.getRoute(reportID, doesLastReportActionExist ? reportActionID : undefined, referrer, backTo));
+                return;
+            }
+        }
+
+        Navigation.navigate(ROUTES.INBOX);
+    };
+
+    const accessibilityLabel = chatTabBrickRoad ? `${translate('common.inbox')}. ${translate('common.yourReviewIsRequired')}` : translate('common.inbox');
+
+    if (isWideLayout) {
+        return (
+            <PressableWithFeedback
+                onPress={navigateToChats}
+                role={CONST.ROLE.TAB}
+                accessibilityLabel={accessibilityLabel}
+                accessibilityState={inboxAccessibilityState}
+                style={({hovered}) => [styles.leftNavigationTabBarItem, hovered && styles.navigationTabBarItemHovered]}
+                sentryLabel={CONST.SENTRY_LABEL.NAVIGATION_TAB_BAR.INBOX}
+            >
+                {({hovered}) => (
+                    <TabBarItem
+                        icon={expensifyIcons.Inbox}
+                        label={translate('common.inbox')}
+                        isSelected={selectedTab === NAVIGATION_TABS.INBOX}
+                        isHovered={hovered}
+                        statusIndicatorColor={statusIndicatorColor}
+                    />
+                )}
+            </PressableWithFeedback>
+        );
+    }
+
+    return (
+        <PressableWithFeedback
+            onPress={navigateToChats}
+            role={CONST.ROLE.TAB}
+            accessibilityLabel={accessibilityLabel}
+            accessibilityState={inboxAccessibilityState}
+            wrapperStyle={styles.flex1}
+            style={styles.navigationTabBarItem}
+            sentryLabel={CONST.SENTRY_LABEL.NAVIGATION_TAB_BAR.INBOX}
+        >
+            <TabBarItem
+                icon={expensifyIcons.Inbox}
+                label={translate('common.inbox')}
+                isSelected={selectedTab === NAVIGATION_TABS.INBOX}
+                statusIndicatorColor={statusIndicatorColor}
+                numberOfLines={1}
+            />
+        </PressableWithFeedback>
+    );
+}
+
+export default InboxTabButton;
diff --git a/src/components/Navigation/NavigationTabBar/index.tsx b/src/components/Navigation/NavigationTabBar/index.tsx
index b6408aa3b02d..c78cffaa5956 100644
--- a/src/components/Navigation/NavigationTabBar/index.tsx
+++ b/src/components/Navigation/NavigationTabBar/index.tsx
@@ -1,6 +1,5 @@
 import React from 'react';
 import {View} from 'react-native';
-import type {OnyxEntry} from 'react-native-onyx';
 import type {ValueOf} from 'type-fest';
 import FloatingCameraButton from '@components/FloatingCameraButton';
 import FloatingGPSButton from '@components/FloatingGPSButton';
@@ -11,26 +10,18 @@ import {useMemoizedLazyExpensifyIcons} from '@hooks/useLazyAsset';
 import useLocalize from '@hooks/useLocalize';
 import useOnyx from '@hooks/useOnyx';
 import useResponsiveLayout from '@hooks/useResponsiveLayout';
-import useRootNavigationState from '@hooks/useRootNavigationState';
 import {useSidebarOrderedReportsState} from '@hooks/useSidebarOrderedReports';
 import useStyleUtils from '@hooks/useStyleUtils';
 import useTheme from '@hooks/useTheme';
 import useThemeStyles from '@hooks/useThemeStyles';
 import interceptAnonymousUser from '@libs/interceptAnonymousUser';
 import Navigation from '@libs/Navigation/Navigation';
-import navigationRef from '@libs/Navigation/navigationRef';
-import {isDeletedAction} from '@libs/ReportActionsUtils';
-import {startSpan} from '@libs/telemetry/activeSpans';
-import type {ReportsSplitNavigatorParamList} from '@navigation/types';
 import NavigationTabBarAvatar from '@pages/inbox/sidebar/NavigationTabBarAvatar';
 import NavigationTabBarFloatingActionButton from '@pages/inbox/sidebar/NavigationTabBarFloatingActionButton';
 import CONST from '@src/CONST';
-import NAVIGATORS from '@src/NAVIGATORS';
 import ONYXKEYS from '@src/ONYXKEYS';
 import ROUTES from '@src/ROUTES';
-import SCREENS from '@src/SCREENS';
-import type {Report, ReportActions} from '@src/types/onyx';
-import getLastRoute from './getLastRoute';
+import InboxTabButton from './InboxTabButton';
 import NAVIGATION_TABS from './NAVIGATION_TABS';
 import SearchTabButton from './SearchTabButton';
 import TabBarItem from './TabBarItem';
@@ -41,41 +32,13 @@ type NavigationTabBarProps = {
     shouldShowFloatingButtons?: boolean;
 };
 
-function doesLastReportExistSelector(report: OnyxEntry<Report>) {
-    return !!report?.reportID;
-}
-
 function NavigationTabBar({selectedTab, shouldShowFloatingButtons = true}: NavigationTabBarProps) {
     const theme = useTheme();
     const styles = useThemeStyles();
     const {translate} = useLocalize();
     const {chatTabBrickRoad} = useSidebarOrderedReportsState();
     const [isDebugModeEnabled] = useOnyx(ONYXKEYS.IS_DEBUG_MODE_ENABLED);
-    const expensifyIcons = useMemoizedLazyExpensifyIcons(['ExpensifyAppIcon', 'Home', 'Inbox']);
-
-    const lastReportRouteReportID = useRootNavigationState((rootState) => {
-        if (!rootState) {
-            return undefined;
-        }
-        const route = getLastRoute(rootState, NAVIGATORS.REPORTS_SPLIT_NAVIGATOR, SCREENS.REPORT);
-        return (route?.params as ReportsSplitNavigatorParamList[typeof SCREENS.REPORT])?.reportID;
-    });
-
-    const lastReportRouteReportActionID = useRootNavigationState((rootState) => {
-        if (!rootState) {
-            return undefined;
-        }
-        const route = getLastRoute(rootState, NAVIGATORS.REPORTS_SPLIT_NAVIGATOR, SCREENS.REPORT);
-        return (route?.params as ReportsSplitNavigatorParamList[typeof SCREENS.REPORT])?.reportActionID;
-    });
-
-    const [doesLastReportExist] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${lastReportRouteReportID}`, {selector: doesLastReportExistSelector}, [lastReportRouteReportID]);
-
-    const doesLastReportActionExistSelector = (reportActions: OnyxEntry<ReportActions>) => {
-        const reportAction = lastReportRouteReportActionID ? reportActions?.[lastReportRouteReportActionID] : undefined;
-        return !!reportAction && !isDeletedAction(reportAction);
-    };
-    const [doesLastReportActionExist] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${lastReportRouteReportID}`, {selector: doesLastReportActionExistSelector});
+    const expensifyIcons = useMemoizedLazyExpensifyIcons(['ExpensifyAppIcon', 'Home']);
 
     const {shouldUseNarrowLayout} = useResponsiveLayout();
 
@@ -88,8 +51,6 @@ function NavigationTabBar({selectedTab, shouldShowFloatingButtons = true}: Navig
         inboxStatusIndicatorColor = theme.danger;
     }
 
-    const inboxAccessibilityState = {selected: selectedTab === NAVIGATION_TABS.INBOX};
-
     const navigateToNewDotHome = () => {
         if (selectedTab === NAVIGATION_TABS.HOME) {
             return;
@@ -97,30 +58,6 @@ function NavigationTabBar({selectedTab, shouldShowFloatingButtons = true}: Navig
         Navigation.navigate(ROUTES.HOME);
     };
 
-    const navigateToChats = () => {
-        if (selectedTab === NAVIGATION_TABS.INBOX) {
-            return;
-        }
-
-        startSpan(CONST.TELEMETRY.SPAN_NAVIGATE_TO_INBOX_TAB, {
-            name: CONST.TELEMETRY.SPAN_NAVIGATE_TO_INBOX_TAB,
-            op: CONST.TELEMETRY.SPAN_NAVIGATE_TO_INBOX_TAB,
-        });
-
-        if (!shouldUseNarrowLayout && doesLastReportExist) {
-            // Fetch route params on-demand to avoid storing the full route object in render-time state
-            const rootState = navigationRef.getRootState();
-            const lastRoute = rootState ? getLastRoute(rootState, NAVIGATORS.REPORTS_SPLIT_NAVIGATOR, SCREENS.REPORT) : undefined;
-            if (lastRoute) {
-                const {reportID, reportActionID, referrer, backTo} = lastRoute.params as ReportsSplitNavigatorParamList[typeof SCREENS.REPORT];
-                Navigation.navigate(ROUTES.REPORT_WITH_ID.getRoute(reportID, doesLastReportActionExist ? reportActionID : undefined, referrer, backTo));
-                return;
-            }
-        }
-
-        Navigation.navigate(ROUTES.INBOX);
-    };
-
     const navigateToSettings = () => {
         if (selectedTab === NAVIGATION_TABS.SETTINGS) {
             return;
@@ -174,24 +111,12 @@ function NavigationTabBar({selectedTab, shouldShowFloatingButtons = true}: Navig
                                 />
                             )}
                         </PressableWithFeedback>
-                        <PressableWithFeedback
-                            onPress={navigateToChats}
-                            role={CONST.ROLE.TAB}
-                            accessibilityLabel={chatTabBrickRoad ? `${translate('common.inbox')}. ${translate('common.yourReviewIsRequired')}` : translate('common.inbox')}
-                            accessibilityState={inboxAccessibilityState}
-                            style={({hovered}) => [styles.leftNavigationTabBarItem, hovered && styles.navigationTabBarItemHovered]}
-                            sentryLabel={CONST.SENTRY_LABEL.NAVIGATION_TAB_BAR.INBOX}
-                        >
-                            {({hovered}) => (
-                                <TabBarItem
-                                    icon={expensifyIcons.Inbox}
-                                    label={translate('common.inbox')}
-                                    isSelected={selectedTab === NAVIGATION_TABS.INBOX}
-                                    isHovered={hovered}
-                                    statusIndicatorColor={inboxStatusIndicatorColor}
-                                />
-                            )}
-                        </PressableWithFeedback>
+                        <InboxTabButton
+                            selectedTab={selectedTab}
+                            isWideLayout
+                            statusIndicatorColor={inboxStatusIndicatorColor}
+                            chatTabBrickRoad={chatTabBrickRoad}
+                        />
                         <SearchTabButton
                             selectedTab={selectedTab}
                             isWideLayout
@@ -235,23 +160,12 @@ function NavigationTabBar({selectedTab, shouldShowFloatingButtons = true}: Navig
                         isSelected={selectedTab === NAVIGATION_TABS.HOME}
                     />
                 </PressableWithFeedback>
-                <PressableWithFeedback
-                    onPress={navigateToChats}
-                    role={CONST.ROLE.TAB}
-                    accessibilityLabel={chatTabBrickRoad ? `${translate('common.inbox')}. ${translate('common.yourReviewIsRequired')}` : translate('common.inbox')}
-                    accessibilityState={inboxAccessibilityState}
-                    wrapperStyle={styles.flex1}
-                    style={styles.navigationTabBarItem}
-                    sentryLabel={CONST.SENTRY_LABEL.NAVIGATION_TAB_BAR.INBOX}
-                >
-                    <TabBarItem
-                        icon={expensifyIcons.Inbox}
-                        label={translate('common.inbox')}
-                        isSelected={selectedTab === NAVIGATION_TABS.INBOX}
-                        statusIndicatorColor={inboxStatusIndicatorColor}
-                        numberOfLines={1}
-                    />
-                </PressableWithFeedback>
+                <InboxTabButton
+                    selectedTab={selectedTab}
+                    isWideLayout={false}
+                    statusIndicatorColor={inboxStatusIndicatorColor}
+                    chatTabBrickRoad={chatTabBrickRoad}
+                />
                 <SearchTabButton
                     selectedTab={selectedTab}
                     isWideLayout={false}

From 23cbc5e2e09d2d85f6544465fee8a2f7798ed249 Mon Sep 17 00:00:00 2001
From: GCyganek <gabrielcyganek@gmail.com>
Date: Mon, 8 Jun 2026 13:15:47 +0200
Subject: [PATCH 179/435] Update details.md

---
 patches/react-native/details.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/patches/react-native/details.md b/patches/react-native/details.md
index 8b66512f6945..58b04ce0b32e 100644
--- a/patches/react-native/details.md
+++ b/patches/react-native/details.md
@@ -291,4 +291,4 @@
 - Reason: Fixes a fatal iOS crash (APP-8BM) in HybridApp where `RCTNetworking`'s default URL-request-handler provider builds its handler list using an Objective-C array literal (`@[...]`) with `[moduleRegistry moduleForName:"BlobModule"]` at index 3. During OldDot↔NewDot bridge transitions, the `__weak _turboModuleRegistry` in `RCTModuleRegistry` is zeroed by ARC at the start of `TurboModuleManager` dealloc — before `[RCTNetworking invalidate]` clears the handler cache — leaving a window where a concurrent in-flight network request calls `prioritizedHandlers`, finds the cache empty, and tries to rebuild it with a nil `BlobModule`. Since `@[…]` compiles to `+[NSArray arrayWithObjects:count:]` which raises `NSInvalidArgumentException` on any nil element, the crash is fatal. The fix replaces the literal with an `NSMutableArray` built from the three always-non-nil handlers (`RCTHTTPRequestHandler`, `RCTDataRequestHandler`, `RCTFileRequestHandler`) and conditionally appends `BlobModule` only when the registry lookup is non-nil, turning a guaranteed crash into a graceful "no blob handler for this window".
 - Upstream PR/issue: 🛑
 - E/App issue: https://github.com/Expensify/App/issues/92413
-- PR introducing patch: -
\ No newline at end of file
+- PR introducing patch: https://github.com/Expensify/App/pull/92918
\ No newline at end of file

From 67efe0467a3a59ae00b40d144886ac0b0b2262bf Mon Sep 17 00:00:00 2001
From: Rushat Gabhane <rushatgabhane@gmail.com>
Date: Mon, 8 Jun 2026 13:38:50 +0200
Subject: [PATCH 180/435] rm defer

---
 src/components/DatePicker/index.tsx | 9 +--------
 1 file changed, 1 insertion(+), 8 deletions(-)

diff --git a/src/components/DatePicker/index.tsx b/src/components/DatePicker/index.tsx
index b7fb711c1ed1..01f0d72a8b71 100644
--- a/src/components/DatePicker/index.tsx
+++ b/src/components/DatePicker/index.tsx
@@ -116,13 +116,6 @@ function DatePicker({
         setIsModalVisible(false);
     }, []);
 
-    const openDatePickerOnPress = useCallback(() => {
-        if (!shouldDeferShowUntilPositioned) {
-            return;
-        }
-        showDatePickerModal();
-    }, [shouldDeferShowUntilPositioned, showDatePickerModal]);
-
     const handleInputKeyPress = useCallback(
         (event: TextInputKeyPressEvent) => {
             if (!isNumeric(event.nativeEvent.key)) {
@@ -196,7 +189,7 @@ function DatePicker({
                     errorText={errorText}
                     inputStyle={styles.pointerEventsNone}
                     disabled={disabled}
-                    onPress={openDatePickerOnPress}
+                    onPress={() => showDatePickerModal()}
                     onSubmitEditing={() => showDatePickerModal()}
                     onKeyPress={handleInputKeyPress}
                     textInputContainerStyles={isModalVisible ? styles.borderColorFocus : {}}

From 1bd7a9238ca126e8e52737433403a73c4b269670 Mon Sep 17 00:00:00 2001
From: bartlomiej obudzinski <bartlomiej.obudzinski@callstack.com>
Date: Mon, 8 Jun 2026 13:50:22 +0200
Subject: [PATCH 181/435] fix: spell check on InboxTabButton comment

---
 src/components/Navigation/NavigationTabBar/InboxTabButton.tsx | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/components/Navigation/NavigationTabBar/InboxTabButton.tsx b/src/components/Navigation/NavigationTabBar/InboxTabButton.tsx
index 9c3f3b15fa75..6ae62b5a7f05 100644
--- a/src/components/Navigation/NavigationTabBar/InboxTabButton.tsx
+++ b/src/components/Navigation/NavigationTabBar/InboxTabButton.tsx
@@ -65,7 +65,7 @@ function InboxTabButton({selectedTab, isWideLayout, statusIndicatorColor, chatTa
 
     const [doesLastReportExist] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${lastReportRouteReportID}`, {selector: doesLastReportExistSelector}, [lastReportRouteReportID]);
 
-    // useMemo factory: the selector needs lastReportRouteReportActionID from closure, so parameterless is not feasible
+    // Wrap factory in useMemo so the selector identity is stable per actionID
     const doesLastReportActionExistSelector = useMemo(() => makeDoesLastReportActionExistSelector(lastReportRouteReportActionID), [lastReportRouteReportActionID]);
     const [doesLastReportActionExist] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${lastReportRouteReportID}`, {selector: doesLastReportActionExistSelector}, [lastReportRouteReportID]);
 

From 4d49b7bc291947a335a96502331e63ad016f527a Mon Sep 17 00:00:00 2001
From: Adam Grzybowski <adam.grzybowski@swmansion.com>
Date: Mon, 8 Jun 2026 15:04:33 +0200
Subject: [PATCH 182/435] Fix flagged expenses to exclude dismissed violations

---
 .../OnyxDerived/configs/flaggedExpenses.ts    | 23 +++----
 tests/unit/OnyxDerived/flaggedExpensesTest.ts | 60 +++++++++++++------
 2 files changed, 53 insertions(+), 30 deletions(-)

diff --git a/src/libs/actions/OnyxDerived/configs/flaggedExpenses.ts b/src/libs/actions/OnyxDerived/configs/flaggedExpenses.ts
index 3f2163b3979d..d69e39d75686 100644
--- a/src/libs/actions/OnyxDerived/configs/flaggedExpenses.ts
+++ b/src/libs/actions/OnyxDerived/configs/flaggedExpenses.ts
@@ -1,3 +1,4 @@
+import {getVisibleTransactionViolations} from '@libs/TransactionUtils';
 import createOnyxDerivedValueConfig from '@userActions/OnyxDerived/createOnyxDerivedValueConfig';
 import CONST from '@src/CONST';
 import ONYXKEYS from '@src/ONYXKEYS';
@@ -28,14 +29,7 @@ function isCurrentUserOpenExpenseReport(report: Report | null | undefined, curre
     return report.stateNum === CONST.REPORT.STATE_NUM.OPEN && report.statusNum === CONST.REPORT.STATUS_NUM.OPEN;
 }
 
-/**
- * Returns true when the given violation list has at least one entry that should surface in the
- * `Review X expenses` row: a transaction-level violation that the user can act on. Entries marked
- * `showInReview === false` and report-field violations (`fieldRequired`) are excluded. `notice`/
- * `warning` types only count when `showInReview` is explicitly true (omitting it is not enough),
- * mirroring the review-visibility logic in `SearchUIUtils.hasVisibleViolations`; real `violation`
- * types remain actionable.
- */
+/** Returns true when at least one visible violation should surface in the "Review X expenses" row. */
 function hasReviewableViolation(violations: TransactionViolations | null | undefined): boolean {
     if (!violations || violations.length === 0) {
         return false;
@@ -60,13 +54,14 @@ function hasReviewableViolation(violations: TransactionViolations | null | undef
 
 export default createOnyxDerivedValueConfig({
     key: ONYXKEYS.DERIVED.FLAGGED_EXPENSES,
-    dependencies: [ONYXKEYS.COLLECTION.REPORT, ONYXKEYS.COLLECTION.TRANSACTION, ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS, ONYXKEYS.SESSION],
-    compute: ([allReports, allTransactions, allTransactionViolations, session]) => {
+    dependencies: [ONYXKEYS.COLLECTION.REPORT, ONYXKEYS.COLLECTION.TRANSACTION, ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS, ONYXKEYS.COLLECTION.POLICY, ONYXKEYS.SESSION],
+    compute: ([allReports, allTransactions, allTransactionViolations, allPolicies, session]) => {
         if (!allReports || !allTransactions) {
             return EMPTY_VALUE;
         }
 
         const currentUserAccountID = session?.accountID ?? CONST.DEFAULT_NUMBER_ID;
+        const currentUserEmail = session?.email ?? '';
         const flaggedExpenses: FlaggedExpenseEntry[] = [];
 
         for (const transactionKey of Object.keys(allTransactions)) {
@@ -81,7 +76,13 @@ export default createOnyxDerivedValueConfig({
             }
 
             const violations = allTransactionViolations?.[`${ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS}${transaction.transactionID}`];
-            if (!hasReviewableViolation(violations)) {
+            if (!violations || violations.length === 0) {
+                continue;
+            }
+
+            const policy = allPolicies?.[`${ONYXKEYS.COLLECTION.POLICY}${report?.policyID}`];
+            const visibleViolations = getVisibleTransactionViolations(transaction, violations, currentUserEmail, currentUserAccountID, report, policy);
+            if (!hasReviewableViolation(visibleViolations)) {
                 continue;
             }
 
diff --git a/tests/unit/OnyxDerived/flaggedExpensesTest.ts b/tests/unit/OnyxDerived/flaggedExpensesTest.ts
index c2316893628c..12628862c3c0 100644
--- a/tests/unit/OnyxDerived/flaggedExpensesTest.ts
+++ b/tests/unit/OnyxDerived/flaggedExpensesTest.ts
@@ -7,6 +7,7 @@ import type {Report, Session, Transaction, TransactionViolations} from '@src/typ
 import {createMockReport} from '../../utils/ReportTestUtils';
 
 const CURRENT_USER_ACCOUNT_ID = 1;
+const CURRENT_USER_EMAIL = 'user@example.com';
 const OTHER_USER_ACCOUNT_ID = 2;
 const POLICY_ID_1 = 'policy1';
 const POLICY_ID_2 = 'policy2';
@@ -59,14 +60,14 @@ function buildViolations(violationsByTransactionID: Record<string, TransactionVi
     return result;
 }
 
-function createSession(accountID: number = CURRENT_USER_ACCOUNT_ID): Session {
-    return {accountID} as Session;
+function createSession(accountID: number = CURRENT_USER_ACCOUNT_ID, email: string = CURRENT_USER_EMAIL): Session {
+    return {accountID, email} as Session;
 }
 
 const {compute} = flaggedExpensesConfig;
 const emptyContext = {} as DerivedValueContext<
     typeof ONYXKEYS.DERIVED.FLAGGED_EXPENSES,
-    [typeof ONYXKEYS.COLLECTION.REPORT, typeof ONYXKEYS.COLLECTION.TRANSACTION, typeof ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS, typeof ONYXKEYS.SESSION]
+    [typeof ONYXKEYS.COLLECTION.REPORT, typeof ONYXKEYS.COLLECTION.TRANSACTION, typeof ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS, typeof ONYXKEYS.COLLECTION.POLICY, typeof ONYXKEYS.SESSION]
 >;
 
 describe('flaggedExpenses derived value', () => {
@@ -74,7 +75,7 @@ describe('flaggedExpenses derived value', () => {
         it('reports zero flagged expenses and an empty list when no transactions have violations', () => {
             const report = createExpenseReport('r1');
             const transaction = createTransaction('t1', 'r1');
-            const result = compute([buildReports(report), buildTransactions(transaction), {}, createSession()], emptyContext);
+            const result = compute([buildReports(report), buildTransactions(transaction), {}, {}, createSession()], emptyContext);
 
             expect(result.flaggedExpenses).toEqual([]);
         });
@@ -89,7 +90,7 @@ describe('flaggedExpenses derived value', () => {
                 t2: [{type: CONST.VIOLATION_TYPES.VIOLATION, name: CONST.VIOLATIONS.MISSING_CATEGORY}],
             });
 
-            const result = compute([buildReports(report1, report2), buildTransactions(transaction1, transaction2), violations, createSession()], emptyContext);
+            const result = compute([buildReports(report1, report2), buildTransactions(transaction1, transaction2), violations, {}, createSession()], emptyContext);
 
             expect(result.flaggedExpenses).toHaveLength(2);
             const ids = result.flaggedExpenses.map((entry) => entry.transactionID).sort();
@@ -108,7 +109,7 @@ describe('flaggedExpenses derived value', () => {
                 ],
             });
 
-            const result = compute([buildReports(report), buildTransactions(transaction), violations, createSession()], emptyContext);
+            const result = compute([buildReports(report), buildTransactions(transaction), violations, {}, createSession()], emptyContext);
 
             expect(result.flaggedExpenses).toHaveLength(1);
             expect(result.flaggedExpenses.at(0)).toEqual({transactionID: 't1', reportID: 'r1'});
@@ -119,11 +120,11 @@ describe('flaggedExpenses derived value', () => {
             const transactions = [createTransaction('tA', 'r1'), createTransaction('tB', 'r1'), createTransaction('tC', 'r1')];
             const violations = buildViolations({
                 tA: [{type: CONST.VIOLATION_TYPES.VIOLATION, name: CONST.VIOLATIONS.OVER_CATEGORY_LIMIT}],
-                tB: [{type: CONST.VIOLATION_TYPES.VIOLATION, name: CONST.VIOLATIONS.MISSING_ATTENDEES}],
+                tB: [{type: CONST.VIOLATION_TYPES.VIOLATION, name: CONST.VIOLATIONS.MISSING_TAG}],
                 tC: [{type: CONST.VIOLATION_TYPES.VIOLATION, name: CONST.VIOLATIONS.MISSING_COMMENT}],
             });
 
-            const result = compute([buildReports(report), buildTransactions(...transactions), violations, createSession()], emptyContext);
+            const result = compute([buildReports(report), buildTransactions(...transactions), violations, {}, createSession()], emptyContext);
 
             expect(result.flaggedExpenses).toHaveLength(3);
             expect(result.flaggedExpenses.map((entry) => entry.transactionID).sort()).toEqual(['tA', 'tB', 'tC']);
@@ -136,7 +137,7 @@ describe('flaggedExpenses derived value', () => {
                 t1: [{type: CONST.VIOLATION_TYPES.VIOLATION, name: CONST.VIOLATIONS.MISSING_CATEGORY, showInReview: false}],
             });
 
-            const result = compute([buildReports(report), buildTransactions(transaction), violations, createSession()], emptyContext);
+            const result = compute([buildReports(report), buildTransactions(transaction), violations, {}, createSession()], emptyContext);
 
             expect(result.flaggedExpenses).toEqual([]);
         });
@@ -147,10 +148,10 @@ describe('flaggedExpenses derived value', () => {
             const violations = buildViolations({
                 tWarn: [{type: CONST.VIOLATION_TYPES.WARNING, name: CONST.VIOLATIONS.RTER}],
                 tNotice: [{type: CONST.VIOLATION_TYPES.NOTICE, name: CONST.VIOLATIONS.RECEIPT_REQUIRED}],
-                tShown: [{type: CONST.VIOLATION_TYPES.WARNING, name: CONST.VIOLATIONS.RTER, showInReview: true}],
+                tShown: [{type: CONST.VIOLATION_TYPES.NOTICE, name: CONST.VIOLATIONS.RECEIPT_REQUIRED, showInReview: true}],
             });
 
-            const result = compute([buildReports(report), buildTransactions(...transactions), violations, createSession()], emptyContext);
+            const result = compute([buildReports(report), buildTransactions(...transactions), violations, {}, createSession()], emptyContext);
 
             expect(result.flaggedExpenses).toEqual([{transactionID: 'tShown', reportID: 'r1'}]);
         });
@@ -170,7 +171,7 @@ describe('flaggedExpenses derived value', () => {
                 t2: [{type: CONST.VIOLATION_TYPES.VIOLATION, name: CONST.VIOLATIONS.MISSING_CATEGORY}],
             });
 
-            const result = compute([buildReports(draftReport, submittedReport), buildTransactions(draftTransaction, submittedTransaction), violations, createSession()], emptyContext);
+            const result = compute([buildReports(draftReport, submittedReport), buildTransactions(draftTransaction, submittedTransaction), violations, {}, createSession()], emptyContext);
 
             expect(result.flaggedExpenses).toHaveLength(1);
             expect(result.flaggedExpenses.at(0)).toEqual({transactionID: 't1', reportID: 'r1'});
@@ -192,7 +193,7 @@ describe('flaggedExpenses derived value', () => {
                 t2: [{type: CONST.VIOLATION_TYPES.VIOLATION, name: CONST.VIOLATIONS.MISSING_CATEGORY}],
             });
 
-            const result = compute([buildReports(expenseReport, chatReport), buildTransactions(t1, t2), violations, createSession()], emptyContext);
+            const result = compute([buildReports(expenseReport, chatReport), buildTransactions(t1, t2), violations, {}, createSession()], emptyContext);
 
             expect(result.flaggedExpenses).toHaveLength(1);
             expect(result.flaggedExpenses.at(0)).toEqual({transactionID: 't1', reportID: 'r1'});
@@ -205,7 +206,7 @@ describe('flaggedExpenses derived value', () => {
                 t1: [{type: CONST.VIOLATION_TYPES.VIOLATION, name: CONST.REPORT_VIOLATIONS.FIELD_REQUIRED} as TransactionViolations[number]],
             });
 
-            const result = compute([buildReports(report), buildTransactions(transaction), violations, createSession()], emptyContext);
+            const result = compute([buildReports(report), buildTransactions(transaction), violations, {}, createSession()], emptyContext);
 
             expect(result.flaggedExpenses).toEqual([]);
         });
@@ -217,11 +218,11 @@ describe('flaggedExpenses derived value', () => {
                 t1: [{type: CONST.VIOLATION_TYPES.VIOLATION, name: CONST.VIOLATIONS.MISSING_CATEGORY}],
             });
 
-            const flaggedResult = compute([buildReports(report), buildTransactions(transaction), flaggedViolations, createSession()], emptyContext);
+            const flaggedResult = compute([buildReports(report), buildTransactions(transaction), flaggedViolations, {}, createSession()], emptyContext);
             expect(flaggedResult.flaggedExpenses).toHaveLength(1);
 
             const clearedViolations = buildViolations({t1: []});
-            const clearedResult = compute([buildReports(report), buildTransactions(transaction), clearedViolations, createSession()], emptyContext);
+            const clearedResult = compute([buildReports(report), buildTransactions(transaction), clearedViolations, {}, createSession()], emptyContext);
             expect(clearedResult.flaggedExpenses).toEqual([]);
         });
 
@@ -229,7 +230,7 @@ describe('flaggedExpenses derived value', () => {
             const report = createExpenseReport('r1');
             const transaction = createTransaction('t1', 'r1');
 
-            const clearedResult = compute([buildReports(report), buildTransactions(transaction), buildViolations({t1: []}), createSession()], emptyContext);
+            const clearedResult = compute([buildReports(report), buildTransactions(transaction), buildViolations({t1: []}), {}, createSession()], emptyContext);
             expect(clearedResult.flaggedExpenses).toEqual([]);
 
             const reFlaggedResult = compute(
@@ -239,6 +240,7 @@ describe('flaggedExpenses derived value', () => {
                     buildViolations({
                         t1: [{type: CONST.VIOLATION_TYPES.VIOLATION, name: CONST.VIOLATIONS.MISSING_CATEGORY}],
                     }),
+                    {},
                     createSession(),
                 ],
                 emptyContext,
@@ -257,7 +259,7 @@ describe('flaggedExpenses derived value', () => {
                 t2: [{type: CONST.VIOLATION_TYPES.VIOLATION, name: CONST.VIOLATIONS.MISSING_CATEGORY}],
             });
 
-            const result = compute([buildReports(ownReport, foreignReport), buildTransactions(ownTransaction, foreignTransaction), violations, createSession()], emptyContext);
+            const result = compute([buildReports(ownReport, foreignReport), buildTransactions(ownTransaction, foreignTransaction), violations, {}, createSession()], emptyContext);
 
             expect(result.flaggedExpenses).toHaveLength(1);
             expect(result.flaggedExpenses.at(0)).toEqual({transactionID: 't1', reportID: 'r1'});
@@ -270,7 +272,27 @@ describe('flaggedExpenses derived value', () => {
                 t1: [{type: CONST.VIOLATION_TYPES.VIOLATION, name: CONST.VIOLATIONS.MISSING_CATEGORY}],
             });
 
-            const result = compute([buildReports(report), buildTransactions(transaction), violations, {} as Session], emptyContext);
+            const result = compute([buildReports(report), buildTransactions(transaction), violations, {}, {} as Session], emptyContext);
+
+            expect(result.flaggedExpenses).toEqual([]);
+        });
+
+        it('excludes transactions when the current user dismissed the only reviewable violation', () => {
+            const report = createExpenseReport('r1');
+            const transaction = createTransaction('t1', 'r1', {
+                comment: {
+                    dismissedViolations: {
+                        [CONST.VIOLATIONS.MISSING_CATEGORY]: {
+                            [CURRENT_USER_EMAIL]: '2024-01-01',
+                        },
+                    },
+                },
+            });
+            const violations = buildViolations({
+                t1: [{type: CONST.VIOLATION_TYPES.VIOLATION, name: CONST.VIOLATIONS.MISSING_CATEGORY}],
+            });
+
+            const result = compute([buildReports(report), buildTransactions(transaction), violations, {}, createSession()], emptyContext);
 
             expect(result.flaggedExpenses).toEqual([]);
         });

From 781ab76bda50bcf27419ef336e00262afc0d6142 Mon Sep 17 00:00:00 2001
From: Issa Nimaga <inimaga@expensify.com>
Date: Mon, 8 Jun 2026 14:31:07 +0100
Subject: [PATCH 183/435] Fix draft pacing

---
 src/pages/inbox/usePusherDraftPacing.ts | 107 +++++++++++++++++++++++-
 1 file changed, 103 insertions(+), 4 deletions(-)

diff --git a/src/pages/inbox/usePusherDraftPacing.ts b/src/pages/inbox/usePusherDraftPacing.ts
index b1b0fdbf03af..56b45129cbb1 100644
--- a/src/pages/inbox/usePusherDraftPacing.ts
+++ b/src/pages/inbox/usePusherDraftPacing.ts
@@ -4,6 +4,7 @@ import {getReportChannelName} from '@libs/actions/Report';
 import Log from '@libs/Log';
 import Pusher from '@libs/Pusher';
 import type {ConciergeDraftEvent, ConciergeDraftEventsEvent} from '@libs/Pusher/types';
+import Visibility from '@libs/Visibility';
 import type {ConciergeDraft} from './conciergeDraftState';
 import {applyConciergeDraftEvent, getCachedDraft, getNextVisibleConciergeDraftMarkdown, setCachedDraft} from './conciergeDraftState';
 
@@ -13,6 +14,7 @@ type MutableRef<T> = {
 
 type PusherDraftPaceRefs = {
     completedPusherDraftEventRef: MutableRef<ConciergeDraftEvent | null>;
+    lastPaceTickTimeRef: MutableRef<number>;
     latestPusherDraftEventRef: MutableRef<ConciergeDraftEvent | null>;
     pusherPaceIntervalRef: MutableRef<ReturnType<typeof setInterval> | null>;
     queuedPusherDraftEventsRef: MutableRef<ConciergeDraftEvent[]>;
@@ -66,7 +68,15 @@ function stopPusherDraftPace(runtime: PusherDraftPaceRefs) {
 }
 
 function resetPusherDraftPace(runtime: PusherDraftPaceRefs) {
-    const {completedPusherDraftEventRef, latestPusherDraftEventRef, queuedPusherDraftEventsRef, visibleBodyMarkdownRef, visibleSourceMarkdownRef, visibleSourceOffsetRef} = runtime;
+    const {
+        completedPusherDraftEventRef,
+        lastPaceTickTimeRef,
+        latestPusherDraftEventRef,
+        queuedPusherDraftEventsRef,
+        visibleBodyMarkdownRef,
+        visibleSourceMarkdownRef,
+        visibleSourceOffsetRef,
+    } = runtime;
 
     stopPusherDraftPace(runtime);
     latestPusherDraftEventRef.current = null;
@@ -75,6 +85,7 @@ function resetPusherDraftPace(runtime: PusherDraftPaceRefs) {
     visibleBodyMarkdownRef.current = '';
     visibleSourceMarkdownRef.current = '';
     visibleSourceOffsetRef.current = 0;
+    lastPaceTickTimeRef.current = 0;
 }
 
 function clearCachedPusherDraft(runtime: PusherDraftPacingRuntime) {
@@ -150,7 +161,15 @@ function publishVisibleEvent(
 }
 
 function tickPacing(runtime: PusherDraftPacingRuntime) {
-    const {completedPusherDraftEventRef, latestPusherDraftEventRef, queuedPusherDraftEventsRef, visibleBodyMarkdownRef, visibleSourceMarkdownRef, visibleSourceOffsetRef} = runtime;
+    const {
+        completedPusherDraftEventRef,
+        lastPaceTickTimeRef,
+        latestPusherDraftEventRef,
+        queuedPusherDraftEventsRef,
+        visibleBodyMarkdownRef,
+        visibleSourceMarkdownRef,
+        visibleSourceOffsetRef,
+    } = runtime;
     const latestEvent = latestPusherDraftEventRef.current;
     const targetBodyMarkdown = latestEvent?.bodyMarkdown ?? '';
 
@@ -161,11 +180,39 @@ function tickPacing(runtime: PusherDraftPacingRuntime) {
 
     const completedEvent = completedPusherDraftEventRef.current;
     const hasQueuedTarget = queuedPusherDraftEventsRef.current.length > 0;
-    const nextVisibleMarkdown = getNextVisibleConciergeDraftMarkdown(visibleBodyMarkdownRef.current, targetBodyMarkdown, visibleSourceOffsetRef.current, visibleSourceMarkdownRef.current);
+    const now = Date.now();
+    const elapsed = lastPaceTickTimeRef.current ? Math.max(0, now - lastPaceTickTimeRef.current) : PUSHER_DRAFT_PACE_INTERVAL_MS;
+    const elapsedIntervals = Math.floor(elapsed / PUSHER_DRAFT_PACE_INTERVAL_MS);
+    const unitsToReveal = Math.max(1, elapsedIntervals);
+    let revealedUnits = 0;
+    let nextVisibleMarkdown = {
+        bodyMarkdown: visibleBodyMarkdownRef.current,
+        sourceMarkdown: visibleSourceMarkdownRef.current,
+        sourceOffset: visibleSourceOffsetRef.current,
+    };
+
+    while (revealedUnits < unitsToReveal && nextVisibleMarkdown.sourceOffset < targetBodyMarkdown.length) {
+        const advancedVisibleMarkdown = getNextVisibleConciergeDraftMarkdown(
+            nextVisibleMarkdown.bodyMarkdown,
+            targetBodyMarkdown,
+            nextVisibleMarkdown.sourceOffset,
+            nextVisibleMarkdown.sourceMarkdown,
+        );
+
+        if (advancedVisibleMarkdown.sourceOffset <= nextVisibleMarkdown.sourceOffset) {
+            nextVisibleMarkdown = advancedVisibleMarkdown;
+            break;
+        }
+
+        nextVisibleMarkdown = advancedVisibleMarkdown;
+        revealedUnits += 1;
+    }
 
     if (nextVisibleMarkdown.bodyMarkdown !== visibleBodyMarkdownRef.current || nextVisibleMarkdown.sourceOffset !== visibleSourceOffsetRef.current) {
         const isTargetFullyVisible = nextVisibleMarkdown.sourceOffset >= targetBodyMarkdown.length;
         const status = completedEvent && !hasQueuedTarget && isTargetFullyVisible ? 'completed' : 'updated';
+        lastPaceTickTimeRef.current =
+            isTargetFullyVisible || elapsedIntervals === 0 || revealedUnits < unitsToReveal ? now : lastPaceTickTimeRef.current + unitsToReveal * PUSHER_DRAFT_PACE_INTERVAL_MS;
         publishVisibleEvent(runtime, status === 'completed' && completedEvent ? completedEvent : latestEvent, nextVisibleMarkdown, status);
 
         if (status === 'completed') {
@@ -175,6 +222,8 @@ function tickPacing(runtime: PusherDraftPacingRuntime) {
         return;
     }
 
+    lastPaceTickTimeRef.current = now;
+
     if (promoteQueuedPusherDraftTarget(runtime)) {
         startPusherDraftPace(runtime);
         return;
@@ -189,12 +238,13 @@ function tickPacing(runtime: PusherDraftPacingRuntime) {
 }
 
 function startPusherDraftPace(runtime: PusherDraftPacingRuntime) {
-    const {pusherPaceIntervalRef} = runtime;
+    const {lastPaceTickTimeRef, pusherPaceIntervalRef} = runtime;
 
     if (pusherPaceIntervalRef.current) {
         return;
     }
 
+    lastPaceTickTimeRef.current = Date.now();
     pusherPaceIntervalRef.current = setInterval(() => tickPacing(runtime), PUSHER_DRAFT_PACE_INTERVAL_MS);
 }
 
@@ -202,6 +252,38 @@ function getNewestPusherDraftTarget(runtime: PusherDraftPacingRuntime): Concierg
     return runtime.queuedPusherDraftEventsRef.current.at(-1) ?? runtime.latestPusherDraftEventRef.current;
 }
 
+function revealFullPusherDraftTarget(runtime: PusherDraftPacingRuntime) {
+    const {completedPusherDraftEventRef, lastPaceTickTimeRef, latestPusherDraftEventRef, queuedPusherDraftEventsRef} = runtime;
+    const newestTarget = getNewestPusherDraftTarget(runtime);
+    const completedEvent = completedPusherDraftEventRef.current;
+
+    lastPaceTickTimeRef.current = Date.now();
+    stopPusherDraftPace(runtime);
+
+    if (!newestTarget?.bodyMarkdown) {
+        if (completedEvent) {
+            publishVisibleEvent(runtime, completedEvent, undefined, 'completed');
+            completedPusherDraftEventRef.current = null;
+        }
+        return;
+    }
+
+    const targetBodyMarkdown = newestTarget.bodyMarkdown;
+    latestPusherDraftEventRef.current = newestTarget;
+    queuedPusherDraftEventsRef.current = [];
+
+    publishVisibleEvent(
+        runtime,
+        completedEvent ?? newestTarget,
+        {bodyMarkdown: targetBodyMarkdown, sourceMarkdown: targetBodyMarkdown, sourceOffset: targetBodyMarkdown.length},
+        completedEvent ? 'completed' : 'updated',
+    );
+
+    if (completedEvent) {
+        completedPusherDraftEventRef.current = null;
+    }
+}
+
 function queuePusherDraftTargets(runtime: PusherDraftPacingRuntime, events: ConciergeDraftEvent[]) {
     const {queuedPusherDraftEventsRef} = runtime;
     let newestTarget = getNewestPusherDraftTarget(runtime);
@@ -449,12 +531,14 @@ function usePusherDraftPacing(reportID: string) {
     const latestPusherDraftEventRef = useRef<ConciergeDraftEvent | null>(buildPusherDraftEventFromCachedDraft(reportID, draft));
     const queuedPusherDraftEventsRef = useRef<ConciergeDraftEvent[]>(draft?.pusherQueuedTargetEvents ?? []);
     const completedPusherDraftEventRef = useRef<ConciergeDraftEvent | null>(draft?.pusherPendingCompletionEvent ?? null);
+    const lastPaceTickTimeRef = useRef(0);
     const pusherPaceIntervalRef = useRef<ReturnType<typeof setInterval> | null>(null);
 
     const clearDraft = () => {
         clearCachedPusherDraft({
             completedPusherDraftEventRef,
             currentDraftRef,
+            lastPaceTickTimeRef,
             latestPusherDraftEventRef,
             pusherPaceIntervalRef,
             queuedPusherDraftEventsRef,
@@ -470,6 +554,7 @@ function usePusherDraftPacing(reportID: string) {
     const dispatchLocalDraftEvent = (event: ConciergeDraftEvent) => {
         resetPusherDraftPace({
             completedPusherDraftEventRef,
+            lastPaceTickTimeRef,
             latestPusherDraftEventRef,
             pusherPaceIntervalRef,
             queuedPusherDraftEventsRef,
@@ -489,6 +574,7 @@ function usePusherDraftPacing(reportID: string) {
         const runtime = {
             completedPusherDraftEventRef,
             currentDraftRef,
+            lastPaceTickTimeRef,
             latestPusherDraftEventRef,
             pusherPaceIntervalRef,
             queuedPusherDraftEventsRef,
@@ -530,8 +616,21 @@ function usePusherDraftPacing(reportID: string) {
         });
 
         resumeCachedPusherDraftPace(runtime);
+        const unsubscribeVisibility = Visibility.onVisibilityChange(() => {
+            if (completedPusherDraftEventRef.current) {
+                revealFullPusherDraftTarget(runtime);
+                return;
+            }
+
+            if (!Visibility.isVisible() || !pusherPaceIntervalRef.current) {
+                return;
+            }
+
+            tickPacing(runtime);
+        });
 
         return () => {
+            unsubscribeVisibility();
             stopPusherDraftPace(runtime);
             for (const subscription of subscriptions) {
                 subscription.unsubscribe();

From dfc4b80b36f0e517e371b8610c21ac59e4db09a8 Mon Sep 17 00:00:00 2001
From: Issa Nimaga <inimaga@expensify.com>
Date: Mon, 8 Jun 2026 14:31:15 +0100
Subject: [PATCH 184/435] Test draft pacing

---
 .../inbox/ConciergeDraftContext.test.tsx      | 109 ++++++++++++++++++
 1 file changed, 109 insertions(+)

diff --git a/tests/unit/pages/inbox/ConciergeDraftContext.test.tsx b/tests/unit/pages/inbox/ConciergeDraftContext.test.tsx
index 8adbc3acbbd8..121048520e17 100644
--- a/tests/unit/pages/inbox/ConciergeDraftContext.test.tsx
+++ b/tests/unit/pages/inbox/ConciergeDraftContext.test.tsx
@@ -25,12 +25,30 @@ jest.mock('@libs/actions/Report', () => ({
     getReportChannelName: (reportID: string) => `private-report-${reportID}`,
 }));
 
+let mockIsVisible = true;
+const mockVisibilityCallbacks = new Set<() => void>();
+
+jest.mock('@libs/Visibility', () => ({
+    __esModule: true,
+    default: {
+        hasFocus: jest.fn(() => true),
+        isVisible: jest.fn(() => mockIsVisible),
+        onVisibilityChange: jest.fn((callback: () => void) => {
+            mockVisibilityCallbacks.add(callback);
+            return () => {
+                mockVisibilityCallbacks.delete(callback);
+            };
+        }),
+    },
+}));
+
 const REPORT_ID = '123';
 const REPORT_ACTION_ID = '456';
 const CREATED = '2026-04-03 10:00:00.000';
 const STREAM_SESSION_ID = 'stream-session-1';
 const TARGET_BODY_MARKDOWN = 'Hello';
 const COMPLETED_BODY_MARKDOWN = 'Hello world';
+const NEXT_BODY_MARKDOWN = 'HelloWorld';
 const FINAL_RENDERED_HTML = '<comment>Server final response</comment>';
 
 type MockPusherSubscribe = jest.MockedFunction<
@@ -80,6 +98,13 @@ function emitPusherEvent(eventType: string, event: ConciergeDraftEvent | Concier
     callback(event);
 }
 
+function triggerVisibilityChange(isVisible: boolean) {
+    mockIsVisible = isVisible;
+    for (const callback of mockVisibilityCallbacks) {
+        callback();
+    }
+}
+
 describe('ConciergeDraftContext', () => {
     beforeAll(() => {
         Onyx.init({keys: ONYXKEYS});
@@ -87,6 +112,8 @@ describe('ConciergeDraftContext', () => {
 
     beforeEach(async () => {
         getMockPusherSubscribe().mockClear();
+        mockIsVisible = true;
+        mockVisibilityCallbacks.clear();
         setCachedDraft(REPORT_ID, null);
         await Onyx.clear();
         await Onyx.set(ONYXKEYS.CONCIERGE_REPORT_ID, REPORT_ID);
@@ -95,6 +122,7 @@ describe('ConciergeDraftContext', () => {
 
     afterEach(async () => {
         setCachedDraft(REPORT_ID, null);
+        jest.restoreAllMocks();
         await Onyx.clear();
     });
 
@@ -165,6 +193,87 @@ describe('ConciergeDraftContext', () => {
         unmount();
     });
 
+    it('catches up paced Pusher drafts from elapsed time when visibility returns', async () => {
+        let now = 1000;
+        jest.spyOn(Date, 'now').mockImplementation(() => now);
+        const wrapper = ({children}: PropsWithChildren) => <ConciergeDraftProvider reportID={REPORT_ID}>{children}</ConciergeDraftProvider>;
+        const {result, unmount} = renderHook(() => useConciergeDraft(), {wrapper});
+
+        await waitFor(() => {
+            expect(Pusher.subscribe).toHaveBeenCalledTimes(6);
+        });
+
+        act(() => {
+            emitPusherEvent(Pusher.TYPE.CONCIERGE_DRAFT_UPDATED, createDraftEvent(TARGET_BODY_MARKDOWN));
+        });
+        expect(getFirstMessageText(result.current.draftReportAction)).toBe('H');
+
+        act(() => {
+            triggerVisibilityChange(false);
+        });
+
+        now += 40;
+        act(() => {
+            triggerVisibilityChange(true);
+        });
+
+        expect(getFirstMessageText(result.current.draftReportAction)).toBe('Hello');
+
+        act(() => {
+            emitPusherEvent(Pusher.TYPE.CONCIERGE_DRAFT_UPDATED, createDraftEvent(NEXT_BODY_MARKDOWN, {sequence: 2}));
+        });
+        expect(getFirstMessageText(result.current.draftReportAction)).toBe('HelloW');
+
+        now += 10;
+        act(() => {
+            triggerVisibilityChange(true);
+        });
+
+        expect(getFirstMessageText(result.current.draftReportAction)).toBe('HelloWo');
+
+        unmount();
+    });
+
+    it('applies buffered completed Pusher drafts when visibility returns', async () => {
+        const wrapper = ({children}: PropsWithChildren) => <ConciergeDraftProvider reportID={REPORT_ID}>{children}</ConciergeDraftProvider>;
+        const {result, unmount} = renderHook(() => useConciergeDraft(), {wrapper});
+
+        await waitFor(() => {
+            expect(Pusher.subscribe).toHaveBeenCalledTimes(6);
+        });
+
+        act(() => {
+            triggerVisibilityChange(false);
+        });
+        act(() => {
+            emitPusherEvent(Pusher.TYPE.CONCIERGE_DRAFT_UPDATED, createDraftEvent(COMPLETED_BODY_MARKDOWN));
+        });
+        act(() => {
+            emitPusherEvent(
+                Pusher.TYPE.CONCIERGE_DRAFT_COMPLETED,
+                createDraftEvent('', {
+                    sequence: 2,
+                    status: 'completed',
+                    bodyMarkdown: undefined,
+                    finalRenderedHTML: FINAL_RENDERED_HTML,
+                }),
+            );
+        });
+
+        expect(getFirstMessageText(result.current.draftReportAction)).not.toBe('Server final response');
+        expect(result.current.isDraftPendingCompletion).toBe(true);
+
+        act(() => {
+            triggerVisibilityChange(true);
+        });
+
+        expect(getFirstMessageText(result.current.draftReportAction)).toBe('Server final response');
+        expect(result.current.isDraftPendingCompletion).toBe(false);
+        expect(getCachedDraft(REPORT_ID)?.pusherPendingCompletionEvent).toBeUndefined();
+
+        unmount();
+    });
+
     it('paces bodyMarkdown from a completed Pusher event before applying final HTML', async () => {
         const wrapper = ({children}: PropsWithChildren) => <ConciergeDraftProvider reportID={REPORT_ID}>{children}</ConciergeDraftProvider>;
         const {result, unmount} = renderHook(() => useConciergeDraft(), {wrapper});

From f52de533dc2e7fe946335d3ffc55df41ee3ea0de Mon Sep 17 00:00:00 2001
From: Adam Grzybowski <adam.grzybowski@swmansion.com>
Date: Mon, 8 Jun 2026 15:41:32 +0200
Subject: [PATCH 185/435] Fix cross-report carousel using wrong parent report

---
 .../MoneyRequestReportTransactionsNavigation.tsx      | 11 ++++++-----
 1 file changed, 6 insertions(+), 5 deletions(-)

diff --git a/src/components/MoneyRequestReportView/MoneyRequestReportTransactionsNavigation.tsx b/src/components/MoneyRequestReportView/MoneyRequestReportTransactionsNavigation.tsx
index b4c41f0352ed..5c0d06ffb66c 100644
--- a/src/components/MoneyRequestReportView/MoneyRequestReportTransactionsNavigation.tsx
+++ b/src/components/MoneyRequestReportView/MoneyRequestReportTransactionsNavigation.tsx
@@ -93,7 +93,8 @@ function MoneyRequestReportTransactionsNavigation({currentTransactionID, isFromR
         };
     }, [nextTransactionID, parentReportActions, prevTransactionID, transactionIDsList]);
 
-    const [parentReport] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${currentTransaction?.reportID}`);
+    const [prevParentReport] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${prevTransaction?.reportID}`);
+    const [nextParentReport] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${nextTransaction?.reportID}`);
     const [prevThreadReport] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${prevParentReportAction?.childReportID}`);
     const [nextThreadReport] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${nextParentReportAction?.childReportID}`);
 
@@ -132,7 +133,7 @@ function MoneyRequestReportTransactionsNavigation({currentTransactionID, isFromR
         }
         // We know that the next thread report exists, it just wasn't fetched to Onyx yet, so we set it optimistically.
         if (!nextThreadReport && nextThreadReportID) {
-            setOptimisticTransactionThread(nextThreadReportID, parentReport?.reportID, nextParentReportAction?.reportActionID, parentReport?.policyID);
+            setOptimisticTransactionThread(nextThreadReportID, nextParentReport?.reportID, nextParentReportAction?.reportActionID, nextParentReport?.policyID);
         }
         // The transaction thread doesn't exist yet, so we should create it
         if (!nextThreadReportID) {
@@ -141,7 +142,7 @@ function MoneyRequestReportTransactionsNavigation({currentTransactionID, isFromR
                 currentUserLogin: currentUserEmail ?? '',
                 currentUserAccountID,
                 betas,
-                iouReport: parentReport,
+                iouReport: nextParentReport,
                 iouReportAction: nextParentReportAction,
                 transaction: nextTransaction,
             });
@@ -168,7 +169,7 @@ function MoneyRequestReportTransactionsNavigation({currentTransactionID, isFromR
         }
         // We know that the previous thread report exists, it just wasn't fetched to Onyx yet, so we set it optimistically.
         if (!prevThreadReport && prevThreadReportID) {
-            setOptimisticTransactionThread(prevThreadReportID, parentReport?.reportID, prevParentReportAction?.reportActionID, parentReport?.policyID);
+            setOptimisticTransactionThread(prevThreadReportID, prevParentReport?.reportID, prevParentReportAction?.reportActionID, prevParentReport?.policyID);
         }
         // The transaction thread doesn't exist yet, so we should create it
         if (!prevThreadReportID) {
@@ -177,7 +178,7 @@ function MoneyRequestReportTransactionsNavigation({currentTransactionID, isFromR
                 currentUserLogin: currentUserEmail ?? '',
                 currentUserAccountID,
                 betas,
-                iouReport: parentReport,
+                iouReport: prevParentReport,
                 iouReportAction: prevParentReportAction,
                 transaction: prevTransaction,
             });

From ea1e21e4ae9371e2d508dde5c97c86999b47ea53 Mon Sep 17 00:00:00 2001
From: "Issa Nimaga (via MelvinBot)" <infra+melvinbot@expensify.com>
Date: Mon, 8 Jun 2026 14:08:23 +0000
Subject: [PATCH 186/435] Optimistically show Concierge thinking indicator on
 composer send

Co-authored-by: Issa Nimaga <inimaga@users.noreply.github.com>
---
 .../inbox/report/ReportActionCompose/useComposerSubmit.ts     | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/src/pages/inbox/report/ReportActionCompose/useComposerSubmit.ts b/src/pages/inbox/report/ReportActionCompose/useComposerSubmit.ts
index f7cdaac0c877..059293fa2ab3 100644
--- a/src/pages/inbox/report/ReportActionCompose/useComposerSubmit.ts
+++ b/src/pages/inbox/report/ReportActionCompose/useComposerSubmit.ts
@@ -15,6 +15,7 @@ import {rand64} from '@libs/NumberUtils';
 import {addDomainToShortMention} from '@libs/ParsingUtils';
 import {startSpan} from '@libs/telemetry/activeSpans';
 import {generateAccountID} from '@libs/UserUtils';
+import {useAgentZeroStatusActions} from '@pages/inbox/AgentZeroStatusContext';
 import {ActionListContext} from '@pages/inbox/ReportScreenContext';
 import {setIsComposerFullSize} from '@userActions/Report';
 import CONST from '@src/CONST';
@@ -33,6 +34,7 @@ function useComposerSubmit(reportID: string) {
     const [quickAction] = useOnyx(ONYXKEYS.NVP_QUICK_ACTION_GLOBAL_CREATE);
     const [isComposerFullSize = false] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT_IS_COMPOSER_FULL_SIZE}${reportID}`);
     const delegateAccountID = useDelegateAccountID();
+    const {kickoffWaitingIndicator} = useAgentZeroStatusActions();
 
     const {composerRef, attachmentFileRef, textRef} = useComposerMeta();
     const {clearComposer} = useComposerActions();
@@ -66,6 +68,7 @@ function useComposerSubmit(reportID: string) {
         }
 
         if (attachmentFileRef.current) {
+            kickoffWaitingIndicator();
             addAttachmentWithComment({
                 report: targetReport,
                 notifyReportID: reportID,
@@ -148,6 +151,7 @@ function useComposerSubmit(reportID: string) {
                 },
             });
         }
+        kickoffWaitingIndicator();
         addComment({
             report: targetReport,
             notifyReportID: reportID,

From 2e3bfd14e2d0790c940f4d17bad6c7f8ee737646 Mon Sep 17 00:00:00 2001
From: Alex Beaman <alexbeaman@expensify.com>
Date: Mon, 8 Jun 2026 08:12:46 -0600
Subject: [PATCH 187/435] Hide vendor row + block vendor RHP on invoices (Codex
 P2)

shouldShowVendor only excluded reimbursable expenses, so invoice
transactions (which are non-reimbursable) on a QBO + CC/DC + vendorMatching
workspace would surface the Vendor row and let users write comment.vendor
via the RHP. Vendor matching is scoped to non-reimbursable card expenses,
not invoices. Mirror shouldShowReimbursable's !isInvoice guard, and add
the same check to IOURequestStepVendor's not-found gate alongside the
existing isReimbursable defense in depth.
---
 src/components/ReportActionItem/MoneyRequestView.tsx | 2 +-
 src/pages/iou/request/step/IOURequestStepVendor.tsx  | 5 +++--
 2 files changed, 4 insertions(+), 3 deletions(-)

diff --git a/src/components/ReportActionItem/MoneyRequestView.tsx b/src/components/ReportActionItem/MoneyRequestView.tsx
index 3d58affe6781..454593f0f270 100644
--- a/src/components/ReportActionItem/MoneyRequestView.tsx
+++ b/src/components/ReportActionItem/MoneyRequestView.tsx
@@ -460,7 +460,7 @@ function MoneyRequestView({
 
     const transactionVendor = transaction?.comment?.vendor;
     const transactionVendorName = getQBOVendorByID(policy, transactionVendor?.externalID)?.name ?? '';
-    const shouldShowVendor = hasVendorFeature(policy, isBetaEnabled(CONST.BETAS.VENDOR_MATCHING)) && !(updatedTransaction?.reimbursable ?? !!transactionReimbursable);
+    const shouldShowVendor = hasVendorFeature(policy, isBetaEnabled(CONST.BETAS.VENDOR_MATCHING)) && !(updatedTransaction?.reimbursable ?? !!transactionReimbursable) && !isInvoice;
 
     const tripID = getTripIDFromTransactionParentReportID(parentReport?.parentReportID);
     const shouldShowViewTripDetails = hasReservationList(transaction) && !!tripID;
diff --git a/src/pages/iou/request/step/IOURequestStepVendor.tsx b/src/pages/iou/request/step/IOURequestStepVendor.tsx
index c67fa6b663c8..299acaecb61e 100644
--- a/src/pages/iou/request/step/IOURequestStepVendor.tsx
+++ b/src/pages/iou/request/step/IOURequestStepVendor.tsx
@@ -51,8 +51,9 @@ function IOURequestStepVendor({
 
     const isFeatureAvailable = hasVendorFeature(policy, isBetaEnabled(CONST.BETAS.VENDOR_MATCHING));
 
-    // Vendor is scoped to non-reimbursable expenses; block deep-link / stale-open access if the transaction is reimbursable.
+    // Vendor is scoped to non-reimbursable expenses on a policy expense chat; block deep-link / stale-open access if the transaction is reimbursable or is an invoice (invoices are non-reimbursable but don't route through the QBO CC vendor-matching flow).
     const isReimbursable = !!transaction?.reimbursable;
+    const isInvoice = iouType === CONST.IOU.TYPE.INVOICE;
     const vendors = useMemo(() => getQBOVendors(policy), [policy]);
     const currentVendorID = transaction?.comment?.vendor?.externalID;
 
@@ -82,7 +83,7 @@ function IOURequestStepVendor({
         return [clearRow, ...vendorRows];
     }, [vendors, currentVendorID, searchValue, translate]);
 
-    const shouldShowNotFoundPage = useShowNotFoundPageInIOUStep(action, iouType, reportActionID, report, transaction) || !isFeatureAvailable || isReimbursable;
+    const shouldShowNotFoundPage = useShowNotFoundPageInIOUStep(action, iouType, reportActionID, report, transaction) || !isFeatureAvailable || isReimbursable || isInvoice;
 
     const navigateBack = () => {
         Navigation.goBack();

From 9403f022d5900a7342f734ba3236a6abef52841e Mon Sep 17 00:00:00 2001
From: Adam Grzybowski <adam.grzybowski@swmansion.com>
Date: Mon, 8 Jun 2026 17:38:57 +0200
Subject: [PATCH 188/435] Remove unused getIOUActionForTransactionID import

---
 .../MoneyRequestReportTransactionList.tsx                       | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/components/MoneyRequestReportView/MoneyRequestReportTransactionList.tsx b/src/components/MoneyRequestReportView/MoneyRequestReportTransactionList.tsx
index 071119fb763d..8141d499b144 100644
--- a/src/components/MoneyRequestReportView/MoneyRequestReportTransactionList.tsx
+++ b/src/components/MoneyRequestReportView/MoneyRequestReportTransactionList.tsx
@@ -44,7 +44,7 @@ import {resolveTransactionCardFields} from '@libs/CardUtils';
 import {hasNonReimbursableTransactions, isBillableEnabledOnPolicy} from '@libs/MoneyRequestReportUtils';
 import {navigationRef} from '@libs/Navigation/Navigation';
 import {isPolicyTaxEnabled} from '@libs/PolicyUtils';
-import {getIOUActionForTransactionID, getOriginalMessage, isMoneyRequestAction} from '@libs/ReportActionsUtils';
+import {getOriginalMessage, isMoneyRequestAction} from '@libs/ReportActionsUtils';
 import {groupTransactionsByCategory, groupTransactionsByTag} from '@libs/ReportLayoutUtils';
 import {
     canAddTransaction,

From 68cb3fc02f3b5ae9fa5ab425325e465e07e964e6 Mon Sep 17 00:00:00 2001
From: Issa Nimaga <inimaga@expensify.com>
Date: Mon, 8 Jun 2026 17:41:11 +0100
Subject: [PATCH 189/435] Address review comments

---
 src/pages/inbox/usePusherDraftPacing.ts       | 32 ++++++++++++++--
 .../inbox/ConciergeDraftContext.test.tsx      | 37 ++++++++++++++++++-
 2 files changed, 63 insertions(+), 6 deletions(-)

diff --git a/src/pages/inbox/usePusherDraftPacing.ts b/src/pages/inbox/usePusherDraftPacing.ts
index 56b45129cbb1..4794b07ac8c5 100644
--- a/src/pages/inbox/usePusherDraftPacing.ts
+++ b/src/pages/inbox/usePusherDraftPacing.ts
@@ -160,6 +160,14 @@ function publishVisibleEvent(
     });
 }
 
+function getNextLastPaceTickTime(now: number, paceStartTime: number, elapsedIntervals: number, revealedUnits: number, shouldPreserveElapsedDebt: boolean): number {
+    if (!shouldPreserveElapsedDebt || elapsedIntervals === 0 || revealedUnits === 0) {
+        return now;
+    }
+
+    return Math.min(now, paceStartTime + revealedUnits * PUSHER_DRAFT_PACE_INTERVAL_MS);
+}
+
 function tickPacing(runtime: PusherDraftPacingRuntime) {
     const {
         completedPusherDraftEventRef,
@@ -184,6 +192,7 @@ function tickPacing(runtime: PusherDraftPacingRuntime) {
     const elapsed = lastPaceTickTimeRef.current ? Math.max(0, now - lastPaceTickTimeRef.current) : PUSHER_DRAFT_PACE_INTERVAL_MS;
     const elapsedIntervals = Math.floor(elapsed / PUSHER_DRAFT_PACE_INTERVAL_MS);
     const unitsToReveal = Math.max(1, elapsedIntervals);
+    const paceStartTime = lastPaceTickTimeRef.current || now - elapsedIntervals * PUSHER_DRAFT_PACE_INTERVAL_MS;
     let revealedUnits = 0;
     let nextVisibleMarkdown = {
         bodyMarkdown: visibleBodyMarkdownRef.current,
@@ -211,24 +220,39 @@ function tickPacing(runtime: PusherDraftPacingRuntime) {
     if (nextVisibleMarkdown.bodyMarkdown !== visibleBodyMarkdownRef.current || nextVisibleMarkdown.sourceOffset !== visibleSourceOffsetRef.current) {
         const isTargetFullyVisible = nextVisibleMarkdown.sourceOffset >= targetBodyMarkdown.length;
         const status = completedEvent && !hasQueuedTarget && isTargetFullyVisible ? 'completed' : 'updated';
-        lastPaceTickTimeRef.current =
-            isTargetFullyVisible || elapsedIntervals === 0 || revealedUnits < unitsToReveal ? now : lastPaceTickTimeRef.current + unitsToReveal * PUSHER_DRAFT_PACE_INTERVAL_MS;
+        lastPaceTickTimeRef.current = getNextLastPaceTickTime(
+            now,
+            paceStartTime,
+            elapsedIntervals,
+            revealedUnits,
+            (isTargetFullyVisible && hasQueuedTarget) || (!isTargetFullyVisible && revealedUnits >= elapsedIntervals),
+        );
         publishVisibleEvent(runtime, status === 'completed' && completedEvent ? completedEvent : latestEvent, nextVisibleMarkdown, status);
 
         if (status === 'completed') {
             completedPusherDraftEventRef.current = null;
             stopPusherDraftPace(runtime);
         }
+
+        if (isTargetFullyVisible && hasQueuedTarget && revealedUnits < unitsToReveal && promoteQueuedPusherDraftTarget(runtime)) {
+            tickPacing(runtime);
+        }
         return;
     }
 
-    lastPaceTickTimeRef.current = now;
-
     if (promoteQueuedPusherDraftTarget(runtime)) {
+        if (elapsedIntervals > 0) {
+            tickPacing(runtime);
+            return;
+        }
+
+        lastPaceTickTimeRef.current = now;
         startPusherDraftPace(runtime);
         return;
     }
 
+    lastPaceTickTimeRef.current = now;
+
     if (completedEvent) {
         publishVisibleEvent(runtime, completedEvent, {bodyMarkdown: targetBodyMarkdown, sourceMarkdown: targetBodyMarkdown, sourceOffset: targetBodyMarkdown.length}, 'completed');
         completedPusherDraftEventRef.current = null;
diff --git a/tests/unit/pages/inbox/ConciergeDraftContext.test.tsx b/tests/unit/pages/inbox/ConciergeDraftContext.test.tsx
index 121048520e17..77d743aeac69 100644
--- a/tests/unit/pages/inbox/ConciergeDraftContext.test.tsx
+++ b/tests/unit/pages/inbox/ConciergeDraftContext.test.tsx
@@ -50,6 +50,7 @@ const TARGET_BODY_MARKDOWN = 'Hello';
 const COMPLETED_BODY_MARKDOWN = 'Hello world';
 const NEXT_BODY_MARKDOWN = 'HelloWorld';
 const FINAL_RENDERED_HTML = '<comment>Server final response</comment>';
+const PUSHER_DRAFT_PACE_INTERVAL_MS = 10;
 
 type MockPusherSubscribe = jest.MockedFunction<
     (
@@ -212,7 +213,7 @@ describe('ConciergeDraftContext', () => {
             triggerVisibilityChange(false);
         });
 
-        now += 40;
+        now += 4 * PUSHER_DRAFT_PACE_INTERVAL_MS;
         act(() => {
             triggerVisibilityChange(true);
         });
@@ -224,7 +225,7 @@ describe('ConciergeDraftContext', () => {
         });
         expect(getFirstMessageText(result.current.draftReportAction)).toBe('HelloW');
 
-        now += 10;
+        now += PUSHER_DRAFT_PACE_INTERVAL_MS;
         act(() => {
             triggerVisibilityChange(true);
         });
@@ -234,6 +235,38 @@ describe('ConciergeDraftContext', () => {
         unmount();
     });
 
+    it('preserves elapsed catch-up across queued Pusher targets when visibility returns', async () => {
+        let now = 1000;
+        jest.spyOn(Date, 'now').mockImplementation(() => now);
+        const wrapper = ({children}: PropsWithChildren) => <ConciergeDraftProvider reportID={REPORT_ID}>{children}</ConciergeDraftProvider>;
+        const {result, unmount} = renderHook(() => useConciergeDraft(), {wrapper});
+
+        await waitFor(() => {
+            expect(Pusher.subscribe).toHaveBeenCalledTimes(6);
+        });
+
+        act(() => {
+            emitPusherEvent(Pusher.TYPE.CONCIERGE_DRAFT_UPDATED, createDraftEvent(TARGET_BODY_MARKDOWN));
+        });
+        expect(getFirstMessageText(result.current.draftReportAction)).toBe('H');
+
+        act(() => {
+            triggerVisibilityChange(false);
+        });
+        act(() => {
+            emitPusherEvent(Pusher.TYPE.CONCIERGE_DRAFT_UPDATED, createDraftEvent(NEXT_BODY_MARKDOWN, {sequence: 2}));
+        });
+
+        now += 9 * PUSHER_DRAFT_PACE_INTERVAL_MS;
+        act(() => {
+            triggerVisibilityChange(true);
+        });
+
+        expect(getFirstMessageText(result.current.draftReportAction)).toBe(NEXT_BODY_MARKDOWN);
+
+        unmount();
+    });
+
     it('applies buffered completed Pusher drafts when visibility returns', async () => {
         const wrapper = ({children}: PropsWithChildren) => <ConciergeDraftProvider reportID={REPORT_ID}>{children}</ConciergeDraftProvider>;
         const {result, unmount} = renderHook(() => useConciergeDraft(), {wrapper});

From 3bc0b2f0032b660270ebbcf4ba39f52b7c5ba587 Mon Sep 17 00:00:00 2001
From: Jack Senyitko <jsenyitko@expensify.com>
Date: Mon, 8 Jun 2026 15:10:21 -0400
Subject: [PATCH 190/435] fiux lint

---
 src/pages/settings/Wallet/ExpensifyCardPage/index.tsx           | 1 -
 .../expensifyCard/WorkspaceExpensifyCardDetailsPage.tsx         | 2 --
 .../expensifyCard/issueNew/spendRules/SetSpendRulesStep.tsx     | 2 --
 3 files changed, 5 deletions(-)

diff --git a/src/pages/settings/Wallet/ExpensifyCardPage/index.tsx b/src/pages/settings/Wallet/ExpensifyCardPage/index.tsx
index 22185e9e015f..76ec108f8d55 100644
--- a/src/pages/settings/Wallet/ExpensifyCardPage/index.tsx
+++ b/src/pages/settings/Wallet/ExpensifyCardPage/index.tsx
@@ -22,7 +22,6 @@ import ScrollView from '@components/ScrollView';
 import Text from '@components/Text';
 import {useCurrencyListActions} from '@hooks/useCurrencyList';
 import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails';
-import useEnvironment from '@hooks/useEnvironment';
 import {useMemoizedLazyExpensifyIcons} from '@hooks/useLazyAsset';
 import useLocalize from '@hooks/useLocalize';
 import useNetwork from '@hooks/useNetwork';
diff --git a/src/pages/workspace/expensifyCard/WorkspaceExpensifyCardDetailsPage.tsx b/src/pages/workspace/expensifyCard/WorkspaceExpensifyCardDetailsPage.tsx
index e89573bcdf4f..c79f93c8a175 100644
--- a/src/pages/workspace/expensifyCard/WorkspaceExpensifyCardDetailsPage.tsx
+++ b/src/pages/workspace/expensifyCard/WorkspaceExpensifyCardDetailsPage.tsx
@@ -24,7 +24,6 @@ import {useCurrencyListActions} from '@hooks/useCurrencyList';
 import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails';
 import useDefaultFundID from '@hooks/useDefaultFundID';
 import useDynamicBackPath from '@hooks/useDynamicBackPath';
-import useEnvironment from '@hooks/useEnvironment';
 import useExpensifyCardFeeds from '@hooks/useExpensifyCardFeeds';
 import {useMemoizedLazyExpensifyIcons, useMemoizedLazyIllustrations} from '@hooks/useLazyAsset';
 import useLocalize from '@hooks/useLocalize';
@@ -75,7 +74,6 @@ function getLimitHintTranslationKey(limitType?: string): LimitHintTranslationKey
 }
 
 function WorkspaceExpensifyCardDetailsPage({route}: WorkspaceExpensifyCardDetailsPageProps) {
-    const {isProduction} = useEnvironment();
     const navigation = useNavigation<NavigationProp<SettingsNavigatorParamList>>();
     const {policyID, cardID, backTo} = route.params;
     const backPath = useDynamicBackPath(DYNAMIC_ROUTES.EXPENSIFY_CARD_DETAILS.path);
diff --git a/src/pages/workspace/expensifyCard/issueNew/spendRules/SetSpendRulesStep.tsx b/src/pages/workspace/expensifyCard/issueNew/spendRules/SetSpendRulesStep.tsx
index 12d272ae36b0..f0ba776f0de6 100644
--- a/src/pages/workspace/expensifyCard/issueNew/spendRules/SetSpendRulesStep.tsx
+++ b/src/pages/workspace/expensifyCard/issueNew/spendRules/SetSpendRulesStep.tsx
@@ -14,7 +14,6 @@ import SpendRuleRestrictionTypeToggle from '@components/SpendRules/SpendRuleRest
 import TabSelectorBase from '@components/TabSelector/TabSelectorBase';
 import Text from '@components/Text';
 import useDefaultFundID from '@hooks/useDefaultFundID';
-import useEnvironment from '@hooks/useEnvironment';
 import {useMemoizedLazyExpensifyIcons} from '@hooks/useLazyAsset';
 import useLocalize from '@hooks/useLocalize';
 import useOnyx from '@hooks/useOnyx';
@@ -45,7 +44,6 @@ type SetSpendRulesStepProps = {
 function SetSpendRulesStep({policyID, stepNames, startStepIndex}: SetSpendRulesStepProps) {
     const styles = useThemeStyles();
     const {translate} = useLocalize();
-    const {isProduction} = useEnvironment();
     const personalDetails = usePersonalDetails();
     const domainAccountID = useDefaultFundID(policyID);
     const icons = useMemoizedLazyExpensifyIcons(['Copy', 'Pencil']);

From 5178628dbd2397b91aafa034d510daf189b95e2b Mon Sep 17 00:00:00 2001
From: Chuck Dries <chuck@expensify.com>
Date: Mon, 8 Jun 2026 14:28:34 -0700
Subject: [PATCH 191/435] Fix canJoinChat when policy.employeeList is empty

---
 src/libs/PolicyUtils.ts | 1 +
 src/libs/ReportUtils.ts | 3 +--
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/libs/PolicyUtils.ts b/src/libs/PolicyUtils.ts
index 2f04ad026d49..5be8449f5c59 100644
--- a/src/libs/PolicyUtils.ts
+++ b/src/libs/PolicyUtils.ts
@@ -552,6 +552,7 @@ function shouldShowPolicy(policy: OnyxEntry<Policy>, shouldShowPendingDeletePoli
 
 /**
  * Checks if a specific user is a member of the policy.
+ * Note that employeeList can be blank when the policy is not the user's default/active policy
  */
 function isPolicyMember(policy: OnyxEntry<Policy>, userLogin: string | undefined): boolean {
     return !!policy && !!userLogin && (!!policy.employeeList?.[userLogin] || policy.owner === userLogin);
diff --git a/src/libs/ReportUtils.ts b/src/libs/ReportUtils.ts
index 2408ee587974..577457583fd6 100644
--- a/src/libs/ReportUtils.ts
+++ b/src/libs/ReportUtils.ts
@@ -166,7 +166,6 @@ import {
     isPendingDeletePolicy,
     isPolicyAdmin as isPolicyAdminPolicyUtils,
     isPolicyAuditor,
-    isPolicyMember,
     isPolicyMemberWithoutPendingDelete,
     isPolicyOwner,
     isSubmitAndClose,
@@ -11276,7 +11275,7 @@ function canJoinChat(
     }
 
     // For restricted visibility rooms, the user must be a workspace member to join
-    if (isUserCreatedPolicyRoom(report) && report?.visibility === CONST.REPORT.VISIBILITY.RESTRICTED && !isPolicyMember(policy, deprecatedCurrentUserEmail)) {
+    if (isUserCreatedPolicyRoom(report) && report?.visibility === CONST.REPORT.VISIBILITY.RESTRICTED && !getPolicyRole(policy, deprecatedCurrentUserEmail)) {
         return false;
     }
 

From 42ae8da64fc18c76d9dee64e5a813d4acf324f21 Mon Sep 17 00:00:00 2001
From: Chuck Dries <chuck@expensify.com>
Date: Mon, 8 Jun 2026 15:11:25 -0700
Subject: [PATCH 192/435] Update ReportUtilsTest policyWithoutCurrentUser

---
 tests/unit/ReportUtilsTest.ts | 23 +++++++----------------
 1 file changed, 7 insertions(+), 16 deletions(-)

diff --git a/tests/unit/ReportUtilsTest.ts b/tests/unit/ReportUtilsTest.ts
index 5baa16bbee83..04090ee2b483 100644
--- a/tests/unit/ReportUtilsTest.ts
+++ b/tests/unit/ReportUtilsTest.ts
@@ -10419,26 +10419,17 @@ describe('ReportUtils', () => {
             const policyID = '123456';
             await Onyx.set(ONYXKEYS.SESSION, {email: currentUserEmail, accountID: currentUserAccountID});
 
-            const policyWithoutCurrentUser: Policy = {
-                ...createRandomPolicy(1),
-                id: policyID,
-                employeeList: {
-                    'employee@test.com': {
-                        role: CONST.POLICY.ROLE.USER,
-                        errors: {},
-                    },
-                },
-            };
+            // policy.role holds the current user's own role and is synced for every workspace they belong to,
+            // even when employeeList has not loaded (the roster is only fully synced for the active workspace).
+            // A non-member therefore has no role, so membership is determined from policy.role.
+            const policyWithoutCurrentUser: Policy = {...createRandomPolicy(1), id: policyID, employeeList: {}};
+            delete (policyWithoutCurrentUser as Partial<Policy>).role;
 
             const policyWithCurrentUser: Policy = {
                 ...createRandomPolicy(2),
                 id: policyID,
-                employeeList: {
-                    [currentUserEmail]: {
-                        role: CONST.POLICY.ROLE.USER,
-                        errors: {},
-                    },
-                },
+                role: CONST.POLICY.ROLE.USER,
+                employeeList: {},
             };
 
             const restrictedReport: Report = {

From eedfb53ec1f3a51d679d5e22db3b60ff3f4dfd8a Mon Sep 17 00:00:00 2001
From: "Rushat Gabhane (via MelvinBot)" <infra+melvinbot@expensify.com>
Date: Mon, 8 Jun 2026 22:18:04 +0000
Subject: [PATCH 193/435] Fix: high contrast button label uses sign-in intent

Co-authored-by: Rushat Gabhane <rushatgabhane@users.noreply.github.com>
---
 src/components/HighContrastModeSwitcher.tsx | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/src/components/HighContrastModeSwitcher.tsx b/src/components/HighContrastModeSwitcher.tsx
index 22332e1b220e..0fdf3581724f 100644
--- a/src/components/HighContrastModeSwitcher.tsx
+++ b/src/components/HighContrastModeSwitcher.tsx
@@ -18,10 +18,11 @@ function HighContrastModeSwitcher() {
     const styles = useThemeStyles();
     const {translate} = useLocalize();
     const [preferredTheme] = useOnyx(ONYXKEYS.PREFERRED_THEME);
+    const [highContrastIntent] = useOnyx(ONYXKEYS.SIGN_IN_HIGH_CONTRAST_INTENT);
     const icons = useMemoizedLazyExpensifyIcons(['Moon']);
 
     const currentTheme = preferredTheme ?? CONST.THEME.DEFAULT;
-    const isHighContrast = isHighContrastTheme(currentTheme);
+    const isHighContrast = highContrastIntent ?? isHighContrastTheme(currentTheme);
     const label = translate(isHighContrast ? 'themePage.disableHighContrast' : 'themePage.enableHighContrast');
 
     const toggleHighContrast = () => {

From 031aa66291dd824d74ec8ef8e6520b1b31bea1a2 Mon Sep 17 00:00:00 2001
From: Youssef Lourayad <youssef@expensify.com>
Date: Mon, 8 Jun 2026 23:50:35 +0000
Subject: [PATCH 194/435] Update empty view copy and add link to the "all" tab

---
 .../LHNOptionsList/LHNEmptyState.tsx          | 20 +++++++++++++++++++
 src/languages/de.ts                           |  4 ++++
 src/languages/en.ts                           |  4 ++++
 src/languages/es.ts                           |  4 ++++
 src/languages/fr.ts                           |  4 ++++
 src/languages/it.ts                           |  4 ++++
 src/languages/ja.ts                           |  4 ++++
 src/languages/nl.ts                           |  4 ++++
 src/languages/pl.ts                           |  4 ++++
 src/languages/pt-BR.ts                        |  4 ++++
 src/languages/zh-hans.ts                      |  4 ++++
 11 files changed, 60 insertions(+)

diff --git a/src/components/LHNOptionsList/LHNEmptyState.tsx b/src/components/LHNOptionsList/LHNEmptyState.tsx
index 40fed2097bc6..b4681315fc39 100644
--- a/src/components/LHNOptionsList/LHNEmptyState.tsx
+++ b/src/components/LHNOptionsList/LHNEmptyState.tsx
@@ -6,9 +6,11 @@ import Icon from '@components/Icon';
 import TextBlock from '@components/TextBlock';
 import {useMemoizedLazyExpensifyIcons} from '@hooks/useLazyAsset';
 import useLocalize from '@hooks/useLocalize';
+import {useSidebarOrderedReportsActions, useSidebarOrderedReportsState} from '@hooks/useSidebarOrderedReports';
 import useTheme from '@hooks/useTheme';
 import useThemeStyles from '@hooks/useThemeStyles';
 import variables from '@styles/variables';
+import CONST from '@src/CONST';
 import useEmptyLHNIllustration from './useEmptyLHNIllustration';
 
 function LHNEmptyState() {
@@ -17,6 +19,24 @@ function LHNEmptyState() {
     const {translate} = useLocalize();
     const expensifyIcons = useMemoizedLazyExpensifyIcons(['MagnifyingGlass', 'Plus']);
     const emptyLHNIllustration = useEmptyLHNIllustration();
+    const {activeTab} = useSidebarOrderedReportsState();
+    const {setActiveTab} = useSidebarOrderedReportsActions();
+
+    if (activeTab === CONST.INBOX_TAB.UNREAD || activeTab === CONST.INBOX_TAB.TODO) {
+        const title = activeTab === CONST.INBOX_TAB.UNREAD ? translate('common.emptyLHN.noUnreadChats') : translate('common.emptyLHN.noTodos');
+
+        return (
+            <BlockingView
+                {...(emptyLHNIllustration as BlockingViewProps)}
+                title={title}
+                subtitle={translate('common.emptyLHN.caughtUp')}
+                subtitleStyle={styles.textSupporting}
+                linkTranslationKey="common.emptyLHN.seeAllChats"
+                onLinkPress={() => setActiveTab(CONST.INBOX_TAB.ALL)}
+                accessibilityLabel={title}
+            />
+        );
+    }
 
     const subtitle = (
         <View style={[styles.alignItemsCenter, styles.flexRow, styles.justifyContentCenter, styles.flexWrap, styles.textAlignCenter]}>
diff --git a/src/languages/de.ts b/src/languages/de.ts
index c243612f1896..5b495c9da38f 100644
--- a/src/languages/de.ts
+++ b/src/languages/de.ts
@@ -354,6 +354,10 @@ const translations: TranslationDeepObject<typeof en> = {
             subtitleText1: 'Finde einen Chat über die',
             subtitleText2: 'Schaltfläche oben oder erstellen Sie etwas mit der',
             subtitleText3: 'Schaltfläche unten.',
+            noUnreadChats: 'Keine ungelesenen Chats',
+            noTodos: 'Keine Aufgaben',
+            caughtUp: 'Du bist auf dem neuesten Stand. Gut gemacht!',
+            seeAllChats: 'Alle Chats anzeigen',
         },
         businessName: 'Firmenname',
         clear: 'Löschen',
diff --git a/src/languages/en.ts b/src/languages/en.ts
index 5f4f51c6b94a..cf3ff8f64be4 100644
--- a/src/languages/en.ts
+++ b/src/languages/en.ts
@@ -369,6 +369,10 @@ const translations = {
             subtitleText1: 'Find a chat using the',
             subtitleText2: 'button above, or create something using the',
             subtitleText3: 'button below.',
+            noUnreadChats: 'No unread chats',
+            noTodos: 'No to-dos',
+            caughtUp: "You're all caught up. Well done!",
+            seeAllChats: 'See all chats',
         },
         businessName: 'Business name',
         clear: 'Clear',
diff --git a/src/languages/es.ts b/src/languages/es.ts
index af8e6ae47cf3..aee1f08afd8b 100644
--- a/src/languages/es.ts
+++ b/src/languages/es.ts
@@ -310,6 +310,10 @@ const translations: TranslationDeepObject<typeof en> = {
             subtitleText1: 'Encuentra un chat usando el botón',
             subtitleText2: 'o crea algo usando el botón',
             subtitleText3: '.',
+            noUnreadChats: 'No hay chats sin leer',
+            noTodos: 'No hay tareas pendientes',
+            caughtUp: '¡Estás al día. Bien hecho!',
+            seeAllChats: 'Ver todos los chats',
         },
         businessName: 'Nombre de la empresa',
         clear: 'Borrar',
diff --git a/src/languages/fr.ts b/src/languages/fr.ts
index 76fe9e0e5260..453ec2defa1b 100644
--- a/src/languages/fr.ts
+++ b/src/languages/fr.ts
@@ -353,6 +353,10 @@ const translations: TranslationDeepObject<typeof en> = {
             subtitleText1: 'Recherchez une discussion à l’aide de la',
             subtitleText2: 'bouton ci-dessus, ou créez quelque chose en utilisant le',
             subtitleText3: 'bouton ci-dessous.',
+            noUnreadChats: 'Aucun chat non lu',
+            noTodos: 'Aucune tâche',
+            caughtUp: 'Vous êtes à jour. Bien joué !',
+            seeAllChats: 'Voir tous les chats',
         },
         businessName: 'Nom de l’entreprise',
         clear: 'Effacer',
diff --git a/src/languages/it.ts b/src/languages/it.ts
index edb1c6739271..000fb6e227a7 100644
--- a/src/languages/it.ts
+++ b/src/languages/it.ts
@@ -354,6 +354,10 @@ const translations: TranslationDeepObject<typeof en> = {
             subtitleText1: 'Trova una chat usando la',
             subtitleText2: 'pulsante sopra oppure crea qualcosa utilizzando il',
             subtitleText3: 'pulsante qui sotto.',
+            noUnreadChats: 'Nessuna chat non letta',
+            noTodos: 'Nessuna attività',
+            caughtUp: 'Sei aggiornato. Ben fatto!',
+            seeAllChats: 'Vedi tutte le chat',
         },
         businessName: 'Nome azienda',
         clear: 'Pulisci',
diff --git a/src/languages/ja.ts b/src/languages/ja.ts
index 8569738fa3f3..b600c8079124 100644
--- a/src/languages/ja.ts
+++ b/src/languages/ja.ts
@@ -353,6 +353,10 @@ const translations: TranslationDeepObject<typeof en> = {
             subtitleText1: 'チャットを検索するには',
             subtitleText2: '上のボタン、または次を使って何かを作成する',
             subtitleText3: '下のボタンを押してください。',
+            noUnreadChats: '未読のチャットはありません',
+            noTodos: 'タスクはありません',
+            caughtUp: 'すべて確認済みです。お疲れさまでした！',
+            seeAllChats: 'すべてのチャットを表示',
         },
         businessName: '会社名',
         clear: 'クリア',
diff --git a/src/languages/nl.ts b/src/languages/nl.ts
index a9c54585631c..72bf0fafec9a 100644
--- a/src/languages/nl.ts
+++ b/src/languages/nl.ts
@@ -353,6 +353,10 @@ const translations: TranslationDeepObject<typeof en> = {
             subtitleText1: 'Zoek een chat met de',
             subtitleText2: 'knop hierboven, of maak iets met de',
             subtitleText3: 'knop hieronder.',
+            noUnreadChats: 'Geen ongelezen chats',
+            noTodos: 'Geen taken',
+            caughtUp: 'Je bent helemaal bij. Goed gedaan!',
+            seeAllChats: 'Alle chats bekijken',
         },
         businessName: 'Bedrijfsnaam',
         clear: 'Wissen',
diff --git a/src/languages/pl.ts b/src/languages/pl.ts
index e49967481b7e..9606a22696bf 100644
--- a/src/languages/pl.ts
+++ b/src/languages/pl.ts
@@ -353,6 +353,10 @@ const translations: TranslationDeepObject<typeof en> = {
             subtitleText1: 'Znajdź czat za pomocą',
             subtitleText2: 'przycisk powyżej lub utwórz coś za pomocą',
             subtitleText3: 'przycisk poniżej.',
+            noUnreadChats: 'Brak nieprzeczytanych czatów',
+            noTodos: 'Brak zadań',
+            caughtUp: 'Masz wszystko na bieżąco. Dobra robota!',
+            seeAllChats: 'Zobacz wszystkie czaty',
         },
         businessName: 'Nazwa firmy',
         clear: 'Wyczyść',
diff --git a/src/languages/pt-BR.ts b/src/languages/pt-BR.ts
index 4c9c50eca9ab..380de6616a4f 100644
--- a/src/languages/pt-BR.ts
+++ b/src/languages/pt-BR.ts
@@ -353,6 +353,10 @@ const translations: TranslationDeepObject<typeof en> = {
             subtitleText1: 'Encontre um chat usando o',
             subtitleText2: 'botão acima ou crie algo usando o',
             subtitleText3: 'botão abaixo.',
+            noUnreadChats: 'Nenhum chat não lido',
+            noTodos: 'Nenhuma tarefa',
+            caughtUp: 'Você está em dia. Muito bem!',
+            seeAllChats: 'Ver todos os chats',
         },
         businessName: 'Nome da empresa',
         clear: 'Limpar',
diff --git a/src/languages/zh-hans.ts b/src/languages/zh-hans.ts
index f2ee9971e217..6189be08fff4 100644
--- a/src/languages/zh-hans.ts
+++ b/src/languages/zh-hans.ts
@@ -353,6 +353,10 @@ const translations: TranslationDeepObject<typeof en> = {
             subtitleText1: '使用以下方式查找聊天',
             subtitleText2: '上方的按钮，或使用以下内容创建',
             subtitleText3: '下方按钮。',
+            noUnreadChats: '没有未读聊天',
+            noTodos: '没有待办事项',
+            caughtUp: '你已全部处理完毕。干得好！',
+            seeAllChats: '查看所有聊天',
         },
         businessName: '公司名称',
         clear: '清除',

From fcfddc7cfa2fd1cf226be11a754ec24a4628d80e Mon Sep 17 00:00:00 2001
From: Youssef Lourayad <youssef@expensify.com>
Date: Mon, 8 Jun 2026 23:54:29 +0000
Subject: [PATCH 195/435] Translations

---
 src/languages/de.ts      | 10 +++++-----
 src/languages/es.ts      |  6 +++---
 src/languages/fr.ts      | 12 ++++++------
 src/languages/it.ts      |  8 ++++----
 src/languages/ja.ts      |  4 ++--
 src/languages/nl.ts      |  6 +++---
 src/languages/pl.ts      |  6 +++---
 src/languages/pt-BR.ts   |  8 ++++----
 src/languages/zh-hans.ts |  6 +++---
 9 files changed, 33 insertions(+), 33 deletions(-)

diff --git a/src/languages/de.ts b/src/languages/de.ts
index 5b495c9da38f..2f83da0fa036 100644
--- a/src/languages/de.ts
+++ b/src/languages/de.ts
@@ -355,8 +355,8 @@ const translations: TranslationDeepObject<typeof en> = {
             subtitleText2: 'Schaltfläche oben oder erstellen Sie etwas mit der',
             subtitleText3: 'Schaltfläche unten.',
             noUnreadChats: 'Keine ungelesenen Chats',
-            noTodos: 'Keine Aufgaben',
-            caughtUp: 'Du bist auf dem neuesten Stand. Gut gemacht!',
+            noTodos: 'Keine To-dos',
+            caughtUp: 'Sie sind auf dem neuesten Stand. Gut gemacht!',
             seeAllChats: 'Alle Chats anzeigen',
         },
         businessName: 'Firmenname',
@@ -2900,11 +2900,11 @@ ${amount} für ${merchant} – ${date}`,
         },
     },
     focusModeUpdateModal: {
-        title: 'Willkommen im #Fokusmodus!',
+        title: 'Willkommen im #Focus-Modus!',
         prompt: (priorityModePageUrl: string) =>
-            `Behalten Sie den Überblick, indem Sie nur ungelesene Chats oder Chats anzeigen, die Ihre Aufmerksamkeit erfordern. Keine Sorge, Sie können dies jederzeit in den <a href="${priorityModePageUrl}">Einstellungen</a> ändern.`,
+            `Behalten Sie den Überblick, indem Sie nur ungelesene Chats oder Chats sehen, die Ihre Aufmerksamkeit erfordern. Keine Sorge, Sie können dies jederzeit in den <a href="${priorityModePageUrl}">Einstellungen</a> ändern.`,
     },
-    inboxTabs: {all: 'Alle', todo: 'To-dos', unread: 'Ungelesen'},
+    inboxTabs: {all: 'Alle', todo: 'Aufgaben', unread: 'Ungelesen'},
     reportDetailsPage: {
         inWorkspace: (policyName: string) => `in ${policyName}`,
         generatingPDF: 'PDF erstellen',
diff --git a/src/languages/es.ts b/src/languages/es.ts
index aee1f08afd8b..be3f37b58651 100644
--- a/src/languages/es.ts
+++ b/src/languages/es.ts
@@ -312,7 +312,7 @@ const translations: TranslationDeepObject<typeof en> = {
             subtitleText3: '.',
             noUnreadChats: 'No hay chats sin leer',
             noTodos: 'No hay tareas pendientes',
-            caughtUp: '¡Estás al día. Bien hecho!',
+            caughtUp: 'Te has puesto al día. ¡Bien hecho!',
             seeAllChats: 'Ver todos los chats',
         },
         businessName: 'Nombre de la empresa',
@@ -2777,9 +2777,9 @@ ${amount} para ${merchant} - ${date}`,
     focusModeUpdateModal: {
         title: '¡Bienvenido al modo #focus!',
         prompt: (priorityModePageUrl: string) =>
-            `Mantente al tanto de todo viendo solo los chats sin leer o los chats que necesitan tu atención. No te preocupes, puedes cambiar esto en cualquier momento en los <a href="${priorityModePageUrl}">ajustes</a>.`,
+            `Mantente al tanto de todo viendo solo los chats no leídos o los chats que necesitan tu atención. No te preocupes, puedes cambiarlo en cualquier momento en los <a href="${priorityModePageUrl}">ajustes</a>.`,
     },
-    inboxTabs: {all: 'Todo', todo: 'Tareas pendientes', unread: 'Sin leer'},
+    inboxTabs: {all: 'Todo', todo: 'Tareas pendientes', unread: 'No leído'},
     reportDetailsPage: {
         inWorkspace: (policyName) => `en ${policyName}`,
         generatingPDF: 'Generar PDF',
diff --git a/src/languages/fr.ts b/src/languages/fr.ts
index 453ec2defa1b..46c45edaeecb 100644
--- a/src/languages/fr.ts
+++ b/src/languages/fr.ts
@@ -353,10 +353,10 @@ const translations: TranslationDeepObject<typeof en> = {
             subtitleText1: 'Recherchez une discussion à l’aide de la',
             subtitleText2: 'bouton ci-dessus, ou créez quelque chose en utilisant le',
             subtitleText3: 'bouton ci-dessous.',
-            noUnreadChats: 'Aucun chat non lu',
-            noTodos: 'Aucune tâche',
-            caughtUp: 'Vous êtes à jour. Bien joué !',
-            seeAllChats: 'Voir tous les chats',
+            noUnreadChats: 'Aucune discussion non lue',
+            noTodos: 'Aucune tâche à faire',
+            caughtUp: 'Vous êtes à jour. Bravo !',
+            seeAllChats: 'Voir toutes les discussions',
         },
         businessName: 'Nom de l’entreprise',
         clear: 'Effacer',
@@ -2908,11 +2908,11 @@ ${amount} pour ${merchant} - ${date}`,
         },
     },
     focusModeUpdateModal: {
-        title: 'Bienvenue dans le mode #focus !',
+        title: 'Bienvenue dans le mode #focus !',
         prompt: (priorityModePageUrl: string) =>
             `Gardez le contrôle en n’affichant que les discussions non lues ou celles qui nécessitent votre attention. Ne vous inquiétez pas, vous pouvez modifier ce réglage à tout moment dans les <a href="${priorityModePageUrl}">paramètres</a>.`,
     },
-    inboxTabs: {all: 'Tout', todo: 'Tâches à faire', unread: 'Non lu'},
+    inboxTabs: {all: 'Tout', todo: 'Tâches', unread: 'Non lu'},
     reportDetailsPage: {
         inWorkspace: (policyName: string) => `dans ${policyName}`,
         generatingPDF: 'Générer le PDF',
diff --git a/src/languages/it.ts b/src/languages/it.ts
index 000fb6e227a7..bd835f31debe 100644
--- a/src/languages/it.ts
+++ b/src/languages/it.ts
@@ -355,8 +355,8 @@ const translations: TranslationDeepObject<typeof en> = {
             subtitleText2: 'pulsante sopra oppure crea qualcosa utilizzando il',
             subtitleText3: 'pulsante qui sotto.',
             noUnreadChats: 'Nessuna chat non letta',
-            noTodos: 'Nessuna attività',
-            caughtUp: 'Sei aggiornato. Ben fatto!',
+            noTodos: 'Nessuna attività da fare',
+            caughtUp: 'Hai gestito tutto. Ben fatto!',
             seeAllChats: 'Vedi tutte le chat',
         },
         businessName: 'Nome azienda',
@@ -2898,9 +2898,9 @@ ${amount} per ${merchant} - ${date}`,
     focusModeUpdateModal: {
         title: 'Benvenuto nella modalità #focus!',
         prompt: (priorityModePageUrl: string) =>
-            `Tieniti sempre aggiornato vedendo solo le chat non lette o quelle che richiedono la tua attenzione. Non preoccuparti, puoi cambiare questa impostazione in qualsiasi momento nelle <a href="${priorityModePageUrl}">impostazioni</a>.`,
+            `Tieniti al passo vedendo solo le chat non lette o quelle che richiedono la tua attenzione. Non preoccuparti, puoi cambiare questa impostazione in qualsiasi momento nelle <a href="${priorityModePageUrl}">impostazioni</a>.`,
     },
-    inboxTabs: {all: 'Tutto', todo: 'Attività da fare', unread: 'Non letti'},
+    inboxTabs: {all: 'Tutti', todo: 'Attività da fare', unread: 'Non letti'},
     reportDetailsPage: {
         inWorkspace: (policyName: string) => `in ${policyName}`,
         generatingPDF: 'Genera PDF',
diff --git a/src/languages/ja.ts b/src/languages/ja.ts
index b600c8079124..32fc6d4ac21e 100644
--- a/src/languages/ja.ts
+++ b/src/languages/ja.ts
@@ -354,7 +354,7 @@ const translations: TranslationDeepObject<typeof en> = {
             subtitleText2: '上のボタン、または次を使って何かを作成する',
             subtitleText3: '下のボタンを押してください。',
             noUnreadChats: '未読のチャットはありません',
-            noTodos: 'タスクはありません',
+            noTodos: 'To-do はありません',
             caughtUp: 'すべて確認済みです。お疲れさまでした！',
             seeAllChats: 'すべてのチャットを表示',
         },
@@ -2870,7 +2870,7 @@ ${date} の ${merchant} への ${amount}`,
     focusModeUpdateModal: {
         title: '#focus モードへようこそ！',
         prompt: (priorityModePageUrl: string) =>
-            `未読のチャットや対応が必要なチャットだけを表示して、状況を常に把握しましょう。<a href="${priorityModePageUrl}">設定</a>から、いつでもこの設定を変更できます。`,
+            `未読のチャットや対応が必要なチャットだけを表示して、状況を常に把握できるようにしましょう。いつでも<a href="${priorityModePageUrl}">設定</a>で変更できます。`,
     },
     inboxTabs: {all: 'すべて', todo: 'To-do リスト', unread: '未読'},
     reportDetailsPage: {
diff --git a/src/languages/nl.ts b/src/languages/nl.ts
index 72bf0fafec9a..27cfa6b13a83 100644
--- a/src/languages/nl.ts
+++ b/src/languages/nl.ts
@@ -2893,11 +2893,11 @@ ${amount} voor ${merchant} - ${date}`,
         },
     },
     focusModeUpdateModal: {
-        title: 'Welkom in de #focus-modus!',
+        title: 'Welkom in #focus-modus!',
         prompt: (priorityModePageUrl: string) =>
-            `Blijf alles bij door alleen ongelezen chats of chats te zien die je aandacht nodig hebben. Geen zorgen, je kunt dit op elk moment wijzigen in de <a href="${priorityModePageUrl}">instellingen</a>.`,
+            `Blijf op de hoogte door alleen ongelezen chats of chats te zien die je aandacht nodig hebben. Geen zorgen, je kunt dit op elk moment wijzigen in de <a href="${priorityModePageUrl}">instellingen</a>.`,
     },
-    inboxTabs: {all: 'Alles', todo: 'To-do’s', unread: 'Ongelezen'},
+    inboxTabs: {all: 'Alles', todo: 'Te doen', unread: 'Ongelezen'},
     reportDetailsPage: {
         inWorkspace: (policyName: string) => `in ${policyName}`,
         generatingPDF: 'PDF genereren',
diff --git a/src/languages/pl.ts b/src/languages/pl.ts
index 9606a22696bf..15420e19e372 100644
--- a/src/languages/pl.ts
+++ b/src/languages/pl.ts
@@ -355,7 +355,7 @@ const translations: TranslationDeepObject<typeof en> = {
             subtitleText3: 'przycisk poniżej.',
             noUnreadChats: 'Brak nieprzeczytanych czatów',
             noTodos: 'Brak zadań',
-            caughtUp: 'Masz wszystko na bieżąco. Dobra robota!',
+            caughtUp: 'Ze wszystkim już się uporałeś. Dobra robota!',
             seeAllChats: 'Zobacz wszystkie czaty',
         },
         businessName: 'Nazwa firmy',
@@ -2889,9 +2889,9 @@ ${amount} dla ${merchant} - ${date}`,
     focusModeUpdateModal: {
         title: 'Witaj w trybie #focus!',
         prompt: (priorityModePageUrl: string) =>
-            `Bądź na bieżąco, pokazując tylko nieprzeczytane czaty lub czaty wymagające twojej uwagi. Spokojnie, możesz to zmienić w każdej chwili w <a href="${priorityModePageUrl}">ustawieniach</a>.`,
+            `Bądź na bieżąco, widząc tylko nieprzeczytane czaty lub czaty wymagające twojej uwagi. Spokojnie, możesz to zmienić w dowolnym momencie w <a href="${priorityModePageUrl}">ustawieniach</a>.`,
     },
-    inboxTabs: {all: 'Wszystkie', todo: 'Zadania', unread: 'Nieprzeczytane'},
+    inboxTabs: {all: 'Wszystko', todo: 'Zadania do wykonania', unread: 'Nieprzeczytane'},
     reportDetailsPage: {
         inWorkspace: (policyName: string) => `w ${policyName}`,
         generatingPDF: 'Wygeneruj PDF',
diff --git a/src/languages/pt-BR.ts b/src/languages/pt-BR.ts
index 380de6616a4f..ac2d21d694b1 100644
--- a/src/languages/pt-BR.ts
+++ b/src/languages/pt-BR.ts
@@ -354,9 +354,9 @@ const translations: TranslationDeepObject<typeof en> = {
             subtitleText2: 'botão acima ou crie algo usando o',
             subtitleText3: 'botão abaixo.',
             noUnreadChats: 'Nenhum chat não lido',
-            noTodos: 'Nenhuma tarefa',
+            noTodos: 'Nenhuma tarefa pendente',
             caughtUp: 'Você está em dia. Muito bem!',
-            seeAllChats: 'Ver todos os chats',
+            seeAllChats: 'Ver todas as conversas',
         },
         businessName: 'Nome da empresa',
         clear: 'Limpar',
@@ -2889,9 +2889,9 @@ ${amount} para ${merchant} - ${date}`,
     focusModeUpdateModal: {
         title: 'Bem-vindo ao modo #focus!',
         prompt: (priorityModePageUrl: string) =>
-            `Fique por dentro de tudo vendo apenas os chats não lidos ou que precisam da sua atenção. Não se preocupe, você pode mudar isso a qualquer momento em <a href="${priorityModePageUrl}">configurações</a>.`,
+            `Fique no controle vendo apenas chats não lidos ou que precisam da sua atenção. Não se preocupe, você pode mudar isso a qualquer momento em <a href="${priorityModePageUrl}">configurações</a>.`,
     },
-    inboxTabs: {all: 'Tudo', todo: 'Tarefas', unread: 'Não lidas'},
+    inboxTabs: {all: 'Todos', todo: 'Pendências', unread: 'Não lidas'},
     reportDetailsPage: {
         inWorkspace: (policyName: string) => `em ${policyName}`,
         generatingPDF: 'Gerar PDF',
diff --git a/src/languages/zh-hans.ts b/src/languages/zh-hans.ts
index 6189be08fff4..144782a3d77b 100644
--- a/src/languages/zh-hans.ts
+++ b/src/languages/zh-hans.ts
@@ -355,7 +355,7 @@ const translations: TranslationDeepObject<typeof en> = {
             subtitleText3: '下方按钮。',
             noUnreadChats: '没有未读聊天',
             noTodos: '没有待办事项',
-            caughtUp: '你已全部处理完毕。干得好！',
+            caughtUp: '你已经全部处理完了。干得好！',
             seeAllChats: '查看所有聊天',
         },
         businessName: '公司名称',
@@ -2811,8 +2811,8 @@ ${amount}，商户：${merchant} - 日期：${date}`,
         },
     },
     focusModeUpdateModal: {
-        title: '欢迎进入 #focus 模式！',
-        prompt: (priorityModePageUrl: string) => `只查看未读或需要你关注的聊天，时刻掌握最新进展。别担心，你随时可以在<a href="${priorityModePageUrl}">设置</a>中更改此项。`,
+        title: '欢迎使用 #focus 模式！',
+        prompt: (priorityModePageUrl: string) => `通过只查看未读聊天或需要你关注的聊天，随时掌握最新进展。别担心，你可以随时在<a href="${priorityModePageUrl}">设置</a>中更改此项。`,
     },
     inboxTabs: {all: '全部', todo: '待办事项', unread: '未读'},
     reportDetailsPage: {

From 6f9c5b36be017c16aa6aa1ea10a6c491cac66293 Mon Sep 17 00:00:00 2001
From: Youssef Lourayad <youssef@expensify.com>
Date: Tue, 9 Jun 2026 01:07:04 +0000
Subject: [PATCH 196/435] Allow parent chat to show up in LHN when clicked from
 subtitle

---
 src/hooks/useSidebarOrderedReports.tsx | 20 +++++++++++++++++++-
 1 file changed, 19 insertions(+), 1 deletion(-)

diff --git a/src/hooks/useSidebarOrderedReports.tsx b/src/hooks/useSidebarOrderedReports.tsx
index c15e52fe29ae..f3b8ec770abf 100644
--- a/src/hooks/useSidebarOrderedReports.tsx
+++ b/src/hooks/useSidebarOrderedReports.tsx
@@ -45,7 +45,14 @@ type SidebarOrderedReportsActionsContextValue = {
     setStickyReportID: (reportID: string) => void;
 };
 
-type ReportsToDisplayInLHN = Record<string, OnyxTypes.Report & {hasErrorsOtherThanFailedReceipt?: boolean; requiresAttention?: boolean; isUnreadReport?: boolean}>;
+type ReportsToDisplayInLHN = Record<
+    string,
+    OnyxTypes.Report & {
+        hasErrorsOtherThanFailedReceipt?: boolean;
+        requiresAttention?: boolean;
+        isUnreadReport?: boolean;
+    }
+>;
 
 const SidebarOrderedReportsStateContext = createContext<SidebarOrderedReportsStateContextValue>({
     filteredReports: [],
@@ -358,6 +365,17 @@ function SidebarOrderedReportsContextProvider({
         [activeTab],
     );
 
+    // Navigating to a report from somewhere other than the LHN (e.g. opening the parent chat from a
+    // report's header subtitle) should also keep that report visible in the active To-do/Unread tab,
+    // just like opening one from the LHN does. We only react to the focused report changing, not to a
+    // tab switch, so switching tabs while a report is open doesn't pin that report to the new tab.
+    useEffect(() => {
+        if (activeTab === CONST.INBOX_TAB.ALL || !derivedCurrentReportID || derivedCurrentReportID === '-1' || derivedCurrentReportID === prevDerivedCurrentReportID) {
+            return;
+        }
+        setStickyReport({reportID: derivedCurrentReportID, tab: activeTab});
+    }, [activeTab, derivedCurrentReportID, prevDerivedCurrentReportID]);
+
     const stateValue: SidebarOrderedReportsStateContextValue = useMemo(() => {
         // We need to make sure the current report is in the list of reports, but we do not want
         // to have to re-generate the list every time the currentReportID changes. To do that

From ec5ee165729a733ba7b2f3c94b76bd21cc963adb Mon Sep 17 00:00:00 2001
From: Youssef Lourayad <youssef@expensify.com>
Date: Tue, 9 Jun 2026 01:19:13 +0000
Subject: [PATCH 197/435] Revert parent chat fix

---
 src/hooks/useSidebarOrderedReports.tsx | 20 +-------------------
 1 file changed, 1 insertion(+), 19 deletions(-)

diff --git a/src/hooks/useSidebarOrderedReports.tsx b/src/hooks/useSidebarOrderedReports.tsx
index f3b8ec770abf..c15e52fe29ae 100644
--- a/src/hooks/useSidebarOrderedReports.tsx
+++ b/src/hooks/useSidebarOrderedReports.tsx
@@ -45,14 +45,7 @@ type SidebarOrderedReportsActionsContextValue = {
     setStickyReportID: (reportID: string) => void;
 };
 
-type ReportsToDisplayInLHN = Record<
-    string,
-    OnyxTypes.Report & {
-        hasErrorsOtherThanFailedReceipt?: boolean;
-        requiresAttention?: boolean;
-        isUnreadReport?: boolean;
-    }
->;
+type ReportsToDisplayInLHN = Record<string, OnyxTypes.Report & {hasErrorsOtherThanFailedReceipt?: boolean; requiresAttention?: boolean; isUnreadReport?: boolean}>;
 
 const SidebarOrderedReportsStateContext = createContext<SidebarOrderedReportsStateContextValue>({
     filteredReports: [],
@@ -365,17 +358,6 @@ function SidebarOrderedReportsContextProvider({
         [activeTab],
     );
 
-    // Navigating to a report from somewhere other than the LHN (e.g. opening the parent chat from a
-    // report's header subtitle) should also keep that report visible in the active To-do/Unread tab,
-    // just like opening one from the LHN does. We only react to the focused report changing, not to a
-    // tab switch, so switching tabs while a report is open doesn't pin that report to the new tab.
-    useEffect(() => {
-        if (activeTab === CONST.INBOX_TAB.ALL || !derivedCurrentReportID || derivedCurrentReportID === '-1' || derivedCurrentReportID === prevDerivedCurrentReportID) {
-            return;
-        }
-        setStickyReport({reportID: derivedCurrentReportID, tab: activeTab});
-    }, [activeTab, derivedCurrentReportID, prevDerivedCurrentReportID]);
-
     const stateValue: SidebarOrderedReportsStateContextValue = useMemo(() => {
         // We need to make sure the current report is in the list of reports, but we do not want
         // to have to re-generate the list every time the currentReportID changes. To do that

From 2c1905c32cb2301f858568e8f602b5efe2f6a92e Mon Sep 17 00:00:00 2001
From: Youssef Lourayad <youssef@expensify.com>
Date: Tue, 9 Jun 2026 01:27:32 +0000
Subject: [PATCH 198/435] Adjust spacing to match the mock

---
 .../LHNOptionsList/LHNEmptyState.tsx          | 19 +++++++++++++++----
 1 file changed, 15 insertions(+), 4 deletions(-)

diff --git a/src/components/LHNOptionsList/LHNEmptyState.tsx b/src/components/LHNOptionsList/LHNEmptyState.tsx
index b4681315fc39..b8498ac7af75 100644
--- a/src/components/LHNOptionsList/LHNEmptyState.tsx
+++ b/src/components/LHNOptionsList/LHNEmptyState.tsx
@@ -3,7 +3,9 @@ import {View} from 'react-native';
 import type {BlockingViewProps} from '@components/BlockingViews/BlockingView';
 import BlockingView from '@components/BlockingViews/BlockingView';
 import Icon from '@components/Icon';
+import Text from '@components/Text';
 import TextBlock from '@components/TextBlock';
+import TextLink from '@components/TextLink';
 import {useMemoizedLazyExpensifyIcons} from '@hooks/useLazyAsset';
 import useLocalize from '@hooks/useLocalize';
 import {useSidebarOrderedReportsActions, useSidebarOrderedReportsState} from '@hooks/useSidebarOrderedReports';
@@ -24,15 +26,24 @@ function LHNEmptyState() {
 
     if (activeTab === CONST.INBOX_TAB.UNREAD || activeTab === CONST.INBOX_TAB.TODO) {
         const title = activeTab === CONST.INBOX_TAB.UNREAD ? translate('common.emptyLHN.noUnreadChats') : translate('common.emptyLHN.noTodos');
+        const caughtUpSubtitle = (
+            <View style={[styles.alignItemsCenter, styles.justifyContentCenter]}>
+                <Text style={[styles.textAlignCenter, styles.textSupporting]}>{translate('common.emptyLHN.caughtUp')}</Text>
+                <TextLink
+                    onPress={() => setActiveTab(CONST.INBOX_TAB.ALL)}
+                    style={[styles.link, styles.mt5, styles.ph4, styles.textAlignCenter]}
+                >
+                    {translate('common.emptyLHN.seeAllChats')}
+                </TextLink>
+            </View>
+        );
 
         return (
             <BlockingView
                 {...(emptyLHNIllustration as BlockingViewProps)}
                 title={title}
-                subtitle={translate('common.emptyLHN.caughtUp')}
-                subtitleStyle={styles.textSupporting}
-                linkTranslationKey="common.emptyLHN.seeAllChats"
-                onLinkPress={() => setActiveTab(CONST.INBOX_TAB.ALL)}
+                titleStyles={styles.mb2}
+                CustomSubtitle={caughtUpSubtitle}
                 accessibilityLabel={title}
             />
         );

From f9bccc61cadcc761fd65f1062081efbd9c05ecf9 Mon Sep 17 00:00:00 2001
From: Stephanie Elliott <31225194+stephanieelliott@users.noreply.github.com>
Date: Mon, 8 Jun 2026 16:27:16 -1000
Subject: [PATCH 199/435] Update VAT-IT.md

---
 docs/articles/expensify-classic/connections/VAT-IT.md | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/docs/articles/expensify-classic/connections/VAT-IT.md b/docs/articles/expensify-classic/connections/VAT-IT.md
index 29465eaeb874..5ee23fbaf071 100644
--- a/docs/articles/expensify-classic/connections/VAT-IT.md
+++ b/docs/articles/expensify-classic/connections/VAT-IT.md
@@ -27,13 +27,13 @@ Businesses can reclaim VAT on various expenses, including:
 
 # How VAT Refunds Work
 
-VAT refund regulations vary by country and expense type, making the process complex. Global VaTax simplifies this by handling:
+VAT refund regulations vary by country and expense type, making the process complex. VAT IT simplifies this by handling:
 
 - VAT analysis and calculation  
 - Expense classification based on VAT eligibility  
 - Report preparation and submission to tax authorities  
 
-By syncing Expensify with Global VaTax, businesses can automate VAT reporting and reclaim eligible expenses efficiently.
+By syncing Expensify with VAT IT, businesses can automate VAT reporting and reclaim eligible expenses efficiently.
 
 ---
 

From 51ecb9c19c5dc2e0d11e95e5e2ce5c243f2f0497 Mon Sep 17 00:00:00 2001
From: nabi-ebrahimi <nabi.zarin.work@gmail.com>
Date: Tue, 9 Jun 2026 10:34:35 +0430
Subject: [PATCH 200/435] fix: move tracked per diem through requestMoney

---
 .../parameters/CreatePerDiemRequestParams.ts  |   2 -
 src/libs/actions/IOU/MoneyRequestBuilder.ts   |  72 +++++------
 src/libs/actions/IOU/PerDiem.ts               |  54 ++-------
 src/libs/actions/IOU/TrackExpense.ts          |  23 ++--
 .../IOU/types/TrackedExpenseSubmitParams.ts   |  10 --
 .../step/confirmation/useExpenseSubmission.ts |   8 +-
 tests/actions/IOU/PerDiemTest.ts              | 112 ------------------
 tests/unit/hooks/useExpenseSubmission.test.ts | 108 +++++++++++++++++
 8 files changed, 169 insertions(+), 220 deletions(-)
 delete mode 100644 src/libs/actions/IOU/types/TrackedExpenseSubmitParams.ts

diff --git a/src/libs/API/parameters/CreatePerDiemRequestParams.ts b/src/libs/API/parameters/CreatePerDiemRequestParams.ts
index 7b41b4909e51..77d8aaafc06a 100644
--- a/src/libs/API/parameters/CreatePerDiemRequestParams.ts
+++ b/src/libs/API/parameters/CreatePerDiemRequestParams.ts
@@ -17,8 +17,6 @@ type CreatePerDiemRequestParams = {
     reportActionID: string;
     createdChatReportActionID?: string;
     createdIOUReportActionID?: string;
-    actionableWhisperReportActionID?: string;
-    modifiedExpenseReportActionID?: string;
     reportPreviewReportActionID: string;
     transactionThreadReportID?: string;
     createdReportActionIDForThread: string | undefined;
diff --git a/src/libs/actions/IOU/MoneyRequestBuilder.ts b/src/libs/actions/IOU/MoneyRequestBuilder.ts
index 610e0b6fbe98..90119a98db12 100644
--- a/src/libs/actions/IOU/MoneyRequestBuilder.ts
+++ b/src/libs/actions/IOU/MoneyRequestBuilder.ts
@@ -71,7 +71,6 @@ import type BasePolicyParams from './types/BasePolicyParams';
 import type BaseTransactionParams from './types/BaseTransactionParams';
 import type {CreateTrackExpenseParams} from './types/CreateTrackExpenseParams';
 import type RequestMoneyParticipantParams from './types/RequestMoneyParticipantParams';
-import type TrackedExpenseSubmitParams from './types/TrackedExpenseSubmitParams';
 import type {GPSPoint} from './types/TrackExpenseTransactionParams';
 
 type OneOnOneIOUReport = OnyxTypes.Report | undefined | null;
@@ -111,40 +110,43 @@ type MoneyRequestInformation = {
     reimbursable?: boolean;
 };
 
-type RequestMoneyTransactionParams = Omit<BaseTransactionParams, 'comment'> &
-    TrackedExpenseSubmitParams & {
-        attendees?: Attendee[];
-        receipt?: Receipt;
-        waypoints?: WaypointCollection;
-        comment?: string;
-        originalTransactionID?: string;
-        isTestDrive?: boolean;
-        source?: string;
-        pendingAction?: PendingAction;
-        pendingFields?: PendingFields<string>;
-        distance?: number;
-        customUnit?: TransactionCustomUnit;
-        odometerStart?: number;
-        odometerEnd?: number;
-
-        /** Transaction type (e.g., 'time' for time tracking expenses) */
-        type?: ValueOf<typeof CONST.TRANSACTION.TYPE>;
-
-        /** Number of hours for time tracking expenses */
-        count?: number;
-
-        /** Hourly rate in cents. Use convertToBackendAmount() to convert from policy rate (which is stored as a float) */
-        rate?: number;
-
-        /** Unit for time tracking (e.g., 'h' for hours) */
-        unit?: ValueOf<typeof CONST.TIME_TRACKING.UNIT>;
-
-        /** Whether this is a selfDM split transaction */
-        isSelfDMSplit?: boolean;
-
-        /** The selfDM report ID for split transactions */
-        selfDMReportID?: string;
-    };
+type RequestMoneyTransactionParams = Omit<BaseTransactionParams, 'comment'> & {
+    attendees?: Attendee[];
+    actionableWhisperReportActionID?: string;
+    linkedTrackedExpenseReportAction?: OnyxTypes.ReportAction;
+    linkedTrackedExpenseReportID?: string;
+    receipt?: Receipt;
+    waypoints?: WaypointCollection;
+    comment?: string;
+    originalTransactionID?: string;
+    isTestDrive?: boolean;
+    source?: string;
+    pendingAction?: PendingAction;
+    pendingFields?: PendingFields<string>;
+    distance?: number;
+    isLinkedTrackedExpenseReportArchived?: boolean;
+    customUnit?: TransactionCustomUnit;
+    odometerStart?: number;
+    odometerEnd?: number;
+
+    /** Transaction type (e.g., 'time' for time tracking expenses) */
+    type?: ValueOf<typeof CONST.TRANSACTION.TYPE>;
+
+    /** Number of hours for time tracking expenses */
+    count?: number;
+
+    /** Hourly rate in cents. Use convertToBackendAmount() to convert from policy rate (which is stored as a float) */
+    rate?: number;
+
+    /** Unit for time tracking (e.g., 'h' for hours) */
+    unit?: ValueOf<typeof CONST.TIME_TRACKING.UNIT>;
+
+    /** Whether this is a selfDM split transaction */
+    isSelfDMSplit?: boolean;
+
+    /** The selfDM report ID for split transactions */
+    selfDMReportID?: string;
+};
 
 type RequestMoneyInformation = {
     report: OnyxEntry<OnyxTypes.Report>;
diff --git a/src/libs/actions/IOU/PerDiem.ts b/src/libs/actions/IOU/PerDiem.ts
index f016aeffaed4..80c520865ab2 100644
--- a/src/libs/actions/IOU/PerDiem.ts
+++ b/src/libs/actions/IOU/PerDiem.ts
@@ -9,7 +9,7 @@ import {convertAmountToDisplayString, convertToFrontendAmountAsString} from '@li
 import DateUtils from '@libs/DateUtils';
 import {deferOrExecuteWrite} from '@libs/deferredLayoutWrite';
 import {getMicroSecondOnyxErrorWithTranslationKey} from '@libs/ErrorUtils';
-import {getExistingTransactionID, updateIOUOwnerAndTotal} from '@libs/IOUUtils';
+import {updateIOUOwnerAndTotal} from '@libs/IOUUtils';
 import {formatPhoneNumber} from '@libs/LocalePhoneNumber';
 import {validateAmount} from '@libs/MoneyRequestUtils';
 import Navigation from '@libs/Navigation/Navigation';
@@ -58,11 +58,9 @@ import {
 } from './MoneyRequestBuilder';
 import type {MoneyRequestInformation} from './MoneyRequestBuilder';
 import {highlightTransactionOnSearchRouteIfNeeded} from './NavigationHelpers';
-import {getMoveTrackedExpenseInformation} from './TrackExpense';
 import type BasePolicyParams from './types/BasePolicyParams';
 import type BaseTransactionParams from './types/BaseTransactionParams';
 import type RequestMoneyParticipantParams from './types/RequestMoneyParticipantParams';
-import type TrackedExpenseSubmitParams from './types/TrackedExpenseSubmitParams';
 
 function removeSubrate(transaction: OnyxEntry<OnyxTypes.Transaction>, currentIndex: string) {
     // Index comes from the route params and is a string
@@ -204,12 +202,11 @@ function computeDefaultPerDiemExpenseComment(customUnit: TransactionCustomUnit,
     return subRateComments.join(', ');
 }
 
-type PerDiemExpenseTransactionParams = Omit<BaseTransactionParams, 'amount' | 'merchant' | 'customUnitRateID' | 'taxAmount' | 'taxCode' | 'comment'> &
-    TrackedExpenseSubmitParams & {
-        attendees?: Attendee[];
-        customUnit: TransactionCustomUnit;
-        comment?: string;
-    };
+type PerDiemExpenseTransactionParams = Omit<BaseTransactionParams, 'amount' | 'merchant' | 'customUnitRateID' | 'taxAmount' | 'taxCode' | 'comment'> & {
+    attendees?: Attendee[];
+    customUnit: TransactionCustomUnit;
+    comment?: string;
+};
 
 type RecentlyUsedParams = {
     destinations?: OnyxEntry<OnyxTypes.RecentlyUsedCategories>;
@@ -915,20 +912,7 @@ function submitPerDiemExpense(submitPerDiemExpenseInformation: PerDiemExpenseInf
         optimisticTransactionID,
         delegateAccountID,
     } = submitPerDiemExpenseInformation;
-    const {
-        currency,
-        comment = '',
-        category,
-        tag,
-        created,
-        customUnit,
-        attendees,
-        isFromGlobalCreate,
-        actionableWhisperReportActionID,
-        linkedTrackedExpenseReportAction,
-        linkedTrackedExpenseReportID,
-        isLinkedTrackedExpenseReportArchived,
-    } = transactionParams;
+    const {currency, comment = '', category, tag, created, customUnit, attendees, isFromGlobalCreate} = transactionParams;
 
     if (
         isEmptyObject(policyParams.policy) ||
@@ -990,28 +974,6 @@ function submitPerDiemExpense(submitPerDiemExpenseInformation: PerDiemExpenseInf
         name: customUnitRate?.name,
     };
 
-    let modifiedExpenseReportActionID: string | undefined;
-    const sourceTransactionID = getExistingTransactionID(linkedTrackedExpenseReportAction);
-
-    if (sourceTransactionID && linkedTrackedExpenseReportAction && linkedTrackedExpenseReportID) {
-        const linkedTrackedExpenseThreadReportID = linkedTrackedExpenseReportAction.childReportID ?? transactionThreadReportID;
-        const moveTrackedExpenseInformation = getMoveTrackedExpenseInformation(
-            sourceTransactionID,
-            actionableWhisperReportActionID,
-            linkedTrackedExpenseReportAction,
-            linkedTrackedExpenseReportID,
-            linkedTrackedExpenseThreadReportID,
-            CONST.IOU.ACTION.SUBMIT,
-            isLinkedTrackedExpenseReportArchived,
-            currentUserAccountIDParam,
-        );
-
-        onyxData.optimisticData?.push(...moveTrackedExpenseInformation.optimisticData);
-        onyxData.successData?.push(...moveTrackedExpenseInformation.successData);
-        onyxData.failureData?.push(...moveTrackedExpenseInformation.failureData);
-        modifiedExpenseReportActionID = moveTrackedExpenseInformation.modifiedExpenseReportActionID;
-    }
-
     const parameters: CreatePerDiemRequestParams = {
         policyID: policyParams.policy.id,
         customUnitID: customUnit.customUnitID,
@@ -1029,8 +991,6 @@ function submitPerDiemExpense(submitPerDiemExpenseInformation: PerDiemExpenseInf
         reportActionID: iouAction.reportActionID,
         createdChatReportActionID,
         createdIOUReportActionID,
-        actionableWhisperReportActionID,
-        modifiedExpenseReportActionID,
         reportPreviewReportActionID: reportPreviewAction.reportActionID,
         category,
         tag,
diff --git a/src/libs/actions/IOU/TrackExpense.ts b/src/libs/actions/IOU/TrackExpense.ts
index 48b61271860e..5bc9c37cb96a 100644
--- a/src/libs/actions/IOU/TrackExpense.ts
+++ b/src/libs/actions/IOU/TrackExpense.ts
@@ -1164,9 +1164,10 @@ function getTrackExpenseInformation(params: GetTrackExpenseInformationParams): T
     };
 }
 
-const getMoveTrackedExpenseInformation = (
+const getConvertTrackedExpenseInformation = (
     transactionID: string | undefined,
     actionableWhisperReportActionID: string | undefined,
+    moneyRequestReportID: string | undefined,
     linkedTrackedExpenseReportAction: OnyxTypes.ReportAction,
     linkedTrackedExpenseReportID: string,
     transactionThreadReportID: string | undefined,
@@ -1471,9 +1472,10 @@ function convertTrackedExpenseToRequest(convertTrackedExpenseParams: ConvertTrac
     successData?.push(...(onyxData.successData ?? []));
     failureData?.push(...(onyxData.failureData ?? []));
 
-    const convertTrackedExpenseInformation = getMoveTrackedExpenseInformation(
+    const convertTrackedExpenseInformation = getConvertTrackedExpenseInformation(
         transactionID,
         actionableWhisperReportActionID,
+        iouParams.reportID,
         linkedTrackedExpenseReportAction,
         linkedTrackedExpenseReportID,
         transactionThreadReportID,
@@ -2101,16 +2103,23 @@ function categorizeTrackedExpense(trackedExpenseParams: TrackedExpenseParams) {
     const {optimisticData, successData, failureData} = onyxData ?? {};
     const {transactionID} = transactionParams;
     const {isDraftPolicy} = policyParams;
-    const {actionableWhisperReportActionID, linkedTrackedExpenseReportAction, linkedTrackedExpenseReportID, transactionThreadReportID, isLinkedTrackedExpenseReportArchived} =
-        reportInformation;
+    const {
+        actionableWhisperReportActionID,
+        moneyRequestReportID,
+        linkedTrackedExpenseReportAction,
+        linkedTrackedExpenseReportID,
+        transactionThreadReportID,
+        isLinkedTrackedExpenseReportArchived,
+    } = reportInformation;
     const {
         optimisticData: moveTransactionOptimisticData,
         successData: moveTransactionSuccessData,
         failureData: moveTransactionFailureData,
         modifiedExpenseReportActionID,
-    } = getMoveTrackedExpenseInformation(
+    } = getConvertTrackedExpenseInformation(
         transactionID,
         actionableWhisperReportActionID,
+        moneyRequestReportID,
         linkedTrackedExpenseReportAction,
         linkedTrackedExpenseReportID,
         transactionThreadReportID,
@@ -2201,9 +2210,10 @@ function shareTrackedExpense(trackedExpenseParams: TrackedExpenseParams) {
         isLinkedTrackedExpenseReportArchived,
     } = reportInformation;
 
-    const convertTrackedExpenseInformation = getMoveTrackedExpenseInformation(
+    const convertTrackedExpenseInformation = getConvertTrackedExpenseInformation(
         transactionID,
         actionableWhisperReportActionID,
+        moneyRequestReportID,
         linkedTrackedExpenseReportAction,
         linkedTrackedExpenseReportID,
         transactionThreadReportID,
@@ -2819,7 +2829,6 @@ export {
     convertBulkTrackedExpensesToIOU,
     deleteTrackExpense,
     getDeleteTrackExpenseInformation,
-    getMoveTrackedExpenseInformation,
     getNavigationUrlAfterTrackExpenseDelete,
     getTrackExpenseInformation,
     hasManualDistanceOverride,
diff --git a/src/libs/actions/IOU/types/TrackedExpenseSubmitParams.ts b/src/libs/actions/IOU/types/TrackedExpenseSubmitParams.ts
deleted file mode 100644
index b15fd14f8f1b..000000000000
--- a/src/libs/actions/IOU/types/TrackedExpenseSubmitParams.ts
+++ /dev/null
@@ -1,10 +0,0 @@
-import type * as OnyxTypes from '@src/types/onyx';
-
-type TrackedExpenseSubmitParams = {
-    actionableWhisperReportActionID?: string;
-    linkedTrackedExpenseReportAction?: OnyxTypes.ReportAction;
-    linkedTrackedExpenseReportID?: string;
-    isLinkedTrackedExpenseReportArchived?: boolean;
-};
-
-export default TrackedExpenseSubmitParams;
diff --git a/src/pages/iou/request/step/confirmation/useExpenseSubmission.ts b/src/pages/iou/request/step/confirmation/useExpenseSubmission.ts
index 3206d5e7b7f2..39361bc5a176 100644
--- a/src/pages/iou/request/step/confirmation/useExpenseSubmission.ts
+++ b/src/pages/iou/request/step/confirmation/useExpenseSubmission.ts
@@ -546,8 +546,6 @@ function useExpenseSubmission(params: UseExpenseSubmissionParams) {
                 existingChatReport,
             );
             const activeReportID = isExpenseReport && Navigation.getTopmostReportId() === report?.reportID ? report?.reportID : chatReportID;
-            const isLinkedTrackedExpenseReportArchived =
-                !!transaction.linkedTrackedExpenseReportID && privateIsArchivedMap[`${ONYXKEYS.COLLECTION.REPORT_NAME_VALUE_PAIRS}${transaction.linkedTrackedExpenseReportID}`];
 
             const result = submitPerDiemExpenseIOUActions({
                 report,
@@ -576,10 +574,6 @@ function useExpenseSubmission(params: UseExpenseSubmissionParams) {
                     billable: transaction.billable,
                     reimbursable: transaction.reimbursable,
                     attendees: transaction.comment?.attendees,
-                    actionableWhisperReportActionID: transaction.actionableWhisperReportActionID,
-                    linkedTrackedExpenseReportAction: transaction.linkedTrackedExpenseReportAction,
-                    linkedTrackedExpenseReportID: transaction.linkedTrackedExpenseReportID,
-                    isLinkedTrackedExpenseReportArchived,
                     isFromGlobalCreate: getIsFromGlobalCreate(transaction),
                 },
                 isASAPSubmitBetaEnabled,
@@ -953,7 +947,7 @@ function useExpenseSubmission(params: UseExpenseSubmissionParams) {
             return;
         }
 
-        if (isPerDiemRequest) {
+        if (isPerDiemRequest && action !== CONST.IOU.ACTION.SUBMIT) {
             submitPerDiemExpense(trimmedComment, shouldHandleNavigation, policyRecentlyUsedCategories);
             markSubmitExpenseEnd();
             return;
diff --git a/tests/actions/IOU/PerDiemTest.ts b/tests/actions/IOU/PerDiemTest.ts
index 335a066e2335..f8ba62bb4690 100644
--- a/tests/actions/IOU/PerDiemTest.ts
+++ b/tests/actions/IOU/PerDiemTest.ts
@@ -3,15 +3,11 @@ import type {OnyxCollection, OnyxEntry} from 'react-native-onyx';
 import type {PerDiemExpenseTransactionParams} from '@libs/actions/IOU/PerDiem';
 import {addSubrate, clearSubrates, computePerDiemExpenseAmount, getPerDiemExpenseInformation, removeSubrate, submitPerDiemExpense, updateSubrate} from '@libs/actions/IOU/PerDiem';
 import type RequestMoneyParticipantParams from '@libs/actions/IOU/types/RequestMoneyParticipantParams';
-import * as API from '@libs/API';
-import type {CreatePerDiemRequestParams} from '@libs/API/parameters';
-import {WRITE_COMMANDS} from '@libs/API/types';
 import CONST from '@src/CONST';
 import DateUtils from '@src/libs/DateUtils';
 import ONYXKEYS from '@src/ONYXKEYS';
 import type {PersonalDetailsList, RecentlyUsedTags, Report} from '@src/types/onyx';
 import type {CurrentUserPersonalDetails} from '@src/types/onyx/PersonalDetails';
-import type ReportAction from '@src/types/onyx/ReportAction';
 import type Transaction from '@src/types/onyx/Transaction';
 import type {TransactionCustomUnit} from '@src/types/onyx/Transaction';
 import createPersonalDetails from '../../utils/collections/personalDetails';
@@ -75,10 +71,6 @@ describe('PerDiem', () => {
         return Onyx.clear().then(waitForBatchedUpdates);
     });
 
-    afterEach(() => {
-        jest.restoreAllMocks();
-    });
-
     describe('computePerDiemExpenseAmount', () => {
         it('should compute total amount from subRates', () => {
             const customUnit: TransactionCustomUnit = {
@@ -655,110 +647,6 @@ describe('PerDiem', () => {
     });
 
     describe('submitPerDiemExpense', () => {
-        it('should clean up the linked tracked expense when submitting a per diem from self DM', async () => {
-            const sourceTransactionID = 'tracked-per-diem-transaction';
-            const selfDMReportID = 'self-dm-report';
-            const actionableWhisperReportActionID = 'actionable-whisper-action';
-            const linkedTrackedExpenseReportAction = {
-                actionName: CONST.REPORT.ACTIONS.TYPE.IOU,
-                reportActionID: 'tracked-per-diem-action',
-                childReportID: 'tracked-per-diem-thread',
-                created: DateUtils.getDBTime(),
-                message: [],
-                originalMessage: {
-                    IOUTransactionID: sourceTransactionID,
-                    type: CONST.IOU.REPORT_ACTION_TYPE.TRACK,
-                },
-            } as unknown as ReportAction<typeof CONST.REPORT.ACTIONS.TYPE.IOU>;
-
-            await Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT}${selfDMReportID}`, {
-                reportID: selfDMReportID,
-                type: CONST.REPORT.TYPE.CHAT,
-                chatType: CONST.REPORT.CHAT_TYPE.SELF_DM,
-            });
-            await Onyx.merge(`${ONYXKEYS.COLLECTION.TRANSACTION}${sourceTransactionID}`, {
-                transactionID: sourceTransactionID,
-                reportID: CONST.REPORT.UNREPORTED_REPORT_ID,
-            });
-            await Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${selfDMReportID}`, {
-                [linkedTrackedExpenseReportAction.reportActionID]: linkedTrackedExpenseReportAction,
-            });
-            await waitForBatchedUpdates();
-
-            const writeSpy = jest.spyOn(API, 'write').mockImplementation(jest.fn());
-
-            submitPerDiemExpense({
-                currentUserAccountIDParam: currentUserPersonalDetails.accountID,
-                currentUserEmailParam: currentUserPersonalDetails.login ?? '',
-                hasViolations: false,
-                isASAPSubmitBetaEnabled: false,
-                participantParams: {
-                    payeeEmail: currentUserPersonalDetails.login,
-                    payeeAccountID: currentUserPersonalDetails.accountID,
-                    participant: {},
-                },
-                report: {
-                    reportID: '1',
-                },
-                transactionParams: {
-                    created: DateUtils.getDBTime(),
-                    currency: CONST.CURRENCY.USD,
-                    customUnit: {
-                        customUnitID: 'A',
-                        name: CONST.CUSTOM_UNITS.NAME_PER_DIEM_INTERNATIONAL,
-                        customUnitRateID: 'B',
-                        subRates: [{id: '1', name: 'rate_a', quantity: 1, rate: 2}],
-                        attributes: {dates: {end: '', start: ''}},
-                    },
-                    actionableWhisperReportActionID,
-                    linkedTrackedExpenseReportAction,
-                    linkedTrackedExpenseReportID: selfDMReportID,
-                },
-                policyRecentlyUsedCurrencies: [],
-                policyParams: {
-                    policy: {...createRandomPolicy(1)},
-                },
-                quickAction: undefined,
-                betas: [CONST.BETAS.ALL],
-                personalDetails: {[RORY_ACCOUNT_ID]: {accountID: RORY_ACCOUNT_ID, login: RORY_EMAIL}},
-                conciergeReportID: undefined,
-            });
-
-            const createPerDiemRequestCall = writeSpy.mock.calls.find(([command]) => command === WRITE_COMMANDS.CREATE_PER_DIEM_REQUEST);
-            const parameters = createPerDiemRequestCall?.[1] as CreatePerDiemRequestParams | undefined;
-            const onyxData = createPerDiemRequestCall?.[2];
-            expect(parameters?.actionableWhisperReportActionID).toBe(actionableWhisperReportActionID);
-            expect(typeof parameters?.modifiedExpenseReportActionID).toBe('string');
-            const modifiedExpenseReportActionID = parameters?.modifiedExpenseReportActionID;
-            if (!modifiedExpenseReportActionID) {
-                throw new Error('Expected modifiedExpenseReportActionID to be defined');
-            }
-            expect(onyxData?.optimisticData).toEqual(
-                expect.arrayContaining([
-                    expect.objectContaining({
-                        key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${linkedTrackedExpenseReportAction.childReportID}`,
-                        value: expect.objectContaining({
-                            [modifiedExpenseReportActionID]: expect.objectContaining({
-                                actionName: CONST.REPORT.ACTIONS.TYPE.MOVED_TRANSACTION,
-                            }),
-                        }),
-                    }),
-                ]),
-            );
-            expect(onyxData?.optimisticData).toEqual(
-                expect.arrayContaining([
-                    expect.objectContaining({
-                        key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${selfDMReportID}`,
-                        value: expect.objectContaining({
-                            [linkedTrackedExpenseReportAction.reportActionID]: expect.objectContaining({
-                                originalMessage: {IOUTransactionID: null},
-                            }),
-                        }),
-                    }),
-                ]),
-            );
-        });
-
         it('should update policyRecentlyUsedTags when tag is provided', async () => {
             // Given a transaction with a tag
             const iouReportID = '2';
diff --git a/tests/unit/hooks/useExpenseSubmission.test.ts b/tests/unit/hooks/useExpenseSubmission.test.ts
index 08ea679d68da..ea97574cda20 100644
--- a/tests/unit/hooks/useExpenseSubmission.test.ts
+++ b/tests/unit/hooks/useExpenseSubmission.test.ts
@@ -9,6 +9,8 @@ import waitForBatchedUpdatesWithAct from '../../utils/waitForBatchedUpdatesWithA
 
 const mockRequestMoneyAction = jest.fn();
 const mockTrackExpenseAction = jest.fn();
+const mockSubmitPerDiemExpenseAction = jest.fn();
+const mockSubmitPerDiemExpenseForSelfDMAction = jest.fn();
 const mockCleanupAfterExpenseCreate = jest.fn();
 const mockCleanupAndNavigateAfterExpenseCreate = jest.fn();
 const mockResolveChatTargetForSubmitCleanup = jest.fn();
@@ -18,6 +20,11 @@ jest.mock('@userActions/IOU/TrackExpense', () => ({
     trackExpense: (...args: unknown[]) => mockTrackExpenseAction(...args),
 }));
 
+jest.mock('@userActions/IOU/PerDiem', () => ({
+    submitPerDiemExpense: (...args: unknown[]) => mockSubmitPerDiemExpenseAction(...args),
+    submitPerDiemExpenseForSelfDM: (...args: unknown[]) => mockSubmitPerDiemExpenseForSelfDMAction(...args),
+}));
+
 jest.mock('@libs/Navigation/helpers/cleanupAfterExpenseCreate', () => ({
     __esModule: true,
     default: (...args: unknown[]) => mockCleanupAfterExpenseCreate(...args),
@@ -106,6 +113,29 @@ function buildTransaction(overrides: Partial<Transaction> = {}): Transaction {
     } as Transaction;
 }
 
+function buildPerDiemTransaction(overrides: Partial<Transaction> = {}): Transaction {
+    return buildTransaction({
+        amount: 200,
+        merchant: 'Per diem',
+        comment: {
+            comment: 'Trip per diem',
+            customUnit: {
+                customUnitID: 'per-diem-custom-unit',
+                customUnitRateID: 'per-diem-rate',
+                name: CONST.CUSTOM_UNITS.NAME_PER_DIEM_INTERNATIONAL,
+                subRates: [{id: 'sub-rate-1', name: 'Meals', quantity: 1, rate: 200}],
+                attributes: {
+                    dates: {
+                        start: '2026-04-24',
+                        end: '2026-04-24',
+                    },
+                },
+            },
+        },
+        ...overrides,
+    } as Transaction);
+}
+
 function buildParams(overrides: Partial<Parameters<typeof useExpenseSubmission>[0]> = {}): Parameters<typeof useExpenseSubmission>[0] {
     const transaction = buildTransaction();
     return {
@@ -244,6 +274,57 @@ describe('useExpenseSubmission orchestrator-suppressed cleanup', () => {
             expect(mockResolveChatTargetForSubmitCleanup).not.toHaveBeenCalled();
             expect(mockCleanupAndNavigateAfterExpenseCreate).toHaveBeenCalledWith(expect.objectContaining({optimisticChatReportID: 'iou-chat-77'}));
         });
+
+        it('routes tracked per diem SUBMIT through requestMoney so the original tracked expense is moved', async () => {
+            const existingTrackedTransactionID = 'tracked-per-diem-transaction-1';
+            const linkedTrackedExpenseReportAction = {
+                reportActionID: 'tracked-per-diem-action-1',
+                actionName: CONST.REPORT.ACTIONS.TYPE.IOU,
+                childReportID: 'tracked-per-diem-thread-1',
+                created: '2026-04-24',
+                originalMessage: {
+                    IOUTransactionID: existingTrackedTransactionID,
+                    IOUReportID: 'tracked-per-diem-report-1',
+                    type: CONST.IOU.REPORT_ACTION_TYPE.CREATE,
+                },
+            } as unknown as ReportAction;
+            const perDiemTransaction = buildPerDiemTransaction({
+                linkedTrackedExpenseReportAction,
+                linkedTrackedExpenseReportID: 'tracked-per-diem-report-1',
+            });
+
+            const {result} = renderHook(() =>
+                useExpenseSubmission(
+                    buildParams({
+                        action: CONST.IOU.ACTION.SUBMIT,
+                        requestType: CONST.IOU.REQUEST_TYPE.PER_DIEM,
+                        isPerDiemRequest: true,
+                        transaction: perDiemTransaction,
+                        transactions: [perDiemTransaction],
+                    }),
+                ),
+            );
+            await waitForBatchedUpdatesWithAct();
+
+            await act(async () => {
+                result.current.createTransaction(false, true);
+            });
+            await waitForBatchedUpdatesWithAct();
+
+            expect(mockRequestMoneyAction).toHaveBeenCalledTimes(1);
+            expect(mockRequestMoneyAction).toHaveBeenCalledWith(
+                expect.objectContaining({
+                    action: CONST.IOU.ACTION.SUBMIT,
+                    existingTransaction: perDiemTransaction,
+                    transactionParams: expect.objectContaining({
+                        linkedTrackedExpenseReportAction,
+                        linkedTrackedExpenseReportID: 'tracked-per-diem-report-1',
+                    }),
+                }),
+            );
+            expect(mockSubmitPerDiemExpenseAction).not.toHaveBeenCalled();
+            expect(mockSubmitPerDiemExpenseForSelfDMAction).not.toHaveBeenCalled();
+        });
     });
 
     describe('trackExpense path', () => {
@@ -293,6 +374,33 @@ describe('useExpenseSubmission orchestrator-suppressed cleanup', () => {
             expect(mockTrackExpenseAction).toHaveBeenCalledWith(expect.objectContaining({existingTransaction: params.transactions.at(0)}));
         });
     });
+
+    describe('per diem path', () => {
+        it('keeps initial self-DM per diem tracking on submitPerDiemExpenseForSelfDM', async () => {
+            const perDiemTransaction = buildPerDiemTransaction();
+
+            const {result} = renderHook(() =>
+                useExpenseSubmission(
+                    buildParams({
+                        iouType: CONST.IOU.TYPE.TRACK,
+                        requestType: CONST.IOU.REQUEST_TYPE.PER_DIEM,
+                        isPerDiemRequest: true,
+                        transaction: perDiemTransaction,
+                        transactions: [perDiemTransaction],
+                    }),
+                ),
+            );
+            await waitForBatchedUpdatesWithAct();
+
+            await act(async () => {
+                result.current.createTransaction(false, true);
+            });
+            await waitForBatchedUpdatesWithAct();
+
+            expect(mockSubmitPerDiemExpenseForSelfDMAction).toHaveBeenCalledTimes(1);
+            expect(mockRequestMoneyAction).not.toHaveBeenCalled();
+        });
+    });
 });
 
 describe('useExpenseSubmission action-bailout safety', () => {

From 78cf3b2cc7086b12bd99f33b29ac4db36a344cf3 Mon Sep 17 00:00:00 2001
From: Yehor Kharchenko <yehorkharchenko4@gmail.com>
Date: Tue, 9 Jun 2026 11:24:34 +0200
Subject: [PATCH 201/435] add two removed migrations from the first part

---
 .../MoneyRequestHeaderSecondaryActions.tsx    | 15 ++++++-----
 src/hooks/useExpenseActions.ts                | 25 ++++++++++---------
 2 files changed, 20 insertions(+), 20 deletions(-)

diff --git a/src/components/MoneyRequestHeaderSecondaryActions.tsx b/src/components/MoneyRequestHeaderSecondaryActions.tsx
index 803afe512d8d..c4b2001a5723 100644
--- a/src/components/MoneyRequestHeaderSecondaryActions.tsx
+++ b/src/components/MoneyRequestHeaderSecondaryActions.tsx
@@ -3,8 +3,6 @@ import {shouldFailAllRequestsSelector} from '@selectors/Network';
 import {hasSeenTourSelector} from '@selectors/Onboarding';
 import {validTransactionDraftsSelector} from '@selectors/TransactionDraft';
 import React, {useRef, useState} from 'react';
-// eslint-disable-next-line no-restricted-imports
-import {InteractionManager} from 'react-native';
 import type {ValueOf} from 'type-fest';
 import useConfirmModal from '@hooks/useConfirmModal';
 import {useCurrencyListActions} from '@hooks/useCurrencyList';
@@ -84,7 +82,7 @@ type MoneyRequestHeaderSecondaryActionsProps = {
     reportID: string | undefined;
 
     /** Method to trigger when pressing close button of the header */
-    onBackButtonPress: (prioritizeBackTo?: boolean) => void;
+    onBackButtonPress: (prioritizeBackTo?: boolean, options?: {afterTransition?: () => void}) => void;
 };
 
 function MoneyRequestHeaderSecondaryActions({reportID, onBackButtonPress}: MoneyRequestHeaderSecondaryActionsProps) {
@@ -442,6 +440,8 @@ function MoneyRequestHeaderSecondaryActions({reportID, onBackButtonPress}: Money
                     }
                     const backToRoute = route.params?.backTo ?? Navigation.getActiveRoute();
                     setDeleteTransactionNavigateBackUrl(backToRoute);
+
+                    let afterDelete: (() => void) | undefined;
                     if (isTrackExpenseAction(parentReportAction) && !isExpenseSplit) {
                         deleteTrackExpense({
                             chatReportID: report?.parentReportID,
@@ -464,8 +464,7 @@ function MoneyRequestHeaderSecondaryActions({reportID, onBackButtonPress}: Money
                             deleteTransactions([transaction.transactionID], duplicateTransactions, duplicateTransactionViolations, currentSearchHash, true);
                             return;
                         }
-                        // eslint-disable-next-line @typescript-eslint/no-deprecated
-                        InteractionManager.runAfterInteractions(() => {
+                        afterDelete = () => {
                             const deleteResult = deleteTransactions(
                                 [transaction.transactionID],
                                 duplicateTransactions,
@@ -479,14 +478,14 @@ function MoneyRequestHeaderSecondaryActions({reportID, onBackButtonPress}: Money
                             }
 
                             removeTransaction(transaction.transactionID);
-                        });
+                        };
                     }
                     if (isInNarrowPaneModal) {
-                        Navigation.navigateBackToLastSuperWideRHPScreen();
+                        Navigation.navigateBackToLastSuperWideRHPScreen({afterTransition: afterDelete});
                         return;
                     }
 
-                    onBackButtonPress();
+                    onBackButtonPress(false, {afterTransition: afterDelete});
                 });
             },
         },
diff --git a/src/hooks/useExpenseActions.ts b/src/hooks/useExpenseActions.ts
index 1eee933bf7dd..5524591417ec 100644
--- a/src/hooks/useExpenseActions.ts
+++ b/src/hooks/useExpenseActions.ts
@@ -546,18 +546,19 @@ function useExpenseActions({reportID, isReportInSearch = false, backTo, onDuplic
                 setDeleteTransactionNavigateBackUrl(deleteNavigateBackUrl);
 
                 Navigation.setNavigationActionToMicrotaskQueue(() => {
-                    Navigation.goBack(backToRoute);
-                    InteractionManager.runAfterInteractions(() => {
-                        deleteAppReport({
-                            report: moneyRequestReport,
-                            selfDMReport,
-                            currentUserEmailParam: email ?? '',
-                            currentUserAccountIDParam: accountID,
-                            reportTransactions,
-                            allTransactionViolations,
-                            bankAccountList,
-                            hash: currentSearchHash,
-                        });
+                    Navigation.goBack(backToRoute, {
+                        afterTransition: () => {
+                            deleteAppReport({
+                                report: moneyRequestReport,
+                                selfDMReport,
+                                currentUserEmailParam: email ?? '',
+                                currentUserAccountIDParam: accountID,
+                                reportTransactions,
+                                allTransactionViolations,
+                                bankAccountList,
+                                hash: currentSearchHash,
+                            });
+                        },
                     });
                 });
             },

From ebf19de9dce96b97b2193c4dcd016ca11190697b Mon Sep 17 00:00:00 2001
From: MobileMage <aidelojejoshua@gmail.com>
Date: Tue, 9 Jun 2026 12:00:23 +0100
Subject: [PATCH 202/435] Address review feedback: extract helper, type, nav
 guard, add cross-report test

- Extract DiscardedSource type and buildSoftDeleteReportActionUpdate helper
  to reduce duplication in optimistic/failure report action updates
- Guard navigation so dismissModal is used when kept report is already active,
  preventing duplicate stack entries from goBack
- Add cross-report mergeDuplicates unit test mirroring the existing
  resolveDuplicates cross-report test
---
 src/libs/actions/IOU/Duplicate.ts             | 39 +++++----
 .../TransactionDuplicate/Confirmation.tsx     |  7 +-
 tests/actions/IOUTest/DuplicateTest.ts        | 87 +++++++++++++++++++
 3 files changed, 116 insertions(+), 17 deletions(-)

diff --git a/src/libs/actions/IOU/Duplicate.ts b/src/libs/actions/IOU/Duplicate.ts
index 257166082f7e..2ba07831850c 100644
--- a/src/libs/actions/IOU/Duplicate.ts
+++ b/src/libs/actions/IOU/Duplicate.ts
@@ -76,6 +76,26 @@ function getIOUActionForTransactions(transactionIDList: Array<string | undefined
     );
 }
 
+type DiscardedSource = {
+    amount: number;
+    actions: Array<OnyxTypes.ReportAction<typeof CONST.REPORT.ACTIONS.TYPE.IOU>>;
+};
+
+function buildSoftDeleteReportActionUpdate(
+    reportAction: OnyxTypes.ReportAction<typeof CONST.REPORT.ACTIONS.TYPE.IOU>,
+    deletedTime: string | null,
+): NullishDeep<PartialDeep<OnyxTypes.ReportAction<typeof CONST.REPORT.ACTIONS.TYPE.IOU>>> {
+    if (deletedTime === null) {
+        return {originalMessage: {deleted: null}, message: reportAction.message};
+    }
+    const firstMessage = Array.isArray(reportAction.message) ? reportAction.message.at(0) : null;
+    return {
+        originalMessage: {deleted: deletedTime},
+        ...(firstMessage && {message: [{...firstMessage, deleted: deletedTime}, ...(Array.isArray(reportAction.message) ? reportAction.message.slice(1) : [])]}),
+        ...(!Array.isArray(reportAction.message) && {message: {deleted: deletedTime}}),
+    };
+}
+
 type DuplicateTransactionParams = {
     transactionID: string | undefined;
     originalSelectedTransaction: OnyxEntry<OnyxTypes.Transaction>;
@@ -213,7 +233,7 @@ function mergeDuplicates({
 
     // Group each discarded duplicate's IOU action and amount by its own source report so the
     // soft-delete MERGE and total decrement target the correct keys when duplicates span reports.
-    const sources = new Map<string, {amount: number; actions: Array<OnyxTypes.ReportAction<typeof CONST.REPORT.ACTIONS.TYPE.IOU>>}>();
+    const sources = new Map<string, DiscardedSource>();
     for (const id of params.transactionIDList) {
         const transaction = allTransactions[`${ONYXKEYS.COLLECTION.TRANSACTION}${id}`];
         if (!transaction?.reportID) {
@@ -239,25 +259,12 @@ function mergeDuplicates({
         expenseReportActionsOptimisticData.push({
             onyxMethod: Onyx.METHOD.MERGE,
             key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${sourceReportID}`,
-            value: actions.reduce<Record<string, PartialDeep<OnyxTypes.ReportAction<typeof CONST.REPORT.ACTIONS.TYPE.IOU>>>>((val, reportAction) => {
-                const firstMessage = Array.isArray(reportAction.message) ? reportAction.message.at(0) : null;
-                // eslint-disable-next-line no-param-reassign
-                val[reportAction.reportActionID] = {
-                    originalMessage: {deleted: deletedTime},
-                    ...(firstMessage && {message: [{...firstMessage, deleted: deletedTime}, ...(Array.isArray(reportAction.message) ? reportAction.message.slice(1) : [])]}),
-                    ...(!Array.isArray(reportAction.message) && {message: {deleted: deletedTime}}),
-                };
-                return val;
-            }, {}),
+            value: Object.fromEntries(actions.map((a) => [a.reportActionID, buildSoftDeleteReportActionUpdate(a, deletedTime)])),
         });
         expenseReportActionsFailureData.push({
             onyxMethod: Onyx.METHOD.MERGE,
             key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${sourceReportID}`,
-            value: actions.reduce<Record<string, NullishDeep<PartialDeep<OnyxTypes.ReportAction<typeof CONST.REPORT.ACTIONS.TYPE.IOU>>>>>((val, reportAction) => {
-                // eslint-disable-next-line no-param-reassign
-                val[reportAction.reportActionID] = {originalMessage: {deleted: null}, message: reportAction.message};
-                return val;
-            }, {}),
+            value: Object.fromEntries(actions.map((a) => [a.reportActionID, buildSoftDeleteReportActionUpdate(a, null)])),
         });
 
         // Reset the report-preview accumulator per source so each source report's chat parent
diff --git a/src/pages/TransactionDuplicate/Confirmation.tsx b/src/pages/TransactionDuplicate/Confirmation.tsx
index 174c8a0d8a69..28456f38eca8 100644
--- a/src/pages/TransactionDuplicate/Confirmation.tsx
+++ b/src/pages/TransactionDuplicate/Confirmation.tsx
@@ -114,7 +114,12 @@ function Confirmation() {
             Navigation.dismissToSuperWideRHP();
             return;
         }
-        Navigation.goBack(keptReportRoute);
+        const topmostReportID = Navigation.getTopmostReportId?.();
+        if (topmostReportID === mergeParams.reportID) {
+            Navigation.dismissModal();
+        } else {
+            Navigation.goBack(keptReportRoute);
+        }
     }, [childReportID, transactionsMergeParams, taxData, currentUserAccountID, currentUserLogin, isSuperWideRHPDisplayed]);
 
     const handleResolveDuplicates = useCallback(() => {
diff --git a/tests/actions/IOUTest/DuplicateTest.ts b/tests/actions/IOUTest/DuplicateTest.ts
index e86780586aea..58a9b8edee8c 100644
--- a/tests/actions/IOUTest/DuplicateTest.ts
+++ b/tests/actions/IOUTest/DuplicateTest.ts
@@ -663,6 +663,93 @@ describe('actions/Duplicate', () => {
                 }),
             );
         });
+
+        it('should handle cross-report duplicates by cleaning up IOU actions and totals in each source report', async () => {
+            // Given: Duplicate transactions in different reports
+            const keptReportID = 'reportA';
+            const crossReportID = 'reportB';
+            const mainTransactionID = 'mainTx';
+            const crossReportDuplicateID = 'crossDupTx';
+            const childReportIDMain = 'childMain';
+            const childReportIDCross = 'childCross';
+
+            const mainTransaction = createMockTransaction(mainTransactionID, keptReportID, 100);
+            const crossDuplicateTransaction = createMockTransaction(crossReportDuplicateID, crossReportID, 100);
+
+            const keptReport = createMockReport(keptReportID, 200);
+            const crossReport = createMockReport(crossReportID, 200);
+
+            const mainViolations = createMockViolations();
+            const crossDuplicateViolations = createMockViolations();
+
+            const mainIouAction = createMockIouAction(mainTransactionID, 'actionMain', childReportIDMain);
+            const crossIouAction = createMockIouAction(crossReportDuplicateID, 'actionCross', childReportIDCross);
+
+            await Onyx.set(`${ONYXKEYS.COLLECTION.TRANSACTION}${mainTransactionID}`, mainTransaction);
+            await Onyx.set(`${ONYXKEYS.COLLECTION.TRANSACTION}${crossReportDuplicateID}`, crossDuplicateTransaction);
+            await Onyx.set(`${ONYXKEYS.COLLECTION.REPORT}${keptReportID}`, keptReport);
+            await Onyx.set(`${ONYXKEYS.COLLECTION.REPORT}${crossReportID}`, crossReport);
+            await Onyx.set(`${ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS}${mainTransactionID}`, mainViolations);
+            await Onyx.set(`${ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS}${crossReportDuplicateID}`, crossDuplicateViolations);
+            await Onyx.set(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${keptReportID}`, {
+                actionMain: mainIouAction,
+            });
+            await Onyx.set(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${crossReportID}`, {
+                actionCross: crossIouAction,
+            });
+            await Onyx.set(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${childReportIDMain}`, {});
+            await Onyx.set(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${childReportIDCross}`, {});
+            await waitForBatchedUpdates();
+
+            const mergeParams: MergeDuplicatesParams = {
+                transactionID: mainTransactionID,
+                transactionIDList: [crossReportDuplicateID],
+                created: '2024-01-01 12:00:00',
+                merchant: 'Updated Merchant',
+                amount: 100,
+                currency: CONST.CURRENCY.EUR,
+                category: 'Travel',
+                comment: 'Updated comment',
+                billable: true,
+                reimbursable: false,
+                tag: 'UpdatedProject',
+                receiptID: 123,
+                reportID: keptReportID,
+            };
+
+            // When: Call mergeDuplicates with cross-report duplicates
+            mergeDuplicates({...mergeParams, currentUserLogin: RORY_EMAIL, currentUserAccountID: RORY_ACCOUNT_ID});
+            await waitForBatchedUpdates();
+
+            // Then: cross-report IOU action was soft-deleted
+            const crossReportActions = await getOnyxValue(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${crossReportID}`);
+            expect(getOriginalMessage(crossReportActions?.actionCross)).toHaveProperty('deleted');
+
+            // Then: kept report total was NOT decremented (kept transaction stays)
+            const updatedKeptReport = await getOnyxValue(`${ONYXKEYS.COLLECTION.REPORT}${keptReportID}`);
+            expect(updatedKeptReport?.total).toBe(200);
+
+            // Then: cross-report total WAS decremented
+            const updatedCrossReport = await getOnyxValue(`${ONYXKEYS.COLLECTION.REPORT}${crossReportID}`);
+            expect(updatedCrossReport?.total).toBe(100); // 200 - 100 = 100
+
+            // Then: duplicate transaction was removed
+            const removedDuplicate = await getOnyxValue(`${ONYXKEYS.COLLECTION.TRANSACTION}${crossReportDuplicateID}`);
+            expect(removedDuplicate).toBeFalsy();
+
+            // Then: Verify API was called with correct parameters
+            expect(writeSpy).toHaveBeenCalledWith(
+                WRITE_COMMANDS.MERGE_DUPLICATES,
+                expect.objectContaining({
+                    transactionID: mainTransactionID,
+                    transactionIDList: [crossReportDuplicateID],
+                }),
+                expect.objectContaining({
+                    optimisticData: expect.arrayContaining([]),
+                    failureData: expect.arrayContaining([]),
+                }),
+            );
+        });
     });
 
     describe('resolveDuplicates', () => {

From ab148db916dfa2a176c5a4218ff8d33520d124d2 Mon Sep 17 00:00:00 2001
From: Abdelrahman Khattab <abzokhattab@gmail.com>
Date: Tue, 9 Jun 2026 13:23:08 +0200
Subject: [PATCH 203/435] Migrate group-feature isPaidGroupPolicy checks to
 isGroupPolicy for Submit plan

Submit (submit2026) workspaces are free group workspaces, so isPaidGroupPolicy
(team/corporate only) was wrongly excluding them from group features. This audits
every isPaidGroupPolicy call site and migrates the ones gating group features
(violations, report fields, workspace usability/report creation, Submit search tab)
to isGroupPolicy, while leaving billing/paid-only checks untouched.

isGroupPolicy is a strict superset of isPaidGroupPolicy (adds only submit2026), so
behavior is unchanged for Collect/Control/Personal; only the beta Submit plan is affected.
---
 .../MoneyRequestViewReportFields.tsx          |  6 +++---
 .../ReportActionItem/MoneyReportView.tsx      |  8 ++++----
 .../MoneyRequestReceiptView.tsx               |  4 ++--
 .../ReportActionItem/MoneyRequestView.tsx     |  3 +--
 src/hooks/useCreateReport.tsx                 |  4 ++--
 src/hooks/useDefaultExpensePolicy.tsx         |  8 ++++----
 src/hooks/useParticipantSubmission.ts         |  4 ++--
 src/hooks/usePolicyForMovingExpenses.ts       |  4 ++--
 src/hooks/useReceiptScanDrop.tsx              |  4 ++--
 src/libs/IOUUtils.ts                          |  6 +++---
 src/libs/PolicyUtils.ts                       |  6 +++---
 src/libs/ReportUtils.ts                       | 16 ++++++++++++---
 src/libs/TransactionPreviewUtils.ts           | 20 ++++++-------------
 src/libs/actions/IOU/MoneyRequestBuilder.ts   |  6 +++---
 src/libs/actions/IOU/Receipt.ts               |  6 +++---
 src/libs/actions/IOU/UpdateMoneyRequest.ts    |  4 ++--
 src/libs/actions/Transaction.ts               |  8 ++++----
 src/libs/shouldUseDefaultExpensePolicy.ts     |  4 ++--
 src/pages/DynamicEditReportFieldPage.tsx      |  4 ++--
 .../SearchPageNarrow/StaticSearchTypeMenu.tsx | 10 +++++-----
 .../staticPolicyInfoSelector.ts               | 17 ++++++++--------
 src/pages/SetDefaultWorkspacePage.tsx         |  4 ++--
 src/pages/Share/SubmitDetailsPage.tsx         |  4 ++--
 .../AttachmentPickerWithMenuItems.tsx         |  4 ++--
 .../iou/request/ParticipantSearchResults.tsx  |  6 +++---
 .../confirmation/ExpenseDefaultsSetter.tsx    |  4 ++--
 tests/unit/useCreateReportTest.tsx            |  1 +
 27 files changed, 89 insertions(+), 86 deletions(-)

diff --git a/src/components/MoneyRequestReportView/MoneyRequestViewReportFields.tsx b/src/components/MoneyRequestReportView/MoneyRequestViewReportFields.tsx
index c609af3806b9..73d105909a67 100644
--- a/src/components/MoneyRequestReportView/MoneyRequestViewReportFields.tsx
+++ b/src/components/MoneyRequestReportView/MoneyRequestViewReportFields.tsx
@@ -15,8 +15,8 @@ import {
     getFieldViolationTranslation,
     getReportFieldKey,
     getReportFieldMaps,
+    isGroupPolicyExpenseReport as isGroupPolicyExpenseReportUtils,
     isInvoiceReport as isInvoiceReportUtils,
-    isPaidGroupPolicyExpenseReport as isPaidGroupPolicyExpenseReportUtils,
     isReportFieldDisabled,
     isReportFieldDisabledForUser,
     isReportFieldOfTypeTitle,
@@ -119,10 +119,10 @@ function MoneyRequestViewReportFields({report, policy, isCombinedReport = false,
         (reportField) => !isReportFieldDisabled(report, reportField, policy) || reportField.type === CONST.REPORT_FIELD_TYPES.FORMULA,
     );
     const isOnlyTitleFieldEnabled = enabledReportFields.length === 1 && isReportFieldOfTypeTitle(enabledReportFields.at(0));
-    const isPaidGroupPolicyExpenseReport = isPaidGroupPolicyExpenseReportUtils(report);
+    const isGroupPolicyExpenseReport = isGroupPolicyExpenseReportUtils(report);
     const isInvoiceReport = isInvoiceReportUtils(report);
 
-    const shouldDisplayReportFields = (isPaidGroupPolicyExpenseReport || isInvoiceReport) && !!policy?.areReportFieldsEnabled && (!isOnlyTitleFieldEnabled || !isCombinedReport);
+    const shouldDisplayReportFields = (isGroupPolicyExpenseReport || isInvoiceReport) && !!policy?.areReportFieldsEnabled && (!isOnlyTitleFieldEnabled || !isCombinedReport);
 
     if (!shouldDisplayReportFields || !sortedPolicyReportFields.length) {
         return null;
diff --git a/src/components/ReportActionItem/MoneyReportView.tsx b/src/components/ReportActionItem/MoneyReportView.tsx
index b3408917b50a..1e8b277803c6 100644
--- a/src/components/ReportActionItem/MoneyReportView.tsx
+++ b/src/components/ReportActionItem/MoneyReportView.tsx
@@ -33,8 +33,8 @@ import {
     getReportFieldMaps,
     hasUpdatedTotal,
     isClosedExpenseReportWithNoExpenses as isClosedExpenseReportWithNoExpensesReportUtils,
+    isGroupPolicyExpenseReport as isGroupPolicyExpenseReportUtils,
     isInvoiceReport as isInvoiceReportUtils,
-    isPaidGroupPolicyExpenseReport as isPaidGroupPolicyExpenseReportUtils,
     isReportFieldDisabled,
     isReportFieldDisabledForUser,
     isReportFieldOfTypeTitle,
@@ -149,12 +149,12 @@ function MoneyReportView({
     );
     const isOnlyTitleFieldEnabled = enabledReportFields.length === 1 && isReportFieldOfTypeTitle(enabledReportFields.at(0));
     const isClosedExpenseReportWithNoExpenses = isClosedExpenseReportWithNoExpensesReportUtils(report);
-    const isPaidGroupPolicyExpenseReport = isPaidGroupPolicyExpenseReportUtils(report);
+    const isGroupPolicyExpenseReport = isGroupPolicyExpenseReportUtils(report);
     const isInvoiceReport = isInvoiceReportUtils(report);
 
     const shouldShowReportField =
         !isClosedExpenseReportWithNoExpenses &&
-        (isPaidGroupPolicyExpenseReport || isInvoiceReport) &&
+        (isGroupPolicyExpenseReport || isInvoiceReport) &&
         (!isCombinedReport || !isOnlyTitleFieldEnabled) &&
         !sortedPolicyReportFields.every(shouldHideSingleReportField);
 
@@ -183,7 +183,7 @@ function MoneyReportView({
                 {shouldShowAnimatedBackground && <AnimatedEmptyStateBackground />}
                 {!isClosedExpenseReportWithNoExpenses && (
                     <>
-                        {(isPaidGroupPolicyExpenseReport || isInvoiceReport) &&
+                        {(isGroupPolicyExpenseReport || isInvoiceReport) &&
                             !!policy?.areReportFieldsEnabled &&
                             (!isCombinedReport || !isOnlyTitleFieldEnabled) &&
                             sortedPolicyReportFields.map((reportField) => {
diff --git a/src/components/ReportActionItem/MoneyRequestReceiptView.tsx b/src/components/ReportActionItem/MoneyRequestReceiptView.tsx
index 8a635a558816..36129c2e7247 100644
--- a/src/components/ReportActionItem/MoneyRequestReceiptView.tsx
+++ b/src/components/ReportActionItem/MoneyRequestReceiptView.tsx
@@ -51,7 +51,7 @@ import {
     canUserPerformWriteAction as canUserPerformWriteActionReportUtils,
     getCreationReportErrors,
     isInvoiceReport,
-    isPaidGroupPolicy,
+    isReportInGroupPolicy,
     isTrackExpenseReportNew,
 } from '@libs/ReportUtils';
 import trackExpenseCreationError from '@libs/telemetry/trackExpenseCreationError';
@@ -347,7 +347,7 @@ function MoneyRequestReceiptView({
         !isTransactionScanning &&
         (hasReceipt || !!receiptRequiredViolation || !!itemizedReceiptRequiredViolation || !!customRulesViolation) &&
         !!(receiptViolations.length || didReceiptScanSucceed) &&
-        isPaidGroupPolicy(report);
+        isReportInGroupPolicy(report);
     const shouldShowReceiptAudit = !isInvoice && (shouldShowReceiptEmptyState || hasReceipt || hasReceiptUploadError);
 
     const fallbackReceiptError = useMemo(() => {
diff --git a/src/components/ReportActionItem/MoneyRequestView.tsx b/src/components/ReportActionItem/MoneyRequestView.tsx
index 2cd705181d07..95a4f435ca61 100644
--- a/src/components/ReportActionItem/MoneyRequestView.tsx
+++ b/src/components/ReportActionItem/MoneyRequestView.tsx
@@ -82,7 +82,6 @@ import {
     isExpenseReport,
     isInvoiceReport,
     isOpenReport,
-    isPaidGroupPolicy,
     isReportApproved,
     isReportInGroupPolicy,
     isSettled as isSettledReportUtils,
@@ -483,7 +482,7 @@ function MoneyRequestView({
     const tripRoomName = tripRoomInfo?.name;
     const shouldShowTripRoomLink = !!tripRoomReportID && !!tripRoomName;
 
-    const {getViolationsForField} = useViolations(transactionViolations ?? [], isTransactionScanning || !isPaidGroupPolicy(transactionThreadReport));
+    const {getViolationsForField} = useViolations(transactionViolations ?? [], isTransactionScanning || !isReportInGroupPolicy(transactionThreadReport));
     const hasViolations = (field: ViolationField, data?: OnyxTypes.TransactionViolation['data'], policyHasDependentTags = false, tagValue?: string): boolean =>
         getViolationsForField(field, data, policyHasDependentTags, tagValue).length > 0;
     const isMarkAsCash = parentReport && currentUserEmailParam ? isMarkAsCashActionForTransaction(currentUserEmailParam, parentReport, transactionViolations, policy) : false;
diff --git a/src/hooks/useCreateReport.tsx b/src/hooks/useCreateReport.tsx
index 65df7e71255b..0b0225de3bec 100644
--- a/src/hooks/useCreateReport.tsx
+++ b/src/hooks/useCreateReport.tsx
@@ -3,7 +3,7 @@ import type {OnyxEntry} from 'react-native-onyx';
 import interceptAnonymousUser from '@libs/interceptAnonymousUser';
 import createDynamicRoute from '@libs/Navigation/helpers/dynamicRoutesUtils/createDynamicRoute';
 import Navigation from '@libs/Navigation/Navigation';
-import {getDefaultChatEnabledPolicy, isPaidGroupPolicy} from '@libs/PolicyUtils';
+import {getDefaultChatEnabledPolicy, isGroupPolicy} from '@libs/PolicyUtils';
 import {generateReportID} from '@libs/ReportUtils';
 import {shouldRestrictUserBillableActions} from '@libs/SubscriptionUtils';
 import CONST from '@src/CONST';
@@ -104,7 +104,7 @@ export default function useCreateReport({
             // at least 2 non-personal workspaces to choose between. Also fall back to the selector if
             // the default is billing-restricted and alternatives exist, so the user isn't dead-ended
             // on the restricted-action page.
-            const isDefaultPersonal = !activePolicy || activePolicy.type === CONST.POLICY.TYPE.PERSONAL || !isPaidGroupPolicy(activePolicy);
+            const isDefaultPersonal = !activePolicy || activePolicy.type === CONST.POLICY.TYPE.PERSONAL || !isGroupPolicy(activePolicy);
             const hasMultipleNonPersonalWorkspaces = groupPoliciesWithChatEnabled.length > 1;
             const isDefaultBillingRestricted =
                 !!workspaceIDForReportCreation && shouldRestrictUserBillableActions(defaultChatEnabledPolicy, ownerBillingGracePeriodEnd, userBillingGracePeriodEnds, amountOwed, accountID);
diff --git a/src/hooks/useDefaultExpensePolicy.tsx b/src/hooks/useDefaultExpensePolicy.tsx
index 32630fafff88..850004e037d9 100644
--- a/src/hooks/useDefaultExpensePolicy.tsx
+++ b/src/hooks/useDefaultExpensePolicy.tsx
@@ -1,5 +1,5 @@
 import type {OnyxCollection} from 'react-native-onyx';
-import {isPaidGroupPolicy, isPolicyAccessible} from '@libs/PolicyUtils';
+import {isGroupPolicy, isPolicyAccessible} from '@libs/PolicyUtils';
 import ONYXKEYS from '@src/ONYXKEYS';
 import type {Policy} from '@src/types/onyx';
 import useCurrentUserPersonalDetails from './useCurrentUserPersonalDetails';
@@ -17,7 +17,7 @@ function getSingleGroupPolicyID(policies: OnyxCollection<Policy>, login: string)
 
     let singlePolicyID: string | undefined;
     for (const policy of Object.values(policies)) {
-        if (!policy || !isPaidGroupPolicy(policy) || !isPolicyAccessible(policy, login)) {
+        if (!policy || !isGroupPolicy(policy) || !isPolicyAccessible(policy, login)) {
             continue;
         }
         if (!singlePolicyID) {
@@ -45,11 +45,11 @@ export default function useDefaultExpensePolicy() {
     // Per-key lookup for the single group policy (only fires when that specific policy changes)
     const [singleGroupPolicy] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY}${singleGroupPolicyID}`);
 
-    if (isRestrictedToPreferredPolicy && isPaidGroupPolicy(preferredPolicy) && isPolicyAccessible(preferredPolicy, login)) {
+    if (isRestrictedToPreferredPolicy && isGroupPolicy(preferredPolicy) && isPolicyAccessible(preferredPolicy, login)) {
         return preferredPolicy;
     }
 
-    if (isPaidGroupPolicy(activePolicy) && isPolicyAccessible(activePolicy, login)) {
+    if (isGroupPolicy(activePolicy) && isPolicyAccessible(activePolicy, login)) {
         return activePolicy;
     }
 
diff --git a/src/hooks/useParticipantSubmission.ts b/src/hooks/useParticipantSubmission.ts
index fe1dd0ec9fc6..7162ff00acff 100644
--- a/src/hooks/useParticipantSubmission.ts
+++ b/src/hooks/useParticipantSubmission.ts
@@ -5,7 +5,7 @@ import {READ_COMMANDS} from '@libs/API/types';
 import DistanceRequestUtils from '@libs/DistanceRequestUtils';
 import HttpUtils from '@libs/HttpUtils';
 import Navigation from '@libs/Navigation/Navigation';
-import {isPaidGroupPolicy} from '@libs/PolicyUtils';
+import {isGroupPolicy} from '@libs/PolicyUtils';
 import {findSelfDMReportID, generateReportID, isInvoiceRoomWithID} from '@libs/ReportUtils';
 import {shouldRestrictUserBillableActions} from '@libs/SubscriptionUtils';
 import {isDistanceRequest} from '@libs/TransactionUtils';
@@ -96,7 +96,7 @@ function useParticipantSubmission({
 
     const isActivePolicyRequest =
         iouType === CONST.IOU.TYPE.CREATE &&
-        isPaidGroupPolicy(activePolicy) &&
+        isGroupPolicy(activePolicy) &&
         activePolicy?.isPolicyExpenseChatEnabled &&
         !shouldRestrictUserBillableActions(activePolicy, ownerBillingGracePeriodEnd, userBillingGracePeriodEnds, amountOwed, currentUserPersonalDetails.accountID);
 
diff --git a/src/hooks/usePolicyForMovingExpenses.ts b/src/hooks/usePolicyForMovingExpenses.ts
index b3f88e88a2ac..74f3e8384158 100644
--- a/src/hooks/usePolicyForMovingExpenses.ts
+++ b/src/hooks/usePolicyForMovingExpenses.ts
@@ -1,7 +1,7 @@
 import {activePolicySelector} from '@selectors/Policy';
 import type {OnyxCollection, OnyxEntry} from 'react-native-onyx';
 import {useSession} from '@components/OnyxListItemProvider';
-import {canSubmitPerDiemExpenseFromWorkspace, isPaidGroupPolicy, isPolicyMemberWithoutPendingDelete, isTimeTrackingEnabled} from '@libs/PolicyUtils';
+import {canSubmitPerDiemExpenseFromWorkspace, isGroupPolicy, isPolicyMemberWithoutPendingDelete, isTimeTrackingEnabled} from '@libs/PolicyUtils';
 import CONST from '@src/CONST';
 import ONYXKEYS from '@src/ONYXKEYS';
 import type {Policy} from '@src/types/onyx';
@@ -24,7 +24,7 @@ function isPolicyValidForMovingExpenses(policy: OnyxEntry<Policy>, login: string
     return (
         checkForUserPendingDelete(login, policy) &&
         isPolicyMemberByRole(policy) &&
-        isPaidGroupPolicy(policy) &&
+        isGroupPolicy(policy) &&
         policy?.pendingAction !== CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE &&
         (!isPerDiemRequest || canSubmitPerDiemExpenseFromWorkspace(policy)) &&
         (!isTimeRequest || isTimeTrackingEnabled(policy))
diff --git a/src/hooks/useReceiptScanDrop.tsx b/src/hooks/useReceiptScanDrop.tsx
index 0ea8a8ac55d4..6e519cc74611 100644
--- a/src/hooks/useReceiptScanDrop.tsx
+++ b/src/hooks/useReceiptScanDrop.tsx
@@ -3,7 +3,7 @@ import React, {useMemo} from 'react';
 import {setTransactionReport} from '@libs/actions/Transaction';
 import {navigateToParticipantPage} from '@libs/IOUUtils';
 import Navigation from '@libs/Navigation/Navigation';
-import {hasOnlyPersonalPolicies as hasOnlyPersonalPoliciesUtil, isPaidGroupPolicy} from '@libs/PolicyUtils';
+import {hasOnlyPersonalPolicies as hasOnlyPersonalPoliciesUtil, isGroupPolicy} from '@libs/PolicyUtils';
 import {generateReportID, getPolicyExpenseChat, isSelfDM} from '@libs/ReportUtils';
 import {shouldRestrictUserBillableActions} from '@libs/SubscriptionUtils';
 import type {ReceiptFile} from '@pages/iou/request/step/IOURequestStepScan/types';
@@ -80,7 +80,7 @@ function useReceiptScanDrop() {
         }
 
         if (
-            isPaidGroupPolicy(activePolicy) &&
+            isGroupPolicy(activePolicy) &&
             activePolicy?.isPolicyExpenseChatEnabled &&
             !shouldRestrictUserBillableActions(activePolicy, ownerBillingGracePeriodEnd, userBillingGracePeriodEnds, amountOwed, currentUserPersonalDetails.accountID)
         ) {
diff --git a/src/libs/IOUUtils.ts b/src/libs/IOUUtils.ts
index e8efb813640c..e7b5b0634351 100644
--- a/src/libs/IOUUtils.ts
+++ b/src/libs/IOUUtils.ts
@@ -8,7 +8,7 @@ import type {Attendee, Participant} from '@src/types/onyx/IOU';
 import SafeString from '@src/utils/SafeString';
 import {getCurrencyUnit} from './CurrencyUtils';
 import Navigation from './Navigation/Navigation';
-import {isPaidGroupPolicy} from './PolicyUtils';
+import {isGroupPolicy} from './PolicyUtils';
 import {getOriginalMessage, isMoneyRequestAction} from './ReportActionsUtils';
 import {generateReportID, getChatByParticipants, isProcessingReport, isReportOutstanding, isSelfDM} from './ReportUtils';
 import {endSpan, getSpan, startSpan} from './telemetry/activeSpans';
@@ -316,7 +316,7 @@ function shouldShowReceiptEmptyState(iouType: IOUType, action: IOUAction, policy
     return (
         (iouType === CONST.IOU.TYPE.SUBMIT || iouType === CONST.IOU.TYPE.TRACK || iouType === CONST.IOU.TYPE.PAY || iouType === CONST.IOU.TYPE.CREATE) &&
         !isPerDiemRequest &&
-        (!isMovingTransactionFromTrackExpense(action) || isPaidGroupPolicy(policy))
+        (!isMovingTransactionFromTrackExpense(action) || isGroupPolicy(policy))
     );
 }
 
@@ -422,7 +422,7 @@ function calculateDefaultReimbursable({
     const isUnreported = transactionReportID === CONST.REPORT.UNREPORTED_REPORT_ID;
     const isPolicyExpenseChat = !!participant?.isPolicyExpenseChat;
     const reportPolicy = isCreatingTrackExpense || isUnreported ? policyForMovingExpenses : policy;
-    return (isPolicyExpenseChat && isPaidGroupPolicy(reportPolicy)) || isCreatingTrackExpense ? (reportPolicy?.defaultReimbursable ?? true) : true;
+    return (isPolicyExpenseChat && isGroupPolicy(reportPolicy)) || isCreatingTrackExpense ? (reportPolicy?.defaultReimbursable ?? true) : true;
 }
 
 function getInitialPerDiemTargetReport(
diff --git a/src/libs/PolicyUtils.ts b/src/libs/PolicyUtils.ts
index 2f04ad026d49..d8de6607b7dd 100644
--- a/src/libs/PolicyUtils.ts
+++ b/src/libs/PolicyUtils.ts
@@ -1112,9 +1112,9 @@ function canEditWorkspaceSettings(policy: OnyxInputOrEntry<Policy>, login?: stri
 /**
  * Returns true for any group workspace: paid (Team/Corporate) or Submit.
  *
- * Note: not to be confused with `ReportUtils.isGroupPolicy(policyType: string)`,
- * which excludes Submit. Use this helper when Submit workspaces should be treated
- * like paid workspaces (e.g. access gating for shared workspace pages).
+ * Use this helper when Submit workspaces should be treated like paid workspaces
+ * (e.g. access gating for shared workspace pages). For report-based call sites,
+ * use `ReportUtils.isReportInGroupPolicy(report)`, which delegates to this helper.
  */
 function isGroupPolicy(policy: OnyxInputOrEntry<Policy>): boolean {
     return isPaidGroupPolicy(policy) || isSubmitPolicy(policy);
diff --git a/src/libs/ReportUtils.ts b/src/libs/ReportUtils.ts
index 2bba8bd2c0dc..2414e83c088d 100644
--- a/src/libs/ReportUtils.ts
+++ b/src/libs/ReportUtils.ts
@@ -1763,6 +1763,15 @@ function isPaidGroupPolicyExpenseReport(report: OnyxEntry<Report>): boolean {
     return isExpenseReport(report) && isPaidGroupPolicy(report);
 }
 
+/**
+ * Whether the provided report belongs to a group policy (Collect, Control, or Submit) and is an expense report.
+ * Use this instead of `isPaidGroupPolicyExpenseReport` for features that Submit workspaces also support
+ * (e.g. report fields), so the free Submit plan isn't incorrectly excluded.
+ */
+function isGroupPolicyExpenseReport(report: OnyxEntry<Report>): boolean {
+    return isExpenseReport(report) && isReportInGroupPolicy(report);
+}
+
 /**
  * Checks if the supplied report is an invoice report in Open state and status.
  */
@@ -4527,7 +4536,7 @@ function canEditReportTitle(report: OnyxEntry<Report>, policy: OnyxEntry<Policy>
         getAvailableReportFields(report, Object.values(policy?.fieldList ?? {})).find((reportField) => isReportFieldOfTypeTitle(reportField)) ?? getTitleFieldWithFallback(policy);
     const isFieldDisabled = isReportFieldDisabled(report, titleField, policy);
 
-    return !isFieldDisabled && isAdminOwnerApproverOrReportOwner(report, policy, currentUserAccountID) && isExpenseReport(report) && isPaidGroupPolicyPolicyUtils(policy);
+    return !isFieldDisabled && isAdminOwnerApproverOrReportOwner(report, policy, currentUserAccountID) && isExpenseReport(report) && isGroupPolicyPolicyUtils(policy);
 }
 
 /**
@@ -11653,7 +11662,7 @@ function getOutstandingChildRequest(iouReport: OnyxInputOrEntry<Report>): Outsta
 
     // This will be fixed as part of https://github.com/Expensify/Expensify/issues/507850
     const policy = getPolicy(iouReport.policyID);
-    const shouldBeManuallySubmitted = isPaidGroupPolicyPolicyUtils(policy) && !policy?.harvesting?.enabled && isOpenReport(iouReport);
+    const shouldBeManuallySubmitted = isGroupPolicyPolicyUtils(policy) && !policy?.harvesting?.enabled && isOpenReport(iouReport);
     if (shouldBeManuallySubmitted) {
         return {
             hasOutstandingChildRequest: true,
@@ -12602,7 +12611,7 @@ function isWorkspaceEligibleForReportChange(submitterEmail: string | undefined,
     if (report?.stateNum === CONST.REPORT.STATE_NUM.APPROVED && report.statusNum === CONST.REPORT.STATUS_NUM.CLOSED && !isPolicyAdminPolicyUtils(newPolicy)) {
         return false;
     }
-    return isPaidGroupPolicyPolicyUtils(newPolicy) && !!newPolicy.role && !isPendingDeletePolicy(newPolicy);
+    return isGroupPolicyPolicyUtils(newPolicy) && !!newPolicy.role && !isPendingDeletePolicy(newPolicy);
 }
 
 /**
@@ -13480,6 +13489,7 @@ export {
     isOptimisticPersonalDetail,
     isPaidGroupPolicy,
     isPaidGroupPolicyExpenseReport,
+    isGroupPolicyExpenseReport,
     isPayer,
     isPolicyAdmin,
     isPolicyExpenseChat,
diff --git a/src/libs/TransactionPreviewUtils.ts b/src/libs/TransactionPreviewUtils.ts
index c776205cad23..b28fce6c5f67 100644
--- a/src/libs/TransactionPreviewUtils.ts
+++ b/src/libs/TransactionPreviewUtils.ts
@@ -12,15 +12,7 @@ import {isCategoryMissing} from './CategoryUtils';
 import DateUtils from './DateUtils';
 import {hasDynamicExternalWorkflow} from './PolicyUtils';
 import {getMostRecentActiveDEWSubmitFailedAction, getOriginalMessage, isDynamicExternalWorkflowSubmitFailedAction, isMessageDeleted, isMoneyRequestAction} from './ReportActionsUtils';
-import {
-    hasActionWithErrorsForTransaction,
-    hasReceiptError,
-    isExpenseReport,
-    isPaidGroupPolicyExpenseReport,
-    isPaidGroupPolicy as isPaidGroupPolicyUtil,
-    isReportApproved,
-    isSettled,
-} from './ReportUtils';
+import {hasActionWithErrorsForTransaction, hasReceiptError, isExpenseReport, isPaidGroupPolicyExpenseReport, isReportApproved, isReportInGroupPolicy, isSettled} from './ReportUtils';
 import type {ActionErrorsByTransaction, TransactionDetails} from './ReportUtils';
 import StringUtils from './StringUtils';
 import {
@@ -240,9 +232,9 @@ function getTransactionPreviewTextAndTranslationPaths({
     const shouldShowHoldMessage = !(isMoneyRequestSettled && !isSettlementOrApprovalPartial) && !!transaction?.comment?.hold;
     const isTransactionScanning = isScanning(transaction);
     const hasFieldErrors = hasMissingSmartscanFields(transaction, iouReport);
-    const isPaidGroupPolicy = isPaidGroupPolicyUtil(iouReport);
+    const isGroupPolicyReport = isReportInGroupPolicy(iouReport);
 
-    const hasViolationsOfTypeNotice = hasNoticeTypeViolation(transaction, violations, currentUserEmail ?? '', currentUserAccountID, iouReport, policy, true) && isPaidGroupPolicy;
+    const hasViolationsOfTypeNotice = hasNoticeTypeViolation(transaction, violations, currentUserEmail ?? '', currentUserAccountID, iouReport, policy, true) && isGroupPolicyReport;
     const hasActionWithErrors = hasActionWithErrorsForTransaction(iouReport?.reportID, transaction, reportActions);
 
     const {amount: requestAmount, currency: requestCurrency} = transactionDetails;
@@ -257,7 +249,7 @@ function getTransactionPreviewTextAndTranslationPaths({
         RBRMessage = {translationPath: 'iou.expenseWasPutOnHold'};
     }
 
-    const path = getViolationTranslatePath(violations, hasFieldErrors, violationMessage ?? '', isTransactionOnHold, !isPaidGroupPolicy);
+    const path = getViolationTranslatePath(violations, hasFieldErrors, violationMessage ?? '', isTransactionOnHold, !isGroupPolicyReport);
     if (path.translationPath === 'violations.reviewRequired' || (RBRMessage === undefined && violationMessage)) {
         RBRMessage = path;
     }
@@ -404,7 +396,7 @@ function createTransactionPreviewConditionals({
     const isSettlementOrApprovalPartial = !!iouReport?.pendingFields?.partial;
 
     const hasViolationsOfTypeNotice =
-        hasNoticeTypeViolation(transaction, violations, currentUserEmail ?? '', currentUserAccountID, iouReport ?? undefined, policy, true) && iouReport && isPaidGroupPolicyUtil(iouReport);
+        hasNoticeTypeViolation(transaction, violations, currentUserEmail ?? '', currentUserAccountID, iouReport ?? undefined, policy, true) && iouReport && isReportInGroupPolicy(iouReport);
     const hasFieldErrors = hasMissingSmartscanFields(transaction, iouReport);
 
     const isFetchingWaypoints = isFetchingWaypointsFromServer(transaction);
@@ -491,7 +483,7 @@ function transactionHasRBR(
     }
 
     // Check for notice-type violations (only on paid group policies)
-    if (hasNoticeTypeViolation(transaction, violations, currentUserEmail, currentUserAccountID, iouReport, policy, true) && isPaidGroupPolicyUtil(iouReport)) {
+    if (hasNoticeTypeViolation(transaction, violations, currentUserEmail, currentUserAccountID, iouReport, policy, true) && isReportInGroupPolicy(iouReport)) {
         return true;
     }
 
diff --git a/src/libs/actions/IOU/MoneyRequestBuilder.ts b/src/libs/actions/IOU/MoneyRequestBuilder.ts
index 5def3efdfd77..54b6761cad23 100644
--- a/src/libs/actions/IOU/MoneyRequestBuilder.ts
+++ b/src/libs/actions/IOU/MoneyRequestBuilder.ts
@@ -12,7 +12,7 @@ import {translateLocal} from '@libs/Localize';
 import {buildNextStepNew, buildOptimisticNextStep} from '@libs/NextStepUtils';
 import {rand64} from '@libs/NumberUtils';
 import {addSMSDomainIfPhoneNumber} from '@libs/PhoneNumber';
-import {hasDependentTags, isPaidGroupPolicy} from '@libs/PolicyUtils';
+import {hasDependentTags, isGroupPolicy} from '@libs/PolicyUtils';
 import {getOriginalMessage, getReportActionHtml, getReportActionText, isReportPreviewAction} from '@libs/ReportActionsUtils';
 import type {OptimisticChatReport, OptimisticCreatedReportAction, OptimisticIOUReportAction} from '@libs/ReportUtils';
 import {
@@ -1082,8 +1082,8 @@ function buildOnyxDataForMoneyRequest(moneyRequestParams: BuildOnyxDataForMoneyR
         }
     }
 
-    // We don't need to compute violations unless we're on a paid policy
-    if (!policy || !isPaidGroupPolicy(policy) || transaction.reportID === CONST.REPORT.UNREPORTED_REPORT_ID) {
+    // We don't need to compute violations unless we're on a group policy (Collect, Control, or Submit)
+    if (!policy || !isGroupPolicy(policy) || transaction.reportID === CONST.REPORT.UNREPORTED_REPORT_ID) {
         return onyxData;
     }
     const violationsOnyxData = ViolationsUtils.getViolationsOnyxData({
diff --git a/src/libs/actions/IOU/Receipt.ts b/src/libs/actions/IOU/Receipt.ts
index 391592ca6bbc..27f429798fab 100644
--- a/src/libs/actions/IOU/Receipt.ts
+++ b/src/libs/actions/IOU/Receipt.ts
@@ -8,7 +8,7 @@ import {getMicroSecondOnyxErrorWithTranslationKey} from '@libs/ErrorUtils';
 import {readFileAsync} from '@libs/fileDownload/FileUtils';
 import {navigateToStartMoneyRequestStep} from '@libs/IOUUtils';
 import Navigation from '@libs/Navigation/Navigation';
-import {hasDependentTags, isPaidGroupPolicy} from '@libs/PolicyUtils';
+import {hasDependentTags, isGroupPolicy} from '@libs/PolicyUtils';
 import {buildOptimisticDetachReceipt, isInvoiceReport as isInvoiceReportReportUtils} from '@libs/ReportUtils';
 import {getCurrentSearchQueryJSON} from '@libs/SearchQueryUtils';
 import ViolationsUtils from '@libs/Violations/ViolationsUtils';
@@ -101,7 +101,7 @@ function detachReceipt(
         },
     ];
 
-    if (transactionPolicy && isPaidGroupPolicy(transactionPolicy) && newTransaction) {
+    if (transactionPolicy && isGroupPolicy(transactionPolicy) && newTransaction) {
         const currentTransactionViolations = allTransactionViolations[`${ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS}${transactionID}`] ?? [];
         const violationsOnyxData = ViolationsUtils.getViolationsOnyxData({
             updatedTransaction: newTransaction,
@@ -239,7 +239,7 @@ function replaceReceipt({transactionID, file, source, state, transactionPolicy,
         },
     ];
 
-    if (transactionPolicy && isPaidGroupPolicy(transactionPolicy) && newTransaction) {
+    if (transactionPolicy && isGroupPolicy(transactionPolicy) && newTransaction) {
         const currentTransactionViolations = allTransactionViolations[`${ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS}${transactionID}`] ?? [];
         const violationsOnyxData = ViolationsUtils.getViolationsOnyxData({
             updatedTransaction: newTransaction,
diff --git a/src/libs/actions/IOU/UpdateMoneyRequest.ts b/src/libs/actions/IOU/UpdateMoneyRequest.ts
index dca8086ca4be..162494c4e2f0 100644
--- a/src/libs/actions/IOU/UpdateMoneyRequest.ts
+++ b/src/libs/actions/IOU/UpdateMoneyRequest.ts
@@ -9,7 +9,7 @@ import DistanceRequestUtils from '@libs/DistanceRequestUtils';
 import {getMicroSecondOnyxErrorWithTranslationKey} from '@libs/ErrorUtils';
 import {buildNextStepNew, buildOptimisticNextStep} from '@libs/NextStepUtils';
 import {rand64} from '@libs/NumberUtils';
-import {hasDependentTags, isPaidGroupPolicy} from '@libs/PolicyUtils';
+import {hasDependentTags, isGroupPolicy} from '@libs/PolicyUtils';
 import type {TransactionDetails} from '@libs/ReportUtils';
 import {
     buildOptimisticModifiedExpenseReportAction,
@@ -1620,7 +1620,7 @@ function getUpdateMoneyRequestParams(params: GetUpdateMoneyRequestParamsType): U
     if (
         transactionID &&
         policy &&
-        isPaidGroupPolicy(policy) &&
+        isGroupPolicy(policy) &&
         !isInvoice &&
         updatedTransaction &&
         (hasPendingWaypoints ||
diff --git a/src/libs/actions/Transaction.ts b/src/libs/actions/Transaction.ts
index 91825cda8dec..728019a9b791 100644
--- a/src/libs/actions/Transaction.ts
+++ b/src/libs/actions/Transaction.ts
@@ -21,7 +21,7 @@ import {translateLocal} from '@libs/Localize';
 import {buildNextStepNew, buildOptimisticNextStep} from '@libs/NextStepUtils';
 import * as NumberUtils from '@libs/NumberUtils';
 import {rand64, roundToTwoDecimalPlaces} from '@libs/NumberUtils';
-import {getDistanceRateCustomUnitRate, hasDependentTags, isPaidGroupPolicy} from '@libs/PolicyUtils';
+import {getDistanceRateCustomUnitRate, hasDependentTags, isGroupPolicy} from '@libs/PolicyUtils';
 import {
     getAllReportActions,
     getIOUActionForReportID,
@@ -1169,7 +1169,7 @@ function changeTransactionsReport({
         // Auto-select a valid default distance rate when moving to a workspace where the current rate is invalid,
         // and recalculate derived fields (amount, merchant, currency) to match the new rate.
         let transactionForViolations = transaction;
-        if (isPaidGroupPolicy(policy) && policy?.id && isDistanceRequest(transaction)) {
+        if (isGroupPolicy(policy) && policy?.id && isDistanceRequest(transaction)) {
             const currentRateID = transaction.comment?.customUnit?.customUnitRateID;
             const currentRate = currentRateID ? getDistanceRateCustomUnitRate(policy, currentRateID) : undefined;
             if (!currentRateID || !currentRate || currentRate.enabled === false) {
@@ -1269,7 +1269,7 @@ function changeTransactionsReport({
 
         let transactionReimbursable = transaction.reimbursable;
         // 2. Calculate transaction violations if moving transaction to a workspace
-        if (isPaidGroupPolicy(policy) && policy?.id) {
+        if (isGroupPolicy(policy) && policy?.id) {
             const violationData = ViolationsUtils.getViolationsOnyxData({
                 updatedTransaction: transactionForViolations,
                 transactionViolations: currentTransactionViolations[transaction.transactionID] ?? [],
@@ -1666,7 +1666,7 @@ function changeTransactionsReport({
 
     const reportTransactions = getReportTransactions(reportID);
     for (const transaction of reportTransactions) {
-        if (!isPaidGroupPolicy(policy) || !policy?.id) {
+        if (!isGroupPolicy(policy) || !policy?.id) {
             continue;
         }
         const violationData = ViolationsUtils.getViolationsOnyxData({
diff --git a/src/libs/shouldUseDefaultExpensePolicy.ts b/src/libs/shouldUseDefaultExpensePolicy.ts
index 68e454f0260c..504705e3718d 100644
--- a/src/libs/shouldUseDefaultExpensePolicy.ts
+++ b/src/libs/shouldUseDefaultExpensePolicy.ts
@@ -2,7 +2,7 @@ import type {OnyxCollection, OnyxEntry} from 'react-native-onyx';
 import type {IOUType} from '@src/CONST';
 import CONST from '@src/CONST';
 import type {BillingGraceEndPeriod, OnyxInputOrEntry, Policy} from '@src/types/onyx';
-import {isPaidGroupPolicy} from './PolicyUtils';
+import {isGroupPolicy} from './PolicyUtils';
 import {shouldRestrictUserBillableActions} from './SubscriptionUtils';
 
 function shouldUseDefaultExpensePolicy(
@@ -15,7 +15,7 @@ function shouldUseDefaultExpensePolicy(
 ) {
     return (
         iouType === CONST.IOU.TYPE.CREATE &&
-        isPaidGroupPolicy(defaultExpensePolicy) &&
+        isGroupPolicy(defaultExpensePolicy) &&
         defaultExpensePolicy?.isPolicyExpenseChatEnabled &&
         !shouldRestrictUserBillableActions(defaultExpensePolicy, ownerBillingGracePeriodEnd, userBillingGracePeriodEnds, amountOwed, currentUserAccountID)
     );
diff --git a/src/pages/DynamicEditReportFieldPage.tsx b/src/pages/DynamicEditReportFieldPage.tsx
index 42cc4164dd24..55d3522dd929 100644
--- a/src/pages/DynamicEditReportFieldPage.tsx
+++ b/src/pages/DynamicEditReportFieldPage.tsx
@@ -26,8 +26,8 @@ import {
     getReportFieldKey,
     getTitleFieldWithFallback,
     hasViolations as hasViolationsReportUtils,
+    isGroupPolicyExpenseReport,
     isInvoiceReport,
-    isPaidGroupPolicyExpenseReport,
     isReportFieldDisabled,
     isReportFieldDisabledForUser,
     isReportFieldOfTypeTitle,
@@ -77,7 +77,7 @@ function DynamicEditReportFieldPage({route}: DynamicEditReportFieldPageProps) {
     const {showConfirmModal} = useConfirmModal();
     const icons = useMemoizedLazyExpensifyIcons(['Trashcan']);
     const isReportFieldTitle = isReportFieldOfTypeTitle(reportField);
-    const reportFieldsEnabled = ((isPaidGroupPolicyExpenseReport(report) || isInvoiceReport(report)) && !!policy?.areReportFieldsEnabled) || isReportFieldTitle;
+    const reportFieldsEnabled = ((isGroupPolicyExpenseReport(report) || isInvoiceReport(report)) && !!policy?.areReportFieldsEnabled) || isReportFieldTitle;
     const hasOtherViolations =
         report?.fieldList && Object.entries(report.fieldList).some(([key, field]) => key !== fieldKey && field.value === '' && !isReportFieldDisabled(report, reportField, policy));
 
diff --git a/src/pages/Search/SearchPageNarrow/StaticSearchTypeMenu.tsx b/src/pages/Search/SearchPageNarrow/StaticSearchTypeMenu.tsx
index d348ea95d2fe..0d4af448002d 100644
--- a/src/pages/Search/SearchPageNarrow/StaticSearchTypeMenu.tsx
+++ b/src/pages/Search/SearchPageNarrow/StaticSearchTypeMenu.tsx
@@ -15,11 +15,11 @@ import CONST from '@src/CONST';
 import ONYXKEYS from '@src/ONYXKEYS';
 import staticPolicyInfoSelector from './staticPolicyInfoSelector';
 
-function getActiveKey(similarSearchHash: number, hasPaidGroupPolicy: boolean, searches: Record<string, SearchTypeMenuItem>): string {
+function getActiveKey(similarSearchHash: number, hasGroupPolicy: boolean, searches: Record<string, SearchTypeMenuItem>): string {
     const reportsSearch = searches[CONST.SEARCH.SEARCH_KEYS.REPORTS];
     const expensesSearch = searches[CONST.SEARCH.SEARCH_KEYS.EXPENSES];
     const submitSearch = searches[CONST.SEARCH.SEARCH_KEYS.SUBMIT];
-    const candidates = [reportsSearch, expensesSearch, ...(hasPaidGroupPolicy ? [submitSearch] : [])];
+    const candidates = [reportsSearch, expensesSearch, ...(hasGroupPolicy ? [submitSearch] : [])];
     return candidates.find((entry) => similarSearchHash === entry.similarSearchHash)?.key ?? reportsSearch.key;
 }
 
@@ -27,7 +27,7 @@ function StaticSearchTypeMenu({queryJSON}: {queryJSON: SearchQueryJSON}) {
     const {translate} = useLocalize();
     const expensifyIcons = useMemoizedLazyExpensifyIcons(['Receipt', 'Document', 'Pencil']);
     const [policyInfo] = useOnyx(ONYXKEYS.COLLECTION.POLICY, {selector: staticPolicyInfoSelector});
-    const hasPaidGroupPolicy = policyInfo?.hasPaidGroupPolicy ?? false;
+    const hasGroupPolicy = policyInfo?.hasGroupPolicy ?? false;
     const session = useSession();
     const accountID = session?.accountID ?? CONST.DEFAULT_NUMBER_ID;
 
@@ -41,11 +41,11 @@ function StaticSearchTypeMenu({queryJSON}: {queryJSON: SearchQueryJSON}) {
         {key: expensesSearch.key, icon: expensifyIcons.Receipt, title: translate(expensesSearch.translationPath)},
     ];
 
-    if (hasPaidGroupPolicy) {
+    if (hasGroupPolicy) {
         tabs.push({key: submitSearch.key, icon: expensifyIcons.Pencil, title: translate(submitSearch.translationPath)});
     }
 
-    const activeKey = getActiveKey(queryJSON.similarSearchHash, hasPaidGroupPolicy, suggestedSearches);
+    const activeKey = getActiveKey(queryJSON.similarSearchHash, hasGroupPolicy, suggestedSearches);
 
     return (
         <SearchTypeMenuNarrowContent
diff --git a/src/pages/Search/SearchPageNarrow/staticPolicyInfoSelector.ts b/src/pages/Search/SearchPageNarrow/staticPolicyInfoSelector.ts
index c3b4d1a627b0..0d100d10b519 100644
--- a/src/pages/Search/SearchPageNarrow/staticPolicyInfoSelector.ts
+++ b/src/pages/Search/SearchPageNarrow/staticPolicyInfoSelector.ts
@@ -1,16 +1,17 @@
 import type {OnyxCollection} from 'react-native-onyx';
-import {shouldShowPolicy} from '@libs/PolicyUtils';
-import CONST from '@src/CONST';
+import {isGroupPolicy, shouldShowPolicy} from '@libs/PolicyUtils';
 import type {Policy} from '@src/types/onyx';
 
 type StaticPolicyInfo = {
     hasMultipleWorkspaces: boolean;
-    hasPaidGroupPolicy: boolean;
+    // True for any group workspace (Collect, Control, or Submit). Gates the "Submit" search tab,
+    // which Submit workspaces also need — matches `getSuggestedSearchesVisibility` in SearchUIUtils.
+    hasGroupPolicy: boolean;
 };
 
 function staticPolicyInfoSelector(policies: OnyxCollection<Policy>): StaticPolicyInfo {
     let workspaceCount = 0;
-    let hasPaidGroupPolicy = false;
+    let hasGroupPolicy = false;
 
     for (const policy of Object.values(policies ?? {})) {
         if (!policy) {
@@ -19,15 +20,15 @@ function staticPolicyInfoSelector(policies: OnyxCollection<Policy>): StaticPolic
         if (!policy.isJoinRequestPending && shouldShowPolicy(policy, false, undefined)) {
             workspaceCount++;
         }
-        if (policy.type === CONST.POLICY.TYPE.TEAM || policy.type === CONST.POLICY.TYPE.CORPORATE) {
-            hasPaidGroupPolicy = true;
+        if (isGroupPolicy(policy)) {
+            hasGroupPolicy = true;
         }
-        if (workspaceCount > 1 && hasPaidGroupPolicy) {
+        if (workspaceCount > 1 && hasGroupPolicy) {
             break;
         }
     }
 
-    return {hasMultipleWorkspaces: workspaceCount > 1, hasPaidGroupPolicy};
+    return {hasMultipleWorkspaces: workspaceCount > 1, hasGroupPolicy};
 }
 
 export default staticPolicyInfoSelector;
diff --git a/src/pages/SetDefaultWorkspacePage.tsx b/src/pages/SetDefaultWorkspacePage.tsx
index 73ac8f2d92ff..ce6e55c43d86 100644
--- a/src/pages/SetDefaultWorkspacePage.tsx
+++ b/src/pages/SetDefaultWorkspacePage.tsx
@@ -16,7 +16,7 @@ import useWorkspaceList from '@hooks/useWorkspaceList';
 import Log from '@libs/Log';
 import Navigation from '@libs/Navigation/Navigation';
 import type {PlatformStackScreenProps} from '@libs/Navigation/PlatformStackNavigation/types';
-import {isPaidGroupPolicy} from '@libs/PolicyUtils';
+import {isGroupPolicy} from '@libs/PolicyUtils';
 import type {MoneyRequestNavigatorParamList} from '@navigation/types';
 import {setNameValuePair} from '@userActions/User';
 import CONST from '@src/CONST';
@@ -68,7 +68,7 @@ function SetDefaultWorkspacePage({route}: SetDefaultWorkspacePageProps) {
         selectedPolicyIDs: undefined,
         searchTerm: debouncedSearchTerm,
         localeCompare,
-        additionalFilter: (newPolicy) => isPaidGroupPolicy(newPolicy),
+        additionalFilter: (newPolicy) => isGroupPolicy(newPolicy),
     });
 
     const textInputOptions = useMemo(
diff --git a/src/pages/Share/SubmitDetailsPage.tsx b/src/pages/Share/SubmitDetailsPage.tsx
index 8b2f7f83a602..c8eae0a5dc80 100644
--- a/src/pages/Share/SubmitDetailsPage.tsx
+++ b/src/pages/Share/SubmitDetailsPage.tsx
@@ -45,7 +45,7 @@ import Navigation from '@libs/Navigation/Navigation';
 import type {ShareNavigatorParamList} from '@libs/Navigation/types';
 import {rand64} from '@libs/NumberUtils';
 import {getParticipantsOption, getReportOption} from '@libs/OptionsListUtils';
-import {hasOnlyPersonalPolicies as hasOnlyPersonalPoliciesUtil, isPaidGroupPolicy} from '@libs/PolicyUtils';
+import {hasOnlyPersonalPolicies as hasOnlyPersonalPoliciesUtil, isGroupPolicy} from '@libs/PolicyUtils';
 import {shouldValidateFile} from '@libs/ReceiptUtils';
 import {isMoneyRequestReport, isSelfDM} from '@libs/ReportUtils';
 import {getDefaultTaxCode, getIsFromGlobalCreate, getTaxValue} from '@libs/TransactionUtils';
@@ -195,7 +195,7 @@ function SubmitDetailsPage({
     }, [defaultBillable]);
 
     useEffect(() => {
-        const defaultReimbursable = (isPolicyExpenseChat && isPaidGroupPolicy(policy)) || isCreatingTrackExpense ? (policy?.defaultReimbursable ?? true) : true;
+        const defaultReimbursable = (isPolicyExpenseChat && isGroupPolicy(policy)) || isCreatingTrackExpense ? (policy?.defaultReimbursable ?? true) : true;
         setMoneyRequestReimbursable(CONST.IOU.OPTIMISTIC_TRANSACTION_ID, defaultReimbursable);
     }, [policy, isPolicyExpenseChat, isCreatingTrackExpense]);
 
diff --git a/src/pages/inbox/report/ReportActionCompose/AttachmentPickerWithMenuItems.tsx b/src/pages/inbox/report/ReportActionCompose/AttachmentPickerWithMenuItems.tsx
index 0c0bfb1416e7..8accb5cebe16 100644
--- a/src/pages/inbox/report/ReportActionCompose/AttachmentPickerWithMenuItems.tsx
+++ b/src/pages/inbox/report/ReportActionCompose/AttachmentPickerWithMenuItems.tsx
@@ -31,8 +31,8 @@ import {
     canCreateTaskInReport,
     getPayeeName,
     hasViolations as hasViolationsReportUtils,
-    isPaidGroupPolicy,
     isPolicyExpenseChat,
+    isReportInGroupPolicy,
     isReportOwner,
     temporary_getMoneyRequestOptions,
 } from '@libs/ReportUtils';
@@ -320,7 +320,7 @@ function AttachmentPickerWithMenuItems({
     ]);
 
     const createReportOption: PopoverMenuItem[] = useMemo(() => {
-        if (!isPolicyExpenseChat(report) || !isPaidGroupPolicy(report) || !isReportOwner(report)) {
+        if (!isPolicyExpenseChat(report) || !isReportInGroupPolicy(report) || !isReportOwner(report)) {
             return [];
         }
 
diff --git a/src/pages/iou/request/ParticipantSearchResults.tsx b/src/pages/iou/request/ParticipantSearchResults.tsx
index 2999f230d273..9a7efdc33fe3 100644
--- a/src/pages/iou/request/ParticipantSearchResults.tsx
+++ b/src/pages/iou/request/ParticipantSearchResults.tsx
@@ -31,7 +31,7 @@ import {formatSectionsFromSearchTerm, getHeaderMessage, getParticipantsOption, g
 import type {Option} from '@libs/OptionsListUtils';
 import {doesPersonalDetailMatchSearchTerm} from '@libs/OptionsListUtils/searchMatchUtils';
 import type {OptionWithKey} from '@libs/OptionsListUtils/types';
-import {getActiveAdminWorkspaces, isPaidGroupPolicy as isPaidGroupPolicyUtil} from '@libs/PolicyUtils';
+import {getActiveAdminWorkspaces, isGroupPolicy as isGroupPolicyUtil} from '@libs/PolicyUtils';
 import type {OptionData} from '@libs/ReportUtils';
 import {isInvoiceRoom} from '@libs/ReportUtils';
 import {shouldRestrictUserBillableActions} from '@libs/SubscriptionUtils';
@@ -157,7 +157,7 @@ function ParticipantSearchResults({
 
     const {isDismissed: isDismissedReferralBanner} = useDismissedReferralBanners({referralContentType: CONST.REFERRAL_PROGRAM.CONTENT_TYPES.SUBMIT_EXPENSE});
 
-    const isPaidGroupPolicy = isPaidGroupPolicyUtil(policy);
+    const isGroupPolicy = isGroupPolicyUtil(policy);
     const activeAdminWorkspaces = getActiveAdminWorkspaces(allPolicies, currentUserLogin);
 
     const getValidOptionsConfig = {
@@ -174,7 +174,7 @@ function ParticipantSearchResults({
         isPerDiemRequest,
         isTimeRequest,
         showRBR: false,
-        preferPolicyExpenseChat: isPaidGroupPolicy,
+        preferPolicyExpenseChat: isGroupPolicy,
         preferRecentExpenseReports: action === CONST.IOU.ACTION.CREATE,
         isRestrictedToPreferredPolicy,
         preferredPolicyID,
diff --git a/src/pages/iou/request/step/confirmation/ExpenseDefaultsSetter.tsx b/src/pages/iou/request/step/confirmation/ExpenseDefaultsSetter.tsx
index 681da6bd0192..429a4c8c3446 100644
--- a/src/pages/iou/request/step/confirmation/ExpenseDefaultsSetter.tsx
+++ b/src/pages/iou/request/step/confirmation/ExpenseDefaultsSetter.tsx
@@ -1,6 +1,6 @@
 import {useEffect} from 'react';
 import type {OnyxEntry} from 'react-native-onyx';
-import {isPaidGroupPolicy} from '@libs/PolicyUtils';
+import {isGroupPolicy} from '@libs/PolicyUtils';
 import {setMoneyRequestBillable, setMoneyRequestReimbursable} from '@userActions/IOU/MoneyRequest';
 import type {Policy} from '@src/types/onyx';
 
@@ -32,7 +32,7 @@ function ExpenseDefaultsSetter({transactionIDs, policy, isPolicyExpenseChat, isM
         if (isMovingTransactionFromTrackExpense) {
             return;
         }
-        const defaultReimbursable = (isPolicyExpenseChat && isPaidGroupPolicy(policy)) || isCreatingTrackExpense ? (policy?.defaultReimbursable ?? true) : true;
+        const defaultReimbursable = (isPolicyExpenseChat && isGroupPolicy(policy)) || isCreatingTrackExpense ? (policy?.defaultReimbursable ?? true) : true;
         for (const transactionID of transactionIDs) {
             setMoneyRequestReimbursable(transactionID, defaultReimbursable);
         }
diff --git a/tests/unit/useCreateReportTest.tsx b/tests/unit/useCreateReportTest.tsx
index 8c76cf0a9169..d4dcbe58d183 100644
--- a/tests/unit/useCreateReportTest.tsx
+++ b/tests/unit/useCreateReportTest.tsx
@@ -39,6 +39,7 @@ jest.mock('@libs/PolicyUtils', () => ({
         return undefined;
     }),
     isPaidGroupPolicy: jest.fn((policy: OnyxEntry<Policy>) => policy?.type === 'team' || policy?.type === 'corporate'),
+    isGroupPolicy: jest.fn((policy: OnyxEntry<Policy>) => policy?.type === 'team' || policy?.type === 'corporate' || policy?.type === 'submit2026'),
 }));
 
 jest.mock('@libs/interceptAnonymousUser', () => jest.fn((cb: () => void) => cb()));

From 8a32b351ea46a48b7c66741fbe2a4eadbc30e6b7 Mon Sep 17 00:00:00 2001
From: bartlomiej obudzinski <bartlomiej.obudzinski@callstack.com>
Date: Tue, 9 Jun 2026 13:36:23 +0200
Subject: [PATCH 204/435] fix: useOnyx deps and drop redundant useMemo in
 InboxTabButton

---
 .../Navigation/NavigationTabBar/InboxTabButton.tsx     | 10 ++++++----
 1 file changed, 6 insertions(+), 4 deletions(-)

diff --git a/src/components/Navigation/NavigationTabBar/InboxTabButton.tsx b/src/components/Navigation/NavigationTabBar/InboxTabButton.tsx
index 6ae62b5a7f05..806909023a48 100644
--- a/src/components/Navigation/NavigationTabBar/InboxTabButton.tsx
+++ b/src/components/Navigation/NavigationTabBar/InboxTabButton.tsx
@@ -1,4 +1,4 @@
-import React, {useMemo} from 'react';
+import React from 'react';
 import type {OnyxEntry} from 'react-native-onyx';
 import type {ValueOf} from 'type-fest';
 import {PressableWithFeedback} from '@components/Pressable';
@@ -65,9 +65,11 @@ function InboxTabButton({selectedTab, isWideLayout, statusIndicatorColor, chatTa
 
     const [doesLastReportExist] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${lastReportRouteReportID}`, {selector: doesLastReportExistSelector}, [lastReportRouteReportID]);
 
-    // Wrap factory in useMemo so the selector identity is stable per actionID
-    const doesLastReportActionExistSelector = useMemo(() => makeDoesLastReportActionExistSelector(lastReportRouteReportActionID), [lastReportRouteReportActionID]);
-    const [doesLastReportActionExist] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${lastReportRouteReportID}`, {selector: doesLastReportActionExistSelector}, [lastReportRouteReportID]);
+    const doesLastReportActionExistSelector = makeDoesLastReportActionExistSelector(lastReportRouteReportActionID);
+    const [doesLastReportActionExist] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${lastReportRouteReportID}`, {selector: doesLastReportActionExistSelector}, [
+        lastReportRouteReportID,
+        lastReportRouteReportActionID,
+    ]);
 
     const inboxAccessibilityState = {selected: selectedTab === NAVIGATION_TABS.INBOX};
 

From 3e1859f0a43e5b7f946c46db940a3d802d690862 Mon Sep 17 00:00:00 2001
From: Abdelrahman Khattab <abzokhattab@gmail.com>
Date: Tue, 9 Jun 2026 13:39:10 +0200
Subject: [PATCH 205/435] Include transaction amount-sign in isGroupPolicy
 migration + fix test mock

getTransactionDetails and TotalCell now use isGroupPolicy for the amount-sign
isFromExpenseReport clause. This is safe (isGroupPolicy is a superset of
isPaidGroupPolicy, so Collect/Control/Personal are unaffected) and correct for
Submit (group expenses negate like Collect/Control).

CreateDraftTransactionTest stubbed isPaidGroupPolicy=true; add the paired
isGroupPolicy stub so the rename doesn't bypass the mock (same pattern as
useCreateReportTest).
---
 src/components/TransactionItemRow/DataCells/TotalCell.tsx | 4 ++--
 src/libs/ReportUtils.ts                                   | 3 +--
 tests/actions/IOU/CreateDraftTransactionTest.ts           | 1 +
 3 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/src/components/TransactionItemRow/DataCells/TotalCell.tsx b/src/components/TransactionItemRow/DataCells/TotalCell.tsx
index 18ec1cd2060c..4f910c6faa3b 100644
--- a/src/components/TransactionItemRow/DataCells/TotalCell.tsx
+++ b/src/components/TransactionItemRow/DataCells/TotalCell.tsx
@@ -11,7 +11,7 @@ import useThemeStyles from '@hooks/useThemeStyles';
 import {convertToBackendAmount, convertToFrontendAmountAsString, getCurrencyDecimals, sanitizeCurrencyCode} from '@libs/CurrencyUtils';
 import {formatToParts} from '@libs/NumberFormatUtils';
 import {parseFloatAnyLocale, roundToTwoDecimalPlaces} from '@libs/NumberUtils';
-import {isPaidGroupPolicy} from '@libs/PolicyUtils';
+import {isGroupPolicy} from '@libs/PolicyUtils';
 import {isExpenseReport, isInvoiceReport, shouldEnableNegative} from '@libs/ReportUtils';
 import {getAmount as getTransactionAmount, getCurrency as getTransactionCurrency, isDeletedTransaction, isExpenseUnreported, isScanning} from '@libs/TransactionUtils';
 import CONST from '@src/CONST';
@@ -47,7 +47,7 @@ function TotalCell({shouldShowTooltip, transactionItem, canEdit, onSave, report,
     const effectiveReport = report ?? transactionItem.report;
     const effectivePolicy = policy ?? transactionItem.policy;
     const isDeleted = isDeletedTransaction(transactionItem);
-    const isFromExpenseReport = (!isEmptyObject(effectiveReport) && isExpenseReport(effectiveReport)) || isPaidGroupPolicy(effectivePolicy);
+    const isFromExpenseReport = (!isEmptyObject(effectiveReport) && isExpenseReport(effectiveReport)) || isGroupPolicy(effectivePolicy);
     const amount = getTransactionAmount(transactionItem, isFromExpenseReport, transactionItem.reportID === CONST.REPORT.UNREPORTED_REPORT_ID, isDeleted);
     let amountToDisplay = convertToDisplayString(amount, currency);
     if (isScanning(transactionItem)) {
diff --git a/src/libs/ReportUtils.ts b/src/libs/ReportUtils.ts
index 2414e83c088d..47d0b4bbb55e 100644
--- a/src/libs/ReportUtils.ts
+++ b/src/libs/ReportUtils.ts
@@ -162,7 +162,6 @@ import {
     isExpensifyTeam,
     isGroupPolicy as isGroupPolicyPolicyUtils,
     isInstantSubmitEnabled,
-    isPaidGroupPolicy as isPaidGroupPolicyPolicyUtils,
     isPendingDeletePolicy,
     isPolicyAdmin as isPolicyAdminPolicyUtils,
     isPolicyAuditor,
@@ -4656,7 +4655,7 @@ function getTransactionDetails(
     }
 
     const report = getReportOrDraftReport(transaction?.reportID, undefined, 'report' in transaction ? transaction.report : undefined);
-    const isFromExpenseReport = (!isEmptyObject(report) && isExpenseReport(report)) || isPaidGroupPolicyPolicyUtils(policy);
+    const isFromExpenseReport = (!isEmptyObject(report) && isExpenseReport(report)) || isGroupPolicyPolicyUtils(policy);
 
     return {
         created: getFormattedCreated(transaction, createdDateFormat),
diff --git a/tests/actions/IOU/CreateDraftTransactionTest.ts b/tests/actions/IOU/CreateDraftTransactionTest.ts
index 4b0446cf0f89..f4110376bd22 100644
--- a/tests/actions/IOU/CreateDraftTransactionTest.ts
+++ b/tests/actions/IOU/CreateDraftTransactionTest.ts
@@ -96,6 +96,7 @@ jest.mock('@src/libs/SearchQueryUtils', () => {
 jest.mock('@libs/PolicyUtils', () => ({
     ...jest.requireActual<typeof PolicyUtils>('@libs/PolicyUtils'),
     isPaidGroupPolicy: jest.fn().mockReturnValue(true),
+    isGroupPolicy: jest.fn().mockReturnValue(true),
     isPolicyOwner: jest.fn().mockImplementation((policy?: OnyxEntry<Policy>, currentUserAccountID?: number) => !!currentUserAccountID && policy?.ownerAccountID === currentUserAccountID),
 }));
 

From 1089c80cc91dd4cf66462f0c891fd9015f889698 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marcin=20Warcho=C5=82?=
 <61014013+war-in@users.noreply.github.com>
Date: Tue, 9 Jun 2026 13:46:49 +0200
Subject: [PATCH 206/435] Revert "[CP Staging] Revert "chore: upgrade
 `react-native-svg` to 15.15.5""

---
 ios/Podfile.lock                                |  8 ++++----
 package-lock.json                               | 11 +++++------
 package.json                                    |  2 +-
 src/pages/home/ForYouSection/ForYouSkeleton.tsx |  2 +-
 4 files changed, 11 insertions(+), 12 deletions(-)

diff --git a/ios/Podfile.lock b/ios/Podfile.lock
index 1d385f71f0f0..f56a0a3c3c15 100644
--- a/ios/Podfile.lock
+++ b/ios/Podfile.lock
@@ -4088,7 +4088,7 @@ PODS:
     - ReactCommon/turbomodule/core
     - SocketRocket
     - Yoga
-  - RNSVG (15.12.1):
+  - RNSVG (15.15.5):
     - boost
     - DoubleConversion
     - fast_float
@@ -4114,10 +4114,10 @@ PODS:
     - ReactCodegen
     - ReactCommon/turbomodule/bridging
     - ReactCommon/turbomodule/core
-    - RNSVG/common (= 15.12.1)
+    - RNSVG/common (= 15.15.5)
     - SocketRocket
     - Yoga
-  - RNSVG/common (15.12.1):
+  - RNSVG/common (15.15.5):
     - boost
     - DoubleConversion
     - fast_float
@@ -4938,7 +4938,7 @@ SPEC CHECKSUMS:
   RNScreens: 2b6107925ee4e14a9b2eb0dfb52fe25223aa64d7
   RNSentry: f73f4da92e4c20841ab16e1fa22fc289bc2f9f4e
   RNShare: 1c1fde2c4134b9cf220ffebbd6df9c414036d382
-  RNSVG: 74eb75bd44d62ba9969941e80d8f9832971c681f
+  RNSVG: 14e21dacbded6cfa51becd6076c5921aa52a6992
   RNWorklets: 165079e6aa8caad7a05156ec2161fd4c52f9b745
   SDWebImage: 16309af6d214ba3f77a7c6f6fdda888cb313a50a
   SDWebImageAVIFCoder: afe194a084e851f70228e4be35ef651df0fc5c57
diff --git a/package-lock.json b/package-lock.json
index dbbcf191818d..3730b726696b 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -132,7 +132,7 @@
         "react-native-safe-area-context": "5.6.2",
         "react-native-screens": "4.25.0",
         "react-native-share": "11.0.2",
-        "react-native-svg": "15.12.1",
+        "react-native-svg": "15.15.5",
         "react-native-tab-view": "^4.3.0",
         "react-native-url-polyfill": "^2.0.0",
         "react-native-view-shot": "5.1.0",
@@ -35942,14 +35942,13 @@
       }
     },
     "node_modules/react-native-svg": {
-      "version": "15.12.1",
-      "resolved": "https://registry.npmjs.org/react-native-svg/-/react-native-svg-15.12.1.tgz",
-      "integrity": "sha512-vCuZJDf8a5aNC2dlMovEv4Z0jjEUET53lm/iILFnFewa15b4atjVxU6Wirm6O9y6dEsdjDZVD7Q3QM4T1wlI8g==",
+      "version": "15.15.5",
+      "resolved": "https://registry.npmjs.org/react-native-svg/-/react-native-svg-15.15.5.tgz",
+      "integrity": "sha512-L4go5jA+GWutdJ/JucuN20cjAbMg1HmMtAP+wZ+3JLCf6Jd0bhXQHxciRP/AQm/FlrIEZwkMcHNZP+FXAiic0w==",
       "license": "MIT",
       "dependencies": {
         "css-select": "^5.1.0",
-        "css-tree": "^1.1.3",
-        "warn-once": "0.1.1"
+        "css-tree": "^1.1.3"
       },
       "peerDependencies": {
         "react": "*",
diff --git a/package.json b/package.json
index 23a580a2d3dd..597562eeed9a 100644
--- a/package.json
+++ b/package.json
@@ -205,7 +205,7 @@
     "react-native-safe-area-context": "5.6.2",
     "react-native-screens": "4.25.0",
     "react-native-share": "11.0.2",
-    "react-native-svg": "15.12.1",
+    "react-native-svg": "15.15.5",
     "react-native-tab-view": "^4.3.0",
     "react-native-url-polyfill": "^2.0.0",
     "react-native-view-shot": "5.1.0",
diff --git a/src/pages/home/ForYouSection/ForYouSkeleton.tsx b/src/pages/home/ForYouSection/ForYouSkeleton.tsx
index d073fd8008d1..7549e5d3abe2 100644
--- a/src/pages/home/ForYouSection/ForYouSkeleton.tsx
+++ b/src/pages/home/ForYouSection/ForYouSkeleton.tsx
@@ -43,7 +43,7 @@ function ForYouSkeleton({reasonAttributes}: Props) {
             const iconY = 12;
             const titleX = iconX + 40 + gap;
             const titleWidth = getTitleSkeletonWidth(args.itemIndex);
-            const buttonWidth = styles.widgetItemButton.minWidth;
+            const buttonWidth = styles.widgetItemButton.minWidth ?? 0;
             const buttonHeight = 28;
             const buttonX = pageWidth - horizontalPadding - buttonWidth;
             const buttonY = (ITEM_HEIGHT - buttonHeight) / 2;

From 1eead7bc45007b6154a507b9d8f06d7852d05ef9 Mon Sep 17 00:00:00 2001
From: war-in <war-in@users.noreply.github.com>
Date: Tue, 9 Jun 2026 13:30:02 +0200
Subject: [PATCH 207/435] fix: migrate from transform to flexbox

---
 .../Skeletons/TabNavigatorSkeleton.tsx        | 50 ++++++++++---------
 1 file changed, 26 insertions(+), 24 deletions(-)

diff --git a/src/components/Skeletons/TabNavigatorSkeleton.tsx b/src/components/Skeletons/TabNavigatorSkeleton.tsx
index a4aa38e96790..efffbbcf250e 100644
--- a/src/components/Skeletons/TabNavigatorSkeleton.tsx
+++ b/src/components/Skeletons/TabNavigatorSkeleton.tsx
@@ -18,32 +18,34 @@ function TabNavigatorSkeleton({reasonAttributes}: TabNavigatorSkeletonProps) {
 
     return (
         <View style={[styles.flexRow, styles.w100, styles.justifyContentBetween, styles.h10]}>
-            <SkeletonViewContentLoader
-                animate
-                height={40}
-                backgroundColor={theme.skeletonLHNIn}
-                foregroundColor={theme.skeletonLHNOut}
-                style={[styles.flex1, styles.ml4, styles.button, styles.highlightBG]}
-            >
-                <SkeletonRect
-                    transform={[{translateX: '20%'}, {translateY: 13}]}
+            <View style={[styles.flex1, styles.ml4, styles.button, styles.highlightBG, styles.alignItemsCenter, styles.justifyContentCenter]}>
+                <SkeletonViewContentLoader
+                    animate
                     width="60%"
-                    height={14}
-                />
-            </SkeletonViewContentLoader>
-            <SkeletonViewContentLoader
-                animate
-                height={40}
-                backgroundColor={theme.skeletonLHNIn}
-                foregroundColor={theme.skeletonLHNOut}
-                style={[styles.flex1, styles.mr4, styles.button, styles.appBG]}
-            >
-                <SkeletonRect
-                    transform={[{translateX: '20%'}, {translateY: 13}]}
+                    height="35%"
+                    backgroundColor={theme.skeletonLHNIn}
+                    foregroundColor={theme.skeletonLHNOut}
+                >
+                    <SkeletonRect
+                        width="100%"
+                        height="100%"
+                    />
+                </SkeletonViewContentLoader>
+            </View>
+            <View style={[styles.flex1, styles.mr4, styles.button, styles.appBG, styles.alignItemsCenter, styles.justifyContentCenter]}>
+                <SkeletonViewContentLoader
+                    animate
                     width="60%"
-                    height={14}
-                />
-            </SkeletonViewContentLoader>
+                    height="35%"
+                    backgroundColor={theme.skeletonLHNIn}
+                    foregroundColor={theme.skeletonLHNOut}
+                >
+                    <SkeletonRect
+                        width="100%"
+                        height="100%"
+                    />
+                </SkeletonViewContentLoader>
+            </View>
         </View>
     );
 }

From e2f20f3f23d3cfb8dc0e91dde71730becf9e1954 Mon Sep 17 00:00:00 2001
From: mkhutornyi <mkhutorniy@gmail.com>
Date: Tue, 9 Jun 2026 12:57:45 +0100
Subject: [PATCH 208/435] fix Search - User in Recent chats section is not
 highlighted

---
 .../Search/SearchAutocompleteList.tsx         | 25 +++++++----
 .../Search/SearchRouter/SearchRouter.tsx      |  3 +-
 tests/unit/SearchAutocompleteListTest.tsx     | 43 +++++++++++++++++++
 3 files changed, 60 insertions(+), 11 deletions(-)

diff --git a/src/components/Search/SearchAutocompleteList.tsx b/src/components/Search/SearchAutocompleteList.tsx
index 67c1acc4b16f..37360092d84f 100644
--- a/src/components/Search/SearchAutocompleteList.tsx
+++ b/src/components/Search/SearchAutocompleteList.tsx
@@ -67,8 +67,9 @@ type SearchAutocompleteListProps = {
     /** Whether to subscribe to KeyboardShortcut arrow keys events */
     shouldSubscribeToArrowKeyEvents?: boolean;
 
-    /** Callback to highlight (e.g. scroll to) the first matched item in the list. */
-    onHighlightFirstItem?: () => void;
+    /** Whether to highlight the first matched result so Enter selects it. Only the SearchRouter (Cmd+K) uses this;
+     *  the search page input keeps focus on the search-query row to match production behavior. */
+    shouldHighlightFirstItem?: boolean;
 
     /** Ref for the external text input */
     textInputRef?: RefObject<AnimatedTextInputRef | null>;
@@ -144,7 +145,7 @@ function SearchAutocompleteList({
     getAdditionalSections,
     onListItemPress,
     shouldSubscribeToArrowKeyEvents = true,
-    onHighlightFirstItem,
+    shouldHighlightFirstItem = false,
     textInputRef,
     autocompleteSubstitutions,
     ref,
@@ -272,8 +273,8 @@ function SearchAutocompleteList({
                 // effect can re-fire and correctly focus the first focusable item (skipping section headers).
                 hasSetInitialFocusRef.current = false;
             } else {
-                // When query changes to a non-empty value, focus on the search query item (index 0) and scroll to top
-                // onHighlightFirstItem will switch focus to the first result when there's a good match
+                // When query changes to a non-empty value, focus on the search query item (index 0) and scroll to top.
+                // The highlight effect below switches focus to the first result when there's a good match.
                 innerListRef.current?.updateAndScrollToFocusedIndex(0, true);
             }
         }
@@ -569,7 +570,10 @@ function SearchAutocompleteList({
         reports,
     ]);
 
-    const sectionItemText = sections?.at(1)?.data?.[0]?.text ?? '';
+    // Derive the highlight reference text from the actual first result rather than a fixed section index.
+    // After the two-section ("Recent chats" / "Search results") switcher, sections.at(1) can be the empty
+    // local section when a result is server-only, which would leave the first result unhighlighted.
+    const sectionItemText = styledRecentReports.at(0)?.text ?? '';
     const normalizedReferenceText = sectionItemText.toLowerCase();
     const trimmedAutocompleteQueryValue = autocompleteQueryValue.trim();
     const isLoading = !isRecentSearchesDataLoaded;
@@ -618,10 +622,13 @@ function SearchAutocompleteList({
     useEffect(() => {
         const targetText = autocompleteQueryValue;
 
-        if (shouldHighlight(normalizedReferenceText, targetText)) {
-            onHighlightFirstItem?.();
+        if (!shouldHighlightFirstItem || firstRecentReportFlatIndex === -1 || !shouldHighlight(normalizedReferenceText, targetText)) {
+            return;
         }
-    }, [autocompleteQueryValue, onHighlightFirstItem, normalizedReferenceText]);
+        // Focus the header-aware flat index of the first result. A fixed index (e.g. searchQueryItems.length)
+        // lands on the "Recent chats" section header row after the two-section switcher was introduced.
+        innerListRef.current?.updateAndScrollToFocusedIndex(firstRecentReportFlatIndex, true);
+    }, [autocompleteQueryValue, firstRecentReportFlatIndex, normalizedReferenceText, shouldHighlightFirstItem]);
 
     if (isLoading) {
         return (
diff --git a/src/components/Search/SearchRouter/SearchRouter.tsx b/src/components/Search/SearchRouter/SearchRouter.tsx
index 973871e5be97..ee60f0ca0895 100644
--- a/src/components/Search/SearchRouter/SearchRouter.tsx
+++ b/src/components/Search/SearchRouter/SearchRouter.tsx
@@ -372,7 +372,6 @@ function SearchRouter({onRouterClose, shouldHideInputCaret, isSearchRouterDispla
     useKeyboardShortcut(CONST.KEYBOARD_SHORTCUTS.ESCAPE, () => {
         onRouterClose();
     });
-    const updateAndScrollToFocusedIndex = useCallback(() => listRef.current?.updateAndScrollToFocusedIndex(searchQueryItems?.length ?? 1, true), [searchQueryItems?.length]);
 
     const modalWidth = shouldUseNarrowLayout ? styles.w100 : {width: variables.searchRouterPopoverWidth};
 
@@ -421,7 +420,7 @@ function SearchRouter({onRouterClose, shouldHideInputCaret, isSearchRouterDispla
                 searchQueryItems={searchQueryItems}
                 getAdditionalSections={getAdditionalSections}
                 onListItemPress={onListItemPress}
-                onHighlightFirstItem={updateAndScrollToFocusedIndex}
+                shouldHighlightFirstItem
                 ref={listRef}
                 textInputRef={textInputRef}
                 autocompleteSubstitutions={autocompleteSubstitutions}
diff --git a/tests/unit/SearchAutocompleteListTest.tsx b/tests/unit/SearchAutocompleteListTest.tsx
index 16b77aa90ce3..5f4cfc2e4973 100644
--- a/tests/unit/SearchAutocompleteListTest.tsx
+++ b/tests/unit/SearchAutocompleteListTest.tsx
@@ -9,9 +9,11 @@ import SearchRouter from '@components/Search/SearchRouter/SearchRouter';
 import type {PrivateIsArchivedMap} from '@hooks/usePrivateIsArchivedMap';
 import type * as OptionsListUtilsModule from '@libs/OptionsListUtils';
 import {createOptionList} from '@libs/OptionsListUtils';
+import Navigation from '@navigation/Navigation';
 import ComposeProviders from '@src/components/ComposeProviders';
 import CONST from '@src/CONST';
 import ONYXKEYS from '@src/ONYXKEYS';
+import ROUTES from '@src/ROUTES';
 import type {PersonalDetails, Report} from '@src/types/onyx';
 import createCollection from '../utils/collections/createCollection';
 import createPersonalDetails from '../utils/collections/personalDetails';
@@ -419,5 +421,46 @@ describe('SearchAutocompleteList', () => {
             // NewServer should appear after the local results (in the server section)
             expect(relevantOrder.indexOf('Charlie Report')).toBeLessThan(relevantOrder.indexOf('NewServer Report'));
         });
+
+        // Regression test for https://github.com/Expensify/App/issues/93009: after the two-section switcher was
+        // introduced, the first matched chat was no longer highlighted because the highlight focused a fixed flat
+        // index that now lands on the "Recent chats" section header row instead of the first result. As a result
+        // pressing Enter ran a text search instead of opening the chat. The fix focuses the header-aware index of
+        // the first result.
+        it('should focus the first matched chat so submitting opens it instead of running a search', async () => {
+            const recentSearches: Record<string, {query: string; timestamp: string}> = {};
+            recentSearches['2024-01-01T00:00:00'] = {query: 'type:expense', timestamp: '2024-01-01T00:00:00'};
+
+            await waitForBatchedUpdates();
+            await Onyx.multiSet({
+                ...mockedReports,
+                [ONYXKEYS.PERSONAL_DETAILS_LIST]: mockedPersonalDetails,
+                [ONYXKEYS.BETAS]: mockedBetas,
+                [ONYXKEYS.RECENT_SEARCHES]: recentSearches,
+            });
+
+            render(<SearchRouterWrapper />);
+            await flushAllUpdates();
+
+            // Wait for the first recent chat row (not just the header) to render so the highlight has a target.
+            await waitFor(() => {
+                expect(screen.getByText('Recent chats')).toBeTruthy();
+                expect(screen.getByText('Alice Report')).toBeTruthy();
+            });
+
+            // Type a query that matches the first recent chat ("Alice Report") as a whole word.
+            // The header-aware highlight effect should move focus onto that result row, not a section header.
+            const textInput = screen.getByTestId('search-autocomplete-text-input');
+            fireEvent.changeText(textInput, 'Alice');
+            await flushAllUpdates();
+
+            // Submitting (Enter) should open the focused chat rather than run a text search. The highlight effect
+            // runs asynchronously, so poll the submit until focus settles on the result. With the bug present the
+            // first row is never highlighted, so submit always runs a text search and this never becomes true.
+            await waitFor(() => {
+                fireEvent(textInput, 'submitEditing');
+                expect(Navigation.navigate).toHaveBeenCalledWith(ROUTES.REPORT_WITH_ID.getRoute('101'));
+            });
+        });
     });
 });

From 9a150ec66f504bb647511520c0c04d41cb22f5c0 Mon Sep 17 00:00:00 2001
From: Adam Grzybowski <adam.grzybowski@swmansion.com>
Date: Tue, 9 Jun 2026 14:02:20 +0200
Subject: [PATCH 209/435] Recognize optimistic report focused in search RHP
 transaction carousel

Match the SEARCH_REPORT RHP route by name + reportID param so the "Review X
expenses" carousel swaps to the preexisting thread instead of clearing the
report and bouncing to the parent. Add a regression test for this case.
---
 ...replaceOptimisticReportWithActualReport.ts | 13 +++-
 ...aceOptimisticReportWithActualReportTest.ts | 65 +++++++++++++++++++
 2 files changed, 77 insertions(+), 1 deletion(-)

diff --git a/src/libs/actions/replaceOptimisticReportWithActualReport.ts b/src/libs/actions/replaceOptimisticReportWithActualReport.ts
index 150f65a6827d..0bb103ce149f 100644
--- a/src/libs/actions/replaceOptimisticReportWithActualReport.ts
+++ b/src/libs/actions/replaceOptimisticReportWithActualReport.ts
@@ -140,7 +140,18 @@ function replaceOptimisticReportWithActualReport(report: Report, draftReportComm
         const backTo = (currentRouteInfo?.params as {backTo?: Route})?.backTo;
         const screenName = currentRouteInfo?.name;
 
-        const isOptimisticReportFocused = activeRoute.includes(`/r/${reportID}`);
+        // Besides the central-pane report route (/r/:reportID), the optimistic report can also be focused
+        // in the RHP transaction-thread carousel (search/view/:reportID) used by the "Review X expenses"
+        // flow. Matched via route name + reportID param (not a path substring) since the carousel's nested
+        // backTo can contain other report IDs. Without this, the report is cleared out from under the user
+        // and ReportNavigateAwayHandler treats it as removed, dismissing the RHP and navigating to the parent.
+        const isOptimisticReportFocusedInSearchRHP =
+            screenName === SCREENS.RIGHT_MODAL.SEARCH_REPORT &&
+            !!currentRouteInfo?.params &&
+            typeof currentRouteInfo.params === 'object' &&
+            'reportID' in currentRouteInfo.params &&
+            currentRouteInfo.params.reportID === reportID;
+        const isOptimisticReportFocused = activeRoute.includes(`/r/${reportID}`) || isOptimisticReportFocusedInSearchRHP;
 
         // Fix specific case: https://github.com/Expensify/App/pull/77657#issuecomment-3678696730.
         // When user is editing a money request report (/e/:reportID route) and has
diff --git a/tests/actions/ReplaceOptimisticReportWithActualReportTest.ts b/tests/actions/ReplaceOptimisticReportWithActualReportTest.ts
index f879c4dcb8cb..6bf71df0c476 100644
--- a/tests/actions/ReplaceOptimisticReportWithActualReportTest.ts
+++ b/tests/actions/ReplaceOptimisticReportWithActualReportTest.ts
@@ -917,6 +917,71 @@ describe('replaceOptimisticReportWithActualReport', () => {
         subscription.remove();
     });
 
+    it('should swap to preexisting thread when focused on the search RHP transaction-thread carousel', async () => {
+        // Given an optimistic transaction thread under a multi-transaction IOU report opened in the
+        // "Review X expenses" carousel, i.e. the focused route is the SEARCH_REPORT RHP (search/view/:reportID)
+        const iouReportID = '9999';
+        const optimisticReportID = '1234';
+        const preexistingReportID = '5555';
+
+        mockIsReady.mockReturnValue(true);
+        // The carousel route is search/view/<id>, NOT /r/<id>
+        mockGetActiveRoute.mockReturnValue(`/search/view/${optimisticReportID}`);
+        mockGetCurrentRoute.mockReturnValue({name: SCREENS.RIGHT_MODAL.SEARCH_REPORT, params: {reportID: optimisticReportID}});
+
+        const reportActionID1 = '1';
+        const reportActionID2 = '2';
+        await Onyx.set(`${ONYXKEYS.COLLECTION.REPORT}${iouReportID}`, {
+            reportID: iouReportID,
+            type: CONST.REPORT.TYPE.IOU,
+            transactionCount: 2,
+        });
+        await Onyx.set(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${iouReportID}`, {
+            [reportActionID1]: {
+                reportActionID: reportActionID1,
+                actionName: CONST.REPORT.ACTIONS.TYPE.IOU,
+                originalMessage: {type: CONST.IOU.REPORT_ACTION_TYPE.CREATE, IOUTransactionID: 'trans1'},
+            },
+            [reportActionID2]: {
+                reportActionID: reportActionID2,
+                actionName: CONST.REPORT.ACTIONS.TYPE.IOU,
+                originalMessage: {type: CONST.IOU.REPORT_ACTION_TYPE.CREATE, IOUTransactionID: 'trans2'},
+            },
+        });
+
+        const optimisticReport = {
+            reportID: optimisticReportID,
+            type: CONST.REPORT.TYPE.CHAT,
+            parentReportID: iouReportID,
+            parentReportActionID: reportActionID1,
+            preexistingReportID,
+        };
+
+        await Onyx.set(`${ONYXKEYS.COLLECTION.REPORT}${optimisticReportID}`, optimisticReport);
+        await waitForBatchedUpdates();
+
+        let capturedEventData: SwitchReportEventData | undefined;
+        const subscription = DeviceEventEmitter.addListener(`switchToPreExistingReport_${optimisticReportID}`, (data: SwitchReportEventData) => {
+            capturedEventData = data;
+        });
+
+        // When replaceOptimisticReportWithActualReport is called and the callback is executed
+        replaceOptimisticReportWithActualReport(optimisticReport, undefined);
+        await waitForBatchedUpdates();
+
+        // Then the switch event is emitted (the focused optimistic report is recognized on the RHP route)
+        expect(capturedEventData).toBeDefined();
+
+        capturedEventData?.callback();
+        await waitForBatchedUpdates();
+
+        // And the carousel is swapped to the preexisting thread via setParams (staying in the RHP),
+        // instead of being cleared out and bounced to the parent report
+        expect(mockSetParams).toHaveBeenCalledWith({reportID: preexistingReportID.toString()});
+
+        subscription.remove();
+    });
+
     it('should update backTo route when optimistic report is in background on expense report screen', async () => {
         // Given an optimistic report in the background while user is on expense report screen with backTo pointing to it
         const reportID = '1';

From 2093b0c8c29aace0df9dc5feb031d591ae2e8337 Mon Sep 17 00:00:00 2001
From: Abdelrahman Khattab <abzokhattab@gmail.com>
Date: Tue, 9 Jun 2026 14:12:13 +0200
Subject: [PATCH 210/435] Migrate inline report-field-violation RBR check +
 document paid vs group helpers

- hasVisibleReportFieldViolations used an inline team/corporate check for the
  report-field-violation RBR; switch it to isGroupPolicyExpenseReport so it stays
  consistent with the rest of the report-fields migration (superset-safe).
- Add JSDoc to isPaidGroupPolicy/isGroupPolicy (PolicyUtils) and the report-based
  counterparts (ReportUtils) clarifying billing-only vs group-feature usage, to
  steer future code to the right helper.
---
 src/libs/PolicyUtils.ts | 24 ++++++++++++++++++++----
 src/libs/ReportUtils.ts | 18 ++++++++++++------
 2 files changed, 32 insertions(+), 10 deletions(-)

diff --git a/src/libs/PolicyUtils.ts b/src/libs/PolicyUtils.ts
index d8de6607b7dd..bb9a21240af3 100644
--- a/src/libs/PolicyUtils.ts
+++ b/src/libs/PolicyUtils.ts
@@ -1079,6 +1079,18 @@ function isPendingDeletePolicy(policy: OnyxEntry<Policy>): boolean {
     return policy?.pendingAction === CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE;
 }
 
+/**
+ * ⚠️ BILLING / PAID-ONLY. Returns true only for paid plans (Collect/Control).
+ *
+ * Use this ONLY to gate billing/paid-only concerns: subscriptions, payments & reimbursement,
+ * company cards, Expensify Card, Travel, Invoices, "do I own a paid workspace" checks.
+ *
+ * For "does this workspace have group features?" gating (violations, report fields, workspace
+ * chat, report creation, expense-workspace usability) use `isGroupPolicy` instead — otherwise
+ * free group plans like Submit (submit2026) are incorrectly excluded and you reintroduce
+ * access bugs. For report-based call sites, the equivalents are `ReportUtils.isPaidGroupPolicy`
+ * (paid-only) vs `ReportUtils.isReportInGroupPolicy` (group).
+ */
 function isPaidGroupPolicy(policy: OnyxInputOrEntry<Policy>): boolean {
     return policy?.type === CONST.POLICY.TYPE.TEAM || policy?.type === CONST.POLICY.TYPE.CORPORATE;
 }
@@ -1110,11 +1122,15 @@ function canEditWorkspaceSettings(policy: OnyxInputOrEntry<Policy>, login?: stri
 }
 
 /**
- * Returns true for any group workspace: paid (Team/Corporate) or Submit.
+ * ✅ GROUP-FEATURE gating. Returns true for any group workspace: paid (Collect/Control) or Submit.
+ *
+ * Prefer this over `isPaidGroupPolicy` whenever the check is about workspace *features* rather than
+ * billing — violations, report fields, workspace chat, report creation, expense-workspace usability —
+ * so free group plans like Submit (submit2026) aren't wrongly excluded. It's a strict superset of
+ * `isPaidGroupPolicy`, so switching a feature check to it never changes Collect/Control/Personal
+ * behavior. Only use `isPaidGroupPolicy` when the concern is genuinely billing/paid-only.
  *
- * Use this helper when Submit workspaces should be treated like paid workspaces
- * (e.g. access gating for shared workspace pages). For report-based call sites,
- * use `ReportUtils.isReportInGroupPolicy(report)`, which delegates to this helper.
+ * For report-based call sites, use `ReportUtils.isReportInGroupPolicy(report)`, which delegates here.
  */
 function isGroupPolicy(policy: OnyxInputOrEntry<Policy>): boolean {
     return isPaidGroupPolicy(policy) || isSubmitPolicy(policy);
diff --git a/src/libs/ReportUtils.ts b/src/libs/ReportUtils.ts
index 47d0b4bbb55e..35cb4becbdc9 100644
--- a/src/libs/ReportUtils.ts
+++ b/src/libs/ReportUtils.ts
@@ -1741,14 +1741,20 @@ function isCurrentUserInvoiceReceiver(report: OnyxEntry<Report>): boolean {
 }
 
 /**
- * Whether the provided report belongs to a paid group or Submit policy
+ * ✅ GROUP-FEATURE gating. Whether the report belongs to a group policy (Collect, Control, or Submit).
+ *
+ * Report-based counterpart of `PolicyUtils.isGroupPolicy`. Prefer this over `isPaidGroupPolicy(report)`
+ * for feature gating (violations, report fields, etc.) so free group plans like Submit aren't excluded.
  */
 function isReportInGroupPolicy(report: OnyxInputOrEntry<Report>, policy?: OnyxInputOrEntry<Policy>): boolean {
     return isGroupPolicyPolicyUtils(policy ?? allPolicies?.[`${ONYXKEYS.COLLECTION.POLICY}${report?.policyID}`]);
 }
 
 /**
- * Whether the provided report belongs to a Control or Collect policy
+ * ⚠️ BILLING / PAID-ONLY. Whether the report belongs to a paid policy (Collect/Control) only.
+ *
+ * Report-based counterpart of `PolicyUtils.isPaidGroupPolicy`. For group-feature gating use
+ * `isReportInGroupPolicy` instead, or Submit workspaces will be wrongly excluded.
  */
 function isPaidGroupPolicy(report: OnyxEntry<Report>): boolean {
     const policyType = getPolicyType(report, allPolicies);
@@ -9260,18 +9266,18 @@ function hasVisibleReportFieldViolations(report: OnyxEntry<Report>, policy: Onyx
         return false;
     }
 
-    const isPaidGroupPolicyReport = isExpenseReport(report) && (policy?.type === CONST.POLICY.TYPE.CORPORATE || policy?.type === CONST.POLICY.TYPE.TEAM);
-    if (!isPaidGroupPolicyReport && !isInvoiceReport(report)) {
+    const isGroupPolicyReport = isGroupPolicyExpenseReport(report);
+    if (!isGroupPolicyReport && !isInvoiceReport(report)) {
         return false;
     }
 
     // We only show the RBR to the submitter for expense reports
-    if (isPaidGroupPolicyReport && !isCurrentUserSubmitter(report)) {
+    if (isGroupPolicyReport && !isCurrentUserSubmitter(report)) {
         return false;
     }
 
     // Allow both open and processing reports to show RBR for field violations (expense reports only)
-    if (isPaidGroupPolicyReport && !isOpenOrProcessingReport(report)) {
+    if (isGroupPolicyReport && !isOpenOrProcessingReport(report)) {
         return false;
     }
 

From dfbd942e2ee554965b0ea3d451a22cf9dc8b92c9 Mon Sep 17 00:00:00 2001
From: Abdelrahman Khattab <abzokhattab@gmail.com>
Date: Tue, 9 Jun 2026 14:15:05 +0200
Subject: [PATCH 211/435] Use plain JSDoc (no emojis) for paid vs group policy
 helper docs

---
 src/libs/PolicyUtils.ts | 26 ++++++++++++--------------
 src/libs/ReportUtils.ts | 14 ++++++--------
 2 files changed, 18 insertions(+), 22 deletions(-)

diff --git a/src/libs/PolicyUtils.ts b/src/libs/PolicyUtils.ts
index bb9a21240af3..c95cc40e2c87 100644
--- a/src/libs/PolicyUtils.ts
+++ b/src/libs/PolicyUtils.ts
@@ -1080,16 +1080,14 @@ function isPendingDeletePolicy(policy: OnyxEntry<Policy>): boolean {
 }
 
 /**
- * ⚠️ BILLING / PAID-ONLY. Returns true only for paid plans (Collect/Control).
+ * Returns true only for paid plans (Collect/Control). Use this only for billing/paid-only concerns:
+ * subscriptions, payments and reimbursement, company cards, Expensify Card, Travel, Invoices, and
+ * "do I own a paid workspace" checks.
  *
- * Use this ONLY to gate billing/paid-only concerns: subscriptions, payments & reimbursement,
- * company cards, Expensify Card, Travel, Invoices, "do I own a paid workspace" checks.
- *
- * For "does this workspace have group features?" gating (violations, report fields, workspace
- * chat, report creation, expense-workspace usability) use `isGroupPolicy` instead — otherwise
- * free group plans like Submit (submit2026) are incorrectly excluded and you reintroduce
- * access bugs. For report-based call sites, the equivalents are `ReportUtils.isPaidGroupPolicy`
- * (paid-only) vs `ReportUtils.isReportInGroupPolicy` (group).
+ * For workspace feature gating (violations, report fields, workspace chat, report creation,
+ * expense-workspace usability) use `isGroupPolicy` instead, otherwise free group plans like Submit
+ * (submit2026) are wrongly excluded. The report-based counterparts are `ReportUtils.isPaidGroupPolicy`
+ * (paid-only) and `ReportUtils.isReportInGroupPolicy` (group).
  */
 function isPaidGroupPolicy(policy: OnyxInputOrEntry<Policy>): boolean {
     return policy?.type === CONST.POLICY.TYPE.TEAM || policy?.type === CONST.POLICY.TYPE.CORPORATE;
@@ -1122,13 +1120,13 @@ function canEditWorkspaceSettings(policy: OnyxInputOrEntry<Policy>, login?: stri
 }
 
 /**
- * ✅ GROUP-FEATURE gating. Returns true for any group workspace: paid (Collect/Control) or Submit.
+ * Returns true for any group workspace: paid (Collect/Control) or Submit.
  *
- * Prefer this over `isPaidGroupPolicy` whenever the check is about workspace *features* rather than
- * billing — violations, report fields, workspace chat, report creation, expense-workspace usability —
- * so free group plans like Submit (submit2026) aren't wrongly excluded. It's a strict superset of
+ * Prefer this over `isPaidGroupPolicy` whenever the check is about workspace features rather than
+ * billing (violations, report fields, workspace chat, report creation, expense-workspace usability),
+ * so free group plans like Submit (submit2026) are not excluded. It is a strict superset of
  * `isPaidGroupPolicy`, so switching a feature check to it never changes Collect/Control/Personal
- * behavior. Only use `isPaidGroupPolicy` when the concern is genuinely billing/paid-only.
+ * behavior. Use `isPaidGroupPolicy` only when the concern is genuinely billing/paid-only.
  *
  * For report-based call sites, use `ReportUtils.isReportInGroupPolicy(report)`, which delegates here.
  */
diff --git a/src/libs/ReportUtils.ts b/src/libs/ReportUtils.ts
index 35cb4becbdc9..0d0275453f14 100644
--- a/src/libs/ReportUtils.ts
+++ b/src/libs/ReportUtils.ts
@@ -1741,20 +1741,18 @@ function isCurrentUserInvoiceReceiver(report: OnyxEntry<Report>): boolean {
 }
 
 /**
- * ✅ GROUP-FEATURE gating. Whether the report belongs to a group policy (Collect, Control, or Submit).
- *
- * Report-based counterpart of `PolicyUtils.isGroupPolicy`. Prefer this over `isPaidGroupPolicy(report)`
- * for feature gating (violations, report fields, etc.) so free group plans like Submit aren't excluded.
+ * Whether the report belongs to a group policy (Collect, Control, or Submit). Report-based counterpart
+ * of `PolicyUtils.isGroupPolicy`. Prefer this over `isPaidGroupPolicy(report)` for feature gating
+ * (violations, report fields, etc.) so free group plans like Submit are not excluded.
  */
 function isReportInGroupPolicy(report: OnyxInputOrEntry<Report>, policy?: OnyxInputOrEntry<Policy>): boolean {
     return isGroupPolicyPolicyUtils(policy ?? allPolicies?.[`${ONYXKEYS.COLLECTION.POLICY}${report?.policyID}`]);
 }
 
 /**
- * ⚠️ BILLING / PAID-ONLY. Whether the report belongs to a paid policy (Collect/Control) only.
- *
- * Report-based counterpart of `PolicyUtils.isPaidGroupPolicy`. For group-feature gating use
- * `isReportInGroupPolicy` instead, or Submit workspaces will be wrongly excluded.
+ * Whether the report belongs to a paid policy (Collect/Control) only. Report-based counterpart of
+ * `PolicyUtils.isPaidGroupPolicy`. For group-feature gating use `isReportInGroupPolicy` instead,
+ * otherwise Submit workspaces are wrongly excluded.
  */
 function isPaidGroupPolicy(report: OnyxEntry<Report>): boolean {
     const policyType = getPolicyType(report, allPolicies);

From 60e19a8441bb46bb5181c7ac50151fdc0e5084cd Mon Sep 17 00:00:00 2001
From: Abdelrahman Khattab <abzokhattab@gmail.com>
Date: Tue, 9 Jun 2026 14:36:14 +0200
Subject: [PATCH 212/435] Fix knip: drop now-unused
 ReportUtils.isPaidGroupPolicy export

All external consumers were migrated to isReportInGroupPolicy; the report-based
isPaidGroupPolicy is now only used internally, so stop exporting it.
---
 src/libs/ReportUtils.ts | 1 -
 1 file changed, 1 deletion(-)

diff --git a/src/libs/ReportUtils.ts b/src/libs/ReportUtils.ts
index 0d0275453f14..3ac540b395e1 100644
--- a/src/libs/ReportUtils.ts
+++ b/src/libs/ReportUtils.ts
@@ -13490,7 +13490,6 @@ export {
     isOpenExpenseReport,
     isOpenTaskReport,
     isOptimisticPersonalDetail,
-    isPaidGroupPolicy,
     isPaidGroupPolicyExpenseReport,
     isGroupPolicyExpenseReport,
     isPayer,

From 379840b2fa8d1b8e399dd4cf2222b94dcf66f1cf Mon Sep 17 00:00:00 2001
From: mkhutornyi <mkhutorniy@gmail.com>
Date: Tue, 9 Jun 2026 13:36:18 +0100
Subject: [PATCH 213/435] address feedback

---
 .../Search/SearchAutocompleteList.tsx         | 47 ++++++++++---------
 1 file changed, 25 insertions(+), 22 deletions(-)

diff --git a/src/components/Search/SearchAutocompleteList.tsx b/src/components/Search/SearchAutocompleteList.tsx
index 37360092d84f..f71c8115ac94 100644
--- a/src/components/Search/SearchAutocompleteList.tsx
+++ b/src/components/Search/SearchAutocompleteList.tsx
@@ -570,11 +570,6 @@ function SearchAutocompleteList({
         reports,
     ]);
 
-    // Derive the highlight reference text from the actual first result rather than a fixed section index.
-    // After the two-section ("Recent chats" / "Search results") switcher, sections.at(1) can be the empty
-    // local section when a result is server-only, which would leave the first result unhighlighted.
-    const sectionItemText = styledRecentReports.at(0)?.text ?? '';
-    const normalizedReferenceText = sectionItemText.toLowerCase();
     const trimmedAutocompleteQueryValue = autocompleteQueryValue.trim();
     const isLoading = !isRecentSearchesDataLoaded;
     const suggestionsAnnouncement = suggestionsCount > 0 ? translate('search.suggestionsAvailable', {count: suggestionsCount}, trimmedAutocompleteQueryValue) : '';
@@ -584,29 +579,37 @@ function SearchAutocompleteList({
     const shouldAnnounceNoResults = !isLoading && suggestionsCount === 0 && !!trimmedAutocompleteQueryValue;
     useDebouncedAccessibilityAnnouncement(noResultsFoundText, shouldAnnounceNoResults, autocompleteQueryValue);
 
-    const firstRecentReportKey = styledRecentReports.at(0)?.keyForList;
+    // Locate the first recent report row in the order it is actually rendered. The two-section switcher sorts the
+    // local "Recent chats" rows by a frozen rank, so the rendered order can differ from styledRecentReports (the
+    // unsorted combined local + server list). Walking sections keeps the focused row, its reference text, and the
+    // initially focused key all pointing at the first row the user actually sees.
+    const recentReportKeys = new Set(styledRecentReports.map((report) => report.keyForList));
+    let firstRecentReportKey: string | undefined;
+    let firstRecentReportText = '';
     let firstRecentReportFlatIndex = -1;
-    if (firstRecentReportKey) {
-        let flatIndex = 0;
-        for (const section of sections) {
-            const hasData = (section.data?.length ?? 0) > 0;
-            const hasHeader = hasData && (section.title !== undefined || ('customHeader' in section && section.customHeader !== undefined));
-            if (hasHeader) {
-                flatIndex++;
-            }
-            for (const item of section.data ?? []) {
-                if (item.keyForList === firstRecentReportKey) {
-                    firstRecentReportFlatIndex = flatIndex;
-                    break;
-                }
-                flatIndex++;
-            }
-            if (firstRecentReportFlatIndex !== -1) {
+    let flatIndex = 0;
+    for (const section of sections) {
+        const hasData = (section.data?.length ?? 0) > 0;
+        const hasHeader = hasData && (section.title !== undefined || ('customHeader' in section && section.customHeader !== undefined));
+        if (hasHeader) {
+            flatIndex++;
+        }
+        for (const item of section.data ?? []) {
+            if (item.keyForList && recentReportKeys.has(item.keyForList)) {
+                firstRecentReportKey = item.keyForList;
+                firstRecentReportText = item.text ?? '';
+                firstRecentReportFlatIndex = flatIndex;
                 break;
             }
+            flatIndex++;
+        }
+        if (firstRecentReportFlatIndex !== -1) {
+            break;
         }
     }
 
+    const normalizedReferenceText = firstRecentReportText.toLowerCase();
+
     // When options initialize after the list is already mounted, initiallyFocusedItemKey has no effect
     // because useState(initialFocusedIndex) in useArrowKeyFocusManager only reads the initial value.
     // Imperatively focus the first recent report once options become available (desktop only).

From aef977535ea5200376275ad081f12e9739260ffc Mon Sep 17 00:00:00 2001
From: bartlomiej obudzinski <bartlomiej.obudzinski@callstack.com>
Date: Tue, 9 Jun 2026 14:52:37 +0200
Subject: [PATCH 214/435] Revert "fix: useOnyx deps and drop redundant useMemo
 in InboxTabButton"

This reverts commit 8a32b351ea46a48b7c66741fbe2a4eadbc30e6b7.
---
 .../Navigation/NavigationTabBar/InboxTabButton.tsx     | 10 ++++------
 1 file changed, 4 insertions(+), 6 deletions(-)

diff --git a/src/components/Navigation/NavigationTabBar/InboxTabButton.tsx b/src/components/Navigation/NavigationTabBar/InboxTabButton.tsx
index 806909023a48..6ae62b5a7f05 100644
--- a/src/components/Navigation/NavigationTabBar/InboxTabButton.tsx
+++ b/src/components/Navigation/NavigationTabBar/InboxTabButton.tsx
@@ -1,4 +1,4 @@
-import React from 'react';
+import React, {useMemo} from 'react';
 import type {OnyxEntry} from 'react-native-onyx';
 import type {ValueOf} from 'type-fest';
 import {PressableWithFeedback} from '@components/Pressable';
@@ -65,11 +65,9 @@ function InboxTabButton({selectedTab, isWideLayout, statusIndicatorColor, chatTa
 
     const [doesLastReportExist] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${lastReportRouteReportID}`, {selector: doesLastReportExistSelector}, [lastReportRouteReportID]);
 
-    const doesLastReportActionExistSelector = makeDoesLastReportActionExistSelector(lastReportRouteReportActionID);
-    const [doesLastReportActionExist] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${lastReportRouteReportID}`, {selector: doesLastReportActionExistSelector}, [
-        lastReportRouteReportID,
-        lastReportRouteReportActionID,
-    ]);
+    // Wrap factory in useMemo so the selector identity is stable per actionID
+    const doesLastReportActionExistSelector = useMemo(() => makeDoesLastReportActionExistSelector(lastReportRouteReportActionID), [lastReportRouteReportActionID]);
+    const [doesLastReportActionExist] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${lastReportRouteReportID}`, {selector: doesLastReportActionExistSelector}, [lastReportRouteReportID]);
 
     const inboxAccessibilityState = {selected: selectedTab === NAVIGATION_TABS.INBOX};
 

From bdb76e560e5ffce0e8821ecb9f42c52d53d0ad84 Mon Sep 17 00:00:00 2001
From: neil-marcellini <neil@expensify.com>
Date: Tue, 9 Jun 2026 09:02:33 -0400
Subject: [PATCH 215/435] Document MelvinBot workflow for contributors, C+, and
 CMEs

Adds a dedicated guide for proposal review, C+ PR ownership, and CME merge
on MelvinBot issues, and links it prominently from CONTRIBUTING.md.

Co-authored-by: Cursor <cursoragent@cursor.com>
---
 contributingGuides/CONTRIBUTING.md            |  5 +
 .../HOW_TO_BECOME_A_CONTRIBUTOR_PLUS.md       |  1 +
 .../HOW_TO_WORK_WITH_MELVINBOT.md             | 97 +++++++++++++++++++
 3 files changed, 103 insertions(+)
 create mode 100644 contributingGuides/HOW_TO_WORK_WITH_MELVINBOT.md

diff --git a/contributingGuides/CONTRIBUTING.md b/contributingGuides/CONTRIBUTING.md
index 449f5ff7a125..d874ccad4c96 100644
--- a/contributingGuides/CONTRIBUTING.md
+++ b/contributingGuides/CONTRIBUTING.md
@@ -4,6 +4,9 @@ Welcome! Thanks for checking out the New Expensify app and taking the time to co
 ## Getting Started
 If you would like to become an Expensify contributor, the first step is to read this document in its **entirety**. The second step is to review the README guidelines [here](https://github.com/Expensify/App/blob/main/README.md) to understand our coding philosophy and for a general overview of the code repository (i.e. how to run the app locally, testing, storage, our app philosophy, etc). Please read both documents before asking questions, as it may be covered within the documentation.
 
+### MelvinBot issues (read this)
+Many App jobs use [MelvinBot](https://github.com/Expensify/App/blob/main/contributingGuides/HOW_TO_WORK_WITH_MELVINBOT.md) (Melvin), our AI agent that posts the first proposal on an issue. **Do not open a pull request until a proposal is accepted.** Contributors, C+, and internal engineers each have specific responsibilities on these jobs. See **[How to Work with MelvinBot](./HOW_TO_WORK_WITH_MELVINBOT.md)** before working on any issue where Melvin has posted a proposal.
+
 ### Test Accounts
 You can create as many accounts as needed in order to test your changes directly from [the app](https://new.expensify.com/). An initial account can be created when logging in for the first time, and additional accounts can be created by opening the "New Chat" or "Group Chat" pages via the Global Create menu, inputting a valid email or phone number, and tapping the user's avatar. Do not use Expensify employee or customer accounts for testing.
 
@@ -153,6 +156,7 @@ This helps future investigators understand the history and current status of err
 
 ### Propose a solution for the job
 4. Proposals must only be posted after the `Help Wanted` label is added. Any proposals submitted beforehand will be ignored and not reviewed. Do not post proposals in Slack.
+    - On issues where [MelvinBot](./HOW_TO_WORK_WITH_MELVINBOT.md) has posted a proposal, Melvin's proposal will be first. Follow the same review standards and **do not open a PR** until a proposal is accepted. C+ members: see [How to Work with MelvinBot](./HOW_TO_WORK_WITH_MELVINBOT.md) for your implementation and PR ownership steps.
 5. Contributors should **not** submit proposals on issues when they have assigned issues or PRs that are awaiting an action from them. If so, they will be in violation of Rule #1 (Get Shit Done) in our [Code of Conduct](https://github.com/Expensify/App/blob/main/CODE_OF_CONDUCT.md) and will receive a warning. Multiple warnings can lead to removal from the program. 
 6. After you reproduce the issue, complete the [proposal template here](./PROPOSAL_TEMPLATE.md) and post it as a comment in the corresponding GitHub issue (linked in the Upwork job).
     - Note: Before submitting a proposal on an issue, be sure to read any other existing proposals. ALL NEW PROPOSALS MUST BE DIFFERENT FROM EXISTING PROPOSALS. The *difference* should be important, meaningful or considerable.
@@ -241,3 +245,4 @@ During communication with Expensify, you will come across a variety of acronyms
 - **QA:** Quality Assurance
 - **GH:** GitHub
 - **LGTM:*** Looks good to me
+- **Melv / MelvinBot:** Expensify's AI agent for App GitHub issues (posts proposals, implements accepted solutions). See [How to Work with MelvinBot](./HOW_TO_WORK_WITH_MELVINBOT.md).
diff --git a/contributingGuides/HOW_TO_BECOME_A_CONTRIBUTOR_PLUS.md b/contributingGuides/HOW_TO_BECOME_A_CONTRIBUTOR_PLUS.md
index 9993755274e5..65f56dd2e73e 100644
--- a/contributingGuides/HOW_TO_BECOME_A_CONTRIBUTOR_PLUS.md
+++ b/contributingGuides/HOW_TO_BECOME_A_CONTRIBUTOR_PLUS.md
@@ -2,6 +2,7 @@
 C+ are contributors who are experienced at working with Expensify and have gained the confidence of the internal Expensify team. Accordingly, they are allocated additional opportunities and responsibilities:
   - They review proposed solutions in external GitHub issues, validate them, and make recommendations to an internal Contributor Manager Engineer (CME).
   - Once a proposal has been accepted by a CME, the C+ will be the first person to review the pull request associated with that proposal.
+  - On [MelvinBot issues](./HOW_TO_WORK_WITH_MELVINBOT.md), the C+ reviews Melvin's proposal, directs implementation if accepted, and owns the PR as the human author before CME review.
 
 ## Why would someone want to be a C+
 - C+ are compensated the same price as the contributor for reviewing proposals and the associated PR. (ie. if a job is listed at $250, that’s how much the C+ will make if they review both the proposals and PR).  If regressions are found that should have* been caught after the PR has been approved, C+ payment is reduced by 50% for each regression found.
diff --git a/contributingGuides/HOW_TO_WORK_WITH_MELVINBOT.md b/contributingGuides/HOW_TO_WORK_WITH_MELVINBOT.md
new file mode 100644
index 000000000000..8f7b6296ad0a
--- /dev/null
+++ b/contributingGuides/HOW_TO_WORK_WITH_MELVINBOT.md
@@ -0,0 +1,97 @@
+# Working with MelvinBot on App Issues
+
+MelvinBot (Melvin) is Expensify's AI agent for App GitHub issues. On many open-source jobs, Melvin posts the first proposal automatically. This guide explains how contributors, Contributor+ (C+), and internal engineers work together on those issues.
+
+For general contributor workflow (proposals, payment, PR standards), see [CONTRIBUTING.md](./CONTRIBUTING.md). For C+ responsibilities, see [HOW_TO_BECOME_A_CONTRIBUTOR_PLUS.md](./HOW_TO_BECOME_A_CONTRIBUTOR_PLUS.md).
+
+## Why this process exists
+
+Melvin can open pull requests before a human has validated the approach. Without a clear process, contributors waste time on unapproved work, and internal engineers may review PRs that should not have been started. Proposal review must happen **before** implementation.
+
+## Roles
+
+| Role | Responsibility on Melvin issues |
+|------|----------------------------------|
+| **MelvinBot** | Posts the first proposal on the issue. Implements the accepted solution when asked. Opens a draft PR with MelvinBot as the GitHub author. |
+| **Contributor** | May submit their own proposal if they have a meaningfully different approach. Must not open a PR until a proposal is accepted and they are hired on the job. |
+| **Contributor+ (C+)** | Reviews proposals (Melvin's and any contributor proposals) using the same standards as any other job. If Melvin's proposal is accepted, asks Melvin to implement, then owns the PR as the human author before sending it for final review. |
+| **Contributor Manager Engineer (CME)** | Internal engineer assigned to review and merge the PR. |
+
+Only Expensify employees, C+ members, and backend contributors can trigger Melvin with `@MelvinBot` comments on GitHub.
+
+## Workflow overview
+
+```
+Issue opened → Melvin posts proposal → C+ reviews proposal(s)
+    → Accepted: C+ asks Melvin to implement
+    → Not accepted: C+ explains why
+→ Melvin opens draft PR → C+ tweaks, tests, completes Author checklist, self-reviews
+→ C+ submits PR for review as human author → CME reviews and merges
+```
+
+## Phase 1: Proposal review
+
+Melvin's proposal will always be the first on the issue. Follow the **same proposal review process** as any other App job:
+
+1. Use the [proposal template](./PROPOSAL_TEMPLATE.md) criteria: clear root cause, concrete solution, no code diffs.
+2. C+ reviews Melvin's proposal with the same rigor as a contributor proposal. Do not approve proposals that lack a satisfying root-cause explanation.
+3. Contributors may still post proposals if they have a **meaningfully different** approach (see [CONTRIBUTING.md](./CONTRIBUTING.md#propose-a-solution-for-the-job)).
+4. **No one opens a pull request** until a proposal is accepted.
+
+### If Melvin's proposal is accepted
+
+The assigned C+ comments on the issue asking Melvin to implement, for example:
+
+```
+@MelvinBot please implement your proposal
+```
+
+Adjust the wording if needed, but the comment must mention `@MelvinBot` and clearly request implementation.
+
+### If Melvin's proposal is not accepted
+
+The C+ explains **why** the proposal was not accepted (wrong root cause, incomplete solution, better alternative exists, etc.). If a contributor's proposal is accepted instead, follow the standard contributor hiring and implementation flow in [CONTRIBUTING.md](./CONTRIBUTING.md).
+
+When a C+ accepts a proposal, they may also post `🎀👀🎀` on the issue to trigger CME assignment for the job.
+
+## Phase 2: C+ owns the pull request
+
+Melvin opens a draft PR linked to the issue. MelvinBot remains the GitHub author on that branch until the C+ takes ownership.
+
+Before requesting final review, the assigned C+ must:
+
+1. **Manually tweak the PR** if Melvin's implementation needs corrections.
+2. **Test the change** on all required platforms (see [CONTRIBUTING.md](./CONTRIBUTING.md#make-sure-you-can-test-on-all-platforms)).
+3. **Complete every step** in the PR Author Checklist.
+4. **Self-review the code** against [PR Review Guidelines](./PR_REVIEW_GUIDELINES.md) and [PR Authoring & Reviewing Best Practices](./PR_AUTHOR_REVIEWER_BEST_PRACTICES.md).
+5. **Submit the PR for review** and become the **official human author** of record for that change.
+
+The C+ is accountable for the PR quality, the same as any contributor who authored a PR.
+
+## Phase 3: CME review and merge
+
+After the C+ submits the PR for review:
+
+1. A **CME** (internal engineer) is assigned to review and merge.
+2. The CME follows the normal internal review process.
+3. Payment and regression checklists follow the standard rules in [CONTRIBUTING.md](./CONTRIBUTING.md).
+
+### No additional contributor or C+ PR review
+
+We intentionally do **not** add a second round of contributor or C+ PR review on top of the CME review. Prior discussions did not surface a problem that extra review would solve, and an additional review step would add cost and delay without clear benefit. The C+ self-review before submission, combined with CME review, is the intended quality gate.
+
+## Quick reference: what not to do
+
+| Do not | Why |
+|--------|-----|
+| Open a PR before a proposal is accepted | Wastes contributor and reviewer time if the approach is wrong |
+| Skip C+ proposal review because Melvin wrote it | Melvin proposals need the same validation as human proposals |
+| Send Melvin's draft PR for CME review without testing and checklist completion | The C+ is the human author and owns quality |
+| Expect a second C+ or contributor review after C+ submission | Only the CME reviews before merge |
+
+## Related documentation
+
+- [CONTRIBUTING.md](./CONTRIBUTING.md) — full contributor workflow
+- [PROPOSAL_TEMPLATE.md](./PROPOSAL_TEMPLATE.md) — proposal format and C+ review instructions
+- [AI Etiquette](./AI_ETIQUETTE.md) — accountability for AI-assisted work
+- [AI Reviewer philosophy](./philosophies/AI-REVIEWER.md) — automated PR feedback vs human review

From ae783658fceed5e723dcbb5b4ac6cfaa60e829f6 Mon Sep 17 00:00:00 2001
From: bartlomiej obudzinski <bartlomiej.obudzinski@callstack.com>
Date: Tue, 9 Jun 2026 15:06:34 +0200
Subject: [PATCH 216/435] fix: useOnyx deps, drop useMemo, replace unsafe casts
 with type guards in InboxTabButton

---
 .../NavigationTabBar/InboxTabButton.tsx       | 32 ++++++++++++++-----
 1 file changed, 24 insertions(+), 8 deletions(-)

diff --git a/src/components/Navigation/NavigationTabBar/InboxTabButton.tsx b/src/components/Navigation/NavigationTabBar/InboxTabButton.tsx
index 6ae62b5a7f05..d5a94fbbcd59 100644
--- a/src/components/Navigation/NavigationTabBar/InboxTabButton.tsx
+++ b/src/components/Navigation/NavigationTabBar/InboxTabButton.tsx
@@ -1,4 +1,4 @@
-import React, {useMemo} from 'react';
+import React from 'react';
 import type {OnyxEntry} from 'react-native-onyx';
 import type {ValueOf} from 'type-fest';
 import {PressableWithFeedback} from '@components/Pressable';
@@ -11,7 +11,6 @@ import Navigation from '@libs/Navigation/Navigation';
 import navigationRef from '@libs/Navigation/navigationRef';
 import {isDeletedAction} from '@libs/ReportActionsUtils';
 import {startSpan} from '@libs/telemetry/activeSpans';
-import type {ReportsSplitNavigatorParamList} from '@navigation/types';
 import CONST from '@src/CONST';
 import NAVIGATORS from '@src/NAVIGATORS';
 import ONYXKEYS from '@src/ONYXKEYS';
@@ -22,6 +21,18 @@ import getLastRoute from './getLastRoute';
 import NAVIGATION_TABS from './NAVIGATION_TABS';
 import TabBarItem from './TabBarItem';
 
+function getStringParam(params: unknown, key: string): string | undefined {
+    if (!params || typeof params !== 'object') {
+        return undefined;
+    }
+    for (const [k, v] of Object.entries(params)) {
+        if (k === key && typeof v === 'string') {
+            return v;
+        }
+    }
+    return undefined;
+}
+
 type BrickRoad = ValueOf<typeof CONST.BRICK_ROAD_INDICATOR_STATUS> | undefined;
 
 type InboxTabButtonProps = {
@@ -52,7 +63,7 @@ function InboxTabButton({selectedTab, isWideLayout, statusIndicatorColor, chatTa
             return undefined;
         }
         const route = getLastRoute(rootState, NAVIGATORS.REPORTS_SPLIT_NAVIGATOR, SCREENS.REPORT);
-        return (route?.params as ReportsSplitNavigatorParamList[typeof SCREENS.REPORT])?.reportID;
+        return getStringParam(route?.params, 'reportID');
     });
 
     const lastReportRouteReportActionID = useRootNavigationState((rootState) => {
@@ -60,14 +71,16 @@ function InboxTabButton({selectedTab, isWideLayout, statusIndicatorColor, chatTa
             return undefined;
         }
         const route = getLastRoute(rootState, NAVIGATORS.REPORTS_SPLIT_NAVIGATOR, SCREENS.REPORT);
-        return (route?.params as ReportsSplitNavigatorParamList[typeof SCREENS.REPORT])?.reportActionID;
+        return getStringParam(route?.params, 'reportActionID');
     });
 
     const [doesLastReportExist] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${lastReportRouteReportID}`, {selector: doesLastReportExistSelector}, [lastReportRouteReportID]);
 
-    // Wrap factory in useMemo so the selector identity is stable per actionID
-    const doesLastReportActionExistSelector = useMemo(() => makeDoesLastReportActionExistSelector(lastReportRouteReportActionID), [lastReportRouteReportActionID]);
-    const [doesLastReportActionExist] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${lastReportRouteReportID}`, {selector: doesLastReportActionExistSelector}, [lastReportRouteReportID]);
+    const doesLastReportActionExistSelector = makeDoesLastReportActionExistSelector(lastReportRouteReportActionID);
+    const [doesLastReportActionExist] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${lastReportRouteReportID}`, {selector: doesLastReportActionExistSelector}, [
+        lastReportRouteReportID,
+        lastReportRouteReportActionID,
+    ]);
 
     const inboxAccessibilityState = {selected: selectedTab === NAVIGATION_TABS.INBOX};
 
@@ -86,7 +99,10 @@ function InboxTabButton({selectedTab, isWideLayout, statusIndicatorColor, chatTa
             const rootState = navigationRef.getRootState();
             const lastRoute = rootState ? getLastRoute(rootState, NAVIGATORS.REPORTS_SPLIT_NAVIGATOR, SCREENS.REPORT) : undefined;
             if (lastRoute) {
-                const {reportID, reportActionID, referrer, backTo} = lastRoute.params as ReportsSplitNavigatorParamList[typeof SCREENS.REPORT];
+                const reportID = getStringParam(lastRoute.params, 'reportID');
+                const reportActionID = getStringParam(lastRoute.params, 'reportActionID');
+                const referrer = getStringParam(lastRoute.params, 'referrer');
+                const backTo = getStringParam(lastRoute.params, 'backTo');
                 Navigation.navigate(ROUTES.REPORT_WITH_ID.getRoute(reportID, doesLastReportActionExist ? reportActionID : undefined, referrer, backTo));
                 return;
             }

From f46298b684357b389593b66a6aeacd3e9a6ebe18 Mon Sep 17 00:00:00 2001
From: neil-marcellini <neil@expensify.com>
Date: Tue, 9 Jun 2026 09:09:26 -0400
Subject: [PATCH 217/435] Clarify C+ must complete Reviewer Checklist during
 self-review

Co-authored-by: Cursor <cursoragent@cursor.com>
---
 contributingGuides/HOW_TO_WORK_WITH_MELVINBOT.md | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/contributingGuides/HOW_TO_WORK_WITH_MELVINBOT.md b/contributingGuides/HOW_TO_WORK_WITH_MELVINBOT.md
index 8f7b6296ad0a..cb46c9cfbe96 100644
--- a/contributingGuides/HOW_TO_WORK_WITH_MELVINBOT.md
+++ b/contributingGuides/HOW_TO_WORK_WITH_MELVINBOT.md
@@ -25,7 +25,7 @@ Only Expensify employees, C+ members, and backend contributors can trigger Melvi
 Issue opened → Melvin posts proposal → C+ reviews proposal(s)
     → Accepted: C+ asks Melvin to implement
     → Not accepted: C+ explains why
-→ Melvin opens draft PR → C+ tweaks, tests, completes Author checklist, self-reviews
+→ Melvin opens draft PR → C+ tweaks, tests, completes Author checklist, self-reviews (including Reviewer checklist)
 → C+ submits PR for review as human author → CME reviews and merges
 ```
 
@@ -63,7 +63,7 @@ Before requesting final review, the assigned C+ must:
 1. **Manually tweak the PR** if Melvin's implementation needs corrections.
 2. **Test the change** on all required platforms (see [CONTRIBUTING.md](./CONTRIBUTING.md#make-sure-you-can-test-on-all-platforms)).
 3. **Complete every step** in the PR Author Checklist.
-4. **Self-review the code** against [PR Review Guidelines](./PR_REVIEW_GUIDELINES.md) and [PR Authoring & Reviewing Best Practices](./PR_AUTHOR_REVIEWER_BEST_PRACTICES.md).
+4. **Self-review the code** against [PR Review Guidelines](./PR_REVIEW_GUIDELINES.md), [PR Authoring & Reviewing Best Practices](./PR_AUTHOR_REVIEWER_BEST_PRACTICES.md), and complete the [Reviewer Checklist](./REVIEWER_CHECKLIST.md) as part of that self-review.
 5. **Submit the PR for review** and become the **official human author** of record for that change.
 
 The C+ is accountable for the PR quality, the same as any contributor who authored a PR.
@@ -93,5 +93,6 @@ We intentionally do **not** add a second round of contributor or C+ PR review on
 
 - [CONTRIBUTING.md](./CONTRIBUTING.md) — full contributor workflow
 - [PROPOSAL_TEMPLATE.md](./PROPOSAL_TEMPLATE.md) — proposal format and C+ review instructions
+- [Reviewer Checklist](./REVIEWER_CHECKLIST.md) — C+ completes this during self-review before submitting for CME review
 - [AI Etiquette](./AI_ETIQUETTE.md) — accountability for AI-assisted work
 - [AI Reviewer philosophy](./philosophies/AI-REVIEWER.md) — automated PR feedback vs human review

From dd03967fd3c09297cfa8ab7e9babed0536dbb938 Mon Sep 17 00:00:00 2001
From: neil-marcellini <neil@expensify.com>
Date: Tue, 9 Jun 2026 09:14:37 -0400
Subject: [PATCH 218/435] Add Melv and MelvinBot to cspell dictionary

Fixes spellcheck failure on the Melv acronym in CONTRIBUTING.md.

Co-authored-by: Cursor <cursoragent@cursor.com>
---
 cspell.json | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/cspell.json b/cspell.json
index 5a6fad6a1adc..ca327c58ed5a 100644
--- a/cspell.json
+++ b/cspell.json
@@ -202,6 +202,9 @@
         "Marqeta",
         "McAfee",
         "Michelina",
+        "Melv",
+        "Melvin",
+        "MelvinBot",
         "Menlo",
         "Microtransaction",
         "Miniwarehouses",

From f2cc81040a9d3023613cef8515dd3dd9178ca31c Mon Sep 17 00:00:00 2001
From: bartlomiej obudzinski <bartlomiej.obudzinski@callstack.com>
Date: Tue, 9 Jun 2026 15:15:33 +0200
Subject: [PATCH 219/435] fix: add missing reportActionsList arg in
 PolicyMemberTest

---
 tests/actions/PolicyMemberTest.ts | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/tests/actions/PolicyMemberTest.ts b/tests/actions/PolicyMemberTest.ts
index 6d65a4f7a1b7..414995f62ed0 100644
--- a/tests/actions/PolicyMemberTest.ts
+++ b/tests/actions/PolicyMemberTest.ts
@@ -478,7 +478,7 @@ describe('actions/PolicyMember', () => {
 
             mockFetch?.pause?.();
             // When the caller passes ROLE.USER for a Submit workspace
-            Member.addMembersToWorkspace({[newUserEmail]: 1234}, 'Welcome', policy, [], CONST.POLICY.ROLE.USER, TestHelper.formatPhoneNumber, currentUser);
+            Member.addMembersToWorkspace({[newUserEmail]: 1234}, 'Welcome', policy, [], CONST.POLICY.ROLE.USER, TestHelper.formatPhoneNumber, currentUser, {});
 
             await waitForBatchedUpdates();
 
@@ -511,7 +511,7 @@ describe('actions/PolicyMember', () => {
 
             mockFetch?.pause?.();
             // When the caller passes ROLE.USER on a non-Submit workspace
-            Member.addMembersToWorkspace({[newUserEmail]: 1234}, 'Welcome', policy, [], CONST.POLICY.ROLE.USER, TestHelper.formatPhoneNumber, currentUser);
+            Member.addMembersToWorkspace({[newUserEmail]: 1234}, 'Welcome', policy, [], CONST.POLICY.ROLE.USER, TestHelper.formatPhoneNumber, currentUser, {});
 
             await waitForBatchedUpdates();
 
@@ -554,7 +554,7 @@ describe('actions/PolicyMember', () => {
 
             // When inviting a new member on a Submit workspace (role is forced to Editor)
             mockFetch?.pause?.();
-            Member.addMembersToWorkspace({[editorEmail]: editorAccountID}, 'Welcome', policy, [], CONST.POLICY.ROLE.USER, TestHelper.formatPhoneNumber, currentUser);
+            Member.addMembersToWorkspace({[editorEmail]: editorAccountID}, 'Welcome', policy, [], CONST.POLICY.ROLE.USER, TestHelper.formatPhoneNumber, currentUser, {});
 
             await waitForBatchedUpdates();
 

From 9ff2bd6551be9df1052986fda759098651c387f5 Mon Sep 17 00:00:00 2001
From: neil-marcellini <neil@expensify.com>
Date: Tue, 9 Jun 2026 09:37:08 -0400
Subject: [PATCH 220/435] Document C+ PR body workaround via issue comment and
 MelvinBot

C+ who cannot edit Melvin-authored PR descriptions should post the full
body or checklist in a details block and ask Melvin to apply it; CMEs
may review that comment directly.

Co-authored-by: Cursor <cursoragent@cursor.com>
---
 .../HOW_TO_WORK_WITH_MELVINBOT.md             | 52 +++++++++++++++++--
 1 file changed, 47 insertions(+), 5 deletions(-)

diff --git a/contributingGuides/HOW_TO_WORK_WITH_MELVINBOT.md b/contributingGuides/HOW_TO_WORK_WITH_MELVINBOT.md
index cb46c9cfbe96..49ad662bed43 100644
--- a/contributingGuides/HOW_TO_WORK_WITH_MELVINBOT.md
+++ b/contributingGuides/HOW_TO_WORK_WITH_MELVINBOT.md
@@ -25,8 +25,8 @@ Only Expensify employees, C+ members, and backend contributors can trigger Melvi
 Issue opened → Melvin posts proposal → C+ reviews proposal(s)
     → Accepted: C+ asks Melvin to implement
     → Not accepted: C+ explains why
-→ Melvin opens draft PR → C+ tweaks, tests, completes Author checklist, self-reviews (including Reviewer checklist)
-→ C+ submits PR for review as human author → CME reviews and merges
+→ Melvin opens draft PR → C+ tweaks, tests, posts PR body/checklist in issue comment, asks Melvin to apply it, self-reviews (including Reviewer checklist)
+→ C+ submits PR for review as human author → CME reviews and merges (PR body and/or C+ comment)
 ```
 
 ## Phase 1: Proposal review
@@ -56,24 +56,65 @@ When a C+ accepts a proposal, they may also post `🎀👀🎀` on the issue to
 
 ## Phase 2: C+ owns the pull request
 
-Melvin opens a draft PR linked to the issue. MelvinBot remains the GitHub author on that branch until the C+ takes ownership.
+Melvin opens a draft PR linked to the issue. MelvinBot remains the GitHub author on GitHub until the C+ takes ownership of the work. Because MelvinBot is the PR author, most C+ members **cannot edit the PR description directly** (GitHub only allows the author or users with write access to edit a pull request body).
 
 Before requesting final review, the assigned C+ must:
 
 1. **Manually tweak the PR** if Melvin's implementation needs corrections.
 2. **Test the change** on all required platforms (see [CONTRIBUTING.md](./CONTRIBUTING.md#make-sure-you-can-test-on-all-platforms)).
-3. **Complete every step** in the PR Author Checklist.
+3. **Complete every step** in the PR Author Checklist (see [Updating the PR description and checklist](#updating-the-pr-description-and-checklist) below).
 4. **Self-review the code** against [PR Review Guidelines](./PR_REVIEW_GUIDELINES.md), [PR Authoring & Reviewing Best Practices](./PR_AUTHOR_REVIEWER_BEST_PRACTICES.md), and complete the [Reviewer Checklist](./REVIEWER_CHECKLIST.md) as part of that self-review.
 5. **Submit the PR for review** and become the **official human author** of record for that change.
 
 The C+ is accountable for the PR quality, the same as any contributor who authored a PR.
 
+### Updating the PR description and checklist
+
+C+ members who cannot edit the PR body directly should use this workaround:
+
+1. On the **linked GitHub issue** (not the PR), post a comment with the exact content you want in the PR description. Put the full body inside a `<details>` block so the issue thread stays readable. Include the complete [PR template](https://github.com/Expensify/App/blob/main/.github/PULL_REQUEST_TEMPLATE.md) when possible: Explanation of Change, Fixed Issues, Tests, Offline tests, QA Steps, a fully checked PR Author Checklist, and Screenshots/Videos sections as needed.
+2. In the same comment, ask Melvin to copy that content into the pull request body, for example:
+
+```
+@MelvinBot please set the PR body to the content in the details section above
+```
+
+To update only the checklist, post the checklist section in a `<details>` block and ask Melvin to set just that portion of the PR body.
+
+Example:
+
+```markdown
+<details>
+<summary>PR body for MelvinBot to apply</summary>
+
+### Explanation of Change
+...
+
+### Fixed Issues
+$ https://github.com/Expensify/App/issues/12345
+
+### Tests
+1. ...
+
+### PR Author Checklist
+- [x] I linked the correct issue in the `### Fixed Issues` section above
+...
+
+</details>
+
+@MelvinBot please set the PR body to the content in the details section above
+```
+
+3. Confirm Melvin updated the PR description before marking the pull request ready for review.
+
+The C+ comment is the **source of truth** for what was tested and checked. CMEs may review that comment directly when the PR body is incomplete, out of date, or hard to verify.
+
 ## Phase 3: CME review and merge
 
 After the C+ submits the PR for review:
 
 1. A **CME** (internal engineer) is assigned to review and merge.
-2. The CME follows the normal internal review process.
+2. The CME follows the normal internal review process. Review the **PR body** when Melvin has applied the C+ content, or review the C+ **issue comment** (with the `<details>` block) directly for testing steps and checklist completion.
 3. Payment and regression checklists follow the standard rules in [CONTRIBUTING.md](./CONTRIBUTING.md).
 
 ### No additional contributor or C+ PR review
@@ -87,6 +128,7 @@ We intentionally do **not** add a second round of contributor or C+ PR review on
 | Open a PR before a proposal is accepted | Wastes contributor and reviewer time if the approach is wrong |
 | Skip C+ proposal review because Melvin wrote it | Melvin proposals need the same validation as human proposals |
 | Send Melvin's draft PR for CME review without testing and checklist completion | The C+ is the human author and owns quality |
+| Assume you can edit Melvin's PR description in the GitHub UI | Post the body in an issue comment and ask `@MelvinBot` to apply it |
 | Expect a second C+ or contributor review after C+ submission | Only the CME reviews before merge |
 
 ## Related documentation

From b6515d7ba5c201902b86d9492f4ebaae5e294d5a Mon Sep 17 00:00:00 2001
From: Youssef Lourayad <youssef@expensify.com>
Date: Tue, 9 Jun 2026 13:42:34 +0000
Subject: [PATCH 221/435] Lint

---
 src/components/LHNOptionsList/LHNEmptyState.tsx | 6 +++---
 src/pages/inbox/sidebar/InboxTabSelector.tsx    | 8 ++++++--
 2 files changed, 9 insertions(+), 5 deletions(-)

diff --git a/src/components/LHNOptionsList/LHNEmptyState.tsx b/src/components/LHNOptionsList/LHNEmptyState.tsx
index b8498ac7af75..f3626566a96b 100644
--- a/src/components/LHNOptionsList/LHNEmptyState.tsx
+++ b/src/components/LHNOptionsList/LHNEmptyState.tsx
@@ -20,7 +20,7 @@ function LHNEmptyState() {
     const styles = useThemeStyles();
     const {translate} = useLocalize();
     const expensifyIcons = useMemoizedLazyExpensifyIcons(['MagnifyingGlass', 'Plus']);
-    const emptyLHNIllustration = useEmptyLHNIllustration();
+    const emptyLHNIllustration = useEmptyLHNIllustration() as BlockingViewProps;
     const {activeTab} = useSidebarOrderedReportsState();
     const {setActiveTab} = useSidebarOrderedReportsActions();
 
@@ -40,7 +40,7 @@ function LHNEmptyState() {
 
         return (
             <BlockingView
-                {...(emptyLHNIllustration as BlockingViewProps)}
+                {...emptyLHNIllustration}
                 title={title}
                 titleStyles={styles.mb2}
                 CustomSubtitle={caughtUpSubtitle}
@@ -87,7 +87,7 @@ function LHNEmptyState() {
 
     return (
         <BlockingView
-            {...(emptyLHNIllustration as BlockingViewProps)}
+            {...emptyLHNIllustration}
             title={translate('common.emptyLHN.title')}
             CustomSubtitle={subtitle}
             accessibilityLabel={translate('common.emptyLHN.title')}
diff --git a/src/pages/inbox/sidebar/InboxTabSelector.tsx b/src/pages/inbox/sidebar/InboxTabSelector.tsx
index 6e80677cfbfe..a675df7900eb 100644
--- a/src/pages/inbox/sidebar/InboxTabSelector.tsx
+++ b/src/pages/inbox/sidebar/InboxTabSelector.tsx
@@ -1,6 +1,5 @@
 import React from 'react';
 import {View} from 'react-native';
-import type {ValueOf} from 'type-fest';
 import TabSelectorBase from '@components/TabSelector/TabSelectorBase';
 import TabSelectorContextProvider from '@components/TabSelector/TabSelectorContext';
 import type {TabSelectorBaseItem} from '@components/TabSelector/types';
@@ -44,7 +43,12 @@ function InboxTabSelector() {
                 <TabSelectorBase
                     tabs={tabs}
                     activeTabKey={activeTab}
-                    onTabPress={(key) => setActiveTab(key as ValueOf<typeof CONST.INBOX_TAB>)}
+                    onTabPress={(key) => {
+                        if (key !== CONST.INBOX_TAB.ALL && key !== CONST.INBOX_TAB.UNREAD && key !== CONST.INBOX_TAB.TODO) {
+                            return;
+                        }
+                        setActiveTab(key);
+                    }}
                     equalWidth
                     contentContainerStyles={styles.pb1}
                 />

From 11b1b2231365f693efad2a2e5602ed823db2e2fd Mon Sep 17 00:00:00 2001
From: bartlomiej obudzinski <bartlomiej.obudzinski@callstack.com>
Date: Tue, 9 Jun 2026 15:44:13 +0200
Subject: [PATCH 222/435] fix: use jest.mocked instead of unsafe require cast
 in useHoldRejectActionsTest

---
 tests/unit/hooks/useHoldRejectActionsTest.ts | 9 ++++-----
 1 file changed, 4 insertions(+), 5 deletions(-)

diff --git a/tests/unit/hooks/useHoldRejectActionsTest.ts b/tests/unit/hooks/useHoldRejectActionsTest.ts
index 45e2ba90b7fd..85dc4f3eb67e 100644
--- a/tests/unit/hooks/useHoldRejectActionsTest.ts
+++ b/tests/unit/hooks/useHoldRejectActionsTest.ts
@@ -1,5 +1,6 @@
 import {renderHook} from '@testing-library/react-native';
 import Onyx from 'react-native-onyx';
+import {useDelegateNoAccessActions, useDelegateNoAccessState} from '@components/DelegateNoAccessModalProvider';
 import useHoldRejectActions from '@hooks/useHoldRejectActions';
 import CONST from '@src/CONST';
 import ONYXKEYS from '@src/ONYXKEYS';
@@ -65,8 +66,6 @@ jest.mock('@libs/ReportUtils', () => ({
     changeMoneyRequestHoldStatus: jest.fn(),
 }));
 
-const DelegateProvider = require('@components/DelegateNoAccessModalProvider') as Record<string, jest.Mock>;
-
 const mockReport: Report = {
     reportID: TEST_REPORT_ID,
     chatReportID: '2',
@@ -96,8 +95,8 @@ describe('useHoldRejectActions - report-level reject', () => {
         await Onyx.clear();
         await waitForBatchedUpdates();
         jest.clearAllMocks();
-        DelegateProvider.useDelegateNoAccessState.mockReturnValue({isDelegateAccessRestricted: false});
-        DelegateProvider.useDelegateNoAccessActions.mockReturnValue({showDelegateNoAccessModal: mockShowDelegateNoAccessModal});
+        jest.mocked(useDelegateNoAccessState).mockReturnValue({isDelegateAccessRestricted: false, isActingAsDelegate: false});
+        jest.mocked(useDelegateNoAccessActions).mockReturnValue({showDelegateNoAccessModal: mockShowDelegateNoAccessModal});
         await Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT}${TEST_REPORT_ID}`, mockReport);
     });
 
@@ -124,7 +123,7 @@ describe('useHoldRejectActions - report-level reject', () => {
     });
 
     it('shows the delegate no-access modal and does nothing else when delegate access is restricted', async () => {
-        DelegateProvider.useDelegateNoAccessState.mockReturnValue({isDelegateAccessRestricted: true});
+        jest.mocked(useDelegateNoAccessState).mockReturnValue({isDelegateAccessRestricted: true, isActingAsDelegate: false});
         await Onyx.merge(ONYXKEYS.NVP_DISMISSED_REJECT_USE_EXPLANATION, false);
         await waitForBatchedUpdates();
 

From 36aed5593785ad7cc52225b08acedd8f5445474c Mon Sep 17 00:00:00 2001
From: bartlomiej obudzinski <bartlomiej.obudzinski@callstack.com>
Date: Tue, 9 Jun 2026 15:45:02 +0200
Subject: [PATCH 223/435] Revert "fix: use jest.mocked instead of unsafe
 require cast in useHoldRejectActionsTest"

This reverts commit 11b1b2231365f693efad2a2e5602ed823db2e2fd.
---
 tests/unit/hooks/useHoldRejectActionsTest.ts | 9 +++++----
 1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/tests/unit/hooks/useHoldRejectActionsTest.ts b/tests/unit/hooks/useHoldRejectActionsTest.ts
index 85dc4f3eb67e..45e2ba90b7fd 100644
--- a/tests/unit/hooks/useHoldRejectActionsTest.ts
+++ b/tests/unit/hooks/useHoldRejectActionsTest.ts
@@ -1,6 +1,5 @@
 import {renderHook} from '@testing-library/react-native';
 import Onyx from 'react-native-onyx';
-import {useDelegateNoAccessActions, useDelegateNoAccessState} from '@components/DelegateNoAccessModalProvider';
 import useHoldRejectActions from '@hooks/useHoldRejectActions';
 import CONST from '@src/CONST';
 import ONYXKEYS from '@src/ONYXKEYS';
@@ -66,6 +65,8 @@ jest.mock('@libs/ReportUtils', () => ({
     changeMoneyRequestHoldStatus: jest.fn(),
 }));
 
+const DelegateProvider = require('@components/DelegateNoAccessModalProvider') as Record<string, jest.Mock>;
+
 const mockReport: Report = {
     reportID: TEST_REPORT_ID,
     chatReportID: '2',
@@ -95,8 +96,8 @@ describe('useHoldRejectActions - report-level reject', () => {
         await Onyx.clear();
         await waitForBatchedUpdates();
         jest.clearAllMocks();
-        jest.mocked(useDelegateNoAccessState).mockReturnValue({isDelegateAccessRestricted: false, isActingAsDelegate: false});
-        jest.mocked(useDelegateNoAccessActions).mockReturnValue({showDelegateNoAccessModal: mockShowDelegateNoAccessModal});
+        DelegateProvider.useDelegateNoAccessState.mockReturnValue({isDelegateAccessRestricted: false});
+        DelegateProvider.useDelegateNoAccessActions.mockReturnValue({showDelegateNoAccessModal: mockShowDelegateNoAccessModal});
         await Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT}${TEST_REPORT_ID}`, mockReport);
     });
 
@@ -123,7 +124,7 @@ describe('useHoldRejectActions - report-level reject', () => {
     });
 
     it('shows the delegate no-access modal and does nothing else when delegate access is restricted', async () => {
-        jest.mocked(useDelegateNoAccessState).mockReturnValue({isDelegateAccessRestricted: true, isActingAsDelegate: false});
+        DelegateProvider.useDelegateNoAccessState.mockReturnValue({isDelegateAccessRestricted: true});
         await Onyx.merge(ONYXKEYS.NVP_DISMISSED_REJECT_USE_EXPLANATION, false);
         await waitForBatchedUpdates();
 

From beee43fcf4fb84e1be79617bf8b772f6d183b9ab Mon Sep 17 00:00:00 2001
From: neil-marcellini <neil@expensify.com>
Date: Tue, 9 Jun 2026 09:49:31 -0400
Subject: [PATCH 224/435] Fix PR body workaround: comment on the PR, not the
 issue

Co-authored-by: Cursor <cursoragent@cursor.com>
---
 contributingGuides/HOW_TO_WORK_WITH_MELVINBOT.md | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/contributingGuides/HOW_TO_WORK_WITH_MELVINBOT.md b/contributingGuides/HOW_TO_WORK_WITH_MELVINBOT.md
index 49ad662bed43..8adea0ed267c 100644
--- a/contributingGuides/HOW_TO_WORK_WITH_MELVINBOT.md
+++ b/contributingGuides/HOW_TO_WORK_WITH_MELVINBOT.md
@@ -25,8 +25,8 @@ Only Expensify employees, C+ members, and backend contributors can trigger Melvi
 Issue opened → Melvin posts proposal → C+ reviews proposal(s)
     → Accepted: C+ asks Melvin to implement
     → Not accepted: C+ explains why
-→ Melvin opens draft PR → C+ tweaks, tests, posts PR body/checklist in issue comment, asks Melvin to apply it, self-reviews (including Reviewer checklist)
-→ C+ submits PR for review as human author → CME reviews and merges (PR body and/or C+ comment)
+→ Melvin opens draft PR → C+ tweaks, tests, posts PR body/checklist in a PR comment, asks Melvin to apply it, self-reviews (including Reviewer checklist)
+→ C+ submits PR for review as human author → CME reviews and merges (PR body and/or C+ PR comment)
 ```
 
 ## Phase 1: Proposal review
@@ -72,7 +72,7 @@ The C+ is accountable for the PR quality, the same as any contributor who author
 
 C+ members who cannot edit the PR body directly should use this workaround:
 
-1. On the **linked GitHub issue** (not the PR), post a comment with the exact content you want in the PR description. Put the full body inside a `<details>` block so the issue thread stays readable. Include the complete [PR template](https://github.com/Expensify/App/blob/main/.github/PULL_REQUEST_TEMPLATE.md) when possible: Explanation of Change, Fixed Issues, Tests, Offline tests, QA Steps, a fully checked PR Author Checklist, and Screenshots/Videos sections as needed.
+1. On the **pull request**, post a comment with the exact content you want in the PR description. Put the full body inside a `<details>` block so the PR thread stays readable. Include the complete [PR template](https://github.com/Expensify/App/blob/main/.github/PULL_REQUEST_TEMPLATE.md) when possible: Explanation of Change, Fixed Issues, Tests, Offline tests, QA Steps, a fully checked PR Author Checklist, and Screenshots/Videos sections as needed.
 2. In the same comment, ask Melvin to copy that content into the pull request body, for example:
 
 ```
@@ -107,14 +107,14 @@ $ https://github.com/Expensify/App/issues/12345
 
 3. Confirm Melvin updated the PR description before marking the pull request ready for review.
 
-The C+ comment is the **source of truth** for what was tested and checked. CMEs may review that comment directly when the PR body is incomplete, out of date, or hard to verify.
+The C+ PR comment is the **source of truth** for what was tested and checked. CMEs may review that comment directly when the PR body is incomplete, out of date, or hard to verify.
 
 ## Phase 3: CME review and merge
 
 After the C+ submits the PR for review:
 
 1. A **CME** (internal engineer) is assigned to review and merge.
-2. The CME follows the normal internal review process. Review the **PR body** when Melvin has applied the C+ content, or review the C+ **issue comment** (with the `<details>` block) directly for testing steps and checklist completion.
+2. The CME follows the normal internal review process. Review the **PR body** when Melvin has applied the C+ content, or review the C+ **PR comment** (with the `<details>` block) directly for testing steps and checklist completion.
 3. Payment and regression checklists follow the standard rules in [CONTRIBUTING.md](./CONTRIBUTING.md).
 
 ### No additional contributor or C+ PR review
@@ -128,7 +128,7 @@ We intentionally do **not** add a second round of contributor or C+ PR review on
 | Open a PR before a proposal is accepted | Wastes contributor and reviewer time if the approach is wrong |
 | Skip C+ proposal review because Melvin wrote it | Melvin proposals need the same validation as human proposals |
 | Send Melvin's draft PR for CME review without testing and checklist completion | The C+ is the human author and owns quality |
-| Assume you can edit Melvin's PR description in the GitHub UI | Post the body in an issue comment and ask `@MelvinBot` to apply it |
+| Assume you can edit Melvin's PR description in the GitHub UI | Post the body in a PR comment and ask `@MelvinBot` to apply it |
 | Expect a second C+ or contributor review after C+ submission | Only the CME reviews before merge |
 
 ## Related documentation

From c4cc06af6ea73ae44348ee262ceaa7b9c3f2a24f Mon Sep 17 00:00:00 2001
From: neil-marcellini <neil@expensify.com>
Date: Tue, 9 Jun 2026 09:53:22 -0400
Subject: [PATCH 225/435] Clarify CME must approve proposal before Melvin
 implements
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Reorder Phase 1 so C+ recommends via 🎀👀🎀, CME approves, then C+ asks
Melvin to implement—not immediately after C+ review.

Co-authored-by: Cursor <cursoragent@cursor.com>
---
 .../HOW_TO_BECOME_A_CONTRIBUTOR_PLUS.md       |  2 +-
 .../HOW_TO_WORK_WITH_MELVINBOT.md             | 28 ++++++++++++-------
 2 files changed, 19 insertions(+), 11 deletions(-)

diff --git a/contributingGuides/HOW_TO_BECOME_A_CONTRIBUTOR_PLUS.md b/contributingGuides/HOW_TO_BECOME_A_CONTRIBUTOR_PLUS.md
index 65f56dd2e73e..9922324c1ea8 100644
--- a/contributingGuides/HOW_TO_BECOME_A_CONTRIBUTOR_PLUS.md
+++ b/contributingGuides/HOW_TO_BECOME_A_CONTRIBUTOR_PLUS.md
@@ -2,7 +2,7 @@
 C+ are contributors who are experienced at working with Expensify and have gained the confidence of the internal Expensify team. Accordingly, they are allocated additional opportunities and responsibilities:
   - They review proposed solutions in external GitHub issues, validate them, and make recommendations to an internal Contributor Manager Engineer (CME).
   - Once a proposal has been accepted by a CME, the C+ will be the first person to review the pull request associated with that proposal.
-  - On [MelvinBot issues](./HOW_TO_WORK_WITH_MELVINBOT.md), the C+ reviews Melvin's proposal, directs implementation if accepted, and owns the PR as the human author before CME review.
+  - On [MelvinBot issues](./HOW_TO_WORK_WITH_MELVINBOT.md), the C+ reviews Melvin's proposal, recommends it to the CME, asks Melvin to implement after CME approval, and owns the PR as the human author before CME PR review.
 
 ## Why would someone want to be a C+
 - C+ are compensated the same price as the contributor for reviewing proposals and the associated PR. (ie. if a job is listed at $250, that’s how much the C+ will make if they review both the proposals and PR).  If regressions are found that should have* been caught after the PR has been approved, C+ payment is reduced by 50% for each regression found.
diff --git a/contributingGuides/HOW_TO_WORK_WITH_MELVINBOT.md b/contributingGuides/HOW_TO_WORK_WITH_MELVINBOT.md
index 8adea0ed267c..aca6d124642b 100644
--- a/contributingGuides/HOW_TO_WORK_WITH_MELVINBOT.md
+++ b/contributingGuides/HOW_TO_WORK_WITH_MELVINBOT.md
@@ -14,8 +14,8 @@ Melvin can open pull requests before a human has validated the approach. Without
 |------|----------------------------------|
 | **MelvinBot** | Posts the first proposal on the issue. Implements the accepted solution when asked. Opens a draft PR with MelvinBot as the GitHub author. |
 | **Contributor** | May submit their own proposal if they have a meaningfully different approach. Must not open a PR until a proposal is accepted and they are hired on the job. |
-| **Contributor+ (C+)** | Reviews proposals (Melvin's and any contributor proposals) using the same standards as any other job. If Melvin's proposal is accepted, asks Melvin to implement, then owns the PR as the human author before sending it for final review. |
-| **Contributor Manager Engineer (CME)** | Internal engineer assigned to review and merge the PR. |
+| **Contributor+ (C+)** | Reviews proposals (Melvin's and any contributor proposals) using the same standards as any other job. Recommends acceptance to the CME. After the CME approves, asks Melvin to implement, then owns the PR as the human author before sending it for final review. |
+| **Contributor Manager Engineer (CME)** | Reviews and approves proposals (same as any other App job). After implementation, reviews and merges the PR. |
 
 Only Expensify employees, C+ members, and backend contributors can trigger Melvin with `@MelvinBot` comments on GitHub.
 
@@ -23,8 +23,9 @@ Only Expensify employees, C+ members, and backend contributors can trigger Melvi
 
 ```
 Issue opened → Melvin posts proposal → C+ reviews proposal(s)
-    → Accepted: C+ asks Melvin to implement
-    → Not accepted: C+ explains why
+    → C+ recommends acceptance (🎀👀🎀) → CME approves proposal
+    → C+ asks Melvin to implement (only after CME approval)
+    → Not accepted: C+ or CME explains why
 → Melvin opens draft PR → C+ tweaks, tests, posts PR body/checklist in a PR comment, asks Melvin to apply it, self-reviews (including Reviewer checklist)
 → C+ submits PR for review as human author → CME reviews and merges (PR body and/or C+ PR comment)
 ```
@@ -36,11 +37,19 @@ Melvin's proposal will always be the first on the issue. Follow the **same propo
 1. Use the [proposal template](./PROPOSAL_TEMPLATE.md) criteria: clear root cause, concrete solution, no code diffs.
 2. C+ reviews Melvin's proposal with the same rigor as a contributor proposal. Do not approve proposals that lack a satisfying root-cause explanation.
 3. Contributors may still post proposals if they have a **meaningfully different** approach (see [CONTRIBUTING.md](./CONTRIBUTING.md#propose-a-solution-for-the-job)).
-4. **No one opens a pull request** until a proposal is accepted.
+4. **No one opens a pull request** until a proposal is accepted by the CME (same as any other App job; see [CONTRIBUTING.md](./CONTRIBUTING.md#propose-a-solution-for-the-job)).
 
-### If Melvin's proposal is accepted
+### C+ reviews and recommends
 
-The assigned C+ comments on the issue asking Melvin to implement, for example:
+The C+ reviews Melvin's proposal with the same rigor as a contributor proposal. Follow the [proposal template](./PROPOSAL_TEMPLATE.md) review instructions.
+
+When the C+ is satisfied with Melvin's proposal, they recommend it to the CME by posting `🎀👀🎀` on the issue. That triggers CME assignment for the job.
+
+**Do not ask Melvin to implement until the CME has approved the proposal.** C+ recommendation is not the same as CME approval.
+
+### After the CME approves the proposal
+
+Once the assigned CME has approved Melvin's proposal (the same acceptance step as for any contributor proposal), the C+ comments on the issue asking Melvin to implement, for example:
 
 ```
 @MelvinBot please implement your proposal
@@ -50,9 +59,7 @@ Adjust the wording if needed, but the comment must mention `@MelvinBot` and clea
 
 ### If Melvin's proposal is not accepted
 
-The C+ explains **why** the proposal was not accepted (wrong root cause, incomplete solution, better alternative exists, etc.). If a contributor's proposal is accepted instead, follow the standard contributor hiring and implementation flow in [CONTRIBUTING.md](./CONTRIBUTING.md).
-
-When a C+ accepts a proposal, they may also post `🎀👀🎀` on the issue to trigger CME assignment for the job.
+The C+ or CME explains **why** the proposal was not accepted (wrong root cause, incomplete solution, better alternative exists, etc.). If a contributor's proposal is accepted instead, follow the standard contributor hiring and implementation flow in [CONTRIBUTING.md](./CONTRIBUTING.md).
 
 ## Phase 2: C+ owns the pull request
 
@@ -126,6 +133,7 @@ We intentionally do **not** add a second round of contributor or C+ PR review on
 | Do not | Why |
 |--------|-----|
 | Open a PR before a proposal is accepted | Wastes contributor and reviewer time if the approach is wrong |
+| Ask `@MelvinBot` to implement before the CME approves the proposal | Implementation must wait for CME approval, not just C+ recommendation |
 | Skip C+ proposal review because Melvin wrote it | Melvin proposals need the same validation as human proposals |
 | Send Melvin's draft PR for CME review without testing and checklist completion | The C+ is the human author and owns quality |
 | Assume you can edit Melvin's PR description in the GitHub UI | Post the body in a PR comment and ask `@MelvinBot` to apply it |

From 1b385dffb05db1fdbe30d3c4a5a13d0837d03e35 Mon Sep 17 00:00:00 2001
From: ShridharGoel <35566748+ShridharGoel@users.noreply.github.com>
Date: Tue, 9 Jun 2026 19:48:32 +0530
Subject: [PATCH 226/435] Fix elevated role assignment permission check

---
 src/pages/workspace/WorkspaceMembersPage.tsx | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/src/pages/workspace/WorkspaceMembersPage.tsx b/src/pages/workspace/WorkspaceMembersPage.tsx
index 18f2e9a2561e..2b6bdb0228d7 100644
--- a/src/pages/workspace/WorkspaceMembersPage.tsx
+++ b/src/pages/workspace/WorkspaceMembersPage.tsx
@@ -68,6 +68,7 @@ import {isPersonalDetailsReady, sortAlphabetically} from '@libs/OptionsListUtils
 import {getDisplayNameOrDefault, getPersonalDetailsByID} from '@libs/PersonalDetailsUtils';
 import {
     canEditWorkspaceSettings,
+    canMemberWrite,
     getConnectionExporters,
     getMemberAccountIDsForWorkspace,
     isControlPolicy,
@@ -415,7 +416,7 @@ function WorkspaceMembersPage({personalDetails, route, policy}: WorkspaceMembers
 
     const policyOwner = policy?.owner;
     const currentUserLogin = currentUserPersonalDetails.login;
-    const canAssignElevatedRoles = isStrictPolicyAdmin(policy, currentUserLogin);
+    const canAssignElevatedRoles = canMemberWrite(policy, currentUserLogin, CONST.POLICY.POLICY_FEATURE.ASSIGN_ELEVATED_ROLES);
     const invitedPrimaryToSecondaryLogins = useMemo(() => invertObject(policy?.primaryLoginsInvited ?? {}), [policy?.primaryLoginsInvited]);
     const isControlPolicyWithWideLayout = !shouldUseNarrowLayout && isControlPolicy(policy);
 

From 1fcdd08d52cacdd30777eb8f36c25dfa56d9471d Mon Sep 17 00:00:00 2001
From: neil-marcellini <neil@expensify.com>
Date: Tue, 9 Jun 2026 10:20:08 -0400
Subject: [PATCH 227/435] Manual clean up to how to work with melvinbot guide

---
 contributingGuides/CONTRIBUTING.md            | 38 +++++++++---------
 .../HOW_TO_WORK_WITH_MELVINBOT.md             | 40 +++----------------
 cspell.json                                   |  1 -
 3 files changed, 24 insertions(+), 55 deletions(-)

diff --git a/contributingGuides/CONTRIBUTING.md b/contributingGuides/CONTRIBUTING.md
index d874ccad4c96..3fdbd76b7be0 100644
--- a/contributingGuides/CONTRIBUTING.md
+++ b/contributingGuides/CONTRIBUTING.md
@@ -10,7 +10,7 @@ Many App jobs use [MelvinBot](https://github.com/Expensify/App/blob/main/contrib
 ### Test Accounts
 You can create as many accounts as needed in order to test your changes directly from [the app](https://new.expensify.com/). An initial account can be created when logging in for the first time, and additional accounts can be created by opening the "New Chat" or "Group Chat" pages via the Global Create menu, inputting a valid email or phone number, and tapping the user's avatar. Do not use Expensify employee or customer accounts for testing.
 
-**Notes**: 
+**Notes**:
 
 1. When creating test accounts:
   - Include a `+` (plus sign) in the email address (e.g., matt+1@gmail.com). This marks the account and their associated workspaces as test accounts in Expensify, ensuring Expensify Guides are not assigned to help with account setup.
@@ -24,7 +24,7 @@ You can generate multiple test accounts by using a `+` postfix, for example if y
 
 #### High Traffic Accounts
 
-All internal engineers, contributors, and C+ members are required to test with a “high traffic” account against the staging or production web servers. Use these Google forms to manage your high-traffic accounts. You'll need to authenticate via Google first. 
+All internal engineers, contributors, and C+ members are required to test with a “high traffic” account against the staging or production web servers. Use these Google forms to manage your high-traffic accounts. You'll need to authenticate via Google first.
 1. [Make an account high-traffic](https://docs.google.com/forms/d/e/1FAIpQLScpiS0Mo-HA5xHPsvDow79yTsMBgF0wjuqc0K37lTK5fheB8Q/viewform)
 2. [Remove a high-traffic account](https://docs.google.com/forms/d/e/1FAIpQLSd9_FDav83pnhhtu1KGAKIpf2yttQ_0Bvq1b9nuFM1-wbL11Q/viewform)
 
@@ -43,7 +43,7 @@ We have a shared Slack channel called #expensify-open-source — this channel is
 
 That said, we have a small issue with adding users at the moment and we’re working with Slack to try and get this resolved. If you would like to join, [fill out this form](https://forms.gle/Q7hnhUJPnQCK7Fe56) with your email and Upwork profile link. Once resolved, we’ll add you.
 
-Note: Do not send direct messages to the Expensify team in Slack or Expensify Chat, they will not be able to respond. 
+Note: Do not send direct messages to the Expensify team in Slack or Expensify Chat, they will not be able to respond.
 
 Note: if you are hired for an Upwork job and have any job-specific questions, please ask in the GitHub issue or pull request. This will ensure that the person addressing your question has as much context as possible.
 
@@ -51,9 +51,9 @@ Note: if you are hired for an Upwork job and have any job-specific questions, pl
 If you've found a vulnerability, please email security@expensify.com with the subject `Vulnerability Report` instead of creating an issue.
 
 ## Payment for Contributions
-We hire and pay external contributors via [Upwork.com](https://www.upwork.com). If you'd like to be paid for contributing, please create an Upwork account, apply for an available job in [GitHub](https://github.com/Expensify/App/issues?q=is%3Aopen+is%3Aissue+label%3A%22Help+Wanted%22), and finally apply for the job in Upwork once your proposal gets selected in GitHub. Please make sure your Upwork profile is **fully verified** before applying, otherwise you run the risk of not being paid. If you think your compensation should be increased for a specific job, you can request a reevaluation by commenting in the Github issue where the Upwork job was posted. 
+We hire and pay external contributors via [Upwork.com](https://www.upwork.com). If you'd like to be paid for contributing, please create an Upwork account, apply for an available job in [GitHub](https://github.com/Expensify/App/issues?q=is%3Aopen+is%3Aissue+label%3A%22Help+Wanted%22), and finally apply for the job in Upwork once your proposal gets selected in GitHub. Please make sure your Upwork profile is **fully verified** before applying, otherwise you run the risk of not being paid. If you think your compensation should be increased for a specific job, you can request a reevaluation by commenting in the Github issue where the Upwork job was posted.
 
-Please add your Upwork profile link in your GitHub Bio to help ensure prompt payment.  If you're using Slack or Expensify for discussions, please add your Upwork profile link **and** your GitHub username in your Slack Title and Expensify Status. 
+Please add your Upwork profile link in your GitHub Bio to help ensure prompt payment.  If you're using Slack or Expensify for discussions, please add your Upwork profile link **and** your GitHub username in your Slack Title and Expensify Status.
 
 Payment for your contributions will be made no less than 7 days after the pull request is deployed to production to allow for [regression](https://github.com/Expensify/App/blob/main/contributingGuides/CONTRIBUTING.md#regressions) testing. If you have not received payment after 8 days of the PR being deployed to production, and there are no [regressions](https://github.com/Expensify/App/blob/main/contributingGuides/CONTRIBUTING.md#regressions), please add a comment to the issue mentioning the team member assigned to pay (Look for the melvin-bot "Triggered auto assignment to... (`Awaiting Payment`)" to see who this is).
 
@@ -61,13 +61,13 @@ New contributors are limited to working on one job at a time, **do not submit pr
 
 Please be aware that compensation for any support in solving an issue is provided **entirely at Expensify’s discretion**. Personal time or resources applied towards investigating a proposal **will not guarantee compensation**. Compensation is only guaranteed to those who **[propose a solution and get hired for that job](https://github.com/Expensify/App/blob/main/contributingGuides/CONTRIBUTING.md#propose-a-solution-for-the-job)**. We understand there may be cases where a selected proposal may take inspiration from a previous proposal. Unfortunately, it’s not possible for us to evaluate every individual case and we have no process that can efficiently do so. Issues with higher rewards come with higher risk factors so try to keep things civil and make the best proposal you can. Once again, **any information provided may not necessarily lead to you getting hired for that issue or compensated in any way.**
 
-**Important:** Payment amounts are variable, dependent on if there are any [regressions](https://github.com/Expensify/App/blob/main/contributingGuides/CONTRIBUTING.md#regressions). Your PR will be reviewed by a [Contributor+ (C+)](https://github.com/Expensify/App/blob/main/contributingGuides/HOW_TO_BECOME_A_CONTRIBUTOR_PLUS.md) team member and an internal engineer.  All tests must pass and all code must pass lint checks before a merge. 
+**Important:** Payment amounts are variable, dependent on if there are any [regressions](https://github.com/Expensify/App/blob/main/contributingGuides/CONTRIBUTING.md#regressions). Your PR will be reviewed by a [Contributor+ (C+)](https://github.com/Expensify/App/blob/main/contributingGuides/HOW_TO_BECOME_A_CONTRIBUTOR_PLUS.md) team member and an internal engineer.  All tests must pass and all code must pass lint checks before a merge.
 
 Contributors are eligible to be paid via Expensify 18 months after they were first assigned to a job. More details at [PAYMENT_VIA_EXPENSIFY.md](https://github.com/Expensify/App/blob/main/contributingGuides/PAYMENT_VIA_EXPENSIFY.md)
 
 ### Regressions
 
-If a PR causes a regression at any point within the regression period (starting when the code is merged and ending 168 hours (that's 7 days) after being deployed to production): 
+If a PR causes a regression at any point within the regression period (starting when the code is merged and ending 168 hours (that's 7 days) after being deployed to production):
 - payments will be issued 7 days after all regressions are fixed (ie: deployed to production)
 - a 50% penalty will be applied to the Contributor and [Contributor+](https://github.com/Expensify/App/blob/main/contributingGuides/HOW_TO_BECOME_A_CONTRIBUTOR_PLUS.md) for each regression on an issue
 
@@ -91,7 +91,7 @@ In short, a good problem statement makes no mention whatsoever of the desired so
 
 **Bad:**
 > **Problem:** We don't have a car
-> 
+>
 > **Solution:** Buy a car.
 
 
@@ -157,7 +157,7 @@ This helps future investigators understand the history and current status of err
 ### Propose a solution for the job
 4. Proposals must only be posted after the `Help Wanted` label is added. Any proposals submitted beforehand will be ignored and not reviewed. Do not post proposals in Slack.
     - On issues where [MelvinBot](./HOW_TO_WORK_WITH_MELVINBOT.md) has posted a proposal, Melvin's proposal will be first. Follow the same review standards and **do not open a PR** until a proposal is accepted. C+ members: see [How to Work with MelvinBot](./HOW_TO_WORK_WITH_MELVINBOT.md) for your implementation and PR ownership steps.
-5. Contributors should **not** submit proposals on issues when they have assigned issues or PRs that are awaiting an action from them. If so, they will be in violation of Rule #1 (Get Shit Done) in our [Code of Conduct](https://github.com/Expensify/App/blob/main/CODE_OF_CONDUCT.md) and will receive a warning. Multiple warnings can lead to removal from the program. 
+5. Contributors should **not** submit proposals on issues when they have assigned issues or PRs that are awaiting an action from them. If so, they will be in violation of Rule #1 (Get Shit Done) in our [Code of Conduct](https://github.com/Expensify/App/blob/main/CODE_OF_CONDUCT.md) and will receive a warning. Multiple warnings can lead to removal from the program.
 6. After you reproduce the issue, complete the [proposal template here](./PROPOSAL_TEMPLATE.md) and post it as a comment in the corresponding GitHub issue (linked in the Upwork job).
     - Note: Before submitting a proposal on an issue, be sure to read any other existing proposals. ALL NEW PROPOSALS MUST BE DIFFERENT FROM EXISTING PROPOSALS. The *difference* should be important, meaningful or considerable.
 7. Refrain from leaving additional comments until someone from the Contributor-Plus team and / or someone from Expensify provides feedback on your proposal (do not create a pull request yet).
@@ -201,18 +201,18 @@ This helps future investigators understand the history and current status of err
 
 ### Completing the final checklist
 20. Once your PR has been deployed to production, a checklist will automatically be commented in the GH issue. You're required to complete the steps that have your name mentioned before payment will be issued.
-21. The items requiring your completion consist of: 
+21. The items requiring your completion consist of:
     1. Proposing steps to take for a regression test to ensure the bug doesn't occur again (For information on how to successfully complete this, head [here](https://github.com/Expensify/App/blob/main/contributingGuides/REGRESSION_TEST_BEST_PRACTICES.md)).
     2. Identifying and noting the offending PR that caused the bug (if any).
     3. Commenting on the offending PR to note the bug it caused and why (if applicable).
-    4. Starting a conversation on if any additional steps should be taken to prevent further bugs similar to the one fixed from occurring again. 
-22. Once the above items have been successfully completed, then payments will begin to be issued. 
+    4. Starting a conversation on if any additional steps should be taken to prevent further bugs similar to the one fixed from occurring again.
+22. Once the above items have been successfully completed, then payments will begin to be issued.
 
 ### Timeline expectations and asking for help along the way
 - If you have made a change to your pull request and are ready for another review, leave a comment that says "Updated" on the pull request  itself.
 - Please keep the conversation in GitHub, and do not ping individual reviewers in Slack or Upwork to get their attention.
 - Pull Request reviews can sometimes take a few days. If your pull request has not been addressed after four days, please let us know via the #expensify-open-source Slack channel.
-- On occasion, our engineers will need to focus on a feature release and choose to place a hold on the review of your PR. 
+- On occasion, our engineers will need to focus on a feature release and choose to place a hold on the review of your PR.
 
 ### Important note about JavaScript Style
 - Read our official [JavaScript and React style guide](https://github.com/Expensify/App/blob/main/contributingGuides/STYLE.md). Please refer to our Style Guide before asking for a review.
@@ -223,9 +223,9 @@ This helps future investigators understand the history and current status of err
 ### For external agencies that Expensify partners with
 Follow all the above above steps and processes. When you find a job you'd like to work on:
 - Post “I’m from [agency], I’d like to work on this job”
-  - If no proposals have been submitted by other contributors, BugZero (BZ) team member or an internal engineer will assign the issue to you. 
-  - If there are existing proposals, BZ will put the issue on hold. [Contributor+](https://github.com/Expensify/App/blob/main/contributingGuides/HOW_TO_BECOME_A_CONTRIBUTOR_PLUS.md) will review the existing proposals.  If a contributor’s proposal is accepted then the contributor will be assigned to the issue.  If not the issue will be assigned to the agency-employee. 
-- Once assigned follow the steps [here](https://github.com/Expensify/App/blob/main/contributingGuides/CONTRIBUTING.md#propose-a-solution-for-the-job) to submit your proposal 
+  - If no proposals have been submitted by other contributors, BugZero (BZ) team member or an internal engineer will assign the issue to you.
+  - If there are existing proposals, BZ will put the issue on hold. [Contributor+](https://github.com/Expensify/App/blob/main/contributingGuides/HOW_TO_BECOME_A_CONTRIBUTOR_PLUS.md) will review the existing proposals.  If a contributor’s proposal is accepted then the contributor will be assigned to the issue.  If not the issue will be assigned to the agency-employee.
+- Once assigned follow the steps [here](https://github.com/Expensify/App/blob/main/contributingGuides/CONTRIBUTING.md#propose-a-solution-for-the-job) to submit your proposal
 
 ## Guide on Acronyms used within Expensify Communication
 During communication with Expensify, you will come across a variety of acronyms used by our team. While acronyms can be useful, they cease to be the moment they are not known to the receiver. As such, we wanted to create a list here of our most commonly used acronyms and what they're referring to. Lastly, please never hesitate to ask in Slack or the GH issue if there are any that are not understood/known!
@@ -235,8 +235,8 @@ During communication with Expensify, you will come across a variety of acronyms
 - **LHN:** Left Hand Navigation (Primary navigation modal in Expensify Chat, docked on the left-hand side)
 - **OP:** Original Post (Most commonly the post in E/App GH issues that reports the bug)
 - **FAB** Floating Action Button (the + Button that is used to launch flows like 'New Chat', 'Request Money')
-- **GBR:** Green Brick Road (UX Design Principle that utilizes green indicators on action items to encourage the user down the optimal path for a given process or task) 
-- **RBR:** Red Brick Road (UX Design Principle that utilizes red indicators on action items to encourage the user down the optimal path for handling and discovering errors) 
+- **GBR:** Green Brick Road (UX Design Principle that utilizes green indicators on action items to encourage the user down the optimal path for a given process or task)
+- **RBR:** Red Brick Road (UX Design Principle that utilizes red indicators on action items to encourage the user down the optimal path for handling and discovering errors)
 - **VBA:** Verified Bank Account (Bank account that has been verified as real and belonging to the correct business/individual)
 - **NAB:** Not a Blocker (An issue that doesn't block progress, but would be nice to not have)
 - **IOU:** I owe you (used to describe payment requests between users)
@@ -245,4 +245,4 @@ During communication with Expensify, you will come across a variety of acronyms
 - **QA:** Quality Assurance
 - **GH:** GitHub
 - **LGTM:*** Looks good to me
-- **Melv / MelvinBot:** Expensify's AI agent for App GitHub issues (posts proposals, implements accepted solutions). See [How to Work with MelvinBot](./HOW_TO_WORK_WITH_MELVINBOT.md).
+- **MelvinBot:** Expensify's AI agent for App GitHub issues (posts proposals, implements accepted solutions). See [How to Work with MelvinBot](./HOW_TO_WORK_WITH_MELVINBOT.md).
diff --git a/contributingGuides/HOW_TO_WORK_WITH_MELVINBOT.md b/contributingGuides/HOW_TO_WORK_WITH_MELVINBOT.md
index aca6d124642b..4f1b2defee84 100644
--- a/contributingGuides/HOW_TO_WORK_WITH_MELVINBOT.md
+++ b/contributingGuides/HOW_TO_WORK_WITH_MELVINBOT.md
@@ -32,12 +32,13 @@ Issue opened → Melvin posts proposal → C+ reviews proposal(s)
 
 ## Phase 1: Proposal review
 
-Melvin's proposal will always be the first on the issue. Follow the **same proposal review process** as any other App job:
+Follow the **same proposal review process** as any other App job, but make sure to start with Melvin's proposal first.
 
 1. Use the [proposal template](./PROPOSAL_TEMPLATE.md) criteria: clear root cause, concrete solution, no code diffs.
 2. C+ reviews Melvin's proposal with the same rigor as a contributor proposal. Do not approve proposals that lack a satisfying root-cause explanation.
 3. Contributors may still post proposals if they have a **meaningfully different** approach (see [CONTRIBUTING.md](./CONTRIBUTING.md#propose-a-solution-for-the-job)).
 4. **No one opens a pull request** until a proposal is accepted by the CME (same as any other App job; see [CONTRIBUTING.md](./CONTRIBUTING.md#propose-a-solution-for-the-job)).
+5. If Melvin's proposal is not acceptable, the C+ can review proposals from other contributors, or iterate with Melvin by asking it to update it's proposal or post new ones until it is satisfactory.
 
 ### C+ reviews and recommends
 
@@ -45,8 +46,6 @@ The C+ reviews Melvin's proposal with the same rigor as a contributor proposal.
 
 When the C+ is satisfied with Melvin's proposal, they recommend it to the CME by posting `🎀👀🎀` on the issue. That triggers CME assignment for the job.
 
-**Do not ask Melvin to implement until the CME has approved the proposal.** C+ recommendation is not the same as CME approval.
-
 ### After the CME approves the proposal
 
 Once the assigned CME has approved Melvin's proposal (the same acceptance step as for any contributor proposal), the C+ comments on the issue asking Melvin to implement, for example:
@@ -57,13 +56,9 @@ Once the assigned CME has approved Melvin's proposal (the same acceptance step a
 
 Adjust the wording if needed, but the comment must mention `@MelvinBot` and clearly request implementation.
 
-### If Melvin's proposal is not accepted
-
-The C+ or CME explains **why** the proposal was not accepted (wrong root cause, incomplete solution, better alternative exists, etc.). If a contributor's proposal is accepted instead, follow the standard contributor hiring and implementation flow in [CONTRIBUTING.md](./CONTRIBUTING.md).
-
 ## Phase 2: C+ owns the pull request
 
-Melvin opens a draft PR linked to the issue. MelvinBot remains the GitHub author on GitHub until the C+ takes ownership of the work. Because MelvinBot is the PR author, most C+ members **cannot edit the PR description directly** (GitHub only allows the author or users with write access to edit a pull request body).
+Melvin opens a draft PR linked to the issue. MelvinBot remains the GitHub author but the C+ is the human author. Most C+ members will **not be able to edit the PR description directly** (GitHub only allows the author or users with write access to edit a pull request body).
 
 Before requesting final review, the assigned C+ must:
 
@@ -71,7 +66,6 @@ Before requesting final review, the assigned C+ must:
 2. **Test the change** on all required platforms (see [CONTRIBUTING.md](./CONTRIBUTING.md#make-sure-you-can-test-on-all-platforms)).
 3. **Complete every step** in the PR Author Checklist (see [Updating the PR description and checklist](#updating-the-pr-description-and-checklist) below).
 4. **Self-review the code** against [PR Review Guidelines](./PR_REVIEW_GUIDELINES.md), [PR Authoring & Reviewing Best Practices](./PR_AUTHOR_REVIEWER_BEST_PRACTICES.md), and complete the [Reviewer Checklist](./REVIEWER_CHECKLIST.md) as part of that self-review.
-5. **Submit the PR for review** and become the **official human author** of record for that change.
 
 The C+ is accountable for the PR quality, the same as any contributor who authored a PR.
 
@@ -86,31 +80,7 @@ C+ members who cannot edit the PR body directly should use this workaround:
 @MelvinBot please set the PR body to the content in the details section above
 ```
 
-To update only the checklist, post the checklist section in a `<details>` block and ask Melvin to set just that portion of the PR body.
-
-Example:
-
-```markdown
-<details>
-<summary>PR body for MelvinBot to apply</summary>
-
-### Explanation of Change
-...
-
-### Fixed Issues
-$ https://github.com/Expensify/App/issues/12345
-
-### Tests
-1. ...
-
-### PR Author Checklist
-- [x] I linked the correct issue in the `### Fixed Issues` section above
-...
-
-</details>
-
-@MelvinBot please set the PR body to the content in the details section above
-```
+To update only the checklist, etc, post the section in a `<details>` block and ask Melvin to set just that portion of the PR body.
 
 3. Confirm Melvin updated the PR description before marking the pull request ready for review.
 
@@ -121,7 +91,7 @@ The C+ PR comment is the **source of truth** for what was tested and checked. CM
 After the C+ submits the PR for review:
 
 1. A **CME** (internal engineer) is assigned to review and merge.
-2. The CME follows the normal internal review process. Review the **PR body** when Melvin has applied the C+ content, or review the C+ **PR comment** (with the `<details>` block) directly for testing steps and checklist completion.
+2. The CME follows the normal internal review process. Review the **PR body** when Melvin has applied the C+ content, or failing that, review the C+ **PR comment** (with the `<details>` block) directly for testing steps and checklist completion.
 3. Payment and regression checklists follow the standard rules in [CONTRIBUTING.md](./CONTRIBUTING.md).
 
 ### No additional contributor or C+ PR review
diff --git a/cspell.json b/cspell.json
index ca327c58ed5a..e719fa87354a 100644
--- a/cspell.json
+++ b/cspell.json
@@ -202,7 +202,6 @@
         "Marqeta",
         "McAfee",
         "Michelina",
-        "Melv",
         "Melvin",
         "MelvinBot",
         "Menlo",

From c6f4d224805c32926cafb974a17da85978ad3568 Mon Sep 17 00:00:00 2001
From: Issa Nimaga <inimaga@expensify.com>
Date: Tue, 9 Jun 2026 15:39:35 +0100
Subject: [PATCH 228/435] Update src/pages/inbox/usePusherDraftPacing.ts

Co-authored-by: Shubham Agrawal <58412969+shubham1206agra@users.noreply.github.com>
---
 src/pages/inbox/usePusherDraftPacing.ts | 1 +
 1 file changed, 1 insertion(+)

diff --git a/src/pages/inbox/usePusherDraftPacing.ts b/src/pages/inbox/usePusherDraftPacing.ts
index 4794b07ac8c5..9ec16fa2eec9 100644
--- a/src/pages/inbox/usePusherDraftPacing.ts
+++ b/src/pages/inbox/usePusherDraftPacing.ts
@@ -220,6 +220,7 @@ function tickPacing(runtime: PusherDraftPacingRuntime) {
     if (nextVisibleMarkdown.bodyMarkdown !== visibleBodyMarkdownRef.current || nextVisibleMarkdown.sourceOffset !== visibleSourceOffsetRef.current) {
         const isTargetFullyVisible = nextVisibleMarkdown.sourceOffset >= targetBodyMarkdown.length;
         const status = completedEvent && !hasQueuedTarget && isTargetFullyVisible ? 'completed' : 'updated';
+        // Only consume time for the units we actually revealed; keep the rest for the next target.
         lastPaceTickTimeRef.current = getNextLastPaceTickTime(
             now,
             paceStartTime,

From 42dad761edfe5d510faf54041e4149060eaa4b52 Mon Sep 17 00:00:00 2001
From: Issa Nimaga <inimaga@expensify.com>
Date: Tue, 9 Jun 2026 15:44:33 +0100
Subject: [PATCH 229/435] address review issues

---
 src/pages/inbox/usePusherDraftPacing.ts | 18 ++++++++++--------
 1 file changed, 10 insertions(+), 8 deletions(-)

diff --git a/src/pages/inbox/usePusherDraftPacing.ts b/src/pages/inbox/usePusherDraftPacing.ts
index 9ec16fa2eec9..ad33908357db 100644
--- a/src/pages/inbox/usePusherDraftPacing.ts
+++ b/src/pages/inbox/usePusherDraftPacing.ts
@@ -220,14 +220,10 @@ function tickPacing(runtime: PusherDraftPacingRuntime) {
     if (nextVisibleMarkdown.bodyMarkdown !== visibleBodyMarkdownRef.current || nextVisibleMarkdown.sourceOffset !== visibleSourceOffsetRef.current) {
         const isTargetFullyVisible = nextVisibleMarkdown.sourceOffset >= targetBodyMarkdown.length;
         const status = completedEvent && !hasQueuedTarget && isTargetFullyVisible ? 'completed' : 'updated';
+        const shouldPreserveElapsedDebt = (isTargetFullyVisible && hasQueuedTarget) || (!isTargetFullyVisible && revealedUnits >= elapsedIntervals);
+
         // Only consume time for the units we actually revealed; keep the rest for the next target.
-        lastPaceTickTimeRef.current = getNextLastPaceTickTime(
-            now,
-            paceStartTime,
-            elapsedIntervals,
-            revealedUnits,
-            (isTargetFullyVisible && hasQueuedTarget) || (!isTargetFullyVisible && revealedUnits >= elapsedIntervals),
-        );
+        lastPaceTickTimeRef.current = getNextLastPaceTickTime(now, paceStartTime, elapsedIntervals, revealedUnits, shouldPreserveElapsedDebt);
         publishVisibleEvent(runtime, status === 'completed' && completedEvent ? completedEvent : latestEvent, nextVisibleMarkdown, status);
 
         if (status === 'completed') {
@@ -642,12 +638,18 @@ function usePusherDraftPacing(reportID: string) {
 
         resumeCachedPusherDraftPace(runtime);
         const unsubscribeVisibility = Visibility.onVisibilityChange(() => {
+            if (!Visibility.isVisible()) {
+                return;
+            }
+
             if (completedPusherDraftEventRef.current) {
+                // Completion may arrive while the tab is hidden. Reveal the full target on visibility return
+                // so final HTML is not delayed by throttled timers.
                 revealFullPusherDraftTarget(runtime);
                 return;
             }
 
-            if (!Visibility.isVisible() || !pusherPaceIntervalRef.current) {
+            if (!pusherPaceIntervalRef.current) {
                 return;
             }
 

From e4d472c4dd30015ffe250d27ec1195093f32eafc Mon Sep 17 00:00:00 2001
From: Nicolas Bonet <nicolas@expensify.com>
Date: Mon, 8 Jun 2026 15:24:20 -0500
Subject: [PATCH 230/435] Add disclaimer text to multiple language files and AI
 rule pages

This commit introduces a disclaimer message indicating that Concierge may make mistakes across various language translations (German, English, Spanish, French, Italian, Japanese, Dutch, Polish, Portuguese, and Chinese). Additionally, the disclaimer is displayed on the Add and Edit AI Rule pages to inform users about potential errors in the AI-generated rules.
---
 src/languages/de.ts                                  | 1 +
 src/languages/en.ts                                  | 1 +
 src/languages/es.ts                                  | 1 +
 src/languages/fr.ts                                  | 1 +
 src/languages/it.ts                                  | 1 +
 src/languages/ja.ts                                  | 1 +
 src/languages/nl.ts                                  | 1 +
 src/languages/pl.ts                                  | 1 +
 src/languages/pt-BR.ts                               | 1 +
 src/languages/zh-hans.ts                             | 1 +
 src/pages/workspace/rules/AIRules/AddAIRulePage.tsx  | 1 +
 src/pages/workspace/rules/AIRules/EditAIRulePage.tsx | 1 +
 12 files changed, 12 insertions(+)

diff --git a/src/languages/de.ts b/src/languages/de.ts
index d49ab9960341..ba161577b955 100644
--- a/src/languages/de.ts
+++ b/src/languages/de.ts
@@ -7356,6 +7356,7 @@ Fügen Sie weitere Ausgabelimits hinzu, um den Cashflow Ihres Unternehmens zu sc
                 deleteRuleConfirmation: 'Sind Sie sicher, dass Sie diese Regel löschen möchten?',
                 describeRuleTitle: 'Beschreiben Sie Ihre Regel',
                 describeRuleSubtitle: 'Beschreiben Sie Ihre Regel und Concierge erstellt sie',
+                disclaimer: 'Concierge kann Fehler machen.',
             },
         },
         planTypePage: {
diff --git a/src/languages/en.ts b/src/languages/en.ts
index 8dc27e1bea60..d2dc396259f3 100644
--- a/src/languages/en.ts
+++ b/src/languages/en.ts
@@ -7454,6 +7454,7 @@ const translations = {
                 deleteRuleConfirmation: 'Are you sure you want to delete this rule?',
                 describeRuleTitle: 'Describe your rule',
                 describeRuleSubtitle: 'Describe your rule and Concierge will build it',
+                disclaimer: 'Concierge can make mistakes.',
             },
         },
         planTypePage: {
diff --git a/src/languages/es.ts b/src/languages/es.ts
index 4ed11c0837eb..525a0fe3be59 100644
--- a/src/languages/es.ts
+++ b/src/languages/es.ts
@@ -7251,6 +7251,7 @@ ${amount} para ${merchant} - ${date}`,
                 editRuleTitle: 'Editar regla',
                 deleteRule: 'Eliminar regla',
                 deleteRuleConfirmation: '¿Seguro que quieres eliminar esta regla?',
+                disclaimer: 'Concierge puede cometer errores.',
             },
         },
         emptyDomain: {
diff --git a/src/languages/fr.ts b/src/languages/fr.ts
index 81ed59d53e2f..314c37492400 100644
--- a/src/languages/fr.ts
+++ b/src/languages/fr.ts
@@ -7384,6 +7384,7 @@ Ajoutez davantage de règles de dépenses pour protéger la trésorerie de l’e
                 deleteRuleConfirmation: 'Voulez-vous vraiment supprimer cette règle ?',
                 describeRuleTitle: 'Décrivez votre règle',
                 describeRuleSubtitle: 'Décrivez votre règle et Concierge la créera',
+                disclaimer: 'Concierge peut faire des erreurs.',
             },
         },
         planTypePage: {
diff --git a/src/languages/it.ts b/src/languages/it.ts
index f73777568947..567c84105e25 100644
--- a/src/languages/it.ts
+++ b/src/languages/it.ts
@@ -7341,6 +7341,7 @@ Aggiungi altre regole di spesa per proteggere il flusso di cassa aziendale.`,
                 deleteRuleConfirmation: 'Sei sicuro di voler eliminare questa regola?',
                 describeRuleTitle: 'Descrivi la tua regola',
                 describeRuleSubtitle: 'Descrivi la tua regola e Concierge la creerà',
+                disclaimer: 'Concierge può commettere errori.',
             },
         },
         planTypePage: {
diff --git a/src/languages/ja.ts b/src/languages/ja.ts
index 0de98845eab1..d65db1d54e0f 100644
--- a/src/languages/ja.ts
+++ b/src/languages/ja.ts
@@ -7259,6 +7259,7 @@ ${reportName}
                 deleteRuleConfirmation: 'このルールを削除してもよろしいですか？',
                 describeRuleTitle: 'ルールの内容を記入してください',
                 describeRuleSubtitle: 'ルールの内容を入力すると、Concierge が自動作成します',
+                disclaimer: 'Concierge は間違える場合があります。',
             },
         },
         planTypePage: {
diff --git a/src/languages/nl.ts b/src/languages/nl.ts
index 0aba8236fe62..8d33ad1793e6 100644
--- a/src/languages/nl.ts
+++ b/src/languages/nl.ts
@@ -7315,6 +7315,7 @@ er bestedingsregels toe om de kasstroom van het bedrijf te beschermen.`,
                 deleteRuleConfirmation: 'Weet je zeker dat je deze regel wilt verwijderen?',
                 describeRuleTitle: 'Beschrijf je regel',
                 describeRuleSubtitle: 'Beschrijf je regel en Concierge maakt hem voor je',
+                disclaimer: 'Concierge kan fouten maken.',
             },
         },
         planTypePage: {
diff --git a/src/languages/pl.ts b/src/languages/pl.ts
index 51fbc5014fc3..eb10e4268e79 100644
--- a/src/languages/pl.ts
+++ b/src/languages/pl.ts
@@ -7308,6 +7308,7 @@ Dodaj więcej zasad wydatków, żeby chronić płynność finansową firmy.`,
                 deleteRuleConfirmation: 'Na pewno chcesz usunąć tę regułę?',
                 describeRuleTitle: 'Opisz swoją regułę',
                 describeRuleSubtitle: 'Opisz swoją regułę, a Concierge ją utworzy',
+                disclaimer: 'Concierge może popełniać błędy.',
             },
         },
         planTypePage: {
diff --git a/src/languages/pt-BR.ts b/src/languages/pt-BR.ts
index f8942f7398f1..0c4309c52ebe 100644
--- a/src/languages/pt-BR.ts
+++ b/src/languages/pt-BR.ts
@@ -7314,6 +7314,7 @@ Adicione mais regras de gasto para proteger o fluxo de caixa da empresa.`,
                 deleteRuleConfirmation: 'Tem certeza de que quer excluir esta regra?',
                 describeRuleTitle: 'Descreva sua regra',
                 describeRuleSubtitle: 'Descreva sua regra e a Concierge vai criá-la',
+                disclaimer: 'A Concierge pode cometer erros.',
             },
         },
         planTypePage: {
diff --git a/src/languages/zh-hans.ts b/src/languages/zh-hans.ts
index 2a75e959f486..5ba6b7a8d91e 100644
--- a/src/languages/zh-hans.ts
+++ b/src/languages/zh-hans.ts
@@ -7125,6 +7125,7 @@ ${reportName}
                 deleteRuleConfirmation: '确定要删除此规则吗？',
                 describeRuleTitle: '描述你的规则',
                 describeRuleSubtitle: '描述你的规则，我们会由 Concierge 为你创建',
+                disclaimer: 'Concierge 可能会犯错。',
             },
         },
         planTypePage: {
diff --git a/src/pages/workspace/rules/AIRules/AddAIRulePage.tsx b/src/pages/workspace/rules/AIRules/AddAIRulePage.tsx
index a5735f1ab4c6..68ba35e430ff 100644
--- a/src/pages/workspace/rules/AIRules/AddAIRulePage.tsx
+++ b/src/pages/workspace/rules/AIRules/AddAIRulePage.tsx
@@ -104,6 +104,7 @@ function AddAIRulePage({
                             textInputContainerStyles={[styles.flex1]}
                             inputStyle={[styles.flex1, styles.textAlignVerticalTop]}
                         />
+                        <Text style={[styles.textMicroSupporting, styles.textAlignCenter, styles.mt2]}>{translate('workspace.rules.aiRules.disclaimer')}</Text>
                     </View>
                 </FormProvider>
             </ScreenWrapper>
diff --git a/src/pages/workspace/rules/AIRules/EditAIRulePage.tsx b/src/pages/workspace/rules/AIRules/EditAIRulePage.tsx
index e06bf59e0c9b..de2096580043 100644
--- a/src/pages/workspace/rules/AIRules/EditAIRulePage.tsx
+++ b/src/pages/workspace/rules/AIRules/EditAIRulePage.tsx
@@ -151,6 +151,7 @@ function EditAIRulePage({
                             textInputContainerStyles={[styles.flex1]}
                             inputStyle={[styles.flex1, styles.textAlignVerticalTop]}
                         />
+                        <Text style={[styles.textMicroSupporting, styles.textAlignCenter, styles.mt2]}>{translate('workspace.rules.aiRules.disclaimer')}</Text>
                     </View>
                 </FormProvider>
             </ScreenWrapper>

From 5d9aaa688d7bea8a01eb8cd49b490d7b01a499c5 Mon Sep 17 00:00:00 2001
From: Nicolas Bonet <nicolas@expensify.com>
Date: Mon, 8 Jun 2026 15:31:48 -0500
Subject: [PATCH 231/435] Update disclaimer text in multiple language files to
 reflect AI terminology

This commit modifies the disclaimer message across various language translations (German, English, Spanish, French, Italian, Japanese, Dutch, Polish, Portuguese, and Chinese) to specify that "AI agents" can make mistakes instead of "Concierge." This change enhances clarity regarding the source of potential errors in AI-generated content.
---
 src/languages/de.ts      | 2 +-
 src/languages/en.ts      | 2 +-
 src/languages/es.ts      | 2 +-
 src/languages/fr.ts      | 2 +-
 src/languages/it.ts      | 2 +-
 src/languages/ja.ts      | 2 +-
 src/languages/nl.ts      | 2 +-
 src/languages/pl.ts      | 2 +-
 src/languages/pt-BR.ts   | 2 +-
 src/languages/zh-hans.ts | 2 +-
 10 files changed, 10 insertions(+), 10 deletions(-)

diff --git a/src/languages/de.ts b/src/languages/de.ts
index ba161577b955..f445b49569ca 100644
--- a/src/languages/de.ts
+++ b/src/languages/de.ts
@@ -7356,7 +7356,7 @@ Fügen Sie weitere Ausgabelimits hinzu, um den Cashflow Ihres Unternehmens zu sc
                 deleteRuleConfirmation: 'Sind Sie sicher, dass Sie diese Regel löschen möchten?',
                 describeRuleTitle: 'Beschreiben Sie Ihre Regel',
                 describeRuleSubtitle: 'Beschreiben Sie Ihre Regel und Concierge erstellt sie',
-                disclaimer: 'Concierge kann Fehler machen.',
+                disclaimer: 'KI-Agenten können Fehler machen.',
             },
         },
         planTypePage: {
diff --git a/src/languages/en.ts b/src/languages/en.ts
index d2dc396259f3..518fa42e6a85 100644
--- a/src/languages/en.ts
+++ b/src/languages/en.ts
@@ -7454,7 +7454,7 @@ const translations = {
                 deleteRuleConfirmation: 'Are you sure you want to delete this rule?',
                 describeRuleTitle: 'Describe your rule',
                 describeRuleSubtitle: 'Describe your rule and Concierge will build it',
-                disclaimer: 'Concierge can make mistakes.',
+                disclaimer: 'AI agents can make mistakes.',
             },
         },
         planTypePage: {
diff --git a/src/languages/es.ts b/src/languages/es.ts
index 525a0fe3be59..a3692c4be973 100644
--- a/src/languages/es.ts
+++ b/src/languages/es.ts
@@ -7251,7 +7251,7 @@ ${amount} para ${merchant} - ${date}`,
                 editRuleTitle: 'Editar regla',
                 deleteRule: 'Eliminar regla',
                 deleteRuleConfirmation: '¿Seguro que quieres eliminar esta regla?',
-                disclaimer: 'Concierge puede cometer errores.',
+                disclaimer: 'Los agentes de IA pueden cometer errores.',
             },
         },
         emptyDomain: {
diff --git a/src/languages/fr.ts b/src/languages/fr.ts
index 314c37492400..f2b120ce3b1a 100644
--- a/src/languages/fr.ts
+++ b/src/languages/fr.ts
@@ -7384,7 +7384,7 @@ Ajoutez davantage de règles de dépenses pour protéger la trésorerie de l’e
                 deleteRuleConfirmation: 'Voulez-vous vraiment supprimer cette règle ?',
                 describeRuleTitle: 'Décrivez votre règle',
                 describeRuleSubtitle: 'Décrivez votre règle et Concierge la créera',
-                disclaimer: 'Concierge peut faire des erreurs.',
+                disclaimer: 'Les agents IA peuvent faire des erreurs.',
             },
         },
         planTypePage: {
diff --git a/src/languages/it.ts b/src/languages/it.ts
index 567c84105e25..f4591d5d7391 100644
--- a/src/languages/it.ts
+++ b/src/languages/it.ts
@@ -7341,7 +7341,7 @@ Aggiungi altre regole di spesa per proteggere il flusso di cassa aziendale.`,
                 deleteRuleConfirmation: 'Sei sicuro di voler eliminare questa regola?',
                 describeRuleTitle: 'Descrivi la tua regola',
                 describeRuleSubtitle: 'Descrivi la tua regola e Concierge la creerà',
-                disclaimer: 'Concierge può commettere errori.',
+                disclaimer: 'Gli agenti IA possono commettere errori.',
             },
         },
         planTypePage: {
diff --git a/src/languages/ja.ts b/src/languages/ja.ts
index d65db1d54e0f..269229055c84 100644
--- a/src/languages/ja.ts
+++ b/src/languages/ja.ts
@@ -7259,7 +7259,7 @@ ${reportName}
                 deleteRuleConfirmation: 'このルールを削除してもよろしいですか？',
                 describeRuleTitle: 'ルールの内容を記入してください',
                 describeRuleSubtitle: 'ルールの内容を入力すると、Concierge が自動作成します',
-                disclaimer: 'Concierge は間違える場合があります。',
+                disclaimer: 'AI エージェントは間違える場合があります。',
             },
         },
         planTypePage: {
diff --git a/src/languages/nl.ts b/src/languages/nl.ts
index 8d33ad1793e6..5338e5a4eecf 100644
--- a/src/languages/nl.ts
+++ b/src/languages/nl.ts
@@ -7315,7 +7315,7 @@ er bestedingsregels toe om de kasstroom van het bedrijf te beschermen.`,
                 deleteRuleConfirmation: 'Weet je zeker dat je deze regel wilt verwijderen?',
                 describeRuleTitle: 'Beschrijf je regel',
                 describeRuleSubtitle: 'Beschrijf je regel en Concierge maakt hem voor je',
-                disclaimer: 'Concierge kan fouten maken.',
+                disclaimer: 'AI-agents kunnen fouten maken.',
             },
         },
         planTypePage: {
diff --git a/src/languages/pl.ts b/src/languages/pl.ts
index eb10e4268e79..33b52e18320f 100644
--- a/src/languages/pl.ts
+++ b/src/languages/pl.ts
@@ -7308,7 +7308,7 @@ Dodaj więcej zasad wydatków, żeby chronić płynność finansową firmy.`,
                 deleteRuleConfirmation: 'Na pewno chcesz usunąć tę regułę?',
                 describeRuleTitle: 'Opisz swoją regułę',
                 describeRuleSubtitle: 'Opisz swoją regułę, a Concierge ją utworzy',
-                disclaimer: 'Concierge może popełniać błędy.',
+                disclaimer: 'Agenci AI mogą popełniać błędy.',
             },
         },
         planTypePage: {
diff --git a/src/languages/pt-BR.ts b/src/languages/pt-BR.ts
index 0c4309c52ebe..44c63ae9eb0a 100644
--- a/src/languages/pt-BR.ts
+++ b/src/languages/pt-BR.ts
@@ -7314,7 +7314,7 @@ Adicione mais regras de gasto para proteger o fluxo de caixa da empresa.`,
                 deleteRuleConfirmation: 'Tem certeza de que quer excluir esta regra?',
                 describeRuleTitle: 'Descreva sua regra',
                 describeRuleSubtitle: 'Descreva sua regra e a Concierge vai criá-la',
-                disclaimer: 'A Concierge pode cometer erros.',
+                disclaimer: 'Os agentes de IA podem cometer erros.',
             },
         },
         planTypePage: {
diff --git a/src/languages/zh-hans.ts b/src/languages/zh-hans.ts
index 5ba6b7a8d91e..2664c14d080c 100644
--- a/src/languages/zh-hans.ts
+++ b/src/languages/zh-hans.ts
@@ -7125,7 +7125,7 @@ ${reportName}
                 deleteRuleConfirmation: '确定要删除此规则吗？',
                 describeRuleTitle: '描述你的规则',
                 describeRuleSubtitle: '描述你的规则，我们会由 Concierge 为你创建',
-                disclaimer: 'Concierge 可能会犯错。',
+                disclaimer: 'AI 智能体可能会犯错。',
             },
         },
         planTypePage: {

From 2e38ba72b991b8887b47bf6e57c4f515d74f333a Mon Sep 17 00:00:00 2001
From: Rayane <77965000+rayane-d@users.noreply.github.com>
Date: Tue, 9 Jun 2026 16:57:26 +0100
Subject: [PATCH 232/435] Add formatTax utility function for tax name and
 percentage formatting

---
 src/libs/ReportActionsUtils.ts | 11 +++++++++--
 1 file changed, 9 insertions(+), 2 deletions(-)

diff --git a/src/libs/ReportActionsUtils.ts b/src/libs/ReportActionsUtils.ts
index db6dfea966d7..763034a55de8 100644
--- a/src/libs/ReportActionsUtils.ts
+++ b/src/libs/ReportActionsUtils.ts
@@ -3436,6 +3436,13 @@ function getAutoPayApprovedReportsEnabledMessage(translate: LocalizedTranslate,
     return translate('workspaceActions.updatedAutoPayApprovedReports', {enabled: !!enabled});
 }
 
+function formatTax(taxName?: string, taxPercentage?: string): string {
+    if (!taxName) {
+        return '';
+    }
+    return taxPercentage ? `${taxName} (${taxPercentage})` : taxName;
+}
+
 function getCategoryTaxRateMessage(translate: LocalizedTranslate, action: ReportAction): string {
     const {categoryName, oldTaxName, oldTaxPercentage, newTaxName, newTaxPercentage} =
         getOriginalMessage(action as ReportAction<typeof CONST.REPORT.ACTIONS.TYPE.POLICY_CHANGE_LOG.UPDATE_CATEGORY_TAX_RATE>) ?? {};
@@ -3444,8 +3451,8 @@ function getCategoryTaxRateMessage(translate: LocalizedTranslate, action: Report
         return getReportActionText(action);
     }
 
-    const oldTax = oldTaxPercentage ? `${oldTaxName} (${oldTaxPercentage})` : (oldTaxName ?? '');
-    const newTax = newTaxPercentage ? `${newTaxName} (${newTaxPercentage})` : newTaxName;
+    const oldTax = formatTax(oldTaxName, oldTaxPercentage);
+    const newTax = formatTax(newTaxName, newTaxPercentage);
 
     return translate('workspaceActions.updatedCategoryTaxRate', {
         categoryName: getDecodedCategoryName(categoryName),

From 3af7ef769502b0a8aa6f19dbf3c57281627f3d21 Mon Sep 17 00:00:00 2001
From: Rayane <77965000+rayane-d@users.noreply.github.com>
Date: Tue, 9 Jun 2026 16:57:40 +0100
Subject: [PATCH 233/435] Enhance getCategoryTaxRateMessage function to include
 oldTaxName validation

---
 src/libs/ReportActionsUtils.ts | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/libs/ReportActionsUtils.ts b/src/libs/ReportActionsUtils.ts
index 763034a55de8..02a17e318aaa 100644
--- a/src/libs/ReportActionsUtils.ts
+++ b/src/libs/ReportActionsUtils.ts
@@ -3447,7 +3447,7 @@ function getCategoryTaxRateMessage(translate: LocalizedTranslate, action: Report
     const {categoryName, oldTaxName, oldTaxPercentage, newTaxName, newTaxPercentage} =
         getOriginalMessage(action as ReportAction<typeof CONST.REPORT.ACTIONS.TYPE.POLICY_CHANGE_LOG.UPDATE_CATEGORY_TAX_RATE>) ?? {};
 
-    if (!categoryName || !newTaxName) {
+    if (!categoryName || !newTaxName || !oldTaxName) {
         return getReportActionText(action);
     }
 

From f08dda043470b4719e7d2cc7b8a9434ed9c96b71 Mon Sep 17 00:00:00 2001
From: Rayane <77965000+rayane-d@users.noreply.github.com>
Date: Tue, 9 Jun 2026 16:58:50 +0100
Subject: [PATCH 234/435] Refactor updatedCategoryTaxRate translations
 functions converting the block-body arrows to concise bodies

---
 src/languages/de.ts      | 5 ++---
 src/languages/en.ts      | 5 ++---
 src/languages/es.ts      | 5 ++---
 src/languages/fr.ts      | 5 ++---
 src/languages/it.ts      | 5 ++---
 src/languages/ja.ts      | 5 ++---
 src/languages/nl.ts      | 5 ++---
 src/languages/pl.ts      | 5 ++---
 src/languages/pt-BR.ts   | 5 ++---
 src/languages/zh-hans.ts | 5 ++---
 10 files changed, 20 insertions(+), 30 deletions(-)

diff --git a/src/languages/de.ts b/src/languages/de.ts
index 5c6184d8705e..1d5ee49f3cd8 100644
--- a/src/languages/de.ts
+++ b/src/languages/de.ts
@@ -7957,9 +7957,8 @@ Fügen Sie weitere Ausgabelimits hinzu, um den Cashflow Ihres Unternehmens zu sc
                 composeFromCards: ({content, cards}: {content: string; cards: string}) => `${content} von ${cards}`,
             },
         },
-        updatedCategoryTaxRate: ({categoryName, oldTax, newTax}: {categoryName: string; oldTax: string; newTax: string}) => {
-            return `hat den Standardsteuersatz der Kategorie „${categoryName}“ auf „${newTax}“ geändert (zuvor „${oldTax}“)`;
-        },
+        updatedCategoryTaxRate: ({categoryName, oldTax, newTax}: {categoryName: string; oldTax: string; newTax: string}) =>
+            `hat den Standardsteuersatz der Kategorie „${categoryName}“ auf „${newTax}“ geändert (zuvor „${oldTax}“)`,
     },
     roomMembersPage: {
         memberNotFound: 'Mitglied nicht gefunden.',
diff --git a/src/languages/en.ts b/src/languages/en.ts
index 1b6fa43fd4bb..cc36634d2c7d 100644
--- a/src/languages/en.ts
+++ b/src/languages/en.ts
@@ -7895,9 +7895,8 @@ const translations = {
         updatedAutoPayApprovedReportsLimit: ({oldLimit, newLimit}: {oldLimit: string; newLimit: string}) =>
             `changed the auto-pay approved reports threshold to "${newLimit}" (previously "${oldLimit}")`,
         removedAutoPayApprovedReportsLimit: 'removed the auto-pay approved reports threshold',
-        updatedCategoryTaxRate: ({categoryName, oldTax, newTax}: {categoryName: string; oldTax: string; newTax: string}) => {
-            return `changed the "${categoryName}" category default tax rate to "${newTax}" (previously "${oldTax}")`;
-        },
+        updatedCategoryTaxRate: ({categoryName, oldTax, newTax}: {categoryName: string; oldTax: string; newTax: string}) =>
+            `changed the "${categoryName}" category default tax rate to "${newTax}" (previously "${oldTax}")`,
         updatedMccGroupCategory: ({mccGroupName, oldCategory, newCategory}: {mccGroupName: string; oldCategory: string; newCategory: string}) =>
             `changed the default spend category for "${mccGroupName}" to "${newCategory}" (previously "${oldCategory}")`,
         changedDefaultApprover: ({newApprover, previousApprover}: {newApprover: string; previousApprover?: string}) =>
diff --git a/src/languages/es.ts b/src/languages/es.ts
index 0e9167703c88..de2687526319 100644
--- a/src/languages/es.ts
+++ b/src/languages/es.ts
@@ -7664,9 +7664,8 @@ ${amount} para ${merchant} - ${date}`,
         updatedAutoPayApprovedReportsLimit: ({oldLimit, newLimit}: {oldLimit: string; newLimit: string}) =>
             `cambió el umbral de autopago de informes aprobados a "${newLimit}" (previamente "${oldLimit}")`,
         removedAutoPayApprovedReportsLimit: 'eliminó el umbral de autopago de informes aprobados',
-        updatedCategoryTaxRate: ({categoryName, oldTax, newTax}: {categoryName: string; oldTax: string; newTax: string}) => {
-            return `cambió la tasa de impuesto predeterminada de la categoría "${categoryName}" a "${newTax}" (previamente "${oldTax}")`;
-        },
+        updatedCategoryTaxRate: ({categoryName, oldTax, newTax}: {categoryName: string; oldTax: string; newTax: string}) =>
+            `cambió la tasa de impuesto predeterminada de la categoría "${categoryName}" a "${newTax}" (previamente "${oldTax}")`,
         updatedMccGroupCategory: ({mccGroupName, oldCategory, newCategory}: {mccGroupName: string; oldCategory: string; newCategory: string}) =>
             `cambió la categoría de gasto predeterminada para "${mccGroupName}" a "${newCategory}" (previamente "${oldCategory}")`,
         changedDefaultApprover: ({newApprover, previousApprover}: {newApprover: string; previousApprover?: string}) =>
diff --git a/src/languages/fr.ts b/src/languages/fr.ts
index d347ad01a4e6..1a2e960e1a6c 100644
--- a/src/languages/fr.ts
+++ b/src/languages/fr.ts
@@ -7992,9 +7992,8 @@ Ajoutez davantage de règles de dépenses pour protéger la trésorerie de l’e
                 composeFromCards: ({content, cards}: {content: string; cards: string}) => `${content} de ${cards}`,
             },
         },
-        updatedCategoryTaxRate: ({categoryName, oldTax, newTax}: {categoryName: string; oldTax: string; newTax: string}) => {
-            return `a modifié le taux de taxe par défaut de la catégorie « ${categoryName} » en « ${newTax} » (auparavant « ${oldTax} »)`;
-        },
+        updatedCategoryTaxRate: ({categoryName, oldTax, newTax}: {categoryName: string; oldTax: string; newTax: string}) =>
+            `a modifié le taux de taxe par défaut de la catégorie « ${categoryName} » en « ${newTax} » (auparavant « ${oldTax} »)`,
     },
     roomMembersPage: {
         memberNotFound: 'Membre introuvable.',
diff --git a/src/languages/it.ts b/src/languages/it.ts
index 3b1009edd28d..3c06e759d4bc 100644
--- a/src/languages/it.ts
+++ b/src/languages/it.ts
@@ -7947,9 +7947,8 @@ Aggiungi altre regole di spesa per proteggere il flusso di cassa aziendale.`,
                 composeFromCards: ({content, cards}: {content: string; cards: string}) => `${content} da ${cards}`,
             },
         },
-        updatedCategoryTaxRate: ({categoryName, oldTax, newTax}: {categoryName: string; oldTax: string; newTax: string}) => {
-            return `ha cambiato l’aliquota fiscale predefinita della categoria "${categoryName}" in "${newTax}" (in precedenza "${oldTax}")`;
-        },
+        updatedCategoryTaxRate: ({categoryName, oldTax, newTax}: {categoryName: string; oldTax: string; newTax: string}) =>
+            `ha cambiato l’aliquota fiscale predefinita della categoria "${categoryName}" in "${newTax}" (in precedenza "${oldTax}")`,
     },
     roomMembersPage: {
         memberNotFound: 'Membro non trovato.',
diff --git a/src/languages/ja.ts b/src/languages/ja.ts
index 2d9e98015ef2..55cdaf2edd9d 100644
--- a/src/languages/ja.ts
+++ b/src/languages/ja.ts
@@ -7848,9 +7848,8 @@ ${reportName}
                 composeFromCards: ({content, cards}: {content: string; cards: string}) => `${cards} からの ${content}`,
             },
         },
-        updatedCategoryTaxRate: ({categoryName, oldTax, newTax}: {categoryName: string; oldTax: string; newTax: string}) => {
-            return `「${categoryName}」カテゴリのデフォルト税率を「${newTax}」に変更しました（以前は「${oldTax}」）`;
-        },
+        updatedCategoryTaxRate: ({categoryName, oldTax, newTax}: {categoryName: string; oldTax: string; newTax: string}) =>
+            `「${categoryName}」カテゴリのデフォルト税率を「${newTax}」に変更しました（以前は「${oldTax}」）`,
     },
     roomMembersPage: {
         memberNotFound: 'メンバーが見つかりません。',
diff --git a/src/languages/nl.ts b/src/languages/nl.ts
index 79d640444b52..af4f8d956f96 100644
--- a/src/languages/nl.ts
+++ b/src/languages/nl.ts
@@ -7915,9 +7915,8 @@ er bestedingsregels toe om de kasstroom van het bedrijf te beschermen.`,
                 composeFromCards: ({content, cards}: {content: string; cards: string}) => `${content} van ${cards}`,
             },
         },
-        updatedCategoryTaxRate: ({categoryName, oldTax, newTax}: {categoryName: string; oldTax: string; newTax: string}) => {
-            return `heeft het standaardbelastingtarief van de categorie "${categoryName}" gewijzigd naar "${newTax}" (voorheen "${oldTax}")`;
-        },
+        updatedCategoryTaxRate: ({categoryName, oldTax, newTax}: {categoryName: string; oldTax: string; newTax: string}) =>
+            `heeft het standaardbelastingtarief van de categorie "${categoryName}" gewijzigd naar "${newTax}" (voorheen "${oldTax}")`,
     },
     roomMembersPage: {
         memberNotFound: 'Lid niet gevonden.',
diff --git a/src/languages/pl.ts b/src/languages/pl.ts
index b95effc097b3..f4af2018f853 100644
--- a/src/languages/pl.ts
+++ b/src/languages/pl.ts
@@ -7907,9 +7907,8 @@ Dodaj więcej zasad wydatków, żeby chronić płynność finansową firmy.`,
                 composeFromCards: ({content, cards}: {content: string; cards: string}) => `${content} z ${cards}`,
             },
         },
-        updatedCategoryTaxRate: ({categoryName, oldTax, newTax}: {categoryName: string; oldTax: string; newTax: string}) => {
-            return `zmienił(a) domyślną stawkę podatku dla kategorii „${categoryName}” na „${newTax}” (wcześniej „${oldTax}”)`;
-        },
+        updatedCategoryTaxRate: ({categoryName, oldTax, newTax}: {categoryName: string; oldTax: string; newTax: string}) =>
+            `zmienił(a) domyślną stawkę podatku dla kategorii „${categoryName}” na „${newTax}” (wcześniej „${oldTax}”)`,
     },
     roomMembersPage: {
         memberNotFound: 'Nie znaleziono członka.',
diff --git a/src/languages/pt-BR.ts b/src/languages/pt-BR.ts
index 998f3148b1b1..b8764baeff02 100644
--- a/src/languages/pt-BR.ts
+++ b/src/languages/pt-BR.ts
@@ -7909,9 +7909,8 @@ Adicione mais regras de gasto para proteger o fluxo de caixa da empresa.`,
                 composeFromCards: ({content, cards}: {content: string; cards: string}) => `${content} de ${cards}`,
             },
         },
-        updatedCategoryTaxRate: ({categoryName, oldTax, newTax}: {categoryName: string; oldTax: string; newTax: string}) => {
-            return `alterou a alíquota de imposto padrão da categoria "${categoryName}" para "${newTax}" (antes "${oldTax}")`;
-        },
+        updatedCategoryTaxRate: ({categoryName, oldTax, newTax}: {categoryName: string; oldTax: string; newTax: string}) =>
+            `alterou a alíquota de imposto padrão da categoria "${categoryName}" para "${newTax}" (antes "${oldTax}")`,
     },
     roomMembersPage: {
         memberNotFound: 'Membro não encontrado.',
diff --git a/src/languages/zh-hans.ts b/src/languages/zh-hans.ts
index 817c3ec9b22c..ebe0a2a98e21 100644
--- a/src/languages/zh-hans.ts
+++ b/src/languages/zh-hans.ts
@@ -7697,9 +7697,8 @@ ${reportName}
                 composeFromCards: ({content, cards}: {content: string; cards: string}) => `来自 ${cards} 的 ${content}`,
             },
         },
-        updatedCategoryTaxRate: ({categoryName, oldTax, newTax}: {categoryName: string; oldTax: string; newTax: string}) => {
-            return `将“${categoryName}”类别的默认税率更改为“${newTax}”（之前为“${oldTax}”）`;
-        },
+        updatedCategoryTaxRate: ({categoryName, oldTax, newTax}: {categoryName: string; oldTax: string; newTax: string}) =>
+            `将“${categoryName}”类别的默认税率更改为“${newTax}”（之前为“${oldTax}”）`,
     },
     roomMembersPage: {
         memberNotFound: '未找到成员。',

From 9b6042f75d31e0d408743cdbc57dc1c51c43034c Mon Sep 17 00:00:00 2001
From: ShridharGoel <35566748+ShridharGoel@users.noreply.github.com>
Date: Tue, 9 Jun 2026 23:48:22 +0530
Subject: [PATCH 235/435] Rename auditor upgrade item for control roles

---
 src/CONST/index.ts                                  | 12 ++++++------
 src/languages/de.ts                                 |  2 +-
 src/languages/en.ts                                 |  8 ++++----
 src/languages/es.ts                                 |  2 +-
 src/languages/fr.ts                                 |  2 +-
 src/languages/it.ts                                 |  2 +-
 src/languages/ja.ts                                 |  2 +-
 src/languages/nl.ts                                 |  2 +-
 src/languages/pl.ts                                 |  2 +-
 src/languages/pt-BR.ts                              |  2 +-
 src/languages/zh-hans.ts                            |  2 +-
 src/pages/workspace/members/ImportedMembersPage.tsx |  5 +++--
 12 files changed, 22 insertions(+), 21 deletions(-)

diff --git a/src/CONST/index.ts b/src/CONST/index.ts
index c5b4559373d2..250331f873aa 100644
--- a/src/CONST/index.ts
+++ b/src/CONST/index.ts
@@ -8091,12 +8091,12 @@ const CONST = {
                 description: 'workspace.upgrade.distanceRates.description' as const,
                 icon: 'CarIce',
             },
-            auditor: {
-                id: 'auditor' as const,
-                alias: 'auditor',
-                name: 'Auditor',
-                title: 'workspace.upgrade.auditor.title' as const,
-                description: 'workspace.upgrade.auditor.description' as const,
+            controlPolicyRoles: {
+                id: 'controlPolicyRoles' as const,
+                alias: 'control-policy-roles',
+                name: 'Control policy roles',
+                title: 'workspace.upgrade.controlPolicyRoles.title' as const,
+                description: 'workspace.upgrade.controlPolicyRoles.description' as const,
                 icon: 'BlueShield',
             },
             reports: {
diff --git a/src/languages/de.ts b/src/languages/de.ts
index 371d7f8d2ab1..13c8baab5b92 100644
--- a/src/languages/de.ts
+++ b/src/languages/de.ts
@@ -6927,7 +6927,7 @@ Fordern Sie Spesendetails wie Belege und Beschreibungen an, legen Sie Limits und
                 onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
                     `<muted-text>Entfernungsraten sind im Collect-Tarif verfügbar, beginnend bei <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `pro Mitglied und Monat.` : `pro aktivem Mitglied und Monat.`}</muted-text>`,
             },
-            auditor: {
+            controlPolicyRoles: {
                 title: 'Prüfer',
                 description: 'Prüfer erhalten schreibgeschützten Zugriff auf alle Berichte für vollständige Transparenz und Compliance-Überwachung.',
                 onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
diff --git a/src/languages/en.ts b/src/languages/en.ts
index 81e4d650705e..f4b2f668ef1a 100644
--- a/src/languages/en.ts
+++ b/src/languages/en.ts
@@ -7066,11 +7066,11 @@ const translations = {
                 onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
                     `<muted-text>Distance rates are available on the Collect plan, starting at <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `per member per month.` : `per active member per month.`}</muted-text>`,
             },
-            auditor: {
-                title: 'Auditor',
-                description: 'Auditors get read-only access to all reports for full visibility and compliance monitoring.',
+            controlPolicyRoles: {
+                title: 'Control policy roles',
+                description: 'Use specialized roles like Auditor and Card Admin to give members focused workspace access.',
                 onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
-                    `<muted-text>Auditors are only available on the Control plan, starting at <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `per member per month.` : `per active member per month.`}</muted-text>`,
+                    `<muted-text>Specialized workspace roles are only available on the Control plan, starting at <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `per member per month.` : `per active member per month.`}</muted-text>`,
             },
             [CONST.UPGRADE_FEATURE_INTRO_MAPPING.multiApprovalLevels.id]: {
                 title: 'Multiple approval levels',
diff --git a/src/languages/es.ts b/src/languages/es.ts
index 886bf1d08e06..521b81caa89a 100644
--- a/src/languages/es.ts
+++ b/src/languages/es.ts
@@ -6876,7 +6876,7 @@ ${amount} para ${merchant} - ${date}`,
                 onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}) =>
                     `<muted-text>Las tasas de distancia están disponibles en el plan Recopilar, a partir de <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `por miembro al mes.` : `por miembro activo al mes.`}</muted-text>`,
             },
-            auditor: {
+            controlPolicyRoles: {
                 title: 'Auditor',
                 description: 'Los auditores tienen acceso de lectura a todos los informes para una visibilidad completa y la supervisión del cumplimiento.',
                 onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
diff --git a/src/languages/fr.ts b/src/languages/fr.ts
index 66dce12247f8..33826d949606 100644
--- a/src/languages/fr.ts
+++ b/src/languages/fr.ts
@@ -6954,7 +6954,7 @@ Rendez obligatoires des informations de dépense comme les reçus et les descrip
                 onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
                     `<muted-text>Les taux de distance sont disponibles avec l’abonnement Collect, à partir de <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `par membre et par mois.` : `par membre actif et par mois.`}</muted-text>`,
             },
-            auditor: {
+            controlPolicyRoles: {
                 title: 'Auditeur',
                 description: 'Les auditeurs obtiennent un accès en lecture seule à toutes les notes de frais pour une visibilité complète et le suivi de la conformité.',
                 onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
diff --git a/src/languages/it.ts b/src/languages/it.ts
index 0538b1cdac97..083518714c12 100644
--- a/src/languages/it.ts
+++ b/src/languages/it.ts
@@ -6911,7 +6911,7 @@ Richiedi dettagli sulle spese come ricevute e descrizioni, imposta limiti e valo
                 onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
                     `<muted-text>Le tariffe chilometriche sono disponibili con il piano Collect, a partire da <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `per utente al mese.` : `per membro attivo al mese.`}</muted-text>`,
             },
-            auditor: {
+            controlPolicyRoles: {
                 title: 'Revisore',
                 description: 'I revisori ottengono accesso in sola lettura a tutti i report per garantire completa visibilità e monitoraggio della conformità.',
                 onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
diff --git a/src/languages/ja.ts b/src/languages/ja.ts
index bbb026f3fff9..98a21fac9bec 100644
--- a/src/languages/ja.ts
+++ b/src/languages/ja.ts
@@ -6838,7 +6838,7 @@ ${reportName}
                 onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
                     `<muted-text>距離レートはCollectプランで利用できます。<strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `メンバー1人あたり月額` : `アクティブメンバー1人あたり月額`}からご利用になれます</muted-text>`,
             },
-            auditor: {
+            controlPolicyRoles: {
                 title: '監査人',
                 description: '監査担当者は、可視性とコンプライアンス監視を徹底するため、すべてのレポートを閲覧専用で確認できます。',
                 onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
diff --git a/src/languages/nl.ts b/src/languages/nl.ts
index 387bc787e7e8..0f92aeecbe60 100644
--- a/src/languages/nl.ts
+++ b/src/languages/nl.ts
@@ -6889,7 +6889,7 @@ Vereis onkostendetails zoals bonnen en beschrijvingen, stel limieten en standaar
                 onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
                     `<muted-text>Afstandstarieven zijn beschikbaar in het Collect-abonnement, vanaf <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `per lid per maand.` : `per actieve deelnemer per maand.`}</muted-text>`,
             },
-            auditor: {
+            controlPolicyRoles: {
                 title: 'Auditor',
                 description: 'Auditors krijgen alleen-lezen-toegang tot alle rapporten voor volledige transparantie en nalevingsbewaking.',
                 onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
diff --git a/src/languages/pl.ts b/src/languages/pl.ts
index 4cb7cc2b7384..07793c0fc448 100644
--- a/src/languages/pl.ts
+++ b/src/languages/pl.ts
@@ -6883,7 +6883,7 @@ Wymagaj szczegółów wydatków, takich jak paragony i opisy, ustawiaj limity i
                 onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
                     `<muted-text>Stawki za przejazdy są dostępne w planie Collect, zaczynając od <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `za użytkownika miesięcznie.` : `na aktywnego członka miesięcznie.`}</muted-text>`,
             },
-            auditor: {
+            controlPolicyRoles: {
                 title: 'Audytor',
                 description: 'Biegli rewidentci otrzymują dostęp tylko do odczytu do wszystkich raportów, aby zapewnić pełną widoczność i monitorowanie zgodności.',
                 onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
diff --git a/src/languages/pt-BR.ts b/src/languages/pt-BR.ts
index e2b30fcb9b1e..4fc0bf2fc721 100644
--- a/src/languages/pt-BR.ts
+++ b/src/languages/pt-BR.ts
@@ -6887,7 +6887,7 @@ Exija dados de despesas como recibos e descrições, defina limites e padrões e
                 onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
                     `<muted-text>Tarifas por distância estão disponíveis no plano Collect, a partir de <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `por membro por mês.` : `por membro ativo por mês.`}</muted-text>`,
             },
-            auditor: {
+            controlPolicyRoles: {
                 title: 'Auditor',
                 description: 'Auditores têm acesso somente leitura a todos os relatórios para total visibilidade e monitoramento de conformidade.',
                 onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
diff --git a/src/languages/zh-hans.ts b/src/languages/zh-hans.ts
index 99f71e8f5d13..c9a966c99292 100644
--- a/src/languages/zh-hans.ts
+++ b/src/languages/zh-hans.ts
@@ -6713,7 +6713,7 @@ ${reportName}
                 onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
                     `<muted-text>里程费率适用于 Collect 方案，起始价格为 <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `每位成员每月。` : `每位活跃成员每月。`}</muted-text>`,
             },
-            auditor: {
+            controlPolicyRoles: {
                 title: '审计员',
                 description: '审计员将获得所有报表的只读访问权限，以实现全面可见性和合规监控。',
                 onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
diff --git a/src/pages/workspace/members/ImportedMembersPage.tsx b/src/pages/workspace/members/ImportedMembersPage.tsx
index df1f9cc00ecc..5b648ad6deda 100644
--- a/src/pages/workspace/members/ImportedMembersPage.tsx
+++ b/src/pages/workspace/members/ImportedMembersPage.tsx
@@ -94,15 +94,16 @@ function ImportedMembersPage({route}: ImportedMembersPageProps) {
         const columns = Object.values(spreadsheet?.columns ?? {});
 
         const membersRolesColumn = columns.findIndex((column) => column === CONST.CSV_IMPORT_COLUMNS.ROLE);
+        const controlPolicyOnlyRoles = [CONST.POLICY.ROLE.AUDITOR, CONST.POLICY.ROLE.CARD_ADMIN, CONST.POLICY.ROLE.PEOPLE_ADMIN, CONST.POLICY.ROLE.PAYMENTS_ADMIN];
         const hasControlPolicyOnlyRole =
             membersRolesColumn !== -1 &&
             spreadsheet?.data?.at(membersRolesColumn)?.some((role, index) => {
                 const memberRole = containsHeader ? spreadsheet?.data?.at(membersRolesColumn)?.at(index + 1) : (role ?? '');
-                return memberRole === CONST.POLICY.ROLE.AUDITOR || memberRole === CONST.POLICY.ROLE.CARD_ADMIN;
+                return controlPolicyOnlyRoles.some((controlPolicyOnlyRole) => controlPolicyOnlyRole === memberRole);
             });
 
         if (hasControlPolicyOnlyRole && !isControlPolicy(policy)) {
-            Navigation.navigate(ROUTES.WORKSPACE_UPGRADE.getRoute(route.params.policyID, CONST.UPGRADE_FEATURE_INTRO_MAPPING.roles.alias, Navigation.getActiveRoute()));
+            Navigation.navigate(ROUTES.WORKSPACE_UPGRADE.getRoute(route.params.policyID, CONST.UPGRADE_FEATURE_INTRO_MAPPING.controlPolicyRoles.alias, Navigation.getActiveRoute()));
             return;
         }
 

From 1450f2e25f397e9a9d25e63f43d06f6a6ec96eb4 Mon Sep 17 00:00:00 2001
From: ShridharGoel <35566748+ShridharGoel@users.noreply.github.com>
Date: Wed, 10 Jun 2026 00:08:56 +0530
Subject: [PATCH 236/435] TS fix

---
 src/pages/workspace/WorkspaceMembersPage.tsx | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/pages/workspace/WorkspaceMembersPage.tsx b/src/pages/workspace/WorkspaceMembersPage.tsx
index 2b6bdb0228d7..94a460943361 100644
--- a/src/pages/workspace/WorkspaceMembersPage.tsx
+++ b/src/pages/workspace/WorkspaceMembersPage.tsx
@@ -416,7 +416,7 @@ function WorkspaceMembersPage({personalDetails, route, policy}: WorkspaceMembers
 
     const policyOwner = policy?.owner;
     const currentUserLogin = currentUserPersonalDetails.login;
-    const canAssignElevatedRoles = canMemberWrite(policy, currentUserLogin, CONST.POLICY.POLICY_FEATURE.ASSIGN_ELEVATED_ROLES);
+    const canAssignElevatedRoles = canMemberWrite(policy, currentUserLogin ?? '', CONST.POLICY.POLICY_FEATURE.ASSIGN_ELEVATED_ROLES);
     const invitedPrimaryToSecondaryLogins = useMemo(() => invertObject(policy?.primaryLoginsInvited ?? {}), [policy?.primaryLoginsInvited]);
     const isControlPolicyWithWideLayout = !shouldUseNarrowLayout && isControlPolicy(policy);
 

From 4e3c0f97cdbd89f8ebe1291fdffb9a8ff6d88cec Mon Sep 17 00:00:00 2001
From: Youssef Lourayad <youssef@expensify.com>
Date: Tue, 9 Jun 2026 19:34:04 +0000
Subject: [PATCH 237/435] Adjust link style

---
 src/components/LHNOptionsList/LHNEmptyState.tsx | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/components/LHNOptionsList/LHNEmptyState.tsx b/src/components/LHNOptionsList/LHNEmptyState.tsx
index f3626566a96b..cb0f4552dbca 100644
--- a/src/components/LHNOptionsList/LHNEmptyState.tsx
+++ b/src/components/LHNOptionsList/LHNEmptyState.tsx
@@ -31,7 +31,7 @@ function LHNEmptyState() {
                 <Text style={[styles.textAlignCenter, styles.textSupporting]}>{translate('common.emptyLHN.caughtUp')}</Text>
                 <TextLink
                     onPress={() => setActiveTab(CONST.INBOX_TAB.ALL)}
-                    style={[styles.link, styles.mt5, styles.ph4, styles.textAlignCenter]}
+                    style={[styles.textStrong, styles.mt5, styles.ph4, styles.textAlignCenter]}
                 >
                     {translate('common.emptyLHN.seeAllChats')}
                 </TextLink>

From fc992b1108909e64187ddff2c6e57187a3b737ac Mon Sep 17 00:00:00 2001
From: Stephanie Elliott <31225194+stephanieelliott@users.noreply.github.com>
Date: Tue, 9 Jun 2026 10:07:13 -1000
Subject: [PATCH 238/435] Update VAT-IT.md

---
 docs/articles/expensify-classic/connections/VAT-IT.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/docs/articles/expensify-classic/connections/VAT-IT.md b/docs/articles/expensify-classic/connections/VAT-IT.md
index 5ee23fbaf071..f55b6e7d6e9f 100644
--- a/docs/articles/expensify-classic/connections/VAT-IT.md
+++ b/docs/articles/expensify-classic/connections/VAT-IT.md
@@ -52,6 +52,6 @@ Once VAT IT prepares your VAT reclaim documents in the required languages, they
 
 # Tracking Your VAT Reclaim
 
-After submission, you can monitor the progress of your VAT reclaim via the **Submission Analysis Report** in Global VaTax.
+After submission, you can monitor the progress of your VAT reclaim via the **Submission Analysis Report** in VAT IT.
 
 By integrating Expensify with VAT IT, businesses can maximize VAT recovery while reducing administrative burden.

From 5577fb72ffb8fcfd0098e3528f06707a4e483d30 Mon Sep 17 00:00:00 2001
From: "Carlos Alvarez (via MelvinBot)" <infra+melvinbot@expensify.com>
Date: Tue, 9 Jun 2026 21:42:11 +0000
Subject: [PATCH 239/435] Build recent attendees exclusion set from displayed
 options

Co-authored-by: Carlos Alvarez <cead22@users.noreply.github.com>
---
 src/libs/OptionsListUtils/index.ts | 18 +++++++++---------
 1 file changed, 9 insertions(+), 9 deletions(-)

diff --git a/src/libs/OptionsListUtils/index.ts b/src/libs/OptionsListUtils/index.ts
index c2f0dffde85b..1791bb548cd7 100644
--- a/src/libs/OptionsListUtils/index.ts
+++ b/src/libs/OptionsListUtils/index.ts
@@ -2572,15 +2572,6 @@ function getValidOptions(
             recentReportOptions = recentReportOptions.filter((report) => !report.reportID || !reportIDsToExclude.has(report.reportID));
         }
     } else if (recentAttendees && recentAttendees?.length > 0) {
-        recentAttendees.filter((attendee) => {
-            const login = attendee.login ?? attendee.displayName;
-            if (login) {
-                loginsToExcludeFromSuggestions[login] = true;
-                return true;
-            }
-
-            return false;
-        });
         recentReportOptions = filterReports(recentAttendees as SearchOptionData[], searchTerms) as Array<SearchOption<Report>>;
 
         // Only cap the recent attendees when there's no active search. During a search we surface every match, since
@@ -2588,6 +2579,15 @@ function getValidOptions(
         if (maxRecentReportElements && searchTerms.length === 0) {
             recentReportOptions = recentReportOptions.slice(0, maxRecentReportElements);
         }
+
+        // Build the exclusion set from the recent attendees actually shown (after filtering and the cap) so that
+        // attendees that aren't displayed in "Recent" remain available in "Contacts".
+        recentReportOptions.forEach((option) => {
+            const login = option.login ?? option.displayName;
+            if (login) {
+                loginsToExcludeFromSuggestions[login] = true;
+            }
+        });
     }
 
     // Get valid personal details and check if we can find the current user:

From c28e593b89514f4668f349eb35926c38a334c968 Mon Sep 17 00:00:00 2001
From: Yuwen Memon <yuwen@expensify.com>
Date: Fri, 5 Jun 2026 11:35:11 -0700
Subject: [PATCH 240/435] refactor(chatbot): gate AgentZero on
 personalDetails.isCustomAgent flag

---
 .../AppNavigator/AuthScreensInitHandler.tsx   |  6 ----
 src/pages/inbox/AgentZeroStatusContext.tsx    | 17 ++++-----
 src/pages/inbox/ConciergeDraftContext.tsx     | 10 +++---
 src/selectors/AgentZeroChat.ts                | 36 +++++++++----------
 src/types/onyx/PersonalDetails.ts             |  9 +++++
 tests/ui/AuthScreensInitHandlerTest.tsx       |  4 ---
 6 files changed, 38 insertions(+), 44 deletions(-)

diff --git a/src/libs/Navigation/AppNavigator/AuthScreensInitHandler.tsx b/src/libs/Navigation/AppNavigator/AuthScreensInitHandler.tsx
index f953488083a9..7eb752147fe0 100644
--- a/src/libs/Navigation/AppNavigator/AuthScreensInitHandler.tsx
+++ b/src/libs/Navigation/AppNavigator/AuthScreensInitHandler.tsx
@@ -19,7 +19,6 @@ import {getReportIDFromLink} from '@libs/ReportUtils';
 import * as SessionUtils from '@libs/SessionUtils';
 import {endSpan, getSpan, startSpan} from '@libs/telemetry/activeSpans';
 import {getSearchParamFromUrl} from '@libs/Url';
-import {openAgentsPage} from '@userActions/Agent';
 import * as App from '@userActions/App';
 import * as Download from '@userActions/Download';
 import {clearStaleExportDownloads} from '@userActions/Export';
@@ -132,11 +131,6 @@ function AuthScreensInitHandler() {
             App.reconnectApp(initialLastUpdateIDAppliedToClient);
         }
 
-        // Hydrate the user's custom-agent prompts so AgentZeroStatusProvider can recognize
-        // custom-agent chats opened directly from a deep link or right after sign-in, without
-        // requiring a prior visit to Settings > Agents.
-        openAgentsPage();
-
         App.setUpPoliciesAndNavigate(
             session,
             introSelected,
diff --git a/src/pages/inbox/AgentZeroStatusContext.tsx b/src/pages/inbox/AgentZeroStatusContext.tsx
index dfda44ffaf9a..50919a5afeb5 100644
--- a/src/pages/inbox/AgentZeroStatusContext.tsx
+++ b/src/pages/inbox/AgentZeroStatusContext.tsx
@@ -1,4 +1,4 @@
-import {getAgentAccountIDFlags, getReportParticipantAccountIDs} from '@selectors/AgentZeroChat';
+import {getCustomAgentParticipantAccountID, getReportParticipantAccountIDs} from '@selectors/AgentZeroChat';
 import {getReportChatType} from '@selectors/Report';
 import {agentZeroProcessingAgentIDsSelector} from '@selectors/ReportNameValuePairs';
 import {accountIDSelector} from '@selectors/Session';
@@ -41,24 +41,19 @@ const AgentZeroStatusActionsContext = createContext<AgentZeroStatusActions>(defa
  * metadata. For non-AgentZero reports (the common case), returns children directly.
  *
  * AgentZero chats include Concierge DMs, policy #admins rooms, and custom-agent chats (any
- * report with a participant — other than the current user — whose accountID has a
- * `SHARED_NVP_AGENT_PROMPT_<accountID>` entry, populated by `OpenAgentsPage` for agents the
- * current user owns).
+ * report with a participant whose personalDetails carries `isCustomAgent: true`, stamped
+ * server-side in `Account::formatNewDotPersonalDetails`).
  */
 function AgentZeroStatusProvider({reportID, children}: React.PropsWithChildren<{reportID: string | undefined}>) {
     const [chatType] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${reportID}`, {selector: getReportChatType});
     const [participantAccountIDs] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${reportID}`, {selector: getReportParticipantAccountIDs});
-    const [agentAccountIDFlags] = useOnyx(ONYXKEYS.COLLECTION.SHARED_NVP_AGENT_PROMPT, {selector: getAgentAccountIDFlags});
+    const [agentParticipantAccountID] = useOnyx(ONYXKEYS.PERSONAL_DETAILS_LIST, {selector: getCustomAgentParticipantAccountID(participantAccountIDs)});
     const [conciergeReportID] = useOnyx(ONYXKEYS.CONCIERGE_REPORT_ID);
-    const [currentUserAccountID] = useOnyx(ONYXKEYS.SESSION, {selector: accountIDSelector});
 
     const isConciergeChat = reportID === conciergeReportID;
     const isAdmin = chatType === CONST.REPORT.CHAT_TYPE.POLICY_ADMINS;
-    // A custom-agent chat has a participant — excluding the current user — whose accountID owns
-    // an agent prompt. Excluding the current user prevents a user who owns agents from turning
-    // their own DMs into agent chats.
-    const hasAgentParticipant = participantAccountIDs?.some((accountID) => accountID !== currentUserAccountID && !!agentAccountIDFlags?.[accountID]) ?? false;
-    const isAgentZeroChat = isConciergeChat || isAdmin || hasAgentParticipant;
+    const isCustomAgentChat = agentParticipantAccountID !== undefined;
+    const isAgentZeroChat = isConciergeChat || isAdmin || isCustomAgentChat;
 
     if (!reportID || !isAgentZeroChat) {
         return children;
diff --git a/src/pages/inbox/ConciergeDraftContext.tsx b/src/pages/inbox/ConciergeDraftContext.tsx
index 45f5bf185168..ae1bb361008e 100644
--- a/src/pages/inbox/ConciergeDraftContext.tsx
+++ b/src/pages/inbox/ConciergeDraftContext.tsx
@@ -1,4 +1,4 @@
-import {getAgentAccountIDFlags, getReportParticipantAccountIDs} from '@selectors/AgentZeroChat';
+import {getCustomAgentParticipantAccountID, getReportParticipantAccountIDs} from '@selectors/AgentZeroChat';
 import {getReportChatType} from '@selectors/Report';
 import React, {createContext, useContext} from 'react';
 import useOnyx from '@hooks/useOnyx';
@@ -41,14 +41,14 @@ const ConciergeDraftActionsContext = createContext<ConciergeDraftActions>(defaul
 function ConciergeDraftProvider({reportID, children}: React.PropsWithChildren<{reportID: string | undefined}>) {
     const [chatType] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${reportID}`, {selector: getReportChatType});
     const [participantAccountIDs] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${reportID}`, {selector: getReportParticipantAccountIDs});
-    const [agentAccountIDFlags] = useOnyx(ONYXKEYS.COLLECTION.SHARED_NVP_AGENT_PROMPT, {selector: getAgentAccountIDFlags});
+    const [agentParticipantAccountID] = useOnyx(ONYXKEYS.PERSONAL_DETAILS_LIST, {selector: getCustomAgentParticipantAccountID(participantAccountIDs)});
     const [conciergeReportID] = useOnyx(ONYXKEYS.CONCIERGE_REPORT_ID);
 
     const isConciergeChat = reportID === conciergeReportID;
     const isAdmin = chatType === CONST.REPORT.CHAT_TYPE.POLICY_ADMINS;
-    // See AgentZeroStatusContext for the rationale: agentAccountIDFlags reflects agents the
-    // user owns (populated by `OpenAgentsPage`).
-    const isCustomAgentChat = participantAccountIDs?.some((accountID) => !!agentAccountIDFlags?.[accountID]);
+    // See AgentZeroStatusContext for the rationale: `isCustomAgent` lives on the participant's
+    // personalDetails, stamped by Auth in `Account::formatNewDotPersonalDetails`.
+    const isCustomAgentChat = agentParticipantAccountID !== undefined;
     const isAgentZeroChat = isConciergeChat || isAdmin || isCustomAgentChat;
 
     if (!reportID || !isAgentZeroChat) {
diff --git a/src/selectors/AgentZeroChat.ts b/src/selectors/AgentZeroChat.ts
index b38bd74b731a..57dd959b2d24 100644
--- a/src/selectors/AgentZeroChat.ts
+++ b/src/selectors/AgentZeroChat.ts
@@ -1,31 +1,31 @@
-import type {OnyxCollection, OnyxEntry} from 'react-native-onyx';
-import ONYXKEYS from '@src/ONYXKEYS';
-import type {AgentPrompt, ConciergePendingFollowupList} from '@src/types/onyx';
+import type {OnyxEntry} from 'react-native-onyx';
+import type {ConciergePendingFollowupList, PersonalDetailsList} from '@src/types/onyx';
 import type Report from '@src/types/onyx/Report';
 
 const getReportParticipantAccountIDs = (report: OnyxEntry<Report>): number[] => (report?.participants ? Object.keys(report.participants).map(Number) : []);
 
 /**
- * Reduces the SHARED_NVP_AGENT_PROMPT collection to a `Record<accountID, true>` so callers
- * can do O(1) lookups without re-rendering on every prompt-content edit.
+ * Returns the first participant accountID flagged as a custom agent (`isCustomAgent` on its
+ * personalDetails entry, stamped server-side in `Account::formatNewDotPersonalDetails`), or
+ * `undefined` when no participant is an agent.
+ *
+ * Parameterized so the closure captures only the report's small `participantAccountIDs` array —
+ * the selector iterates those (small N) against `personalDetailsList`, not the full list. Output
+ * is a primitive `number | undefined`, so `deepEqual` short-circuits cheaply and re-renders fire
+ * only when an agent participant's flag flips.
  */
-const getAgentAccountIDFlags = (agentPrompts: OnyxCollection<AgentPrompt>): Record<number, true> => {
-    if (!agentPrompts) {
-        return {};
-    }
-    const flags: Record<number, true> = {};
-    for (const key of Object.keys(agentPrompts)) {
-        const accountID = Number(key.slice(ONYXKEYS.COLLECTION.SHARED_NVP_AGENT_PROMPT.length));
-        if (!Number.isNaN(accountID)) {
-            flags[accountID] = true;
+const getCustomAgentParticipantAccountID =
+    (participantAccountIDs: number[] | undefined) =>
+    (personalDetails: OnyxEntry<PersonalDetailsList>): number | undefined => {
+        if (!participantAccountIDs?.length || !personalDetails) {
+            return undefined;
         }
-    }
-    return flags;
-};
+        return participantAccountIDs.find((accountID) => !!personalDetails[accountID]?.isCustomAgent);
+    };
 
 const hasPendingFollowupListSkeletonSelector =
     (reportActionID: string) =>
     (pending: OnyxEntry<ConciergePendingFollowupList>): boolean =>
         !pending?.hidden && pending?.reportActionID === reportActionID;
 
-export {getReportParticipantAccountIDs, getAgentAccountIDFlags, hasPendingFollowupListSkeletonSelector};
+export {getReportParticipantAccountIDs, getCustomAgentParticipantAccountID, hasPendingFollowupListSkeletonSelector};
diff --git a/src/types/onyx/PersonalDetails.ts b/src/types/onyx/PersonalDetails.ts
index 6d41b6a0d2cc..6f1f85e4ce3b 100644
--- a/src/types/onyx/PersonalDetails.ts
+++ b/src/types/onyx/PersonalDetails.ts
@@ -74,6 +74,15 @@ type PersonalDetails = OnyxCommon.OnyxValueWithOfflineFeedback<{
     /** Flag for checking if data is from optimistic data */
     isOptimisticPersonalDetail?: boolean;
 
+    /**
+     * True when this account is a registered custom agent (server-side `private_agentOwnerID`
+     * NVP set). Stamped by Auth in `Account::formatNewDotPersonalDetails`, so it travels with
+     * every personalDetails payload returned to the client (OpenReport, OpenApp, ReconnectApp,
+     * GetPersonalDetailsForEmails, etc.). Lets chat surfaces detect custom-agent participants
+     * without subscribing to the wider `SHARED_NVP_AGENT_PROMPT` collection.
+     */
+    isCustomAgent?: boolean;
+
     /** Field-specific server side errors keyed by microtime */
     errorFields?: OnyxCommon.ErrorFields<'avatar'>;
 
diff --git a/tests/ui/AuthScreensInitHandlerTest.tsx b/tests/ui/AuthScreensInitHandlerTest.tsx
index 5a2732f79c41..9f2d8f927d07 100644
--- a/tests/ui/AuthScreensInitHandlerTest.tsx
+++ b/tests/ui/AuthScreensInitHandlerTest.tsx
@@ -72,10 +72,6 @@ jest.mock('@userActions/App', () => ({
     setLocale: jest.fn(),
 }));
 
-jest.mock('@userActions/Agent', () => ({
-    openAgentsPage: jest.fn(),
-}));
-
 jest.mock('@userActions/Download', () => ({
     clearDownloads: jest.fn(),
 }));

From 185f7fcdf910162d3b89aebeaa44f30709e1bd20 Mon Sep 17 00:00:00 2001
From: Brian Lee <brianlee@expensify.com>
Date: Tue, 9 Jun 2026 15:00:20 -0700
Subject: [PATCH 241/435] Update Configure-Quickbooks-Online.md

---
 .../quickbooks-online/Configure-Quickbooks-Online.md          | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/docs/articles/new-expensify/connections/quickbooks-online/Configure-Quickbooks-Online.md b/docs/articles/new-expensify/connections/quickbooks-online/Configure-Quickbooks-Online.md
index b7d71247a78b..1c55091863b7 100644
--- a/docs/articles/new-expensify/connections/quickbooks-online/Configure-Quickbooks-Online.md
+++ b/docs/articles/new-expensify/connections/quickbooks-online/Configure-Quickbooks-Online.md
@@ -75,8 +75,8 @@ To manage automation and other connection preferences:
 - **Sync reimbursed reports**:
   - If marked as paid in QuickBooks Online, the report will show as reimbursed in Expensify
   - If reimbursed via ACH in Expensify, the status will sync to paid in QuickBooks
-- **QuickBooks bill payment account**: Select where paid expense reports are stored
-- **QuickBooks invoice collections account**: Select where paid invoices are stored
+- **QuickBooks bill payment account**: Select where payments for expense reports are recorded
+- **QuickBooks invoice collections account**: Select where payments for invoices are recorded
 
 ---
 

From 62ce64977734631da8d9241fdc0538a5db99ed27 Mon Sep 17 00:00:00 2001
From: krishna2323 <belivethatkg@gmail.com>
Date: Wed, 10 Jun 2026 04:37:29 +0530
Subject: [PATCH 242/435] Adopt Table selection middleware and remove beta gate
 for distance rates table

Signed-off-by: krishna2323 <belivethatkg@gmail.com>
---
 .../WorkspaceDistanceRatesTableRow.tsx        |  91 +++----
 .../WorkspaceDistanceRatesTable/index.tsx     | 139 +++++-----
 src/languages/de.ts                           |   4 +
 src/languages/es.ts                           |   4 +
 src/languages/fr.ts                           |   4 +
 src/languages/it.ts                           |   4 +
 src/languages/ja.ts                           |   4 +
 src/languages/nl.ts                           |   4 +
 src/languages/pl.ts                           |   4 +
 src/languages/pt-BR.ts                        |   4 +
 src/languages/zh-hans.ts                      |   4 +
 .../distanceRates/PolicyDistanceRatesPage.tsx | 237 ++----------------
 src/styles/variables.ts                       |   1 +
 13 files changed, 159 insertions(+), 345 deletions(-)

diff --git a/src/components/Tables/WorkspaceDistanceRatesTable/WorkspaceDistanceRatesTableRow.tsx b/src/components/Tables/WorkspaceDistanceRatesTable/WorkspaceDistanceRatesTableRow.tsx
index 8c729a92e36e..a3c070995746 100644
--- a/src/components/Tables/WorkspaceDistanceRatesTable/WorkspaceDistanceRatesTableRow.tsx
+++ b/src/components/Tables/WorkspaceDistanceRatesTable/WorkspaceDistanceRatesTableRow.tsx
@@ -1,10 +1,10 @@
 import {format, parseISO} from 'date-fns';
 import React from 'react';
 import {View} from 'react-native';
-import Checkbox from '@components/Checkbox';
 import Icon from '@components/Icon';
+import Switch from '@components/Switch';
 import Table from '@components/Table';
-import Text from '@components/Text';
+import type {TableData} from '@components/Table';
 import TextWithTooltip from '@components/TextWithTooltip';
 import {useMemoizedLazyExpensifyIcons} from '@hooks/useLazyAsset';
 import useTheme from '@hooks/useTheme';
@@ -16,50 +16,39 @@ import CONST from '@src/CONST';
 import type * as OnyxCommon from '@src/types/onyx/OnyxCommon';
 import type {Rate} from '@src/types/onyx/Policy';
 
-type DistanceRateTableItemData = {
+type DistanceRateTableItemData = TableData & {
     rateID: string;
     rate: Rate;
     formattedRate: string;
+    enabled: boolean;
+    isLocked: boolean;
     pendingAction?: OnyxCommon.PendingAction;
     errors?: OnyxCommon.Errors;
-    onDismissError?: () => void;
+    action: () => void;
+    dismissError: () => void;
+    onToggleEnabled: (value: boolean) => void;
 };
 
 type WorkspaceDistanceRatesTableRowProps = {
     item: DistanceRateTableItemData;
     rowIndex: number;
-    isSelected: boolean;
-    canSelectMultiple: boolean;
-    onToggle: () => void;
-    onPress: () => void;
-    onLongPress?: () => void;
     shouldUseNarrowTableLayout: boolean;
     statusLabels: Record<string, string>;
 };
 
-function formatDateColumn(dateString: string | undefined): string {
+function formatDateColumn(dateString: string | null | undefined): string {
     if (!dateString) {
         return '';
     }
     return format(parseISO(dateString), CONST.DATE.MONTH_DAY_YEAR_FORMAT);
 }
 
-function WorkspaceDistanceRatesTableRow({
-    item,
-    rowIndex,
-    isSelected,
-    canSelectMultiple,
-    onToggle,
-    onPress,
-    onLongPress,
-    shouldUseNarrowTableLayout,
-    statusLabels,
-}: WorkspaceDistanceRatesTableRowProps) {
+function WorkspaceDistanceRatesTableRow({item, rowIndex, shouldUseNarrowTableLayout, statusLabels}: WorkspaceDistanceRatesTableRowProps) {
     const theme = useTheme();
     const styles = useThemeStyles();
     const Expensicons = useMemoizedLazyExpensifyIcons(['ArrowRight']);
 
-    const {rate, formattedRate, pendingAction, errors, onDismissError} = item;
+    const {rate, formattedRate, pendingAction, errors} = item;
     const isDeleting = pendingAction === CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE;
 
     const status = getRateStatus(rate);
@@ -73,26 +62,14 @@ function WorkspaceDistanceRatesTableRow({
         <Table.Row
             interactive
             rowIndex={rowIndex}
-            disabled={isDeleting}
+            disabled={item.disabled}
             skeletonReasonAttributes={reasonAttributes}
             sentryLabel={CONST.SENTRY_LABEL.WORKSPACE.DISTANCE_RATES.ADD_BUTTON}
-            offlineWithFeedback={{errors, pendingAction, onClose: onDismissError, shouldHideOnDelete: false}}
-            onPress={onPress}
-            onLongPress={onLongPress}
+            offlineWithFeedback={{errors, pendingAction, dismissError: item.dismissError, shouldHideOnDelete: false}}
+            onPress={item.action}
         >
             {({hovered}) => (
                 <>
-                    {canSelectMultiple && (
-                        <View style={[styles.mr3]}>
-                            <Checkbox
-                                isChecked={isSelected}
-                                onPress={onToggle}
-                                accessibilityLabel={rate.name ?? ''}
-                                disabled={isDeleting}
-                            />
-                        </View>
-                    )}
-
                     <View style={[styles.flex1]}>
                         <TextWithTooltip
                             text={statusLabels[status] ?? ''}
@@ -108,52 +85,58 @@ function WorkspaceDistanceRatesTableRow({
 
                     {!shouldUseNarrowTableLayout && (
                         <View style={[styles.flex1]}>
-                            <Text
+                            <TextWithTooltip
                                 numberOfLines={1}
+                                text={rate.name ?? ''}
                                 style={[styles.lh16, styles.optionDisplayName, styles.pre]}
-                            >
-                                {rate.name}
-                            </Text>
+                            />
                         </View>
                     )}
 
                     {!shouldUseNarrowTableLayout && (
                         <View style={[styles.flex1]}>
-                            <Text
+                            <TextWithTooltip
                                 numberOfLines={1}
+                                text={formattedRate}
                                 style={[styles.lh16, styles.optionDisplayName, styles.pre]}
-                            >
-                                {formattedRate}
-                            </Text>
+                            />
                         </View>
                     )}
 
                     {!shouldUseNarrowTableLayout && (
                         <View style={[styles.flex1]}>
-                            <Text
+                            <TextWithTooltip
                                 numberOfLines={1}
+                                text={formatDateColumn(rate.startDate)}
                                 style={[styles.lh16, styles.optionDisplayName, styles.pre]}
-                            >
-                                {formatDateColumn(rate.startDate)}
-                            </Text>
+                            />
                         </View>
                     )}
 
                     {!shouldUseNarrowTableLayout && (
                         <View style={[styles.flex1]}>
-                            <Text
+                            <TextWithTooltip
                                 numberOfLines={1}
+                                text={formatDateColumn(rate.endDate)}
                                 style={[styles.lh16, styles.optionDisplayName, styles.pre]}
-                            >
-                                {formatDateColumn(rate.endDate)}
-                            </Text>
+                            />
                         </View>
                     )}
 
+                    <View style={[styles.justifyContentCenter, styles.alignItemsEnd]}>
+                        <Switch
+                            isOn={item.enabled}
+                            showLockIcon={item.isLocked}
+                            disabled={item.disabled}
+                            accessibilityLabel={rate.name ?? ''}
+                            onToggle={item.onToggleEnabled}
+                        />
+                    </View>
+
                     <Icon
                         src={Expensicons.ArrowRight}
                         fill={theme.icon}
-                        additionalStyles={[styles.alignSelfCenter, !hovered && styles.opacitySemiTransparent]}
+                        additionalStyles={[styles.justifyContentCenter, styles.alignItemsCenter, (!hovered || item.disabled) && styles.opacitySemiTransparent]}
                         width={variables.iconSizeNormal}
                         height={variables.iconSizeNormal}
                     />
diff --git a/src/components/Tables/WorkspaceDistanceRatesTable/index.tsx b/src/components/Tables/WorkspaceDistanceRatesTable/index.tsx
index 783146b3e584..60c775bb5146 100644
--- a/src/components/Tables/WorkspaceDistanceRatesTable/index.tsx
+++ b/src/components/Tables/WorkspaceDistanceRatesTable/index.tsx
@@ -1,7 +1,5 @@
 import type {ListRenderItemInfo} from '@shopify/flash-list';
 import React, {useEffect, useMemo, useRef, useState} from 'react';
-import {View} from 'react-native';
-import Checkbox from '@components/Checkbox';
 import Table from '@components/Table';
 import type {ActiveSorting, CompareItemsCallback, IsItemInSearchCallback, TableColumn, TableHandle} from '@components/Table';
 import useBottomSafeSafeAreaPaddingStyle from '@hooks/useBottomSafeSafeAreaPaddingStyle';
@@ -11,24 +9,25 @@ import useThemeStyles from '@hooks/useThemeStyles';
 import {convertAmountToDisplayString} from '@libs/CurrencyUtils';
 import {getRateStatus} from '@libs/PolicyDistanceRatesUtils';
 import tokenizedSearch from '@libs/tokenizedSearch';
+import variables from '@styles/variables';
 import CONST from '@src/CONST';
 import type * as OnyxCommon from '@src/types/onyx/OnyxCommon';
 import type {Rate} from '@src/types/onyx/Policy';
 import WorkspaceDistanceRatesTableRow from './WorkspaceDistanceRatesTableRow';
 import type {DistanceRateTableItemData} from './WorkspaceDistanceRatesTableRow';
 
-type DistanceRatesTableColumnKey = 'status' | 'name' | 'rate' | 'startDate' | 'endDate';
+type DistanceRatesTableColumnKey = 'status' | 'name' | 'rate' | 'startDate' | 'endDate' | 'enabled' | 'actions';
 
 type WorkspaceDistanceRatesTableProps = {
     customUnitRates: Record<string, Rate>;
     unitTranslation: string;
-    selectedDistanceRates: string[];
-    canSelectMultiple: boolean;
-    onToggleRate: (rateID: string) => void;
-    onToggleAllRates: () => void;
+    selectionEnabled: boolean;
+    selectedKeys: string[];
+    onRowSelectionChange: (selectedRowKeys: string[]) => void;
     onPressRate: (rateID: string) => void;
-    onLongPressRate?: (rateID: string) => void;
     onDismissError: (rateID: string) => void;
+    onToggleEnabled: (value: boolean, rateID: string) => void;
+    canDisableOrDeleteRate: (rateID: string) => boolean;
     pendingAction?: OnyxCommon.PendingAction;
     pendingFields?: OnyxCommon.PendingFields<string>;
 };
@@ -43,13 +42,13 @@ const STATUS_ORDER: Record<string, number> = {
 function WorkspaceDistanceRatesTable({
     customUnitRates,
     unitTranslation,
-    selectedDistanceRates,
-    canSelectMultiple,
-    onToggleRate,
-    onToggleAllRates,
+    selectionEnabled,
+    selectedKeys,
+    onRowSelectionChange,
     onPressRate,
-    onLongPressRate,
     onDismissError,
+    onToggleEnabled,
+    canDisableOrDeleteRate,
     pendingAction,
     pendingFields,
 }: WorkspaceDistanceRatesTableProps) {
@@ -61,34 +60,46 @@ function WorkspaceDistanceRatesTable({
     const tableRef = useRef<TableHandle<DistanceRateTableItemData, DistanceRatesTableColumnKey>>(null);
 
     const columns: Array<TableColumn<DistanceRatesTableColumnKey>> = [
-        {key: 'status', label: translate('workspace.distanceRates.status')},
-        {key: 'name', label: translate('common.name')},
-        {key: 'rate', label: translate('workspace.distanceRates.rate')},
-        {key: 'startDate', label: translate('workspace.distanceRates.startDate')},
-        {key: 'endDate', label: translate('workspace.distanceRates.endDate')},
+        {key: 'status', label: translate('workspace.distanceRates.status'), sortable: true, width: variables.tableStatusColumnWidth},
+        {key: 'name', label: translate('common.name'), sortable: true},
+        {key: 'rate', label: translate('workspace.distanceRates.rate'), sortable: true},
+        {key: 'startDate', label: translate('workspace.distanceRates.startDate'), sortable: true},
+        {key: 'endDate', label: translate('workspace.distanceRates.endDate'), sortable: true},
+        {key: 'enabled', label: translate('common.enabled'), sortable: true, width: variables.tableSwitchColumnWidth, styling: {containerStyles: [styles.justifyContentEnd]}},
+        {key: 'actions', label: '', sortable: false, width: variables.tableCaretColumnWidth},
     ];
 
-    const ratesData: DistanceRateTableItemData[] = Object.values(customUnitRates).map((rate) => {
-        const resolvedPendingAction =
-            rate.pendingAction ??
-            rate.pendingFields?.rate ??
-            rate.pendingFields?.enabled ??
-            rate.pendingFields?.currency ??
-            rate.pendingFields?.name ??
-            pendingFields?.attributes ??
-            (pendingAction === CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD ? pendingAction : undefined);
-
-        return {
-            rateID: rate.customUnitRateID,
-            rate,
-            formattedRate: `${convertAmountToDisplayString(rate.rate, rate.currency ?? CONST.CURRENCY.USD)} / ${unitTranslation}`,
-            pendingAction: resolvedPendingAction ?? undefined,
-            errors: rate.errors ?? undefined,
-            onDismissError: () => onDismissError(rate.customUnitRateID),
-        };
-    });
-
-    const keyExtractor = (item: DistanceRateTableItemData) => item.rateID;
+    const ratesData: DistanceRateTableItemData[] = useMemo(
+        () =>
+            Object.values(customUnitRates).map((rate) => {
+                const resolvedPendingAction =
+                    rate.pendingAction ??
+                    rate.pendingFields?.rate ??
+                    rate.pendingFields?.enabled ??
+                    rate.pendingFields?.currency ??
+                    rate.pendingFields?.name ??
+                    pendingFields?.attributes ??
+                    (pendingAction === CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD ? pendingAction : undefined);
+
+                const isDeleting = resolvedPendingAction === CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE;
+
+                return {
+                    keyForList: rate.customUnitRateID,
+                    rateID: rate.customUnitRateID,
+                    rate,
+                    disabled: isDeleting,
+                    enabled: !!rate.enabled,
+                    isLocked: !selectionEnabled || !canDisableOrDeleteRate(rate.customUnitRateID) || isDeleting,
+                    formattedRate: `${convertAmountToDisplayString(rate.rate, rate.currency ?? CONST.CURRENCY.USD)} / ${unitTranslation}`,
+                    pendingAction: resolvedPendingAction ?? undefined,
+                    errors: rate.errors ?? undefined,
+                    action: () => onPressRate(rate.customUnitRateID),
+                    dismissError: () => onDismissError(rate.customUnitRateID),
+                    onToggleEnabled: (value: boolean) => onToggleEnabled(value, rate.customUnitRateID),
+                };
+            }),
+        [customUnitRates, unitTranslation, pendingFields?.attributes, pendingAction, onPressRate, onDismissError, onToggleEnabled, canDisableOrDeleteRate, selectionEnabled],
+    );
 
     const tableBodyContentContainerStyle = useBottomSafeSafeAreaPaddingStyle({
         addBottomSafeAreaPadding: true,
@@ -125,6 +136,10 @@ function WorkspaceDistanceRatesTable({
             return localeCompare(a.rate.endDate ?? '', b.rate.endDate ?? '') * orderMultiplier;
         }
 
+        if (activeSorting.columnKey === 'enabled') {
+            return ((a.enabled ? 1 : 0) - (b.enabled ? 1 : 0)) * orderMultiplier;
+        }
+
         return 0;
     };
 
@@ -148,11 +163,6 @@ function WorkspaceDistanceRatesTable({
             key={item.rateID}
             item={item}
             rowIndex={index}
-            isSelected={selectedDistanceRates.includes(item.rateID)}
-            canSelectMultiple={canSelectMultiple}
-            onToggle={() => onToggleRate(item.rateID)}
-            onPress={() => onPressRate(item.rateID)}
-            onLongPress={onLongPressRate ? () => onLongPressRate(item.rateID) : undefined}
             shouldUseNarrowTableLayout={shouldUseNarrowTableLayout}
             statusLabels={statusLabels}
         />
@@ -181,54 +191,25 @@ function WorkspaceDistanceRatesTable({
         tableRef.current?.updateSorting(activeSortingInWideLayout);
     }, [activeSortingInWideLayout, shouldUseNarrowTableLayout]);
 
-    const allSelected = ratesData.length > 0 && ratesData.every((item) => selectedDistanceRates.includes(item.rateID));
-    const someSelected = selectedDistanceRates.length > 0 && !allSelected;
-
-    const SelectAllHeader = canSelectMultiple ? (
-        <View style={[styles.mr3, styles.alignSelfCenter]}>
-            <Checkbox
-                isChecked={allSelected}
-                isIndeterminate={someSelected}
-                onPress={onToggleAllRates}
-                accessibilityLabel={translate('accessibilityHints.selectAllDistanceRates')}
-            />
-        </View>
-    ) : null;
-
     const shouldShowSearchBar = Object.keys(customUnitRates).length >= CONST.STANDARD_LIST_ITEM_LIMIT;
 
-    const ListHeader = (
-        <>
-            {shouldShowSearchBar && <Table.SearchBar />}
-            {!shouldUseNarrowTableLayout && <Table.Header />}
-        </>
-    );
-
     return (
         <Table
             ref={tableRef}
             data={ratesData}
             columns={columns}
+            selectionEnabled={selectionEnabled}
+            selectedKeys={selectedKeys}
+            onRowSelectionChange={onRowSelectionChange}
             renderItem={renderItem}
-            keyExtractor={keyExtractor}
+            keyExtractor={(item) => item.keyForList}
             compareItems={compareItems}
             isItemInSearch={isItemInSearch}
             initialSortColumn="name"
             title={translate('workspace.common.distanceRates')}
-            ListHeaderComponent={shouldUseNarrowTableLayout ? ListHeader : undefined}
         >
-            {!shouldUseNarrowTableLayout && (
-                <>
-                    {shouldShowSearchBar && <Table.SearchBar />}
-                    <View style={[styles.flexRow, styles.alignItemsCenter, styles.mh5]}>
-                        {SelectAllHeader}
-                        <View style={[styles.flex1]}>
-                            <Table.Header />
-                        </View>
-                    </View>
-                </>
-            )}
-
+            {shouldShowSearchBar && <Table.SearchBar label={translate('workspace.distanceRates.findRate')} />}
+            <Table.Header />
             <Table.Body contentContainerStyle={tableBodyContentContainerStyle} />
         </Table>
     );
diff --git a/src/languages/de.ts b/src/languages/de.ts
index d49ab9960341..f2f0b811f40e 100644
--- a/src/languages/de.ts
+++ b/src/languages/de.ts
@@ -6696,6 +6696,10 @@ _Für ausführlichere Anweisungen [besuchen Sie unsere Hilfeseite](${CONST.NETSU
             }),
             enableRate: 'Kurs aktivieren',
             status: 'Status',
+            statusActive: 'Aktiv',
+            statusFuture: 'Zukünftig',
+            statusExpired: 'Abgelaufen',
+            statusInactive: 'Inaktiv',
             unit: 'Einheit',
             taxFeatureNotEnabledMessage:
                 '<muted-text>Steuern müssen im Workspace aktiviert sein, um diese Funktion zu verwenden. Gehe zu <a href="#">Weitere Funktionen</a>, um das zu ändern.</muted-text>',
diff --git a/src/languages/es.ts b/src/languages/es.ts
index 4ed11c0837eb..cce95beb0b18 100644
--- a/src/languages/es.ts
+++ b/src/languages/es.ts
@@ -6614,6 +6614,10 @@ ${amount} para ${merchant} - ${date}`,
             }),
             enableRate: 'Activar tasa',
             status: 'Estado',
+            statusActive: 'Activo',
+            statusFuture: 'Futuro',
+            statusExpired: 'Expirado',
+            statusInactive: 'Inactivo',
             unit: 'Unidad',
             taxFeatureNotEnabledMessage:
                 '<muted-text>Los impuestos deben estar activados en el área de trabajo para poder utilizar esta función. Dirígete a <a href="#">Más funcionalidades</a> para hacer ese cambio.</muted-text>',
diff --git a/src/languages/fr.ts b/src/languages/fr.ts
index 81ed59d53e2f..6264820e731d 100644
--- a/src/languages/fr.ts
+++ b/src/languages/fr.ts
@@ -6723,6 +6723,10 @@ _Pour des instructions plus détaillées, [visitez notre site d’aide](${CONST.
             }),
             enableRate: 'Activer le taux',
             status: 'Statut',
+            statusActive: 'Actif',
+            statusFuture: 'Futur',
+            statusExpired: 'Expiré',
+            statusInactive: 'Inactif',
             unit: 'Unité',
             taxFeatureNotEnabledMessage:
                 '<muted-text>Les taxes doivent être activées sur l’espace de travail pour utiliser cette fonctionnalité. Rendez-vous dans <a href="#">Plus de fonctionnalités</a> pour effectuer cette modification.</muted-text>',
diff --git a/src/languages/it.ts b/src/languages/it.ts
index f73777568947..e66bad25d034 100644
--- a/src/languages/it.ts
+++ b/src/languages/it.ts
@@ -6682,6 +6682,10 @@ _Per istruzioni più dettagliate, [visita il nostro sito di assistenza](${CONST.
             }),
             enableRate: 'Abilita tariffa',
             status: 'Stato',
+            statusActive: 'Attivo',
+            statusFuture: 'Futuro',
+            statusExpired: 'Scaduto',
+            statusInactive: 'Inattivo',
             unit: 'Unit',
             taxFeatureNotEnabledMessage:
                 '<muted-text>Per usare questa funzione devi abilitare le imposte nello spazio di lavoro. Vai su <a href="#">Altre funzionalità</a> per effettuare questa modifica.</muted-text>',
diff --git a/src/languages/ja.ts b/src/languages/ja.ts
index 0de98845eab1..7b80100a123c 100644
--- a/src/languages/ja.ts
+++ b/src/languages/ja.ts
@@ -6611,6 +6611,10 @@ _詳しい手順については、[ヘルプサイトをご覧ください](${CO
             }),
             enableRate: 'レートを有効にする',
             status: 'ステータス',
+            statusActive: 'アクティブ',
+            statusFuture: '将来',
+            statusExpired: '期限切れ',
+            statusInactive: '無効',
             unit: '単位',
             taxFeatureNotEnabledMessage:
                 '<muted-text>この機能を利用するには、ワークスペースで税金設定を有効にする必要があります。設定を変更するには、<a href="#">その他の機能</a>に移動してください。</muted-text>',
diff --git a/src/languages/nl.ts b/src/languages/nl.ts
index 0aba8236fe62..9fc65b00ffe5 100644
--- a/src/languages/nl.ts
+++ b/src/languages/nl.ts
@@ -6661,6 +6661,10 @@ _Voor meer gedetailleerde instructies, [bezoek onze help-site](${CONST.NETSUITE_
             }),
             enableRate: 'Tarief inschakelen',
             status: 'Status',
+            statusActive: 'Actief',
+            statusFuture: 'Toekomstig',
+            statusExpired: 'Verlopen',
+            statusInactive: 'Inactief',
             unit: 'Eenheid',
             taxFeatureNotEnabledMessage:
                 '<muted-text>Belastingen moeten in de workspace zijn ingeschakeld om deze functie te gebruiken. Ga naar <a href="#">Meer functies</a> om dat te wijzigen.</muted-text>',
diff --git a/src/languages/pl.ts b/src/languages/pl.ts
index 51fbc5014fc3..9aae731a4390 100644
--- a/src/languages/pl.ts
+++ b/src/languages/pl.ts
@@ -6654,6 +6654,10 @@ _Aby uzyskać bardziej szczegółowe instrukcje, [odwiedź naszą stronę pomocy
             }),
             enableRate: 'Włącz stawkę',
             status: 'Status',
+            statusActive: 'Aktywna',
+            statusFuture: 'Przyszła',
+            statusExpired: 'Wygasła',
+            statusInactive: 'Nieaktywna',
             unit: 'Jednostka',
             taxFeatureNotEnabledMessage:
                 '<muted-text>Aby korzystać z tej funkcji, włącz podatki w przestrzeni roboczej. Przejdź do sekcji <a href="#">Więcej funkcji</a>, aby to zmienić.</muted-text>',
diff --git a/src/languages/pt-BR.ts b/src/languages/pt-BR.ts
index f8942f7398f1..803b70de82d2 100644
--- a/src/languages/pt-BR.ts
+++ b/src/languages/pt-BR.ts
@@ -6659,6 +6659,10 @@ _Para instruções mais detalhadas, [visite nossa central de ajuda](${CONST.NETS
             }),
             enableRate: 'Ativar tarifa',
             status: 'Status',
+            statusActive: 'Ativo',
+            statusFuture: 'Futuro',
+            statusExpired: 'Expirado',
+            statusInactive: 'Inativo',
             unit: 'Unidade',
             taxFeatureNotEnabledMessage:
                 '<muted-text>Os impostos precisam estar ativados no workspace para usar este recurso. Vá até <a href="#">Mais recursos</a> para fazer essa alteração.</muted-text>',
diff --git a/src/languages/zh-hans.ts b/src/languages/zh-hans.ts
index 2a75e959f486..926083c1f2e6 100644
--- a/src/languages/zh-hans.ts
+++ b/src/languages/zh-hans.ts
@@ -6494,6 +6494,10 @@ _如需更详细的说明，请[访问我们的帮助网站](${CONST.NETSUITE_IM
             }),
             enableRate: '启用费率',
             status: '状态',
+            statusActive: '活跃',
+            statusFuture: '未来',
+            statusExpired: '已过期',
+            statusInactive: '未启用',
             unit: '单位',
             taxFeatureNotEnabledMessage: '<muted-text>必须在工作区中启用税费才能使用此功能。前往<a href="#">更多功能</a>进行更改。</muted-text>',
             deleteDistanceRate: '删除距离费率',
diff --git a/src/pages/workspace/distanceRates/PolicyDistanceRatesPage.tsx b/src/pages/workspace/distanceRates/PolicyDistanceRatesPage.tsx
index 2691af12d89e..59a7843a1993 100644
--- a/src/pages/workspace/distanceRates/PolicyDistanceRatesPage.tsx
+++ b/src/pages/workspace/distanceRates/PolicyDistanceRatesPage.tsx
@@ -9,12 +9,6 @@ import {loadIllustration} from '@components/Icon/IllustrationLoader';
 import type {IllustrationName} from '@components/Icon/IllustrationLoader';
 import {ModalActions} from '@components/Modal/Global/ModalContext';
 import ScreenWrapper from '@components/ScreenWrapper';
-import SearchBar from '@components/SearchBar';
-import TableListItem from '@components/SelectionList/ListItem/TableListItem';
-import type {ListItem} from '@components/SelectionList/types';
-import SelectionListWithModal from '@components/SelectionListWithModal';
-import CustomListHeader from '@components/SelectionListWithModal/CustomListHeader';
-import Switch from '@components/Switch';
 import WorkspaceDistanceRatesTable from '@components/Tables/WorkspaceDistanceRatesTable';
 import Text from '@components/Text';
 import useConfirmModal from '@hooks/useConfirmModal';
@@ -24,17 +18,15 @@ import useLocalize from '@hooks/useLocalize';
 import useMobileSelectionMode from '@hooks/useMobileSelectionMode';
 import useNetwork from '@hooks/useNetwork';
 import useOnyx from '@hooks/useOnyx';
-import usePermissions from '@hooks/usePermissions';
 import usePolicy from '@hooks/usePolicy';
 import usePolicyFeatureWriteAccess from '@hooks/usePolicyFeatureWriteAccess';
 import useResponsiveLayout from '@hooks/useResponsiveLayout';
 import useSearchBackPress from '@hooks/useSearchBackPress';
-import useSearchResults from '@hooks/useSearchResults';
 import useShouldDisplayButtonsInSeparateLine from '@hooks/useShouldDisplayButtonsInSeparateLine';
 import useThemeStyles from '@hooks/useThemeStyles';
 import useTransactionViolation from '@hooks/useTransactionViolation';
 import useWorkspaceDocumentTitle from '@hooks/useWorkspaceDocumentTitle';
-import {turnOffMobileSelectionMode, turnOnMobileSelectionMode} from '@libs/actions/MobileSelectionMode';
+import {turnOffMobileSelectionMode} from '@libs/actions/MobileSelectionMode';
 import {
     clearCreateDistanceRateItemAndError,
     clearDeleteDistanceRateError,
@@ -42,13 +34,10 @@ import {
     openPolicyDistanceRatesPage,
     setPolicyDistanceRatesEnabled,
 } from '@libs/actions/Policy/DistanceRate';
-import {convertAmountToDisplayString} from '@libs/CurrencyUtils';
-import {canUseTouchScreen} from '@libs/DeviceCapabilities';
 import Navigation from '@libs/Navigation/Navigation';
 import type {PlatformStackScreenProps} from '@libs/Navigation/PlatformStackNavigation/types';
 import {getDistanceRateCustomUnit} from '@libs/PolicyUtils';
 import type {SkeletonSpanReasonAttributes} from '@libs/telemetry/useSkeletonSpan';
-import tokenizedSearch from '@libs/tokenizedSearch';
 import type {WorkspaceSplitNavigatorParamList} from '@navigation/types';
 import AccessOrNotFoundWrapper from '@pages/workspace/AccessOrNotFoundWrapper';
 import ButtonWithDropdownMenu from '@src/components/ButtonWithDropdownMenu';
@@ -59,8 +48,6 @@ import type SCREENS from '@src/SCREENS';
 import type {Report, Transaction} from '@src/types/onyx';
 import type {Rate} from '@src/types/onyx/Policy';
 
-type RateForList = ListItem & {value: string; rate?: number};
-
 type PolicyDistanceRatesPageProps = PlatformStackScreenProps<WorkspaceSplitNavigatorParamList, typeof SCREENS.WORKSPACE.DISTANCE_RATES>;
 
 function PolicyDistanceRatesPage({
@@ -69,18 +56,15 @@ function PolicyDistanceRatesPage({
     },
 }: PolicyDistanceRatesPageProps) {
     const icons = useMemoizedLazyExpensifyIcons(['Checkmark', 'Close', 'Gear', 'Plus', 'Trashcan']);
-    const {isBetaEnabled} = usePermissions();
-    const isDateBoundMileageRateEnabled = isBetaEnabled(CONST.BETAS.DATE_BOUND_MILEAGE_RATE);
     const {shouldUseNarrowLayout, isInLandscapeMode} = useResponsiveLayout();
     const styles = useThemeStyles();
-    const {translate, localeCompare} = useLocalize();
+    const {translate} = useLocalize();
     const {showConfirmModal} = useConfirmModal();
     const policy = usePolicy(policyID);
     useWorkspaceDocumentTitle(policy?.name, 'workspace.common.distanceRates');
     const isMobileSelectionModeEnabled = useMobileSelectionMode();
-    const {canWrite: canWriteDistanceRates, showReadOnlyModal, withReadOnlyFallback} = usePolicyFeatureWriteAccess(policy, CONST.POLICY.POLICY_FEATURE.DISTANCE_RATES);
+    const {canWrite: canWriteDistanceRates, showReadOnlyModal} = usePolicyFeatureWriteAccess(policy, CONST.POLICY.POLICY_FEATURE.DISTANCE_RATES);
 
-    const canSelectMultiple = canWriteDistanceRates && (shouldUseNarrowLayout ? isMobileSelectionModeEnabled : true);
     const {asset: CarIce} = useMemoizedLazyAsset(() => loadIllustration('CarIce' as IllustrationName));
     const customUnit = useMemo(() => getDistanceRateCustomUnit(policy), [policy]);
     const customUnitRates: Record<string, Rate> = useMemo(() => customUnit?.rates ?? {}, [customUnit?.rates]);
@@ -167,22 +151,6 @@ function PolicyDistanceRatesPage({
         openPolicyDistanceRatesPage(policyID);
     }, [policyID]);
 
-    const dismissError = useCallback(
-        (item: RateForList) => {
-            if (!customUnit?.customUnitID) {
-                return;
-            }
-
-            if (customUnitRates[item.value].errors) {
-                clearDeleteDistanceRateError(policyID, customUnit.customUnitID, item.value);
-                return;
-            }
-
-            clearCreateDistanceRateItemAndError(policyID, customUnit.customUnitID, item.value);
-        },
-        [customUnit?.customUnitID, customUnitRates, policyID],
-    );
-
     const {isOffline} = useNetwork({onReconnect: fetchDistanceRates});
 
     useEffect(() => {
@@ -223,7 +191,6 @@ function PolicyDistanceRatesPage({
                 return;
             }
             const rate = customUnit?.rates?.[rateID];
-            // Rates can be disabled or deleted as long as in the remaining rates there is always at least one enabled rate and there are no pending delete actions
             if (!rate?.enabled || canDisableOrDeleteRate(rateID)) {
                 setPolicyDistanceRatesEnabled(policyID, customUnit, [{...rate, enabled: value}]);
             } else {
@@ -235,60 +202,6 @@ function PolicyDistanceRatesPage({
 
     const unitTranslation = translate(`common.${customUnit?.attributes?.unit ?? CONST.CUSTOM_UNITS.DISTANCE_UNIT_MILES}`);
 
-    const distanceRatesList = useMemo<RateForList[]>(
-        () =>
-            Object.values(customUnitRates).map((value) => {
-                const alternateText = `${convertAmountToDisplayString(value.rate, value.currency ?? CONST.CURRENCY.USD)} / ${unitTranslation}`;
-
-                return {
-                    rate: value.rate,
-                    value: value.customUnitRateID,
-                    text: value.name,
-                    alternateText,
-                    keyForList: value.customUnitRateID,
-                    isDisabled: value.pendingAction === CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE,
-                    pendingAction:
-                        value.pendingAction ??
-                        value.pendingFields?.rate ??
-                        value.pendingFields?.enabled ??
-                        value.pendingFields?.currency ??
-                        value.pendingFields?.taxRateExternalID ??
-                        value.pendingFields?.taxClaimablePercentage ??
-                        value.pendingFields?.name ??
-                        customUnit?.pendingFields?.attributes ??
-                        (policy?.pendingAction === CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD ? policy?.pendingAction : undefined),
-                    errors: value.errors ?? undefined,
-                    rightElement: (
-                        <Switch
-                            isOn={!!value?.enabled}
-                            accessibilityLabel={value?.name ?? ''}
-                            onToggle={(newValue: boolean) => updateDistanceRateEnabled(newValue, value.customUnitRateID)}
-                            showLockIcon={!canWriteDistanceRates || !canDisableOrDeleteRate(value.customUnitRateID)}
-                            disabled={!canWriteDistanceRates || value.pendingAction === CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE}
-                            disabledAction={withReadOnlyFallback()}
-                        />
-                    ),
-                };
-            }),
-        [
-            canDisableOrDeleteRate,
-            canWriteDistanceRates,
-            customUnitRates,
-            unitTranslation,
-            customUnit?.pendingFields?.attributes,
-            policy?.pendingAction,
-            withReadOnlyFallback,
-            updateDistanceRateEnabled,
-        ],
-    );
-
-    const filterRate = useCallback((rate: RateForList, searchInput: string) => {
-        const results = tokenizedSearch([rate], searchInput, (option) => [option.text ?? '']);
-        return results.length > 0;
-    }, []);
-    const sortRates = useCallback((rates: RateForList[]) => rates.sort((a, b) => localeCompare(a.text ?? '', b.text ?? '')), [localeCompare]);
-    const [inputValue, setInputValue, filteredDistanceRatesList] = useSearchResults(distanceRatesList, filterRate, sortRates);
-
     const addRate = () => {
         Navigation.navigate(ROUTES.WORKSPACE_CREATE_DISTANCE_RATE.getRoute(policyID));
     };
@@ -297,10 +210,6 @@ function PolicyDistanceRatesPage({
         Navigation.navigate(ROUTES.WORKSPACE_DISTANCE_RATES_SETTINGS.getRoute(policyID));
     }, [policyID]);
 
-    const openRateDetails = (rate: RateForList) => {
-        Navigation.navigate(ROUTES.WORKSPACE_DISTANCE_RATE_DETAILS.getRoute(policyID, rate.value));
-    };
-
     const disableRates = () => {
         if (customUnit === undefined) {
             return;
@@ -344,57 +253,20 @@ function PolicyDistanceRatesPage({
         setSelectedDistanceRates([]);
     };
 
-    const toggleRateByID = useCallback(
+    const dismissErrorByID = useCallback(
         (rateID: string) => {
-            setSelectedDistanceRates((prevSelectedRates) => {
-                if (prevSelectedRates.includes(rateID)) {
-                    return prevSelectedRates.filter((selectedRate) => selectedRate !== rateID);
-                }
-                return [...prevSelectedRates, rateID];
-            });
+            if (!customUnit?.customUnitID) {
+                return;
+            }
+            if (customUnitRates[rateID]?.errors) {
+                clearDeleteDistanceRateError(policyID, customUnit.customUnitID, rateID);
+                return;
+            }
+            clearCreateDistanceRateItemAndError(policyID, customUnit.customUnitID, rateID);
         },
-        [setSelectedDistanceRates],
+        [customUnit?.customUnitID, customUnitRates, policyID],
     );
 
-    const toggleRate = (rate: RateForList) => {
-        toggleRateByID(rate.value);
-    };
-
-    const toggleAllRates = () => {
-        if (selectedDistanceRates.length > 0) {
-            setSelectedDistanceRates([]);
-        } else {
-            setSelectedDistanceRates(
-                Object.entries(selectableRates)
-                    .filter(([, rate]) => rate.pendingAction !== CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE && filteredDistanceRatesList.some((item) => item.value === rate.customUnitRateID))
-                    .map(([key]) => key),
-            );
-        }
-    };
-
-    const toggleAllRatesForTable = useCallback(() => {
-        if (selectedDistanceRates.length > 0) {
-            setSelectedDistanceRates([]);
-        } else {
-            setSelectedDistanceRates(
-                Object.entries(selectableRates)
-                    .filter(([, rate]) => rate.pendingAction !== CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE)
-                    .map(([key]) => key),
-            );
-        }
-    }, [selectedDistanceRates.length, selectableRates, setSelectedDistanceRates]);
-
-    const dismissErrorByID = (rateID: string) => {
-        if (!customUnit?.customUnitID) {
-            return;
-        }
-        if (customUnitRates[rateID]?.errors) {
-            clearDeleteDistanceRateError(policyID, customUnit.customUnitID, rateID);
-            return;
-        }
-        clearCreateDistanceRateItemAndError(policyID, customUnit.customUnitID, rateID);
-    };
-
     const openRateDetailsByID = useCallback(
         (rateID: string) => {
             Navigation.navigate(ROUTES.WORKSPACE_DISTANCE_RATE_DETAILS.getRoute(policyID, rateID));
@@ -402,30 +274,6 @@ function PolicyDistanceRatesPage({
         [policyID],
     );
 
-    const handleLongPressRate = useCallback(
-        (rateID: string) => {
-            if (shouldUseNarrowLayout && !isMobileSelectionModeEnabled) {
-                turnOnMobileSelectionMode();
-            }
-            toggleRateByID(rateID);
-        },
-        [shouldUseNarrowLayout, isMobileSelectionModeEnabled, toggleRateByID],
-    );
-
-    const getCustomListHeader = () => {
-        if (filteredDistanceRatesList.length === 0) {
-            return null;
-        }
-        return (
-            <CustomListHeader
-                canSelectMultiple={canSelectMultiple}
-                leftHeaderText={translate('workspace.distanceRates.rate')}
-                rightHeaderText={translate('common.enabled')}
-                shouldShowRightCaret
-            />
-        );
-    };
-
     const getBulkActionsButtonOptions = () => {
         const options: Array<DropdownOption<WorkspaceDistanceRatesBulkActionType>> = [
             {
@@ -534,24 +382,6 @@ function PolicyDistanceRatesPage({
 
     const selectionModeHeader = isMobileSelectionModeEnabled && shouldUseNarrowLayout;
 
-    const headerContent = (
-        <>
-            {Object.values(customUnitRates).length > 0 && (
-                <View style={[styles.ph5, styles.pb5, styles.pt3, shouldUseNarrowLayout ? styles.workspaceSectionMobile : styles.workspaceSection]}>
-                    <Text style={[styles.textNormal, styles.colorMuted]}>{translate('workspace.distanceRates.centrallyManage')}</Text>
-                </View>
-            )}
-            {Object.values(customUnitRates).length >= CONST.STANDARD_LIST_ITEM_LIMIT && (
-                <SearchBar
-                    label={translate('workspace.distanceRates.findRate')}
-                    inputValue={inputValue}
-                    onChangeText={setInputValue}
-                    shouldShowEmptyState={filteredDistanceRatesList.length === 0}
-                />
-            )}
-        </>
-    );
-
     return (
         <AccessOrNotFoundWrapper
             accessVariants={[CONST.POLICY.ACCESS_VARIANTS.ADMIN, CONST.POLICY.ACCESS_VARIANTS.PAID]}
@@ -591,43 +421,26 @@ function PolicyDistanceRatesPage({
                         reasonAttributes={reasonAttributes}
                     />
                 )}
-                {Object.values(customUnitRates).length > 0 &&
-                    (isDateBoundMileageRateEnabled ? (
+                {Object.values(customUnitRates).length > 0 && (
+                    <>
+                        <View style={[styles.ph5, styles.pb5, styles.pt3, shouldUseNarrowLayout ? styles.workspaceSectionMobile : styles.workspaceSection]}>
+                            <Text style={[styles.textNormal, styles.colorMuted]}>{translate('workspace.distanceRates.centrallyManage')}</Text>
+                        </View>
                         <WorkspaceDistanceRatesTable
                             customUnitRates={customUnitRates}
                             unitTranslation={unitTranslation}
-                            selectedDistanceRates={selectedDistanceRates}
-                            canSelectMultiple={canSelectMultiple}
-                            onToggleRate={toggleRateByID}
-                            onToggleAllRates={toggleAllRatesForTable}
+                            selectionEnabled={canWriteDistanceRates}
+                            selectedKeys={selectedDistanceRates}
+                            onRowSelectionChange={setSelectedDistanceRates}
                             onPressRate={openRateDetailsByID}
-                            onLongPressRate={handleLongPressRate}
                             onDismissError={dismissErrorByID}
+                            onToggleEnabled={updateDistanceRateEnabled}
+                            canDisableOrDeleteRate={canDisableOrDeleteRate}
                             pendingAction={policy?.pendingAction === CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD ? policy?.pendingAction : undefined}
                             pendingFields={customUnit?.pendingFields}
                         />
-                    ) : (
-                        <SelectionListWithModal
-                            data={filteredDistanceRatesList}
-                            ListItem={TableListItem}
-                            onSelectRow={openRateDetails}
-                            onSelectionButtonPress={toggleRate}
-                            selectedItems={selectedDistanceRates}
-                            customListHeader={getCustomListHeader()}
-                            onTurnOnSelectionMode={(item) => item && canWriteDistanceRates && toggleRate(item)}
-                            onSelectAll={canWriteDistanceRates && filteredDistanceRatesList.length > 0 ? toggleAllRates : undefined}
-                            shouldPreventDefaultFocusOnSelectRow={!canUseTouchScreen()}
-                            customListHeaderContent={headerContent}
-                            canSelectMultiple={canSelectMultiple}
-                            selectAllAccessibilityLabel={translate('accessibilityHints.selectAllDistanceRates')}
-                            onDismissError={dismissError}
-                            shouldShowListEmptyContent={false}
-                            showScrollIndicator={false}
-                            turnOnSelectionModeOnLongPress={canWriteDistanceRates}
-                            shouldHeaderBeInsideList
-                            shouldShowRightCaret
-                        />
-                    ))}
+                    </>
+                )}
             </ScreenWrapper>
         </AccessOrNotFoundWrapper>
     );
diff --git a/src/styles/variables.ts b/src/styles/variables.ts
index 0e9eaee8ec44..4f7043f0d272 100644
--- a/src/styles/variables.ts
+++ b/src/styles/variables.ts
@@ -135,6 +135,7 @@ export default {
     tableGroupRowHeight: 36,
     tableSkeletonHeight: 32,
     tableCheckboxColumnWidth: 20,
+    tableStatusColumnWidth: 60,
     tableSwitchColumnWidth: 58,
     tableCaretColumnWidth: 20,
     domainTableActionColumnWidth: 64,

From 8eecdb40cb270d88e5c8d933a04364a6d5a7c525 Mon Sep 17 00:00:00 2001
From: krishna2323 <belivethatkg@gmail.com>
Date: Wed, 10 Jun 2026 04:47:58 +0530
Subject: [PATCH 243/435] Use StatusBadge for distance rate status column with
 themed colors

Signed-off-by: krishna2323 <belivethatkg@gmail.com>
---
 .../WorkspaceDistanceRatesTableRow.tsx        | 32 ++++++++++++++++---
 1 file changed, 27 insertions(+), 5 deletions(-)

diff --git a/src/components/Tables/WorkspaceDistanceRatesTable/WorkspaceDistanceRatesTableRow.tsx b/src/components/Tables/WorkspaceDistanceRatesTable/WorkspaceDistanceRatesTableRow.tsx
index a3c070995746..42c7ddcfaa55 100644
--- a/src/components/Tables/WorkspaceDistanceRatesTable/WorkspaceDistanceRatesTableRow.tsx
+++ b/src/components/Tables/WorkspaceDistanceRatesTable/WorkspaceDistanceRatesTableRow.tsx
@@ -1,7 +1,9 @@
 import {format, parseISO} from 'date-fns';
-import React from 'react';
+import React, {useMemo} from 'react';
+import type {ColorValue} from 'react-native';
 import {View} from 'react-native';
 import Icon from '@components/Icon';
+import StatusBadge from '@components/StatusBadge';
 import Switch from '@components/Switch';
 import Table from '@components/Table';
 import type {TableData} from '@components/Table';
@@ -43,6 +45,23 @@ function formatDateColumn(dateString: string | null | undefined): string {
     return format(parseISO(dateString), CONST.DATE.MONTH_DAY_YEAR_FORMAT);
 }
 
+function useRateStatusColors(status: string): {backgroundColor: ColorValue; textColor: ColorValue} {
+    const theme = useTheme();
+    return useMemo(() => {
+        switch (status) {
+            case CONST.CUSTOM_UNITS.RATE_STATUS.ACTIVE:
+                return theme.reportStatusBadge.paid;
+            case CONST.CUSTOM_UNITS.RATE_STATUS.FUTURE:
+                return theme.reportStatusBadge.draft;
+            case CONST.CUSTOM_UNITS.RATE_STATUS.EXPIRED:
+                return theme.reportStatusBadge.outstanding;
+            case CONST.CUSTOM_UNITS.RATE_STATUS.INACTIVE:
+            default:
+                return {backgroundColor: theme.badgeDefaultBG, textColor: theme.text};
+        }
+    }, [status, theme]);
+}
+
 function WorkspaceDistanceRatesTableRow({item, rowIndex, shouldUseNarrowTableLayout, statusLabels}: WorkspaceDistanceRatesTableRowProps) {
     const theme = useTheme();
     const styles = useThemeStyles();
@@ -52,6 +71,7 @@ function WorkspaceDistanceRatesTableRow({item, rowIndex, shouldUseNarrowTableLay
     const isDeleting = pendingAction === CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE;
 
     const status = getRateStatus(rate);
+    const statusColors = useRateStatusColors(status);
 
     const reasonAttributes: SkeletonSpanReasonAttributes = {
         context: 'WorkspaceDistanceRatesTableItem',
@@ -70,15 +90,17 @@ function WorkspaceDistanceRatesTableRow({item, rowIndex, shouldUseNarrowTableLay
         >
             {({hovered}) => (
                 <>
-                    <View style={[styles.flex1]}>
-                        <TextWithTooltip
+                    <View style={[styles.justifyContentCenter]}>
+                        <StatusBadge
                             text={statusLabels[status] ?? ''}
-                            style={[styles.optionDisplayName, styles.pre]}
+                            backgroundColor={statusColors.backgroundColor}
+                            textColor={statusColors.textColor}
+                            badgeStyles={styles.alignSelfStart}
                         />
                         {shouldUseNarrowTableLayout && (
                             <TextWithTooltip
                                 text={`${rate.name ?? ''} · ${formattedRate}`}
-                                style={[styles.textLabelSupporting, styles.lh16, styles.pre]}
+                                style={[styles.textLabelSupporting, styles.lh16, styles.pre, styles.mt1]}
                             />
                         )}
                     </View>

From bfc74dd0c91b2b11fe40b0da7393ac93327961b6 Mon Sep 17 00:00:00 2001
From: krishna2323 <belivethatkg@gmail.com>
Date: Wed, 10 Jun 2026 04:55:39 +0530
Subject: [PATCH 244/435] Use StatusBadge with themed colors for distance rate
 status column

Signed-off-by: krishna2323 <belivethatkg@gmail.com>
---
 .../WorkspaceDistanceRatesTableRow.tsx                    | 1 -
 .../Tables/WorkspaceDistanceRatesTable/index.tsx          | 8 +++++++-
 src/styles/variables.ts                                   | 2 +-
 3 files changed, 8 insertions(+), 3 deletions(-)

diff --git a/src/components/Tables/WorkspaceDistanceRatesTable/WorkspaceDistanceRatesTableRow.tsx b/src/components/Tables/WorkspaceDistanceRatesTable/WorkspaceDistanceRatesTableRow.tsx
index 42c7ddcfaa55..17d09cffb159 100644
--- a/src/components/Tables/WorkspaceDistanceRatesTable/WorkspaceDistanceRatesTableRow.tsx
+++ b/src/components/Tables/WorkspaceDistanceRatesTable/WorkspaceDistanceRatesTableRow.tsx
@@ -95,7 +95,6 @@ function WorkspaceDistanceRatesTableRow({item, rowIndex, shouldUseNarrowTableLay
                             text={statusLabels[status] ?? ''}
                             backgroundColor={statusColors.backgroundColor}
                             textColor={statusColors.textColor}
-                            badgeStyles={styles.alignSelfStart}
                         />
                         {shouldUseNarrowTableLayout && (
                             <TextWithTooltip
diff --git a/src/components/Tables/WorkspaceDistanceRatesTable/index.tsx b/src/components/Tables/WorkspaceDistanceRatesTable/index.tsx
index 60c775bb5146..7d607785a754 100644
--- a/src/components/Tables/WorkspaceDistanceRatesTable/index.tsx
+++ b/src/components/Tables/WorkspaceDistanceRatesTable/index.tsx
@@ -60,7 +60,13 @@ function WorkspaceDistanceRatesTable({
     const tableRef = useRef<TableHandle<DistanceRateTableItemData, DistanceRatesTableColumnKey>>(null);
 
     const columns: Array<TableColumn<DistanceRatesTableColumnKey>> = [
-        {key: 'status', label: translate('workspace.distanceRates.status'), sortable: true, width: variables.tableStatusColumnWidth},
+        {
+            key: 'status',
+            label: translate('workspace.distanceRates.status'),
+            sortable: true,
+            width: variables.tableStatusColumnWidth,
+            styling: {containerStyles: [styles.justifyContentCenter]},
+        },
         {key: 'name', label: translate('common.name'), sortable: true},
         {key: 'rate', label: translate('workspace.distanceRates.rate'), sortable: true},
         {key: 'startDate', label: translate('workspace.distanceRates.startDate'), sortable: true},
diff --git a/src/styles/variables.ts b/src/styles/variables.ts
index 4f7043f0d272..440983320d34 100644
--- a/src/styles/variables.ts
+++ b/src/styles/variables.ts
@@ -135,7 +135,7 @@ export default {
     tableGroupRowHeight: 36,
     tableSkeletonHeight: 32,
     tableCheckboxColumnWidth: 20,
-    tableStatusColumnWidth: 60,
+    tableStatusColumnWidth: 48,
     tableSwitchColumnWidth: 58,
     tableCaretColumnWidth: 20,
     domainTableActionColumnWidth: 64,

From 40e7552d534cf44b2150a55f872326dd031b77bd Mon Sep 17 00:00:00 2001
From: krishna2323 <belivethatkg@gmail.com>
Date: Wed, 10 Jun 2026 05:02:21 +0530
Subject: [PATCH 245/435] Use StatusBadge for distance rate status and update
 narrow layout

Signed-off-by: krishna2323 <belivethatkg@gmail.com>
---
 .../WorkspaceDistanceRatesTableRow.tsx        | 39 +++++++++++++------
 1 file changed, 28 insertions(+), 11 deletions(-)

diff --git a/src/components/Tables/WorkspaceDistanceRatesTable/WorkspaceDistanceRatesTableRow.tsx b/src/components/Tables/WorkspaceDistanceRatesTable/WorkspaceDistanceRatesTableRow.tsx
index 17d09cffb159..b26ec28a6aec 100644
--- a/src/components/Tables/WorkspaceDistanceRatesTable/WorkspaceDistanceRatesTableRow.tsx
+++ b/src/components/Tables/WorkspaceDistanceRatesTable/WorkspaceDistanceRatesTableRow.tsx
@@ -90,19 +90,36 @@ function WorkspaceDistanceRatesTableRow({item, rowIndex, shouldUseNarrowTableLay
         >
             {({hovered}) => (
                 <>
-                    <View style={[styles.justifyContentCenter]}>
-                        <StatusBadge
-                            text={statusLabels[status] ?? ''}
-                            backgroundColor={statusColors.backgroundColor}
-                            textColor={statusColors.textColor}
-                        />
-                        {shouldUseNarrowTableLayout && (
+                    {shouldUseNarrowTableLayout && (
+                        <View style={[styles.flex1, styles.justifyContentCenter]}>
                             <TextWithTooltip
-                                text={`${rate.name ?? ''} · ${formattedRate}`}
-                                style={[styles.textLabelSupporting, styles.lh16, styles.pre, styles.mt1]}
+                                text={rate.name ?? ''}
+                                style={[styles.optionDisplayName, styles.pre]}
                             />
-                        )}
-                    </View>
+                            <View style={[styles.flexRow, styles.alignItemsCenter, styles.mt1, styles.gap2]}>
+                                <StatusBadge
+                                    text={statusLabels[status] ?? ''}
+                                    backgroundColor={statusColors.backgroundColor}
+                                    textColor={statusColors.textColor}
+                                />
+                                <TextWithTooltip
+                                    text={[formattedRate, formatDateColumn(rate.startDate), formatDateColumn(rate.endDate)].filter(Boolean).join(' · ')}
+                                    numberOfLines={1}
+                                    style={[styles.textLabelSupporting, styles.lh16, styles.pre, styles.flexShrink1]}
+                                />
+                            </View>
+                        </View>
+                    )}
+
+                    {!shouldUseNarrowTableLayout && (
+                        <View style={[styles.justifyContentCenter]}>
+                            <StatusBadge
+                                text={statusLabels[status] ?? ''}
+                                backgroundColor={statusColors.backgroundColor}
+                                textColor={statusColors.textColor}
+                            />
+                        </View>
+                    )}
 
                     {!shouldUseNarrowTableLayout && (
                         <View style={[styles.flex1]}>

From 427022b1fbe0da36147e7a24b310cd5bc95aacc4 Mon Sep 17 00:00:00 2001
From: krishna2323 <belivethatkg@gmail.com>
Date: Wed, 10 Jun 2026 05:18:38 +0530
Subject: [PATCH 246/435] Use StatusBadge and shared getRateDateLabel for
 distance rate status and date display

Signed-off-by: krishna2323 <belivethatkg@gmail.com>
---
 .../WorkspaceDistanceRatesTableRow.tsx        | 14 +++++++----
 src/languages/de.ts                           |  3 +++
 src/languages/en.ts                           |  3 +++
 src/languages/es.ts                           |  3 +++
 src/languages/fr.ts                           |  4 ++-
 src/languages/it.ts                           |  3 +++
 src/languages/ja.ts                           |  3 +++
 src/languages/nl.ts                           |  3 +++
 src/languages/pl.ts                           |  3 +++
 src/languages/pt-BR.ts                        |  3 +++
 src/languages/zh-hans.ts                      |  3 +++
 src/libs/DistanceRequestUtils.ts              | 25 +++++++++++++++++++
 12 files changed, 64 insertions(+), 6 deletions(-)

diff --git a/src/components/Tables/WorkspaceDistanceRatesTable/WorkspaceDistanceRatesTableRow.tsx b/src/components/Tables/WorkspaceDistanceRatesTable/WorkspaceDistanceRatesTableRow.tsx
index b26ec28a6aec..6ee5166c2a39 100644
--- a/src/components/Tables/WorkspaceDistanceRatesTable/WorkspaceDistanceRatesTableRow.tsx
+++ b/src/components/Tables/WorkspaceDistanceRatesTable/WorkspaceDistanceRatesTableRow.tsx
@@ -9,8 +9,10 @@ import Table from '@components/Table';
 import type {TableData} from '@components/Table';
 import TextWithTooltip from '@components/TextWithTooltip';
 import {useMemoizedLazyExpensifyIcons} from '@hooks/useLazyAsset';
+import useLocalize from '@hooks/useLocalize';
 import useTheme from '@hooks/useTheme';
 import useThemeStyles from '@hooks/useThemeStyles';
+import DistanceRequestUtils from '@libs/DistanceRequestUtils';
 import {getRateStatus} from '@libs/PolicyDistanceRatesUtils';
 import type {SkeletonSpanReasonAttributes} from '@libs/telemetry/useSkeletonSpan';
 import variables from '@styles/variables';
@@ -38,11 +40,11 @@ type WorkspaceDistanceRatesTableRowProps = {
     statusLabels: Record<string, string>;
 };
 
-function formatDateColumn(dateString: string | null | undefined): string {
+function formatDate(dateString: string | null | undefined): string {
     if (!dateString) {
         return '';
     }
-    return format(parseISO(dateString), CONST.DATE.MONTH_DAY_YEAR_FORMAT);
+    return format(parseISO(dateString), CONST.DATE.MONTH_DAY_YEAR_ABBR_FORMAT);
 }
 
 function useRateStatusColors(status: string): {backgroundColor: ColorValue; textColor: ColorValue} {
@@ -65,6 +67,7 @@ function useRateStatusColors(status: string): {backgroundColor: ColorValue; text
 function WorkspaceDistanceRatesTableRow({item, rowIndex, shouldUseNarrowTableLayout, statusLabels}: WorkspaceDistanceRatesTableRowProps) {
     const theme = useTheme();
     const styles = useThemeStyles();
+    const {translate} = useLocalize();
     const Expensicons = useMemoizedLazyExpensifyIcons(['ArrowRight']);
 
     const {rate, formattedRate, pendingAction, errors} = item;
@@ -72,6 +75,7 @@ function WorkspaceDistanceRatesTableRow({item, rowIndex, shouldUseNarrowTableLay
 
     const status = getRateStatus(rate);
     const statusColors = useRateStatusColors(status);
+    const dateLabelText = DistanceRequestUtils.getRateDateLabel({...rate, unit: CONST.CUSTOM_UNITS.DISTANCE_UNIT_MILES}, translate);
 
     const reasonAttributes: SkeletonSpanReasonAttributes = {
         context: 'WorkspaceDistanceRatesTableItem',
@@ -103,7 +107,7 @@ function WorkspaceDistanceRatesTableRow({item, rowIndex, shouldUseNarrowTableLay
                                     textColor={statusColors.textColor}
                                 />
                                 <TextWithTooltip
-                                    text={[formattedRate, formatDateColumn(rate.startDate), formatDateColumn(rate.endDate)].filter(Boolean).join(' · ')}
+                                    text={[formattedRate, dateLabelText].filter(Boolean).join(` ${CONST.DOT_SEPARATOR} `)}
                                     numberOfLines={1}
                                     style={[styles.textLabelSupporting, styles.lh16, styles.pre, styles.flexShrink1]}
                                 />
@@ -145,7 +149,7 @@ function WorkspaceDistanceRatesTableRow({item, rowIndex, shouldUseNarrowTableLay
                         <View style={[styles.flex1]}>
                             <TextWithTooltip
                                 numberOfLines={1}
-                                text={formatDateColumn(rate.startDate)}
+                                text={formatDate(rate.startDate)}
                                 style={[styles.lh16, styles.optionDisplayName, styles.pre]}
                             />
                         </View>
@@ -155,7 +159,7 @@ function WorkspaceDistanceRatesTableRow({item, rowIndex, shouldUseNarrowTableLay
                         <View style={[styles.flex1]}>
                             <TextWithTooltip
                                 numberOfLines={1}
-                                text={formatDateColumn(rate.endDate)}
+                                text={formatDate(rate.endDate)}
                                 style={[styles.lh16, styles.optionDisplayName, styles.pre]}
                             />
                         </View>
diff --git a/src/languages/de.ts b/src/languages/de.ts
index f2f0b811f40e..d49ffadc36ce 100644
--- a/src/languages/de.ts
+++ b/src/languages/de.ts
@@ -1565,6 +1565,9 @@ const translations: TranslationDeepObject<typeof en> = {
         removed: 'entfernt',
         transactionPending: 'Transaktion ausstehend.',
         chooseARate: 'Wähle einen Rückerstattungssatz pro Meile oder Kilometer für den Workspace aus',
+        rateValidDateRange: ({startDate, endDate}: {startDate: string; endDate: string}) => `${startDate} bis ${endDate}`,
+        rateValidFrom: ({startDate}: {startDate: string}) => `Gültig ab ${startDate}`,
+        rateValidUntil: ({endDate}: {endDate: string}) => `Gültig bis ${endDate}`,
         unapprove: 'Genehmigung aufheben',
         unapproveReport: 'Bericht ablehnen',
         headsUp: 'Achtung!',
diff --git a/src/languages/en.ts b/src/languages/en.ts
index fb48ccc800dd..27fe5697339f 100644
--- a/src/languages/en.ts
+++ b/src/languages/en.ts
@@ -1625,6 +1625,9 @@ const translations = {
         removed: 'removed',
         transactionPending: 'Transaction pending.',
         chooseARate: 'Select a workspace reimbursement rate per mile or kilometer',
+        rateValidDateRange: ({startDate, endDate}: {startDate: string; endDate: string}) => `${startDate} to ${endDate}`,
+        rateValidFrom: ({startDate}: {startDate: string}) => `Valid from ${startDate}`,
+        rateValidUntil: ({endDate}: {endDate: string}) => `Valid until ${endDate}`,
         unapprove: 'Unapprove',
         unapproveReport: 'Unapprove report',
         headsUp: 'Heads up!',
diff --git a/src/languages/es.ts b/src/languages/es.ts
index cce95beb0b18..1469f6416268 100644
--- a/src/languages/es.ts
+++ b/src/languages/es.ts
@@ -1531,6 +1531,9 @@ const translations: TranslationDeepObject<typeof en> = {
         removed: 'eliminó',
         transactionPending: 'Transacción pendiente.',
         chooseARate: 'Selecciona una tasa de reembolso por milla o kilómetro para el espacio de trabajo',
+        rateValidDateRange: ({startDate, endDate}: {startDate: string; endDate: string}) => `${startDate} a ${endDate}`,
+        rateValidFrom: ({startDate}: {startDate: string}) => `Válido desde ${startDate}`,
+        rateValidUntil: ({endDate}: {endDate: string}) => `Válido hasta ${endDate}`,
         unapprove: 'Desaprobar',
         unapproveReport: 'Anular la aprobación del informe',
         headsUp: 'Atención!',
diff --git a/src/languages/fr.ts b/src/languages/fr.ts
index 6264820e731d..c32859be3bf5 100644
--- a/src/languages/fr.ts
+++ b/src/languages/fr.ts
@@ -1,7 +1,6 @@
 /**
  *   _____                      __         __
  *  / ___/__ ___  ___ _______ _/ /____ ___/ /
- * / (_ / -_) _ \/ -_) __/ _ \`/ __/ -_) _  /
  * \___/\__/_//_/\__/_/  \_,_/\__/\__/\_,_/
  *
  * This file was automatically generated. Please consider these alternatives before manually editing it:
@@ -1570,6 +1569,9 @@ const translations: TranslationDeepObject<typeof en> = {
         removed: 'supprimé',
         transactionPending: 'Transaction en attente.',
         chooseARate: 'Sélectionnez un taux de remboursement par mile ou kilomètre pour l’espace de travail',
+        rateValidDateRange: ({startDate, endDate}: {startDate: string; endDate: string}) => `${startDate} au ${endDate}`,
+        rateValidFrom: ({startDate}: {startDate: string}) => `Valide à partir du ${startDate}`,
+        rateValidUntil: ({endDate}: {endDate: string}) => `Valide jusqu’au ${endDate}`,
         unapprove: 'Annuler l’approbation',
         unapproveReport: 'Retirer l’approbation de la note de frais',
         headsUp: 'Attention !',
diff --git a/src/languages/it.ts b/src/languages/it.ts
index e66bad25d034..7d4d7d83e267 100644
--- a/src/languages/it.ts
+++ b/src/languages/it.ts
@@ -1564,6 +1564,9 @@ const translations: TranslationDeepObject<typeof en> = {
         removed: 'rimosso',
         transactionPending: 'Transazione in sospeso.',
         chooseARate: 'Seleziona una tariffa di rimborso per miglio o chilometro per lo spazio di lavoro',
+        rateValidDateRange: ({startDate, endDate}: {startDate: string; endDate: string}) => `${startDate} al ${endDate}`,
+        rateValidFrom: ({startDate}: {startDate: string}) => `Valido dal ${startDate}`,
+        rateValidUntil: ({endDate}: {endDate: string}) => `Valido fino al ${endDate}`,
         unapprove: 'Revoca approvazione',
         unapproveReport: 'Annulla approvazione rapporto',
         headsUp: 'Attenzione!',
diff --git a/src/languages/ja.ts b/src/languages/ja.ts
index 7b80100a123c..0d077ecf784b 100644
--- a/src/languages/ja.ts
+++ b/src/languages/ja.ts
@@ -1548,6 +1548,9 @@ const translations: TranslationDeepObject<typeof en> = {
         removed: '削除済み',
         transactionPending: '取引は保留中です。',
         chooseARate: 'ワークスペースの払い戻しレートをマイルまたはキロメートルごとに選択してください',
+        rateValidDateRange: ({startDate, endDate}: {startDate: string; endDate: string}) => `${startDate}から${endDate}まで有効`,
+        rateValidFrom: ({startDate}: {startDate: string}) => `${startDate}から有効`,
+        rateValidUntil: ({endDate}: {endDate: string}) => `${endDate}まで有効`,
         unapprove: '承認を取り消す',
         unapproveReport: 'レポートの承認を取り消す',
         headsUp: 'ご注意ください！',
diff --git a/src/languages/nl.ts b/src/languages/nl.ts
index 9fc65b00ffe5..a019dc0961ba 100644
--- a/src/languages/nl.ts
+++ b/src/languages/nl.ts
@@ -1560,6 +1560,9 @@ const translations: TranslationDeepObject<typeof en> = {
         removed: 'verwijderd',
         transactionPending: 'Transactie in behandeling.',
         chooseARate: 'Selecteer een workspace-vergoeding per mijl of kilometer',
+        rateValidDateRange: ({startDate, endDate}: {startDate: string; endDate: string}) => `${startDate} tot ${endDate}`,
+        rateValidFrom: ({startDate}: {startDate: string}) => `Geldig vanaf ${startDate}`,
+        rateValidUntil: ({endDate}: {endDate: string}) => `Geldig tot ${endDate}`,
         unapprove: 'Intrekken goedkeuring',
         unapproveReport: 'Goedkeuring rapport intrekken',
         headsUp: 'Let op!',
diff --git a/src/languages/pl.ts b/src/languages/pl.ts
index 9aae731a4390..756d71f4834b 100644
--- a/src/languages/pl.ts
+++ b/src/languages/pl.ts
@@ -1559,6 +1559,9 @@ const translations: TranslationDeepObject<typeof en> = {
         removed: 'usunięto',
         transactionPending: 'Transakcja w toku.',
         chooseARate: 'Wybierz stawkę zwrotu kosztów za milę lub kilometr dla przestrzeni roboczej',
+        rateValidDateRange: ({startDate, endDate}: {startDate: string; endDate: string}) => `${startDate} do ${endDate}`,
+        rateValidFrom: ({startDate}: {startDate: string}) => `Ważne od ${startDate}`,
+        rateValidUntil: ({endDate}: {endDate: string}) => `Ważne do ${endDate}`,
         unapprove: 'Cofnij zatwierdzenie',
         unapproveReport: 'Cofnij zatwierdzenie raportu',
         headsUp: 'Uwaga!',
diff --git a/src/languages/pt-BR.ts b/src/languages/pt-BR.ts
index 803b70de82d2..d48fbd3ddb68 100644
--- a/src/languages/pt-BR.ts
+++ b/src/languages/pt-BR.ts
@@ -1558,6 +1558,9 @@ const translations: TranslationDeepObject<typeof en> = {
         removed: 'removido',
         transactionPending: 'Transação pendente.',
         chooseARate: 'Selecione uma taxa de reembolso do espaço de trabalho por milha ou quilômetro',
+        rateValidDateRange: ({startDate, endDate}: {startDate: string; endDate: string}) => `${startDate} a ${endDate}`,
+        rateValidFrom: ({startDate}: {startDate: string}) => `Válido a partir de ${startDate}`,
+        rateValidUntil: ({endDate}: {endDate: string}) => `Válido até ${endDate}`,
         unapprove: 'Reprovar',
         unapproveReport: 'Rejeitar relatório',
         headsUp: 'Atenção!',
diff --git a/src/languages/zh-hans.ts b/src/languages/zh-hans.ts
index 926083c1f2e6..da09653bea09 100644
--- a/src/languages/zh-hans.ts
+++ b/src/languages/zh-hans.ts
@@ -1515,6 +1515,9 @@ const translations: TranslationDeepObject<typeof en> = {
         removed: '已移除',
         transactionPending: '交易处理中。',
         chooseARate: '选择工作区每英里或每公里的报销费率',
+        rateValidDateRange: ({startDate, endDate}: {startDate: string; endDate: string}) => `${startDate} 至 ${endDate}`,
+        rateValidFrom: ({startDate}: {startDate: string}) => `有效期自 ${startDate}`,
+        rateValidUntil: ({endDate}: {endDate: string}) => `有效期至 ${endDate}`,
         unapprove: '取消批准',
         unapproveReport: '取消批准报销单',
         headsUp: '注意！',
diff --git a/src/libs/DistanceRequestUtils.ts b/src/libs/DistanceRequestUtils.ts
index b08017bf6e62..81d0f5948104 100644
--- a/src/libs/DistanceRequestUtils.ts
+++ b/src/libs/DistanceRequestUtils.ts
@@ -1,3 +1,4 @@
+import {format, parseISO} from 'date-fns';
 import type {OnyxCollection, OnyxEntry} from 'react-native-onyx';
 import Onyx from 'react-native-onyx';
 import type {CurrencyListActionsContextType} from '@components/CurrencyListContextProvider';
@@ -639,6 +640,29 @@ function prepareTextForDisplay(text: string): string {
     return text.replaceAll(/[^0-9., ]/g, '').replace(/^0+(?=\d)/, '');
 }
 
+function getRateDateLabel(rate: MileageRate, translate: LocaleContextProps['translate']): string {
+    const dateFormat = CONST.DATE.MONTH_DAY_YEAR_ABBR_FORMAT;
+
+    try {
+        if (rate.startDate && rate.endDate) {
+            return translate('iou.rateValidDateRange', {
+                startDate: format(parseISO(rate.startDate), dateFormat),
+                endDate: format(parseISO(rate.endDate), dateFormat),
+            });
+        }
+        if (rate.startDate) {
+            return translate('iou.rateValidFrom', {startDate: format(parseISO(rate.startDate), dateFormat)});
+        }
+        if (rate.endDate) {
+            return translate('iou.rateValidUntil', {endDate: format(parseISO(rate.endDate), dateFormat)});
+        }
+    } catch {
+        return '';
+    }
+
+    return '';
+}
+
 export default {
     getDefaultMileageRate,
     getDistanceMerchant,
@@ -663,6 +687,7 @@ export default {
     prepareTextForDisplay,
     isRateEligibleForDate,
     getBestEligibleRate,
+    getRateDateLabel,
 };
 
 export type {MileageRate};

From 45570b339e4cc215ee155f8b44a6e1bf07bee209 Mon Sep 17 00:00:00 2001
From: krishna2323 <belivethatkg@gmail.com>
Date: Wed, 10 Jun 2026 05:22:49 +0530
Subject: [PATCH 247/435] fix knip check.

Signed-off-by: krishna2323 <belivethatkg@gmail.com>
---
 src/components/Tables/WorkspaceDistanceRatesTable/index.tsx | 1 -
 1 file changed, 1 deletion(-)

diff --git a/src/components/Tables/WorkspaceDistanceRatesTable/index.tsx b/src/components/Tables/WorkspaceDistanceRatesTable/index.tsx
index 7d607785a754..a4b67d42f699 100644
--- a/src/components/Tables/WorkspaceDistanceRatesTable/index.tsx
+++ b/src/components/Tables/WorkspaceDistanceRatesTable/index.tsx
@@ -222,4 +222,3 @@ function WorkspaceDistanceRatesTable({
 }
 
 export default WorkspaceDistanceRatesTable;
-export type {DistanceRateTableItemData, DistanceRatesTableColumnKey};

From 42da6c4f8b30e28477edbc5568b8cd2ccf805cb9 Mon Sep 17 00:00:00 2001
From: Rayane <77965000+rayane-d@users.noreply.github.com>
Date: Wed, 10 Jun 2026 01:02:53 +0100
Subject: [PATCH 248/435] Bump eslint-seatbelt baseline for category-tax-rate
 type assertions, we do not refactor them to stay consistent with the
 identical pattern used by every sibling change-log getter

---
 config/eslint/eslint.seatbelt.tsv | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/config/eslint/eslint.seatbelt.tsv b/config/eslint/eslint.seatbelt.tsv
index dd8ac0e99af4..0112396379be 100644
--- a/config/eslint/eslint.seatbelt.tsv
+++ b/config/eslint/eslint.seatbelt.tsv
@@ -760,7 +760,7 @@
 "../../src/libs/ReportActionItemEventHandler/index.android.ts"	"@typescript-eslint/no-deprecated/InteractionManager.runAfterInteractions"	1
 "../../src/libs/ReportActionsUtils.ts"	"@typescript-eslint/no-deprecated/reportAction.sequenceNumber"	1
 "../../src/libs/ReportActionsUtils.ts"	"@typescript-eslint/no-deprecated/reportAction?.originalMessage"	2
-"../../src/libs/ReportActionsUtils.ts"	"@typescript-eslint/no-unsafe-type-assertion"	110
+"../../src/libs/ReportActionsUtils.ts"	"@typescript-eslint/no-unsafe-type-assertion"	111
 "../../src/libs/ReportActionsUtils.ts"	"rulesdir/no-onyx-connect"	3
 "../../src/libs/ReportNameUtils.ts"	"@typescript-eslint/no-deprecated/translateLocal"	12
 "../../src/libs/ReportNameUtils.ts"	"@typescript-eslint/no-unsafe-type-assertion"	2
@@ -1828,7 +1828,7 @@
 "../../tests/unit/ReportActionsListPaddingViewTest.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	4
 "../../tests/unit/ReportActionsUtilsTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	35
 "../../tests/unit/ReportLayoutUtilsTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	1
-"../../tests/unit/ReportNameUtilsTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	22
+"../../tests/unit/ReportNameUtilsTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	23
 "../../tests/unit/ReportPrimaryActionUtilsTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	168
 "../../tests/unit/ReportSecondaryActionUtilsTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	450
 "../../tests/unit/ReportSubmitUtilsTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	1

From 77d6d3f7b5363550ae55b2b59259ebbffd1df365 Mon Sep 17 00:00:00 2001
From: krishna2323 <belivethatkg@gmail.com>
Date: Wed, 10 Jun 2026 05:33:19 +0530
Subject: [PATCH 249/435] Fix row sentryLabel, selection cleanup, tax pending
 fields, accessibility, and formatDate safety

Signed-off-by: krishna2323 <belivethatkg@gmail.com>
---
 src/CONST/index.ts                                |  1 +
 .../WorkspaceDistanceRatesTableRow.tsx            | 11 +++++++++--
 .../Tables/WorkspaceDistanceRatesTable/index.tsx  |  2 ++
 .../distanceRates/PolicyDistanceRatesPage.tsx     | 15 +++++++++++++++
 4 files changed, 27 insertions(+), 2 deletions(-)

diff --git a/src/CONST/index.ts b/src/CONST/index.ts
index 54ea4b5ff368..2e79e3016b97 100644
--- a/src/CONST/index.ts
+++ b/src/CONST/index.ts
@@ -9127,6 +9127,7 @@ const CONST = {
                 BULK_ACTIONS_DROPDOWN: 'WorkspaceTaxes-BulkActionsDropdown',
             },
             DISTANCE_RATES: {
+                ROW: 'WorkspaceDistanceRates-Row',
                 ADD_BUTTON: 'WorkspaceDistanceRates-AddButton',
                 MORE_DROPDOWN: 'WorkspaceDistanceRates-MoreDropdown',
                 BULK_ACTIONS_DROPDOWN: 'WorkspaceDistanceRates-BulkActionsDropdown',
diff --git a/src/components/Tables/WorkspaceDistanceRatesTable/WorkspaceDistanceRatesTableRow.tsx b/src/components/Tables/WorkspaceDistanceRatesTable/WorkspaceDistanceRatesTableRow.tsx
index 6ee5166c2a39..72f997695ba7 100644
--- a/src/components/Tables/WorkspaceDistanceRatesTable/WorkspaceDistanceRatesTableRow.tsx
+++ b/src/components/Tables/WorkspaceDistanceRatesTable/WorkspaceDistanceRatesTableRow.tsx
@@ -44,7 +44,11 @@ function formatDate(dateString: string | null | undefined): string {
     if (!dateString) {
         return '';
     }
-    return format(parseISO(dateString), CONST.DATE.MONTH_DAY_YEAR_ABBR_FORMAT);
+    try {
+        return format(parseISO(dateString), CONST.DATE.MONTH_DAY_YEAR_ABBR_FORMAT);
+    } catch {
+        return '';
+    }
 }
 
 function useRateStatusColors(status: string): {backgroundColor: ColorValue; textColor: ColorValue} {
@@ -77,6 +81,8 @@ function WorkspaceDistanceRatesTableRow({item, rowIndex, shouldUseNarrowTableLay
     const statusColors = useRateStatusColors(status);
     const dateLabelText = DistanceRequestUtils.getRateDateLabel({...rate, unit: CONST.CUSTOM_UNITS.DISTANCE_UNIT_MILES}, translate);
 
+    const accessibilityLabel = [rate.name, statusLabels[status], formattedRate, dateLabelText].filter(Boolean).join(', ');
+
     const reasonAttributes: SkeletonSpanReasonAttributes = {
         context: 'WorkspaceDistanceRatesTableItem',
         isDeleting,
@@ -87,8 +93,9 @@ function WorkspaceDistanceRatesTableRow({item, rowIndex, shouldUseNarrowTableLay
             interactive
             rowIndex={rowIndex}
             disabled={item.disabled}
+            accessibilityLabel={accessibilityLabel}
             skeletonReasonAttributes={reasonAttributes}
-            sentryLabel={CONST.SENTRY_LABEL.WORKSPACE.DISTANCE_RATES.ADD_BUTTON}
+            sentryLabel={CONST.SENTRY_LABEL.WORKSPACE.DISTANCE_RATES.ROW}
             offlineWithFeedback={{errors, pendingAction, dismissError: item.dismissError, shouldHideOnDelete: false}}
             onPress={item.action}
         >
diff --git a/src/components/Tables/WorkspaceDistanceRatesTable/index.tsx b/src/components/Tables/WorkspaceDistanceRatesTable/index.tsx
index a4b67d42f699..f0a5fbbb89db 100644
--- a/src/components/Tables/WorkspaceDistanceRatesTable/index.tsx
+++ b/src/components/Tables/WorkspaceDistanceRatesTable/index.tsx
@@ -83,6 +83,8 @@ function WorkspaceDistanceRatesTable({
                     rate.pendingFields?.rate ??
                     rate.pendingFields?.enabled ??
                     rate.pendingFields?.currency ??
+                    rate.pendingFields?.taxRateExternalID ??
+                    rate.pendingFields?.taxClaimablePercentage ??
                     rate.pendingFields?.name ??
                     pendingFields?.attributes ??
                     (pendingAction === CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD ? pendingAction : undefined);
diff --git a/src/pages/workspace/distanceRates/PolicyDistanceRatesPage.tsx b/src/pages/workspace/distanceRates/PolicyDistanceRatesPage.tsx
index 59a7843a1993..3a7da08422fd 100644
--- a/src/pages/workspace/distanceRates/PolicyDistanceRatesPage.tsx
+++ b/src/pages/workspace/distanceRates/PolicyDistanceRatesPage.tsx
@@ -11,6 +11,7 @@ import {ModalActions} from '@components/Modal/Global/ModalContext';
 import ScreenWrapper from '@components/ScreenWrapper';
 import WorkspaceDistanceRatesTable from '@components/Tables/WorkspaceDistanceRatesTable';
 import Text from '@components/Text';
+import useCleanupSelectedOptions from '@hooks/useCleanupSelectedOptions';
 import useConfirmModal from '@hooks/useConfirmModal';
 import useFilteredSelection from '@hooks/useFilteredSelection';
 import {useMemoizedLazyAsset, useMemoizedLazyExpensifyIcons} from '@hooks/useLazyAsset';
@@ -139,6 +140,20 @@ function PolicyDistanceRatesPage({
 
     const [selectedDistanceRates, setSelectedDistanceRates] = useFilteredSelection(selectableRates, filterRateSelection);
 
+    const clearTableSelection = useCallback(() => {
+        setSelectedDistanceRates((prev) => (prev.length > 0 ? [] : prev));
+    }, [setSelectedDistanceRates]);
+
+    useCleanupSelectedOptions(clearTableSelection);
+
+    useEffect(() => {
+        if (isMobileSelectionModeEnabled) {
+            return;
+        }
+
+        clearTableSelection();
+    }, [clearTableSelection, isMobileSelectionModeEnabled]);
+
     const canDisableOrDeleteSelectedRates = useMemo(
         () =>
             Object.keys(selectableRates)

From 23128f369d005614f3f4248f11738f8fbca03d1b Mon Sep 17 00:00:00 2001
From: krishna2323 <belivethatkg@gmail.com>
Date: Wed, 10 Jun 2026 05:36:41 +0530
Subject: [PATCH 250/435] Use local date instead of UTC for rate status
 comparison

Signed-off-by: krishna2323 <belivethatkg@gmail.com>
---
 src/libs/PolicyDistanceRatesUtils.ts | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/src/libs/PolicyDistanceRatesUtils.ts b/src/libs/PolicyDistanceRatesUtils.ts
index 16c01dc69c7f..abab94dfa2eb 100644
--- a/src/libs/PolicyDistanceRatesUtils.ts
+++ b/src/libs/PolicyDistanceRatesUtils.ts
@@ -176,7 +176,8 @@ function getRateStatus(rate: Rate): string {
         return CONST.CUSTOM_UNITS.RATE_STATUS.INACTIVE;
     }
 
-    const now = new Date().toISOString().slice(0, 10);
+    const today = new Date();
+    const now = `${today.getFullYear()}-${String(today.getMonth() + 1).padStart(2, '0')}-${String(today.getDate()).padStart(2, '0')}`;
 
     if (rate.startDate && rate.startDate > now) {
         return CONST.CUSTOM_UNITS.RATE_STATUS.FUTURE;

From 9f3fef213ac1d34faa3e06f89457ec13295061d7 Mon Sep 17 00:00:00 2001
From: krishna2323 <belivethatkg@gmail.com>
Date: Wed, 10 Jun 2026 06:28:14 +0530
Subject: [PATCH 251/435] Increase status column width to 56px

Signed-off-by: krishna2323 <belivethatkg@gmail.com>
---
 src/styles/variables.ts | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/styles/variables.ts b/src/styles/variables.ts
index 440983320d34..e1e56abb11ef 100644
--- a/src/styles/variables.ts
+++ b/src/styles/variables.ts
@@ -135,7 +135,7 @@ export default {
     tableGroupRowHeight: 36,
     tableSkeletonHeight: 32,
     tableCheckboxColumnWidth: 20,
-    tableStatusColumnWidth: 48,
+    tableStatusColumnWidth: 56,
     tableSwitchColumnWidth: 58,
     tableCaretColumnWidth: 20,
     domainTableActionColumnWidth: 64,

From 0b700da0c88e219424cceead6d222a2310860b18 Mon Sep 17 00:00:00 2001
From: krishna2323 <belivethatkg@gmail.com>
Date: Wed, 10 Jun 2026 06:30:01 +0530
Subject: [PATCH 252/435] Fix narrow layout ref not resetting when page opens
 in narrow mode

Signed-off-by: krishna2323 <belivethatkg@gmail.com>
---
 src/components/Tables/WorkspaceDistanceRatesTable/index.tsx | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/src/components/Tables/WorkspaceDistanceRatesTable/index.tsx b/src/components/Tables/WorkspaceDistanceRatesTable/index.tsx
index f0a5fbbb89db..45308562284f 100644
--- a/src/components/Tables/WorkspaceDistanceRatesTable/index.tsx
+++ b/src/components/Tables/WorkspaceDistanceRatesTable/index.tsx
@@ -191,12 +191,14 @@ function WorkspaceDistanceRatesTable({
             return;
         }
 
-        if (!activeSortingInWideLayout || !isNarrowLayoutRef.current) {
+        if (!isNarrowLayoutRef.current) {
             return;
         }
 
         isNarrowLayoutRef.current = false;
-        tableRef.current?.updateSorting(activeSortingInWideLayout);
+        if (activeSortingInWideLayout) {
+            tableRef.current?.updateSorting(activeSortingInWideLayout);
+        }
     }, [activeSortingInWideLayout, shouldUseNarrowTableLayout]);
 
     const shouldShowSearchBar = Object.keys(customUnitRates).length >= CONST.STANDARD_LIST_ITEM_LIMIT;

From 3fa797af53aa798dbeb29450c4e053e859dcaaba Mon Sep 17 00:00:00 2001
From: krishna2323 <belivethatkg@gmail.com>
Date: Wed, 10 Jun 2026 06:41:41 +0530
Subject: [PATCH 253/435] Keep table mounted when empty and revert
 tableRowHeightCompact to 72

Signed-off-by: krishna2323 <belivethatkg@gmail.com>
---
 .../Tables/WorkspaceDistanceRatesTable/index.tsx   | 14 +++++++++++---
 .../distanceRates/PolicyDistanceRatesPage.tsx      | 10 ++++++----
 src/styles/variables.ts                            |  2 +-
 3 files changed, 18 insertions(+), 8 deletions(-)

diff --git a/src/components/Tables/WorkspaceDistanceRatesTable/index.tsx b/src/components/Tables/WorkspaceDistanceRatesTable/index.tsx
index 45308562284f..2bb5e3533e1c 100644
--- a/src/components/Tables/WorkspaceDistanceRatesTable/index.tsx
+++ b/src/components/Tables/WorkspaceDistanceRatesTable/index.tsx
@@ -30,6 +30,7 @@ type WorkspaceDistanceRatesTableProps = {
     canDisableOrDeleteRate: (rateID: string) => boolean;
     pendingAction?: OnyxCommon.PendingAction;
     pendingFields?: OnyxCommon.PendingFields<string>;
+    EmptyStateComponent?: React.ReactElement;
 };
 
 const STATUS_ORDER: Record<string, number> = {
@@ -51,6 +52,7 @@ function WorkspaceDistanceRatesTable({
     canDisableOrDeleteRate,
     pendingAction,
     pendingFields,
+    EmptyStateComponent,
 }: WorkspaceDistanceRatesTableProps) {
     const styles = useThemeStyles();
     const {translate, localeCompare} = useLocalize();
@@ -201,6 +203,7 @@ function WorkspaceDistanceRatesTable({
         }
     }, [activeSortingInWideLayout, shouldUseNarrowTableLayout]);
 
+    const isEmpty = ratesData.length === 0;
     const shouldShowSearchBar = Object.keys(customUnitRates).length >= CONST.STANDARD_LIST_ITEM_LIMIT;
 
     return (
@@ -218,9 +221,14 @@ function WorkspaceDistanceRatesTable({
             initialSortColumn="name"
             title={translate('workspace.common.distanceRates')}
         >
-            {shouldShowSearchBar && <Table.SearchBar label={translate('workspace.distanceRates.findRate')} />}
-            <Table.Header />
-            <Table.Body contentContainerStyle={tableBodyContentContainerStyle} />
+            {isEmpty && EmptyStateComponent}
+            {!isEmpty && (
+                <>
+                    {shouldShowSearchBar && <Table.SearchBar label={translate('workspace.distanceRates.findRate')} />}
+                    <Table.Header />
+                    <Table.Body contentContainerStyle={tableBodyContentContainerStyle} />
+                </>
+            )}
         </Table>
     );
 }
diff --git a/src/pages/workspace/distanceRates/PolicyDistanceRatesPage.tsx b/src/pages/workspace/distanceRates/PolicyDistanceRatesPage.tsx
index 3a7da08422fd..5868b85a9026 100644
--- a/src/pages/workspace/distanceRates/PolicyDistanceRatesPage.tsx
+++ b/src/pages/workspace/distanceRates/PolicyDistanceRatesPage.tsx
@@ -436,11 +436,13 @@ function PolicyDistanceRatesPage({
                         reasonAttributes={reasonAttributes}
                     />
                 )}
-                {Object.values(customUnitRates).length > 0 && (
+                {!isLoading && (
                     <>
-                        <View style={[styles.ph5, styles.pb5, styles.pt3, shouldUseNarrowLayout ? styles.workspaceSectionMobile : styles.workspaceSection]}>
-                            <Text style={[styles.textNormal, styles.colorMuted]}>{translate('workspace.distanceRates.centrallyManage')}</Text>
-                        </View>
+                        {Object.values(customUnitRates).length > 0 && (
+                            <View style={[styles.ph5, styles.pb5, styles.pt3, shouldUseNarrowLayout ? styles.workspaceSectionMobile : styles.workspaceSection]}>
+                                <Text style={[styles.textNormal, styles.colorMuted]}>{translate('workspace.distanceRates.centrallyManage')}</Text>
+                            </View>
+                        )}
                         <WorkspaceDistanceRatesTable
                             customUnitRates={customUnitRates}
                             unitTranslation={unitTranslation}
diff --git a/src/styles/variables.ts b/src/styles/variables.ts
index e1e56abb11ef..60a17fe596aa 100644
--- a/src/styles/variables.ts
+++ b/src/styles/variables.ts
@@ -128,7 +128,7 @@ export default {
     optionRowHeightCompact: 52,
     tableHeaderContentHeight: 20,
     tableRowHeight: 56,
-    tableRowHeightCompact: 60,
+    tableRowHeightCompact: 72,
     tableRowPaddingVertical: 8,
     tableRowPaddingHorizontal: 12,
     tableGroupRowPaddingVertical: 4,

From be3b2b5d1958d2647613f5218913f02cd4cc2ae2 Mon Sep 17 00:00:00 2001
From: Rushat Gabhane <rushatgabhane@gmail.com>
Date: Wed, 10 Jun 2026 03:56:28 +0200
Subject: [PATCH 254/435] talkback focus

---
 src/components/DatePicker/index.tsx                   |  2 +-
 src/hooks/useAutoFocusInput.ts                        | 11 ++++++++---
 .../Accessibility/moveAccessibilityFocus/index.ts     |  2 +-
 .../Accessibility/moveAccessibilityFocus/types.ts     |  4 ++--
 4 files changed, 12 insertions(+), 7 deletions(-)

diff --git a/src/components/DatePicker/index.tsx b/src/components/DatePicker/index.tsx
index 01f0d72a8b71..a54830c016f3 100644
--- a/src/components/DatePicker/index.tsx
+++ b/src/components/DatePicker/index.tsx
@@ -56,7 +56,7 @@ function DatePicker({
     // picker was dismissed before it resolved.
     const openIntentRef = useRef(false);
 
-    const {inputCallbackRef: autoFocusCallbackRef, cancelAutoFocus} = useAutoFocusInput();
+    const {inputCallbackRef: autoFocusCallbackRef, cancelAutoFocus} = useAutoFocusInput(false, true);
     const autoFocusCallbackRefRef = useRef(autoFocusCallbackRef);
     autoFocusCallbackRefRef.current = autoFocusCallbackRef;
 
diff --git a/src/hooks/useAutoFocusInput.ts b/src/hooks/useAutoFocusInput.ts
index ea29b398cc03..956de0bb7673 100644
--- a/src/hooks/useAutoFocusInput.ts
+++ b/src/hooks/useAutoFocusInput.ts
@@ -25,7 +25,7 @@ type UseAutoFocusInput = {
     cancelAutoFocus: () => void;
 };
 
-export default function useAutoFocusInput(isMultiline = false): UseAutoFocusInput {
+export default function useAutoFocusInput(isMultiline = false, shouldMoveAccessibilityFocus = false): UseAutoFocusInput {
     const [isInputInitialized, setIsInputInitialized] = useState(false);
     const [isScreenTransitionEnded, setIsScreenTransitionEnded] = useState(false);
     const [modal] = useOnyx(ONYXKEYS.MODAL);
@@ -56,7 +56,7 @@ export default function useAutoFocusInput(isMultiline = false): UseAutoFocusInpu
 
     useEffect(() => {
         if (
-            isScreenReaderEnabled ||
+            (isScreenReaderEnabled && !shouldMoveAccessibilityFocus) ||
             !isScreenTransitionEnded ||
             !isInputInitialized ||
             !inputRef.current ||
@@ -67,6 +67,11 @@ export default function useAutoFocusInput(isMultiline = false): UseAutoFocusInpu
             return;
         }
         const focusTaskHandle = InteractionManager.runAfterInteractions(() => {
+            if (isScreenReaderEnabled) {
+                Accessibility.moveAccessibilityFocus(inputRef.current);
+                setIsScreenTransitionEnded(false);
+                return;
+            }
             if (inputRef.current && isMultiline) {
                 moveSelectionToEnd(inputRef.current);
             }
@@ -95,7 +100,7 @@ export default function useAutoFocusInput(isMultiline = false): UseAutoFocusInpu
         return () => {
             focusTaskHandle.cancel();
         };
-    }, [isScreenReaderEnabled, isMultiline, isScreenTransitionEnded, isInputInitialized, splashScreenState, isPopoverVisible, isInLandscapeMode]);
+    }, [isScreenReaderEnabled, shouldMoveAccessibilityFocus, isMultiline, isScreenTransitionEnded, isInputInitialized, splashScreenState, isPopoverVisible, isInLandscapeMode]);
 
     useFocusEffect(
         useCallback(() => {
diff --git a/src/libs/Accessibility/moveAccessibilityFocus/index.ts b/src/libs/Accessibility/moveAccessibilityFocus/index.ts
index cafe1a216db3..c73e52bda726 100644
--- a/src/libs/Accessibility/moveAccessibilityFocus/index.ts
+++ b/src/libs/Accessibility/moveAccessibilityFocus/index.ts
@@ -1,7 +1,7 @@
 import type MoveAccessibilityFocus from './types';
 
 const moveAccessibilityFocus: MoveAccessibilityFocus = (ref) => {
-    if (!ref?.current) {
+    if (!ref || !('current' in ref) || !ref.current) {
         return;
     }
     ref.current.focus();
diff --git a/src/libs/Accessibility/moveAccessibilityFocus/types.ts b/src/libs/Accessibility/moveAccessibilityFocus/types.ts
index 6756bdd6f773..d6ef3207306a 100644
--- a/src/libs/Accessibility/moveAccessibilityFocus/types.ts
+++ b/src/libs/Accessibility/moveAccessibilityFocus/types.ts
@@ -1,6 +1,6 @@
 import type {ElementRef, RefObject} from 'react';
-import type {HostComponent} from 'react-native';
+import type {HostComponent, TextInput} from 'react-native';
 
-type MoveAccessibilityFocus = (ref?: ElementRef<HostComponent<unknown>> & RefObject<HTMLOrSVGElement>) => void;
+type MoveAccessibilityFocus = (ref?: (ElementRef<HostComponent<unknown>> & RefObject<HTMLOrSVGElement>) | TextInput | null) => void;
 
 export default MoveAccessibilityFocus;

From 9d9c8fcea0c2d0be8b84bfd290d628bbd429840a Mon Sep 17 00:00:00 2001
From: jayeshmangwani <jayeshmangwani@gmail.com>
Date: Wed, 10 Jun 2026 11:56:00 +0530
Subject: [PATCH 255/435] added shouldShowMarkAsDone check to
 DeferredActionCell and FloatingMessageCounter

---
 .../MoneyRequestReportActionsList.tsx         | 11 +++++++++-
 .../ActionCell/DeferredActionCell.tsx         | 22 ++++++++++++++++++-
 .../inbox/report/FloatingMessageCounter.tsx   | 18 +++++++++++++--
 src/pages/inbox/report/ReportActionsList.tsx  | 13 +++++++++++
 4 files changed, 60 insertions(+), 4 deletions(-)

diff --git a/src/components/MoneyRequestReportView/MoneyRequestReportActionsList.tsx b/src/components/MoneyRequestReportView/MoneyRequestReportActionsList.tsx
index 333261612976..bc19b0285efa 100644
--- a/src/components/MoneyRequestReportView/MoneyRequestReportActionsList.tsx
+++ b/src/components/MoneyRequestReportView/MoneyRequestReportActionsList.tsx
@@ -1,5 +1,6 @@
 /* eslint-disable rulesdir/prefer-early-return */
 import {useIsFocused, useRoute} from '@react-navigation/native';
+import {isTrackIntentUserSelector} from '@selectors/Onboarding';
 import isEmpty from 'lodash/isEmpty';
 import React, {useCallback, useContext, useEffect, useLayoutEffect, useMemo, useRef, useState} from 'react';
 import type {LayoutChangeEvent, ListRenderItemInfo, NativeScrollEvent, NativeSyntheticEvent} from 'react-native';
@@ -42,7 +43,7 @@ import {
     isReportActionVisible,
     wasMessageReceivedWhileOffline,
 } from '@libs/ReportActionsUtils';
-import {canUserPerformWriteAction, chatIncludesChronosWithID, getReportLastVisibleActionCreated, isHarvestCreatedExpenseReport, isUnread} from '@libs/ReportUtils';
+import {canUserPerformWriteAction, chatIncludesChronosWithID, getReportLastVisibleActionCreated, isHarvestCreatedExpenseReport, isUnread, shouldShowMarkAsDone} from '@libs/ReportUtils';
 import markOpenReportEnd from '@libs/telemetry/markOpenReportEnd';
 import type {SkeletonSpanReasonAttributes} from '@libs/telemetry/useSkeletonSpan';
 import Visibility from '@libs/Visibility';
@@ -656,6 +657,13 @@ function MoneyRequestReportActionsList({onLayout}: MoneyRequestReportListProps)
     if (!report) {
         return null;
     }
+    const [isTrackIntentUser] = useOnyx(ONYXKEYS.NVP_INTRO_SELECTED, {selector: isTrackIntentUserSelector});
+
+    const shouldUseMarkAsDoneCopy = shouldShowMarkAsDone({
+        policy,
+        report,
+        isTrackIntentUser,
+    });
 
     return (
         <View
@@ -672,6 +680,7 @@ function MoneyRequestReportActionsList({onLayout}: MoneyRequestReportListProps)
                     hasNewMessages={!!unreadMarkerReportActionID}
                     isActive={isFloatingMessageCounterVisible}
                     onClick={scrollToBottomAndMarkReportAsRead}
+                    isMarkAsDone={shouldUseMarkAsDoneCopy}
                 />
                 {/* Exactly one of these two branches is active at a time:
                     1. showEmptyState — genuinely empty report
diff --git a/src/components/Search/SearchList/ListItem/ActionCell/DeferredActionCell.tsx b/src/components/Search/SearchList/ListItem/ActionCell/DeferredActionCell.tsx
index a8687c6f60ae..85eca228b672 100644
--- a/src/components/Search/SearchList/ListItem/ActionCell/DeferredActionCell.tsx
+++ b/src/components/Search/SearchList/ListItem/ActionCell/DeferredActionCell.tsx
@@ -1,8 +1,13 @@
+import {isTrackIntentUserSelector} from '@selectors/Onboarding';
 import React, {useDeferredValue} from 'react';
 import Button from '@components/Button';
 import useLocalize from '@hooks/useLocalize';
+import useOnyx from '@hooks/useOnyx';
 import useThemeStyles from '@hooks/useThemeStyles';
+import getNonEmptyStringOnyxID from '@libs/getNonEmptyStringOnyxID';
+import {shouldShowMarkAsDone} from '@libs/ReportUtils';
 import CONST from '@src/CONST';
+import ONYXKEYS from '@src/ONYXKEYS';
 import ActionCell from '.';
 import type {ActionCellProps} from '.';
 import actionTranslationsMap from './actionTranslationsMap';
@@ -11,12 +16,27 @@ function DeferredActionCell(actionCellProps: ActionCellProps) {
     const styles = useThemeStyles();
     const {translate} = useLocalize();
     const shouldRender = useDeferredValue(true, false);
+    const [isTrackIntentUser] = useOnyx(ONYXKEYS.NVP_INTRO_SELECTED, {selector: isTrackIntentUserSelector});
+    const [actionCellPolicy] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY}${getNonEmptyStringOnyxID(actionCellProps.policyID)}`);
+    const [actionCellReport] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${getNonEmptyStringOnyxID(actionCellProps.reportID)}`);
 
     if (!shouldRender) {
         const action = actionCellProps.action ?? CONST.SEARCH.ACTION_TYPES.VIEW;
         const shouldUseViewAction = action === CONST.SEARCH.ACTION_TYPES.VIEW || action === CONST.SEARCH.ACTION_TYPES.PAID || action === CONST.SEARCH.ACTION_TYPES.DONE;
         const isSuccess = !shouldUseViewAction && action !== CONST.SEARCH.ACTION_TYPES.UNDELETE;
-        const text = shouldUseViewAction ? translate(actionTranslationsMap[CONST.SEARCH.ACTION_TYPES.VIEW]) : translate(actionTranslationsMap[action]);
+        let text: string;
+        if (shouldUseViewAction) {
+            text = translate(actionTranslationsMap[CONST.SEARCH.ACTION_TYPES.VIEW]);
+        } else {
+            const shouldUseMarkAsDone =
+                shouldShowMarkAsDone({
+                    isTrackIntentUser,
+                    report: actionCellReport,
+                    policy: actionCellPolicy,
+                }) && action === CONST.SEARCH.ACTION_TYPES.SUBMIT;
+
+            text = shouldUseMarkAsDone ? translate('common.done') : translate(actionTranslationsMap[action]);
+        }
 
         return (
             <Button
diff --git a/src/pages/inbox/report/FloatingMessageCounter.tsx b/src/pages/inbox/report/FloatingMessageCounter.tsx
index f75fe695fab5..69722fd0f575 100644
--- a/src/pages/inbox/report/FloatingMessageCounter.tsx
+++ b/src/pages/inbox/report/FloatingMessageCounter.tsx
@@ -6,6 +6,7 @@ import type {ValueOf} from 'type-fest';
 import Button from '@components/Button';
 import Icon from '@components/Icon';
 import Text from '@components/Text';
+import getActionBadgeText from '@components/utils/getActionBadgeText';
 import {useMemoizedLazyExpensifyIcons} from '@hooks/useLazyAsset';
 import useLocalize from '@hooks/useLocalize';
 import useTheme from '@hooks/useTheme';
@@ -83,12 +84,23 @@ type FloatingMessageCounterProps = {
 
     /** Callback when the action badge pill is clicked */
     onActionBadgePress?: () => void;
+
+    /** Whether to show "Mark as done" copy instead of "Submit" copy for track-intent users */
+    isMarkAsDone?: boolean;
 };
 
 const MARKER_INACTIVE_TRANSLATE_Y = -40;
 const MARKER_ACTIVE_TRANSLATE_Y = 10;
 
-function FloatingMessageCounter({isActive = false, onClick = () => {}, hasNewMessages, actionBadge, actionBadgeBrickRoadStatus, onActionBadgePress}: FloatingMessageCounterProps) {
+function FloatingMessageCounter({
+    isActive = false,
+    onClick = () => {},
+    hasNewMessages,
+    actionBadge,
+    actionBadgeBrickRoadStatus,
+    onActionBadgePress,
+    isMarkAsDone,
+}: FloatingMessageCounterProps) {
     const icons = useMemoizedLazyExpensifyIcons(['DownArrow', 'UpArrow']);
     const theme = useTheme();
     const styles = useThemeStyles();
@@ -123,6 +135,8 @@ function FloatingMessageCounter({isActive = false, onClick = () => {}, hasNewMes
         transform: [{translateY: translateY.get()}],
     }));
 
+    const actionBadgeText = getActionBadgeText(actionBadge, translate, isMarkAsDone);
+
     return (
         <Animated.View
             accessibilityHint={translate(shouldShowActionBadgePill ? 'accessibilityHints.scrollToActionBadgeTarget' : 'accessibilityHints.scrollToNewestMessages')}
@@ -137,7 +151,7 @@ function FloatingMessageCounter({isActive = false, onClick = () => {}, hasNewMes
                             onPress={onActionBadgePress}
                             icon={icons.UpArrow}
                             iconFill={theme.textLight}
-                            label={translate(`common.actionBadge.${actionBadge}`)}
+                            label={actionBadgeText}
                             textStyle={styles.textWhite}
                         />
                     ) : (
diff --git a/src/pages/inbox/report/ReportActionsList.tsx b/src/pages/inbox/report/ReportActionsList.tsx
index 0d3c6e578a33..4bb59cd2d6e7 100644
--- a/src/pages/inbox/report/ReportActionsList.tsx
+++ b/src/pages/inbox/report/ReportActionsList.tsx
@@ -1,4 +1,5 @@
 import {useRoute} from '@react-navigation/native';
+import {isTrackIntentUserSelector} from '@selectors/Onboarding';
 import type {ListRenderItemInfo} from '@shopify/flash-list';
 import React, {memo, useCallback, useContext, useEffect, useMemo, useRef, useState} from 'react';
 import type {LayoutChangeEvent, NativeScrollEvent, NativeSyntheticEvent} from 'react-native';
@@ -23,6 +24,7 @@ import useUnreadMarker from '@hooks/useUnreadMarker';
 import useWindowDimensions from '@hooks/useWindowDimensions';
 import {isSafari} from '@libs/Browser';
 import {isConsecutiveChronosAutomaticTimerAction} from '@libs/ChronosUtils';
+import getNonEmptyStringOnyxID from '@libs/getNonEmptyStringOnyxID';
 import durationHighlightItem from '@libs/Navigation/helpers/getDurationHighlightItem';
 import isSearchTopmostFullScreenRoute from '@libs/Navigation/helpers/isSearchTopmostFullScreenRoute';
 import Navigation from '@libs/Navigation/Navigation';
@@ -50,6 +52,7 @@ import {
     isIOUReport,
     isMoneyRequestReport,
     isTaskReport,
+    shouldShowMarkAsDone,
 } from '@libs/ReportUtils';
 import type {ReportsSplitNavigatorParamList} from '@navigation/types';
 import {useConciergeDraft, useConciergeDraftActions} from '@pages/inbox/ConciergeDraftContext';
@@ -189,6 +192,9 @@ function ReportActionsList({
     const [reportLoadingState] = useOnyx(`${ONYXKEYS.COLLECTION.RAM_ONLY_REPORT_LOADING_STATE}${report.reportID}`);
     const prevIsLoadingInitialReportActions = usePrevious(reportLoadingState?.isLoadingInitialReportActions);
     const [reportNameValuePairs] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT_NAME_VALUE_PAIRS}${report.reportID}`);
+    const [isTrackIntentUser] = useOnyx(ONYXKEYS.NVP_INTRO_SELECTED, {selector: isTrackIntentUserSelector});
+    const [policy] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY}${getNonEmptyStringOnyxID(report?.policyID)}`);
+
     const reportAttributesSelector = useCallback(
         (value: OnyxEntry<OnyxTypes.ReportAttributesDerivedValue>) => {
             const attrs = value?.reports?.[report.reportID];
@@ -688,6 +694,12 @@ function ReportActionsList({
         requestAnimationFrame(() => setShouldAutoscrollToBottom(false));
     }, [shouldFocusToTopOnMount, shouldAutoscrollToBottom, prevHasOnceLoadedReportActions, reportLoadingState?.hasOnceLoadedReportActions]);
 
+    const shouldUseMarkAsDoneCopy = shouldShowMarkAsDone({
+        policy,
+        report,
+        isTrackIntentUser,
+    });
+
     return (
         <>
             <FloatingMessageCounter
@@ -697,6 +709,7 @@ function ReportActionsList({
                 actionBadge={!isProduction && isActionBadgeAboveViewport ? reportAttributes?.actionBadge : undefined}
                 actionBadgeBrickRoadStatus={!isProduction && isActionBadgeAboveViewport ? reportAttributes?.brickRoadStatus : undefined}
                 onActionBadgePress={scrollToActionBadgeTarget}
+                isMarkAsDone={shouldUseMarkAsDoneCopy}
             />
             <ReportActionsListPaddingView
                 report={report}

From cd4ecaff9725a99ace63b9b80eb3a93fcaedfae4 Mon Sep 17 00:00:00 2001
From: jayeshmangwani <jayeshmangwani@gmail.com>
Date: Wed, 10 Jun 2026 12:02:15 +0530
Subject: [PATCH 256/435] revert Mobile-Expensify changes

---
 Mobile-Expensify | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Mobile-Expensify b/Mobile-Expensify
index 51d784194fc4..a45e4eb672dd 160000
--- a/Mobile-Expensify
+++ b/Mobile-Expensify
@@ -1 +1 @@
-Subproject commit 51d784194fc4d515be523c8d345cd9d88a1e7a29
+Subproject commit a45e4eb672dd52e0a860795943458d71b3345ebc

From a9330b1328f6036939b4ee360a1e1e1dc553e8a2 Mon Sep 17 00:00:00 2001
From: yuldashevyusuf <yusufdeveloper2903@gmail.com>
Date: Fri, 5 Jun 2026 16:30:42 +0500
Subject: [PATCH 257/435] fix: create workspace on Enter after selecting
 currency

Pressing Enter to pick a currency during workspace creation restored
focus to the currency menu-item button on the confirmation page. Because
a focused button disables the form's submit-on-Enter shortcut
(shouldDisableEnterShortcut), the next Enter re-activated that button and
re-opened the currency page in a loop instead of creating the workspace.

Call skipNextFocusRestore() on the selection path so no button is focused
on return, letting the form's pressOnEnter submit fire. The header Back
button still restores focus for accessibility. Mirrors the precedent in
IOURequestStepMerchant.

Fixes #92764

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
---
 src/pages/WorkspaceCurrencySelectionPage.tsx | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/src/pages/WorkspaceCurrencySelectionPage.tsx b/src/pages/WorkspaceCurrencySelectionPage.tsx
index d28c51ff8ad8..78d4e0859b2c 100644
--- a/src/pages/WorkspaceCurrencySelectionPage.tsx
+++ b/src/pages/WorkspaceCurrencySelectionPage.tsx
@@ -10,6 +10,7 @@ import useOnyx from '@hooks/useOnyx';
 import useThemeStyles from '@hooks/useThemeStyles';
 import {setWorkspaceConfirmationCurrency} from '@libs/actions/Policy/Policy';
 import Navigation from '@libs/Navigation/Navigation';
+import {skipNextFocusRestore} from '@libs/NavigationFocusReturn';
 import CONST from '@src/CONST';
 import ONYXKEYS from '@src/ONYXKEYS';
 import type {Route} from '@src/ROUTES';
@@ -39,6 +40,10 @@ function WorkspaceCurrencySelectionPage({route}: WorkspaceCurrencySelectionPageP
     const onSelect = useCallback(
         (option: CurrencyListItem) => {
             setWorkspaceConfirmationCurrency(option.currencyCode);
+            // After selecting, don't restore focus to the currency menu item on the confirmation page —
+            // a focused button suppresses the form's submit-on-Enter, so the next Enter would re-open this
+            // page instead of creating the workspace. The header Back button keeps the default focus restore.
+            skipNextFocusRestore();
             goBack();
         },
         [goBack],

From e0564310fa93609a10246e250b99a079d1b0833d Mon Sep 17 00:00:00 2001
From: jayeshmangwani <jayeshmangwani@gmail.com>
Date: Wed, 10 Jun 2026 14:18:14 +0530
Subject: [PATCH 258/435] fixed lint

---
 .../MoneyRequestReportView/MoneyRequestReportActionsList.tsx    | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/components/MoneyRequestReportView/MoneyRequestReportActionsList.tsx b/src/components/MoneyRequestReportView/MoneyRequestReportActionsList.tsx
index bc19b0285efa..db0495c0b480 100644
--- a/src/components/MoneyRequestReportView/MoneyRequestReportActionsList.tsx
+++ b/src/components/MoneyRequestReportView/MoneyRequestReportActionsList.tsx
@@ -149,6 +149,7 @@ function MoneyRequestReportActionsList({onLayout}: MoneyRequestReportListProps)
     const shouldShowHarvestCreatedAction = isHarvestCreatedExpenseReport(reportNameValuePairs?.origin, reportNameValuePairs?.originalID);
     const [enableScrollToEnd, setEnableScrollToEnd] = useState<boolean>(false);
     const [lastActionEventId, setLastActionEventId] = useState<string>('');
+    const [isTrackIntentUser] = useOnyx(ONYXKEYS.NVP_INTRO_SELECTED, {selector: isTrackIntentUserSelector});
 
     // We are reversing actions because in this View we are starting at the top and don't use Inverted list
     const visibleReportActions = useMemo(() => {
@@ -657,7 +658,6 @@ function MoneyRequestReportActionsList({onLayout}: MoneyRequestReportListProps)
     if (!report) {
         return null;
     }
-    const [isTrackIntentUser] = useOnyx(ONYXKEYS.NVP_INTRO_SELECTED, {selector: isTrackIntentUserSelector});
 
     const shouldUseMarkAsDoneCopy = shouldShowMarkAsDone({
         policy,

From 54899fd15353616a1653ba9edaba32a4baf3d839 Mon Sep 17 00:00:00 2001
From: war-in <war-in@users.noreply.github.com>
Date: Wed, 10 Jun 2026 10:53:28 +0200
Subject: [PATCH 259/435] chore: update Podfile.lock

---
 ios/Podfile.lock | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/ios/Podfile.lock b/ios/Podfile.lock
index f56a0a3c3c15..480cdc510747 100644
--- a/ios/Podfile.lock
+++ b/ios/Podfile.lock
@@ -4808,7 +4808,7 @@ SPEC CHECKSUMS:
   GTMAppAuth: f69bd07d68cd3b766125f7e072c45d7340dea0de
   GTMSessionFetcher: 5aea5ba6bd522a239e236100971f10cb71b96ab6
   GzipSwift: 893f3e48e597a1a4f62fafcb6514220fcf8287fa
-  hermes-engine: c57209f580d9916632aeb0aa3851b1b90b47859f
+  hermes-engine: a0c087309de5ae9b2297a2cd8acfa9c53de099ee
   libavif: 84bbb62fb232c3018d6f1bab79beea87e35de7b7
   libdav1d: 23581a4d8ec811ff171ed5e2e05cd27bad64c39f
   libwebp: 02b23773aedb6ff1fd38cec7a77b81414c6842a8

From 4202803c881de0bf28bd1700272848789b74b91e Mon Sep 17 00:00:00 2001
From: Abdelrahman Khattab <abzokhattab@gmail.com>
Date: Wed, 10 Jun 2026 11:10:56 +0200
Subject: [PATCH 260/435] Add ESLint guard nudging new isPaidGroupPolicy
 imports to isGroupPolicy

Adds a no-restricted-imports pattern flagging imports of isPaidGroupPolicy /
isPaidGroupPolicyExpenseReport from PolicyUtils/ReportUtils, pointing to
isGroupPolicy / isReportInGroupPolicy for feature gating. Existing usages are
grandfathered via eslint-seatbelt so only NEW imports fail, forcing a conscious
"is this really billing/paid-only?" decision and preventing free group plans
like Submit from being re-excluded.
---
 config/eslint/eslint.config.mjs   | 22 +++++++-
 config/eslint/eslint.seatbelt.tsv | 88 +++++++++++++++++++++++++++++++
 2 files changed, 109 insertions(+), 1 deletion(-)

diff --git a/config/eslint/eslint.config.mjs b/config/eslint/eslint.config.mjs
index f41e62edc95c..2667469bd17e 100644
--- a/config/eslint/eslint.config.mjs
+++ b/config/eslint/eslint.config.mjs
@@ -188,6 +188,26 @@ const restrictedReportNameImportPatterns = [
     },
 ];
 
+// `isPaidGroupPolicy` is BILLING/paid-only (Collect/Control). Existing usages are grandfathered via
+// eslint-seatbelt; this only flags NEW imports so they make a conscious choice: for workspace feature
+// gating (violations, report fields, workspace chat, report creation, expense-workspace usability) use
+// `isGroupPolicy` / `isReportInGroupPolicy` instead, otherwise free group plans like Submit (submit2026)
+// are wrongly excluded and access bugs return.
+const restrictedPaidGroupPolicyImportPatterns = [
+    {
+        group: ['**/PolicyUtils', '**/libs/PolicyUtils'],
+        importNames: ['isPaidGroupPolicy'],
+        message:
+            'isPaidGroupPolicy is billing/paid-only (Collect/Control). For workspace feature gating use isGroupPolicy so free group plans like Submit are not excluded. If this is genuinely a billing/paid-only check, keep it and disable this line with a reason.',
+    },
+    {
+        group: ['**/ReportUtils', '**/libs/ReportUtils'],
+        importNames: ['isPaidGroupPolicy', 'isPaidGroupPolicyExpenseReport'],
+        message:
+            'isPaidGroupPolicy / isPaidGroupPolicyExpenseReport are billing/paid-only. For feature gating use isReportInGroupPolicy / isGroupPolicyExpenseReport so Submit workspaces are not excluded. If this is genuinely billing/paid-only, keep it and disable this line with a reason.',
+    },
+];
+
 const config = defineConfig([
     expensifyConfig,
     typescriptEslint.configs.recommendedTypeChecked,
@@ -715,7 +735,7 @@ const config = defineConfig([
                 'error',
                 {
                     paths: restrictedImportPaths,
-                    patterns: [...restrictedImportPatterns, ...restrictedReportNameImportPatterns],
+                    patterns: [...restrictedImportPatterns, ...restrictedReportNameImportPatterns, ...restrictedPaidGroupPolicyImportPatterns],
                 },
             ],
         },
diff --git a/config/eslint/eslint.seatbelt.tsv b/config/eslint/eslint.seatbelt.tsv
index bd4f60383a83..dd2e1247d227 100644
--- a/config/eslint/eslint.seatbelt.tsv
+++ b/config/eslint/eslint.seatbelt.tsv
@@ -110,6 +110,7 @@
 "../../src/components/AvatarSelector.tsx"	"no-restricted-syntax"	2
 "../../src/components/AvatarWithImagePicker.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../src/components/AvatarWithImagePicker.tsx"	"react-hooks/set-state-in-effect"	2
+"../../src/components/BookTravelButton.tsx"	"no-restricted-imports"	1
 "../../src/components/Button/index.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	2
 "../../src/components/Button/validateSubmitShortcut/index.ts"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../src/components/ButtonComposed/Button.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	2
@@ -299,6 +300,7 @@
 "../../src/components/Navigation/NavigationTabBar/SearchTabButton.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../src/components/Navigation/NavigationTabBar/index.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	3
 "../../src/components/Navigation/QuickCreationActionsBar/index.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
+"../../src/components/Navigation/QuickCreationActionsBar/index.tsx"	"no-restricted-imports"	1
 "../../src/components/Navigation/TopLevelNavigationTabBar/index.tsx"	"react-hooks/set-state-in-effect"	1
 "../../src/components/NavigationDeferredMount.tsx"	"no-restricted-imports"	1
 "../../src/components/NumberWithSymbolForm.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
@@ -425,6 +427,7 @@
 "../../src/components/SelectionList/utils/getListboxRole/index.web.ts"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../src/components/SettlementButton/AnimatedSettlementButton.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../src/components/SettlementButton/index.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	11
+"../../src/components/SettlementButton/index.tsx"	"no-restricted-imports"	1
 "../../src/components/SidePanel/SidePanelOverlay.tsx"	"no-restricted-syntax"	1
 "../../src/components/SidePanel/SidePanelReport/index.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../src/components/SignInButtons/IconButton.tsx"	"no-restricted-syntax"	1
@@ -505,6 +508,7 @@
 "../../src/hooks/useAdvancedSearchFilters.ts"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../src/hooks/useAnimatedHighlightStyle/index.ts"	"react-hooks/set-state-in-effect"	2
 "../../src/hooks/useAssignCard.ts"	"@typescript-eslint/no-unsafe-type-assertion"	1
+"../../src/hooks/useAutoCreateTrackWorkspace.ts"	"no-restricted-imports"	1
 "../../src/hooks/useAutoFocusInput.ts"	"@typescript-eslint/no-deprecated/InteractionManager.runAfterInteractions"	1
 "../../src/hooks/useAutoUpdateTimezone.ts"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../src/hooks/useAutocompleteSuggestions.ts"	"@typescript-eslint/no-unsafe-type-assertion"	1
@@ -516,7 +520,9 @@
 "../../src/hooks/useCachedImageSource.ts"	"react-hooks/set-state-in-effect"	1
 "../../src/hooks/useCancellationType.ts"	"react-hooks/refs"	2
 "../../src/hooks/useCancellationType.ts"	"react-hooks/set-state-in-effect"	1
+"../../src/hooks/useCardFeedsForActivePolicies.ts"	"no-restricted-imports"	1
 "../../src/hooks/useCardFeedsForDisplay.ts"	"@typescript-eslint/no-unsafe-type-assertion"	1
+"../../src/hooks/useCardFeedsForDisplay.ts"	"no-restricted-imports"	1
 "../../src/hooks/useCreateReport.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../src/hooks/useDebounce.ts"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../src/hooks/useDebounceNonReactive.ts"	"@typescript-eslint/no-unsafe-type-assertion"	1
@@ -540,6 +546,7 @@
 "../../src/hooks/useInitial.ts"	"react-hooks/refs"	4
 "../../src/hooks/useIsBlockedToAddFeed.ts"	"react-hooks/set-state-in-effect"	1
 "../../src/hooks/useIsOwnWorkspaceChatRef.ts"	"react-hooks/refs"	2
+"../../src/hooks/useIsPaidPolicyAdmin.ts"	"no-restricted-imports"	1
 "../../src/hooks/useKeyboardShortcut.ts"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../src/hooks/useLazyAsset.ts"	"@typescript-eslint/no-unsafe-type-assertion"	5
 "../../src/hooks/useLazyAsset.ts"	"react-hooks/refs"	2
@@ -649,6 +656,7 @@
 "../../src/libs/Middleware/Pagination.ts"	"@typescript-eslint/no-unsafe-type-assertion"	5
 "../../src/libs/Middleware/SaveResponseInOnyx.ts"	"no-restricted-syntax"	1
 "../../src/libs/ModifiedExpenseMessage.ts"	"@typescript-eslint/no-unsafe-type-assertion"	6
+"../../src/libs/MoneyRequestReportUtils.ts"	"no-restricted-imports"	1
 "../../src/libs/Navigation/AppNavigator/AuthScreens.tsx"	"no-restricted-syntax"	1
 "../../src/libs/Navigation/AppNavigator/AuthScreensInitHandler.tsx"	"no-restricted-syntax"	6
 "../../src/libs/Navigation/AppNavigator/AuthScreensInitHandler.tsx"	"react-hooks/refs"	1
@@ -659,6 +667,7 @@
 "../../src/libs/Navigation/AppNavigator/KeyboardShortcutsHandler/ShortcutsOverviewHandler.tsx"	"no-restricted-syntax"	1
 "../../src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	5
 "../../src/libs/Navigation/AppNavigator/Navigators/Overlay/BaseOverlay.tsx"	"no-restricted-syntax"	2
+"../../src/libs/Navigation/AppNavigator/Navigators/ReportsSplitNavigator.tsx"	"no-restricted-imports"	1
 "../../src/libs/Navigation/AppNavigator/Navigators/ReportsSplitNavigator.tsx"	"no-restricted-syntax"	1
 "../../src/libs/Navigation/AppNavigator/Navigators/RightModalNavigator.tsx"	"@typescript-eslint/no-deprecated/InteractionManager.runAfterInteractions"	2
 "../../src/libs/Navigation/AppNavigator/Navigators/RightModalNavigator.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
@@ -727,6 +736,7 @@
 "../../src/libs/NextStepUtils.ts"	"@typescript-eslint/no-deprecated/buildNextStepNew"	2
 "../../src/libs/Notification/LocalNotification/BrowserNotifications.ts"	"@typescript-eslint/no-deprecated/translateLocal"	1
 "../../src/libs/Notification/LocalNotification/BrowserNotifications.ts"	"@typescript-eslint/no-unsafe-type-assertion"	1
+"../../src/libs/Notification/LocalNotification/BrowserNotifications.ts"	"no-restricted-imports"	1
 "../../src/libs/Notification/LocalNotification/BrowserNotifications.ts"	"no-restricted-syntax"	2
 "../../src/libs/Notification/PushNotification/parsePushNotificationPayload.ts"	"@typescript-eslint/no-unsafe-type-assertion"	5
 "../../src/libs/Notification/PushNotification/shouldShowPushNotification.ts"	"no-restricted-syntax"	2
@@ -764,6 +774,8 @@
 "../../src/libs/ReportActionsUtils.ts"	"rulesdir/no-onyx-connect"	3
 "../../src/libs/ReportNameUtils.ts"	"@typescript-eslint/no-deprecated/translateLocal"	12
 "../../src/libs/ReportNameUtils.ts"	"@typescript-eslint/no-unsafe-type-assertion"	2
+"../../src/libs/ReportPrimaryActionUtils.ts"	"no-restricted-imports"	1
+"../../src/libs/ReportSecondaryActionUtils.ts"	"no-restricted-imports"	1
 "../../src/libs/ReportTitleUtils.ts"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../src/libs/ReportUtils.ts"	"@typescript-eslint/no-deprecated/getPolicy"	29
 "../../src/libs/ReportUtils.ts"	"@typescript-eslint/no-deprecated/getReportName"	3
@@ -775,6 +787,7 @@
 "../../src/libs/SearchQueryUtils.ts"	"@typescript-eslint/no-unsafe-type-assertion"	73
 "../../src/libs/SearchUIUtils.ts"	"@typescript-eslint/no-deprecated/getSearchReportName"	1
 "../../src/libs/SearchUIUtils.ts"	"@typescript-eslint/no-unsafe-type-assertion"	71
+"../../src/libs/SearchUIUtils.ts"	"no-restricted-imports"	1
 "../../src/libs/SelectionScraper/index.ts"	"@typescript-eslint/no-unsafe-type-assertion"	4
 "../../src/libs/SidebarUtils.ts"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../src/libs/Sound/index.native.ts"	"@typescript-eslint/no-unsafe-type-assertion"	4
@@ -785,8 +798,10 @@
 "../../src/libs/StatusBar/types.ts"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../src/libs/StringUtils/index.ts"	"@typescript-eslint/no-unsafe-type-assertion"	2
 "../../src/libs/TransactionPreviewUtils.ts"	"@typescript-eslint/no-unsafe-type-assertion"	1
+"../../src/libs/TransactionPreviewUtils.ts"	"no-restricted-imports"	1
 "../../src/libs/TransactionUtils/index.ts"	"@typescript-eslint/no-deprecated/translateLocal"	5
 "../../src/libs/TransactionUtils/index.ts"	"@typescript-eslint/no-unsafe-type-assertion"	8
+"../../src/libs/UnreadIndicatorUpdater/index.ts"	"no-restricted-imports"	1
 "../../src/libs/UnreadIndicatorUpdater/index.ts"	"no-restricted-syntax"	1
 "../../src/libs/Url.ts"	"@typescript-eslint/no-unsafe-type-assertion"	3
 "../../src/libs/UserAvatarUtils.ts"	"@typescript-eslint/no-unsafe-type-assertion"	4
@@ -805,6 +820,7 @@
 "../../src/libs/actions/Chronos.ts"	"no-restricted-syntax"	1
 "../../src/libs/actions/ClearReportActionErrors.ts"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../src/libs/actions/CompanyCards.ts"	"@typescript-eslint/no-unsafe-type-assertion"	4
+"../../src/libs/actions/CompanyCards.ts"	"no-restricted-imports"	1
 "../../src/libs/actions/CompanyCards.ts"	"no-restricted-syntax"	5
 "../../src/libs/actions/Delegate.ts"	"no-restricted-syntax"	4
 "../../src/libs/actions/Domain.ts"	"@typescript-eslint/no-unsafe-type-assertion"	3
@@ -829,6 +845,7 @@
 "../../src/libs/actions/IOU/MoneyRequestBuilder.ts"	"@typescript-eslint/no-unsafe-type-assertion"	2
 "../../src/libs/actions/IOU/PayMoneyRequest.ts"	"@typescript-eslint/no-deprecated/buildNextStepNew"	3
 "../../src/libs/actions/IOU/PayMoneyRequest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	2
+"../../src/libs/actions/IOU/PayMoneyRequest.ts"	"no-restricted-imports"	1
 "../../src/libs/actions/IOU/PayMoneyRequest.ts"	"no-restricted-syntax"	1
 "../../src/libs/actions/IOU/PerDiem.ts"	"@typescript-eslint/no-deprecated/InteractionManager.runAfterInteractions"	2
 "../../src/libs/actions/IOU/PerDiem.ts"	"@typescript-eslint/no-deprecated/buildNextStepNew"	1
@@ -840,6 +857,7 @@
 "../../src/libs/actions/IOU/RejectMoneyRequest.ts"	"no-restricted-syntax"	1
 "../../src/libs/actions/IOU/ReportWorkflow.ts"	"@typescript-eslint/no-deprecated/buildNextStepNew"	7
 "../../src/libs/actions/IOU/ReportWorkflow.ts"	"@typescript-eslint/no-unsafe-type-assertion"	1
+"../../src/libs/actions/IOU/ReportWorkflow.ts"	"no-restricted-imports"	1
 "../../src/libs/actions/IOU/ReportWorkflow.ts"	"no-restricted-syntax"	1
 "../../src/libs/actions/IOU/SearchUpdate.ts"	"@typescript-eslint/no-unsafe-type-assertion"	2
 "../../src/libs/actions/IOU/SendInvoice.ts"	"@typescript-eslint/no-deprecated/InteractionManager.runAfterInteractions"	1
@@ -877,6 +895,7 @@
 "../../src/libs/actions/MergeAccounts.ts"	"no-restricted-syntax"	1
 "../../src/libs/actions/MergeTransaction.ts"	"@typescript-eslint/no-deprecated/getPolicyTagsData"	1
 "../../src/libs/actions/MergeTransaction.ts"	"@typescript-eslint/no-unsafe-type-assertion"	2
+"../../src/libs/actions/MergeTransaction.ts"	"no-restricted-imports"	1
 "../../src/libs/actions/MergeTransaction.ts"	"no-restricted-syntax"	1
 "../../src/libs/actions/OdometerTransactionUtils.ts"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../src/libs/actions/Onboarding.ts"	"no-restricted-syntax"	1
@@ -895,6 +914,7 @@
 "../../src/libs/actions/Policy/Category.ts"	"no-restricted-syntax"	5
 "../../src/libs/actions/Policy/DistanceRate.ts"	"no-restricted-syntax"	2
 "../../src/libs/actions/Policy/Member.ts"	"@typescript-eslint/no-unsafe-type-assertion"	2
+"../../src/libs/actions/Policy/Member.ts"	"no-restricted-imports"	1
 "../../src/libs/actions/Policy/Member.ts"	"no-restricted-syntax"	8
 "../../src/libs/actions/Policy/Member.ts"	"rulesdir/no-onyx-connect"	1
 "../../src/libs/actions/Policy/PerDiem.ts"	"no-restricted-syntax"	1
@@ -902,11 +922,14 @@
 "../../src/libs/actions/Policy/Policy.ts"	"@typescript-eslint/no-deprecated/buildNextStepNew"	1
 "../../src/libs/actions/Policy/Policy.ts"	"@typescript-eslint/no-deprecated/translateLocal"	1
 "../../src/libs/actions/Policy/Policy.ts"	"@typescript-eslint/no-unsafe-type-assertion"	8
+"../../src/libs/actions/Policy/Policy.ts"	"no-restricted-imports"	2
 "../../src/libs/actions/Policy/Policy.ts"	"no-restricted-syntax"	10
 "../../src/libs/actions/Policy/Policy.ts"	"rulesdir/no-onyx-connect"	3
+"../../src/libs/actions/Policy/ReportField.ts"	"no-restricted-imports"	1
 "../../src/libs/actions/Policy/ReportField.ts"	"no-restricted-syntax"	4
 "../../src/libs/actions/Policy/Rules.ts"	"no-restricted-syntax"	3
 "../../src/libs/actions/Policy/Tag.ts"	"@typescript-eslint/no-unsafe-type-assertion"	2
+"../../src/libs/actions/Policy/Tag.ts"	"no-restricted-imports"	1
 "../../src/libs/actions/Policy/Tag.ts"	"no-restricted-syntax"	4
 "../../src/libs/actions/Policy/Travel.ts"	"no-restricted-syntax"	2
 "../../src/libs/actions/PolicyConnections.ts"	"no-restricted-syntax"	1
@@ -937,6 +960,7 @@
 "../../src/libs/actions/Subscription.ts"	"no-restricted-syntax"	1
 "../../src/libs/actions/Tab.ts"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../src/libs/actions/Task.ts"	"@typescript-eslint/no-unsafe-type-assertion"	3
+"../../src/libs/actions/Task.ts"	"no-restricted-imports"	1
 "../../src/libs/actions/Task.ts"	"no-restricted-syntax"	7
 "../../src/libs/actions/TaxRate.ts"	"no-restricted-syntax"	1
 "../../src/libs/actions/TeachersUnite.ts"	"no-restricted-syntax"	1
@@ -949,6 +973,7 @@
 "../../src/libs/actions/TravelInvoicing.ts"	"no-restricted-syntax"	3
 "../../src/libs/actions/UnreportedExpenses.tsx"	"no-restricted-syntax"	1
 "../../src/libs/actions/User.ts"	"@typescript-eslint/no-unsafe-type-assertion"	5
+"../../src/libs/actions/User.ts"	"no-restricted-imports"	1
 "../../src/libs/actions/User.ts"	"no-restricted-syntax"	8
 "../../src/libs/actions/VacationDelegate.ts"	"no-restricted-syntax"	2
 "../../src/libs/actions/Wallet.ts"	"@typescript-eslint/no-unsafe-type-assertion"	4
@@ -966,8 +991,10 @@
 "../../src/libs/actions/connections/QuickbooksOnline.ts"	"no-restricted-syntax"	2
 "../../src/libs/actions/connections/SageIntacct.ts"	"no-restricted-syntax"	2
 "../../src/libs/actions/connections/Xero.ts"	"no-restricted-syntax"	2
+"../../src/libs/actions/connections/index.ts"	"no-restricted-imports"	1
 "../../src/libs/actions/connections/index.ts"	"no-restricted-syntax"	3
 "../../src/libs/actions/getCompanyCardBankConnection/index.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	4
+"../../src/libs/actions/getCompanyCardBankConnection/index.tsx"	"no-restricted-imports"	1
 "../../src/libs/actions/getCompanyCardBankConnection/index.tsx"	"no-restricted-syntax"	2
 "../../src/libs/actions/replaceOptimisticReportWithActualReport.ts"	"@typescript-eslint/no-deprecated/InteractionManager.runAfterInteractions"	1
 "../../src/libs/actions/replaceOptimisticReportWithActualReport.ts"	"@typescript-eslint/no-unsafe-type-assertion"	2
@@ -1037,10 +1064,14 @@
 "../../src/pages/MissingPersonalDetails/subPages/Address.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	5
 "../../src/pages/MissingPersonalDetails/subPages/Address.tsx"	"react-hooks/refs"	4
 "../../src/pages/MultifactorAuthentication/RevokePage.tsx"	"@typescript-eslint/no-deprecated/ConfirmModal"	1
+"../../src/pages/OnboardingAccounting/BaseOnboardingAccounting.tsx"	"no-restricted-imports"	1
 "../../src/pages/OnboardingInterestedFeatures/BaseOnboardingInterestedFeatures.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
+"../../src/pages/OnboardingInterestedFeatures/BaseOnboardingInterestedFeatures.tsx"	"no-restricted-imports"	1
 "../../src/pages/OnboardingInterestedFeatures/BaseOnboardingInterestedFeatures.tsx"	"react-hooks/preserve-manual-memoization"	2
 "../../src/pages/OnboardingPrivateDomain/BaseOnboardingPrivateDomain.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
+"../../src/pages/OnboardingWorkspaceConfirmation/BaseOnboardingWorkspaceConfirmation.tsx"	"no-restricted-imports"	1
 "../../src/pages/OnboardingWorkspaceCurrency/BaseOnboardingWorkspaceCurrency.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
+"../../src/pages/OnboardingWorkspaceOptional/BaseOnboardingWorkspaceOptional.tsx"	"no-restricted-imports"	1
 "../../src/pages/ProfilePage.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../src/pages/ReimbursementAccount/AddressFormFields.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	2
 "../../src/pages/ReimbursementAccount/EnterSignerInfo/index.tsx"	"@typescript-eslint/no-deprecated/useSubStep"	1
@@ -1074,6 +1105,7 @@
 "../../src/pages/ReimbursementAccount/USD/ConnectBankAccount/components/BankAccountValidationForm.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	2
 "../../src/pages/ReimbursementAccount/USD/USDVerifiedBankAccountFlowPage.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	3
 "../../src/pages/ReimbursementAccount/utils/getSubStepValues.ts"	"@typescript-eslint/no-unsafe-type-assertion"	4
+"../../src/pages/ReportDescriptionPage.tsx"	"no-restricted-imports"	1
 "../../src/pages/ReportDescriptionPage.tsx"	"no-restricted-syntax"	1
 "../../src/pages/ReportParticipantDetailsPage.tsx"	"@typescript-eslint/no-deprecated/ConfirmModal"	1
 "../../src/pages/ReportParticipantDetailsPage.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
@@ -1104,6 +1136,7 @@
 "../../src/pages/ShareCodePage.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	2
 "../../src/pages/TeachersUnite/SaveTheWorldPage.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../src/pages/TransactionDuplicate/Confirmation.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
+"../../src/pages/TransactionDuplicate/Confirmation.tsx"	"no-restricted-imports"	1
 "../../src/pages/TransactionDuplicate/Confirmation.tsx"	"react-hooks/refs"	12
 "../../src/pages/TransactionDuplicate/DuplicateTransactionItem.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	2
 "../../src/pages/TransactionMerge/ConfirmationPage.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
@@ -1111,6 +1144,7 @@
 "../../src/pages/TransactionMerge/MergeTransactionItem.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../src/pages/TransactionMerge/MergeTransactionsListContent.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../src/pages/Travel/DynamicTravelTerms.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
+"../../src/pages/Travel/DynamicTravelUpgrade.tsx"	"no-restricted-imports"	1
 "../../src/pages/Travel/TravelUpgrade.tsx"	"react-hooks/set-state-in-effect"	1
 "../../src/pages/Travel/WorkspaceConfirmationForTravelPage.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	2
 "../../src/pages/UnreportedExpenseListItem.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
@@ -1119,9 +1153,11 @@
 "../../src/pages/domain/Saml/SamlLoginSectionContent.tsx"	"@typescript-eslint/no-deprecated/ConfirmModal"	1
 "../../src/pages/home/ForYouSection/EmptyState.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../src/pages/home/GettingStartedSection/hooks/useGettingStartedItems.ts"	"@typescript-eslint/no-unsafe-type-assertion"	1
+"../../src/pages/home/GettingStartedSection/hooks/useGettingStartedItems.ts"	"no-restricted-imports"	1
 "../../src/pages/home/SpendOverTimeSection/useSpendOverTimeData.ts"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../src/pages/home/TimeSensitiveSection/index.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../src/pages/home/TimeSensitiveSection/items/FixCompanyCardConnection.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	2
+"../../src/pages/home/YourSpendSection/useYourSpendData.ts"	"no-restricted-imports"	1
 "../../src/pages/inbox/DeleteTransactionNavigateBackHandler.tsx"	"no-restricted-imports"	1
 "../../src/pages/inbox/ReactionListWrapper.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../src/pages/inbox/ReportFetchHandler.tsx"	"@typescript-eslint/no-deprecated/InteractionManager.runAfterInteractions"	2
@@ -1175,6 +1211,7 @@
 "../../src/pages/inbox/sidebar/FABPopoverContent/menuItems/InvoiceMenuItem.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../src/pages/inbox/sidebar/FABPopoverContent/menuItems/NewWorkspaceMenuItem.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../src/pages/inbox/sidebar/FABPopoverContent/menuItems/QuickActionMenuItem.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	3
+"../../src/pages/inbox/sidebar/FABPopoverContent/menuItems/TravelMenuItem.tsx"	"no-restricted-imports"	1
 "../../src/pages/inbox/sidebar/FABPopoverContent/useScanActions.ts"	"@typescript-eslint/no-unsafe-type-assertion"	2
 "../../src/pages/inbox/sidebar/SidebarLinksData.tsx"	"react-hooks/refs"	1
 "../../src/pages/inbox/usePusherDraftPacing.ts"	"@typescript-eslint/no-unsafe-type-assertion"	2
@@ -1184,6 +1221,7 @@
 "../../src/pages/iou/SplitExpensePage.tsx"	"react-hooks/set-state-in-effect"	3
 "../../src/pages/iou/SplitList/index.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	2
 "../../src/pages/iou/request/MoneyRequestAttendeeSelector.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	2
+"../../src/pages/iou/request/MoneyRequestAttendeeSelector.tsx"	"no-restricted-imports"	1
 "../../src/pages/iou/request/ParticipantSearchResults.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	4
 "../../src/pages/iou/request/step/DistanceManualTabContent.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../src/pages/iou/request/step/IOURequestEditReport.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
@@ -1298,6 +1336,7 @@
 "../../src/pages/settings/Wallet/UnshareBankAccount/UnshareBankAccount.tsx"	"react-hooks/set-state-in-effect"	1
 "../../src/pages/settings/Wallet/UpdatePersonalBankAccountPage.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../src/pages/settings/Wallet/WalletPage/index.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	2
+"../../src/pages/settings/Wallet/WalletPage/index.tsx"	"no-restricted-imports"	1
 "../../src/pages/settings/Wallet/WalletPage/index.tsx"	"react-hooks/set-state-in-effect"	1
 "../../src/pages/signin/LoginForm/BaseLoginForm.tsx"	"@typescript-eslint/no-deprecated/InteractionManager.runAfterInteractions"	1
 "../../src/pages/signin/SAMLSignInPage/index.native.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
@@ -1318,6 +1357,7 @@
 "../../src/pages/workspace/WorkspaceConfirmationPage.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	2
 "../../src/pages/workspace/WorkspaceInitialPage.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	2
 "../../src/pages/workspace/WorkspaceMembersPage.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
+"../../src/pages/workspace/WorkspaceMembersPage.tsx"	"no-restricted-imports"	1
 "../../src/pages/workspace/WorkspaceMembersPage.tsx"	"react-hooks/exhaustive-deps"	1
 "../../src/pages/workspace/WorkspaceMembersPage.tsx"	"react-hooks/refs"	1
 "../../src/pages/workspace/WorkspaceNewRoomPage.tsx"	"@typescript-eslint/no-deprecated/InteractionManager.runAfterInteractions"	1
@@ -1380,12 +1420,16 @@
 "../../src/pages/workspace/accounting/qbd/export/DynamicQuickbooksDesktopOutOfPocketExpenseEntitySelectPage.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../src/pages/workspace/accounting/qbd/import/QuickbooksDesktopChartOfAccountsPage.tsx"	"no-restricted-syntax"	2
 "../../src/pages/workspace/accounting/qbd/import/QuickbooksDesktopChartOfAccountsPage.tsx"	"rulesdir/no-default-id-values"	1
+"../../src/pages/workspace/accounting/qbd/import/QuickbooksDesktopClassesPage.tsx"	"no-restricted-imports"	1
 "../../src/pages/workspace/accounting/qbd/import/QuickbooksDesktopClassesPage.tsx"	"no-restricted-syntax"	3
 "../../src/pages/workspace/accounting/qbd/import/QuickbooksDesktopClassesPage.tsx"	"rulesdir/no-default-id-values"	1
+"../../src/pages/workspace/accounting/qbd/import/QuickbooksDesktopCustomersPage.tsx"	"no-restricted-imports"	1
 "../../src/pages/workspace/accounting/qbd/import/QuickbooksDesktopCustomersPage.tsx"	"no-restricted-syntax"	3
 "../../src/pages/workspace/accounting/qbd/import/QuickbooksDesktopCustomersPage.tsx"	"rulesdir/no-default-id-values"	1
+"../../src/pages/workspace/accounting/qbd/import/QuickbooksDesktopImportPage.tsx"	"no-restricted-imports"	1
 "../../src/pages/workspace/accounting/qbd/import/QuickbooksDesktopImportPage.tsx"	"no-restricted-syntax"	1
 "../../src/pages/workspace/accounting/qbd/import/QuickbooksDesktopImportPage.tsx"	"rulesdir/no-default-id-values"	1
+"../../src/pages/workspace/accounting/qbd/import/QuickbooksDesktopItemsPage.tsx"	"no-restricted-imports"	1
 "../../src/pages/workspace/accounting/qbd/import/QuickbooksDesktopItemsPage.tsx"	"no-restricted-syntax"	3
 "../../src/pages/workspace/accounting/qbd/import/QuickbooksDesktopItemsPage.tsx"	"rulesdir/no-default-id-values"	1
 "../../src/pages/workspace/accounting/qbo/advanced/DynamicQuickbooksOnlineAccountingMethodPage.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
@@ -1396,15 +1440,18 @@
 "../../src/pages/workspace/accounting/qbo/import/QuickbooksClassesPage.tsx"	"rulesdir/no-default-id-values"	1
 "../../src/pages/workspace/accounting/qbo/import/QuickbooksCustomersPage.tsx"	"no-restricted-syntax"	2
 "../../src/pages/workspace/accounting/qbo/import/QuickbooksCustomersPage.tsx"	"rulesdir/no-default-id-values"	1
+"../../src/pages/workspace/accounting/qbo/import/QuickbooksImportPage.tsx"	"no-restricted-imports"	1
 "../../src/pages/workspace/accounting/qbo/import/QuickbooksImportPage.tsx"	"no-restricted-syntax"	2
 "../../src/pages/workspace/accounting/qbo/import/QuickbooksImportPage.tsx"	"rulesdir/no-default-id-values"	1
 "../../src/pages/workspace/accounting/qbo/import/QuickbooksTaxesPage.tsx"	"no-restricted-syntax"	2
 "../../src/pages/workspace/accounting/qbo/import/QuickbooksTaxesPage.tsx"	"rulesdir/no-default-id-values"	1
 "../../src/pages/workspace/accounting/reconciliation/CardReconciliationPage.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../src/pages/workspace/accounting/utils.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
+"../../src/pages/workspace/accounting/xero/XeroImportPage.tsx"	"no-restricted-imports"	1
 "../../src/pages/workspace/accounting/xero/XeroImportPage.tsx"	"no-restricted-syntax"	1
 "../../src/pages/workspace/accounting/xero/XeroImportPage.tsx"	"rulesdir/no-default-id-values"	1
 "../../src/pages/workspace/accounting/xero/XeroMapTrackingCategoryConfigurationPage.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	2
+"../../src/pages/workspace/accounting/xero/XeroTaxesConfigurationPage.tsx"	"no-restricted-imports"	1
 "../../src/pages/workspace/accounting/xero/XeroTaxesConfigurationPage.tsx"	"no-restricted-syntax"	4
 "../../src/pages/workspace/accounting/xero/XeroTaxesConfigurationPage.tsx"	"rulesdir/no-default-id-values"	1
 "../../src/pages/workspace/accounting/xero/XeroTrackingCategoryConfigurationPage.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	2
@@ -1413,6 +1460,7 @@
 "../../src/pages/workspace/accounting/xero/export/DynamicXeroPurchaseBillStatusSelectorPage.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../src/pages/workspace/accounting/xero/import/XeroChartOfAccountsPage.tsx"	"no-restricted-syntax"	2
 "../../src/pages/workspace/accounting/xero/import/XeroChartOfAccountsPage.tsx"	"rulesdir/no-default-id-values"	1
+"../../src/pages/workspace/accounting/xero/import/XeroCustomerConfigurationPage.tsx"	"no-restricted-imports"	1
 "../../src/pages/workspace/accounting/xero/import/XeroCustomerConfigurationPage.tsx"	"no-restricted-syntax"	3
 "../../src/pages/workspace/accounting/xero/import/XeroCustomerConfigurationPage.tsx"	"rulesdir/no-default-id-values"	1
 "../../src/pages/workspace/categories/CategorySettingsPage.tsx"	"react-hooks/preserve-manual-memoization"	1
@@ -1448,6 +1496,7 @@
 "../../src/pages/workspace/hr/HRProviderCard.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../src/pages/workspace/hr/utils.ts"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../src/pages/workspace/invoices/WorkspaceInvoiceVBASection.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	2
+"../../src/pages/workspace/members/ImportMembersPage.tsx"	"no-restricted-imports"	1
 "../../src/pages/workspace/members/ImportMembersPage.tsx"	"no-restricted-syntax"	1
 "../../src/pages/workspace/members/ImportMembersPage.tsx"	"rulesdir/no-default-id-values"	1
 "../../src/pages/workspace/members/ImportedMembersConfirmationPage.tsx"	"react-hooks/refs"	7
@@ -1470,6 +1519,7 @@
 "../../src/pages/workspace/travel/WorkspaceTravelInvoicingSection.tsx"	"@typescript-eslint/no-deprecated/ConfirmModal"	3
 "../../src/pages/workspace/travel/WorkspaceTravelInvoicingSettlementAccountPage.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../src/pages/workspace/upgrade/UpgradeIntro.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	2
+"../../src/pages/workspace/upgrade/WorkspaceUpgradePage.tsx"	"no-restricted-imports"	1
 "../../src/pages/workspace/withPolicy.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	3
 "../../src/pages/workspace/withPolicyAndFullscreenLoading.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../src/pages/workspace/workflows/WorkspaceAutoReportingFrequencyPage.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	2
@@ -1481,6 +1531,7 @@
 "../../src/selectors/AdvancedSearchFiltersForm.ts"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../src/selectors/Domain.ts"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../src/selectors/Policy.ts"	"@typescript-eslint/no-unsafe-type-assertion"	2
+"../../src/selectors/Policy.ts"	"no-restricted-imports"	1
 "../../src/setup/addUtilsToWindow.ts"	"@typescript-eslint/no-unsafe-type-assertion"	20
 "../../src/setup/moduleInitPolyfill.ts"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../src/setup/telemetry/index.web.ts"	"@typescript-eslint/no-unsafe-type-assertion"	1
@@ -1565,19 +1616,29 @@
 "../../tests/actions/BankAccountsTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	2
 "../../tests/actions/CopyPolicySettingsTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	18
 "../../tests/actions/DomainTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	20
+"../../tests/actions/EnforceActionExportRestrictions.ts"	"no-restricted-imports"	1
 "../../tests/actions/IOU/BuildOnyxDataForMoneyRequestTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	17
+"../../tests/actions/IOU/CreateDraftTransactionTest.ts"	"no-restricted-imports"	1
 "../../tests/actions/IOU/GetMoneyRequestInformationTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	1
+"../../tests/actions/IOU/MoneyRequestBuilderTest.ts"	"no-restricted-imports"	1
+"../../tests/actions/IOU/MoneyRequestSettersTest.ts"	"no-restricted-imports"	1
 "../../tests/actions/IOU/PerDiemTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	6
 "../../tests/actions/IOU/RequestMoneyTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	5
+"../../tests/actions/IOU/RequestMoneyTest.ts"	"no-restricted-imports"	1
 "../../tests/actions/IOU/SearchUpdateTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	4
+"../../tests/actions/IOU/SearchUpdateTest.ts"	"no-restricted-imports"	1
 "../../tests/actions/IOU/SplitReportTotalsTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	10
+"../../tests/actions/IOU/SplitReportTotalsTest.ts"	"no-restricted-imports"	1
 "../../tests/actions/IOUTest/BulkEditTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	25
 "../../tests/actions/IOUTest/DeleteMoneyRequestTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	2
 "../../tests/actions/IOUTest/DuplicateTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	23
 "../../tests/actions/IOUTest/GetUpdateMoneyRequestParamsTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	3
 "../../tests/actions/IOUTest/HoldTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	4
+"../../tests/actions/IOUTest/HoldTest.ts"	"no-restricted-imports"	1
 "../../tests/actions/IOUTest/PayMoneyRequestTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	6
+"../../tests/actions/IOUTest/PayMoneyRequestTest.ts"	"no-restricted-imports"	1
 "../../tests/actions/IOUTest/ReceiptTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	9
+"../../tests/actions/IOUTest/ReceiptTest.ts"	"no-restricted-imports"	1
 "../../tests/actions/IOUTest/RejectMoneyRequestTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../tests/actions/IOUTest/ReportWorkflowTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	64
 "../../tests/actions/IOUTest/SendInvoiceTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	7
@@ -1585,27 +1646,37 @@
 "../../tests/actions/IOUTest/SplitSelfDMTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	2
 "../../tests/actions/IOUTest/SplitTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	21
 "../../tests/actions/IOUTest/TrackExpenseTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	10
+"../../tests/actions/IOUTest/TrackExpenseTest.ts"	"no-restricted-imports"	1
 "../../tests/actions/IOUTest/UpdateMoneyRequestTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	4
+"../../tests/actions/IOUTest/UpdateMoneyRequestTest.ts"	"no-restricted-imports"	1
 "../../tests/actions/IOUTest/UpdateMoneyRequestVendorTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	2
 "../../tests/actions/MergeTransactionTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	10
+"../../tests/actions/OdometerTransactionUtilsTest.ts"	"no-restricted-imports"	1
 "../../tests/actions/OnyxUpdateManagerTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	4
 "../../tests/actions/PersonalDetailsTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	10
 "../../tests/actions/PolicyCategoryTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../tests/actions/PolicyMemberTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	9
 "../../tests/actions/PolicyProfileTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	1
+"../../tests/actions/PolicyProfileTest.ts"	"no-restricted-imports"	1
 "../../tests/actions/PolicyTagTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../tests/actions/PolicyTaxTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../tests/actions/PolicyTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	86
+"../../tests/actions/PolicyTest.ts"	"no-restricted-imports"	1
 "../../tests/actions/QueuedOnyxUpdatesTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../tests/actions/ReimbursementAccountTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	5
 "../../tests/actions/ReplaceOptimisticReportWithActualReportTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	3
 "../../tests/actions/ReportFieldTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	1
+"../../tests/actions/ReportFieldTest.ts"	"no-restricted-imports"	1
 "../../tests/actions/ReportPreviewActionUtilsTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	28
+"../../tests/actions/ReportPreviewActionUtilsTest.ts"	"no-restricted-imports"	2
 "../../tests/actions/ReportTest.ts"	"@typescript-eslint/no-deprecated/buildNextStepNew"	1
 "../../tests/actions/ReportTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	80
+"../../tests/actions/ReportTest.ts"	"no-restricted-imports"	1
 "../../tests/actions/SessionTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	12
 "../../tests/actions/SubscriptionTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	2
 "../../tests/actions/TaskTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	44
+"../../tests/actions/TaskTest.ts"	"no-restricted-imports"	1
+"../../tests/actions/TransactionTest.ts"	"no-restricted-imports"	1
 "../../tests/actions/UserTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	45
 "../../tests/actions/WorkflowTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	13
 "../../tests/actions/connections/NetSuite.ts"	"@typescript-eslint/no-unsafe-type-assertion"	6
@@ -1669,6 +1740,7 @@
 "../../tests/ui/MoneyReportViewTest.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../tests/ui/MoneyRequestReportActionsListRejectModalTest.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	2
 "../../tests/ui/MoneyRequestReportFooter.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	5
+"../../tests/ui/MoneyRequestReportPreview.test.tsx"	"no-restricted-imports"	1
 "../../tests/ui/MoneyRequestViewTest.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../tests/ui/MonthListItemHeaderTest.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	2
 "../../tests/ui/MultifactorAuthenticationRevokePageTest.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	8
@@ -1708,6 +1780,7 @@
 "../../tests/ui/WorkspaceInviteMessageApproverPageTest.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../tests/ui/WorkspaceMembersTest.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../tests/ui/WorkspaceMoreFeaturesPageTest.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	2
+"../../tests/ui/WorkspaceMoreFeaturesPageTest.tsx"	"no-restricted-imports"	1
 "../../tests/ui/WorkspaceOnboarding.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../tests/ui/WorkspaceTagsTest.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	2
 "../../tests/ui/WorkspaceUpgradeTest.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	2
@@ -1773,14 +1846,17 @@
 "../../tests/unit/FlashListTest.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../tests/unit/FocusTrapForModalTest.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	3
 "../../tests/unit/FormulaTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	78
+"../../tests/unit/FormulaTest.ts"	"no-restricted-imports"	1
 "../../tests/unit/FraudProtectionTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	2
 "../../tests/unit/GitTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	5
 "../../tests/unit/GithubUtilsTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	3
 "../../tests/unit/HomePage/YourSpendSection/YourSpendSectionTest.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	3
 "../../tests/unit/HomePage/YourSpendSection/useYourSpendDataTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	6
+"../../tests/unit/HomePage/YourSpendSection/useYourSpendDataTest.ts"	"no-restricted-imports"	1
 "../../tests/unit/HrUtilsTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	50
 "../../tests/unit/HybridAppActionsTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	2
 "../../tests/unit/IOUUtilsTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	11
+"../../tests/unit/IOUUtilsTest.ts"	"no-restricted-imports"	1
 "../../tests/unit/ImageSVGCachePolicyTest.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	3
 "../../tests/unit/ImportTransactions.test.ts"	"@typescript-eslint/no-unsafe-type-assertion"	17
 "../../tests/unit/LHNAvatarPipelineTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	2
@@ -1792,6 +1868,7 @@
 "../../tests/unit/MentionUtilsTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	4
 "../../tests/unit/MiddlewareTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	20
 "../../tests/unit/ModifiedExpenseMessageTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	5
+"../../tests/unit/ModifiedExpenseMessageTest.ts"	"no-restricted-imports"	1
 "../../tests/unit/MoneyRequestReportTransactionListActiveTransactionIDsTest.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	5
 "../../tests/unit/MoneyRequestReportUtilsTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	8
 "../../tests/unit/MoneyRequestUtilsTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	3
@@ -1823,6 +1900,7 @@
 "../../tests/unit/PopoverMenuV2Test.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	4
 "../../tests/unit/PressResponderTest.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../tests/unit/QuickActionUtilsTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	7
+"../../tests/unit/QuickActionUtilsTest.ts"	"no-restricted-imports"	2
 "../../tests/unit/ReceiptAlternativeMethodsTest.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	4
 "../../tests/unit/RefreshCardFeedConnectionPageTest.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	4
 "../../tests/unit/ReimbursementAccountUtilsTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	2
@@ -1833,11 +1911,15 @@
 "../../tests/unit/ReportLayoutUtilsTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../tests/unit/ReportNameUtilsTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	22
 "../../tests/unit/ReportPrimaryActionUtilsTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	168
+"../../tests/unit/ReportPrimaryActionUtilsTest.ts"	"no-restricted-imports"	1
 "../../tests/unit/ReportSecondaryActionUtilsTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	450
+"../../tests/unit/ReportSecondaryActionUtilsTest.ts"	"no-restricted-imports"	2
 "../../tests/unit/ReportSubmitUtilsTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../tests/unit/ReportTitleUtilsTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	3
+"../../tests/unit/ReportTitleUtilsTest.ts"	"no-restricted-imports"	1
 "../../tests/unit/ReportUtilsGetIconsTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../tests/unit/ReportUtilsTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	98
+"../../tests/unit/ReportUtilsTest.ts"	"no-restricted-imports"	1
 "../../tests/unit/ReportWelcomeTextTest.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../tests/unit/RequestConflictUtilsTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	11
 "../../tests/unit/RequestTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	1
@@ -1862,6 +1944,7 @@
 "../../tests/unit/SettlementButtonUtilsTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	4
 "../../tests/unit/SidebarTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	2
 "../../tests/unit/SidebarUtilsTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	31
+"../../tests/unit/SidebarUtilsTest.ts"	"no-restricted-imports"	1
 "../../tests/unit/SplitExpenseAutoAdjustmentTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../tests/unit/SubscriptionUtilsTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	2
 "../../tests/unit/SuggestedFollowupTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	1
@@ -1872,6 +1955,7 @@
 "../../tests/unit/TelemetrySynchronizerTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	9
 "../../tests/unit/TransactionNavigationUtilsTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	6
 "../../tests/unit/TransactionPreviewUtils.test.ts"	"@typescript-eslint/no-unsafe-type-assertion"	7
+"../../tests/unit/TransactionPreviewUtils.test.ts"	"no-restricted-imports"	1
 "../../tests/unit/TransactionTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	12
 "../../tests/unit/TransactionUtilsTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	20
 "../../tests/unit/TranslateTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	9
@@ -1993,10 +2077,13 @@
 "../../tests/unit/markPullRequestsAsDeployedTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	2
 "../../tests/unit/navigateAfterExpenseCreateTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	8
 "../../tests/unit/navigateAfterOnboardingTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	1
+"../../tests/unit/navigateAfterOnboardingTest.ts"	"no-restricted-imports"	1
 "../../tests/unit/navigateToWorkspacesPageTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	14
+"../../tests/unit/navigateToWorkspacesPageTest.ts"	"no-restricted-imports"	1
 "../../tests/unit/pages/home/GettingStartedSection/GettingStartedSectionTest.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	11
 "../../tests/unit/pages/inbox/ConciergeDraftContext.test.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../tests/unit/pages/inbox/report/ReportActionEditMessageContext.test.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	2
+"../../tests/unit/pages/inbox/report/ReportActionEditMessageContext.test.tsx"	"no-restricted-imports"	1
 "../../tests/unit/pages/settings/AddAgentAvatarPageTest.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../tests/unit/pages/settings/AddAgentPageTest.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	11
 "../../tests/unit/pages/settings/AgentsListRowTest.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
@@ -2032,6 +2119,7 @@
 "../../tests/unit/useGroupDraftRestoreTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	14
 "../../tests/unit/useIndicatorStatusTest.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../tests/unit/useLastWorkspaceNumberTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	4
+"../../tests/unit/useMarkAsReadTest.ts"	"no-restricted-imports"	1
 "../../tests/unit/usePersonalDetailSearchSelectorTest.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../tests/unit/usePolicyIndicatorChecksTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	11
 "../../tests/unit/usePopoverPositionTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	1

From b2cc5b80871c2fd9a689f74c0de61fb8e761ecdf Mon Sep 17 00:00:00 2001
From: borys3kk <szymon.banys01@wp.pl>
Date: Wed, 10 Jun 2026 12:09:31 +0200
Subject: [PATCH 261/435] fix using isFocused

---
 src/components/BlockingViews/ForceFullScreenView/index.tsx | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/src/components/BlockingViews/ForceFullScreenView/index.tsx b/src/components/BlockingViews/ForceFullScreenView/index.tsx
index f856794e4a57..a222d69f6816 100644
--- a/src/components/BlockingViews/ForceFullScreenView/index.tsx
+++ b/src/components/BlockingViews/ForceFullScreenView/index.tsx
@@ -1,4 +1,4 @@
-import {useRoute} from '@react-navigation/native';
+import {useIsFocused, useRoute} from '@react-navigation/native';
 import React, {useEffect} from 'react';
 import {View} from 'react-native';
 import {useFullScreenBlockingViewActions} from '@components/FullScreenBlockingViewContextProvider';
@@ -9,16 +9,17 @@ function ForceFullScreenView({children, shouldForceFullScreen = false}: ForceFul
     const route = useRoute();
     const styles = useThemeStyles();
     const {addRouteKey, removeRouteKey} = useFullScreenBlockingViewActions();
+    const isFocused = useIsFocused();
 
     useEffect(() => {
-        if (!shouldForceFullScreen) {
+        if (!shouldForceFullScreen || !isFocused) {
             return;
         }
 
         addRouteKey(route.key);
 
         return () => removeRouteKey(route.key);
-    }, [addRouteKey, removeRouteKey, route.key, shouldForceFullScreen]);
+    }, [addRouteKey, removeRouteKey, route.key, shouldForceFullScreen, isFocused]);
 
     if (shouldForceFullScreen) {
         return <View style={styles.forcedBlockingViewContainer}>{children}</View>;

From 6944ea45d400fbd2bc3a6cc8406c27bfe754ffcc Mon Sep 17 00:00:00 2001
From: Adam Horodyski <ad.horodyski@gmail.com>
Date: Wed, 10 Jun 2026 12:53:45 +0200
Subject: [PATCH 262/435] SequentialQueue: don't block the queue when a persist
 write fails
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

The conflict-resolution persist paths (update / deleteRequestsByIndices)
returned a raw Onyx.set that could reject. Awaiting that in push() before
flush() stranded isReadyPromise on a disk-write failure, hanging every
READ parked on waitForIdle() and never flushing the request.

These paths now swallow the rejection like save() already did — the
in-memory queue stays the source of truth for retry — and surface it via
Log.alert so a disk-write failure is observable rather than silent.
push() keeps a defensive try/catch so a persist rejection can never wedge
the queue; on failure it flushes best-effort, matching pre-async behavior.

Adds a regression test that fails on the pre-fix code.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
---
 src/libs/Network/SequentialQueue.ts   |  8 +++++-
 src/libs/actions/PersistedRequests.ts | 30 ++++++++++++++++-----
 tests/unit/SequentialQueueTest.ts     | 39 +++++++++++++++++++++++++++
 3 files changed, 70 insertions(+), 7 deletions(-)

diff --git a/src/libs/Network/SequentialQueue.ts b/src/libs/Network/SequentialQueue.ts
index 8009166745a5..9c4a1b366bf7 100644
--- a/src/libs/Network/SequentialQueue.ts
+++ b/src/libs/Network/SequentialQueue.ts
@@ -584,7 +584,13 @@ async function push<TKey extends OnyxKey>(newRequest: OnyxRequest<TKey>): Promis
 
     // Block until the Onyx disk commit lands so flush() → XHR cannot race the disk write —
     // a process kill in that window would lose the request on next launch.
-    await persistencePromise;
+    try {
+        await persistencePromise;
+    } catch {
+        // Backstop: persistence alerts+swallows on failure, so this shouldn't reject. If it ever does,
+        // flush anyway (the request is already in the in-memory queue) rather than stranding isReadyPromise.
+        Log.info('[SequentialQueue] Persist rejected — flushing anyway', false, {command: newRequest.command});
+    }
 
     // The network may have flipped offline while we awaited the disk write. flush() would
     // early-return on its offline check without resolving isReadyPromise, leaving READs parked
diff --git a/src/libs/actions/PersistedRequests.ts b/src/libs/actions/PersistedRequests.ts
index a689e238a2d7..847946eeb51e 100644
--- a/src/libs/actions/PersistedRequests.ts
+++ b/src/libs/actions/PersistedRequests.ts
@@ -260,10 +260,12 @@ function save<TKey extends OnyxKey>(requestToPersist: Request<TKey>): Promise<vo
                 queueLength: getLength(),
             });
         })
-        .catch(() => {
-            Log.info('[PersistedRequests] ERROR: Failed to persist request to disk', false, {
+        .catch((error) => {
+            // Disk-write failure risks losing this request on a crash — alert as a storage emergency.
+            Log.alert('[PersistedRequests] ERROR: Failed to persist request to disk', {
                 command: requestToPersist.command,
                 queueLength: getLength(),
+                error,
             });
         });
 }
@@ -334,9 +336,18 @@ function deleteRequestsByIndices(indices: number[]): Promise<void> {
     persistedRequests = persistedRequests.filter((_, index) => !indicesSet.has(index));
 
     // Update the persisted requests in storage or state as necessary
-    return trackOnyxWrite(Onyx.set(ONYXKEYS.PERSISTED_REQUESTS, persistedRequests)).then(() => {
-        Log.info(`Multiple (${indices.length}) requests removed from the queue. Queue length is ${persistedRequests.length}`);
-    });
+    return trackOnyxWrite(Onyx.set(ONYXKEYS.PERSISTED_REQUESTS, persistedRequests))
+        .then(() => {
+            Log.info(`Multiple (${indices.length}) requests removed from the queue. Queue length is ${persistedRequests.length}`);
+        })
+        .catch((error) => {
+            // Swallow so the conflict promise resolves (in-memory queue is the source of truth); alert as a storage emergency.
+            Log.alert('[PersistedRequests] ERROR: Failed to persist request deletion to disk', {
+                indicesCount: indices.length,
+                queueLength: getLength(),
+                error,
+            });
+        });
 }
 
 function update<TKey extends OnyxKey>(oldRequestIndex: number, newRequest: Request<TKey>): Promise<void> {
@@ -349,7 +360,14 @@ function update<TKey extends OnyxKey>(oldRequestIndex: number, newRequest: Reque
     if (requestIndex != null) {
         knownRequestIDs.add(requestIndex);
     }
-    return trackOnyxWrite(Onyx.set(ONYXKEYS.PERSISTED_REQUESTS, requests));
+    return trackOnyxWrite(Onyx.set(ONYXKEYS.PERSISTED_REQUESTS, requests)).catch((error) => {
+        // Swallow so the conflict promise resolves (in-memory queue is the source of truth); alert as a storage emergency.
+        Log.alert('[PersistedRequests] ERROR: Failed to persist updated request to disk', {
+            command: newRequest.command,
+            queueLength: getLength(),
+            error,
+        });
+    });
 }
 
 function shouldPersistOngoingRequest(request: AnyRequest | null): boolean {
diff --git a/tests/unit/SequentialQueueTest.ts b/tests/unit/SequentialQueueTest.ts
index 5082928796fe..a0a3dedcebff 100644
--- a/tests/unit/SequentialQueueTest.ts
+++ b/tests/unit/SequentialQueueTest.ts
@@ -74,6 +74,45 @@ describe('SequentialQueue', () => {
         }
     });
 
+    it('should not block the queue when a disk write fails during persist', async () => {
+        // If a conflict-resolution disk write rejects (storage full / corruption), push() must not throw
+        // or strand isReadyPromise — the request should still flush and waitForIdle() should resolve.
+        const mockedFetch = global.fetch as ReturnType<typeof TestHelper.getGlobalFetchMock> & {pause: () => void; resume: () => Promise<void>};
+        const originalSet = Onyx.set.bind(Onyx);
+
+        mockedFetch.pause();
+        try {
+            await SequentialQueue.push({command: 'OpenReport'}); // occupies ongoingRequest
+            await waitForBatchedUpdates();
+            await SequentialQueue.push(request); // ReconnectApp stacks in the queue
+
+            // Fail the conflict-resolution persist (a raw Onyx.set on the persisted-requests key).
+            const setMock = jest
+                .spyOn(Onyx, 'set')
+                .mockImplementation((key, value) => (key === ONYXKEYS.PERSISTED_REQUESTS ? Promise.reject(new Error('simulated disk-write failure')) : originalSet(key, value)));
+            try {
+                const replacing: Request<never> = {
+                    command: 'ReconnectApp',
+                    data: {accountID: 56789},
+                    checkAndFixConflictingRequest: (persistedRequests) => {
+                        const index = persistedRequests.findIndex((r) => r.command === 'ReconnectApp');
+                        return {conflictAction: index === -1 ? {type: 'push'} : {type: 'replace', index}};
+                    },
+                };
+                // The failed disk write must not reject the caller.
+                await expect(SequentialQueue.push(replacing)).resolves.toBeUndefined();
+            } finally {
+                setMock.mockRestore();
+            }
+        } finally {
+            await mockedFetch.resume();
+        }
+
+        // The queue still drains and READs unblock — a hang here would fail the test by timing out.
+        await SequentialQueue.waitForIdle();
+        expect(getLength()).toBe(0);
+    });
+
     it('should push two requests with conflict resolution and replace', async () => {
         // Pause the queue so `process()` does not consume the first request before
         // the conflict resolver runs. Under persist-before-fire `push()` is async,

From 57e6849dda2ba4a361b77e9dbf98ca09ab876b1b Mon Sep 17 00:00:00 2001
From: neil-marcellini <neil@expensify.com>
Date: Wed, 10 Jun 2026 07:23:33 -0400
Subject: [PATCH 263/435] Move process explanation into overview paragraph, per
 feedback

---
 contributingGuides/HOW_TO_WORK_WITH_MELVINBOT.md | 6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/contributingGuides/HOW_TO_WORK_WITH_MELVINBOT.md b/contributingGuides/HOW_TO_WORK_WITH_MELVINBOT.md
index 4f1b2defee84..ad695017a306 100644
--- a/contributingGuides/HOW_TO_WORK_WITH_MELVINBOT.md
+++ b/contributingGuides/HOW_TO_WORK_WITH_MELVINBOT.md
@@ -2,11 +2,9 @@
 
 MelvinBot (Melvin) is Expensify's AI agent for App GitHub issues. On many open-source jobs, Melvin posts the first proposal automatically. This guide explains how contributors, Contributor+ (C+), and internal engineers work together on those issues.
 
-For general contributor workflow (proposals, payment, PR standards), see [CONTRIBUTING.md](./CONTRIBUTING.md). For C+ responsibilities, see [HOW_TO_BECOME_A_CONTRIBUTOR_PLUS.md](./HOW_TO_BECOME_A_CONTRIBUTOR_PLUS.md).
-
-## Why this process exists
+Clearly documenting the process helps us move efficiently by preventing all of us from wasting time on incorrect solutions. Internal engineering approval is required on Melvinbot proposals because we usually have the most context to know whether a solution aligns with our best practices.
 
-Melvin can open pull requests before a human has validated the approach. Without a clear process, contributors waste time on unapproved work, and internal engineers may review PRs that should not have been started. Proposal review must happen **before** implementation.
+For general contributor workflow (proposals, payment, PR standards), see [CONTRIBUTING.md](./CONTRIBUTING.md). For C+ responsibilities, see [HOW_TO_BECOME_A_CONTRIBUTOR_PLUS.md](./HOW_TO_BECOME_A_CONTRIBUTOR_PLUS.md).
 
 ## Roles
 

From 8acab5a2d06d6ce98b9fc4f9f36026823b536adf Mon Sep 17 00:00:00 2001
From: neil-marcellini <neil@expensify.com>
Date: Wed, 10 Jun 2026 07:27:00 -0400
Subject: [PATCH 264/435] Address Shridar review feedback on MelvinBot
 contributor docs

Clarify MelvinBot Help Wanted exception, first-come-first-serve proposal
order, proposal link when asking Melvin to implement, @MelvinBot tagging
for PR tweaks, and Reviewer-only screenshots/videos.

Co-authored-by: Cursor <cursoragent@cursor.com>
---
 contributingGuides/CONTRIBUTING.md               |  4 ++--
 contributingGuides/HOW_TO_WORK_WITH_MELVINBOT.md | 14 +++++++-------
 2 files changed, 9 insertions(+), 9 deletions(-)

diff --git a/contributingGuides/CONTRIBUTING.md b/contributingGuides/CONTRIBUTING.md
index 3fdbd76b7be0..fbce6cf82a41 100644
--- a/contributingGuides/CONTRIBUTING.md
+++ b/contributingGuides/CONTRIBUTING.md
@@ -155,8 +155,8 @@ This helps future investigators understand the history and current status of err
 3. If you cannot reproduce the problem, pause on this step and add a comment to the issue explaining where you are stuck or that you don't think the issue can be reproduced.
 
 ### Propose a solution for the job
-4. Proposals must only be posted after the `Help Wanted` label is added. Any proposals submitted beforehand will be ignored and not reviewed. Do not post proposals in Slack.
-    - On issues where [MelvinBot](./HOW_TO_WORK_WITH_MELVINBOT.md) has posted a proposal, Melvin's proposal will be first. Follow the same review standards and **do not open a PR** until a proposal is accepted. C+ members: see [How to Work with MelvinBot](./HOW_TO_WORK_WITH_MELVINBOT.md) for your implementation and PR ownership steps.
+4. Proposals must only be posted after the `Help Wanted` label is added. Any proposals submitted beforehand will be ignored and not reviewed. Do not post proposals in Slack. MelvinBot is an exception: it may post a proposal before `Help Wanted` is applied.
+    - On issues where [MelvinBot](./HOW_TO_WORK_WITH_MELVINBOT.md) has posted a proposal, review Melvin's proposal using the same standards as contributor proposals. Melvin's proposal is not guaranteed to be the earliest if `Help Wanted` was applied before Melvin posted (for example when an employee adds the `External` label). Follow first-come-first-serve review order for all proposals after `Help Wanted`. **Do not open a PR** until a proposal is accepted. C+ members: see [How to Work with MelvinBot](./HOW_TO_WORK_WITH_MELVINBOT.md) for your implementation and PR ownership steps.
 5. Contributors should **not** submit proposals on issues when they have assigned issues or PRs that are awaiting an action from them. If so, they will be in violation of Rule #1 (Get Shit Done) in our [Code of Conduct](https://github.com/Expensify/App/blob/main/CODE_OF_CONDUCT.md) and will receive a warning. Multiple warnings can lead to removal from the program.
 6. After you reproduce the issue, complete the [proposal template here](./PROPOSAL_TEMPLATE.md) and post it as a comment in the corresponding GitHub issue (linked in the Upwork job).
     - Note: Before submitting a proposal on an issue, be sure to read any other existing proposals. ALL NEW PROPOSALS MUST BE DIFFERENT FROM EXISTING PROPOSALS. The *difference* should be important, meaningful or considerable.
diff --git a/contributingGuides/HOW_TO_WORK_WITH_MELVINBOT.md b/contributingGuides/HOW_TO_WORK_WITH_MELVINBOT.md
index ad695017a306..d7995d0ec144 100644
--- a/contributingGuides/HOW_TO_WORK_WITH_MELVINBOT.md
+++ b/contributingGuides/HOW_TO_WORK_WITH_MELVINBOT.md
@@ -30,13 +30,13 @@ Issue opened → Melvin posts proposal → C+ reviews proposal(s)
 
 ## Phase 1: Proposal review
 
-Follow the **same proposal review process** as any other App job, but make sure to start with Melvin's proposal first.
+Follow the **same proposal review process** as any other App job, including first-come-first-serve review order after `Help Wanted` is applied (see [CONTRIBUTING.md](./CONTRIBUTING.md#propose-a-solution-for-the-job)).
 
 1. Use the [proposal template](./PROPOSAL_TEMPLATE.md) criteria: clear root cause, concrete solution, no code diffs.
 2. C+ reviews Melvin's proposal with the same rigor as a contributor proposal. Do not approve proposals that lack a satisfying root-cause explanation.
 3. Contributors may still post proposals if they have a **meaningfully different** approach (see [CONTRIBUTING.md](./CONTRIBUTING.md#propose-a-solution-for-the-job)).
 4. **No one opens a pull request** until a proposal is accepted by the CME (same as any other App job; see [CONTRIBUTING.md](./CONTRIBUTING.md#propose-a-solution-for-the-job)).
-5. If Melvin's proposal is not acceptable, the C+ can review proposals from other contributors, or iterate with Melvin by asking it to update it's proposal or post new ones until it is satisfactory.
+5. If Melvin's proposal is not acceptable, the C+ can review proposals from other contributors, or iterate with Melvin by tagging `@MelvinBot` on the issue, explaining the needed changes, and asking it to update its proposal or post a new one until it is satisfactory.
 
 ### C+ reviews and recommends
 
@@ -46,13 +46,13 @@ When the C+ is satisfied with Melvin's proposal, they recommend it to the CME by
 
 ### After the CME approves the proposal
 
-Once the assigned CME has approved Melvin's proposal (the same acceptance step as for any contributor proposal), the C+ comments on the issue asking Melvin to implement, for example:
+Once the assigned CME has approved Melvin's proposal (the same acceptance step as for any contributor proposal), the C+ comments on the issue asking Melvin to implement. Include a link to the specific proposal comment so Melvin implements the latest version (Melvin may post a new proposal when asked to update). For example:
 
 ```
-@MelvinBot please implement your proposal
+@MelvinBot please implement your proposal at https://github.com/Expensify/App/issues/12345#issuecomment-6789012345
 ```
 
-Adjust the wording if needed, but the comment must mention `@MelvinBot` and clearly request implementation.
+Adjust the wording if needed, but the comment must mention `@MelvinBot`, link to the proposal comment, and clearly request implementation.
 
 ## Phase 2: C+ owns the pull request
 
@@ -60,9 +60,9 @@ Melvin opens a draft PR linked to the issue. MelvinBot remains the GitHub author
 
 Before requesting final review, the assigned C+ must:
 
-1. **Manually tweak the PR** if Melvin's implementation needs corrections.
+1. **Manually tweak the PR** if Melvin's implementation needs corrections. Comment on the pull request, tag `@MelvinBot`, and explain the needed changes so Melvin can update the code.
 2. **Test the change** on all required platforms (see [CONTRIBUTING.md](./CONTRIBUTING.md#make-sure-you-can-test-on-all-platforms)).
-3. **Complete every step** in the PR Author Checklist (see [Updating the PR description and checklist](#updating-the-pr-description-and-checklist) below).
+3. **Complete every step** in the PR Author Checklist (see [Updating the PR description and checklist](#updating-the-pr-description-and-checklist) below). Screenshots and videos may live only in the Reviewer Checklist section of your PR comment; you do not need to duplicate them in the Author Checklist.
 4. **Self-review the code** against [PR Review Guidelines](./PR_REVIEW_GUIDELINES.md), [PR Authoring & Reviewing Best Practices](./PR_AUTHOR_REVIEWER_BEST_PRACTICES.md), and complete the [Reviewer Checklist](./REVIEWER_CHECKLIST.md) as part of that self-review.
 
 The C+ is accountable for the PR quality, the same as any contributor who authored a PR.

From c39b7c93a20017ca18197afa57ee55dda31a5853 Mon Sep 17 00:00:00 2001
From: neil-marcellini <neil@expensify.com>
Date: Wed, 10 Jun 2026 07:35:04 -0400
Subject: [PATCH 265/435] Manually clarify proposal review order with Melvin

---
 contributingGuides/CONTRIBUTING.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/contributingGuides/CONTRIBUTING.md b/contributingGuides/CONTRIBUTING.md
index fbce6cf82a41..8e0cd9a65e59 100644
--- a/contributingGuides/CONTRIBUTING.md
+++ b/contributingGuides/CONTRIBUTING.md
@@ -156,7 +156,7 @@ This helps future investigators understand the history and current status of err
 
 ### Propose a solution for the job
 4. Proposals must only be posted after the `Help Wanted` label is added. Any proposals submitted beforehand will be ignored and not reviewed. Do not post proposals in Slack. MelvinBot is an exception: it may post a proposal before `Help Wanted` is applied.
-    - On issues where [MelvinBot](./HOW_TO_WORK_WITH_MELVINBOT.md) has posted a proposal, review Melvin's proposal using the same standards as contributor proposals. Melvin's proposal is not guaranteed to be the earliest if `Help Wanted` was applied before Melvin posted (for example when an employee adds the `External` label). Follow first-come-first-serve review order for all proposals after `Help Wanted`. **Do not open a PR** until a proposal is accepted. C+ members: see [How to Work with MelvinBot](./HOW_TO_WORK_WITH_MELVINBOT.md) for your implementation and PR ownership steps.
+    - On issues where [MelvinBot](./HOW_TO_WORK_WITH_MELVINBOT.md) has posted a proposal, review Melvin's proposal using the same standards as contributor proposals. Melvin's proposal is not guaranteed to be the earliest, but it should always be reviewed first because we are spending the money to run it. Follow first-come-first-serve review order for all other proposals after `Help Wanted`. **Do not open a PR** until a proposal is accepted. See [How to Work with MelvinBot](./HOW_TO_WORK_WITH_MELVINBOT.md) for more details.
 5. Contributors should **not** submit proposals on issues when they have assigned issues or PRs that are awaiting an action from them. If so, they will be in violation of Rule #1 (Get Shit Done) in our [Code of Conduct](https://github.com/Expensify/App/blob/main/CODE_OF_CONDUCT.md) and will receive a warning. Multiple warnings can lead to removal from the program.
 6. After you reproduce the issue, complete the [proposal template here](./PROPOSAL_TEMPLATE.md) and post it as a comment in the corresponding GitHub issue (linked in the Upwork job).
     - Note: Before submitting a proposal on an issue, be sure to read any other existing proposals. ALL NEW PROPOSALS MUST BE DIFFERENT FROM EXISTING PROPOSALS. The *difference* should be important, meaningful or considerable.

From 4f92f7f2e857a07b8328dfc330250463b1fe5864 Mon Sep 17 00:00:00 2001
From: neil-marcellini <neil@expensify.com>
Date: Wed, 10 Jun 2026 07:43:35 -0400
Subject: [PATCH 266/435] Manually clean up proposal review order section in
 MelvinBot doc

---
 contributingGuides/HOW_TO_WORK_WITH_MELVINBOT.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/contributingGuides/HOW_TO_WORK_WITH_MELVINBOT.md b/contributingGuides/HOW_TO_WORK_WITH_MELVINBOT.md
index d7995d0ec144..9b7ab7cbd9f4 100644
--- a/contributingGuides/HOW_TO_WORK_WITH_MELVINBOT.md
+++ b/contributingGuides/HOW_TO_WORK_WITH_MELVINBOT.md
@@ -30,7 +30,7 @@ Issue opened → Melvin posts proposal → C+ reviews proposal(s)
 
 ## Phase 1: Proposal review
 
-Follow the **same proposal review process** as any other App job, including first-come-first-serve review order after `Help Wanted` is applied (see [CONTRIBUTING.md](./CONTRIBUTING.md#propose-a-solution-for-the-job)).
+Follow the **same proposal review process** as any other App job, but remember to review the MelvinBot proposal first, and then review in first-come-first-serve review order for proposals posted after the `Help Wanted` is applied (see [CONTRIBUTING.md](./CONTRIBUTING.md#propose-a-solution-for-the-job)).
 
 1. Use the [proposal template](./PROPOSAL_TEMPLATE.md) criteria: clear root cause, concrete solution, no code diffs.
 2. C+ reviews Melvin's proposal with the same rigor as a contributor proposal. Do not approve proposals that lack a satisfying root-cause explanation.

From 853b670352ebc90502674293c7ca8ba94303ee27 Mon Sep 17 00:00:00 2001
From: neil-marcellini <neil@expensify.com>
Date: Wed, 10 Jun 2026 08:03:45 -0400
Subject: [PATCH 267/435] Remove what not to do section since it's all
 duplicates

---
 contributingGuides/HOW_TO_WORK_WITH_MELVINBOT.md | 11 -----------
 1 file changed, 11 deletions(-)

diff --git a/contributingGuides/HOW_TO_WORK_WITH_MELVINBOT.md b/contributingGuides/HOW_TO_WORK_WITH_MELVINBOT.md
index 9b7ab7cbd9f4..da3b0101a5d9 100644
--- a/contributingGuides/HOW_TO_WORK_WITH_MELVINBOT.md
+++ b/contributingGuides/HOW_TO_WORK_WITH_MELVINBOT.md
@@ -96,17 +96,6 @@ After the C+ submits the PR for review:
 
 We intentionally do **not** add a second round of contributor or C+ PR review on top of the CME review. Prior discussions did not surface a problem that extra review would solve, and an additional review step would add cost and delay without clear benefit. The C+ self-review before submission, combined with CME review, is the intended quality gate.
 
-## Quick reference: what not to do
-
-| Do not | Why |
-|--------|-----|
-| Open a PR before a proposal is accepted | Wastes contributor and reviewer time if the approach is wrong |
-| Ask `@MelvinBot` to implement before the CME approves the proposal | Implementation must wait for CME approval, not just C+ recommendation |
-| Skip C+ proposal review because Melvin wrote it | Melvin proposals need the same validation as human proposals |
-| Send Melvin's draft PR for CME review without testing and checklist completion | The C+ is the human author and owns quality |
-| Assume you can edit Melvin's PR description in the GitHub UI | Post the body in a PR comment and ask `@MelvinBot` to apply it |
-| Expect a second C+ or contributor review after C+ submission | Only the CME reviews before merge |
-
 ## Related documentation
 
 - [CONTRIBUTING.md](./CONTRIBUTING.md) — full contributor workflow

From 89ba4da67c481d2f10f6e1fc2c0d78babc7c73d4 Mon Sep 17 00:00:00 2001
From: Issa Nimaga <inimaga@expensify.com>
Date: Wed, 10 Jun 2026 13:27:08 +0100
Subject: [PATCH 268/435] Fix AgentZero indicator selector crash

---
 src/selectors/ReportNameValuePairs.ts  | 21 +++++++++++++++++----
 src/types/onyx/ReportNameValuePairs.ts |  7 ++++---
 2 files changed, 21 insertions(+), 7 deletions(-)

diff --git a/src/selectors/ReportNameValuePairs.ts b/src/selectors/ReportNameValuePairs.ts
index 939aba91fd62..008a814e09c3 100644
--- a/src/selectors/ReportNameValuePairs.ts
+++ b/src/selectors/ReportNameValuePairs.ts
@@ -2,6 +2,12 @@ import type {OnyxEntry} from 'react-native-onyx';
 import CONST from '@src/CONST';
 import type {ReportNameValuePairs} from '@src/types/onyx';
 
+type AgentZeroProcessingIndicator = NonNullable<ReportNameValuePairs['agentZeroProcessingRequestIndicator']>;
+
+function isAgentZeroProcessingIndicatorMap(indicator: AgentZeroProcessingIndicator): indicator is Record<string, string | null> {
+    return typeof indicator === 'object' && indicator !== null && !Array.isArray(indicator);
+}
+
 /**
  * Reads the AgentZero processing-indicator label for a single agent, trimmed.
  *
@@ -16,7 +22,11 @@ function getAgentZeroProcessingLabel(reportNameValuePairs: OnyxEntry<ReportNameV
     if (typeof indicator === 'string') {
         return agentAccountID === CONST.ACCOUNT_ID.CONCIERGE ? indicator.trim() : '';
     }
-    return indicator[String(agentAccountID)]?.trim() ?? '';
+    if (!isAgentZeroProcessingIndicatorMap(indicator)) {
+        return '';
+    }
+    const label = indicator[String(agentAccountID)];
+    return typeof label === 'string' ? label.trim() : '';
 }
 
 /**
@@ -31,9 +41,12 @@ function agentZeroProcessingAgentIDsSelector(reportNameValuePairs: OnyxEntry<Rep
     if (typeof indicator === 'string') {
         return indicator.trim() ? [CONST.ACCOUNT_ID.CONCIERGE] : [];
     }
-    return Object.keys(indicator)
-        .filter((key) => !!indicator[key]?.trim())
-        .map(Number)
+    if (!isAgentZeroProcessingIndicatorMap(indicator)) {
+        return [];
+    }
+    return Object.entries(indicator)
+        .filter(([, label]) => typeof label === 'string' && !!label.trim())
+        .map(([key]) => Number(key))
         .filter((accountID) => !Number.isNaN(accountID))
         .sort((a, b) => a - b);
 }
diff --git a/src/types/onyx/ReportNameValuePairs.ts b/src/types/onyx/ReportNameValuePairs.ts
index f96c140e37bb..8a193c2fa67a 100644
--- a/src/types/onyx/ReportNameValuePairs.ts
+++ b/src/types/onyx/ReportNameValuePairs.ts
@@ -85,10 +85,11 @@ type ReportNameValuePairs = OnyxCommon.OnyxValueWithOfflineFeedback<{
     /**
      * Agent Zero processing-indicator labels, keyed by the persona accountID (Concierge or a
      * custom agent) so a room with several agents shows one bubble per actively-thinking agent.
-     * Each value is the status string for that agent. A legacy scalar string may still arrive
-     * during a backend/client deploy overlap and is attributed to Concierge.
+     * Each value is the status string for that agent. A null value clears that agent's slot during
+     * local Onyx merge transitions. A legacy scalar string may still arrive during a backend/client
+     * deploy overlap and is attributed to Concierge.
      */
-    agentZeroProcessingRequestIndicator?: Record<string, string> | string;
+    agentZeroProcessingRequestIndicator?: Record<string, string | null> | string;
 
     /** Parent report ID */
     parentReportID?: string;

From b3d60dc52deddae37374ede6b8d9fcc0b1f90590 Mon Sep 17 00:00:00 2001
From: Rodrigo Lino da Costa <rodrigo@expensify.com>
Date: Wed, 10 Jun 2026 09:46:37 -0300
Subject: [PATCH 269/435] match messages from backend

---
 src/languages/de.ts                  | 10 ----
 src/languages/en.ts                  | 16 +++----
 src/languages/es.ts                  | 18 +++-----
 src/languages/fr.ts                  | 10 ----
 src/languages/it.ts                  | 14 ------
 src/languages/ja.ts                  | 10 ----
 src/languages/nl.ts                  | 10 ----
 src/languages/pl.ts                  | 10 ----
 src/languages/pt-BR.ts               | 10 ----
 src/languages/zh-hans.ts             | 10 ----
 src/libs/ReportActionsUtils.ts       | 63 ++++++++-----------------
 tests/unit/ReportActionsUtilsTest.ts | 69 ++++++++++++++++++++++++++++
 12 files changed, 99 insertions(+), 151 deletions(-)

diff --git a/src/languages/de.ts b/src/languages/de.ts
index 6980ed3f5f9c..c369aa736693 100644
--- a/src/languages/de.ts
+++ b/src/languages/de.ts
@@ -8066,16 +8066,6 @@ Fügen Sie weitere Ausgabelimits hinzu, um den Cashflow Ihres Unternehmens zu sc
         addCustomUnitRateWithAmountAndEndDate: (rateName: string, rateValue: string, endDate: string) => `„${rateName}“-Satz von ${rateValue} hinzugefügt, gültig bis ${endDate}`,
         addCustomUnitRateWithAmountAndDates: (rateName: string, rateValue: string, startDate: string, endDate: string) =>
             `hat den Tarif „${rateName}“ mit ${rateValue} hinzugefügt, gültig vom ${startDate} bis ${endDate}`,
-        updatedCustomUnitRateStartDate: (rateName: string, newDate: string, oldDate?: string) =>
-            oldDate ? `Startdatum des Tarifs „${rateName}“ auf ${newDate} aktualisiert (zuvor ${oldDate})` : `Startdatum des Tarifs „${rateName}“ auf ${newDate} festlegen`,
-        updatedCustomUnitRateEndDate: (rateName: string, newDate: string, oldDate?: string) =>
-            oldDate ? `Enddatum des Tarifs „${rateName}“ auf ${newDate} aktualisiert (zuvor ${oldDate})` : `Enddatum des Tarifs „${rateName}“ auf ${newDate} setzen`,
-        updatedCustomUnitRateStartAndEndDate: (rateName: string, newStartDate: string, newEndDate: string, oldStartDate?: string, oldEndDate?: string) =>
-            oldStartDate && oldEndDate
-                ? `Start- und Enddatum des Tarifs „${rateName}“ auf ${newStartDate} - ${newEndDate} aktualisiert (zuvor ${oldStartDate} - ${oldEndDate})`
-                : `Start- und Enddatum des Tarifs „${rateName}“ auf ${newStartDate} – ${newEndDate} festlegen`,
-        removedCustomUnitRateStartDate: (rateName: string, oldDate: string) => `Startdatum aus Tarif „${rateName}“ entfernt (zuvor ${oldDate})`,
-        removedCustomUnitRateEndDate: (rateName: string, oldDate: string) => `Enddatum aus dem Tarif „${rateName}“ entfernt (zuvor ${oldDate})`,
     },
     roomMembersPage: {
         memberNotFound: 'Mitglied nicht gefunden.',
diff --git a/src/languages/en.ts b/src/languages/en.ts
index c12c99b6fb2f..00f01c515711 100644
--- a/src/languages/en.ts
+++ b/src/languages/en.ts
@@ -7724,16 +7724,12 @@ const translations = {
         updatedCustomUnitRateEnabled: (customUnitName: string, customUnitRateName: string, newValue: boolean) => {
             return `${newValue ? 'enabled' : 'disabled'} the ${customUnitName} rate "${customUnitRateName}"`;
         },
-        updatedCustomUnitRateStartDate: (rateName: string, newDate: string, oldDate?: string) =>
-            oldDate ? `updated start date of "${rateName}" rate to ${newDate} (previously ${oldDate})` : `set start date of "${rateName}" rate to ${newDate}`,
-        updatedCustomUnitRateEndDate: (rateName: string, newDate: string, oldDate?: string) =>
-            oldDate ? `updated end date of "${rateName}" rate to ${newDate} (previously ${oldDate})` : `set end date of "${rateName}" rate to ${newDate}`,
-        updatedCustomUnitRateStartAndEndDate: (rateName: string, newStartDate: string, newEndDate: string, oldStartDate?: string, oldEndDate?: string) =>
-            oldStartDate && oldEndDate
-                ? `updated start and end date of "${rateName}" rate to ${newStartDate} - ${newEndDate} (previously ${oldStartDate} - ${oldEndDate})`
-                : `set start and end date of "${rateName}" rate to ${newStartDate} - ${newEndDate}`,
-        removedCustomUnitRateStartDate: (rateName: string, oldDate: string) => `removed start date from "${rateName}" rate (previously ${oldDate})`,
-        removedCustomUnitRateEndDate: (rateName: string, oldDate: string) => `removed end date from "${rateName}" rate (previously ${oldDate})`,
+        updatedCustomUnitRateDateRange: (rateName: string, newDateRange: string, oldDateRange: string) =>
+            `updated the distance rate "${rateName}" to apply ${newDateRange} (previously ${oldDateRange})`,
+        customUnitRateDateRangeStartToEnd: (startDate: string, endDate: string) => `${startDate} - ${endDate}`,
+        customUnitRateDateRangeFrom: (date: string) => `from ${date}`,
+        customUnitRateDateRangeUntilEnd: (date: string) => `until ${date}`,
+        customUnitRateDateRangeAllDates: () => `for all dates`,
         updateReportFieldDefaultValue: (defaultValue?: string, fieldName?: string) => `set the default value of report field "${fieldName}" to "${defaultValue}"`,
         addedReportFieldOption: (fieldName: string, optionName: string) => `added the option "${optionName}" to the report field "${fieldName}"`,
         removedReportFieldOption: (fieldName: string, optionName: string) => `removed the option "${optionName}" from the report field "${fieldName}"`,
diff --git a/src/languages/es.ts b/src/languages/es.ts
index 627428c7c49a..2c9526b631d7 100644
--- a/src/languages/es.ts
+++ b/src/languages/es.ts
@@ -7864,18 +7864,12 @@ ${amount} para ${merchant} - ${date}`,
         addCustomUnitRateWithAmountAndEndDate: (rateName: string, rateValue: string, endDate: string) => `añadió la tasa "${rateName}" de ${rateValue}, válida hasta ${endDate}`,
         addCustomUnitRateWithAmountAndDates: (rateName: string, rateValue: string, startDate: string, endDate: string) =>
             `añadió la tasa "${rateName}" de ${rateValue}, válida del ${startDate} al ${endDate}`,
-        updatedCustomUnitRateStartDate: (rateName: string, newDate: string, oldDate?: string) =>
-            oldDate ? `actualizó la fecha de inicio de la tasa "${rateName}" a ${newDate} (previamente ${oldDate})` : `establecer la fecha de inicio de la tasa "${rateName}" a ${newDate}`,
-        updatedCustomUnitRateEndDate: (rateName: string, newDate: string, oldDate?: string) =>
-            oldDate
-                ? `actualizó la fecha de finalización de la tasa "${rateName}" a ${newDate} (previamente ${oldDate})`
-                : `establecer la fecha de finalización de la tasa "${rateName}" en ${newDate}`,
-        updatedCustomUnitRateStartAndEndDate: (rateName: string, newStartDate: string, newEndDate: string, oldStartDate?: string, oldEndDate?: string) =>
-            oldStartDate && oldEndDate
-                ? `actualizó la fecha de inicio y fin de la tasa "${rateName}" a ${newStartDate} - ${newEndDate} (previamente ${oldStartDate} - ${oldEndDate})`
-                : `establece la fecha de inicio y fin de la tasa "${rateName}" a ${newStartDate} - ${newEndDate}`,
-        removedCustomUnitRateStartDate: (rateName: string, oldDate: string) => `se eliminó la fecha de inicio de la tasa "${rateName}" (previamente ${oldDate})`,
-        removedCustomUnitRateEndDate: (rateName: string, oldDate: string) => `eliminó la fecha de finalización de la tasa «${rateName}» (previamente ${oldDate})`,
+        updatedCustomUnitRateDateRange: (rateName: string, newDateRange: string, oldDateRange: string) =>
+            `actualizó la tasa de distancia "${rateName}" para que aplique ${newDateRange} (previamente ${oldDateRange})`,
+        customUnitRateDateRangeStartToEnd: (startDate: string, endDate: string) => `${startDate} - ${endDate}`,
+        customUnitRateDateRangeFrom: (date: string) => `desde ${date}`,
+        customUnitRateDateRangeUntilEnd: (date: string) => `hasta ${date}`,
+        customUnitRateDateRangeAllDates: () => `para todas las fechas`,
     },
     roomMembersPage: {
         memberNotFound: 'Miembro no encontrado.',
diff --git a/src/languages/fr.ts b/src/languages/fr.ts
index f9e5bbd1bd46..acadd45d9ab8 100644
--- a/src/languages/fr.ts
+++ b/src/languages/fr.ts
@@ -8102,16 +8102,6 @@ Ajoutez davantage de règles de dépenses pour protéger la trésorerie de l’e
         addCustomUnitRateWithAmountAndEndDate: (rateName: string, rateValue: string, endDate: string) => `a ajouté le taux « ${rateName} » de ${rateValue}, valable jusqu’au ${endDate}`,
         addCustomUnitRateWithAmountAndDates: (rateName: string, rateValue: string, startDate: string, endDate: string) =>
             `a ajouté le taux « ${rateName} » de ${rateValue}, valable du ${startDate} au ${endDate}`,
-        updatedCustomUnitRateStartDate: (rateName: string, newDate: string, oldDate?: string) =>
-            oldDate ? `a mis à jour la date de début du taux « ${rateName} » à ${newDate} (auparavant ${oldDate})` : `définir la date de début du taux « ${rateName} » sur ${newDate}`,
-        updatedCustomUnitRateEndDate: (rateName: string, newDate: string, oldDate?: string) =>
-            oldDate ? `a mis à jour la date de fin du taux « ${rateName} » à ${newDate} (auparavant ${oldDate})` : `définir la date de fin du taux « ${rateName} » sur ${newDate}`,
-        updatedCustomUnitRateStartAndEndDate: (rateName: string, newStartDate: string, newEndDate: string, oldStartDate?: string, oldEndDate?: string) =>
-            oldStartDate && oldEndDate
-                ? `a mis à jour les dates de début et de fin du taux « ${rateName} » en ${newStartDate} - ${newEndDate} (précédemment ${oldStartDate} - ${oldEndDate})`
-                : `définir les dates de début et de fin du taux « ${rateName} » sur ${newStartDate} - ${newEndDate}`,
-        removedCustomUnitRateStartDate: (rateName: string, oldDate: string) => `a supprimé la date de début du taux « ${rateName} » (précédemment ${oldDate})`,
-        removedCustomUnitRateEndDate: (rateName: string, oldDate: string) => `a supprimé la date de fin du taux « ${rateName} » (auparavant ${oldDate})`,
     },
     roomMembersPage: {
         memberNotFound: 'Membre introuvable.',
diff --git a/src/languages/it.ts b/src/languages/it.ts
index 680fa15058fa..0e93d13876c7 100644
--- a/src/languages/it.ts
+++ b/src/languages/it.ts
@@ -8056,20 +8056,6 @@ Aggiungi altre regole di spesa per proteggere il flusso di cassa aziendale.`,
         addCustomUnitRateWithAmountAndEndDate: (rateName: string, rateValue: string, endDate: string) => `ha aggiunto la tariffa "${rateName}" di ${rateValue}, valida fino al ${endDate}`,
         addCustomUnitRateWithAmountAndDates: (rateName: string, rateValue: string, startDate: string, endDate: string) =>
             `ha aggiunto la tariffa "${rateName}" di ${rateValue}, valida dal ${startDate} al ${endDate}`,
-        updatedCustomUnitRateStartDate: (rateName: string, newDate: string, oldDate?: string) =>
-            oldDate
-                ? `aggiornata la data di inizio della tariffa "${rateName}" a ${newDate} (in precedenza ${oldDate})`
-                : `imposta la data di inizio della tariffa "${rateName}" su ${newDate}`,
-        updatedCustomUnitRateEndDate: (rateName: string, newDate: string, oldDate?: string) =>
-            oldDate
-                ? `ha aggiornato la data di fine della tariffa "${rateName}" a ${newDate} (in precedenza ${oldDate})`
-                : `imposta la data di fine della tariffa "${rateName}" al ${newDate}`,
-        updatedCustomUnitRateStartAndEndDate: (rateName: string, newStartDate: string, newEndDate: string, oldStartDate?: string, oldEndDate?: string) =>
-            oldStartDate && oldEndDate
-                ? `ha aggiornato la data di inizio e fine della tariffa "${rateName}" in ${newStartDate} - ${newEndDate} (in precedenza ${oldStartDate} - ${oldEndDate})`
-                : `imposta data di inizio e fine della tariffa "${rateName}" su ${newStartDate} - ${newEndDate}`,
-        removedCustomUnitRateStartDate: (rateName: string, oldDate: string) => `rimossa la data di inizio dalla tariffa "${rateName}" (in precedenza ${oldDate})`,
-        removedCustomUnitRateEndDate: (rateName: string, oldDate: string) => `data di fine rimossa dalla tariffa "${rateName}" (precedentemente ${oldDate})`,
     },
     roomMembersPage: {
         memberNotFound: 'Membro non trovato.',
diff --git a/src/languages/ja.ts b/src/languages/ja.ts
index 34febe75c522..bb9e853ea13a 100644
--- a/src/languages/ja.ts
+++ b/src/languages/ja.ts
@@ -7960,16 +7960,6 @@ ${reportName}
         addCustomUnitRateWithAmountAndEndDate: (rateName: string, rateValue: string, endDate: string) => `「${rateName}」レート（${rateValue}）を${endDate}まで有効として追加しました`,
         addCustomUnitRateWithAmountAndDates: (rateName: string, rateValue: string, startDate: string, endDate: string) =>
             `「${rateName}」レート（${rateValue}）を追加しました。有効期間：${startDate}〜${endDate}`,
-        updatedCustomUnitRateStartDate: (rateName: string, newDate: string, oldDate?: string) =>
-            oldDate ? `「${rateName}」レートの開始日を${newDate}に更新しました（以前は${oldDate}）` : `「${rateName}」レートの開始日を${newDate}に設定する`,
-        updatedCustomUnitRateEndDate: (rateName: string, newDate: string, oldDate?: string) =>
-            oldDate ? `「${rateName}」レートの終了日を${newDate}（以前は${oldDate}）に更新しました` : `「${rateName}」レートの終了日を${newDate}に設定します`,
-        updatedCustomUnitRateStartAndEndDate: (rateName: string, newStartDate: string, newEndDate: string, oldStartDate?: string, oldEndDate?: string) =>
-            oldStartDate && oldEndDate
-                ? `「${rateName}」レートの開始日と終了日を${newStartDate}〜${newEndDate}に更新しました（以前は${oldStartDate}〜${oldEndDate}）`
-                : `「${rateName}」レートの開始日と終了日を${newStartDate}〜${newEndDate}に設定しました`,
-        removedCustomUnitRateStartDate: (rateName: string, oldDate: string) => `「${rateName}」レートの開始日を削除しました（以前の開始日：${oldDate}）`,
-        removedCustomUnitRateEndDate: (rateName: string, oldDate: string) => `「${rateName}」レートの終了日を削除しました（以前は ${oldDate}）`,
     },
     roomMembersPage: {
         memberNotFound: 'メンバーが見つかりません。',
diff --git a/src/languages/nl.ts b/src/languages/nl.ts
index de2bb6b65066..1b8a9206fb7a 100644
--- a/src/languages/nl.ts
+++ b/src/languages/nl.ts
@@ -8023,16 +8023,6 @@ er bestedingsregels toe om de kasstroom van het bedrijf te beschermen.`,
         addCustomUnitRateWithAmountAndEndDate: (rateName: string, rateValue: string, endDate: string) => `heeft tarief „${rateName}” van ${rateValue} toegevoegd, geldig tot ${endDate}`,
         addCustomUnitRateWithAmountAndDates: (rateName: string, rateValue: string, startDate: string, endDate: string) =>
             `heeft tarief "${rateName}" van ${rateValue} toegevoegd, geldig van ${startDate} - ${endDate}`,
-        updatedCustomUnitRateStartDate: (rateName: string, newDate: string, oldDate?: string) =>
-            oldDate ? `startdatum van tarief "${rateName}" bijgewerkt naar ${newDate} (voorheen ${oldDate})` : `startdatum van tarief "${rateName}" instellen op ${newDate}`,
-        updatedCustomUnitRateEndDate: (rateName: string, newDate: string, oldDate?: string) =>
-            oldDate ? `einddatum van tarief "${rateName}" bijgewerkt naar ${newDate} (voorheen ${oldDate})` : `einddatum van tarief "${rateName}" instellen op ${newDate}`,
-        updatedCustomUnitRateStartAndEndDate: (rateName: string, newStartDate: string, newEndDate: string, oldStartDate?: string, oldEndDate?: string) =>
-            oldStartDate && oldEndDate
-                ? `start- en einddatum van tarief "${rateName}" bijgewerkt naar ${newStartDate} - ${newEndDate} (voorheen ${oldStartDate} - ${oldEndDate})`
-                : `start- en einddatum van tarief "${rateName}" ingesteld op ${newStartDate} - ${newEndDate}`,
-        removedCustomUnitRateStartDate: (rateName: string, oldDate: string) => `startdatum verwijderd van tarief "${rateName}" (voorheen ${oldDate})`,
-        removedCustomUnitRateEndDate: (rateName: string, oldDate: string) => `einddatum verwijderd van tarief "${rateName}" (voorheen ${oldDate})`,
     },
     roomMembersPage: {
         memberNotFound: 'Lid niet gevonden.',
diff --git a/src/languages/pl.ts b/src/languages/pl.ts
index eb7566eaf3e4..64d08d1c62dc 100644
--- a/src/languages/pl.ts
+++ b/src/languages/pl.ts
@@ -8016,16 +8016,6 @@ Dodaj więcej zasad wydatków, żeby chronić płynność finansową firmy.`,
         addCustomUnitRateWithAmountAndEndDate: (rateName: string, rateValue: string, endDate: string) => `dodano stawkę „${rateName}” w wysokości ${rateValue}, obowiązującą do ${endDate}`,
         addCustomUnitRateWithAmountAndDates: (rateName: string, rateValue: string, startDate: string, endDate: string) =>
             `dodano stawkę „${rateName}” w wysokości ${rateValue}, obowiązującą od ${startDate} do ${endDate}`,
-        updatedCustomUnitRateStartDate: (rateName: string, newDate: string, oldDate?: string) =>
-            oldDate ? `zaktualizowano datę rozpoczęcia stawki „${rateName}” na ${newDate} (wcześniej ${oldDate})` : `ustaw datę rozpoczęcia stawki „${rateName}” na ${newDate}`,
-        updatedCustomUnitRateEndDate: (rateName: string, newDate: string, oldDate?: string) =>
-            oldDate ? `zaktualizowano datę końcową stawki „${rateName}” na ${newDate} (wcześniej ${oldDate})` : `ustaw datę zakończenia stawki „${rateName}” na ${newDate}`,
-        updatedCustomUnitRateStartAndEndDate: (rateName: string, newStartDate: string, newEndDate: string, oldStartDate?: string, oldEndDate?: string) =>
-            oldStartDate && oldEndDate
-                ? `zaktualizowano datę początkową i końcową stawki „${rateName}” na ${newStartDate} – ${newEndDate} (wcześniej ${oldStartDate} – ${oldEndDate})`
-                : `ustaw początkową i końcową datę stawki „${rateName}” na ${newStartDate} – ${newEndDate}`,
-        removedCustomUnitRateStartDate: (rateName: string, oldDate: string) => `usunięto datę początkową ze stawki „${rateName}” (wcześniej ${oldDate})`,
-        removedCustomUnitRateEndDate: (rateName: string, oldDate: string) => `usunięto datę zakończenia ze stawki „${rateName}” (wcześniej ${oldDate})`,
     },
     roomMembersPage: {
         memberNotFound: 'Nie znaleziono członka.',
diff --git a/src/languages/pt-BR.ts b/src/languages/pt-BR.ts
index 84a91ce99ba9..6328541ffbe0 100644
--- a/src/languages/pt-BR.ts
+++ b/src/languages/pt-BR.ts
@@ -8018,16 +8018,6 @@ Adicione mais regras de gasto para proteger o fluxo de caixa da empresa.`,
         addCustomUnitRateWithAmountAndEndDate: (rateName: string, rateValue: string, endDate: string) => `adicionou a taxa "${rateName}" de ${rateValue}, válida até ${endDate}`,
         addCustomUnitRateWithAmountAndDates: (rateName: string, rateValue: string, startDate: string, endDate: string) =>
             `adicionou a tarifa "${rateName}" de ${rateValue}, válida de ${startDate} a ${endDate}`,
-        updatedCustomUnitRateStartDate: (rateName: string, newDate: string, oldDate?: string) =>
-            oldDate ? `atualizou a data de início da tarifa "${rateName}" para ${newDate} (antes ${oldDate})` : `definir data de início da tarifa "${rateName}" para ${newDate}`,
-        updatedCustomUnitRateEndDate: (rateName: string, newDate: string, oldDate?: string) =>
-            oldDate ? `atualizou a data de término da tarifa "${rateName}" para ${newDate} (antes ${oldDate})` : `definir data de término da tarifa "${rateName}" para ${newDate}`,
-        updatedCustomUnitRateStartAndEndDate: (rateName: string, newStartDate: string, newEndDate: string, oldStartDate?: string, oldEndDate?: string) =>
-            oldStartDate && oldEndDate
-                ? `atualizou a data de início e término da tarifa "${rateName}" para ${newStartDate} - ${newEndDate} (antes ${oldStartDate} - ${oldEndDate})`
-                : `define a data de início e de término da tarifa "${rateName}" para ${newStartDate} - ${newEndDate}`,
-        removedCustomUnitRateStartDate: (rateName: string, oldDate: string) => `removeu a data de início da tarifa "${rateName}" (antes ${oldDate})`,
-        removedCustomUnitRateEndDate: (rateName: string, oldDate: string) => `removeu a data de término da tarifa "${rateName}" (anteriormente ${oldDate})`,
     },
     roomMembersPage: {
         memberNotFound: 'Membro não encontrado.',
diff --git a/src/languages/zh-hans.ts b/src/languages/zh-hans.ts
index bb0b14546614..1c7240882f91 100644
--- a/src/languages/zh-hans.ts
+++ b/src/languages/zh-hans.ts
@@ -7808,16 +7808,6 @@ ${reportName}
         addCustomUnitRateWithAmountAndEndDate: (rateName: string, rateValue: string, endDate: string) => `已添加“${rateName}”费率 ${rateValue}，有效期至 ${endDate}`,
         addCustomUnitRateWithAmountAndDates: (rateName: string, rateValue: string, startDate: string, endDate: string) =>
             `已添加“${rateName}”费率 ${rateValue}，有效期为 ${startDate} - ${endDate}`,
-        updatedCustomUnitRateStartDate: (rateName: string, newDate: string, oldDate?: string) =>
-            oldDate ? `将“${rateName}”费率的开始日期更新为 ${newDate}（之前为 ${oldDate}）` : `将“${rateName}”费率的开始日期设置为 ${newDate}`,
-        updatedCustomUnitRateEndDate: (rateName: string, newDate: string, oldDate?: string) =>
-            oldDate ? `已将“${rateName}”费率的结束日期更新为 ${newDate}（之前为 ${oldDate}）` : `将“${rateName}”费率的结束日期设置为 ${newDate}`,
-        updatedCustomUnitRateStartAndEndDate: (rateName: string, newStartDate: string, newEndDate: string, oldStartDate?: string, oldEndDate?: string) =>
-            oldStartDate && oldEndDate
-                ? `已将“${rateName}”费率的起止日期更新为 ${newStartDate} - ${newEndDate}（此前为 ${oldStartDate} - ${oldEndDate}）`
-                : `将“${rateName}”费率的开始和结束日期设为 ${newStartDate} - ${newEndDate}`,
-        removedCustomUnitRateStartDate: (rateName: string, oldDate: string) => `已从“${rateName}”费率中移除开始日期（原为 ${oldDate}）`,
-        removedCustomUnitRateEndDate: (rateName: string, oldDate: string) => `已从“${rateName}”费率中移除结束日期（之前为 ${oldDate}）`,
     },
     roomMembersPage: {
         memberNotFound: '未找到成员。',
diff --git a/src/libs/ReportActionsUtils.ts b/src/libs/ReportActionsUtils.ts
index 686db6232c37..2536566d4c4f 100644
--- a/src/libs/ReportActionsUtils.ts
+++ b/src/libs/ReportActionsUtils.ts
@@ -3191,6 +3191,19 @@ function getWorkspaceCustomUnitRateAddedMessage(translate: LocalizedTranslate, a
     return getReportActionText(action);
 }
 
+function getCustomUnitRateDateRangeForMessage(translate: LocalizedTranslate, startDate?: string, endDate?: string): string {
+    if (startDate && endDate) {
+        return translate('workspaceActions.customUnitRateDateRangeStartToEnd', DateUtils.formatToReadableString(startDate), DateUtils.formatToReadableString(endDate));
+    }
+    if (startDate) {
+        return translate('workspaceActions.customUnitRateDateRangeFrom', DateUtils.formatToReadableString(startDate));
+    }
+    if (endDate) {
+        return translate('workspaceActions.customUnitRateDateRangeUntilEnd', DateUtils.formatToReadableString(endDate));
+    }
+    return translate('workspaceActions.customUnitRateDateRangeAllDates');
+}
+
 function getWorkspaceCustomUnitRateUpdatedMessage(translate: LocalizedTranslate, action: ReportAction): string {
     const {customUnitName, customUnitRateName, updatedField, oldValue, newValue, newTaxPercentage, oldTaxPercentage, newStartDate, newEndDate, oldStartDate, oldEndDate} =
         getOriginalMessage(action as ReportAction<typeof CONST.REPORT.ACTIONS.TYPE.POLICY_CHANGE_LOG.UPDATE_CUSTOM_UNIT_RATE>) ?? {};
@@ -3223,52 +3236,12 @@ function getWorkspaceCustomUnitRateUpdatedMessage(translate: LocalizedTranslate,
     }
 
     if (customUnitRateName && updatedField === RATE_CHANGELOG_UPDATED_FIELD.DATE_RANGE) {
-        const startDateChanged = newStartDate !== oldStartDate;
-        const endDateChanged = newEndDate !== oldEndDate;
-
-        if (startDateChanged && endDateChanged && newStartDate && newEndDate) {
-            const formattedOldStartDate = oldStartDate ? DateUtils.formatToReadableString(oldStartDate) : undefined;
-            const formattedOldEndDate = oldEndDate ? DateUtils.formatToReadableString(oldEndDate) : undefined;
-            return translate(
-                'workspaceActions.updatedCustomUnitRateStartAndEndDate',
-                customUnitRateName,
-                DateUtils.formatToReadableString(newStartDate),
-                DateUtils.formatToReadableString(newEndDate),
-                formattedOldStartDate,
-                formattedOldEndDate,
-            );
-        }
-
-        let startDateMessage = '';
-        let endDateMessage = '';
-
-        if (startDateChanged) {
-            if (!newStartDate && oldStartDate) {
-                startDateMessage = translate('workspaceActions.removedCustomUnitRateStartDate', customUnitRateName, DateUtils.formatToReadableString(oldStartDate));
-            } else if (newStartDate) {
-                const formattedOldDate = oldStartDate ? DateUtils.formatToReadableString(oldStartDate) : undefined;
-                startDateMessage = translate('workspaceActions.updatedCustomUnitRateStartDate', customUnitRateName, DateUtils.formatToReadableString(newStartDate), formattedOldDate);
-            }
-        }
-
-        if (endDateChanged) {
-            if (!newEndDate && oldEndDate) {
-                endDateMessage = translate('workspaceActions.removedCustomUnitRateEndDate', customUnitRateName, DateUtils.formatToReadableString(oldEndDate));
-            } else if (newEndDate) {
-                const formattedOldDate = oldEndDate ? DateUtils.formatToReadableString(oldEndDate) : undefined;
-                endDateMessage = translate('workspaceActions.updatedCustomUnitRateEndDate', customUnitRateName, DateUtils.formatToReadableString(newEndDate), formattedOldDate);
-            }
-        }
-
-        if (startDateMessage && endDateMessage) {
-            return `${startDateMessage}, ${endDateMessage}`;
-        }
-        if (startDateMessage) {
-            return startDateMessage;
-        }
-        if (endDateMessage) {
-            return endDateMessage;
+        const oldDateRange = getCustomUnitRateDateRangeForMessage(translate, oldStartDate, oldEndDate);
+        let newDateRange = getCustomUnitRateDateRangeForMessage(translate, newStartDate, newEndDate);
+        if (newStartDate && newEndDate) {
+            newDateRange = translate('workspaceActions.customUnitRateDateRangeFrom', newDateRange);
         }
+        return translate('workspaceActions.updatedCustomUnitRateDateRange', customUnitRateName, newDateRange, oldDateRange);
     }
 
     return getReportActionText(action);
diff --git a/tests/unit/ReportActionsUtilsTest.ts b/tests/unit/ReportActionsUtilsTest.ts
index 51d41614c46a..6159084e607d 100644
--- a/tests/unit/ReportActionsUtilsTest.ts
+++ b/tests/unit/ReportActionsUtilsTest.ts
@@ -3994,6 +3994,75 @@ describe('ReportActionsUtils', () => {
             const actual = ReportActionsUtils.getWorkspaceCustomUnitRateUpdatedMessage(translateLocal, action);
             expect(actual).toBe('renamed the Distance rate "Default Rate" to "Custom Rate"');
         });
+
+        it('should return the correct message when a start date is set on a rate without dates', () => {
+            const action: ReportAction<typeof CONST.REPORT.ACTIONS.TYPE.POLICY_CHANGE_LOG.UPDATE_CUSTOM_UNIT_RATE> = {
+                reportActionID: '1',
+                actionName: CONST.REPORT.ACTIONS.TYPE.POLICY_CHANGE_LOG.UPDATE_CUSTOM_UNIT_RATE,
+                created: '',
+                originalMessage: {
+                    customUnitName: 'Distance',
+                    customUnitRateName: 'Default Rate',
+                    updatedField: 'dateRange',
+                    newStartDate: '2026-04-01',
+                },
+            };
+            const actual = ReportActionsUtils.getWorkspaceCustomUnitRateUpdatedMessage(translateLocal, action);
+            expect(actual).toBe('updated the distance rate "Default Rate" to apply from April 1, 2026 (previously for all dates)');
+        });
+
+        it('should return the correct message when both start and end dates are changed', () => {
+            const action: ReportAction<typeof CONST.REPORT.ACTIONS.TYPE.POLICY_CHANGE_LOG.UPDATE_CUSTOM_UNIT_RATE> = {
+                reportActionID: '1',
+                actionName: CONST.REPORT.ACTIONS.TYPE.POLICY_CHANGE_LOG.UPDATE_CUSTOM_UNIT_RATE,
+                created: '',
+                originalMessage: {
+                    customUnitName: 'Distance',
+                    customUnitRateName: 'Default Rate',
+                    updatedField: 'dateRange',
+                    newStartDate: '2026-04-01',
+                    newEndDate: '2026-05-31',
+                    oldStartDate: '2026-03-01',
+                    oldEndDate: '2026-04-30',
+                },
+            };
+            const actual = ReportActionsUtils.getWorkspaceCustomUnitRateUpdatedMessage(translateLocal, action);
+            expect(actual).toBe('updated the distance rate "Default Rate" to apply from April 1, 2026 - May 31, 2026 (previously March 1, 2026 - April 30, 2026)');
+        });
+
+        it('should return the correct message when an end date is changed', () => {
+            const action: ReportAction<typeof CONST.REPORT.ACTIONS.TYPE.POLICY_CHANGE_LOG.UPDATE_CUSTOM_UNIT_RATE> = {
+                reportActionID: '1',
+                actionName: CONST.REPORT.ACTIONS.TYPE.POLICY_CHANGE_LOG.UPDATE_CUSTOM_UNIT_RATE,
+                created: '',
+                originalMessage: {
+                    customUnitName: 'Distance',
+                    customUnitRateName: 'Default Rate',
+                    updatedField: 'dateRange',
+                    newEndDate: '2026-05-31',
+                    oldEndDate: '2026-04-30',
+                },
+            };
+            const actual = ReportActionsUtils.getWorkspaceCustomUnitRateUpdatedMessage(translateLocal, action);
+            expect(actual).toBe('updated the distance rate "Default Rate" to apply until May 31, 2026 (previously until April 30, 2026)');
+        });
+
+        it('should return the correct message when all dates are cleared', () => {
+            const action: ReportAction<typeof CONST.REPORT.ACTIONS.TYPE.POLICY_CHANGE_LOG.UPDATE_CUSTOM_UNIT_RATE> = {
+                reportActionID: '1',
+                actionName: CONST.REPORT.ACTIONS.TYPE.POLICY_CHANGE_LOG.UPDATE_CUSTOM_UNIT_RATE,
+                created: '',
+                originalMessage: {
+                    customUnitName: 'Distance',
+                    customUnitRateName: 'Default Rate',
+                    updatedField: 'dateRange',
+                    oldStartDate: '2026-03-01',
+                    oldEndDate: '2026-04-30',
+                },
+            };
+            const actual = ReportActionsUtils.getWorkspaceCustomUnitRateUpdatedMessage(translateLocal, action);
+            expect(actual).toBe('updated the distance rate "Default Rate" to apply for all dates (previously March 1, 2026 - April 30, 2026)');
+        });
     });
 
     describe('didMessageMentionCurrentUser', () => {

From c35921148d6e004b3b0d8ba70a5089fc338fedf7 Mon Sep 17 00:00:00 2001
From: Rodrigo Lino da Costa <rodrigo@expensify.com>
Date: Wed, 10 Jun 2026 09:55:08 -0300
Subject: [PATCH 270/435] translations

---
 src/languages/de.ts      | 5 +++++
 src/languages/es.ts      | 2 +-
 src/languages/fr.ts      | 5 +++++
 src/languages/it.ts      | 5 +++++
 src/languages/ja.ts      | 5 +++++
 src/languages/nl.ts      | 5 +++++
 src/languages/pl.ts      | 5 +++++
 src/languages/pt-BR.ts   | 5 +++++
 src/languages/zh-hans.ts | 4 ++++
 9 files changed, 40 insertions(+), 1 deletion(-)

diff --git a/src/languages/de.ts b/src/languages/de.ts
index c369aa736693..d0593bb37ea6 100644
--- a/src/languages/de.ts
+++ b/src/languages/de.ts
@@ -8066,6 +8066,11 @@ Fügen Sie weitere Ausgabelimits hinzu, um den Cashflow Ihres Unternehmens zu sc
         addCustomUnitRateWithAmountAndEndDate: (rateName: string, rateValue: string, endDate: string) => `„${rateName}“-Satz von ${rateValue} hinzugefügt, gültig bis ${endDate}`,
         addCustomUnitRateWithAmountAndDates: (rateName: string, rateValue: string, startDate: string, endDate: string) =>
             `hat den Tarif „${rateName}“ mit ${rateValue} hinzugefügt, gültig vom ${startDate} bis ${endDate}`,
+        updatedCustomUnitRateDateRange: (rateName: string, newDateRange: string, oldDateRange: string) =>
+            `hat den Entfernungs­tarif „${rateName}“ aktualisiert, sodass er für ${newDateRange} gilt (zuvor ${oldDateRange})`,
+        customUnitRateDateRangeFrom: (date: string) => `ab dem ${date}`,
+        customUnitRateDateRangeUntilEnd: (date: string) => `bis ${date}`,
+        customUnitRateDateRangeAllDates: () => `für alle Daten`,
     },
     roomMembersPage: {
         memberNotFound: 'Mitglied nicht gefunden.',
diff --git a/src/languages/es.ts b/src/languages/es.ts
index 2c9526b631d7..43cdcf087327 100644
--- a/src/languages/es.ts
+++ b/src/languages/es.ts
@@ -7865,7 +7865,7 @@ ${amount} para ${merchant} - ${date}`,
         addCustomUnitRateWithAmountAndDates: (rateName: string, rateValue: string, startDate: string, endDate: string) =>
             `añadió la tasa "${rateName}" de ${rateValue}, válida del ${startDate} al ${endDate}`,
         updatedCustomUnitRateDateRange: (rateName: string, newDateRange: string, oldDateRange: string) =>
-            `actualizó la tasa de distancia "${rateName}" para que aplique ${newDateRange} (previamente ${oldDateRange})`,
+            `actualizó la tasa de distancia «${rateName}» para aplicar ${newDateRange} (previamente ${oldDateRange})`,
         customUnitRateDateRangeStartToEnd: (startDate: string, endDate: string) => `${startDate} - ${endDate}`,
         customUnitRateDateRangeFrom: (date: string) => `desde ${date}`,
         customUnitRateDateRangeUntilEnd: (date: string) => `hasta ${date}`,
diff --git a/src/languages/fr.ts b/src/languages/fr.ts
index acadd45d9ab8..5ad3983d4d30 100644
--- a/src/languages/fr.ts
+++ b/src/languages/fr.ts
@@ -8102,6 +8102,11 @@ Ajoutez davantage de règles de dépenses pour protéger la trésorerie de l’e
         addCustomUnitRateWithAmountAndEndDate: (rateName: string, rateValue: string, endDate: string) => `a ajouté le taux « ${rateName} » de ${rateValue}, valable jusqu’au ${endDate}`,
         addCustomUnitRateWithAmountAndDates: (rateName: string, rateValue: string, startDate: string, endDate: string) =>
             `a ajouté le taux « ${rateName} » de ${rateValue}, valable du ${startDate} au ${endDate}`,
+        updatedCustomUnitRateDateRange: (rateName: string, newDateRange: string, oldDateRange: string) =>
+            `a mis à jour le taux kilométrique « ${rateName} » pour s’appliquer à ${newDateRange} (précédemment ${oldDateRange})`,
+        customUnitRateDateRangeFrom: (date: string) => `à partir du ${date}`,
+        customUnitRateDateRangeUntilEnd: (date: string) => `jusqu’au ${date}`,
+        customUnitRateDateRangeAllDates: () => `pour toutes les dates`,
     },
     roomMembersPage: {
         memberNotFound: 'Membre introuvable.',
diff --git a/src/languages/it.ts b/src/languages/it.ts
index 0e93d13876c7..297270a3541b 100644
--- a/src/languages/it.ts
+++ b/src/languages/it.ts
@@ -8056,6 +8056,11 @@ Aggiungi altre regole di spesa per proteggere il flusso di cassa aziendale.`,
         addCustomUnitRateWithAmountAndEndDate: (rateName: string, rateValue: string, endDate: string) => `ha aggiunto la tariffa "${rateName}" di ${rateValue}, valida fino al ${endDate}`,
         addCustomUnitRateWithAmountAndDates: (rateName: string, rateValue: string, startDate: string, endDate: string) =>
             `ha aggiunto la tariffa "${rateName}" di ${rateValue}, valida dal ${startDate} al ${endDate}`,
+        updatedCustomUnitRateDateRange: (rateName: string, newDateRange: string, oldDateRange: string) =>
+            `ha aggiornato la tariffa chilometrica "${rateName}" per applicarla a ${newDateRange} (in precedenza ${oldDateRange})`,
+        customUnitRateDateRangeFrom: (date: string) => `dal ${date}`,
+        customUnitRateDateRangeUntilEnd: (date: string) => `fino al ${date}`,
+        customUnitRateDateRangeAllDates: () => `per tutte le date`,
     },
     roomMembersPage: {
         memberNotFound: 'Membro non trovato.',
diff --git a/src/languages/ja.ts b/src/languages/ja.ts
index bb9e853ea13a..d29e0069ba09 100644
--- a/src/languages/ja.ts
+++ b/src/languages/ja.ts
@@ -7960,6 +7960,11 @@ ${reportName}
         addCustomUnitRateWithAmountAndEndDate: (rateName: string, rateValue: string, endDate: string) => `「${rateName}」レート（${rateValue}）を${endDate}まで有効として追加しました`,
         addCustomUnitRateWithAmountAndDates: (rateName: string, rateValue: string, startDate: string, endDate: string) =>
             `「${rateName}」レート（${rateValue}）を追加しました。有効期間：${startDate}〜${endDate}`,
+        updatedCustomUnitRateDateRange: (rateName: string, newDateRange: string, oldDateRange: string) =>
+            `距離レート「${rateName}」を更新し、${newDateRange} に適用しました（以前は ${oldDateRange}）`,
+        customUnitRateDateRangeFrom: (date: string) => `${date} から`,
+        customUnitRateDateRangeUntilEnd: (date: string) => `${date}まで`,
+        customUnitRateDateRangeAllDates: () => `すべての日付に対して`,
     },
     roomMembersPage: {
         memberNotFound: 'メンバーが見つかりません。',
diff --git a/src/languages/nl.ts b/src/languages/nl.ts
index 1b8a9206fb7a..71eae1b80539 100644
--- a/src/languages/nl.ts
+++ b/src/languages/nl.ts
@@ -8023,6 +8023,11 @@ er bestedingsregels toe om de kasstroom van het bedrijf te beschermen.`,
         addCustomUnitRateWithAmountAndEndDate: (rateName: string, rateValue: string, endDate: string) => `heeft tarief „${rateName}” van ${rateValue} toegevoegd, geldig tot ${endDate}`,
         addCustomUnitRateWithAmountAndDates: (rateName: string, rateValue: string, startDate: string, endDate: string) =>
             `heeft tarief "${rateName}" van ${rateValue} toegevoegd, geldig van ${startDate} - ${endDate}`,
+        updatedCustomUnitRateDateRange: (rateName: string, newDateRange: string, oldDateRange: string) =>
+            `heeft het kilometertarief "${rateName}" bijgewerkt zodat het geldt van ${newDateRange} (voorheen ${oldDateRange})`,
+        customUnitRateDateRangeFrom: (date: string) => `vanaf ${date}`,
+        customUnitRateDateRangeUntilEnd: (date: string) => `tot ${date}`,
+        customUnitRateDateRangeAllDates: () => `voor alle data`,
     },
     roomMembersPage: {
         memberNotFound: 'Lid niet gevonden.',
diff --git a/src/languages/pl.ts b/src/languages/pl.ts
index 64d08d1c62dc..8189bf7364d5 100644
--- a/src/languages/pl.ts
+++ b/src/languages/pl.ts
@@ -8016,6 +8016,11 @@ Dodaj więcej zasad wydatków, żeby chronić płynność finansową firmy.`,
         addCustomUnitRateWithAmountAndEndDate: (rateName: string, rateValue: string, endDate: string) => `dodano stawkę „${rateName}” w wysokości ${rateValue}, obowiązującą do ${endDate}`,
         addCustomUnitRateWithAmountAndDates: (rateName: string, rateValue: string, startDate: string, endDate: string) =>
             `dodano stawkę „${rateName}” w wysokości ${rateValue}, obowiązującą od ${startDate} do ${endDate}`,
+        updatedCustomUnitRateDateRange: (rateName: string, newDateRange: string, oldDateRange: string) =>
+            `zaktualizowano stawkę za dystans „${rateName}”, aby obowiązywała ${newDateRange} (wcześniej ${oldDateRange})`,
+        customUnitRateDateRangeFrom: (date: string) => `od ${date}`,
+        customUnitRateDateRangeUntilEnd: (date: string) => `do ${date}`,
+        customUnitRateDateRangeAllDates: () => `dla wszystkich dat`,
     },
     roomMembersPage: {
         memberNotFound: 'Nie znaleziono członka.',
diff --git a/src/languages/pt-BR.ts b/src/languages/pt-BR.ts
index 6328541ffbe0..ee2347e7f710 100644
--- a/src/languages/pt-BR.ts
+++ b/src/languages/pt-BR.ts
@@ -8018,6 +8018,11 @@ Adicione mais regras de gasto para proteger o fluxo de caixa da empresa.`,
         addCustomUnitRateWithAmountAndEndDate: (rateName: string, rateValue: string, endDate: string) => `adicionou a taxa "${rateName}" de ${rateValue}, válida até ${endDate}`,
         addCustomUnitRateWithAmountAndDates: (rateName: string, rateValue: string, startDate: string, endDate: string) =>
             `adicionou a tarifa "${rateName}" de ${rateValue}, válida de ${startDate} a ${endDate}`,
+        updatedCustomUnitRateDateRange: (rateName: string, newDateRange: string, oldDateRange: string) =>
+            `atualizou a taxa de distância "${rateName}" para se aplicar a ${newDateRange} (anteriormente ${oldDateRange})`,
+        customUnitRateDateRangeFrom: (date: string) => `de ${date}`,
+        customUnitRateDateRangeUntilEnd: (date: string) => `até ${date}`,
+        customUnitRateDateRangeAllDates: () => `para todas as datas`,
     },
     roomMembersPage: {
         memberNotFound: 'Membro não encontrado.',
diff --git a/src/languages/zh-hans.ts b/src/languages/zh-hans.ts
index 1c7240882f91..b275ba86684c 100644
--- a/src/languages/zh-hans.ts
+++ b/src/languages/zh-hans.ts
@@ -7808,6 +7808,10 @@ ${reportName}
         addCustomUnitRateWithAmountAndEndDate: (rateName: string, rateValue: string, endDate: string) => `已添加“${rateName}”费率 ${rateValue}，有效期至 ${endDate}`,
         addCustomUnitRateWithAmountAndDates: (rateName: string, rateValue: string, startDate: string, endDate: string) =>
             `已添加“${rateName}”费率 ${rateValue}，有效期为 ${startDate} - ${endDate}`,
+        updatedCustomUnitRateDateRange: (rateName: string, newDateRange: string, oldDateRange: string) => `已将距离费率“${rateName}”更新为适用于 ${newDateRange}（此前为 ${oldDateRange}）`,
+        customUnitRateDateRangeFrom: (date: string) => `自 ${date} 起`,
+        customUnitRateDateRangeUntilEnd: (date: string) => `直到 ${date}`,
+        customUnitRateDateRangeAllDates: () => `适用于所有日期`,
     },
     roomMembersPage: {
         memberNotFound: '未找到成员。',

From a91f9be64b0233256828c84e83160d49358f29e4 Mon Sep 17 00:00:00 2001
From: Jakub Korytko <jakub@korytko.me>
Date: Wed, 10 Jun 2026 15:04:50 +0200
Subject: [PATCH 271/435] fix: trinet ios, gusto android

---
 src/components/ConnectToHRFlow/index.ios.tsx | 18 +++++++++++++-----
 src/pages/workspace/hr/HRProviderCard.tsx    |  2 +-
 2 files changed, 14 insertions(+), 6 deletions(-)

diff --git a/src/components/ConnectToHRFlow/index.ios.tsx b/src/components/ConnectToHRFlow/index.ios.tsx
index b23f6c79a2bf..f2d1f800e9f0 100644
--- a/src/components/ConnectToHRFlow/index.ios.tsx
+++ b/src/components/ConnectToHRFlow/index.ios.tsx
@@ -17,12 +17,15 @@ function ConnectToHRFlow({setupLink, onDone}: ConnectToHRFlowProps) {
     const styles = useThemeStyles();
     const hasOpened = useRef(false);
     const isDismissed = useRef(false);
+    const isMounted = useRef(true);
     const [isModalOpen, setIsModalOpen] = useState(true);
 
     const dismiss = () => {
+        if (isDismissed.current || !isMounted.current) {
+            return;
+        }
         isDismissed.current = true;
         setIsModalOpen(false);
-        onDone?.();
     };
 
     const openSession = () => {
@@ -40,10 +43,7 @@ function ConnectToHRFlow({setupLink, onDone}: ConnectToHRFlowProps) {
                 }
                 return openAuthSessionAsync(url, CONST.DEEPLINK_BASE_URL, {preferEphemeralSession: true});
             })
-            .finally(() => {
-                setIsModalOpen(false);
-                onDone?.();
-            });
+            .finally(dismiss);
     };
 
     const {isOffline} = useNetwork({onReconnect: openSession});
@@ -56,9 +56,17 @@ function ConnectToHRFlow({setupLink, onDone}: ConnectToHRFlowProps) {
         // eslint-disable-next-line react-hooks/exhaustive-deps -- only the initial setupLink should be used; re-opening the auth session on prop change is not desired
     }, []);
 
+    useEffect(
+        () => () => {
+            isMounted.current = false;
+        },
+        [],
+    );
+
     return (
         <Modal
             onClose={dismiss}
+            onModalHide={onDone}
             fullscreen
             isVisible={isModalOpen}
             type={CONST.MODAL.MODAL_TYPE.CENTERED_UNSWIPEABLE}
diff --git a/src/pages/workspace/hr/HRProviderCard.tsx b/src/pages/workspace/hr/HRProviderCard.tsx
index 9505bf644310..2eb2e184a8a7 100644
--- a/src/pages/workspace/hr/HRProviderCard.tsx
+++ b/src/pages/workspace/hr/HRProviderCard.tsx
@@ -156,7 +156,7 @@ function HRProviderCard({card, policy, handleConnect, canWriteMoreFeatures, show
                 iconType={CONST.ICON_TYPE_AVATAR}
                 wrapperStyle={[styles.ph0, styles.pv2, !!lastSyncErrorMessage && styles.pb0]}
                 interactive={false}
-                description={card.completeSetupRoute ? undefined : connectionDescription}
+                description={!card.completeSetupRoute && card.isConnected ? connectionDescription : undefined}
                 descriptionAddon={
                     card.completeSetupRoute ? (
                         <RenderHTML html={translate('workspace.hr.mergeHR.setupIncomplete', canWriteMoreFeatures ? `${environmentURL}/${card.completeSetupRoute}` : undefined)} />

From 043ada58f7d69d04727808d09ec51423a0f069d2 Mon Sep 17 00:00:00 2001
From: bartlomiej obudzinski <bartlomiej.obudzinski@callstack.com>
Date: Wed, 10 Jun 2026 15:13:51 +0200
Subject: [PATCH 272/435] refactor: self-subscribe brick road and gate
 last-report subs to wide layout

---
 .../NavigationTabBar/InboxTabButton.tsx       | 24 +++++++++++++------
 .../Navigation/NavigationTabBar/index.tsx     | 15 ------------
 2 files changed, 17 insertions(+), 22 deletions(-)

diff --git a/src/components/Navigation/NavigationTabBar/InboxTabButton.tsx b/src/components/Navigation/NavigationTabBar/InboxTabButton.tsx
index d5a94fbbcd59..2784633a7e58 100644
--- a/src/components/Navigation/NavigationTabBar/InboxTabButton.tsx
+++ b/src/components/Navigation/NavigationTabBar/InboxTabButton.tsx
@@ -6,6 +6,8 @@ import {useMemoizedLazyExpensifyIcons} from '@hooks/useLazyAsset';
 import useLocalize from '@hooks/useLocalize';
 import useOnyx from '@hooks/useOnyx';
 import useRootNavigationState from '@hooks/useRootNavigationState';
+import {useSidebarOrderedReportsState} from '@hooks/useSidebarOrderedReports';
+import useTheme from '@hooks/useTheme';
 import useThemeStyles from '@hooks/useThemeStyles';
 import Navigation from '@libs/Navigation/Navigation';
 import navigationRef from '@libs/Navigation/navigationRef';
@@ -33,13 +35,9 @@ function getStringParam(params: unknown, key: string): string | undefined {
     return undefined;
 }
 
-type BrickRoad = ValueOf<typeof CONST.BRICK_ROAD_INDICATOR_STATUS> | undefined;
-
 type InboxTabButtonProps = {
     selectedTab: ValueOf<typeof NAVIGATION_TABS>;
     isWideLayout: boolean;
-    statusIndicatorColor: string | undefined;
-    chatTabBrickRoad: BrickRoad;
 };
 
 function doesLastReportExistSelector(report: OnyxEntry<Report>) {
@@ -53,13 +51,25 @@ function makeDoesLastReportActionExistSelector(actionID: string | undefined) {
     };
 }
 
-function InboxTabButton({selectedTab, isWideLayout, statusIndicatorColor, chatTabBrickRoad}: InboxTabButtonProps) {
+function InboxTabButton({selectedTab, isWideLayout}: InboxTabButtonProps) {
     const styles = useThemeStyles();
+    const theme = useTheme();
     const {translate} = useLocalize();
+    const {chatTabBrickRoad} = useSidebarOrderedReportsState();
     const expensifyIcons = useMemoizedLazyExpensifyIcons(['Inbox']);
 
+    let statusIndicatorColor: string | undefined;
+    if (chatTabBrickRoad === CONST.BRICK_ROAD_INDICATOR_STATUS.INFO) {
+        statusIndicatorColor = theme.iconSuccessFill;
+    } else if (chatTabBrickRoad) {
+        statusIndicatorColor = theme.danger;
+    }
+
+    // The last-report deep link only runs in the wide layout, so gate the lookups on isWideLayout.
+    // In the narrow layout this keeps reportID/reportActionID undefined, leaving the report and
+    // report-action Onyx subscriptions below inert (tapping Inbox always routes to ROUTES.INBOX).
     const lastReportRouteReportID = useRootNavigationState((rootState) => {
-        if (!rootState) {
+        if (!isWideLayout || !rootState) {
             return undefined;
         }
         const route = getLastRoute(rootState, NAVIGATORS.REPORTS_SPLIT_NAVIGATOR, SCREENS.REPORT);
@@ -67,7 +77,7 @@ function InboxTabButton({selectedTab, isWideLayout, statusIndicatorColor, chatTa
     });
 
     const lastReportRouteReportActionID = useRootNavigationState((rootState) => {
-        if (!rootState) {
+        if (!isWideLayout || !rootState) {
             return undefined;
         }
         const route = getLastRoute(rootState, NAVIGATORS.REPORTS_SPLIT_NAVIGATOR, SCREENS.REPORT);
diff --git a/src/components/Navigation/NavigationTabBar/index.tsx b/src/components/Navigation/NavigationTabBar/index.tsx
index c78cffaa5956..12701cdab400 100644
--- a/src/components/Navigation/NavigationTabBar/index.tsx
+++ b/src/components/Navigation/NavigationTabBar/index.tsx
@@ -10,9 +10,7 @@ import {useMemoizedLazyExpensifyIcons} from '@hooks/useLazyAsset';
 import useLocalize from '@hooks/useLocalize';
 import useOnyx from '@hooks/useOnyx';
 import useResponsiveLayout from '@hooks/useResponsiveLayout';
-import {useSidebarOrderedReportsState} from '@hooks/useSidebarOrderedReports';
 import useStyleUtils from '@hooks/useStyleUtils';
-import useTheme from '@hooks/useTheme';
 import useThemeStyles from '@hooks/useThemeStyles';
 import interceptAnonymousUser from '@libs/interceptAnonymousUser';
 import Navigation from '@libs/Navigation/Navigation';
@@ -33,10 +31,8 @@ type NavigationTabBarProps = {
 };
 
 function NavigationTabBar({selectedTab, shouldShowFloatingButtons = true}: NavigationTabBarProps) {
-    const theme = useTheme();
     const styles = useThemeStyles();
     const {translate} = useLocalize();
-    const {chatTabBrickRoad} = useSidebarOrderedReportsState();
     const [isDebugModeEnabled] = useOnyx(ONYXKEYS.IS_DEBUG_MODE_ENABLED);
     const expensifyIcons = useMemoizedLazyExpensifyIcons(['ExpensifyAppIcon', 'Home']);
 
@@ -44,13 +40,6 @@ function NavigationTabBar({selectedTab, shouldShowFloatingButtons = true}: Navig
 
     const StyleUtils = useStyleUtils();
 
-    let inboxStatusIndicatorColor: string | undefined;
-    if (chatTabBrickRoad === CONST.BRICK_ROAD_INDICATOR_STATUS.INFO) {
-        inboxStatusIndicatorColor = theme.iconSuccessFill;
-    } else if (chatTabBrickRoad) {
-        inboxStatusIndicatorColor = theme.danger;
-    }
-
     const navigateToNewDotHome = () => {
         if (selectedTab === NAVIGATION_TABS.HOME) {
             return;
@@ -114,8 +103,6 @@ function NavigationTabBar({selectedTab, shouldShowFloatingButtons = true}: Navig
                         <InboxTabButton
                             selectedTab={selectedTab}
                             isWideLayout
-                            statusIndicatorColor={inboxStatusIndicatorColor}
-                            chatTabBrickRoad={chatTabBrickRoad}
                         />
                         <SearchTabButton
                             selectedTab={selectedTab}
@@ -163,8 +150,6 @@ function NavigationTabBar({selectedTab, shouldShowFloatingButtons = true}: Navig
                 <InboxTabButton
                     selectedTab={selectedTab}
                     isWideLayout={false}
-                    statusIndicatorColor={inboxStatusIndicatorColor}
-                    chatTabBrickRoad={chatTabBrickRoad}
                 />
                 <SearchTabButton
                     selectedTab={selectedTab}

From 75673d31d693e0aa26b7d5ff2b66311603d463a7 Mon Sep 17 00:00:00 2001
From: Rodrigo Lino da Costa <rodrigo@expensify.com>
Date: Wed, 10 Jun 2026 10:25:57 -0300
Subject: [PATCH 273/435] last trnsalation missing

---
 src/languages/de.ts      | 1 +
 src/languages/fr.ts      | 1 +
 src/languages/it.ts      | 1 +
 src/languages/ja.ts      | 1 +
 src/languages/nl.ts      | 1 +
 src/languages/pl.ts      | 1 +
 src/languages/pt-BR.ts   | 1 +
 src/languages/zh-hans.ts | 1 +
 8 files changed, 8 insertions(+)

diff --git a/src/languages/de.ts b/src/languages/de.ts
index d0593bb37ea6..369d4490c3a5 100644
--- a/src/languages/de.ts
+++ b/src/languages/de.ts
@@ -8068,6 +8068,7 @@ Fügen Sie weitere Ausgabelimits hinzu, um den Cashflow Ihres Unternehmens zu sc
             `hat den Tarif „${rateName}“ mit ${rateValue} hinzugefügt, gültig vom ${startDate} bis ${endDate}`,
         updatedCustomUnitRateDateRange: (rateName: string, newDateRange: string, oldDateRange: string) =>
             `hat den Entfernungs­tarif „${rateName}“ aktualisiert, sodass er für ${newDateRange} gilt (zuvor ${oldDateRange})`,
+        customUnitRateDateRangeStartToEnd: (startDate: string, endDate: string) => `${startDate} - ${endDate}`,
         customUnitRateDateRangeFrom: (date: string) => `ab dem ${date}`,
         customUnitRateDateRangeUntilEnd: (date: string) => `bis ${date}`,
         customUnitRateDateRangeAllDates: () => `für alle Daten`,
diff --git a/src/languages/fr.ts b/src/languages/fr.ts
index 5ad3983d4d30..fe95d71cdb47 100644
--- a/src/languages/fr.ts
+++ b/src/languages/fr.ts
@@ -8104,6 +8104,7 @@ Ajoutez davantage de règles de dépenses pour protéger la trésorerie de l’e
             `a ajouté le taux « ${rateName} » de ${rateValue}, valable du ${startDate} au ${endDate}`,
         updatedCustomUnitRateDateRange: (rateName: string, newDateRange: string, oldDateRange: string) =>
             `a mis à jour le taux kilométrique « ${rateName} » pour s’appliquer à ${newDateRange} (précédemment ${oldDateRange})`,
+        customUnitRateDateRangeStartToEnd: (startDate: string, endDate: string) => `${startDate} - ${endDate}`,
         customUnitRateDateRangeFrom: (date: string) => `à partir du ${date}`,
         customUnitRateDateRangeUntilEnd: (date: string) => `jusqu’au ${date}`,
         customUnitRateDateRangeAllDates: () => `pour toutes les dates`,
diff --git a/src/languages/it.ts b/src/languages/it.ts
index 297270a3541b..2f8e728c7df0 100644
--- a/src/languages/it.ts
+++ b/src/languages/it.ts
@@ -8058,6 +8058,7 @@ Aggiungi altre regole di spesa per proteggere il flusso di cassa aziendale.`,
             `ha aggiunto la tariffa "${rateName}" di ${rateValue}, valida dal ${startDate} al ${endDate}`,
         updatedCustomUnitRateDateRange: (rateName: string, newDateRange: string, oldDateRange: string) =>
             `ha aggiornato la tariffa chilometrica "${rateName}" per applicarla a ${newDateRange} (in precedenza ${oldDateRange})`,
+        customUnitRateDateRangeStartToEnd: (startDate: string, endDate: string) => `${startDate} - ${endDate}`,
         customUnitRateDateRangeFrom: (date: string) => `dal ${date}`,
         customUnitRateDateRangeUntilEnd: (date: string) => `fino al ${date}`,
         customUnitRateDateRangeAllDates: () => `per tutte le date`,
diff --git a/src/languages/ja.ts b/src/languages/ja.ts
index d29e0069ba09..cdf362b2a1f5 100644
--- a/src/languages/ja.ts
+++ b/src/languages/ja.ts
@@ -7962,6 +7962,7 @@ ${reportName}
             `「${rateName}」レート（${rateValue}）を追加しました。有効期間：${startDate}〜${endDate}`,
         updatedCustomUnitRateDateRange: (rateName: string, newDateRange: string, oldDateRange: string) =>
             `距離レート「${rateName}」を更新し、${newDateRange} に適用しました（以前は ${oldDateRange}）`,
+        customUnitRateDateRangeStartToEnd: (startDate: string, endDate: string) => `${startDate} - ${endDate}`,
         customUnitRateDateRangeFrom: (date: string) => `${date} から`,
         customUnitRateDateRangeUntilEnd: (date: string) => `${date}まで`,
         customUnitRateDateRangeAllDates: () => `すべての日付に対して`,
diff --git a/src/languages/nl.ts b/src/languages/nl.ts
index 71eae1b80539..226430d9b02b 100644
--- a/src/languages/nl.ts
+++ b/src/languages/nl.ts
@@ -8025,6 +8025,7 @@ er bestedingsregels toe om de kasstroom van het bedrijf te beschermen.`,
             `heeft tarief "${rateName}" van ${rateValue} toegevoegd, geldig van ${startDate} - ${endDate}`,
         updatedCustomUnitRateDateRange: (rateName: string, newDateRange: string, oldDateRange: string) =>
             `heeft het kilometertarief "${rateName}" bijgewerkt zodat het geldt van ${newDateRange} (voorheen ${oldDateRange})`,
+        customUnitRateDateRangeStartToEnd: (startDate: string, endDate: string) => `${startDate} - ${endDate}`,
         customUnitRateDateRangeFrom: (date: string) => `vanaf ${date}`,
         customUnitRateDateRangeUntilEnd: (date: string) => `tot ${date}`,
         customUnitRateDateRangeAllDates: () => `voor alle data`,
diff --git a/src/languages/pl.ts b/src/languages/pl.ts
index 8189bf7364d5..30f98a2c130f 100644
--- a/src/languages/pl.ts
+++ b/src/languages/pl.ts
@@ -8018,6 +8018,7 @@ Dodaj więcej zasad wydatków, żeby chronić płynność finansową firmy.`,
             `dodano stawkę „${rateName}” w wysokości ${rateValue}, obowiązującą od ${startDate} do ${endDate}`,
         updatedCustomUnitRateDateRange: (rateName: string, newDateRange: string, oldDateRange: string) =>
             `zaktualizowano stawkę za dystans „${rateName}”, aby obowiązywała ${newDateRange} (wcześniej ${oldDateRange})`,
+        customUnitRateDateRangeStartToEnd: (startDate: string, endDate: string) => `${startDate} - ${endDate}`,
         customUnitRateDateRangeFrom: (date: string) => `od ${date}`,
         customUnitRateDateRangeUntilEnd: (date: string) => `do ${date}`,
         customUnitRateDateRangeAllDates: () => `dla wszystkich dat`,
diff --git a/src/languages/pt-BR.ts b/src/languages/pt-BR.ts
index ee2347e7f710..ba190fdb0321 100644
--- a/src/languages/pt-BR.ts
+++ b/src/languages/pt-BR.ts
@@ -8020,6 +8020,7 @@ Adicione mais regras de gasto para proteger o fluxo de caixa da empresa.`,
             `adicionou a tarifa "${rateName}" de ${rateValue}, válida de ${startDate} a ${endDate}`,
         updatedCustomUnitRateDateRange: (rateName: string, newDateRange: string, oldDateRange: string) =>
             `atualizou a taxa de distância "${rateName}" para se aplicar a ${newDateRange} (anteriormente ${oldDateRange})`,
+        customUnitRateDateRangeStartToEnd: (startDate: string, endDate: string) => `${startDate} - ${endDate}`,
         customUnitRateDateRangeFrom: (date: string) => `de ${date}`,
         customUnitRateDateRangeUntilEnd: (date: string) => `até ${date}`,
         customUnitRateDateRangeAllDates: () => `para todas as datas`,
diff --git a/src/languages/zh-hans.ts b/src/languages/zh-hans.ts
index b275ba86684c..dd4dcd7b220e 100644
--- a/src/languages/zh-hans.ts
+++ b/src/languages/zh-hans.ts
@@ -7809,6 +7809,7 @@ ${reportName}
         addCustomUnitRateWithAmountAndDates: (rateName: string, rateValue: string, startDate: string, endDate: string) =>
             `已添加“${rateName}”费率 ${rateValue}，有效期为 ${startDate} - ${endDate}`,
         updatedCustomUnitRateDateRange: (rateName: string, newDateRange: string, oldDateRange: string) => `已将距离费率“${rateName}”更新为适用于 ${newDateRange}（此前为 ${oldDateRange}）`,
+        customUnitRateDateRangeStartToEnd: (startDate: string, endDate: string) => `${startDate} - ${endDate}`,
         customUnitRateDateRangeFrom: (date: string) => `自 ${date} 起`,
         customUnitRateDateRangeUntilEnd: (date: string) => `直到 ${date}`,
         customUnitRateDateRangeAllDates: () => `适用于所有日期`,

From 7d174931ce5010a04250bbd25d697ef27692d3cf Mon Sep 17 00:00:00 2001
From: ShridharGoel <35566748+ShridharGoel@users.noreply.github.com>
Date: Wed, 10 Jun 2026 19:32:55 +0530
Subject: [PATCH 274/435] Pass raw role to add employee changelog

---
 src/languages/de.ts            | 5 +++--
 src/languages/en.ts            | 5 +++--
 src/languages/es.ts            | 5 +++--
 src/languages/fr.ts            | 5 +++--
 src/languages/it.ts            | 5 +++--
 src/languages/ja.ts            | 5 +++--
 src/languages/nl.ts            | 5 +++--
 src/languages/pl.ts            | 5 +++--
 src/languages/pt-BR.ts         | 5 +++--
 src/languages/zh-hans.ts       | 5 +++--
 src/libs/ReportActionsUtils.ts | 2 +-
 11 files changed, 31 insertions(+), 21 deletions(-)

diff --git a/src/languages/de.ts b/src/languages/de.ts
index 13c8baab5b92..b3e96eb70bbe 100644
--- a/src/languages/de.ts
+++ b/src/languages/de.ts
@@ -8471,8 +8471,9 @@ Fügen Sie weitere Ausgabelimits hinzu, um den Cashflow Ihres Unternehmens zu sc
                 plaidBalanceFailure: ({maskedAccountNumber, walletRoute}: {maskedAccountNumber: string; walletRoute: string}) =>
                     `Die Plaid-Verbindung zu Ihrem Geschäftskonto ist unterbrochen. Bitte <a href='${walletRoute}'>verbinden Sie Ihr Bankkonto ${maskedAccountNumber} erneut</a>, damit Sie Ihre Expensify Karten weiterhin verwenden können.`,
                 addEmployee: (email: string, role: string, didJoinPolicy?: boolean) => {
-                    const article = role.toLowerCase() === 'auditor' ? 'an' : 'ein';
-                    return didJoinPolicy ? `${email} ist über den Workspace-Einladungslink beigetreten` : `${email} als ${article} ${role} hinzugefügt`;
+                    const translatedRole = translations.workspace.common.roleName(role).toLowerCase();
+                    const article = role === CONST.POLICY.ROLE.AUDITOR ? 'an' : 'ein';
+                    return didJoinPolicy ? `${email} ist über den Workspace-Einladungslink beigetreten` : `${email} als ${article} ${translatedRole} hinzugefügt`;
                 },
                 updateRole: ({email, currentRole, newRole}: UpdateRoleParams) => `hat die Rolle von ${email} in ${newRole} geändert (zuvor ${currentRole})`,
                 updatedCustomField1: (email: string, newValue: string, previousValue: string) => {
diff --git a/src/languages/en.ts b/src/languages/en.ts
index f4b2f668ef1a..45d9203d6943 100644
--- a/src/languages/en.ts
+++ b/src/languages/en.ts
@@ -8517,8 +8517,9 @@ const translations = {
                 plaidBalanceFailure: ({maskedAccountNumber, walletRoute}: {maskedAccountNumber: string; walletRoute: string}) =>
                     `the Plaid connection to your business bank account is broken. Please <a href='${walletRoute}'>reconnect your bank account ${maskedAccountNumber}</a> so you can continue to use your Expensify Cards.`,
                 addEmployee: (email: string, role: string, didJoinPolicy?: boolean) => {
-                    const article = role.toLowerCase() === 'auditor' ? 'an' : 'a';
-                    return didJoinPolicy ? `${email} joined via the workspace invite link` : `added ${email} as ${article} ${role}`;
+                    const translatedRole = translations.workspace.common.roleName(role).toLowerCase();
+                    const article = role === CONST.POLICY.ROLE.AUDITOR ? 'an' : 'a';
+                    return didJoinPolicy ? `${email} joined via the workspace invite link` : `added ${email} as ${article} ${translatedRole}`;
                 },
                 updateRole: ({email, currentRole, newRole}: UpdateRoleParams) => `updated the role of ${email} to ${newRole} (previously ${currentRole})`,
                 updatedCustomField1: (email: string, newValue: string, previousValue: string) => {
diff --git a/src/languages/es.ts b/src/languages/es.ts
index 521b81caa89a..350eba32d234 100644
--- a/src/languages/es.ts
+++ b/src/languages/es.ts
@@ -8267,8 +8267,9 @@ ${amount} para ${merchant} - ${date}`,
                 plaidBalanceFailure: ({maskedAccountNumber, walletRoute}: {maskedAccountNumber: string; walletRoute: string}) =>
                     `la conexión Plaid con tu cuenta bancaria de empresa está rota. Por favor, <a href='${walletRoute}'>reconecta tu cuenta bancaria ${maskedAccountNumber}</a> para poder seguir usando tus Tarjetas Expensify.`,
                 addEmployee: (email: string, role: string, didJoinPolicy?: boolean) => {
-                    const article = role.toLowerCase() === 'auditor' ? 'un' : 'a';
-                    return didJoinPolicy ? `${email} se unió a través del enlace de invitación del espacio de trabajo` : `añadió ${email} como ${article} ${role}`;
+                    const translatedRole = translations.workspace.common.roleName(role).toLowerCase();
+                    const article = role === CONST.POLICY.ROLE.AUDITOR ? 'un' : 'a';
+                    return didJoinPolicy ? `${email} se unió a través del enlace de invitación del espacio de trabajo` : `añadió ${email} como ${article} ${translatedRole}`;
                 },
                 updateRole: ({email, currentRole, newRole}) => `actualizó el rol ${email} a ${newRole} (previamente ${currentRole})`,
                 updatedCustomField1: (email, newValue, previousValue) => {
diff --git a/src/languages/fr.ts b/src/languages/fr.ts
index 33826d949606..8014ad995b6e 100644
--- a/src/languages/fr.ts
+++ b/src/languages/fr.ts
@@ -8506,8 +8506,9 @@ Ajoutez davantage de règles de dépenses pour protéger la trésorerie de l’e
                 plaidBalanceFailure: ({maskedAccountNumber, walletRoute}: {maskedAccountNumber: string; walletRoute: string}) =>
                     `la connexion Plaid à votre compte bancaire professionnel est rompue. Veuillez <a href='${walletRoute}'>reconnecter votre compte bancaire ${maskedAccountNumber}</a> afin de pouvoir continuer à utiliser vos Cartes Expensify.`,
                 addEmployee: (email: string, role: string, didJoinPolicy?: boolean) => {
-                    const article = role.toLowerCase() === 'auditor' ? 'un' : 'un';
-                    return didJoinPolicy ? `${email} a rejoint via le lien d’invitation à l’espace de travail` : `a ajouté ${email} en tant que ${article} ${role}`;
+                    const translatedRole = translations.workspace.common.roleName(role).toLowerCase();
+                    const article = role === CONST.POLICY.ROLE.AUDITOR ? 'un' : 'un';
+                    return didJoinPolicy ? `${email} a rejoint via le lien d’invitation à l’espace de travail` : `a ajouté ${email} en tant que ${article} ${translatedRole}`;
                 },
                 updateRole: ({email, currentRole, newRole}: UpdateRoleParams) => `a mis à jour le rôle de ${email} en ${newRole} (précédemment ${currentRole})`,
                 updatedCustomField1: (email: string, newValue: string, previousValue: string) => {
diff --git a/src/languages/it.ts b/src/languages/it.ts
index 083518714c12..5210c250a73a 100644
--- a/src/languages/it.ts
+++ b/src/languages/it.ts
@@ -8464,8 +8464,9 @@ Aggiungi altre regole di spesa per proteggere il flusso di cassa aziendale.`,
                 plaidBalanceFailure: ({maskedAccountNumber, walletRoute}: {maskedAccountNumber: string; walletRoute: string}) =>
                     `la connessione Plaid al conto bancario della tua azienda non funziona. Per favore, <a href='${walletRoute}'>ricollega il conto bancario ${maskedAccountNumber}</a> così puoi continuare a usare le tue Carte Expensify.`,
                 addEmployee: (email: string, role: string, didJoinPolicy?: boolean) => {
-                    const article = role.toLowerCase() === 'auditor' ? 'un' : 'a';
-                    return didJoinPolicy ? `${email} si è unito tramite il link di invito dello spazio di lavoro` : `ha aggiunto ${email} come ${article} ${role}`;
+                    const translatedRole = translations.workspace.common.roleName(role).toLowerCase();
+                    const article = role === CONST.POLICY.ROLE.AUDITOR ? 'un' : 'a';
+                    return didJoinPolicy ? `${email} si è unito tramite il link di invito dello spazio di lavoro` : `ha aggiunto ${email} come ${article} ${translatedRole}`;
                 },
                 updateRole: ({email, currentRole, newRole}: UpdateRoleParams) => `ha aggiornato il ruolo di ${email} a ${newRole} (in precedenza ${currentRole})`,
                 updatedCustomField1: (email: string, newValue: string, previousValue: string) => {
diff --git a/src/languages/ja.ts b/src/languages/ja.ts
index 98a21fac9bec..576eb2df31a6 100644
--- a/src/languages/ja.ts
+++ b/src/languages/ja.ts
@@ -8353,8 +8353,9 @@ ${reportName}
                 plaidBalanceFailure: ({maskedAccountNumber, walletRoute}: {maskedAccountNumber: string; walletRoute: string}) =>
                     `Plaid によるビジネス銀行口座との接続が切断されています。Expensify カードを引き続きご利用いただくために、<a href='${walletRoute}'>銀行口座 ${maskedAccountNumber} を再接続</a>してください。`,
                 addEmployee: (email: string, role: string, didJoinPolicy?: boolean) => {
-                    const article = role.toLowerCase() === 'auditor' ? '一つの' : 'a';
-                    return didJoinPolicy ? `${email} さんがワークスペースの招待リンクから参加しました` : `${email} を${article}${role}として追加しました`;
+                    const translatedRole = translations.workspace.common.roleName(role).toLowerCase();
+                    const article = role === CONST.POLICY.ROLE.AUDITOR ? '一つの' : 'a';
+                    return didJoinPolicy ? `${email} さんがワークスペースの招待リンクから参加しました` : `${email} を${article}${translatedRole}として追加しました`;
                 },
                 updateRole: ({email, currentRole, newRole}: UpdateRoleParams) => `${email} のロールを ${currentRole} から ${newRole} に更新しました`,
                 updatedCustomField1: (email: string, newValue: string, previousValue: string) => {
diff --git a/src/languages/nl.ts b/src/languages/nl.ts
index 0f92aeecbe60..a045c0612da6 100644
--- a/src/languages/nl.ts
+++ b/src/languages/nl.ts
@@ -8427,8 +8427,9 @@ er bestedingsregels toe om de kasstroom van het bedrijf te beschermen.`,
                 plaidBalanceFailure: ({maskedAccountNumber, walletRoute}: {maskedAccountNumber: string; walletRoute: string}) =>
                     `de Plaid-verbinding met je zakelijke bankrekening is verbroken. <a href='${walletRoute}'>Verbind je bankrekening ${maskedAccountNumber} opnieuw</a> zodat je je Expensify Kaarten kunt blijven gebruiken.`,
                 addEmployee: (email: string, role: string, didJoinPolicy?: boolean) => {
-                    const article = role.toLowerCase() === 'auditor' ? 'een' : 'een';
-                    return didJoinPolicy ? `${email} is via de werkruimte-uitnodigingslink lid geworden` : `heeft ${email} toegevoegd als ${article} ${role}`;
+                    const translatedRole = translations.workspace.common.roleName(role).toLowerCase();
+                    const article = role === CONST.POLICY.ROLE.AUDITOR ? 'een' : 'een';
+                    return didJoinPolicy ? `${email} is via de werkruimte-uitnodigingslink lid geworden` : `heeft ${email} toegevoegd als ${article} ${translatedRole}`;
                 },
                 updateRole: ({email, currentRole, newRole}: UpdateRoleParams) => `heeft de rol van ${email} bijgewerkt naar ${newRole} (voorheen ${currentRole})`,
                 updatedCustomField1: (email: string, newValue: string, previousValue: string) => {
diff --git a/src/languages/pl.ts b/src/languages/pl.ts
index 07793c0fc448..81f07b3fb0dd 100644
--- a/src/languages/pl.ts
+++ b/src/languages/pl.ts
@@ -8419,8 +8419,9 @@ Dodaj więcej zasad wydatków, żeby chronić płynność finansową firmy.`,
                 plaidBalanceFailure: ({maskedAccountNumber, walletRoute}: {maskedAccountNumber: string; walletRoute: string}) =>
                     `połączenie Plaid z twoim firmowym kontem bankowym jest przerwane. Proszę, <a href='${walletRoute}'>połącz ponownie swoje konto bankowe ${maskedAccountNumber}</a>, aby móc dalej używać Kart Expensify.`,
                 addEmployee: (email: string, role: string, didJoinPolicy?: boolean) => {
-                    const article = role.toLowerCase() === 'auditor' ? 'jeden' : 'a';
-                    return didJoinPolicy ? `${email} dołączył przez link zaproszenia do przestrzeni roboczej` : `dodano ${email} jako ${article} ${role}`;
+                    const translatedRole = translations.workspace.common.roleName(role).toLowerCase();
+                    const article = role === CONST.POLICY.ROLE.AUDITOR ? 'jeden' : 'a';
+                    return didJoinPolicy ? `${email} dołączył przez link zaproszenia do przestrzeni roboczej` : `dodano ${email} jako ${article} ${translatedRole}`;
                 },
                 updateRole: ({email, currentRole, newRole}: UpdateRoleParams) => `zaktualizowano rolę użytkownika ${email} na ${newRole} (wcześniej ${currentRole})`,
                 updatedCustomField1: (email: string, newValue: string, previousValue: string) => {
diff --git a/src/languages/pt-BR.ts b/src/languages/pt-BR.ts
index 4fc0bf2fc721..766c6fe3deac 100644
--- a/src/languages/pt-BR.ts
+++ b/src/languages/pt-BR.ts
@@ -8422,8 +8422,9 @@ Adicione mais regras de gasto para proteger o fluxo de caixa da empresa.`,
                 plaidBalanceFailure: ({maskedAccountNumber, walletRoute}: {maskedAccountNumber: string; walletRoute: string}) =>
                     `a conexão Plaid com a sua conta bancária empresarial foi interrompida. Por favor, <a href='${walletRoute}'>reconecte sua conta bancária ${maskedAccountNumber}</a> para continuar usando seus Cartões Expensify.`,
                 addEmployee: (email: string, role: string, didJoinPolicy?: boolean) => {
-                    const article = role.toLowerCase() === 'auditor' ? 'um' : 'um';
-                    return didJoinPolicy ? `${email} entrou pelo link de convite do workspace` : `adicionou ${email} como ${article} ${role}`;
+                    const translatedRole = translations.workspace.common.roleName(role).toLowerCase();
+                    const article = role === CONST.POLICY.ROLE.AUDITOR ? 'um' : 'um';
+                    return didJoinPolicy ? `${email} entrou pelo link de convite do workspace` : `adicionou ${email} como ${article} ${translatedRole}`;
                 },
                 updateRole: ({email, currentRole, newRole}: UpdateRoleParams) => `atualizou a função de ${email} para ${newRole} (anteriormente ${currentRole})`,
                 updatedCustomField1: (email: string, newValue: string, previousValue: string) => {
diff --git a/src/languages/zh-hans.ts b/src/languages/zh-hans.ts
index c9a966c99292..4bdbd17f675c 100644
--- a/src/languages/zh-hans.ts
+++ b/src/languages/zh-hans.ts
@@ -8192,8 +8192,9 @@ ${reportName}
                 plaidBalanceFailure: ({maskedAccountNumber, walletRoute}: {maskedAccountNumber: string; walletRoute: string}) =>
                     `您与企业银行账户的 Plaid 连接已中断。请<a href='${walletRoute}'>重新连接您的银行账户 ${maskedAccountNumber}</a>，以便继续使用 Expensify 卡。`,
                 addEmployee: (email: string, role: string, didJoinPolicy?: boolean) => {
-                    const article = role.toLowerCase() === 'auditor' ? '一' : 'a';
-                    return didJoinPolicy ? `${email} 通过工作区邀请链接加入` : `已将 ${email} 添加为 ${article} ${role}`;
+                    const translatedRole = translations.workspace.common.roleName(role).toLowerCase();
+                    const article = role === CONST.POLICY.ROLE.AUDITOR ? '一' : 'a';
+                    return didJoinPolicy ? `${email} 通过工作区邀请链接加入` : `已将 ${email} 添加为 ${article} ${translatedRole}`;
                 },
                 updateRole: ({email, currentRole, newRole}: UpdateRoleParams) => `已将 ${email} 的角色更新为 ${newRole}（先前为 ${currentRole}）`,
                 updatedCustomField1: (email: string, newValue: string, previousValue: string) => {
diff --git a/src/libs/ReportActionsUtils.ts b/src/libs/ReportActionsUtils.ts
index c97a5b6267ea..2fc6adbc3d50 100644
--- a/src/libs/ReportActionsUtils.ts
+++ b/src/libs/ReportActionsUtils.ts
@@ -2807,7 +2807,7 @@ function getPolicyChangeLogAddEmployeeMessage(translate: LocalizedTranslate, rep
 
     const originalMessage = getOriginalMessage(reportAction);
     const email = originalMessage?.email ?? '';
-    const role = translate('workspace.common.roleName', originalMessage?.role ?? '').toLowerCase();
+    const role = originalMessage?.role ?? '';
     const formattedEmail = formatPhoneNumber(email);
     return translate('report.actions.type.addEmployee', formattedEmail, role, originalMessage?.didJoinPolicy);
 }

From c7dd2564a82afaa2aa164cd62d827cb4fdf9be02 Mon Sep 17 00:00:00 2001
From: bartlomiej obudzinski <bartlomiej.obudzinski@callstack.com>
Date: Wed, 10 Jun 2026 16:17:40 +0200
Subject: [PATCH 275/435] test: add unit tests for useInboxTabSpanLifecycle

---
 .../hooks/useInboxTabSpanLifecycle.test.ts    | 138 ++++++++++++++++++
 1 file changed, 138 insertions(+)
 create mode 100644 tests/unit/hooks/useInboxTabSpanLifecycle.test.ts

diff --git a/tests/unit/hooks/useInboxTabSpanLifecycle.test.ts b/tests/unit/hooks/useInboxTabSpanLifecycle.test.ts
new file mode 100644
index 000000000000..6252fb049de0
--- /dev/null
+++ b/tests/unit/hooks/useInboxTabSpanLifecycle.test.ts
@@ -0,0 +1,138 @@
+import {act, renderHook} from '@testing-library/react-native';
+import useInboxTabSpanLifecycle from '@hooks/useInboxTabSpanLifecycle';
+import CONST from '@src/CONST';
+
+type FocusCallback = () => (() => void) | void;
+type FakeSpan = {id: string};
+
+const SPAN = CONST.TELEMETRY.SPAN_NAVIGATE_TO_INBOX_TAB;
+
+const mockUseFocusEffect = jest.fn<void, [FocusCallback]>();
+const mockGetSpan = jest.fn<FakeSpan | undefined, [string]>();
+const mockEndSpan = jest.fn<void, [string]>();
+const mockCancelSpan = jest.fn<void, [string]>();
+
+// The hook only consumes useFocusEffect from this module. We capture the focus callback
+// (via mockUseFocusEffect.mock.calls) so each test can drive focus/blur explicitly instead
+// of standing up a navigation container.
+jest.mock('@react-navigation/native', () => ({
+    useFocusEffect: (callback: FocusCallback) => {
+        mockUseFocusEffect(callback);
+    },
+}));
+
+jest.mock('@libs/telemetry/activeSpans', () => ({
+    getSpan: (spanId: string) => mockGetSpan(spanId),
+    endSpan: (spanId: string) => mockEndSpan(spanId),
+    cancelSpan: (spanId: string) => mockCancelSpan(spanId),
+}));
+
+const spanAtMount: FakeSpan = {id: 'span-at-mount'};
+const newerSpan: FakeSpan = {id: 'newer-span'};
+
+/** The currently active span returned by getSpan. Defaults to the one present when the hook mounts. */
+let currentActiveSpan: FakeSpan | undefined;
+
+/** Returns the latest focus callback the hook registered with useFocusEffect. */
+function getFocusCallback(): FocusCallback {
+    const callback = mockUseFocusEffect.mock.calls.at(-1)?.[0];
+    if (!callback) {
+        throw new Error('useFocusEffect was never called by the hook');
+    }
+    return callback;
+}
+
+describe('useInboxTabSpanLifecycle', () => {
+    beforeEach(() => {
+        jest.clearAllMocks();
+        currentActiveSpan = spanAtMount;
+        mockGetSpan.mockImplementation(() => currentActiveSpan);
+    });
+
+    it('ends the span when the sidebar lays out for the first time (normal path)', () => {
+        const {result} = renderHook(() => useInboxTabSpanLifecycle());
+
+        act(() => {
+            result.current();
+        });
+
+        expect(mockEndSpan).toHaveBeenCalledTimes(1);
+        expect(mockEndSpan).toHaveBeenCalledWith(SPAN);
+        expect(mockCancelSpan).not.toHaveBeenCalled();
+    });
+
+    it('does not end the span on focus before the first layout (cold path)', () => {
+        renderHook(() => useInboxTabSpanLifecycle());
+
+        act(() => {
+            getFocusCallback()();
+        });
+
+        expect(mockEndSpan).not.toHaveBeenCalled();
+    });
+
+    it('ends the span on re-focus after layout (warm react-freeze path)', () => {
+        const {result} = renderHook(() => useInboxTabSpanLifecycle());
+
+        // First layout completes, then the user leaves and returns: react-freeze keeps the
+        // layout cached so onLayout will not fire again, and focus must end the span instead.
+        act(() => {
+            result.current();
+        });
+        mockEndSpan.mockClear();
+
+        act(() => {
+            getFocusCallback()();
+        });
+
+        expect(mockEndSpan).toHaveBeenCalledTimes(1);
+        expect(mockEndSpan).toHaveBeenCalledWith(SPAN);
+    });
+
+    it('cancels the span on blur when layout never completed (orphan cleanup)', () => {
+        renderHook(() => useInboxTabSpanLifecycle());
+
+        const blurCleanup = getFocusCallback()();
+
+        expect(typeof blurCleanup).toBe('function');
+        act(() => {
+            blurCleanup?.();
+        });
+
+        expect(mockCancelSpan).toHaveBeenCalledTimes(1);
+        expect(mockCancelSpan).toHaveBeenCalledWith(SPAN);
+    });
+
+    it('cancels the span on unmount when layout never completed and the active span is unchanged', () => {
+        const {unmount} = renderHook(() => useInboxTabSpanLifecycle());
+
+        unmount();
+
+        expect(mockCancelSpan).toHaveBeenCalledTimes(1);
+        expect(mockCancelSpan).toHaveBeenCalledWith(SPAN);
+    });
+
+    it('does not cancel on unmount when a newer span has started (subsequent tab click)', () => {
+        const {unmount} = renderHook(() => useInboxTabSpanLifecycle());
+
+        // A later tab click started a fresh span before this instance unmounted. The unmount
+        // cleanup must not cancel that newer span.
+        currentActiveSpan = newerSpan;
+        unmount();
+
+        expect(mockCancelSpan).not.toHaveBeenCalled();
+    });
+
+    it('does not cancel on unmount after layout has completed', () => {
+        const {result, unmount} = renderHook(() => useInboxTabSpanLifecycle());
+
+        act(() => {
+            result.current();
+        });
+        mockCancelSpan.mockClear();
+
+        unmount();
+
+        expect(mockCancelSpan).not.toHaveBeenCalled();
+    });
+});

From 27e899351cbb9ceed878aa431944e6b2c9f11e02 Mon Sep 17 00:00:00 2001
From: ShridharGoel <35566748+ShridharGoel@users.noreply.github.com>
Date: Wed, 10 Jun 2026 19:50:08 +0530
Subject: [PATCH 276/435] Fix role changelog translation typing

---
 src/languages/de.ts      | 2 +-
 src/languages/en.ts      | 2 +-
 src/languages/es.ts      | 2 +-
 src/languages/fr.ts      | 2 +-
 src/languages/it.ts      | 2 +-
 src/languages/ja.ts      | 2 +-
 src/languages/nl.ts      | 2 +-
 src/languages/pl.ts      | 2 +-
 src/languages/pt-BR.ts   | 2 +-
 src/languages/zh-hans.ts | 2 +-
 10 files changed, 10 insertions(+), 10 deletions(-)

diff --git a/src/languages/de.ts b/src/languages/de.ts
index b3e96eb70bbe..356fd3b14b71 100644
--- a/src/languages/de.ts
+++ b/src/languages/de.ts
@@ -8471,7 +8471,7 @@ Fügen Sie weitere Ausgabelimits hinzu, um den Cashflow Ihres Unternehmens zu sc
                 plaidBalanceFailure: ({maskedAccountNumber, walletRoute}: {maskedAccountNumber: string; walletRoute: string}) =>
                     `Die Plaid-Verbindung zu Ihrem Geschäftskonto ist unterbrochen. Bitte <a href='${walletRoute}'>verbinden Sie Ihr Bankkonto ${maskedAccountNumber} erneut</a>, damit Sie Ihre Expensify Karten weiterhin verwenden können.`,
                 addEmployee: (email: string, role: string, didJoinPolicy?: boolean) => {
-                    const translatedRole = translations.workspace.common.roleName(role).toLowerCase();
+                    const translatedRole = String(translations.workspace.common.roleName(role)).toLowerCase();
                     const article = role === CONST.POLICY.ROLE.AUDITOR ? 'an' : 'ein';
                     return didJoinPolicy ? `${email} ist über den Workspace-Einladungslink beigetreten` : `${email} als ${article} ${translatedRole} hinzugefügt`;
                 },
diff --git a/src/languages/en.ts b/src/languages/en.ts
index 45d9203d6943..ad268c732902 100644
--- a/src/languages/en.ts
+++ b/src/languages/en.ts
@@ -8517,7 +8517,7 @@ const translations = {
                 plaidBalanceFailure: ({maskedAccountNumber, walletRoute}: {maskedAccountNumber: string; walletRoute: string}) =>
                     `the Plaid connection to your business bank account is broken. Please <a href='${walletRoute}'>reconnect your bank account ${maskedAccountNumber}</a> so you can continue to use your Expensify Cards.`,
                 addEmployee: (email: string, role: string, didJoinPolicy?: boolean) => {
-                    const translatedRole = translations.workspace.common.roleName(role).toLowerCase();
+                    const translatedRole = String(translations.workspace.common.roleName(role)).toLowerCase();
                     const article = role === CONST.POLICY.ROLE.AUDITOR ? 'an' : 'a';
                     return didJoinPolicy ? `${email} joined via the workspace invite link` : `added ${email} as ${article} ${translatedRole}`;
                 },
diff --git a/src/languages/es.ts b/src/languages/es.ts
index 350eba32d234..ddf94779e83c 100644
--- a/src/languages/es.ts
+++ b/src/languages/es.ts
@@ -8267,7 +8267,7 @@ ${amount} para ${merchant} - ${date}`,
                 plaidBalanceFailure: ({maskedAccountNumber, walletRoute}: {maskedAccountNumber: string; walletRoute: string}) =>
                     `la conexión Plaid con tu cuenta bancaria de empresa está rota. Por favor, <a href='${walletRoute}'>reconecta tu cuenta bancaria ${maskedAccountNumber}</a> para poder seguir usando tus Tarjetas Expensify.`,
                 addEmployee: (email: string, role: string, didJoinPolicy?: boolean) => {
-                    const translatedRole = translations.workspace.common.roleName(role).toLowerCase();
+                    const translatedRole = String(translations.workspace.common.roleName(role)).toLowerCase();
                     const article = role === CONST.POLICY.ROLE.AUDITOR ? 'un' : 'a';
                     return didJoinPolicy ? `${email} se unió a través del enlace de invitación del espacio de trabajo` : `añadió ${email} como ${article} ${translatedRole}`;
                 },
diff --git a/src/languages/fr.ts b/src/languages/fr.ts
index 8014ad995b6e..7c406821c414 100644
--- a/src/languages/fr.ts
+++ b/src/languages/fr.ts
@@ -8506,7 +8506,7 @@ Ajoutez davantage de règles de dépenses pour protéger la trésorerie de l’e
                 plaidBalanceFailure: ({maskedAccountNumber, walletRoute}: {maskedAccountNumber: string; walletRoute: string}) =>
                     `la connexion Plaid à votre compte bancaire professionnel est rompue. Veuillez <a href='${walletRoute}'>reconnecter votre compte bancaire ${maskedAccountNumber}</a> afin de pouvoir continuer à utiliser vos Cartes Expensify.`,
                 addEmployee: (email: string, role: string, didJoinPolicy?: boolean) => {
-                    const translatedRole = translations.workspace.common.roleName(role).toLowerCase();
+                    const translatedRole = String(translations.workspace.common.roleName(role)).toLowerCase();
                     const article = role === CONST.POLICY.ROLE.AUDITOR ? 'un' : 'un';
                     return didJoinPolicy ? `${email} a rejoint via le lien d’invitation à l’espace de travail` : `a ajouté ${email} en tant que ${article} ${translatedRole}`;
                 },
diff --git a/src/languages/it.ts b/src/languages/it.ts
index 5210c250a73a..53a70885cfa1 100644
--- a/src/languages/it.ts
+++ b/src/languages/it.ts
@@ -8464,7 +8464,7 @@ Aggiungi altre regole di spesa per proteggere il flusso di cassa aziendale.`,
                 plaidBalanceFailure: ({maskedAccountNumber, walletRoute}: {maskedAccountNumber: string; walletRoute: string}) =>
                     `la connessione Plaid al conto bancario della tua azienda non funziona. Per favore, <a href='${walletRoute}'>ricollega il conto bancario ${maskedAccountNumber}</a> così puoi continuare a usare le tue Carte Expensify.`,
                 addEmployee: (email: string, role: string, didJoinPolicy?: boolean) => {
-                    const translatedRole = translations.workspace.common.roleName(role).toLowerCase();
+                    const translatedRole = String(translations.workspace.common.roleName(role)).toLowerCase();
                     const article = role === CONST.POLICY.ROLE.AUDITOR ? 'un' : 'a';
                     return didJoinPolicy ? `${email} si è unito tramite il link di invito dello spazio di lavoro` : `ha aggiunto ${email} come ${article} ${translatedRole}`;
                 },
diff --git a/src/languages/ja.ts b/src/languages/ja.ts
index 576eb2df31a6..4fcfecef6b45 100644
--- a/src/languages/ja.ts
+++ b/src/languages/ja.ts
@@ -8353,7 +8353,7 @@ ${reportName}
                 plaidBalanceFailure: ({maskedAccountNumber, walletRoute}: {maskedAccountNumber: string; walletRoute: string}) =>
                     `Plaid によるビジネス銀行口座との接続が切断されています。Expensify カードを引き続きご利用いただくために、<a href='${walletRoute}'>銀行口座 ${maskedAccountNumber} を再接続</a>してください。`,
                 addEmployee: (email: string, role: string, didJoinPolicy?: boolean) => {
-                    const translatedRole = translations.workspace.common.roleName(role).toLowerCase();
+                    const translatedRole = String(translations.workspace.common.roleName(role)).toLowerCase();
                     const article = role === CONST.POLICY.ROLE.AUDITOR ? '一つの' : 'a';
                     return didJoinPolicy ? `${email} さんがワークスペースの招待リンクから参加しました` : `${email} を${article}${translatedRole}として追加しました`;
                 },
diff --git a/src/languages/nl.ts b/src/languages/nl.ts
index a045c0612da6..b75f36031fb5 100644
--- a/src/languages/nl.ts
+++ b/src/languages/nl.ts
@@ -8427,7 +8427,7 @@ er bestedingsregels toe om de kasstroom van het bedrijf te beschermen.`,
                 plaidBalanceFailure: ({maskedAccountNumber, walletRoute}: {maskedAccountNumber: string; walletRoute: string}) =>
                     `de Plaid-verbinding met je zakelijke bankrekening is verbroken. <a href='${walletRoute}'>Verbind je bankrekening ${maskedAccountNumber} opnieuw</a> zodat je je Expensify Kaarten kunt blijven gebruiken.`,
                 addEmployee: (email: string, role: string, didJoinPolicy?: boolean) => {
-                    const translatedRole = translations.workspace.common.roleName(role).toLowerCase();
+                    const translatedRole = String(translations.workspace.common.roleName(role)).toLowerCase();
                     const article = role === CONST.POLICY.ROLE.AUDITOR ? 'een' : 'een';
                     return didJoinPolicy ? `${email} is via de werkruimte-uitnodigingslink lid geworden` : `heeft ${email} toegevoegd als ${article} ${translatedRole}`;
                 },
diff --git a/src/languages/pl.ts b/src/languages/pl.ts
index 81f07b3fb0dd..35131ab11848 100644
--- a/src/languages/pl.ts
+++ b/src/languages/pl.ts
@@ -8419,7 +8419,7 @@ Dodaj więcej zasad wydatków, żeby chronić płynność finansową firmy.`,
                 plaidBalanceFailure: ({maskedAccountNumber, walletRoute}: {maskedAccountNumber: string; walletRoute: string}) =>
                     `połączenie Plaid z twoim firmowym kontem bankowym jest przerwane. Proszę, <a href='${walletRoute}'>połącz ponownie swoje konto bankowe ${maskedAccountNumber}</a>, aby móc dalej używać Kart Expensify.`,
                 addEmployee: (email: string, role: string, didJoinPolicy?: boolean) => {
-                    const translatedRole = translations.workspace.common.roleName(role).toLowerCase();
+                    const translatedRole = String(translations.workspace.common.roleName(role)).toLowerCase();
                     const article = role === CONST.POLICY.ROLE.AUDITOR ? 'jeden' : 'a';
                     return didJoinPolicy ? `${email} dołączył przez link zaproszenia do przestrzeni roboczej` : `dodano ${email} jako ${article} ${translatedRole}`;
                 },
diff --git a/src/languages/pt-BR.ts b/src/languages/pt-BR.ts
index 766c6fe3deac..434d4f97020a 100644
--- a/src/languages/pt-BR.ts
+++ b/src/languages/pt-BR.ts
@@ -8422,7 +8422,7 @@ Adicione mais regras de gasto para proteger o fluxo de caixa da empresa.`,
                 plaidBalanceFailure: ({maskedAccountNumber, walletRoute}: {maskedAccountNumber: string; walletRoute: string}) =>
                     `a conexão Plaid com a sua conta bancária empresarial foi interrompida. Por favor, <a href='${walletRoute}'>reconecte sua conta bancária ${maskedAccountNumber}</a> para continuar usando seus Cartões Expensify.`,
                 addEmployee: (email: string, role: string, didJoinPolicy?: boolean) => {
-                    const translatedRole = translations.workspace.common.roleName(role).toLowerCase();
+                    const translatedRole = String(translations.workspace.common.roleName(role)).toLowerCase();
                     const article = role === CONST.POLICY.ROLE.AUDITOR ? 'um' : 'um';
                     return didJoinPolicy ? `${email} entrou pelo link de convite do workspace` : `adicionou ${email} como ${article} ${translatedRole}`;
                 },
diff --git a/src/languages/zh-hans.ts b/src/languages/zh-hans.ts
index 4bdbd17f675c..11128da02cf8 100644
--- a/src/languages/zh-hans.ts
+++ b/src/languages/zh-hans.ts
@@ -8192,7 +8192,7 @@ ${reportName}
                 plaidBalanceFailure: ({maskedAccountNumber, walletRoute}: {maskedAccountNumber: string; walletRoute: string}) =>
                     `您与企业银行账户的 Plaid 连接已中断。请<a href='${walletRoute}'>重新连接您的银行账户 ${maskedAccountNumber}</a>，以便继续使用 Expensify 卡。`,
                 addEmployee: (email: string, role: string, didJoinPolicy?: boolean) => {
-                    const translatedRole = translations.workspace.common.roleName(role).toLowerCase();
+                    const translatedRole = String(translations.workspace.common.roleName(role)).toLowerCase();
                     const article = role === CONST.POLICY.ROLE.AUDITOR ? '一' : 'a';
                     return didJoinPolicy ? `${email} 通过工作区邀请链接加入` : `已将 ${email} 添加为 ${article} ${translatedRole}`;
                 },

From 6b175bcde6bb06982ec3dfe4d37eb46dd43c1991 Mon Sep 17 00:00:00 2001
From: Alex Beaman <alexbeaman@expensify.com>
Date: Wed, 10 Jun 2026 09:06:03 -0600
Subject: [PATCH 277/435] Remove useMemo + displayName per mkhutornyi review
 (React compiler auto-memoizes)

---
 .../iou/request/step/IOURequestStepVendor.tsx | 81 +++++++++----------
 1 file changed, 38 insertions(+), 43 deletions(-)

diff --git a/src/pages/iou/request/step/IOURequestStepVendor.tsx b/src/pages/iou/request/step/IOURequestStepVendor.tsx
index 299acaecb61e..f05519aaaf8c 100644
--- a/src/pages/iou/request/step/IOURequestStepVendor.tsx
+++ b/src/pages/iou/request/step/IOURequestStepVendor.tsx
@@ -1,4 +1,4 @@
-import React, {useMemo, useState} from 'react';
+import React, {useState} from 'react';
 import BlockingView from '@components/BlockingViews/BlockingView';
 import SelectionList from '@components/SelectionList';
 import SingleSelectListItem from '@components/SelectionList/ListItem/SingleSelectListItem';
@@ -54,34 +54,34 @@ function IOURequestStepVendor({
     // Vendor is scoped to non-reimbursable expenses on a policy expense chat; block deep-link / stale-open access if the transaction is reimbursable or is an invoice (invoices are non-reimbursable but don't route through the QBO CC vendor-matching flow).
     const isReimbursable = !!transaction?.reimbursable;
     const isInvoice = iouType === CONST.IOU.TYPE.INVOICE;
-    const vendors = useMemo(() => getQBOVendors(policy), [policy]);
+    const vendors = getQBOVendors(policy);
     const currentVendorID = transaction?.comment?.vendor?.externalID;
 
-    const data: VendorListItem[] = useMemo(() => {
-        const trimmed = searchValue.trim().toLowerCase();
-        const vendorRows = vendors
-            .filter((vendor) => !trimmed || vendor.name.toLowerCase().includes(trimmed))
-            .map((vendor) => ({
-                value: vendor.id,
-                text: vendor.name,
-                keyForList: vendor.id,
-                isSelected: vendor.id === currentVendorID,
-                searchText: vendor.name,
-            }));
-
-        // When a vendor is currently set, offer a "None" row so the user can clear a stale (e.g. removed-from-QBO) vendor without picking a replacement, which resolves an inactiveVendor violation. Hidden during search to keep results clean.
-        if (!currentVendorID || trimmed) {
-            return vendorRows;
-        }
-        const clearRow: VendorListItem = {
-            value: '',
-            text: translate('common.none'),
-            keyForList: 'clear-vendor',
-            isSelected: false,
-            searchText: '',
-        };
-        return [clearRow, ...vendorRows];
-    }, [vendors, currentVendorID, searchValue, translate]);
+    const trimmedSearch = searchValue.trim().toLowerCase();
+    const vendorRows: VendorListItem[] = vendors
+        .filter((vendor) => !trimmedSearch || vendor.name.toLowerCase().includes(trimmedSearch))
+        .map((vendor) => ({
+            value: vendor.id,
+            text: vendor.name,
+            keyForList: vendor.id,
+            isSelected: vendor.id === currentVendorID,
+            searchText: vendor.name,
+        }));
+
+    // When a vendor is currently set, offer a "None" row so the user can clear a stale (e.g. removed-from-QBO) vendor without picking a replacement, which resolves an inactiveVendor violation. Hidden during search to keep results clean.
+    const data: VendorListItem[] =
+        !currentVendorID || trimmedSearch
+            ? vendorRows
+            : [
+                  {
+                      value: '',
+                      text: translate('common.none'),
+                      keyForList: 'clear-vendor',
+                      isSelected: false,
+                      searchText: '',
+                  },
+                  ...vendorRows,
+              ];
 
     const shouldShowNotFoundPage = useShowNotFoundPageInIOUStep(action, iouType, reportActionID, report, transaction) || !isFeatureAvailable || isReimbursable || isInvoice;
 
@@ -98,20 +98,17 @@ function IOURequestStepVendor({
 
     const headerMessage = searchValue && data.length === 0 ? translate('common.noResultsFound') : '';
 
-    const listEmptyContent = useMemo(
-        () =>
-            vendors.length === 0 ? (
-                <BlockingView
-                    icon={illustrations.Telescope}
-                    iconWidth={variables.emptyListIconWidth}
-                    iconHeight={variables.emptyListIconHeight}
-                    title={translate('workspace.qbo.noAccountsFound')}
-                    subtitle={translate('workspace.qbo.noAccountsFoundDescription')}
-                    containerStyle={styles.pb10}
-                />
-            ) : null,
-        [vendors.length, illustrations.Telescope, translate, styles.pb10],
-    );
+    const listEmptyContent =
+        vendors.length === 0 ? (
+            <BlockingView
+                icon={illustrations.Telescope}
+                iconWidth={variables.emptyListIconWidth}
+                iconHeight={variables.emptyListIconHeight}
+                title={translate('workspace.qbo.noAccountsFound')}
+                subtitle={translate('workspace.qbo.noAccountsFoundDescription')}
+                containerStyle={styles.pb10}
+            />
+        ) : null;
 
     return (
         <StepScreenWrapper
@@ -141,6 +138,4 @@ function IOURequestStepVendor({
     );
 }
 
-IOURequestStepVendor.displayName = 'IOURequestStepVendor';
-
 export default withWritableReportOrNotFound(withFullTransactionOrNotFound(IOURequestStepVendor));

From 3e63560657e9689528140dcff20efa37489388ca Mon Sep 17 00:00:00 2001
From: Jakub Korytko <jakub@korytko.me>
Date: Wed, 10 Jun 2026 17:14:43 +0200
Subject: [PATCH 278/435] fix: gusto ios

---
 src/hooks/useHRSyncResultsModal.ts | 47 +++++++++++++++++++++---------
 1 file changed, 34 insertions(+), 13 deletions(-)

diff --git a/src/hooks/useHRSyncResultsModal.ts b/src/hooks/useHRSyncResultsModal.ts
index 8a45dff48a74..97e33dd88058 100644
--- a/src/hooks/useHRSyncResultsModal.ts
+++ b/src/hooks/useHRSyncResultsModal.ts
@@ -1,10 +1,13 @@
-import {useEffect} from 'react';
+import {useEffect, useEffectEvent, useRef} from 'react';
 import type {OnyxEntry} from 'react-native-onyx';
-import type {TupleToUnion} from 'type-fest';
 import HRSyncResultsModal from '@components/HRSyncResultsModal';
 import {useModal} from '@components/Modal/Global/ModalContext';
+// eslint-disable-next-line no-restricted-imports -- the hook delays a global modal until the existing modal/navigation transitions complete to avoid stacked native modal races.
+import TransitionTracker from '@libs/Navigation/TransitionTracker';
 import CONST from '@src/CONST';
+import ONYXKEYS from '@src/ONYXKEYS';
 import type {PolicyConnectionSyncProgress} from '@src/types/onyx/Policy';
+import useOnyx from './useOnyx';
 import usePrevious from './usePrevious';
 
 /**
@@ -14,37 +17,55 @@ import usePrevious from './usePrevious';
 function useHRSyncResultsModal(policyID: string, connectionSyncProgress: OnyxEntry<PolicyConnectionSyncProgress>, isFocused: boolean) {
     const modal = useModal();
     const previousSyncProgress = usePrevious(connectionSyncProgress);
+    const pendingSyncResultRef = useRef<Pick<PolicyConnectionSyncProgress, 'connectionName' | 'result'> | null>(null);
+    const [isAnyModalActive] = useOnyx(ONYXKEYS.MODAL, {selector: (activeModal) => !!activeModal?.isVisible || !!activeModal?.willAlertModalBecomeVisible});
 
     const connectionName = connectionSyncProgress?.connectionName;
+    const showSyncResultsModal = useEffectEvent((syncResult: PolicyConnectionSyncProgress['result'], syncConnectionName: PolicyConnectionSyncProgress['connectionName']) => {
+        if (!syncResult || !syncConnectionName) {
+            return;
+        }
+
+        modal.showModal({
+            component: HRSyncResultsModal,
+            props: {result: syncResult, policyID},
+            id: `${syncConnectionName}-sync-results-${policyID}`,
+        });
+    });
 
     useEffect(() => {
         const syncResult = connectionSyncProgress?.result;
-        const isHRSyncDoneWithResult =
-            CONST.POLICY.CONNECTIONS.HR_CONNECTION_NAMES.includes(connectionName as TupleToUnion<typeof CONST.POLICY.CONNECTIONS.HR_CONNECTION_NAMES>) &&
-            connectionSyncProgress?.stageInProgress === CONST.POLICY.CONNECTIONS.SYNC_STAGE_NAME.JOB_DONE &&
-            !!syncResult;
+        const isHRConnectionName = CONST.POLICY.CONNECTIONS.HR_CONNECTION_NAMES.some((hrConnectionName) => hrConnectionName === connectionName);
+        const isHRSyncDoneWithResult = isHRConnectionName && connectionSyncProgress?.stageInProgress === CONST.POLICY.CONNECTIONS.SYNC_STAGE_NAME.JOB_DONE && !!syncResult;
         const didTransitionToJobDone = previousSyncProgress?.connectionName === connectionName && previousSyncProgress?.stageInProgress !== CONST.POLICY.CONNECTIONS.SYNC_STAGE_NAME.JOB_DONE;
         const didHRSyncComplete = isFocused && isHRSyncDoneWithResult && didTransitionToJobDone;
 
-        if (!didHRSyncComplete || !syncResult || !connectionName) {
+        if (didHRSyncComplete && syncResult && connectionName) {
+            pendingSyncResultRef.current = {connectionName, result: syncResult};
+        }
+
+        const pendingSyncResult = pendingSyncResultRef.current;
+        if (!pendingSyncResult || isAnyModalActive) {
             return;
         }
 
-        modal.showModal({
-            component: HRSyncResultsModal,
-            props: {result: syncResult, policyID},
-            id: `${connectionName}-sync-results-${policyID}`,
+        const handle = TransitionTracker.runAfterTransitions({
+            callback: () => {
+                showSyncResultsModal(pendingSyncResult.result, pendingSyncResult.connectionName);
+                pendingSyncResultRef.current = null;
+            },
+            waitForUpcomingTransition: true,
         });
+        return () => handle.cancel();
     }, [
         connectionName,
         connectionSyncProgress?.result,
         connectionSyncProgress?.stageInProgress,
         connectionSyncProgress?.timestamp,
+        isAnyModalActive,
         isFocused,
-        policyID,
         previousSyncProgress?.connectionName,
         previousSyncProgress?.stageInProgress,
-        modal,
     ]);
 }
 

From 22bf7ce93210989b7e8e12d4df3021dc50e3b261 Mon Sep 17 00:00:00 2001
From: ShridharGoel <35566748+ShridharGoel@users.noreply.github.com>
Date: Wed, 10 Jun 2026 20:49:50 +0530
Subject: [PATCH 279/435] Fix workspace owner restricted action test lint

---
 .../WorkspaceOwnerRestrictedActionTest.tsx    | 140 ++++++++++++++++++
 1 file changed, 140 insertions(+)
 create mode 100644 tests/unit/pages/RestrictedAction/WorkspaceOwnerRestrictedActionTest.tsx

diff --git a/tests/unit/pages/RestrictedAction/WorkspaceOwnerRestrictedActionTest.tsx b/tests/unit/pages/RestrictedAction/WorkspaceOwnerRestrictedActionTest.tsx
new file mode 100644
index 000000000000..0b65996cc207
--- /dev/null
+++ b/tests/unit/pages/RestrictedAction/WorkspaceOwnerRestrictedActionTest.tsx
@@ -0,0 +1,140 @@
+import {fireEvent, render, screen} from '@testing-library/react-native';
+import React from 'react';
+import type ReactNative from 'react-native';
+import Navigation from '@libs/Navigation/Navigation';
+import WorkspaceOwnerRestrictedActionNative from '@src/pages/RestrictedAction/Workspace/WorkspaceOwnerRestrictedAction/index.native';
+import ROUTES from '@src/ROUTES';
+
+// Jest resolves index.native.tsx by default in the RN test environment; load web implementation explicitly.
+const {default: WorkspaceOwnerRestrictedActionWeb} = jest.requireActual<{default: React.ComponentType}>('@src/pages/RestrictedAction/Workspace/WorkspaceOwnerRestrictedAction/index.tsx');
+
+jest.mock('@libs/Navigation/Navigation', () => ({
+    dismissModal: jest.fn(),
+    closeRHPFlow: jest.fn(),
+    navigate: jest.fn(),
+    getActiveRoute: jest.fn(() => 'r/123'),
+    goBack: jest.fn(),
+}));
+
+jest.mock('@hooks/useLocalize', () => jest.fn(() => ({translate: jest.fn((key: string) => key)})));
+
+jest.mock('@hooks/useThemeStyles', () =>
+    jest.fn(
+        () =>
+            new Proxy(
+                {},
+                {
+                    get: () => ({}),
+                },
+            ),
+    ),
+);
+
+jest.mock('@hooks/useLazyAsset', () => ({
+    useMemoizedLazyExpensifyIcons: jest.fn(() => ({
+        Unlock: () => null,
+    })),
+    useMemoizedLazyIllustrations: jest.fn(() => ({
+        LockClosedOrange: () => null,
+    })),
+}));
+
+jest.mock('@components/ScreenWrapper', () => {
+    function MockScreenWrapper({children}: {children: React.ReactNode}) {
+        return children;
+    }
+    return MockScreenWrapper;
+});
+
+jest.mock('@components/HeaderWithBackButton', () => {
+    function MockHeaderWithBackButton() {
+        return null;
+    }
+    return MockHeaderWithBackButton;
+});
+
+jest.mock('@components/ScrollView', () => {
+    function MockScrollView({children}: {children: React.ReactNode}) {
+        return children;
+    }
+    return MockScrollView;
+});
+
+jest.mock('@components/Icon', () => {
+    function MockIcon() {
+        return null;
+    }
+    return MockIcon;
+});
+
+jest.mock('@components/Badge', () => {
+    function MockBadge() {
+        return null;
+    }
+    return MockBadge;
+});
+
+jest.mock('@components/Text', () => {
+    function MockText({children}: {children: React.ReactNode}) {
+        return children;
+    }
+    return MockText;
+});
+
+jest.mock('@components/Button', () => {
+    const {TouchableOpacity, Text} = jest.requireActual<typeof ReactNative>('react-native');
+    function MockButton({text, onPress}: {text: string; onPress?: () => void}) {
+        return (
+            <TouchableOpacity
+                accessibilityRole="button"
+                onPress={onPress}
+            >
+                <Text>{text}</Text>
+            </TouchableOpacity>
+        );
+    }
+    return MockButton;
+});
+
+function getDismissModalAfterTransition(): (() => void) | undefined {
+    const options = jest.mocked(Navigation.dismissModal).mock.calls.at(0)?.at(0);
+    if (typeof options !== 'object' || options === null || !('afterTransition' in options)) {
+        return undefined;
+    }
+    const {afterTransition} = options;
+    return typeof afterTransition === 'function' ? afterTransition : undefined;
+}
+
+describe('WorkspaceOwnerRestrictedAction', () => {
+    beforeEach(() => {
+        jest.clearAllMocks();
+    });
+
+    it('dismisses modal before navigating to add payment card on web', () => {
+        render(<WorkspaceOwnerRestrictedActionWeb />);
+
+        fireEvent.press(screen.getByText('workspace.restrictedAction.addPaymentCard'));
+
+        expect(Navigation.dismissModal).toHaveBeenCalledTimes(1);
+        expect(Navigation.navigate).not.toHaveBeenCalled();
+
+        const afterTransition = getDismissModalAfterTransition();
+        expect(afterTransition).toBeInstanceOf(Function);
+
+        afterTransition?.();
+
+        expect(Navigation.navigate).toHaveBeenCalledTimes(1);
+        expect(Navigation.navigate).toHaveBeenCalledWith(ROUTES.SETTINGS_SUBSCRIPTION_ADD_PAYMENT_CARD);
+    });
+
+    it('uses unchanged native handler to navigate to subscription route', () => {
+        render(<WorkspaceOwnerRestrictedActionNative />);
+
+        fireEvent.press(screen.getByText('workspace.restrictedAction.goToSubscription'));
+
+        expect(Navigation.closeRHPFlow).toHaveBeenCalledTimes(1);
+        expect(Navigation.navigate).toHaveBeenCalledTimes(1);
+        expect(Navigation.navigate).toHaveBeenCalledWith(ROUTES.SETTINGS_SUBSCRIPTION.getRoute('r/123'));
+        expect(Navigation.dismissModal).not.toHaveBeenCalled();
+    });
+});

From 4620ce487c97509d90af5bef7a046d549c2c627b Mon Sep 17 00:00:00 2001
From: Jakub Korytko <jakub@korytko.me>
Date: Wed, 10 Jun 2026 17:22:45 +0200
Subject: [PATCH 280/435] fix: cla fail


From f68d4c906a5560486fb41be5e9dc097906181be2 Mon Sep 17 00:00:00 2001
From: Adam Horodyski <ad.horodyski@gmail.com>
Date: Wed, 10 Jun 2026 16:33:21 +0200
Subject: [PATCH 281/435] Fix ESLint no-unsafe-type-assertion in
 SequentialQueue test

The test needed a MockFetch-typed handle (pause/resume) for the new
disk-write-failure cases. Casting global.fetch to MockFetch tripped
@typescript-eslint/no-unsafe-type-assertion in CI.

Expose createGlobalFetchMock() returning MockFetch directly (the mock
is already built as MockFetch internally), and keep getGlobalFetchMock
as a thin typeof-fetch wrapper so existing callers are unaffected. The
test now gets a fresh, typed mock per test with no type assertion.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
---
 tests/unit/SequentialQueueTest.ts | 25 ++++++++++++-------------
 tests/utils/TestHelper.ts         |  9 +++++++--
 2 files changed, 19 insertions(+), 15 deletions(-)

diff --git a/tests/unit/SequentialQueueTest.ts b/tests/unit/SequentialQueueTest.ts
index a0a3dedcebff..67adffd451ad 100644
--- a/tests/unit/SequentialQueueTest.ts
+++ b/tests/unit/SequentialQueueTest.ts
@@ -8,6 +8,7 @@ import * as SequentialQueue from '../../src/libs/Network/SequentialQueue';
 import * as RequestModule from '../../src/libs/Request';
 import type Request from '../../src/types/onyx/Request';
 import type {AnyRequest, ConflictActionData} from '../../src/types/onyx/Request';
+import type {MockFetch} from '../utils/TestHelper';
 import * as TestHelper from '../utils/TestHelper';
 import waitForBatchedUpdates from '../utils/waitForBatchedUpdates';
 
@@ -16,13 +17,15 @@ const request: Request<'userMetadata'> = {
     successData: [{key: 'userMetadata', onyxMethod: 'set', value: {accountID: 1234}}],
     failureData: [{key: 'userMetadata', onyxMethod: 'set', value: {}}],
 };
+let mockFetch: MockFetch;
 beforeAll(() => {
     Onyx.init({
         keys: ONYXKEYS,
     });
 });
 beforeEach(() => {
-    global.fetch = TestHelper.getGlobalFetchMock();
+    mockFetch = TestHelper.createGlobalFetchMock();
+    global.fetch = mockFetch;
     return Onyx.clear()
         .then(() => SequentialQueue.clearQueueFlushedData())
         .then(waitForBatchedUpdates);
@@ -77,10 +80,9 @@ describe('SequentialQueue', () => {
     it('should not block the queue when a disk write fails during persist', async () => {
         // If a conflict-resolution disk write rejects (storage full / corruption), push() must not throw
         // or strand isReadyPromise — the request should still flush and waitForIdle() should resolve.
-        const mockedFetch = global.fetch as ReturnType<typeof TestHelper.getGlobalFetchMock> & {pause: () => void; resume: () => Promise<void>};
         const originalSet = Onyx.set.bind(Onyx);
 
-        mockedFetch.pause();
+        mockFetch.pause();
         try {
             await SequentialQueue.push({command: 'OpenReport'}); // occupies ongoingRequest
             await waitForBatchedUpdates();
@@ -105,7 +107,7 @@ describe('SequentialQueue', () => {
                 setMock.mockRestore();
             }
         } finally {
-            await mockedFetch.resume();
+            await mockFetch.resume();
         }
 
         // The queue still drains and READs unblock — a hang here would fail the test by timing out.
@@ -170,8 +172,7 @@ describe('SequentialQueue', () => {
         // The conflict checker on push 2 inspects the persisted queue (which excludes the
         // ongoing request), so it cannot find a 'ReconnectApp' to replace and falls back
         // to 'push'. The new request is therefore added to the queue.
-        const mockedFetch = global.fetch as ReturnType<typeof TestHelper.getGlobalFetchMock> & {pause: () => void; resume: () => Promise<void>};
-        mockedFetch.pause();
+        mockFetch.pause();
         try {
             await SequentialQueue.push(request);
             await waitForBatchedUpdates();
@@ -194,13 +195,12 @@ describe('SequentialQueue', () => {
             // The new request is in the persisted queue with the expected accountID.
             expect(getAll().some((r) => r.data?.accountID === 56789)).toBe(true);
         } finally {
-            await mockedFetch.resume();
+            await mockFetch.resume();
         }
     });
 
     it('should replace request in queue while a similar one is ongoing', async () => {
-        const mockedFetch = global.fetch as ReturnType<typeof TestHelper.getGlobalFetchMock> & {pause: () => void; resume: () => Promise<void>};
-        mockedFetch.pause();
+        mockFetch.pause();
         try {
             await SequentialQueue.push(request);
             await waitForBatchedUpdates();
@@ -234,13 +234,12 @@ describe('SequentialQueue', () => {
 
             expect(getLength()).toBe(2);
         } finally {
-            await mockedFetch.resume();
+            await mockFetch.resume();
         }
     });
 
     it('should replace request in queue while a similar one is ongoing and keep the same index', async () => {
-        const mockedFetch = global.fetch as ReturnType<typeof TestHelper.getGlobalFetchMock> & {pause: () => void; resume: () => Promise<void>};
-        mockedFetch.pause();
+        mockFetch.pause();
         try {
             // First push moves into `ongoingRequest`; subsequent pushes stack in the queue.
             await SequentialQueue.push({command: 'OpenReport'});
@@ -270,7 +269,7 @@ describe('SequentialQueue', () => {
             expect(getOngoingRequest()?.command).toBe('OpenReport');
             expect(persistedRequests.at(0)?.data?.accountID).toBe(56789);
         } finally {
-            await mockedFetch.resume();
+            await mockFetch.resume();
         }
     });
 
diff --git a/tests/utils/TestHelper.ts b/tests/utils/TestHelper.ts
index b710ea226cde..edea0633e606 100644
--- a/tests/utils/TestHelper.ts
+++ b/tests/utils/TestHelper.ts
@@ -217,7 +217,7 @@ function signOutTestUser() {
  * - fail() - start returning a failure response
  * - success() - go back to returning a success response
  */
-function getGlobalFetchMock(mockResponse?: Partial<Response>): typeof fetch {
+function createGlobalFetchMock(mockResponse?: Partial<Response>): MockFetch {
     let queue: QueueItem[] = [];
     // eslint-disable-next-line @typescript-eslint/no-explicit-any
     let responses = new Map<string, (params: any) => OnyxResponse<any>>();
@@ -280,7 +280,11 @@ function getGlobalFetchMock(mockResponse?: Partial<Response>): typeof fetch {
     mockFetch.mockAPICommand = <TCommand extends ApiCommand>(command: TCommand, responseHandler: (params: ApiRequestCommandParameters[TCommand]) => OnyxResponse<any>): void => {
         responses.set(command, responseHandler);
     };
-    return mockFetch as typeof fetch;
+    return mockFetch;
+}
+
+function getGlobalFetchMock(mockResponse?: Partial<Response>): typeof fetch {
+    return createGlobalFetchMock(mockResponse);
 }
 
 function setupGlobalFetchMock(): MockFetch {
@@ -394,6 +398,7 @@ export {
     buildTestReportComment,
     getFetchMockCalls,
     getGlobalFetchMock,
+    createGlobalFetchMock,
     setPersonalDetails,
     signInWithTestUser,
     signOutTestUser,

From 7042741f1a3f1edb7eb5e40dd04ba2c83d0aa95f Mon Sep 17 00:00:00 2001
From: Alex Beaman <alexbeaman@expensify.com>
Date: Wed, 10 Jun 2026 09:38:01 -0600
Subject: [PATCH 282/435] Drop unnecessary type assertion in vendor failure
 test to satisfy seatbelt

---
 tests/actions/IOUTest/UpdateMoneyRequestVendorTest.ts | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/tests/actions/IOUTest/UpdateMoneyRequestVendorTest.ts b/tests/actions/IOUTest/UpdateMoneyRequestVendorTest.ts
index 8bb237327faf..31f4e4ce68d2 100644
--- a/tests/actions/IOUTest/UpdateMoneyRequestVendorTest.ts
+++ b/tests/actions/IOUTest/UpdateMoneyRequestVendorTest.ts
@@ -158,6 +158,6 @@ describe('updateMoneyRequestVendor', () => {
 
         const onyxData = getOnyxDataArg();
         const transactionFailure = onyxData?.failureData.find((entry) => entry.key === `${ONYXKEYS.COLLECTION.TRANSACTION}${TRANSACTION_ID}`);
-        expect((transactionFailure?.value as {pendingFields?: {vendor: null | string}})?.pendingFields).toEqual({vendor: null});
+        expect(transactionFailure?.value).toMatchObject({pendingFields: {vendor: null}});
     });
 });

From 6a3a184c435bb25597447d583fc14249ecd2aaff Mon Sep 17 00:00:00 2001
From: krishna2323 <belivethatkg@gmail.com>
Date: Wed, 10 Jun 2026 21:16:01 +0530
Subject: [PATCH 283/435] Refactor distance rates table: move data prep to
 parent, remove duplicate padding, fix badge blending

Signed-off-by: krishna2323 <belivethatkg@gmail.com>
---
 .../WorkspaceDistanceRatesTableRow.tsx        | 35 +++++----
 .../WorkspaceDistanceRatesTable/index.tsx     | 72 ++-----------------
 .../distanceRates/PolicyDistanceRatesPage.tsx | 57 ++++++++++++---
 3 files changed, 69 insertions(+), 95 deletions(-)

diff --git a/src/components/Tables/WorkspaceDistanceRatesTable/WorkspaceDistanceRatesTableRow.tsx b/src/components/Tables/WorkspaceDistanceRatesTable/WorkspaceDistanceRatesTableRow.tsx
index 72f997695ba7..98519d9085bf 100644
--- a/src/components/Tables/WorkspaceDistanceRatesTable/WorkspaceDistanceRatesTableRow.tsx
+++ b/src/components/Tables/WorkspaceDistanceRatesTable/WorkspaceDistanceRatesTableRow.tsx
@@ -1,12 +1,12 @@
 import {format, parseISO} from 'date-fns';
-import React, {useMemo} from 'react';
-import type {ColorValue} from 'react-native';
+import React from 'react';
 import {View} from 'react-native';
 import Icon from '@components/Icon';
 import StatusBadge from '@components/StatusBadge';
 import Switch from '@components/Switch';
 import Table from '@components/Table';
 import type {TableData} from '@components/Table';
+import {useTableContext} from '@components/Table/TableContext';
 import TextWithTooltip from '@components/TextWithTooltip';
 import {useMemoizedLazyExpensifyIcons} from '@hooks/useLazyAsset';
 import useLocalize from '@hooks/useLocalize';
@@ -51,21 +51,18 @@ function formatDate(dateString: string | null | undefined): string {
     }
 }
 
-function useRateStatusColors(status: string): {backgroundColor: ColorValue; textColor: ColorValue} {
-    const theme = useTheme();
-    return useMemo(() => {
-        switch (status) {
-            case CONST.CUSTOM_UNITS.RATE_STATUS.ACTIVE:
-                return theme.reportStatusBadge.paid;
-            case CONST.CUSTOM_UNITS.RATE_STATUS.FUTURE:
-                return theme.reportStatusBadge.draft;
-            case CONST.CUSTOM_UNITS.RATE_STATUS.EXPIRED:
-                return theme.reportStatusBadge.outstanding;
-            case CONST.CUSTOM_UNITS.RATE_STATUS.INACTIVE:
-            default:
-                return {backgroundColor: theme.badgeDefaultBG, textColor: theme.text};
-        }
-    }, [status, theme]);
+function getRateStatusColors(status: string, theme: ReturnType<typeof useTheme>, isSelected?: boolean) {
+    switch (status) {
+        case CONST.CUSTOM_UNITS.RATE_STATUS.ACTIVE:
+            return theme.reportStatusBadge.paid;
+        case CONST.CUSTOM_UNITS.RATE_STATUS.FUTURE:
+            return theme.reportStatusBadge.draft;
+        case CONST.CUSTOM_UNITS.RATE_STATUS.EXPIRED:
+            return theme.reportStatusBadge.outstanding;
+        case CONST.CUSTOM_UNITS.RATE_STATUS.INACTIVE:
+        default:
+            return {backgroundColor: isSelected ? theme.buttonHoveredBG : theme.badgeDefaultBG, textColor: theme.text};
+    }
 }
 
 function WorkspaceDistanceRatesTableRow({item, rowIndex, shouldUseNarrowTableLayout, statusLabels}: WorkspaceDistanceRatesTableRowProps) {
@@ -73,12 +70,14 @@ function WorkspaceDistanceRatesTableRow({item, rowIndex, shouldUseNarrowTableLay
     const styles = useThemeStyles();
     const {translate} = useLocalize();
     const Expensicons = useMemoizedLazyExpensifyIcons(['ArrowRight']);
+    const {processedData} = useTableContext<DistanceRateTableItemData>();
 
     const {rate, formattedRate, pendingAction, errors} = item;
     const isDeleting = pendingAction === CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE;
+    const isSelected = processedData.at(rowIndex)?.selected ?? false;
 
     const status = getRateStatus(rate);
-    const statusColors = useRateStatusColors(status);
+    const statusColors = getRateStatusColors(status, theme, isSelected);
     const dateLabelText = DistanceRequestUtils.getRateDateLabel({...rate, unit: CONST.CUSTOM_UNITS.DISTANCE_UNIT_MILES}, translate);
 
     const accessibilityLabel = [rate.name, statusLabels[status], formattedRate, dateLabelText].filter(Boolean).join(', ');
diff --git a/src/components/Tables/WorkspaceDistanceRatesTable/index.tsx b/src/components/Tables/WorkspaceDistanceRatesTable/index.tsx
index 2bb5e3533e1c..06ec901bcad1 100644
--- a/src/components/Tables/WorkspaceDistanceRatesTable/index.tsx
+++ b/src/components/Tables/WorkspaceDistanceRatesTable/index.tsx
@@ -2,34 +2,23 @@ import type {ListRenderItemInfo} from '@shopify/flash-list';
 import React, {useEffect, useMemo, useRef, useState} from 'react';
 import Table from '@components/Table';
 import type {ActiveSorting, CompareItemsCallback, IsItemInSearchCallback, TableColumn, TableHandle} from '@components/Table';
-import useBottomSafeSafeAreaPaddingStyle from '@hooks/useBottomSafeSafeAreaPaddingStyle';
 import useLocalize from '@hooks/useLocalize';
 import useResponsiveLayout from '@hooks/useResponsiveLayout';
 import useThemeStyles from '@hooks/useThemeStyles';
-import {convertAmountToDisplayString} from '@libs/CurrencyUtils';
 import {getRateStatus} from '@libs/PolicyDistanceRatesUtils';
 import tokenizedSearch from '@libs/tokenizedSearch';
 import variables from '@styles/variables';
 import CONST from '@src/CONST';
-import type * as OnyxCommon from '@src/types/onyx/OnyxCommon';
-import type {Rate} from '@src/types/onyx/Policy';
 import WorkspaceDistanceRatesTableRow from './WorkspaceDistanceRatesTableRow';
 import type {DistanceRateTableItemData} from './WorkspaceDistanceRatesTableRow';
 
 type DistanceRatesTableColumnKey = 'status' | 'name' | 'rate' | 'startDate' | 'endDate' | 'enabled' | 'actions';
 
 type WorkspaceDistanceRatesTableProps = {
-    customUnitRates: Record<string, Rate>;
-    unitTranslation: string;
+    ratesData: DistanceRateTableItemData[];
     selectionEnabled: boolean;
     selectedKeys: string[];
     onRowSelectionChange: (selectedRowKeys: string[]) => void;
-    onPressRate: (rateID: string) => void;
-    onDismissError: (rateID: string) => void;
-    onToggleEnabled: (value: boolean, rateID: string) => void;
-    canDisableOrDeleteRate: (rateID: string) => boolean;
-    pendingAction?: OnyxCommon.PendingAction;
-    pendingFields?: OnyxCommon.PendingFields<string>;
     EmptyStateComponent?: React.ReactElement;
 };
 
@@ -40,20 +29,7 @@ const STATUS_ORDER: Record<string, number> = {
     [CONST.CUSTOM_UNITS.RATE_STATUS.INACTIVE]: 3,
 };
 
-function WorkspaceDistanceRatesTable({
-    customUnitRates,
-    unitTranslation,
-    selectionEnabled,
-    selectedKeys,
-    onRowSelectionChange,
-    onPressRate,
-    onDismissError,
-    onToggleEnabled,
-    canDisableOrDeleteRate,
-    pendingAction,
-    pendingFields,
-    EmptyStateComponent,
-}: WorkspaceDistanceRatesTableProps) {
+function WorkspaceDistanceRatesTable({ratesData, selectionEnabled, selectedKeys, onRowSelectionChange, EmptyStateComponent}: WorkspaceDistanceRatesTableProps) {
     const styles = useThemeStyles();
     const {translate, localeCompare} = useLocalize();
     const {shouldUseNarrowLayout, isMediumScreenWidth} = useResponsiveLayout();
@@ -77,46 +53,6 @@ function WorkspaceDistanceRatesTable({
         {key: 'actions', label: '', sortable: false, width: variables.tableCaretColumnWidth},
     ];
 
-    const ratesData: DistanceRateTableItemData[] = useMemo(
-        () =>
-            Object.values(customUnitRates).map((rate) => {
-                const resolvedPendingAction =
-                    rate.pendingAction ??
-                    rate.pendingFields?.rate ??
-                    rate.pendingFields?.enabled ??
-                    rate.pendingFields?.currency ??
-                    rate.pendingFields?.taxRateExternalID ??
-                    rate.pendingFields?.taxClaimablePercentage ??
-                    rate.pendingFields?.name ??
-                    pendingFields?.attributes ??
-                    (pendingAction === CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD ? pendingAction : undefined);
-
-                const isDeleting = resolvedPendingAction === CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE;
-
-                return {
-                    keyForList: rate.customUnitRateID,
-                    rateID: rate.customUnitRateID,
-                    rate,
-                    disabled: isDeleting,
-                    enabled: !!rate.enabled,
-                    isLocked: !selectionEnabled || !canDisableOrDeleteRate(rate.customUnitRateID) || isDeleting,
-                    formattedRate: `${convertAmountToDisplayString(rate.rate, rate.currency ?? CONST.CURRENCY.USD)} / ${unitTranslation}`,
-                    pendingAction: resolvedPendingAction ?? undefined,
-                    errors: rate.errors ?? undefined,
-                    action: () => onPressRate(rate.customUnitRateID),
-                    dismissError: () => onDismissError(rate.customUnitRateID),
-                    onToggleEnabled: (value: boolean) => onToggleEnabled(value, rate.customUnitRateID),
-                };
-            }),
-        [customUnitRates, unitTranslation, pendingFields?.attributes, pendingAction, onPressRate, onDismissError, onToggleEnabled, canDisableOrDeleteRate, selectionEnabled],
-    );
-
-    const tableBodyContentContainerStyle = useBottomSafeSafeAreaPaddingStyle({
-        addBottomSafeAreaPadding: true,
-        addOfflineIndicatorBottomSafeAreaPadding: true,
-        style: styles.pb4,
-    });
-
     const compareItems: CompareItemsCallback<DistanceRateTableItemData, DistanceRatesTableColumnKey> = (a, b, activeSorting) => {
         const orderMultiplier = activeSorting.order === 'asc' ? 1 : -1;
 
@@ -204,7 +140,7 @@ function WorkspaceDistanceRatesTable({
     }, [activeSortingInWideLayout, shouldUseNarrowTableLayout]);
 
     const isEmpty = ratesData.length === 0;
-    const shouldShowSearchBar = Object.keys(customUnitRates).length >= CONST.STANDARD_LIST_ITEM_LIMIT;
+    const shouldShowSearchBar = ratesData.length >= CONST.STANDARD_LIST_ITEM_LIMIT;
 
     return (
         <Table
@@ -226,7 +162,7 @@ function WorkspaceDistanceRatesTable({
                 <>
                     {shouldShowSearchBar && <Table.SearchBar label={translate('workspace.distanceRates.findRate')} />}
                     <Table.Header />
-                    <Table.Body contentContainerStyle={tableBodyContentContainerStyle} />
+                    <Table.Body />
                 </>
             )}
         </Table>
diff --git a/src/pages/workspace/distanceRates/PolicyDistanceRatesPage.tsx b/src/pages/workspace/distanceRates/PolicyDistanceRatesPage.tsx
index 5868b85a9026..378d1078c2f3 100644
--- a/src/pages/workspace/distanceRates/PolicyDistanceRatesPage.tsx
+++ b/src/pages/workspace/distanceRates/PolicyDistanceRatesPage.tsx
@@ -10,6 +10,7 @@ import type {IllustrationName} from '@components/Icon/IllustrationLoader';
 import {ModalActions} from '@components/Modal/Global/ModalContext';
 import ScreenWrapper from '@components/ScreenWrapper';
 import WorkspaceDistanceRatesTable from '@components/Tables/WorkspaceDistanceRatesTable';
+import type {DistanceRateTableItemData} from '@components/Tables/WorkspaceDistanceRatesTable/WorkspaceDistanceRatesTableRow';
 import Text from '@components/Text';
 import useCleanupSelectedOptions from '@hooks/useCleanupSelectedOptions';
 import useConfirmModal from '@hooks/useConfirmModal';
@@ -35,6 +36,7 @@ import {
     openPolicyDistanceRatesPage,
     setPolicyDistanceRatesEnabled,
 } from '@libs/actions/Policy/DistanceRate';
+import {convertAmountToDisplayString} from '@libs/CurrencyUtils';
 import Navigation from '@libs/Navigation/Navigation';
 import type {PlatformStackScreenProps} from '@libs/Navigation/PlatformStackNavigation/types';
 import {getDistanceRateCustomUnit} from '@libs/PolicyUtils';
@@ -289,6 +291,50 @@ function PolicyDistanceRatesPage({
         [policyID],
     );
 
+    const ratesData: DistanceRateTableItemData[] = useMemo(
+        () =>
+            Object.values(customUnitRates).map((rate) => {
+                const resolvedPendingAction =
+                    rate.pendingAction ??
+                    rate.pendingFields?.rate ??
+                    rate.pendingFields?.enabled ??
+                    rate.pendingFields?.currency ??
+                    rate.pendingFields?.taxRateExternalID ??
+                    rate.pendingFields?.taxClaimablePercentage ??
+                    rate.pendingFields?.name ??
+                    customUnit?.pendingFields?.attributes ??
+                    (policy?.pendingAction === CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD ? policy?.pendingAction : undefined);
+
+                const isDeleting = resolvedPendingAction === CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE;
+
+                return {
+                    keyForList: rate.customUnitRateID,
+                    rateID: rate.customUnitRateID,
+                    rate,
+                    disabled: isDeleting,
+                    enabled: !!rate.enabled,
+                    isLocked: !canWriteDistanceRates || !canDisableOrDeleteRate(rate.customUnitRateID) || isDeleting,
+                    formattedRate: `${convertAmountToDisplayString(rate.rate, rate.currency ?? CONST.CURRENCY.USD)} / ${unitTranslation}`,
+                    pendingAction: resolvedPendingAction ?? undefined,
+                    errors: rate.errors ?? undefined,
+                    action: () => openRateDetailsByID(rate.customUnitRateID),
+                    dismissError: () => dismissErrorByID(rate.customUnitRateID),
+                    onToggleEnabled: (value: boolean) => updateDistanceRateEnabled(value, rate.customUnitRateID),
+                };
+            }),
+        [
+            customUnitRates,
+            unitTranslation,
+            customUnit?.pendingFields?.attributes,
+            policy?.pendingAction,
+            canWriteDistanceRates,
+            canDisableOrDeleteRate,
+            openRateDetailsByID,
+            dismissErrorByID,
+            updateDistanceRateEnabled,
+        ],
+    );
+
     const getBulkActionsButtonOptions = () => {
         const options: Array<DropdownOption<WorkspaceDistanceRatesBulkActionType>> = [
             {
@@ -438,23 +484,16 @@ function PolicyDistanceRatesPage({
                 )}
                 {!isLoading && (
                     <>
-                        {Object.values(customUnitRates).length > 0 && (
+                        {ratesData.length > 0 && (
                             <View style={[styles.ph5, styles.pb5, styles.pt3, shouldUseNarrowLayout ? styles.workspaceSectionMobile : styles.workspaceSection]}>
                                 <Text style={[styles.textNormal, styles.colorMuted]}>{translate('workspace.distanceRates.centrallyManage')}</Text>
                             </View>
                         )}
                         <WorkspaceDistanceRatesTable
-                            customUnitRates={customUnitRates}
-                            unitTranslation={unitTranslation}
+                            ratesData={ratesData}
                             selectionEnabled={canWriteDistanceRates}
                             selectedKeys={selectedDistanceRates}
                             onRowSelectionChange={setSelectedDistanceRates}
-                            onPressRate={openRateDetailsByID}
-                            onDismissError={dismissErrorByID}
-                            onToggleEnabled={updateDistanceRateEnabled}
-                            canDisableOrDeleteRate={canDisableOrDeleteRate}
-                            pendingAction={policy?.pendingAction === CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD ? policy?.pendingAction : undefined}
-                            pendingFields={customUnit?.pendingFields}
                         />
                     </>
                 )}

From 9d1e10989bf27e4e7ab5e6d7cb06be7b8942756f Mon Sep 17 00:00:00 2001
From: krishna2323 <belivethatkg@gmail.com>
Date: Wed, 10 Jun 2026 21:39:37 +0530
Subject: [PATCH 284/435] Refactor distance rates table: simplify props, fix
 badge, move sort logic to middleware

Signed-off-by: krishna2323 <belivethatkg@gmail.com>
---
 src/components/Table/Table.tsx                | 14 ++++++--
 src/components/Table/middlewares/sorting.ts   | 22 ++++++++++---
 src/components/Table/types.ts                 |  3 ++
 .../WorkspaceDistanceRatesTable/index.tsx     | 33 ++-----------------
 4 files changed, 35 insertions(+), 37 deletions(-)

diff --git a/src/components/Table/Table.tsx b/src/components/Table/Table.tsx
index 89d86d71f8a8..c95436c9b7d7 100644
--- a/src/components/Table/Table.tsx
+++ b/src/components/Table/Table.tsx
@@ -149,6 +149,7 @@ function Table<DataType extends TableData, ColumnKey extends string = string, Fi
     isItemInFilter,
     isItemInSearch,
     initialSortColumn,
+    narrowLayoutSortColumn,
     children,
     selectionEnabled,
     onRowSelectionChange,
@@ -163,6 +164,7 @@ function Table<DataType extends TableData, ColumnKey extends string = string, Fi
     }
 
     const {shouldUseNarrowLayout, isMediumScreenWidth} = useResponsiveLayout();
+    const shouldUseNarrowTableLayout = shouldUseNarrowLayout || isMediumScreenWidth;
 
     const {middleware: filterMiddleware, currentFilters, methods: filterMethods} = useFiltering<DataType, FilterKey>({filters, isItemInFilter});
     const filteredData = filterMiddleware(data);
@@ -170,7 +172,16 @@ function Table<DataType extends TableData, ColumnKey extends string = string, Fi
     const {middleware: searchMiddleware, activeSearchString, methods: searchMethods} = useSearching<DataType>({isItemInSearch});
     const searchedData = searchMiddleware(filteredData);
 
-    const {middleware: sortMiddleware, activeSorting, methods: sortMethods} = useSorting<DataType, ColumnKey>({compareItems, initialSortColumn});
+    const {
+        middleware: sortMiddleware,
+        activeSorting,
+        methods: sortMethods,
+    } = useSorting<DataType, ColumnKey>({
+        compareItems,
+        initialSortColumn,
+        narrowLayoutSortColumn,
+        shouldUseNarrowTableLayout,
+    });
     const sortedData = sortMiddleware(searchedData);
 
     const {middleware: selectionMiddleware, methods: selectionMethods, mobileSelectionModalRowKey} = useSelection<DataType>({data: sortedData, selectedKeys, onRowSelectionChange});
@@ -206,7 +217,6 @@ function Table<DataType extends TableData, ColumnKey extends string = string, Fi
     });
 
     const originalDataLength = data?.length ?? 0;
-    const shouldUseNarrowTableLayout = shouldUseNarrowLayout || isMediumScreenWidth;
 
     // Check if filters are applied (not default values)
     const hasActiveFilters = filters
diff --git a/src/components/Table/middlewares/sorting.ts b/src/components/Table/middlewares/sorting.ts
index 1b775fffa91e..a31344ed6fcc 100644
--- a/src/components/Table/middlewares/sorting.ts
+++ b/src/components/Table/middlewares/sorting.ts
@@ -1,4 +1,4 @@
-import {useState} from 'react';
+import {useMemo, useState} from 'react';
 import type {SetStateAction} from 'react';
 import type {Middleware, MiddlewareHookResult} from './types';
 
@@ -60,6 +60,8 @@ type SortingMethods<ColumnKey extends string = string> = {
 type UseSortingProps<T, ColumnKey extends string = string> = {
     compareItems?: CompareItemsCallback<T, ColumnKey>;
     initialSortColumn?: ColumnKey;
+    narrowLayoutSortColumn?: ColumnKey;
+    shouldUseNarrowTableLayout?: boolean;
 };
 
 /**
@@ -82,14 +84,24 @@ type UseSortingResult<T, ColumnKey extends string = string> = MiddlewareHookResu
  * @param initialSortColumn - The initial column to sort by on mount.
  * @returns The result of the sorting middleware.
  */
-function useSorting<T, ColumnKey extends string = string>({compareItems, initialSortColumn}: UseSortingProps<T, ColumnKey>): UseSortingResult<T, ColumnKey> {
-    const [activeSorting, updateSorting] = useState<ActiveSorting<ColumnKey>>({
+function useSorting<T, ColumnKey extends string = string>({
+    compareItems,
+    initialSortColumn,
+    narrowLayoutSortColumn,
+    shouldUseNarrowTableLayout,
+}: UseSortingProps<T, ColumnKey>): UseSortingResult<T, ColumnKey> {
+    const [userSorting, setUserSorting] = useState<ActiveSorting<ColumnKey>>({
         columnKey: initialSortColumn,
         order: 'asc',
     });
 
+    const activeSorting = useMemo(
+        () => (shouldUseNarrowTableLayout && narrowLayoutSortColumn ? ({columnKey: narrowLayoutSortColumn, order: 'asc'} satisfies ActiveSorting<ColumnKey>) : userSorting),
+        [shouldUseNarrowTableLayout, narrowLayoutSortColumn, userSorting],
+    );
+
     const toggleColumnSorting: SortingMethods<ColumnKey>['toggleColumnSorting'] = (columnKey) => {
-        updateSorting((previousSorting) => {
+        setUserSorting((previousSorting) => {
             const columnKeyToUse = columnKey ?? previousSorting.columnKey;
             const orderToUse = previousSorting.order === 'asc' ? 'desc' : 'asc';
 
@@ -107,7 +119,7 @@ function useSorting<T, ColumnKey extends string = string>({compareItems, initial
     const middleware: Middleware<T> = (data) => sort({data, activeSorting, compareItems});
 
     const methods: SortingMethods<ColumnKey> = {
-        updateSorting,
+        updateSorting: setUserSorting,
         toggleColumnSorting,
         getActiveSorting,
     };
diff --git a/src/components/Table/types.ts b/src/components/Table/types.ts
index 834fad6a2ed9..bb1168abf553 100644
--- a/src/components/Table/types.ts
+++ b/src/components/Table/types.ts
@@ -138,6 +138,9 @@ type TableProps<DataType extends TableData, ColumnKey extends string = string, F
         /** Optional initial column to sort by on mount. */
         initialSortColumn?: ColumnKey;
 
+        /** Optional column to force-sort by when the table switches to narrow layout. The wide-layout sorting is restored when leaving narrow layout. */
+        narrowLayoutSortColumn?: ColumnKey;
+
         /** Optional initial search string to apply on mount. */
         initialSearchString?: string;
 
diff --git a/src/components/Tables/WorkspaceDistanceRatesTable/index.tsx b/src/components/Tables/WorkspaceDistanceRatesTable/index.tsx
index 06ec901bcad1..92ab782a1d46 100644
--- a/src/components/Tables/WorkspaceDistanceRatesTable/index.tsx
+++ b/src/components/Tables/WorkspaceDistanceRatesTable/index.tsx
@@ -1,7 +1,7 @@
 import type {ListRenderItemInfo} from '@shopify/flash-list';
-import React, {useEffect, useMemo, useRef, useState} from 'react';
+import React, {useMemo} from 'react';
 import Table from '@components/Table';
-import type {ActiveSorting, CompareItemsCallback, IsItemInSearchCallback, TableColumn, TableHandle} from '@components/Table';
+import type {CompareItemsCallback, IsItemInSearchCallback, TableColumn} from '@components/Table';
 import useLocalize from '@hooks/useLocalize';
 import useResponsiveLayout from '@hooks/useResponsiveLayout';
 import useThemeStyles from '@hooks/useThemeStyles';
@@ -35,8 +35,6 @@ function WorkspaceDistanceRatesTable({ratesData, selectionEnabled, selectedKeys,
     const {shouldUseNarrowLayout, isMediumScreenWidth} = useResponsiveLayout();
     const shouldUseNarrowTableLayout = shouldUseNarrowLayout || isMediumScreenWidth;
 
-    const tableRef = useRef<TableHandle<DistanceRateTableItemData, DistanceRatesTableColumnKey>>(null);
-
     const columns: Array<TableColumn<DistanceRatesTableColumnKey>> = [
         {
             key: 'status',
@@ -114,37 +112,11 @@ function WorkspaceDistanceRatesTable({ratesData, selectionEnabled, selectedKeys,
         />
     );
 
-    const isNarrowLayoutRef = useRef(shouldUseNarrowTableLayout);
-    const [activeSortingInWideLayout, setActiveSortingInWideLayout] = useState<ActiveSorting<DistanceRatesTableColumnKey> | undefined>(undefined);
-
-    useEffect(() => {
-        if (shouldUseNarrowTableLayout) {
-            if (isNarrowLayoutRef.current) {
-                return;
-            }
-            isNarrowLayoutRef.current = true;
-            const activeSorting = tableRef.current?.getActiveSorting();
-            setActiveSortingInWideLayout(activeSorting);
-            tableRef.current?.updateSorting({columnKey: 'name', order: 'asc'});
-            return;
-        }
-
-        if (!isNarrowLayoutRef.current) {
-            return;
-        }
-
-        isNarrowLayoutRef.current = false;
-        if (activeSortingInWideLayout) {
-            tableRef.current?.updateSorting(activeSortingInWideLayout);
-        }
-    }, [activeSortingInWideLayout, shouldUseNarrowTableLayout]);
-
     const isEmpty = ratesData.length === 0;
     const shouldShowSearchBar = ratesData.length >= CONST.STANDARD_LIST_ITEM_LIMIT;
 
     return (
         <Table
-            ref={tableRef}
             data={ratesData}
             columns={columns}
             selectionEnabled={selectionEnabled}
@@ -155,6 +127,7 @@ function WorkspaceDistanceRatesTable({ratesData, selectionEnabled, selectedKeys,
             compareItems={compareItems}
             isItemInSearch={isItemInSearch}
             initialSortColumn="name"
+            narrowLayoutSortColumn="name"
             title={translate('workspace.common.distanceRates')}
         >
             {isEmpty && EmptyStateComponent}

From ea51981ca1cd5bec5738e71373f651972dc56bdc Mon Sep 17 00:00:00 2001
From: krishna2323 <belivethatkg@gmail.com>
Date: Wed, 10 Jun 2026 21:59:17 +0530
Subject: [PATCH 285/435] Remove defensive try/catch from formatDate.

Signed-off-by: krishna2323 <belivethatkg@gmail.com>
---
 .../WorkspaceDistanceRatesTableRow.tsx                      | 6 +-----
 1 file changed, 1 insertion(+), 5 deletions(-)

diff --git a/src/components/Tables/WorkspaceDistanceRatesTable/WorkspaceDistanceRatesTableRow.tsx b/src/components/Tables/WorkspaceDistanceRatesTable/WorkspaceDistanceRatesTableRow.tsx
index 98519d9085bf..19372d5021e6 100644
--- a/src/components/Tables/WorkspaceDistanceRatesTable/WorkspaceDistanceRatesTableRow.tsx
+++ b/src/components/Tables/WorkspaceDistanceRatesTable/WorkspaceDistanceRatesTableRow.tsx
@@ -44,11 +44,7 @@ function formatDate(dateString: string | null | undefined): string {
     if (!dateString) {
         return '';
     }
-    try {
-        return format(parseISO(dateString), CONST.DATE.MONTH_DAY_YEAR_ABBR_FORMAT);
-    } catch {
-        return '';
-    }
+    return format(parseISO(dateString), CONST.DATE.MONTH_DAY_YEAR_ABBR_FORMAT);
 }
 
 function getRateStatusColors(status: string, theme: ReturnType<typeof useTheme>, isSelected?: boolean) {

From dea52c18359247749bc5a3b715501c7ed4f54d9b Mon Sep 17 00:00:00 2001
From: ShridharGoel <35566748+ShridharGoel@users.noreply.github.com>
Date: Wed, 10 Jun 2026 23:15:20 +0530
Subject: [PATCH 286/435] Restrict Expensify Card bank setup to admins

---
 .../expensifyCard/WorkspaceExpensifyCardBankAccounts.tsx     | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/src/pages/workspace/expensifyCard/WorkspaceExpensifyCardBankAccounts.tsx b/src/pages/workspace/expensifyCard/WorkspaceExpensifyCardBankAccounts.tsx
index 21d8334abff9..65497407c1db 100644
--- a/src/pages/workspace/expensifyCard/WorkspaceExpensifyCardBankAccounts.tsx
+++ b/src/pages/workspace/expensifyCard/WorkspaceExpensifyCardBankAccounts.tsx
@@ -8,6 +8,7 @@ import getBankIcon from '@components/Icon/BankIcons';
 import MenuItem from '@components/MenuItem';
 import ScreenWrapper from '@components/ScreenWrapper';
 import Text from '@components/Text';
+import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails';
 import useDefaultFundID from '@hooks/useDefaultFundID';
 import useExpensifyCardUkEuSupported from '@hooks/useExpensifyCardUkEuSupported';
 import {useMemoizedLazyExpensifyIcons} from '@hooks/useLazyAsset';
@@ -19,6 +20,7 @@ import {getLastFourDigits} from '@libs/BankAccountUtils';
 import {getEligibleBankAccountsForCard, getEligibleBankAccountsForUkEuCard} from '@libs/CardUtils';
 import createDynamicRoute from '@libs/Navigation/helpers/dynamicRoutesUtils/createDynamicRoute';
 import type {PlatformStackScreenProps} from '@libs/Navigation/PlatformStackNavigation/types';
+import {canEditWorkspaceSettings} from '@libs/PolicyUtils';
 import Navigation from '@navigation/Navigation';
 import type {SettingsNavigatorParamList} from '@navigation/types';
 import AccessOrNotFoundWrapper from '@pages/workspace/AccessOrNotFoundWrapper';
@@ -36,9 +38,11 @@ function WorkspaceExpensifyCardBankAccounts({route}: WorkspaceExpensifyCardBankA
     const {translate} = useLocalize();
     const styles = useThemeStyles();
     const [bankAccountsList] = useOnyx(ONYXKEYS.BANK_ACCOUNT_LIST);
+    const {login: currentUserLogin = ''} = useCurrentUserPersonalDetails();
 
     const policyID = route?.params?.policyID;
     const policy = usePolicy(policyID);
+    const canStartBankAccountSetup = canEditWorkspaceSettings(policy, currentUserLogin);
 
     const isUkEuCurrencySupported = useExpensifyCardUkEuSupported(policyID);
 
@@ -140,6 +144,7 @@ function WorkspaceExpensifyCardBankAccounts({route}: WorkspaceExpensifyCardBankA
             featureName={CONST.POLICY.MORE_FEATURES.ARE_EXPENSIFY_CARDS_ENABLED}
             policyFeature={CONST.POLICY.POLICY_FEATURE.EXPENSIFY_CARD}
             policyFeatureAccess={CONST.POLICY.POLICY_FEATURE_ACCESS.WRITE}
+            shouldBeBlocked={!canStartBankAccountSetup}
         >
             <ScreenWrapper
                 testID="WorkspaceExpensifyCardBankAccounts"

From 518294a770173d1ade40d15e0927b4d2e2190e8f Mon Sep 17 00:00:00 2001
From: Alex Beaman <alexbeaman@expensify.com>
Date: Wed, 10 Jun 2026 12:26:32 -0600
Subject: [PATCH 287/435] Render manual vendor change as MODIFIEDEXPENSE 'set
 vendor X'

Auth's UpdateMoneyRequestVendor already writes {externalID, isManuallySet} as vendor/oldVendor on the MODIFIEDEXPENSE originalMessage. Mirror that on the App side:

- Extend OriginalMessageModifiedExpense + AdditionalTransactionChanges with vendor/oldVendor fields.
- Branch in getModifiedExpenseOriginalMessage so a {vendor: ...} change yields oldVendor + vendor on the action.
- ModifiedExpenseMessage resolves names via getQBOVendorByID(policy, externalID), falling back to externalID if the vendor has since been removed from QBO.
- updateMoneyRequestVendor now takes transactionThreadReport + parentReport + policy + delegateAccountID and builds an optimistic MODIFIEDEXPENSE so the message renders without waiting for the server.
- IOURequestStepVendor passes those through.

Tests updated for new param shape.
---
 src/libs/ModifiedExpenseMessage.ts            | 26 +++++-
 src/libs/ReportUtils.ts                       |  5 ++
 src/libs/actions/IOU/UpdateMoneyRequest.ts    | 81 +++++++++++++++++--
 .../iou/request/step/IOURequestStepVendor.tsx | 16 +++-
 src/types/onyx/OriginalMessage.ts             |  6 ++
 src/types/onyx/Transaction.ts                 |  3 +
 .../IOUTest/UpdateMoneyRequestVendorTest.ts   | 18 ++---
 7 files changed, 139 insertions(+), 16 deletions(-)

diff --git a/src/libs/ModifiedExpenseMessage.ts b/src/libs/ModifiedExpenseMessage.ts
index 61d0b20ebf17..df71f55fe1d6 100644
--- a/src/libs/ModifiedExpenseMessage.ts
+++ b/src/libs/ModifiedExpenseMessage.ts
@@ -15,7 +15,7 @@ import {formatList} from './Localize';
 import Log from './Log';
 import Parser from './Parser';
 import {getPersonalDetailByEmail} from './PersonalDetailsUtils';
-import {getCleanedTagName, getCommaSeparatedTagNameWithSanitizedColons, getSortedTagKeys, isPolicyAdmin} from './PolicyUtils';
+import {getCleanedTagName, getCommaSeparatedTagNameWithSanitizedColons, getQBOVendorByID, getSortedTagKeys, isPolicyAdmin} from './PolicyUtils';
 import {getOriginalMessage, isModifiedExpenseAction} from './ReportActionsUtils';
 // This cycle import is safe because ReportNameUtils was extracted from ReportUtils to separate report name computation logic.
 // The functions imported here are pure utility functions that don't create initialization-time dependencies.
@@ -448,6 +448,30 @@ function getForReportAction({
         buildMessageFragmentForValue(translate, newReimbursable, oldReimbursable, translate('iou.expense'), true, setFragments, removalFragments, changeFragments);
     }
 
+    const hasModifiedVendor = isReportActionOriginalMessageAnObject && 'oldVendor' in reportActionOriginalMessage && 'vendor' in reportActionOriginalMessage;
+    if (hasModifiedVendor) {
+        // Vendor is stored on the action as `{externalID, isManuallySet}` (or null). Resolve the
+        // display name from the policy's QBO vendor list; if the vendor has since been removed
+        // from QBO the name is unrecoverable, so fall back to the externalID so the fragment still
+        // identifies which vendor was set rather than rendering `set vendor ""`.
+        const resolveVendorName = (entry: typeof reportActionOriginalMessage.vendor): string => {
+            if (!entry?.externalID) {
+                return '';
+            }
+            return getQBOVendorByID(policy, entry.externalID)?.name ?? entry.externalID;
+        };
+        buildMessageFragmentForValue(
+            translate,
+            resolveVendorName(reportActionOriginalMessage?.vendor),
+            resolveVendorName(reportActionOriginalMessage?.oldVendor),
+            translate('common.vendor'),
+            true,
+            setFragments,
+            removalFragments,
+            changeFragments,
+        );
+    }
+
     const hasModifiedAttendees = isReportActionOriginalMessageAnObject && 'oldAttendees' in reportActionOriginalMessage && 'newAttendees' in reportActionOriginalMessage;
     if (hasModifiedAttendees) {
         const [oldAttendees, attendees] = getFormattedAttendees(reportActionOriginalMessage.newAttendees, reportActionOriginalMessage.oldAttendees);
diff --git a/src/libs/ReportUtils.ts b/src/libs/ReportUtils.ts
index a88ddc1e6995..aec97d747c31 100644
--- a/src/libs/ReportUtils.ts
+++ b/src/libs/ReportUtils.ts
@@ -5647,6 +5647,11 @@ function getModifiedExpenseOriginalMessage(
         originalMessage.reimbursable = transactionChanges?.reimbursable ? 'reimbursable' : 'non-reimbursable';
     }
 
+    if ('vendor' in transactionChanges) {
+        originalMessage.oldVendor = oldTransaction?.comment?.vendor ?? null;
+        originalMessage.vendor = transactionChanges?.vendor ?? null;
+    }
+
     if ('billable' in transactionChanges) {
         const oldBillable = getBillable(oldTransaction);
         originalMessage.oldBillable = oldBillable ? 'billable' : 'non-billable';
diff --git a/src/libs/actions/IOU/UpdateMoneyRequest.ts b/src/libs/actions/IOU/UpdateMoneyRequest.ts
index 7d8ff9edab13..b200e4e4bdea 100644
--- a/src/libs/actions/IOU/UpdateMoneyRequest.ts
+++ b/src/libs/actions/IOU/UpdateMoneyRequest.ts
@@ -424,6 +424,16 @@ function updateMoneyRequestAttendees({
     API.write(WRITE_COMMANDS.UPDATE_MONEY_REQUEST_ATTENDEES, params, onyxData);
 }
 
+type UpdateMoneyRequestVendorParams = {
+    transactionID: string;
+    vendorID: string;
+    transaction?: OnyxEntry<OnyxTypes.Transaction>;
+    transactionThreadReport?: OnyxEntry<OnyxTypes.Report>;
+    parentReport?: OnyxEntry<OnyxTypes.Report>;
+    policy?: OnyxEntry<OnyxTypes.Policy>;
+    delegateAccountID: number | undefined;
+};
+
 /**
  * Update the QBO vendor matched to a non-reimbursable expense. The vendor lives on the transaction's
  * `comment.vendor` NVP as `{ externalID, isManuallySet }`. `isManuallySet` is hard-coded to `true` here
@@ -432,17 +442,33 @@ function updateMoneyRequestAttendees({
  *
  * Passing `vendorID=''` clears the vendor from the transaction.
  */
-function updateMoneyRequestVendor(transactionID: string, vendorID: string, transaction?: OnyxEntry<OnyxTypes.Transaction>) {
+function updateMoneyRequestVendor({transactionID, vendorID, transaction, transactionThreadReport, parentReport, policy, delegateAccountID}: UpdateMoneyRequestVendorParams) {
     // Fall back to the cached Onyx transaction when the caller doesn't pass one so failureData can
     // restore the actual previous vendor on API failure instead of clearing it.
     const resolvedTransaction = transaction ?? getAllTransactions()?.[`${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`];
     const previousVendor = resolvedTransaction?.comment?.vendor;
-    const optimisticReportActionID = rand64();
     const isClearing = !vendorID;
 
     const newVendorOptimisticValue = isClearing ? null : {externalID: vendorID, isManuallySet: true};
 
-    const optimisticData: Array<OnyxUpdate<typeof ONYXKEYS.COLLECTION.TRANSACTION | typeof ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS>> = [
+    // Build an optimistic MODIFIEDEXPENSE so the transaction thread shows "set vendor X" /
+    // "changed vendor from X to Y" / "removed the vendor" immediately. Auth's UpdateMoneyRequestVendor
+    // command writes the same {externalID, isManuallySet} shape to the action's originalMessage; the
+    // optimistic action mirrors that so the local render matches the eventual server payload.
+    const optimisticModifiedExpense =
+        resolvedTransaction && transactionThreadReport?.reportID
+            ? buildOptimisticModifiedExpenseReportAction(
+                  transactionThreadReport,
+                  resolvedTransaction,
+                  {vendor: newVendorOptimisticValue},
+                  isExpenseReport(parentReport),
+                  policy,
+                  delegateAccountID,
+              )
+            : null;
+    const optimisticReportActionID = optimisticModifiedExpense?.reportActionID ?? rand64();
+
+    const optimisticData: Array<OnyxUpdate<typeof ONYXKEYS.COLLECTION.TRANSACTION | typeof ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS | typeof ONYXKEYS.COLLECTION.REPORT_ACTIONS | typeof ONYXKEYS.COLLECTION.REPORT>> = [
         {
             onyxMethod: Onyx.METHOD.MERGE,
             key: `${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}` as const,
@@ -457,7 +483,7 @@ function updateMoneyRequestVendor(transactionID: string, vendorID: string, trans
         },
     ];
 
-    const successData: Array<OnyxUpdate<typeof ONYXKEYS.COLLECTION.TRANSACTION | typeof ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS>> = [
+    const successData: Array<OnyxUpdate<typeof ONYXKEYS.COLLECTION.TRANSACTION | typeof ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS | typeof ONYXKEYS.COLLECTION.REPORT_ACTIONS>> = [
         {
             onyxMethod: Onyx.METHOD.MERGE,
             key: `${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}` as const,
@@ -472,7 +498,7 @@ function updateMoneyRequestVendor(transactionID: string, vendorID: string, trans
     // Only roll back the vendor when we have a known prior snapshot. If the transaction isn't passed
     // in AND isn't cached in Onyx yet, we don't know what to restore — writing null here would silently
     // clear a vendor we don't know about. The next server sync will reconcile.
-    const failureData: Array<OnyxUpdate<typeof ONYXKEYS.COLLECTION.TRANSACTION | typeof ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS>> = [
+    const failureData: Array<OnyxUpdate<typeof ONYXKEYS.COLLECTION.TRANSACTION | typeof ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS | typeof ONYXKEYS.COLLECTION.REPORT_ACTIONS | typeof ONYXKEYS.COLLECTION.REPORT>> = [
         {
             onyxMethod: Onyx.METHOD.MERGE,
             key: `${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}` as const,
@@ -489,6 +515,51 @@ function updateMoneyRequestVendor(transactionID: string, vendorID: string, trans
         },
     ];
 
+    if (optimisticModifiedExpense && transactionThreadReport?.reportID) {
+        optimisticData.push(
+            {
+                onyxMethod: Onyx.METHOD.MERGE,
+                key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${transactionThreadReport.reportID}` as const,
+                value: {
+                    [optimisticModifiedExpense.reportActionID]: optimisticModifiedExpense as OnyxTypes.ReportAction,
+                },
+            },
+            {
+                onyxMethod: Onyx.METHOD.MERGE,
+                key: `${ONYXKEYS.COLLECTION.REPORT}${transactionThreadReport.reportID}` as const,
+                value: {
+                    lastReadTime: optimisticModifiedExpense.created,
+                },
+            },
+        );
+        successData.push({
+            onyxMethod: Onyx.METHOD.MERGE,
+            key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${transactionThreadReport.reportID}` as const,
+            value: {
+                [optimisticModifiedExpense.reportActionID]: {pendingAction: null},
+            },
+        });
+        failureData.push(
+            {
+                onyxMethod: Onyx.METHOD.MERGE,
+                key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${transactionThreadReport.reportID}` as const,
+                value: {
+                    [optimisticModifiedExpense.reportActionID]: {
+                        ...(optimisticModifiedExpense as OnyxTypes.ReportAction),
+                        errors: getMicroSecondOnyxErrorWithTranslationKey('iou.error.genericEditFailureMessage'),
+                    },
+                },
+            },
+            {
+                onyxMethod: Onyx.METHOD.MERGE,
+                key: `${ONYXKEYS.COLLECTION.REPORT}${transactionThreadReport.reportID}` as const,
+                value: {
+                    lastReadTime: transactionThreadReport.lastReadTime,
+                },
+            },
+        );
+    }
+
     // Optimistically clear any existing inactive-vendor violation. This is the user-driven write
     // path: the vendor selector RHP only offers vendors from `getQBOVendors(policy)`, so a user
     // pick is always a valid vendor (resolving the violation); clearing the vendor likewise
diff --git a/src/pages/iou/request/step/IOURequestStepVendor.tsx b/src/pages/iou/request/step/IOURequestStepVendor.tsx
index f05519aaaf8c..b6cb1e3a6250 100644
--- a/src/pages/iou/request/step/IOURequestStepVendor.tsx
+++ b/src/pages/iou/request/step/IOURequestStepVendor.tsx
@@ -1,8 +1,10 @@
 import React, {useState} from 'react';
+import {useOnyx} from 'react-native-onyx';
 import BlockingView from '@components/BlockingViews/BlockingView';
 import SelectionList from '@components/SelectionList';
 import SingleSelectListItem from '@components/SelectionList/ListItem/SingleSelectListItem';
 import type {ListItem} from '@components/SelectionList/types';
+import useDelegateAccountID from '@hooks/useDelegateAccountID';
 import {useMemoizedLazyIllustrations} from '@hooks/useLazyAsset';
 import useLocalize from '@hooks/useLocalize';
 import usePermissions from '@hooks/usePermissions';
@@ -10,11 +12,13 @@ import usePolicyForTransaction from '@hooks/usePolicyForTransaction';
 import useShowNotFoundPageInIOUStep from '@hooks/useShowNotFoundPageInIOUStep';
 import useThemeStyles from '@hooks/useThemeStyles';
 import {updateMoneyRequestVendor} from '@libs/actions/IOU/UpdateMoneyRequest';
+import getNonEmptyStringOnyxID from '@libs/getNonEmptyStringOnyxID';
 import Navigation from '@libs/Navigation/Navigation';
 import {getQBOVendors, hasVendorFeature} from '@libs/PolicyUtils';
 import {isPerDiemRequest} from '@libs/TransactionUtils';
 import variables from '@styles/variables';
 import CONST from '@src/CONST';
+import ONYXKEYS from '@src/ONYXKEYS';
 import type SCREENS from '@src/SCREENS';
 import StepScreenWrapper from './StepScreenWrapper';
 import type {WithFullTransactionOrNotFoundProps} from './withFullTransactionOrNotFound';
@@ -48,6 +52,8 @@ function IOURequestStepVendor({
         iouType,
         isPerDiemRequest: isPerDiemRequest(transaction),
     });
+    const [parentReport] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${getNonEmptyStringOnyxID(report?.parentReportID)}`);
+    const delegateAccountID = useDelegateAccountID();
 
     const isFeatureAvailable = hasVendorFeature(policy, isBetaEnabled(CONST.BETAS.VENDOR_MATCHING));
 
@@ -91,7 +97,15 @@ function IOURequestStepVendor({
 
     const selectVendor = (item: VendorListItem) => {
         if (item.value !== currentVendorID) {
-            updateMoneyRequestVendor(transactionID, item.value, transaction);
+            updateMoneyRequestVendor({
+                transactionID,
+                vendorID: item.value,
+                transaction,
+                transactionThreadReport: report,
+                parentReport,
+                policy,
+                delegateAccountID,
+            });
         }
         navigateBack();
     };
diff --git a/src/types/onyx/OriginalMessage.ts b/src/types/onyx/OriginalMessage.ts
index fb2fbee2a823..a6e664d36b57 100644
--- a/src/types/onyx/OriginalMessage.ts
+++ b/src/types/onyx/OriginalMessage.ts
@@ -952,6 +952,12 @@ type OriginalMessageModifiedExpense = {
     /** Old expense reimbursable */
     oldReimbursable?: string;
 
+    /** Edited accounting-system vendor on the transaction's comment NVP. `null` means the vendor was cleared. */
+    vendor?: {externalID: string; isManuallySet: boolean} | null;
+
+    /** Previous accounting-system vendor on the transaction's comment NVP. `null` means there was no prior vendor. */
+    oldVendor?: {externalID: string; isManuallySet: boolean} | null;
+
     /** Collection of accountIDs of users mentioned in expense report */
     whisperedTo?: number[];
 
diff --git a/src/types/onyx/Transaction.ts b/src/types/onyx/Transaction.ts
index c43e09063466..623194a08639 100644
--- a/src/types/onyx/Transaction.ts
+++ b/src/types/onyx/Transaction.ts
@@ -717,6 +717,9 @@ type AdditionalTransactionChanges = {
 
     /** The unit for the distance/quantity */
     quantity?: number;
+
+    /** Accounting-system vendor on the transaction's comment NVP. `null` clears the vendor. */
+    vendor?: {externalID: string; isManuallySet: boolean} | null;
 };
 
 /** Model of transaction changes  */
diff --git a/tests/actions/IOUTest/UpdateMoneyRequestVendorTest.ts b/tests/actions/IOUTest/UpdateMoneyRequestVendorTest.ts
index 31f4e4ce68d2..3c14807962c1 100644
--- a/tests/actions/IOUTest/UpdateMoneyRequestVendorTest.ts
+++ b/tests/actions/IOUTest/UpdateMoneyRequestVendorTest.ts
@@ -60,7 +60,7 @@ describe('updateMoneyRequestVendor', () => {
         await Onyx.set(`${ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS}${TRANSACTION_ID}`, [otherViolation, inactiveVendorViolation]);
         await waitForBatchedUpdates();
 
-        updateMoneyRequestVendor(TRANSACTION_ID, 'v-active', baseTransaction);
+        updateMoneyRequestVendor({transactionID: TRANSACTION_ID, vendorID: 'v-active', transaction: baseTransaction, delegateAccountID: undefined});
 
         const onyxData = getOnyxDataArg();
         const violationsUpdate = onyxData?.optimisticData.find((entry) => entry.key === `${ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS}${TRANSACTION_ID}`);
@@ -72,7 +72,7 @@ describe('updateMoneyRequestVendor', () => {
         await Onyx.set(`${ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS}${TRANSACTION_ID}`, [inactiveVendorViolation]);
         await waitForBatchedUpdates();
 
-        updateMoneyRequestVendor(TRANSACTION_ID, '', baseTransaction);
+        updateMoneyRequestVendor({transactionID: TRANSACTION_ID, vendorID: '', transaction: baseTransaction, delegateAccountID: undefined});
 
         const onyxData = getOnyxDataArg();
         const violationsUpdate = onyxData?.optimisticData.find((entry) => entry.key === `${ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS}${TRANSACTION_ID}`);
@@ -85,7 +85,7 @@ describe('updateMoneyRequestVendor', () => {
         await Onyx.set(`${ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS}${TRANSACTION_ID}`, original);
         await waitForBatchedUpdates();
 
-        updateMoneyRequestVendor(TRANSACTION_ID, 'v-active', baseTransaction);
+        updateMoneyRequestVendor({transactionID: TRANSACTION_ID, vendorID: 'v-active', transaction: baseTransaction, delegateAccountID: undefined});
 
         const onyxData = getOnyxDataArg();
         const failureViolations = onyxData?.failureData.find((entry) => entry.key === `${ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS}${TRANSACTION_ID}`);
@@ -96,7 +96,7 @@ describe('updateMoneyRequestVendor', () => {
         await Onyx.set(`${ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS}${TRANSACTION_ID}`, [otherViolation]);
         await waitForBatchedUpdates();
 
-        updateMoneyRequestVendor(TRANSACTION_ID, 'v-active', baseTransaction);
+        updateMoneyRequestVendor({transactionID: TRANSACTION_ID, vendorID: 'v-active', transaction: baseTransaction, delegateAccountID: undefined});
 
         const onyxData = getOnyxDataArg();
         const violationsUpdate = onyxData?.optimisticData.find((entry) => entry.key === `${ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS}${TRANSACTION_ID}`);
@@ -111,7 +111,7 @@ describe('updateMoneyRequestVendor', () => {
         });
         await waitForBatchedUpdates();
 
-        updateMoneyRequestVendor(TRANSACTION_ID, 'v-new');
+        updateMoneyRequestVendor({transactionID: TRANSACTION_ID, vendorID: 'v-new', delegateAccountID: undefined});
 
         const onyxData = getOnyxDataArg();
         const transactionFailure = onyxData?.failureData.find((entry) => entry.key === `${ONYXKEYS.COLLECTION.TRANSACTION}${TRANSACTION_ID}`);
@@ -125,7 +125,7 @@ describe('updateMoneyRequestVendor', () => {
         // No transaction arg + nothing in Onyx — the prior vendor is unknown, so we must not
         // write `vendor: null` and silently clear whatever the server actually has. The
         // pendingFields-clear entry still runs (so the offline indicator clears on rejection).
-        updateMoneyRequestVendor(TRANSACTION_ID, 'v-new');
+        updateMoneyRequestVendor({transactionID: TRANSACTION_ID, vendorID: 'v-new', delegateAccountID: undefined});
 
         const onyxData = getOnyxDataArg();
         const transactionFailure = onyxData?.failureData.find((entry) => entry.key === `${ONYXKEYS.COLLECTION.TRANSACTION}${TRANSACTION_ID}`);
@@ -133,7 +133,7 @@ describe('updateMoneyRequestVendor', () => {
     });
 
     it('writes pendingFields.vendor = UPDATE in optimisticData so the offline indicator surfaces', () => {
-        updateMoneyRequestVendor(TRANSACTION_ID, 'v-new', baseTransaction);
+        updateMoneyRequestVendor({transactionID: TRANSACTION_ID, vendorID: 'v-new', transaction: baseTransaction, delegateAccountID: undefined});
 
         const onyxData = getOnyxDataArg();
         const transactionOptimistic = onyxData?.optimisticData.find((entry) => entry.key === `${ONYXKEYS.COLLECTION.TRANSACTION}${TRANSACTION_ID}`);
@@ -144,7 +144,7 @@ describe('updateMoneyRequestVendor', () => {
     });
 
     it('clears pendingFields.vendor in successData when the server confirms the write', () => {
-        updateMoneyRequestVendor(TRANSACTION_ID, 'v-new', baseTransaction);
+        updateMoneyRequestVendor({transactionID: TRANSACTION_ID, vendorID: 'v-new', transaction: baseTransaction, delegateAccountID: undefined});
 
         const onyxData = getOnyxDataArg();
         const transactionSuccess = onyxData?.successData.find((entry) => entry.key === `${ONYXKEYS.COLLECTION.TRANSACTION}${TRANSACTION_ID}`);
@@ -154,7 +154,7 @@ describe('updateMoneyRequestVendor', () => {
     it('clears pendingFields.vendor in failureData when the server rejects the write', () => {
         // Even without a prior snapshot to roll the vendor itself back, the pending indicator must
         // clear on failure — otherwise the row stays stuck in "pending" forever after a server reject.
-        updateMoneyRequestVendor(TRANSACTION_ID, 'v-new');
+        updateMoneyRequestVendor({transactionID: TRANSACTION_ID, vendorID: 'v-new', delegateAccountID: undefined});
 
         const onyxData = getOnyxDataArg();
         const transactionFailure = onyxData?.failureData.find((entry) => entry.key === `${ONYXKEYS.COLLECTION.TRANSACTION}${TRANSACTION_ID}`);

From a2a30dc8ce640a892348fa879db8f7a78adad432 Mon Sep 17 00:00:00 2001
From: Alex Beaman <alexbeaman@expensify.com>
Date: Wed, 10 Jun 2026 12:37:35 -0600
Subject: [PATCH 288/435] Fix prettier + spellcheck on UpdateMoneyRequest

---
 src/libs/actions/IOU/UpdateMoneyRequest.ts | 10 +++++++---
 1 file changed, 7 insertions(+), 3 deletions(-)

diff --git a/src/libs/actions/IOU/UpdateMoneyRequest.ts b/src/libs/actions/IOU/UpdateMoneyRequest.ts
index b200e4e4bdea..9f9fde9a7342 100644
--- a/src/libs/actions/IOU/UpdateMoneyRequest.ts
+++ b/src/libs/actions/IOU/UpdateMoneyRequest.ts
@@ -451,7 +451,7 @@ function updateMoneyRequestVendor({transactionID, vendorID, transaction, transac
 
     const newVendorOptimisticValue = isClearing ? null : {externalID: vendorID, isManuallySet: true};
 
-    // Build an optimistic MODIFIEDEXPENSE so the transaction thread shows "set vendor X" /
+    // Build an optimistic MODIFIED_EXPENSE so the transaction thread shows "set vendor X" /
     // "changed vendor from X to Y" / "removed the vendor" immediately. Auth's UpdateMoneyRequestVendor
     // command writes the same {externalID, isManuallySet} shape to the action's originalMessage; the
     // optimistic action mirrors that so the local render matches the eventual server payload.
@@ -468,7 +468,9 @@ function updateMoneyRequestVendor({transactionID, vendorID, transaction, transac
             : null;
     const optimisticReportActionID = optimisticModifiedExpense?.reportActionID ?? rand64();
 
-    const optimisticData: Array<OnyxUpdate<typeof ONYXKEYS.COLLECTION.TRANSACTION | typeof ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS | typeof ONYXKEYS.COLLECTION.REPORT_ACTIONS | typeof ONYXKEYS.COLLECTION.REPORT>> = [
+    const optimisticData: Array<
+        OnyxUpdate<typeof ONYXKEYS.COLLECTION.TRANSACTION | typeof ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS | typeof ONYXKEYS.COLLECTION.REPORT_ACTIONS | typeof ONYXKEYS.COLLECTION.REPORT>
+    > = [
         {
             onyxMethod: Onyx.METHOD.MERGE,
             key: `${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}` as const,
@@ -498,7 +500,9 @@ function updateMoneyRequestVendor({transactionID, vendorID, transaction, transac
     // Only roll back the vendor when we have a known prior snapshot. If the transaction isn't passed
     // in AND isn't cached in Onyx yet, we don't know what to restore — writing null here would silently
     // clear a vendor we don't know about. The next server sync will reconcile.
-    const failureData: Array<OnyxUpdate<typeof ONYXKEYS.COLLECTION.TRANSACTION | typeof ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS | typeof ONYXKEYS.COLLECTION.REPORT_ACTIONS | typeof ONYXKEYS.COLLECTION.REPORT>> = [
+    const failureData: Array<
+        OnyxUpdate<typeof ONYXKEYS.COLLECTION.TRANSACTION | typeof ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS | typeof ONYXKEYS.COLLECTION.REPORT_ACTIONS | typeof ONYXKEYS.COLLECTION.REPORT>
+    > = [
         {
             onyxMethod: Onyx.METHOD.MERGE,
             key: `${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}` as const,

From 84b7048c43ca2678d2cbdf72361ebcda87a02d97 Mon Sep 17 00:00:00 2001
From: Uzaifm127 <uzaifm127@gmail.com>
Date: Thu, 11 Jun 2026 00:12:26 +0530
Subject: [PATCH 289/435] fix: increased the title number of lines for category
 and tag selector in expense

---
 src/CONST/index.ts                                          | 2 ++
 src/components/CategoryPicker/index.tsx                     | 2 +-
 .../SelectionList/ListItem/MultiSelectListItem.tsx          | 2 ++
 .../SelectionList/ListItem/SingleSelectListItem.tsx         | 2 ++
 src/components/TagPicker/index.tsx                          | 6 +++---
 5 files changed, 10 insertions(+), 4 deletions(-)

diff --git a/src/CONST/index.ts b/src/CONST/index.ts
index c8483621b504..4ddb58279187 100644
--- a/src/CONST/index.ts
+++ b/src/CONST/index.ts
@@ -369,6 +369,8 @@ const CONST = {
 
     API_TRANSACTION_TAG_MAX_LENGTH: 255,
 
+    TRANSACTION_TAG_AND_CATEGORY_PICKER_MAX_TITLE_LINES: 15,
+
     AUTO_AUTH_STATE: {
         NOT_STARTED: 'not-started',
         SIGNING_IN: 'signing-in',
diff --git a/src/components/CategoryPicker/index.tsx b/src/components/CategoryPicker/index.tsx
index 909a4f7a8353..7253482ff633 100644
--- a/src/components/CategoryPicker/index.tsx
+++ b/src/components/CategoryPicker/index.tsx
@@ -92,7 +92,7 @@ function CategoryPicker({selectedCategory, policyID, onSubmit, addBottomSafeArea
             addBottomSafeAreaPadding={addBottomSafeAreaPadding}
             style={{listItemTitleStyles: styles.w100}}
             isRowMultilineSupported
-            titleNumberOfLines={3}
+            titleNumberOfLines={CONST.TRANSACTION_TAG_AND_CATEGORY_PICKER_MAX_TITLE_LINES}
         />
     );
 }
diff --git a/src/components/SelectionList/ListItem/MultiSelectListItem.tsx b/src/components/SelectionList/ListItem/MultiSelectListItem.tsx
index b6d358c58a9b..d8f93bfe6d90 100644
--- a/src/components/SelectionList/ListItem/MultiSelectListItem.tsx
+++ b/src/components/SelectionList/ListItem/MultiSelectListItem.tsx
@@ -28,6 +28,7 @@ function MultiSelectListItem<TItem extends ListItem>({
     wrapperStyle,
     titleStyles,
     shouldHighlightSelectedItem,
+    titleNumberOfLines,
 }: MultiSelectListItemProps<TItem>) {
     const styles = useThemeStyles();
     const icon = item.icons?.at(0);
@@ -59,6 +60,7 @@ function MultiSelectListItem<TItem extends ListItem>({
             wrapperStyle={computedWrapperStyle}
             titleStyles={titleStyles}
             shouldHighlightSelectedItem={shouldHighlightSelectedItem}
+            titleNumberOfLines={titleNumberOfLines}
         />
     );
 }
diff --git a/src/components/SelectionList/ListItem/SingleSelectListItem.tsx b/src/components/SelectionList/ListItem/SingleSelectListItem.tsx
index f47ab05457e3..36fbbe6a2fb3 100644
--- a/src/components/SelectionList/ListItem/SingleSelectListItem.tsx
+++ b/src/components/SelectionList/ListItem/SingleSelectListItem.tsx
@@ -27,6 +27,7 @@ function SingleSelectListItem<TItem extends ListItem>({
     isFocusVisible,
     rightHandSideComponent,
     selectionButtonPosition,
+    titleNumberOfLines,
 }: SingleSelectListItemProps<TItem>) {
     const styles = useThemeStyles();
 
@@ -51,6 +52,7 @@ function SingleSelectListItem<TItem extends ListItem>({
             shouldHighlightSelectedItem={shouldHighlightSelectedItem}
             isFocusVisible={isFocusVisible}
             selectionButtonPosition={selectionButtonPosition}
+            titleNumberOfLines={titleNumberOfLines}
         />
     );
 }
diff --git a/src/components/TagPicker/index.tsx b/src/components/TagPicker/index.tsx
index 8e139d3c8a01..434ae4466905 100644
--- a/src/components/TagPicker/index.tsx
+++ b/src/components/TagPicker/index.tsx
@@ -161,20 +161,20 @@ function TagPicker({
         ref: inputCallbackRef as (ref: BaseTextInputRef | null) => void,
     };
 
-    const listItemTitleStyles = [styles.breakAll, styles.w100];
-
     return (
         <SelectionListWithSections
             sections={sections}
             ListItem={SingleSelectListItem}
             style={{
                 sectionTitleStyles: styles.mt5,
-                listItemTitleStyles,
+                listItemTitleStyles: styles.w100,
             }}
             textInputOptions={textInputOptions}
             shouldShowTextInput={availableTagsCount >= CONST.STANDARD_LIST_ITEM_LIMIT}
             initiallyFocusedItemKey={selectedOptionKey}
             onSelectRow={onSubmit}
+            isRowMultilineSupported
+            titleNumberOfLines={CONST.TRANSACTION_TAG_AND_CATEGORY_PICKER_MAX_TITLE_LINES}
         />
     );
 }

From 2cc99c7293ad6b53d77088b7b94175fea68f8732 Mon Sep 17 00:00:00 2001
From: thelullabyy <182625428+thelullabyy@users.noreply.github.com>
Date: Wed, 10 Jun 2026 14:30:43 -0500
Subject: [PATCH 290/435] chore: bypass knip

---
 knip.json                                      | 3 ++-
 src/libs/actions/connections/FinancialForce.ts | 6 ++++++
 2 files changed, 8 insertions(+), 1 deletion(-)

diff --git a/knip.json b/knip.json
index 2df7e9791c2d..1b8aca27698a 100644
--- a/knip.json
+++ b/knip.json
@@ -43,7 +43,8 @@
             },
             "storybook": {
                 "config": [".storybook/main.ts"]
-            }
+            },
+            "tags": ["-public"]
         },
         "server/victory-chart-renderer": {
             "entry": ["src/bootstrap.tsx", "tests/**/*.test.ts"],
diff --git a/src/libs/actions/connections/FinancialForce.ts b/src/libs/actions/connections/FinancialForce.ts
index c281c15edbc2..ab2be1fae979 100644
--- a/src/libs/actions/connections/FinancialForce.ts
+++ b/src/libs/actions/connections/FinancialForce.ts
@@ -498,6 +498,7 @@ function updateFinancialForceSyncReimbursedReports(policyID: string, enabled: bo
     write(WRITE_COMMANDS.UPDATE_FINANCIAL_FORCE_SYNC_REIMBURSED_REPORTS, {policyID, enabled}, {optimisticData, failureData, successData});
 }
 
+/** @public */
 function updateFinancialForceParentTagMapping(
     policyID: string,
     parentTagMapping: ValueOf<typeof CONST.CERTINIA_PARENT_TAG_MAPPING>,
@@ -512,11 +513,13 @@ function updateFinancialForceParentTagMapping(
     write(WRITE_COMMANDS.UPDATE_FINANCIAL_FORCE_PARENT_TAG_MAPPING, {policyID, parentTagMapping}, {optimisticData, failureData, successData});
 }
 
+/** @public */
 function updateFinancialForceSyncMilestones(policyID: string, enabled: boolean, previousValue?: boolean) {
     const {optimisticData, failureData, successData} = prepareOnyxDataForFinancialForceCodingUpdate(policyID, CONST.CERTINIA_CONFIG.SYNC_MILESTONES, enabled, previousValue);
     write(WRITE_COMMANDS.UPDATE_FINANCIAL_FORCE_SYNC_MILESTONES, {policyID, enabled}, {optimisticData, failureData, successData});
 }
 
+/** @public */
 function updateFinancialForceReportExportStatus(policyID: string, status: ValueOf<typeof CONST.CERTINIA_EXPORT_STATUS>, previousStatus: ValueOf<typeof CONST.CERTINIA_EXPORT_STATUS> | null) {
     const {optimisticData, failureData, successData} = prepareOnyxDataForFinancialForceExportUpdate(
         policyID,
@@ -527,16 +530,19 @@ function updateFinancialForceReportExportStatus(policyID: string, status: ValueO
     write(WRITE_COMMANDS.UPDATE_FINANCIAL_FORCE_REPORT_EXPORT_STATUS, {policyID, reportExportStatus: status}, {optimisticData, failureData, successData});
 }
 
+/** @public */
 function updateFinancialForceTaxNonBillable(policyID: string, enabled: boolean, previousValue?: boolean) {
     const {optimisticData, failureData, successData} = prepareOnyxDataForFinancialForceAdvancedUpdate(policyID, CONST.CERTINIA_CONFIG.TAX_NON_BILLABLE, enabled, previousValue);
     write(WRITE_COMMANDS.UPDATE_FINANCIAL_FORCE_TAX_NON_BILLABLE, {policyID, enabled}, {optimisticData, failureData, successData});
 }
 
+/** @public */
 function updateFinancialForceExportForeignCurrency(policyID: string, enabled: boolean, previousValue?: boolean) {
     const {optimisticData, failureData, successData} = prepareOnyxDataForFinancialForceAdvancedUpdate(policyID, CONST.CERTINIA_CONFIG.EXPORT_FOREIGN_CURRENCY, enabled, previousValue);
     write(WRITE_COMMANDS.UPDATE_FINANCIAL_FORCE_EXPORT_FOREIGN_CURRENCY, {policyID, enabled}, {optimisticData, failureData, successData});
 }
 
+/** @public */
 function updateFinancialForceCompany(policyID: string, companyID: string, previousCompanyID: string | null) {
     const settingName = CONST.CERTINIA_CONFIG.COMPANY;
     const optimisticData: Array<OnyxUpdate<typeof ONYXKEYS.COLLECTION.POLICY>> = [

From 233a976086369deab7930134101e77153a125638 Mon Sep 17 00:00:00 2001
From: Alex Beaman <alexbeaman@expensify.com>
Date: Wed, 10 Jun 2026 13:35:06 -0600
Subject: [PATCH 291/435] Fix ESLint: route useOnyx through @hooks, extract
 TransactionCommentVendor type

---
 src/pages/iou/request/step/IOURequestStepVendor.tsx |  2 +-
 src/types/onyx/OriginalMessage.ts                   |  6 +++---
 src/types/onyx/Transaction.ts                       | 12 +++++++++++-
 3 files changed, 15 insertions(+), 5 deletions(-)

diff --git a/src/pages/iou/request/step/IOURequestStepVendor.tsx b/src/pages/iou/request/step/IOURequestStepVendor.tsx
index b6cb1e3a6250..8a8db9f95426 100644
--- a/src/pages/iou/request/step/IOURequestStepVendor.tsx
+++ b/src/pages/iou/request/step/IOURequestStepVendor.tsx
@@ -1,5 +1,4 @@
 import React, {useState} from 'react';
-import {useOnyx} from 'react-native-onyx';
 import BlockingView from '@components/BlockingViews/BlockingView';
 import SelectionList from '@components/SelectionList';
 import SingleSelectListItem from '@components/SelectionList/ListItem/SingleSelectListItem';
@@ -7,6 +6,7 @@ import type {ListItem} from '@components/SelectionList/types';
 import useDelegateAccountID from '@hooks/useDelegateAccountID';
 import {useMemoizedLazyIllustrations} from '@hooks/useLazyAsset';
 import useLocalize from '@hooks/useLocalize';
+import useOnyx from '@hooks/useOnyx';
 import usePermissions from '@hooks/usePermissions';
 import usePolicyForTransaction from '@hooks/usePolicyForTransaction';
 import useShowNotFoundPageInIOUStep from '@hooks/useShowNotFoundPageInIOUStep';
diff --git a/src/types/onyx/OriginalMessage.ts b/src/types/onyx/OriginalMessage.ts
index a6e664d36b57..8d695596a1db 100644
--- a/src/types/onyx/OriginalMessage.ts
+++ b/src/types/onyx/OriginalMessage.ts
@@ -7,7 +7,7 @@ import type {Attendee} from './IOU';
 import type {OldDotOriginalMessageMap} from './OldDotAction';
 import type {AllConnectionName} from './Policy';
 import type ReportActionName from './ReportActionName';
-import type {Reservation} from './Transaction';
+import type {Reservation, TransactionCommentVendor} from './Transaction';
 import type TransactionPending3DSReview from './TransactionPending3DSReview';
 
 /** Types of join workspace resolutions */
@@ -953,10 +953,10 @@ type OriginalMessageModifiedExpense = {
     oldReimbursable?: string;
 
     /** Edited accounting-system vendor on the transaction's comment NVP. `null` means the vendor was cleared. */
-    vendor?: {externalID: string; isManuallySet: boolean} | null;
+    vendor?: TransactionCommentVendor | null;
 
     /** Previous accounting-system vendor on the transaction's comment NVP. `null` means there was no prior vendor. */
-    oldVendor?: {externalID: string; isManuallySet: boolean} | null;
+    oldVendor?: TransactionCommentVendor | null;
 
     /** Collection of accountIDs of users mentioned in expense report */
     whisperedTo?: number[];
diff --git a/src/types/onyx/Transaction.ts b/src/types/onyx/Transaction.ts
index 623194a08639..37c7e3665d28 100644
--- a/src/types/onyx/Transaction.ts
+++ b/src/types/onyx/Transaction.ts
@@ -469,6 +469,15 @@ type SplitShare = {
 /** Record of participant split data, indexed by their `accountID` */
 type SplitShares = Record<number, SplitShare | null>;
 
+/** Accounting-system vendor stored on a transaction's comment NVP */
+type TransactionCommentVendor = {
+    /** External ID of the vendor in the connected accounting system */
+    externalID: string;
+
+    /** Whether the vendor was set manually by a user (vs. auto-matched by the fuzzy matcher) */
+    isManuallySet: boolean;
+};
+
 /** Model of transaction */
 type Transaction = OnyxCommon.OnyxValueWithOfflineFeedback<
     {
@@ -719,7 +728,7 @@ type AdditionalTransactionChanges = {
     quantity?: number;
 
     /** Accounting-system vendor on the transaction's comment NVP. `null` clears the vendor. */
-    vendor?: {externalID: string; isManuallySet: boolean} | null;
+    vendor?: TransactionCommentVendor | null;
 };
 
 /** Model of transaction changes  */
@@ -752,5 +761,6 @@ export type {
     TransactionCollectionDataSet,
     SplitShares,
     TransactionCustomUnit,
+    TransactionCommentVendor,
     UnreportedTransaction,
 };

From 1079dd08477bc69a277e582dc8978fbbca818f5a Mon Sep 17 00:00:00 2001
From: thelullabyy <182625428+thelullabyy@users.noreply.github.com>
Date: Wed, 10 Jun 2026 14:44:26 -0500
Subject: [PATCH 292/435] fix: remove knip tag

---
 knip.json | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/knip.json b/knip.json
index 1b8aca27698a..2df7e9791c2d 100644
--- a/knip.json
+++ b/knip.json
@@ -43,8 +43,7 @@
             },
             "storybook": {
                 "config": [".storybook/main.ts"]
-            },
-            "tags": ["-public"]
+            }
         },
         "server/victory-chart-renderer": {
             "entry": ["src/bootstrap.tsx", "tests/**/*.test.ts"],

From 10229746f5f5a961d619fe85f08f6bf19a439392 Mon Sep 17 00:00:00 2001
From: thelullabyy <182625428+thelullabyy@users.noreply.github.com>
Date: Wed, 10 Jun 2026 14:46:53 -0500
Subject: [PATCH 293/435] fix: reviewer comments

---
 src/libs/actions/connections/FinancialForce.ts | 13 ++++++-------
 1 file changed, 6 insertions(+), 7 deletions(-)

diff --git a/src/libs/actions/connections/FinancialForce.ts b/src/libs/actions/connections/FinancialForce.ts
index ab2be1fae979..0548beb40411 100644
--- a/src/libs/actions/connections/FinancialForce.ts
+++ b/src/libs/actions/connections/FinancialForce.ts
@@ -544,7 +544,6 @@ function updateFinancialForceExportForeignCurrency(policyID: string, enabled: bo
 
 /** @public */
 function updateFinancialForceCompany(policyID: string, companyID: string, previousCompanyID: string | null) {
-    const settingName = CONST.CERTINIA_CONFIG.COMPANY;
     const optimisticData: Array<OnyxUpdate<typeof ONYXKEYS.COLLECTION.POLICY>> = [
         {
             onyxMethod: Onyx.METHOD.MERGE,
@@ -557,10 +556,10 @@ function updateFinancialForceCompany(policyID: string, companyID: string, previo
                                 companyID,
                             },
                             pendingFields: {
-                                [settingName]: CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE,
+                                [companyID]: CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE,
                             },
                             errorFields: {
-                                [settingName]: null,
+                                [companyID]: null,
                             },
                         },
                     },
@@ -581,10 +580,10 @@ function updateFinancialForceCompany(policyID: string, companyID: string, previo
                                 companyID: previousCompanyID ?? null,
                             },
                             pendingFields: {
-                                [settingName]: null,
+                                [companyID]: null,
                             },
                             errorFields: {
-                                [settingName]: getMicroSecondOnyxErrorWithTranslationKey('common.genericErrorMessage'),
+                                [companyID]: getMicroSecondOnyxErrorWithTranslationKey('common.genericErrorMessage'),
                             },
                         },
                     },
@@ -602,10 +601,10 @@ function updateFinancialForceCompany(policyID: string, companyID: string, previo
                     [CONST.POLICY.CONNECTIONS.NAME.CERTINIA]: {
                         config: {
                             pendingFields: {
-                                [settingName]: null,
+                                [companyID]: null,
                             },
                             errorFields: {
-                                [settingName]: null,
+                                [companyID]: null,
                             },
                         },
                     },

From 5f616fa94d7c0d06c5d1f2f8c96f3277508cc3dc Mon Sep 17 00:00:00 2001
From: thelullabyy <182625428+thelullabyy@users.noreply.github.com>
Date: Wed, 10 Jun 2026 15:03:26 -0500
Subject: [PATCH 294/435] fix: resolve reviewer comments

---
 src/CONST/index.ts                            |  1 +
 .../actions/connections/FinancialForce.ts     | 40 ++++++++++++-------
 2 files changed, 27 insertions(+), 14 deletions(-)

diff --git a/src/CONST/index.ts b/src/CONST/index.ts
index c8483621b504..077835cb6150 100644
--- a/src/CONST/index.ts
+++ b/src/CONST/index.ts
@@ -2995,6 +2995,7 @@ const CONST = {
         TAX_NON_BILLABLE: 'taxNonBillable',
         EXPORT_FOREIGN_CURRENCY: 'exportForeignCurrency',
         COMPANY: 'company',
+        COMPANY_ID: 'companyID',
     },
 
     CERTINIA_EXPORT_STATUS: {
diff --git a/src/libs/actions/connections/FinancialForce.ts b/src/libs/actions/connections/FinancialForce.ts
index 0548beb40411..47d9c3eced19 100644
--- a/src/libs/actions/connections/FinancialForce.ts
+++ b/src/libs/actions/connections/FinancialForce.ts
@@ -498,7 +498,9 @@ function updateFinancialForceSyncReimbursedReports(policyID: string, enabled: bo
     write(WRITE_COMMANDS.UPDATE_FINANCIAL_FORCE_SYNC_REIMBURSED_REPORTS, {policyID, enabled}, {optimisticData, failureData, successData});
 }
 
-/** @public */
+/**
+ * @public
+ */
 function updateFinancialForceParentTagMapping(
     policyID: string,
     parentTagMapping: ValueOf<typeof CONST.CERTINIA_PARENT_TAG_MAPPING>,
@@ -513,13 +515,17 @@ function updateFinancialForceParentTagMapping(
     write(WRITE_COMMANDS.UPDATE_FINANCIAL_FORCE_PARENT_TAG_MAPPING, {policyID, parentTagMapping}, {optimisticData, failureData, successData});
 }
 
-/** @public */
+/**
+ * @public
+ */
 function updateFinancialForceSyncMilestones(policyID: string, enabled: boolean, previousValue?: boolean) {
     const {optimisticData, failureData, successData} = prepareOnyxDataForFinancialForceCodingUpdate(policyID, CONST.CERTINIA_CONFIG.SYNC_MILESTONES, enabled, previousValue);
     write(WRITE_COMMANDS.UPDATE_FINANCIAL_FORCE_SYNC_MILESTONES, {policyID, enabled}, {optimisticData, failureData, successData});
 }
 
-/** @public */
+/**
+ * @public
+ */
 function updateFinancialForceReportExportStatus(policyID: string, status: ValueOf<typeof CONST.CERTINIA_EXPORT_STATUS>, previousStatus: ValueOf<typeof CONST.CERTINIA_EXPORT_STATUS> | null) {
     const {optimisticData, failureData, successData} = prepareOnyxDataForFinancialForceExportUpdate(
         policyID,
@@ -530,19 +536,25 @@ function updateFinancialForceReportExportStatus(policyID: string, status: ValueO
     write(WRITE_COMMANDS.UPDATE_FINANCIAL_FORCE_REPORT_EXPORT_STATUS, {policyID, reportExportStatus: status}, {optimisticData, failureData, successData});
 }
 
-/** @public */
+/**
+ * @public
+ */
 function updateFinancialForceTaxNonBillable(policyID: string, enabled: boolean, previousValue?: boolean) {
     const {optimisticData, failureData, successData} = prepareOnyxDataForFinancialForceAdvancedUpdate(policyID, CONST.CERTINIA_CONFIG.TAX_NON_BILLABLE, enabled, previousValue);
     write(WRITE_COMMANDS.UPDATE_FINANCIAL_FORCE_TAX_NON_BILLABLE, {policyID, enabled}, {optimisticData, failureData, successData});
 }
 
-/** @public */
+/**
+ * @public
+ */
 function updateFinancialForceExportForeignCurrency(policyID: string, enabled: boolean, previousValue?: boolean) {
     const {optimisticData, failureData, successData} = prepareOnyxDataForFinancialForceAdvancedUpdate(policyID, CONST.CERTINIA_CONFIG.EXPORT_FOREIGN_CURRENCY, enabled, previousValue);
     write(WRITE_COMMANDS.UPDATE_FINANCIAL_FORCE_EXPORT_FOREIGN_CURRENCY, {policyID, enabled}, {optimisticData, failureData, successData});
 }
 
-/** @public */
+/**
+ * @public
+ */
 function updateFinancialForceCompany(policyID: string, companyID: string, previousCompanyID: string | null) {
     const optimisticData: Array<OnyxUpdate<typeof ONYXKEYS.COLLECTION.POLICY>> = [
         {
@@ -553,13 +565,13 @@ function updateFinancialForceCompany(policyID: string, companyID: string, previo
                     [CONST.POLICY.CONNECTIONS.NAME.CERTINIA]: {
                         config: {
                             credentials: {
-                                companyID,
+                                [CONST.CERTINIA_CONFIG.COMPANY_ID]: companyID,
                             },
                             pendingFields: {
-                                [companyID]: CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE,
+                                [CONST.CERTINIA_CONFIG.COMPANY_ID]: CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE,
                             },
                             errorFields: {
-                                [companyID]: null,
+                                [CONST.CERTINIA_CONFIG.COMPANY_ID]: null,
                             },
                         },
                     },
@@ -577,13 +589,13 @@ function updateFinancialForceCompany(policyID: string, companyID: string, previo
                     [CONST.POLICY.CONNECTIONS.NAME.CERTINIA]: {
                         config: {
                             credentials: {
-                                companyID: previousCompanyID ?? null,
+                                [CONST.CERTINIA_CONFIG.COMPANY_ID]: previousCompanyID ?? null,
                             },
                             pendingFields: {
-                                [companyID]: null,
+                                [CONST.CERTINIA_CONFIG.COMPANY_ID]: null,
                             },
                             errorFields: {
-                                [companyID]: getMicroSecondOnyxErrorWithTranslationKey('common.genericErrorMessage'),
+                                [CONST.CERTINIA_CONFIG.COMPANY_ID]: getMicroSecondOnyxErrorWithTranslationKey('common.genericErrorMessage'),
                             },
                         },
                     },
@@ -601,10 +613,10 @@ function updateFinancialForceCompany(policyID: string, companyID: string, previo
                     [CONST.POLICY.CONNECTIONS.NAME.CERTINIA]: {
                         config: {
                             pendingFields: {
-                                [companyID]: null,
+                                [CONST.CERTINIA_CONFIG.COMPANY_ID]: null,
                             },
                             errorFields: {
-                                [companyID]: null,
+                                [CONST.CERTINIA_CONFIG.COMPANY_ID]: null,
                             },
                         },
                     },

From ad09f87665288d86f3d87fdab80400ba5a9d263e Mon Sep 17 00:00:00 2001
From: Alex Beaman <alexbeaman@expensify.com>
Date: Wed, 10 Jun 2026 14:07:02 -0600
Subject: [PATCH 295/435] Address bot review: dedupe Comment.vendor, optional
 reportActionID on STEP_VENDOR

---
 src/libs/Navigation/types.ts  | 2 +-
 src/types/onyx/Transaction.ts | 8 +-------
 2 files changed, 2 insertions(+), 8 deletions(-)

diff --git a/src/libs/Navigation/types.ts b/src/libs/Navigation/types.ts
index 0798e532bf3d..72ba0554f3c1 100644
--- a/src/libs/Navigation/types.ts
+++ b/src/libs/Navigation/types.ts
@@ -1946,7 +1946,7 @@ type MoneyRequestNavigatorParamList = {
         action: IOUAction;
         iouType: Exclude<IOUType, typeof CONST.IOU.TYPE.REQUEST | typeof CONST.IOU.TYPE.SEND>;
         transactionID: string;
-        reportActionID: string;
+        reportActionID?: string;
         reportID: string;
     };
     [SCREENS.MONEY_REQUEST.STEP_CATEGORY_CREATE]: {
diff --git a/src/types/onyx/Transaction.ts b/src/types/onyx/Transaction.ts
index 37c7e3665d28..066411806e22 100644
--- a/src/types/onyx/Transaction.ts
+++ b/src/types/onyx/Transaction.ts
@@ -129,13 +129,7 @@ type Comment = {
      * (`isManuallySet=true`). The flag prevents auto-match from overwriting a
      * deliberate selection.
      */
-    vendor?: {
-        /** Vendor ID in the connected accounting integration (e.g. QBO vendor ID) */
-        externalID: string;
-
-        /** `true` when set by the user or a merchant rule; `false` when set by the PHP fuzzy auto-matcher */
-        isManuallySet: boolean;
-    };
+    vendor?: TransactionCommentVendor;
 
     /** Timestamp when auto-categorization was initiated (format: "YYYY-MM-DD HH:MM:SS") */
     pendingAutoCategorizationTime?: string;

From 025c8e4cdf94169d54e61392ed4e7e2cba7ea574 Mon Sep 17 00:00:00 2001
From: thelullabyy <182625428+thelullabyy@users.noreply.github.com>
Date: Wed, 10 Jun 2026 15:15:57 -0500
Subject: [PATCH 296/435] fix: knip

---
 knip.json | 1 +
 1 file changed, 1 insertion(+)

diff --git a/knip.json b/knip.json
index 2df7e9791c2d..c51ef8b3367a 100644
--- a/knip.json
+++ b/knip.json
@@ -1,4 +1,5 @@
 {
+    "tags": ["-public"],
     "workspaces": {
         ".": {
             "entry": [

From fdd5bbb11c0d1d25afe42faca5f6eaf39063c07a Mon Sep 17 00:00:00 2001
From: thelullabyy <182625428+thelullabyy@users.noreply.github.com>
Date: Wed, 10 Jun 2026 15:20:23 -0500
Subject: [PATCH 297/435] fix: knip

---
 .../actions/connections/FinancialForce.ts     | 24 +++++--------------
 1 file changed, 6 insertions(+), 18 deletions(-)

diff --git a/src/libs/actions/connections/FinancialForce.ts b/src/libs/actions/connections/FinancialForce.ts
index 47d9c3eced19..db8262499d9b 100644
--- a/src/libs/actions/connections/FinancialForce.ts
+++ b/src/libs/actions/connections/FinancialForce.ts
@@ -498,9 +498,7 @@ function updateFinancialForceSyncReimbursedReports(policyID: string, enabled: bo
     write(WRITE_COMMANDS.UPDATE_FINANCIAL_FORCE_SYNC_REIMBURSED_REPORTS, {policyID, enabled}, {optimisticData, failureData, successData});
 }
 
-/**
- * @public
- */
+/** @public */
 function updateFinancialForceParentTagMapping(
     policyID: string,
     parentTagMapping: ValueOf<typeof CONST.CERTINIA_PARENT_TAG_MAPPING>,
@@ -515,17 +513,13 @@ function updateFinancialForceParentTagMapping(
     write(WRITE_COMMANDS.UPDATE_FINANCIAL_FORCE_PARENT_TAG_MAPPING, {policyID, parentTagMapping}, {optimisticData, failureData, successData});
 }
 
-/**
- * @public
- */
+/** @public */
 function updateFinancialForceSyncMilestones(policyID: string, enabled: boolean, previousValue?: boolean) {
     const {optimisticData, failureData, successData} = prepareOnyxDataForFinancialForceCodingUpdate(policyID, CONST.CERTINIA_CONFIG.SYNC_MILESTONES, enabled, previousValue);
     write(WRITE_COMMANDS.UPDATE_FINANCIAL_FORCE_SYNC_MILESTONES, {policyID, enabled}, {optimisticData, failureData, successData});
 }
 
-/**
- * @public
- */
+/** @public */
 function updateFinancialForceReportExportStatus(policyID: string, status: ValueOf<typeof CONST.CERTINIA_EXPORT_STATUS>, previousStatus: ValueOf<typeof CONST.CERTINIA_EXPORT_STATUS> | null) {
     const {optimisticData, failureData, successData} = prepareOnyxDataForFinancialForceExportUpdate(
         policyID,
@@ -536,25 +530,19 @@ function updateFinancialForceReportExportStatus(policyID: string, status: ValueO
     write(WRITE_COMMANDS.UPDATE_FINANCIAL_FORCE_REPORT_EXPORT_STATUS, {policyID, reportExportStatus: status}, {optimisticData, failureData, successData});
 }
 
-/**
- * @public
- */
+/** @public */
 function updateFinancialForceTaxNonBillable(policyID: string, enabled: boolean, previousValue?: boolean) {
     const {optimisticData, failureData, successData} = prepareOnyxDataForFinancialForceAdvancedUpdate(policyID, CONST.CERTINIA_CONFIG.TAX_NON_BILLABLE, enabled, previousValue);
     write(WRITE_COMMANDS.UPDATE_FINANCIAL_FORCE_TAX_NON_BILLABLE, {policyID, enabled}, {optimisticData, failureData, successData});
 }
 
-/**
- * @public
- */
+/** @public */
 function updateFinancialForceExportForeignCurrency(policyID: string, enabled: boolean, previousValue?: boolean) {
     const {optimisticData, failureData, successData} = prepareOnyxDataForFinancialForceAdvancedUpdate(policyID, CONST.CERTINIA_CONFIG.EXPORT_FOREIGN_CURRENCY, enabled, previousValue);
     write(WRITE_COMMANDS.UPDATE_FINANCIAL_FORCE_EXPORT_FOREIGN_CURRENCY, {policyID, enabled}, {optimisticData, failureData, successData});
 }
 
-/**
- * @public
- */
+/** @public */
 function updateFinancialForceCompany(policyID: string, companyID: string, previousCompanyID: string | null) {
     const optimisticData: Array<OnyxUpdate<typeof ONYXKEYS.COLLECTION.POLICY>> = [
         {

From affc0146c86ffcb8374040e30063d69df22619cb Mon Sep 17 00:00:00 2001
From: ShridharGoel <35566748+ShridharGoel@users.noreply.github.com>
Date: Thu, 11 Jun 2026 01:55:56 +0530
Subject: [PATCH 298/435] Update copy

---
 src/languages/en.ts | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/languages/en.ts b/src/languages/en.ts
index ad268c732902..9cd3d32e71cb 100644
--- a/src/languages/en.ts
+++ b/src/languages/en.ts
@@ -7068,7 +7068,7 @@ const translations = {
             },
             controlPolicyRoles: {
                 title: 'Control policy roles',
-                description: 'Use specialized roles like Auditor and Card Admin to give members focused workspace access.',
+                description: 'Use specialized roles like Auditor and Card Admin to grant members access only to what they need.',
                 onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
                     `<muted-text>Specialized workspace roles are only available on the Control plan, starting at <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `per member per month.` : `per active member per month.`}</muted-text>`,
             },

From b8dacaa95873c0a0649ba56cc30e0fa59cc134cc Mon Sep 17 00:00:00 2001
From: thelullabyy <182625428+thelullabyy@users.noreply.github.com>
Date: Wed, 10 Jun 2026 15:29:05 -0500
Subject: [PATCH 299/435] fix: knip

---
 knip.json                                      | 3 +--
 src/libs/actions/connections/FinancialForce.ts | 6 ------
 2 files changed, 1 insertion(+), 8 deletions(-)

diff --git a/knip.json b/knip.json
index c51ef8b3367a..1f6121995c89 100644
--- a/knip.json
+++ b/knip.json
@@ -1,5 +1,4 @@
 {
-    "tags": ["-public"],
     "workspaces": {
         ".": {
             "entry": [
@@ -29,7 +28,7 @@
                 ".storybook/**/*.{js,ts,tsx}",
                 ".github/actions/javascript/**/*.ts"
             ],
-            "ignore": [".github/actions/**/index.js", "tests/perf-test/**", "web/snippets/gib.js"],
+            "ignore": [".github/actions/**/index.js", "tests/perf-test/**", "web/snippets/gib.js", "src/libs/actions/connections/FinancialForce.ts"],
             "eslint": {
                 "config": ["config/eslint/eslint.config.mjs", "eslint.changed.config.mjs"]
             },
diff --git a/src/libs/actions/connections/FinancialForce.ts b/src/libs/actions/connections/FinancialForce.ts
index db8262499d9b..769a3f6de75f 100644
--- a/src/libs/actions/connections/FinancialForce.ts
+++ b/src/libs/actions/connections/FinancialForce.ts
@@ -498,7 +498,6 @@ function updateFinancialForceSyncReimbursedReports(policyID: string, enabled: bo
     write(WRITE_COMMANDS.UPDATE_FINANCIAL_FORCE_SYNC_REIMBURSED_REPORTS, {policyID, enabled}, {optimisticData, failureData, successData});
 }
 
-/** @public */
 function updateFinancialForceParentTagMapping(
     policyID: string,
     parentTagMapping: ValueOf<typeof CONST.CERTINIA_PARENT_TAG_MAPPING>,
@@ -513,13 +512,11 @@ function updateFinancialForceParentTagMapping(
     write(WRITE_COMMANDS.UPDATE_FINANCIAL_FORCE_PARENT_TAG_MAPPING, {policyID, parentTagMapping}, {optimisticData, failureData, successData});
 }
 
-/** @public */
 function updateFinancialForceSyncMilestones(policyID: string, enabled: boolean, previousValue?: boolean) {
     const {optimisticData, failureData, successData} = prepareOnyxDataForFinancialForceCodingUpdate(policyID, CONST.CERTINIA_CONFIG.SYNC_MILESTONES, enabled, previousValue);
     write(WRITE_COMMANDS.UPDATE_FINANCIAL_FORCE_SYNC_MILESTONES, {policyID, enabled}, {optimisticData, failureData, successData});
 }
 
-/** @public */
 function updateFinancialForceReportExportStatus(policyID: string, status: ValueOf<typeof CONST.CERTINIA_EXPORT_STATUS>, previousStatus: ValueOf<typeof CONST.CERTINIA_EXPORT_STATUS> | null) {
     const {optimisticData, failureData, successData} = prepareOnyxDataForFinancialForceExportUpdate(
         policyID,
@@ -530,19 +527,16 @@ function updateFinancialForceReportExportStatus(policyID: string, status: ValueO
     write(WRITE_COMMANDS.UPDATE_FINANCIAL_FORCE_REPORT_EXPORT_STATUS, {policyID, reportExportStatus: status}, {optimisticData, failureData, successData});
 }
 
-/** @public */
 function updateFinancialForceTaxNonBillable(policyID: string, enabled: boolean, previousValue?: boolean) {
     const {optimisticData, failureData, successData} = prepareOnyxDataForFinancialForceAdvancedUpdate(policyID, CONST.CERTINIA_CONFIG.TAX_NON_BILLABLE, enabled, previousValue);
     write(WRITE_COMMANDS.UPDATE_FINANCIAL_FORCE_TAX_NON_BILLABLE, {policyID, enabled}, {optimisticData, failureData, successData});
 }
 
-/** @public */
 function updateFinancialForceExportForeignCurrency(policyID: string, enabled: boolean, previousValue?: boolean) {
     const {optimisticData, failureData, successData} = prepareOnyxDataForFinancialForceAdvancedUpdate(policyID, CONST.CERTINIA_CONFIG.EXPORT_FOREIGN_CURRENCY, enabled, previousValue);
     write(WRITE_COMMANDS.UPDATE_FINANCIAL_FORCE_EXPORT_FOREIGN_CURRENCY, {policyID, enabled}, {optimisticData, failureData, successData});
 }
 
-/** @public */
 function updateFinancialForceCompany(policyID: string, companyID: string, previousCompanyID: string | null) {
     const optimisticData: Array<OnyxUpdate<typeof ONYXKEYS.COLLECTION.POLICY>> = [
         {

From bbaa420a523de6367a072a6e80520ccbfd104480 Mon Sep 17 00:00:00 2001
From: Rushat Gabhane <rushatgabhane@gmail.com>
Date: Wed, 10 Jun 2026 22:37:12 +0200
Subject: [PATCH 300/435] pass ref and focus on it

---
 src/components/DatePicker/index.tsx                    |  4 +++-
 .../BaseTextInput/implementation/index.native.tsx      |  2 ++
 .../TextInput/BaseTextInput/implementation/index.tsx   |  2 ++
 src/components/TextInput/BaseTextInput/types.ts        |  7 +++++--
 src/hooks/useAutoFocusInput.ts                         | 10 +++++-----
 src/libs/Accessibility/moveAccessibilityFocus/types.ts |  4 ++--
 6 files changed, 19 insertions(+), 10 deletions(-)

diff --git a/src/components/DatePicker/index.tsx b/src/components/DatePicker/index.tsx
index a54830c016f3..85a518499f81 100644
--- a/src/components/DatePicker/index.tsx
+++ b/src/components/DatePicker/index.tsx
@@ -51,12 +51,13 @@ function DatePicker({
     const [popoverPosition, setPopoverPosition] = useState({horizontal: 0, vertical: 0});
     const textInputRef = useRef<BaseTextInputRef | null>(null);
     const anchorRef = useRef<View>(null);
+    const touchableInputWrapperRef = useRef<View>(null);
     const [isInverted, setIsInverted] = useState(false);
     // Whether the user currently intends the picker to be open. Lets a deferred measurement skip opening if the
     // picker was dismissed before it resolved.
     const openIntentRef = useRef(false);
 
-    const {inputCallbackRef: autoFocusCallbackRef, cancelAutoFocus} = useAutoFocusInput(false, true);
+    const {inputCallbackRef: autoFocusCallbackRef, cancelAutoFocus} = useAutoFocusInput(false, touchableInputWrapperRef);
     const autoFocusCallbackRefRef = useRef(autoFocusCallbackRef);
     autoFocusCallbackRefRef.current = autoFocusCallbackRef;
 
@@ -177,6 +178,7 @@ function DatePicker({
             >
                 <TextInput
                     ref={combinedTextInputRef}
+                    touchableInputWrapperRef={touchableInputWrapperRef}
                     inputID={inputID}
                     forceActiveLabel
                     icon={selectedDate ? null : icons.Calendar}
diff --git a/src/components/TextInput/BaseTextInput/implementation/index.native.tsx b/src/components/TextInput/BaseTextInput/implementation/index.native.tsx
index 02cd0563bfb8..f3a6e3842ced 100644
--- a/src/components/TextInput/BaseTextInput/implementation/index.native.tsx
+++ b/src/components/TextInput/BaseTextInput/implementation/index.native.tsx
@@ -48,6 +48,7 @@ function BaseTextInput({
     textInputContainerStyles,
     shouldApplyPaddingToContainer = true,
     touchableInputWrapperStyle,
+    touchableInputWrapperRef,
     containerStyles,
     inputStyle,
     shouldUseFullInputHeight = false,
@@ -309,6 +310,7 @@ function BaseTextInput({
         <>
             <View style={[containerStyles]}>
                 <PressableWithoutFeedback
+                    ref={touchableInputWrapperRef}
                     role={CONST.ROLE.PRESENTATION}
                     onPress={onPress}
                     tabIndex={-1}
diff --git a/src/components/TextInput/BaseTextInput/implementation/index.tsx b/src/components/TextInput/BaseTextInput/implementation/index.tsx
index 1fa92aa59bd0..71fe87f895ae 100644
--- a/src/components/TextInput/BaseTextInput/implementation/index.tsx
+++ b/src/components/TextInput/BaseTextInput/implementation/index.tsx
@@ -50,6 +50,7 @@ function BaseTextInput({
     textInputContainerStyles,
     shouldApplyPaddingToContainer = true,
     touchableInputWrapperStyle,
+    touchableInputWrapperRef,
     containerStyles,
     inputStyle,
     forceActiveLabel = false,
@@ -344,6 +345,7 @@ function BaseTextInput({
                 {...(shouldInterceptSwipe && SwipeInterceptPanResponder.panHandlers)}
             >
                 <PressableWithoutFeedback
+                    ref={touchableInputWrapperRef}
                     role={CONST.ROLE.PRESENTATION}
                     onPress={onPress}
                     tabIndex={-1}
diff --git a/src/components/TextInput/BaseTextInput/types.ts b/src/components/TextInput/BaseTextInput/types.ts
index b5934d179773..083f5ce0b598 100644
--- a/src/components/TextInput/BaseTextInput/types.ts
+++ b/src/components/TextInput/BaseTextInput/types.ts
@@ -1,7 +1,7 @@
 import type {MarkdownRange, MarkdownStyle} from '@expensify/react-native-live-markdown';
 import type {NavigationProp, NavigationState} from '@react-navigation/native';
-import type {ForwardedRef} from 'react';
-import type {GestureResponderEvent, StyleProp, TextInputProps, TextStyle, ViewStyle} from 'react-native';
+import type {ForwardedRef, RefObject} from 'react';
+import type {GestureResponderEvent, StyleProp, TextInputProps, TextStyle, View, ViewStyle} from 'react-native';
 import type {MaskedTextInputOwnProps} from 'react-native-advanced-input-mask/lib/typescript/src/types';
 import type {AnimatedTextInputRef} from '@components/RNTextInput';
 import type {ForwardedFSClassProps} from '@libs/Fullstory/types';
@@ -47,6 +47,9 @@ type CustomBaseTextInputProps = ForwardedFSClassProps &
         /** Customizes the touchable wrapper of the TextInput component */
         touchableInputWrapperStyle?: StyleProp<ViewStyle>;
 
+        /** Reference to the touchable wrapper of the TextInput component */
+        touchableInputWrapperRef?: RefObject<View | null>;
+
         /** Customize the main container */
         containerStyles?: StyleProp<ViewStyle>;
 
diff --git a/src/hooks/useAutoFocusInput.ts b/src/hooks/useAutoFocusInput.ts
index 956de0bb7673..b3968ac12bb7 100644
--- a/src/hooks/useAutoFocusInput.ts
+++ b/src/hooks/useAutoFocusInput.ts
@@ -1,7 +1,7 @@
 import {useFocusEffect, useNavigation} from '@react-navigation/native';
 import {useCallback, useEffect, useRef, useState} from 'react';
 import type {RefObject} from 'react';
-import type {TextInput} from 'react-native';
+import type {TextInput, View} from 'react-native';
 // eslint-disable-next-line no-restricted-imports -- idiomatic defer primitive past navigation transitions.
 import {InteractionManager} from 'react-native';
 import Accessibility from '@libs/Accessibility';
@@ -25,7 +25,7 @@ type UseAutoFocusInput = {
     cancelAutoFocus: () => void;
 };
 
-export default function useAutoFocusInput(isMultiline = false, shouldMoveAccessibilityFocus = false): UseAutoFocusInput {
+export default function useAutoFocusInput(isMultiline = false, accessibilityFocusRef?: RefObject<View | TextInput | null>): UseAutoFocusInput {
     const [isInputInitialized, setIsInputInitialized] = useState(false);
     const [isScreenTransitionEnded, setIsScreenTransitionEnded] = useState(false);
     const [modal] = useOnyx(ONYXKEYS.MODAL);
@@ -56,7 +56,7 @@ export default function useAutoFocusInput(isMultiline = false, shouldMoveAccessi
 
     useEffect(() => {
         if (
-            (isScreenReaderEnabled && !shouldMoveAccessibilityFocus) ||
+            (isScreenReaderEnabled && !accessibilityFocusRef) ||
             !isScreenTransitionEnded ||
             !isInputInitialized ||
             !inputRef.current ||
@@ -68,7 +68,7 @@ export default function useAutoFocusInput(isMultiline = false, shouldMoveAccessi
         }
         const focusTaskHandle = InteractionManager.runAfterInteractions(() => {
             if (isScreenReaderEnabled) {
-                Accessibility.moveAccessibilityFocus(inputRef.current);
+                Accessibility.moveAccessibilityFocus(accessibilityFocusRef?.current);
                 setIsScreenTransitionEnded(false);
                 return;
             }
@@ -100,7 +100,7 @@ export default function useAutoFocusInput(isMultiline = false, shouldMoveAccessi
         return () => {
             focusTaskHandle.cancel();
         };
-    }, [isScreenReaderEnabled, shouldMoveAccessibilityFocus, isMultiline, isScreenTransitionEnded, isInputInitialized, splashScreenState, isPopoverVisible, isInLandscapeMode]);
+    }, [isScreenReaderEnabled, accessibilityFocusRef, isMultiline, isScreenTransitionEnded, isInputInitialized, splashScreenState, isPopoverVisible, isInLandscapeMode]);
 
     useFocusEffect(
         useCallback(() => {
diff --git a/src/libs/Accessibility/moveAccessibilityFocus/types.ts b/src/libs/Accessibility/moveAccessibilityFocus/types.ts
index d6ef3207306a..cacb0ef7600d 100644
--- a/src/libs/Accessibility/moveAccessibilityFocus/types.ts
+++ b/src/libs/Accessibility/moveAccessibilityFocus/types.ts
@@ -1,6 +1,6 @@
 import type {ElementRef, RefObject} from 'react';
-import type {HostComponent, TextInput} from 'react-native';
+import type {HostComponent, TextInput, View} from 'react-native';
 
-type MoveAccessibilityFocus = (ref?: (ElementRef<HostComponent<unknown>> & RefObject<HTMLOrSVGElement>) | TextInput | null) => void;
+type MoveAccessibilityFocus = (ref?: (ElementRef<HostComponent<unknown>> & RefObject<HTMLOrSVGElement>) | TextInput | View | null) => void;
 
 export default MoveAccessibilityFocus;

From c95f2c332d608ec077d2239b326775c905a1b226 Mon Sep 17 00:00:00 2001
From: jayeshmangwani <jayeshmangwani@gmail.com>
Date: Thu, 11 Jun 2026 02:09:17 +0530
Subject: [PATCH 301/435] revert unnecessary file

---
 .../inbox/report/PureReportActionItem.tsx     | 694 ------------------
 1 file changed, 694 deletions(-)
 delete mode 100644 src/pages/inbox/report/PureReportActionItem.tsx

diff --git a/src/pages/inbox/report/PureReportActionItem.tsx b/src/pages/inbox/report/PureReportActionItem.tsx
deleted file mode 100644
index ceb8e0e30764..000000000000
--- a/src/pages/inbox/report/PureReportActionItem.tsx
+++ /dev/null
@@ -1,694 +0,0 @@
-/* eslint-disable rulesdir/no-deep-equal-in-memo */
-import {useNavigation} from '@react-navigation/native';
-import {personalDetailsDisplayNameSelector} from '@selectors/PersonalDetails';
-import {deepEqual} from 'fast-equals';
-import mapValues from 'lodash/mapValues';
-import React, {memo, useContext, useEffect, useRef, useState} from 'react';
-import type {GestureResponderEvent, TextInput} from 'react-native';
-import {Keyboard, View} from 'react-native';
-import type {OnyxEntry} from 'react-native-onyx';
-import * as ActionSheetAwareScrollView from '@components/ActionSheetAwareScrollView';
-import Hoverable from '@components/Hoverable';
-import InlineSystemMessage from '@components/InlineSystemMessage';
-import {ModalActions} from '@components/Modal/Global/ModalContext';
-import OfflineWithFeedback from '@components/OfflineWithFeedback';
-import PressableWithSecondaryInteraction from '@components/PressableWithSecondaryInteraction';
-import ReportActionItemEmojiReactions from '@components/Reactions/ReportActionItemEmojiReactions';
-import RenderHTML from '@components/RenderHTML';
-import ChronosOOOListActions from '@components/ReportActionItem/ChronosOOOListActions';
-import {useIsOnSearch} from '@components/Search/SearchScopeProvider';
-import type {ShowContextMenuActionsContextType, ShowContextMenuStateContextType} from '@components/ShowContextMenuContext';
-import {ShowContextMenuActionsContext, ShowContextMenuStateContext} from '@components/ShowContextMenuContext';
-import UnreadActionIndicator from '@components/UnreadActionIndicator';
-import useConfirmModal from '@hooks/useConfirmModal';
-import useLocalize from '@hooks/useLocalize';
-import useOnyx from '@hooks/useOnyx';
-import useResponsiveLayout from '@hooks/useResponsiveLayout';
-import useStyleUtils from '@hooks/useStyleUtils';
-import useTheme from '@hooks/useTheme';
-import useThemeStyles from '@hooks/useThemeStyles';
-import {cleanUpMoneyRequest} from '@libs/actions/IOU/DeleteMoneyRequest';
-import {isSafari} from '@libs/Browser';
-import {isChronosOOOListAction} from '@libs/ChronosUtils';
-import ControlSelection from '@libs/ControlSelection';
-import {canUseTouchScreen, hasHoverSupport} from '@libs/DeviceCapabilities';
-import type {OnyxDataWithErrors} from '@libs/ErrorUtils';
-import {getLatestErrorMessageField, isReceiptError} from '@libs/ErrorUtils';
-import getNonEmptyStringOnyxID from '@libs/getNonEmptyStringOnyxID';
-import {isReportMessageAttachment} from '@libs/isReportMessageAttachment';
-import type {PlatformStackNavigationProp} from '@libs/Navigation/PlatformStackNavigation/types';
-import type {ReportsSplitNavigatorParamList} from '@libs/Navigation/types';
-import Permissions from '@libs/Permissions';
-import {
-    extractLinksFromMessageHtml,
-    getOriginalMessage,
-    getReportActionMessage,
-    getReportActionText,
-    getWhisperedTo,
-    isDeletedParentAction as isDeletedParentActionUtils,
-    isMessageDeleted,
-    isMoneyRequestAction,
-    isPendingRemove,
-    isTripPreview,
-    isWhisperActionTargetedToOthers,
-    useTableReportViewActionRenderConditionals,
-} from '@libs/ReportActionsUtils';
-import {canWriteInReport, getTransactionsWithReceipts, isCompletedTaskReport, isTaskReport, shouldDisplayThreadReplies as shouldDisplayThreadRepliesUtils} from '@libs/ReportUtils';
-import SelectionScraper from '@libs/SelectionScraper';
-import {ReactionListContext} from '@pages/inbox/ReportScreenContext';
-import AttachmentModalContext from '@pages/media/AttachmentModalScreen/AttachmentModalContext';
-import {clearAllRelatedReportActionErrors} from '@userActions/ClearReportActionErrors';
-import {hideEmojiPicker, isActive} from '@userActions/EmojiPickerAction';
-import {expandURLPreview} from '@userActions/Report';
-import {clearError} from '@userActions/Transaction';
-import CONST from '@src/CONST';
-import ONYXKEYS from '@src/ONYXKEYS';
-import type SCREENS from '@src/SCREENS';
-import type * as OnyxTypes from '@src/types/onyx';
-import type {Errors} from '@src/types/onyx/OnyxCommon';
-import {isEmptyObject, isEmptyValueObject} from '@src/types/utils/EmptyObject';
-import ActionContentRouter from './actionContents/ActionContentRouter';
-import {RestrictedReadOnlyContextMenuActions} from './ContextMenu/ContextMenuActions';
-import MiniReportActionContextMenu from './ContextMenu/MiniReportActionContextMenu';
-import type {ContextMenuAnchor} from './ContextMenu/ReportActionContextMenu';
-import {hideContextMenu, hideDeleteModal, isActiveReportAction, showContextMenu} from './ContextMenu/ReportActionContextMenu';
-import LinkPreviewer from './LinkPreviewer';
-import ReportActionItemContentCreated from './ReportActionItemContentCreated';
-import ReportActionItemFrame from './ReportActionItemFrame';
-import ReportActionItemThread from './ReportActionItemThread';
-import SearchActionHeader from './SearchActionHeader';
-import TripSummary from './TripSummary';
-import WhisperBanner from './WhisperBanner';
-
-type PureReportActionItemProps = {
-    /** Report for this action */
-    report: OnyxEntry<OnyxTypes.Report>;
-
-    /** The transaction thread report associated with the report for this action, if any */
-    transactionThreadReport: OnyxEntry<OnyxTypes.Report>;
-
-    /** Report action belonging to the report's parent */
-    parentReportAction: OnyxEntry<OnyxTypes.ReportAction>;
-
-    /** The transaction thread report's parentReportAction */
-    parentReportActionForTransactionThread?: OnyxEntry<OnyxTypes.ReportAction>;
-
-    /** All the data of the action item */
-    action: OnyxTypes.ReportAction;
-
-    /** Should the comment have the appearance of being grouped with the previous comment? */
-    displayAsGroup: boolean;
-
-    /** Should we display the new marker on top of the comment? */
-    shouldDisplayNewMarker: boolean;
-
-    /** Flag to show, hide the thread divider line */
-    shouldHideThreadDividerLine?: boolean;
-
-    /** Report action ID that was referenced in the deeplink to report  */
-    linkedReportActionID?: string;
-
-    /** Callback to be called on onPress */
-    onPress?: () => void;
-
-    /** If this is the first visible report action */
-    isFirstVisibleReportAction: boolean;
-
-    /**
-     * Is the action a thread's parent reportAction viewed from within the thread report?
-     * It will be false if we're viewing the same parent report action from the report it belongs to rather than the thread.
-     */
-    isThreadReportParentAction?: boolean;
-
-    /** IF the thread divider line will be used */
-    shouldUseThreadDividerLine?: boolean;
-
-    /** Whether context menu should be displayed */
-    shouldDisplayContextMenu?: boolean;
-
-    /** ReportAction draft message */
-    draftMessage?: string;
-
-    /** The IOU/Expense report we are paying */
-    iouReport?: OnyxTypes.Report;
-
-    /** Linked transaction route error */
-    linkedTransactionRouteError?: Errors;
-
-    /** ID of the original report from which the given reportAction is first created */
-    originalReportID?: string;
-
-    /** Original report from which the given reportAction is first created */
-    originalReport?: OnyxTypes.Report;
-
-    /** Whether the provided report is a closed expense report with no expenses */
-    isClosedExpenseReportWithNoExpenses?: boolean;
-
-    /** Whether to show border for MoneyRequestReportPreviewContent */
-    shouldShowBorder?: boolean;
-
-    /** Whether to highlight the action for a few seconds */
-    shouldHighlight?: boolean;
-
-    /** Whether the action is the "Created" action of a harvest-created expense report */
-    isHarvestCreatedExpenseReport?: boolean;
-
-    /** Whether the user is a track intent user */
-    isTrackIntentUser?: boolean;
-};
-
-function PureReportActionItem({
-    action,
-    report,
-    transactionThreadReport,
-    linkedReportActionID,
-    displayAsGroup,
-    parentReportAction,
-    shouldDisplayNewMarker,
-    shouldHideThreadDividerLine = false,
-    onPress = undefined,
-    isFirstVisibleReportAction = false,
-    isThreadReportParentAction = false,
-    shouldUseThreadDividerLine = false,
-    shouldDisplayContextMenu = true,
-    parentReportActionForTransactionThread,
-    draftMessage,
-    iouReport,
-    linkedTransactionRouteError,
-    originalReportID = '-1',
-    originalReport,
-    isClosedExpenseReportWithNoExpenses,
-    shouldShowBorder,
-    shouldHighlight = false,
-    isHarvestCreatedExpenseReport = false,
-    isTrackIntentUser,
-}: PureReportActionItemProps) {
-    const isConciergeGreeting = action.reportActionID === CONST.CONCIERGE_GREETING_ACTION_ID;
-    const shouldDisplayContextMenuValue = shouldDisplayContextMenu && !isConciergeGreeting;
-    const [actorDisplayName] = useOnyx(ONYXKEYS.PERSONAL_DETAILS_LIST, {selector: personalDetailsDisplayNameSelector(action.actorAccountID ?? CONST.DEFAULT_NUMBER_ID)});
-
-    const {transitionActionSheetState} = ActionSheetAwareScrollView.useActionSheetAwareScrollViewActions();
-    const {translate, datetimeToCalendarTime} = useLocalize();
-    const {showConfirmModal} = useConfirmModal();
-    const {shouldUseNarrowLayout} = useResponsiveLayout();
-    const reportID = report?.reportID ?? action?.reportID;
-    const theme = useTheme();
-    const styles = useThemeStyles();
-    const StyleUtils = useStyleUtils();
-    const [isContextMenuActive, setIsContextMenuActive] = useState(() => isActiveReportAction(action.reportActionID));
-    const [isEmojiPickerActive, setIsEmojiPickerActive] = useState<boolean | undefined>();
-    const [isPaymentMethodPopoverActive, setIsPaymentMethodPopoverActive] = useState<boolean | undefined>();
-    const [isHidden, setIsHidden] = useState(false);
-    const {isActiveReportAction: isActiveReactionListReportAction, hideReactionList} = useContext(ReactionListContext);
-    const {updateHiddenAttachments} = useContext(AttachmentModalContext);
-    const popoverAnchorRef = useRef<Exclude<ContextMenuAnchor, TextInput>>(null);
-    const downloadedPreviews = useRef<string[]>([]);
-    const isReportActionLinked = linkedReportActionID && action.reportActionID && linkedReportActionID === action.reportActionID;
-    const [isReportActionActive, setIsReportActionActive] = useState(!!isReportActionLinked);
-
-    const shouldRenderViewBasedOnAction = useTableReportViewActionRenderConditionals(action);
-
-    const [chatReport] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${getNonEmptyStringOnyxID(report?.chatReportID)}`);
-
-    const highlightedBackgroundColorIfNeeded = isReportActionLinked || shouldHighlight ? StyleUtils.getBackgroundColorStyle(theme.messageHighlightBG) : {};
-
-    const isDeletedParentAction = isDeletedParentActionUtils(action);
-    const hasDraft = draftMessage !== undefined;
-    const isEditingInline = !shouldUseNarrowLayout && hasDraft;
-
-    // IOUDetails only exists when we are sending money
-    const isSendingMoney = isMoneyRequestAction(action) && getOriginalMessage(action)?.type === CONST.IOU.REPORT_ACTION_TYPE.PAY && getOriginalMessage(action)?.IOUDetails;
-
-    const updateHiddenState = (isHiddenValue: boolean) => {
-        setIsHidden(isHiddenValue);
-        const message = Array.isArray(action.message) ? action.message?.at(-1) : action.message;
-        const isAttachment = (message?.html ?? '').search(CONST.REGEX.ATTACHMENT.ATTACHMENT_REGEX) !== -1 || isReportMessageAttachment(message);
-        if (!isAttachment) {
-            return;
-        }
-        updateHiddenAttachments(action.reportActionID, isHiddenValue);
-    };
-
-    const isOnSearch = useIsOnSearch();
-
-    const navigation = useNavigation<PlatformStackNavigationProp<ReportsSplitNavigatorParamList, typeof SCREENS.REPORT>>();
-    const dismissError = () => {
-        const transactionID = isMoneyRequestAction(action) ? getOriginalMessage(action)?.IOUTransactionID : undefined;
-        if (isSendingMoney && transactionID && reportID) {
-            cleanUpMoneyRequest(transactionID, action, reportID, transactionThreadReport, report, chatReport, undefined, originalReportID, true);
-            return;
-        }
-        if (action.pendingAction === CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD && isReportActionLinked) {
-            navigation.setParams({reportActionID: ''});
-        }
-        if (transactionID) {
-            clearError(transactionID);
-        }
-        clearAllRelatedReportActionErrors(reportID, action, originalReportID);
-    };
-
-    const showDismissReceiptErrorModal = async () => {
-        const result = await showConfirmModal({
-            title: translate('iou.dismissReceiptError'),
-            prompt: translate('iou.dismissReceiptErrorConfirmation'),
-            confirmText: translate('common.dismiss'),
-            cancelText: translate('common.cancel'),
-            shouldShowCancelButton: true,
-            danger: true,
-        });
-        if (result.action === ModalActions.CONFIRM) {
-            dismissError();
-        }
-    };
-
-    const onClose = () => {
-        const errors = linkedTransactionRouteError ?? getLatestErrorMessageField(action as OnyxDataWithErrors);
-        const errorEntries = Object.entries(errors ?? {});
-        const errorMessages = mapValues(Object.fromEntries(errorEntries), (error) => error);
-        const hasReceiptError = Object.values(errorMessages).some((error) => isReceiptError(error));
-
-        if (hasReceiptError) {
-            showDismissReceiptErrorModal();
-        } else {
-            dismissError();
-        }
-    };
-
-    useEffect(
-        () => () => {
-            // ReportActionContextMenu, EmojiPicker and PopoverReactionList are global components,
-            // we should also hide them when the current component is destroyed
-            if (isActiveReportAction(action.reportActionID)) {
-                hideContextMenu();
-                hideDeleteModal();
-            }
-            if (isActive(action.reportActionID)) {
-                hideEmojiPicker(true);
-            }
-            if (isActiveReactionListReportAction(action.reportActionID)) {
-                hideReactionList();
-            }
-        },
-        [action.reportActionID, isActiveReactionListReportAction, hideReactionList],
-    );
-
-    useEffect(() => {
-        // We need to hide EmojiPicker when this is a deleted parent action
-        if (!isDeletedParentAction || !isActive(action.reportActionID)) {
-            return;
-        }
-
-        hideEmojiPicker(true);
-    }, [isDeletedParentAction, action.reportActionID]);
-
-    useEffect(() => {
-        if (!Permissions.canUseLinkPreviews()) {
-            return;
-        }
-
-        const urls = extractLinksFromMessageHtml(action);
-        if (deepEqual(downloadedPreviews.current, urls) || action.pendingAction === CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE) {
-            return;
-        }
-
-        downloadedPreviews.current = urls;
-        expandURLPreview(reportID, action.reportActionID);
-    }, [action, reportID]);
-
-    // Hide the message if it is being moderated for a higher offense, or is hidden by a moderator
-    // Removed messages should not be shown anyway and should not need this flow
-    const latestDecision = getReportActionMessage(action)?.moderationDecision?.decision ?? '';
-    useEffect(() => {
-        if (action.actionName !== CONST.REPORT.ACTIONS.TYPE.ADD_COMMENT) {
-            return;
-        }
-
-        // Hide reveal message button and show the message if latestDecision is changed to empty
-        if (!latestDecision) {
-            setIsHidden(false);
-            return;
-        }
-
-        if (![CONST.MODERATION.MODERATOR_DECISION_APPROVED, CONST.MODERATION.MODERATOR_DECISION_PENDING].some((item) => item === latestDecision) && !isPendingRemove(action)) {
-            setIsHidden(true);
-            return;
-        }
-        setIsHidden(false);
-    }, [latestDecision, action]);
-
-    const toggleContextMenuFromActiveReportAction = () => {
-        setIsContextMenuActive(isActiveReportAction(action.reportActionID));
-    };
-
-    const handleShowContextMenu = (callback: () => void) => {
-        if (!(popoverAnchorRef.current && 'measureInWindow' in popoverAnchorRef.current)) {
-            return;
-        }
-
-        popoverAnchorRef.current?.measureInWindow((_fx, frameY, _width, height) => {
-            transitionActionSheetState({
-                type: ActionSheetAwareScrollView.Actions.OPEN_POPOVER,
-                payload: {
-                    popoverHeight: 0,
-                    frameY,
-                    height,
-                },
-            });
-
-            callback();
-        });
-    };
-
-    const disabledActions = !canWriteInReport(report) ? RestrictedReadOnlyContextMenuActions : [];
-
-    const hasActionErrors = !isEmptyValueObject(action.errors);
-
-    // Receipt upload errors should still allow the context menu so the user can access "Delete expense"
-    const hasOnlyReceiptErrors = hasActionErrors && Object.values(action.errors ?? {}).every((error) => error === null || isReceiptError(error));
-
-    const isContextMenuDisabled = hasDraft || (hasActionErrors && !hasOnlyReceiptErrors) || !shouldDisplayContextMenuValue;
-
-    /**
-     * Show the ReportActionContextMenu modal popover.
-     *
-     * @param [event] - A press event.
-     */
-    const showPopover = (event: GestureResponderEvent | MouseEvent) => {
-        // Block menu on the message being Edited or if the report action item has errors
-        if (isContextMenuDisabled) {
-            return;
-        }
-
-        handleShowContextMenu(() => {
-            setIsContextMenuActive(true);
-            const selection = SelectionScraper.getCurrentSelection();
-            showContextMenu({
-                type: CONST.CONTEXT_MENU_TYPES.REPORT_ACTION,
-                event,
-                selection,
-                contextMenuAnchor: popoverAnchorRef.current,
-                report: {
-                    reportID,
-                    originalReportID,
-                },
-                reportAction: {
-                    reportActionID: action.reportActionID,
-                    isThreadReportParentAction,
-                },
-                callbacks: {
-                    onShow: toggleContextMenuFromActiveReportAction,
-                    onHide: toggleContextMenuFromActiveReportAction,
-                    setIsEmojiPickerActive: setIsEmojiPickerActive as () => void,
-                },
-                disabledOptions: disabledActions,
-            });
-        });
-    };
-
-    const contextMenuStateValue: ShowContextMenuStateContextType = {
-        anchor: popoverAnchorRef,
-        report,
-        action,
-        transactionThreadReport,
-        isDisabled: false,
-        shouldDisplayContextMenu: shouldDisplayContextMenuValue,
-        originalReportID,
-    };
-
-    const contextMenuActionsValue: ShowContextMenuActionsContextType = {
-        checkIfContextMenuActive: toggleContextMenuFromActiveReportAction,
-        onShowContextMenu: handleShowContextMenu,
-    };
-
-    const createdTransactionID = isMoneyRequestAction(parentReportActionForTransactionThread) ? getOriginalMessage(parentReportActionForTransactionThread)?.IOUTransactionID : undefined;
-
-    if (action.actionName === CONST.REPORT.ACTIONS.TYPE.CREATED && !isHarvestCreatedExpenseReport) {
-        return (
-            <ShowContextMenuStateContext.Provider value={contextMenuStateValue}>
-                <ShowContextMenuActionsContext.Provider value={contextMenuActionsValue}>
-                    <ReportActionItemContentCreated
-                        parentReportAction={parentReportAction}
-                        transactionID={createdTransactionID}
-                        draftMessage={draftMessage}
-                        shouldHideThreadDividerLine={shouldHideThreadDividerLine}
-                    />
-                </ShowContextMenuActionsContext.Provider>
-            </ShowContextMenuStateContext.Provider>
-        );
-    }
-
-    // Should show the created action content if:
-    // - Harvest report is shown in ReportActionsList (one-transaction view)
-    const shouldShowCreatedAction = action.actionName === CONST.REPORT.ACTIONS.TYPE.CREATED && !!isHarvestCreatedExpenseReport && !!parentReportActionForTransactionThread;
-
-    if (isTripPreview(action) && isThreadReportParentAction) {
-        return <TripSummary reportID={getOriginalMessage(action)?.linkedReportID} />;
-    }
-
-    if (isChronosOOOListAction(action)) {
-        return (
-            <ChronosOOOListActions
-                action={action}
-                reportID={reportID}
-            />
-        );
-    }
-
-    // For the `pay` IOU action on non-pay expense flow, we don't want to render anything if `isWaitingOnBankAccount` is true
-    // Otherwise, we will see two system messages informing the payee needs to add a bank account or wallet
-    if (isMoneyRequestAction(action) && !!report?.isWaitingOnBankAccount && getOriginalMessage(action)?.type === CONST.IOU.REPORT_ACTION_TYPE.PAY && !isSendingMoney) {
-        return null;
-    }
-
-    // We currently send whispers to all report participants and hide them in the UI for users that shouldn't see them.
-    // This is a temporary solution needed for comment-linking.
-    // The long term solution will leverage end-to-end encryption and only targeted users will be able to decrypt.
-    if (isWhisperActionTargetedToOthers(action)) {
-        return null;
-    }
-
-    const whisperedTo = getWhisperedTo(action);
-
-    const iouReportID = isMoneyRequestAction(action) && getOriginalMessage(action)?.IOUReportID ? getOriginalMessage(action)?.IOUReportID?.toString() : undefined;
-    const isWhisper = whisperedTo.length > 0 && getTransactionsWithReceipts(iouReportID).length === 0;
-
-    const isEmpty = !shouldRenderViewBasedOnAction && !isClosedExpenseReportWithNoExpenses;
-    const shouldDisplayThreadReplies = shouldDisplayThreadRepliesUtils(action, isThreadReportParentAction) && !isOnSearch;
-
-    const formattedTimestamp = datetimeToCalendarTime(action.created, false);
-    const plainMessage = getReportActionText(action);
-    const accessibilityLabel = `${actorDisplayName ?? ''}, ${formattedTimestamp}, ${plainMessage}`;
-
-    return (
-        <ShowContextMenuStateContext.Provider value={contextMenuStateValue}>
-            <ShowContextMenuActionsContext.Provider value={contextMenuActionsValue}>
-                <View>
-                    {shouldShowCreatedAction && (
-                        <ReportActionItemContentCreated
-                            parentReportAction={parentReportAction}
-                            transactionID={createdTransactionID}
-                            draftMessage={draftMessage}
-                            shouldHideThreadDividerLine={shouldHideThreadDividerLine}
-                        />
-                    )}
-                    <PressableWithSecondaryInteraction
-                        ref={popoverAnchorRef}
-                        onPress={() => {
-                            if (!hasDraft) {
-                                onPress?.();
-                            }
-                            if (!Keyboard.isVisible()) {
-                                return;
-                            }
-                            Keyboard.dismiss();
-                        }}
-                        style={[action.pendingAction === CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE && !isDeletedParentAction ? styles.pointerEventsNone : styles.pointerEventsAuto]}
-                        onPressIn={() => shouldUseNarrowLayout && canUseTouchScreen() && ControlSelection.block()}
-                        onPressOut={() => ControlSelection.unblock()}
-                        onSecondaryInteraction={showPopover}
-                        preventDefaultContextMenu={!isContextMenuDisabled}
-                        withoutFocusOnSecondaryInteraction
-                        accessibilityLabel={accessibilityLabel}
-                        accessibilityHint={translate('accessibilityHints.chatMessage')}
-                        accessibilityRole={isSafari() && hasHoverSupport() ? undefined : CONST.ROLE.BUTTON}
-                        sentryLabel={CONST.SENTRY_LABEL.REPORT.PURE_REPORT_ACTION_ITEM}
-                    >
-                        <Hoverable
-                            shouldHandleScroll
-                            isDisabled={hasDraft}
-                            shouldFreezeCapture={isPaymentMethodPopoverActive}
-                            onHoverIn={() => {
-                                setIsReportActionActive(false);
-                            }}
-                            onHoverOut={() => {
-                                setIsReportActionActive(!!isReportActionLinked);
-                            }}
-                        >
-                            {(hovered) => {
-                                const isHoveredOrActive = !!hovered || !!isReportActionLinked || isContextMenuActive || !!isEmojiPickerActive;
-
-                                return (
-                                    <View style={highlightedBackgroundColorIfNeeded}>
-                                        {shouldDisplayNewMarker && (!shouldUseThreadDividerLine || !isFirstVisibleReportAction) && (
-                                            <UnreadActionIndicator reportActionID={action.reportActionID} />
-                                        )}
-                                        {shouldDisplayContextMenuValue && (hovered || !!isEmojiPickerActive || isContextMenuActive) && !hasDraft && !hasActionErrors && (
-                                            <MiniReportActionContextMenu
-                                                reportID={reportID}
-                                                reportActionID={action.reportActionID}
-                                                anchor={popoverAnchorRef}
-                                                originalReportID={originalReportID}
-                                                displayAsGroup={displayAsGroup}
-                                                disabledActions={disabledActions}
-                                                isVisible={hovered}
-                                                isThreadReportParentAction={isThreadReportParentAction}
-                                                checkIfContextMenuActive={toggleContextMenuFromActiveReportAction}
-                                                setIsEmojiPickerActive={setIsEmojiPickerActive}
-                                            />
-                                        )}
-                                        <View
-                                            style={StyleUtils.getReportActionItemStyle(
-                                                hovered || isWhisper || isContextMenuActive || !!isEmojiPickerActive || hasDraft || isPaymentMethodPopoverActive,
-                                                !hasDraft && !!onPress,
-                                            )}
-                                        >
-                                            <OfflineWithFeedback
-                                                onClose={onClose}
-                                                dismissError={dismissError}
-                                                pendingAction={
-                                                    hasDraft ? undefined : (action.pendingAction ?? (action.isOptimisticAction ? CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD : undefined))
-                                                }
-                                                shouldHideOnDelete={!isDeletedParentAction}
-                                                errors={(linkedTransactionRouteError ?? !isOnSearch) ? getLatestErrorMessageField(action as OnyxDataWithErrors) : {}}
-                                                errorRowStyles={[styles.ml10, styles.mr2]}
-                                                needsOffscreenAlphaCompositing={isMoneyRequestAction(action)}
-                                                shouldDisableStrikeThrough
-                                            >
-                                                <SearchActionHeader
-                                                    action={action}
-                                                    report={report}
-                                                    isWhisper={isWhisper}
-                                                    onPress={onPress}
-                                                >
-                                                    {isWhisper && <WhisperBanner whisperedTo={whisperedTo} />}
-                                                    {isEmpty ? (
-                                                        <RenderHTML html="" />
-                                                    ) : (
-                                                        <ReportActionItemFrame
-                                                            action={action}
-                                                            report={report}
-                                                            iouReport={iouReport}
-                                                            displayAsGroup={displayAsGroup}
-                                                            isEditingInline={isEditingInline}
-                                                            isWhisper={isWhisper}
-                                                            isOnSearch={isOnSearch}
-                                                            hovered={isHoveredOrActive}
-                                                            isActive={isReportActionActive && !isContextMenuActive}
-                                                        >
-                                                            <ActionContentRouter
-                                                                action={action}
-                                                                report={report}
-                                                                reportID={reportID}
-                                                                originalReport={originalReport}
-                                                                originalReportID={originalReportID}
-                                                                iouReport={iouReport}
-                                                                displayAsGroup={displayAsGroup}
-                                                                draftMessage={draftMessage}
-                                                                isWhisper={isWhisper}
-                                                                hovered={isHoveredOrActive}
-                                                                isHidden={isHidden}
-                                                                updateHiddenState={updateHiddenState}
-                                                                isClosedExpenseReportWithNoExpenses={isClosedExpenseReportWithNoExpenses}
-                                                                isHarvestCreatedExpenseReport={isHarvestCreatedExpenseReport}
-                                                                shouldShowBorder={shouldShowBorder}
-                                                                isOnSearch={isOnSearch}
-                                                                setIsPaymentMethodPopoverActive={setIsPaymentMethodPopoverActive}
-                                                                isTrackIntentUser={isTrackIntentUser ?? false}
-                                                            />
-                                                            {Permissions.canUseLinkPreviews() && !isHidden && (action.linkMetadata?.length ?? 0) > 0 && (
-                                                                <View style={hasDraft ? styles.chatItemReactionsDraftRight : {}}>
-                                                                    <LinkPreviewer linkMetadata={action.linkMetadata?.filter((item) => !isEmptyObject(item))} />
-                                                                </View>
-                                                            )}
-                                                            {!isOnSearch && !isMessageDeleted(action) && (
-                                                                <ReportActionItemEmojiReactions
-                                                                    reportAction={action}
-                                                                    reportID={reportID}
-                                                                    shouldBlockReactions={hasActionErrors}
-                                                                    setIsEmojiPickerActive={setIsEmojiPickerActive}
-                                                                    isEditingInline={isEditingInline}
-                                                                />
-                                                            )}
-                                                            {shouldDisplayThreadReplies && (
-                                                                <ReportActionItemThread
-                                                                    reportAction={action}
-                                                                    report={report}
-                                                                    isHovered={isHoveredOrActive}
-                                                                    onSecondaryInteraction={showPopover}
-                                                                    isActive={isReportActionActive && !isContextMenuActive}
-                                                                    isEditingInline={isEditingInline}
-                                                                />
-                                                            )}
-                                                        </ReportActionItemFrame>
-                                                    )}
-                                                </SearchActionHeader>
-                                            </OfflineWithFeedback>
-                                        </View>
-                                    </View>
-                                );
-                            }}
-                        </Hoverable>
-                        {!!action.error && (
-                            <View style={styles.reportActionSystemMessageContainer}>
-                                <InlineSystemMessage message={action.error} />
-                            </View>
-                        )}
-                    </PressableWithSecondaryInteraction>
-                </View>
-            </ShowContextMenuActionsContext.Provider>
-        </ShowContextMenuStateContext.Provider>
-    );
-}
-
-export type {PureReportActionItemProps};
-export default memo(PureReportActionItem, (prevProps, nextProps) => {
-    const prevParentReportAction = prevProps.parentReportAction;
-    const nextParentReportAction = nextProps.parentReportAction;
-    return (
-        prevProps.displayAsGroup === nextProps.displayAsGroup &&
-        prevProps.shouldDisplayNewMarker === nextProps.shouldDisplayNewMarker &&
-        deepEqual(prevProps.action, nextProps.action) &&
-        deepEqual(prevProps.report?.pendingFields, nextProps.report?.pendingFields) &&
-        deepEqual(prevProps.report?.participants, nextProps.report?.participants) &&
-        deepEqual(prevProps.report?.errorFields, nextProps.report?.errorFields) &&
-        prevProps.report?.isDeletedParentAction === nextProps.report?.isDeletedParentAction &&
-        prevProps.report?.statusNum === nextProps.report?.statusNum &&
-        prevProps.report?.stateNum === nextProps.report?.stateNum &&
-        prevProps.report?.parentReportID === nextProps.report?.parentReportID &&
-        prevProps.report?.parentReportActionID === nextProps.report?.parentReportActionID &&
-        // TaskReport's created actions render the TaskView, which updates depending on certain fields in the TaskReport
-        isTaskReport(prevProps.report) === isTaskReport(nextProps.report) &&
-        prevProps.action.actionName === nextProps.action.actionName &&
-        prevProps.report?.reportName === nextProps.report?.reportName &&
-        prevProps.report?.description === nextProps.report?.description &&
-        isCompletedTaskReport(prevProps.report) === isCompletedTaskReport(nextProps.report) &&
-        prevProps.report?.managerID === nextProps.report?.managerID &&
-        prevProps.shouldHideThreadDividerLine === nextProps.shouldHideThreadDividerLine &&
-        prevProps.report?.total === nextProps.report?.total &&
-        prevProps.report?.nonReimbursableTotal === nextProps.report?.nonReimbursableTotal &&
-        prevProps.report?.policyAvatar === nextProps.report?.policyAvatar &&
-        prevProps.linkedReportActionID === nextProps.linkedReportActionID &&
-        prevProps.shouldDisplayContextMenu === nextProps.shouldDisplayContextMenu &&
-        deepEqual(prevProps.report?.fieldList, nextProps.report?.fieldList) &&
-        deepEqual(prevProps.transactionThreadReport, nextProps.transactionThreadReport) &&
-        deepEqual(prevParentReportAction, nextParentReportAction) &&
-        prevProps.draftMessage === nextProps.draftMessage &&
-        prevProps.iouReport?.reportID === nextProps.iouReport?.reportID &&
-        deepEqual(prevProps.linkedTransactionRouteError, nextProps.linkedTransactionRouteError) &&
-        prevProps.originalReportID === nextProps.originalReportID &&
-        deepEqual(prevProps.originalReport?.participants, nextProps.originalReport?.participants) &&
-        prevProps.isClosedExpenseReportWithNoExpenses === nextProps.isClosedExpenseReportWithNoExpenses &&
-        prevProps.shouldHighlight === nextProps.shouldHighlight &&
-        prevProps.isHarvestCreatedExpenseReport === nextProps.isHarvestCreatedExpenseReport
-    );
-});

From d9fe905a1623202c1674e5f19ca049ba3c5707e7 Mon Sep 17 00:00:00 2001
From: Rushat Gabhane <rushatgabhane@gmail.com>
Date: Wed, 10 Jun 2026 22:45:20 +0200
Subject: [PATCH 302/435] rm autofocus

---
 src/components/DatePicker/index.tsx                 |  4 +---
 .../BaseTextInput/implementation/index.native.tsx   |  2 --
 .../BaseTextInput/implementation/index.tsx          |  2 --
 src/components/TextInput/BaseTextInput/types.ts     |  7 ++-----
 src/hooks/useAutoFocusInput.ts                      | 13 ++++---------
 .../Accessibility/moveAccessibilityFocus/index.ts   |  2 +-
 .../Accessibility/moveAccessibilityFocus/types.ts   |  4 ++--
 7 files changed, 10 insertions(+), 24 deletions(-)

diff --git a/src/components/DatePicker/index.tsx b/src/components/DatePicker/index.tsx
index 85a518499f81..01f0d72a8b71 100644
--- a/src/components/DatePicker/index.tsx
+++ b/src/components/DatePicker/index.tsx
@@ -51,13 +51,12 @@ function DatePicker({
     const [popoverPosition, setPopoverPosition] = useState({horizontal: 0, vertical: 0});
     const textInputRef = useRef<BaseTextInputRef | null>(null);
     const anchorRef = useRef<View>(null);
-    const touchableInputWrapperRef = useRef<View>(null);
     const [isInverted, setIsInverted] = useState(false);
     // Whether the user currently intends the picker to be open. Lets a deferred measurement skip opening if the
     // picker was dismissed before it resolved.
     const openIntentRef = useRef(false);
 
-    const {inputCallbackRef: autoFocusCallbackRef, cancelAutoFocus} = useAutoFocusInput(false, touchableInputWrapperRef);
+    const {inputCallbackRef: autoFocusCallbackRef, cancelAutoFocus} = useAutoFocusInput();
     const autoFocusCallbackRefRef = useRef(autoFocusCallbackRef);
     autoFocusCallbackRefRef.current = autoFocusCallbackRef;
 
@@ -178,7 +177,6 @@ function DatePicker({
             >
                 <TextInput
                     ref={combinedTextInputRef}
-                    touchableInputWrapperRef={touchableInputWrapperRef}
                     inputID={inputID}
                     forceActiveLabel
                     icon={selectedDate ? null : icons.Calendar}
diff --git a/src/components/TextInput/BaseTextInput/implementation/index.native.tsx b/src/components/TextInput/BaseTextInput/implementation/index.native.tsx
index f3a6e3842ced..02cd0563bfb8 100644
--- a/src/components/TextInput/BaseTextInput/implementation/index.native.tsx
+++ b/src/components/TextInput/BaseTextInput/implementation/index.native.tsx
@@ -48,7 +48,6 @@ function BaseTextInput({
     textInputContainerStyles,
     shouldApplyPaddingToContainer = true,
     touchableInputWrapperStyle,
-    touchableInputWrapperRef,
     containerStyles,
     inputStyle,
     shouldUseFullInputHeight = false,
@@ -310,7 +309,6 @@ function BaseTextInput({
         <>
             <View style={[containerStyles]}>
                 <PressableWithoutFeedback
-                    ref={touchableInputWrapperRef}
                     role={CONST.ROLE.PRESENTATION}
                     onPress={onPress}
                     tabIndex={-1}
diff --git a/src/components/TextInput/BaseTextInput/implementation/index.tsx b/src/components/TextInput/BaseTextInput/implementation/index.tsx
index 71fe87f895ae..1fa92aa59bd0 100644
--- a/src/components/TextInput/BaseTextInput/implementation/index.tsx
+++ b/src/components/TextInput/BaseTextInput/implementation/index.tsx
@@ -50,7 +50,6 @@ function BaseTextInput({
     textInputContainerStyles,
     shouldApplyPaddingToContainer = true,
     touchableInputWrapperStyle,
-    touchableInputWrapperRef,
     containerStyles,
     inputStyle,
     forceActiveLabel = false,
@@ -345,7 +344,6 @@ function BaseTextInput({
                 {...(shouldInterceptSwipe && SwipeInterceptPanResponder.panHandlers)}
             >
                 <PressableWithoutFeedback
-                    ref={touchableInputWrapperRef}
                     role={CONST.ROLE.PRESENTATION}
                     onPress={onPress}
                     tabIndex={-1}
diff --git a/src/components/TextInput/BaseTextInput/types.ts b/src/components/TextInput/BaseTextInput/types.ts
index 083f5ce0b598..b5934d179773 100644
--- a/src/components/TextInput/BaseTextInput/types.ts
+++ b/src/components/TextInput/BaseTextInput/types.ts
@@ -1,7 +1,7 @@
 import type {MarkdownRange, MarkdownStyle} from '@expensify/react-native-live-markdown';
 import type {NavigationProp, NavigationState} from '@react-navigation/native';
-import type {ForwardedRef, RefObject} from 'react';
-import type {GestureResponderEvent, StyleProp, TextInputProps, TextStyle, View, ViewStyle} from 'react-native';
+import type {ForwardedRef} from 'react';
+import type {GestureResponderEvent, StyleProp, TextInputProps, TextStyle, ViewStyle} from 'react-native';
 import type {MaskedTextInputOwnProps} from 'react-native-advanced-input-mask/lib/typescript/src/types';
 import type {AnimatedTextInputRef} from '@components/RNTextInput';
 import type {ForwardedFSClassProps} from '@libs/Fullstory/types';
@@ -47,9 +47,6 @@ type CustomBaseTextInputProps = ForwardedFSClassProps &
         /** Customizes the touchable wrapper of the TextInput component */
         touchableInputWrapperStyle?: StyleProp<ViewStyle>;
 
-        /** Reference to the touchable wrapper of the TextInput component */
-        touchableInputWrapperRef?: RefObject<View | null>;
-
         /** Customize the main container */
         containerStyles?: StyleProp<ViewStyle>;
 
diff --git a/src/hooks/useAutoFocusInput.ts b/src/hooks/useAutoFocusInput.ts
index b3968ac12bb7..ea29b398cc03 100644
--- a/src/hooks/useAutoFocusInput.ts
+++ b/src/hooks/useAutoFocusInput.ts
@@ -1,7 +1,7 @@
 import {useFocusEffect, useNavigation} from '@react-navigation/native';
 import {useCallback, useEffect, useRef, useState} from 'react';
 import type {RefObject} from 'react';
-import type {TextInput, View} from 'react-native';
+import type {TextInput} from 'react-native';
 // eslint-disable-next-line no-restricted-imports -- idiomatic defer primitive past navigation transitions.
 import {InteractionManager} from 'react-native';
 import Accessibility from '@libs/Accessibility';
@@ -25,7 +25,7 @@ type UseAutoFocusInput = {
     cancelAutoFocus: () => void;
 };
 
-export default function useAutoFocusInput(isMultiline = false, accessibilityFocusRef?: RefObject<View | TextInput | null>): UseAutoFocusInput {
+export default function useAutoFocusInput(isMultiline = false): UseAutoFocusInput {
     const [isInputInitialized, setIsInputInitialized] = useState(false);
     const [isScreenTransitionEnded, setIsScreenTransitionEnded] = useState(false);
     const [modal] = useOnyx(ONYXKEYS.MODAL);
@@ -56,7 +56,7 @@ export default function useAutoFocusInput(isMultiline = false, accessibilityFocu
 
     useEffect(() => {
         if (
-            (isScreenReaderEnabled && !accessibilityFocusRef) ||
+            isScreenReaderEnabled ||
             !isScreenTransitionEnded ||
             !isInputInitialized ||
             !inputRef.current ||
@@ -67,11 +67,6 @@ export default function useAutoFocusInput(isMultiline = false, accessibilityFocu
             return;
         }
         const focusTaskHandle = InteractionManager.runAfterInteractions(() => {
-            if (isScreenReaderEnabled) {
-                Accessibility.moveAccessibilityFocus(accessibilityFocusRef?.current);
-                setIsScreenTransitionEnded(false);
-                return;
-            }
             if (inputRef.current && isMultiline) {
                 moveSelectionToEnd(inputRef.current);
             }
@@ -100,7 +95,7 @@ export default function useAutoFocusInput(isMultiline = false, accessibilityFocu
         return () => {
             focusTaskHandle.cancel();
         };
-    }, [isScreenReaderEnabled, accessibilityFocusRef, isMultiline, isScreenTransitionEnded, isInputInitialized, splashScreenState, isPopoverVisible, isInLandscapeMode]);
+    }, [isScreenReaderEnabled, isMultiline, isScreenTransitionEnded, isInputInitialized, splashScreenState, isPopoverVisible, isInLandscapeMode]);
 
     useFocusEffect(
         useCallback(() => {
diff --git a/src/libs/Accessibility/moveAccessibilityFocus/index.ts b/src/libs/Accessibility/moveAccessibilityFocus/index.ts
index c73e52bda726..cafe1a216db3 100644
--- a/src/libs/Accessibility/moveAccessibilityFocus/index.ts
+++ b/src/libs/Accessibility/moveAccessibilityFocus/index.ts
@@ -1,7 +1,7 @@
 import type MoveAccessibilityFocus from './types';
 
 const moveAccessibilityFocus: MoveAccessibilityFocus = (ref) => {
-    if (!ref || !('current' in ref) || !ref.current) {
+    if (!ref?.current) {
         return;
     }
     ref.current.focus();
diff --git a/src/libs/Accessibility/moveAccessibilityFocus/types.ts b/src/libs/Accessibility/moveAccessibilityFocus/types.ts
index cacb0ef7600d..6756bdd6f773 100644
--- a/src/libs/Accessibility/moveAccessibilityFocus/types.ts
+++ b/src/libs/Accessibility/moveAccessibilityFocus/types.ts
@@ -1,6 +1,6 @@
 import type {ElementRef, RefObject} from 'react';
-import type {HostComponent, TextInput, View} from 'react-native';
+import type {HostComponent} from 'react-native';
 
-type MoveAccessibilityFocus = (ref?: (ElementRef<HostComponent<unknown>> & RefObject<HTMLOrSVGElement>) | TextInput | View | null) => void;
+type MoveAccessibilityFocus = (ref?: ElementRef<HostComponent<unknown>> & RefObject<HTMLOrSVGElement>) => void;
 
 export default MoveAccessibilityFocus;

From 3e8c0d3ea48232d5998670f2e4b2dcf1d2d5a827 Mon Sep 17 00:00:00 2001
From: Alex Beaman <alexbeaman@expensify.com>
Date: Wed, 10 Jun 2026 15:02:56 -0600
Subject: [PATCH 303/435] Fix vendor MODIFIED_EXPENSE rendering when Onyx
 strips null oldVendor/vendor

Onyx applies updates with shouldRemoveNestedNulls=true, so the optimistic
oldVendor: null (when adding a vendor with no prior) or vendor: null (when
clearing a vendor) was getting stripped on merge. The hasModifiedVendor
guard required BOTH keys to be present, so add/remove cases fell through
to the generic 'changed the expense' fallback instead of rendering
'set the vendor to X' / 'removed the vendor (previously X)'.

Loosen the guard to accept either key, and add tests covering add,
change, remove, and the QBO-deleted-vendor fallback, plus four
optimistic-action shape tests in UpdateMoneyRequestVendorTest.ts.
---
 src/libs/ModifiedExpenseMessage.ts            |  12 +-
 .../IOUTest/UpdateMoneyRequestVendorTest.ts   | 101 +++++++++++++++-
 tests/unit/ModifiedExpenseMessageTest.ts      | 113 ++++++++++++++++++
 3 files changed, 222 insertions(+), 4 deletions(-)

diff --git a/src/libs/ModifiedExpenseMessage.ts b/src/libs/ModifiedExpenseMessage.ts
index df71f55fe1d6..ee7ac77b3720 100644
--- a/src/libs/ModifiedExpenseMessage.ts
+++ b/src/libs/ModifiedExpenseMessage.ts
@@ -448,10 +448,16 @@ function getForReportAction({
         buildMessageFragmentForValue(translate, newReimbursable, oldReimbursable, translate('iou.expense'), true, setFragments, removalFragments, changeFragments);
     }
 
-    const hasModifiedVendor = isReportActionOriginalMessageAnObject && 'oldVendor' in reportActionOriginalMessage && 'vendor' in reportActionOriginalMessage;
+    // Onyx applies updates with `shouldRemoveNestedNulls: true`, so when we build an optimistic
+    // MODIFIED_EXPENSE for a vendor "set" (no prior, `oldVendor: null`) or "remove" (no new,
+    // `vendor: null`), the null-valued key is stripped on merge and only one of the two keys
+    // survives in storage. Treat either key's presence as a vendor modification — requiring both
+    // would let "add" and "remove" cases fall through to the generic "changed the expense"
+    // fallback.
+    const hasModifiedVendor = isReportActionOriginalMessageAnObject && ('oldVendor' in reportActionOriginalMessage || 'vendor' in reportActionOriginalMessage);
     if (hasModifiedVendor) {
-        // Vendor is stored on the action as `{externalID, isManuallySet}` (or null). Resolve the
-        // display name from the policy's QBO vendor list; if the vendor has since been removed
+        // Vendor is stored on the action as `{externalID, isManuallySet}` (or absent/null). Resolve
+        // the display name from the policy's QBO vendor list; if the vendor has since been removed
         // from QBO the name is unrecoverable, so fall back to the externalID so the fragment still
         // identifies which vendor was set rather than rendering `set vendor ""`.
         const resolveVendorName = (entry: typeof reportActionOriginalMessage.vendor): string => {
diff --git a/tests/actions/IOUTest/UpdateMoneyRequestVendorTest.ts b/tests/actions/IOUTest/UpdateMoneyRequestVendorTest.ts
index 3c14807962c1..451ac4e316ca 100644
--- a/tests/actions/IOUTest/UpdateMoneyRequestVendorTest.ts
+++ b/tests/actions/IOUTest/UpdateMoneyRequestVendorTest.ts
@@ -3,7 +3,7 @@ import {updateMoneyRequestVendor} from '@libs/actions/IOU/UpdateMoneyRequest';
 import * as API from '@libs/API';
 import CONST from '@src/CONST';
 import ONYXKEYS from '@src/ONYXKEYS';
-import type {Transaction, TransactionViolation} from '@src/types/onyx';
+import type {Report, Transaction, TransactionViolation} from '@src/types/onyx';
 import waitForBatchedUpdates from '../../utils/waitForBatchedUpdates';
 
 const TRANSACTION_ID = 'txn-vendor-test';
@@ -160,4 +160,103 @@ describe('updateMoneyRequestVendor', () => {
         const transactionFailure = onyxData?.failureData.find((entry) => entry.key === `${ONYXKEYS.COLLECTION.TRANSACTION}${TRANSACTION_ID}`);
         expect(transactionFailure?.value).toMatchObject({pendingFields: {vendor: null}});
     });
+
+    describe('optimistic MODIFIED_EXPENSE report action', () => {
+        // The optimistic action only goes onto the transaction thread when the caller passes the
+        // thread report — `IOURequestStepVendor` does this when the user picks a vendor row. The
+        // action drives the "set the vendor to X" / "changed the vendor from X to Y" / "removed the
+        // vendor" system messages that show up in the thread before the server roundtrips. Without
+        // it the user sees the generic "changed the expense" fallback.
+        const TRANSACTION_THREAD_REPORT_ID = 'txn-thread-vendor-test';
+        const transactionThreadReport: Report = {
+            reportID: TRANSACTION_THREAD_REPORT_ID,
+            reportName: 'Transaction thread',
+        } as Report;
+
+        type ReportActionMap = Record<string, {actionName?: string; originalMessage?: {vendor?: unknown; oldVendor?: unknown}}>;
+
+        const findOptimisticModifiedExpense = (): {actionName?: string; originalMessage?: {vendor?: unknown; oldVendor?: unknown}} | undefined => {
+            const onyxData = getOnyxDataArg();
+            const reportActionsKey = `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${TRANSACTION_THREAD_REPORT_ID}`;
+            const update = onyxData?.optimisticData.find((entry) => entry.key === reportActionsKey);
+            const value = update?.value as ReportActionMap | undefined;
+            return value ? Object.values(value).find((action) => action?.actionName === CONST.REPORT.ACTIONS.TYPE.MODIFIED_EXPENSE) : undefined;
+        };
+
+        it('builds an optimistic MODIFIED_EXPENSE with `vendor` set and `oldVendor` null when adding a vendor (no prior)', () => {
+            updateMoneyRequestVendor({
+                transactionID: TRANSACTION_ID,
+                vendorID: 'v-new',
+                transaction: baseTransaction,
+                transactionThreadReport,
+                delegateAccountID: undefined,
+            });
+
+            const optimisticAction = findOptimisticModifiedExpense();
+            expect(optimisticAction).toBeDefined();
+            // `oldVendor: null` signals "no prior vendor". Onyx strips nested nulls on merge, which
+            // is fine — `ModifiedExpenseMessage` treats either key's presence as a vendor change.
+            expect(optimisticAction?.originalMessage).toMatchObject({
+                vendor: {externalID: 'v-new', isManuallySet: true},
+                oldVendor: null,
+            });
+        });
+
+        it('builds an optimistic MODIFIED_EXPENSE with both `vendor` and `oldVendor` set when changing the vendor', () => {
+            const previousVendor = {externalID: 'v-old', isManuallySet: false};
+            const transactionWithVendor: Transaction = {
+                ...baseTransaction,
+                comment: {vendor: previousVendor},
+            };
+
+            updateMoneyRequestVendor({
+                transactionID: TRANSACTION_ID,
+                vendorID: 'v-new',
+                transaction: transactionWithVendor,
+                transactionThreadReport,
+                delegateAccountID: undefined,
+            });
+
+            const optimisticAction = findOptimisticModifiedExpense();
+            expect(optimisticAction?.originalMessage).toMatchObject({
+                oldVendor: previousVendor,
+                vendor: {externalID: 'v-new', isManuallySet: true},
+            });
+        });
+
+        it('builds an optimistic MODIFIED_EXPENSE with `vendor` null and `oldVendor` set when clearing the vendor', () => {
+            const previousVendor = {externalID: 'v-old', isManuallySet: true};
+            const transactionWithVendor: Transaction = {
+                ...baseTransaction,
+                comment: {vendor: previousVendor},
+            };
+
+            updateMoneyRequestVendor({
+                transactionID: TRANSACTION_ID,
+                vendorID: '',
+                transaction: transactionWithVendor,
+                transactionThreadReport,
+                delegateAccountID: undefined,
+            });
+
+            const optimisticAction = findOptimisticModifiedExpense();
+            expect(optimisticAction?.originalMessage).toMatchObject({
+                oldVendor: previousVendor,
+                vendor: null,
+            });
+        });
+
+        it('does NOT build an optimistic MODIFIED_EXPENSE when no transactionThreadReport is passed (defensive — no thread to write to)', () => {
+            updateMoneyRequestVendor({
+                transactionID: TRANSACTION_ID,
+                vendorID: 'v-new',
+                transaction: baseTransaction,
+                delegateAccountID: undefined,
+            });
+
+            const onyxData = getOnyxDataArg();
+            const reportActionsUpdate = onyxData?.optimisticData.find((entry) => entry.key.startsWith(ONYXKEYS.COLLECTION.REPORT_ACTIONS));
+            expect(reportActionsUpdate).toBeUndefined();
+        });
+    });
 });
diff --git a/tests/unit/ModifiedExpenseMessageTest.ts b/tests/unit/ModifiedExpenseMessageTest.ts
index 4459f3cee9f9..0fae1f042ab1 100644
--- a/tests/unit/ModifiedExpenseMessageTest.ts
+++ b/tests/unit/ModifiedExpenseMessageTest.ts
@@ -2156,5 +2156,118 @@ describe('ModifiedExpenseMessage', () => {
                 expect(result).toEqual(expectedResult);
             });
         });
+
+        describe('vendor changes', () => {
+            // QBO policy with two named vendors used by the resolver. The third case below
+            // omits a vendor from the list to exercise the externalID fallback path.
+            const policyWithVendors: Policy = {
+                id: 'p-1',
+                name: 'My Workspace',
+                role: CONST.POLICY.ROLE.ADMIN,
+                type: CONST.POLICY.TYPE.TEAM,
+                owner: 'test@example.com',
+                outputCurrency: CONST.CURRENCY.USD,
+                isPolicyExpenseChatEnabled: true,
+                connections: {
+                    quickbooksOnline: {
+                        data: {
+                            vendors: [
+                                {id: 'v-acme', name: 'Acme', currency: 'USD', email: ''},
+                                {id: 'v-globex', name: 'Globex', currency: 'USD', email: ''},
+                            ],
+                        },
+                    },
+                },
+            } as Policy;
+
+            describe('when the vendor is set for the first time (oldVendor key stripped by Onyx null-merge)', () => {
+                // Onyx merges with `shouldRemoveNestedNulls: true`, so the optimistic
+                // `oldVendor: null` we write is stripped from storage. The rendered action
+                // must still treat the missing key as a "set" rather than falling back to
+                // the generic "changed the expense" message.
+                const reportAction = {
+                    ...createRandomReportAction(1),
+                    actionName: CONST.REPORT.ACTIONS.TYPE.MODIFIED_EXPENSE,
+                    originalMessage: {
+                        vendor: {externalID: 'v-acme', isManuallySet: true},
+                    },
+                };
+
+                it('renders "set the vendor to X"', () => {
+                    const result = getForReportAction({
+                        translate: translateLocal,
+                        reportAction,
+                        policy: policyWithVendors,
+                        policyTags: undefined,
+                        currentUserLogin: CURRENT_USER_LOGIN,
+                    });
+                    expect(result).toEqual('set the vendor to "Acme"');
+                });
+            });
+
+            describe('when the vendor is changed from one to another', () => {
+                const reportAction = {
+                    ...createRandomReportAction(1),
+                    actionName: CONST.REPORT.ACTIONS.TYPE.MODIFIED_EXPENSE,
+                    originalMessage: {
+                        oldVendor: {externalID: 'v-acme', isManuallySet: false},
+                        vendor: {externalID: 'v-globex', isManuallySet: true},
+                    },
+                };
+
+                it('renders "changed the vendor to Y (previously X)"', () => {
+                    const result = getForReportAction({
+                        translate: translateLocal,
+                        reportAction,
+                        policy: policyWithVendors,
+                        policyTags: undefined,
+                        currentUserLogin: CURRENT_USER_LOGIN,
+                    });
+                    expect(result).toEqual('changed the vendor to "Globex" (previously "Acme")');
+                });
+            });
+
+            describe('when the vendor is removed (vendor key stripped by Onyx null-merge)', () => {
+                const reportAction = {
+                    ...createRandomReportAction(1),
+                    actionName: CONST.REPORT.ACTIONS.TYPE.MODIFIED_EXPENSE,
+                    originalMessage: {
+                        oldVendor: {externalID: 'v-acme', isManuallySet: true},
+                    },
+                };
+
+                it('renders "removed the vendor X"', () => {
+                    const result = getForReportAction({
+                        translate: translateLocal,
+                        reportAction,
+                        policy: policyWithVendors,
+                        policyTags: undefined,
+                        currentUserLogin: CURRENT_USER_LOGIN,
+                    });
+                    expect(result).toEqual('removed the vendor (previously "Acme")');
+                });
+            });
+
+            describe('when the vendor is set to an ID no longer in the QBO vendor list (e.g. deleted from QBO)', () => {
+                const reportAction = {
+                    ...createRandomReportAction(1),
+                    actionName: CONST.REPORT.ACTIONS.TYPE.MODIFIED_EXPENSE,
+                    originalMessage: {
+                        vendor: {externalID: 'v-deleted', isManuallySet: false},
+                    },
+                };
+
+                it('falls back to rendering the externalID so the fragment still identifies which vendor was set', () => {
+                    const result = getForReportAction({
+                        translate: translateLocal,
+                        reportAction,
+                        policy: policyWithVendors,
+                        policyTags: undefined,
+                        currentUserLogin: CURRENT_USER_LOGIN,
+                    });
+                    expect(result).toEqual('set the vendor to "v-deleted"');
+                });
+            });
+        });
     });
 });

From be5bfddc0be27e95344be59122dd99661b1105a2 Mon Sep 17 00:00:00 2001
From: Issa Nimaga <inimaga@expensify.com>
Date: Wed, 10 Jun 2026 22:03:19 +0100
Subject: [PATCH 304/435] fix lint

---
 src/pages/inbox/usePusherDraftPacing.ts       | 28 +++++++++----------
 .../inbox/ConciergeDraftContext.test.tsx      | 13 ++-------
 2 files changed, 15 insertions(+), 26 deletions(-)

diff --git a/src/pages/inbox/usePusherDraftPacing.ts b/src/pages/inbox/usePusherDraftPacing.ts
index bba61f4557d5..5621097f99f5 100644
--- a/src/pages/inbox/usePusherDraftPacing.ts
+++ b/src/pages/inbox/usePusherDraftPacing.ts
@@ -854,24 +854,22 @@ function usePusherDraftPacing(reportID: string) {
             clearCachedPusherDraft(runtime);
         };
 
-        const draftEventSubscriptions: Array<[string, (eventData: unknown) => void]> = [
-            [
-                Pusher.TYPE.CONCIERGE_DRAFT_EVENTS,
-                (eventData) => {
-                    handlePusherDraftEvents(runtime, eventData as ConciergeDraftEventsEvent);
-                },
-            ],
-            ...PUSHER_DRAFT_EVENT_TYPES.map<[string, (eventData: unknown) => void]>((eventType) => [
+        const draftEventSubscriptions = [
+            {
+                eventType: Pusher.TYPE.CONCIERGE_DRAFT_EVENTS,
+                listener: Pusher.subscribe(channelName, Pusher.TYPE.CONCIERGE_DRAFT_EVENTS, (eventData: ConciergeDraftEventsEvent) => {
+                    handlePusherDraftEvents(runtime, eventData);
+                }, handleResubscribe),
+            },
+            ...PUSHER_DRAFT_EVENT_TYPES.map((eventType) => ({
                 eventType,
-                (eventData) => {
-                    handlePusherDraftEvent(runtime, eventData as ConciergeDraftEvent);
-                },
-            ]),
+                listener: Pusher.subscribe(channelName, eventType, (eventData: ConciergeDraftEvent) => {
+                    handlePusherDraftEvent(runtime, eventData);
+                }, handleResubscribe),
+            })),
         ];
 
-        const subscriptions = draftEventSubscriptions.map(([eventType, eventCallback]) => {
-            const listener = Pusher.subscribe(channelName, eventType, eventCallback, handleResubscribe);
-
+        const subscriptions = draftEventSubscriptions.map(({eventType, listener}) => {
             listener.catch((error: unknown) => {
                 Log.hmmm('Failed to subscribe to Pusher concierge draft events', {eventType, reportID, error});
             });
diff --git a/tests/unit/pages/inbox/ConciergeDraftContext.test.tsx b/tests/unit/pages/inbox/ConciergeDraftContext.test.tsx
index 76a7ba41ca1c..1a5a64a65eae 100644
--- a/tests/unit/pages/inbox/ConciergeDraftContext.test.tsx
+++ b/tests/unit/pages/inbox/ConciergeDraftContext.test.tsx
@@ -55,17 +55,8 @@ const SHORT_FINAL_RENDERED_HTML = '<comment>OK</comment>';
 const LONG_FINAL_RENDERED_TEXT = Array.from({length: 12}, (_, index) => `Streaming response ${index}`).join(' ');
 const LONG_FINAL_RENDERED_HTML = `<comment>${LONG_FINAL_RENDERED_TEXT}</comment>`;
 
-type MockPusherSubscribe = jest.MockedFunction<
-    (
-        channelName: string,
-        eventName?: string,
-        eventCallback?: (event: ConciergeDraftEvent | ConciergeDraftEventsEvent) => void,
-        onResubscribe?: () => void,
-    ) => ReturnType<typeof Pusher.subscribe>
->;
-
-function getMockPusherSubscribe(): MockPusherSubscribe {
-    return Pusher.subscribe as MockPusherSubscribe;
+function getMockPusherSubscribe() {
+    return jest.mocked(Pusher.subscribe);
 }
 
 function getFirstMessageText(reportAction: ReportAction | null): string | undefined {

From 524624cfcf775de795a6d28ba166587bc1bc6dda Mon Sep 17 00:00:00 2001
From: "Daniel Gale-Rosen (via MelvinBot)" <infra+melvinbot@expensify.com>
Date: Thu, 28 May 2026 15:48:34 +0000
Subject: [PATCH 305/435] Add removeDelegator API action and three-dot overflow
 menu for delegator rows

Allows users to remove themselves as a copilot from a delegator's account.
Adds RemoveDelegator write command, a confirmation modal, and replaces the
Switch button on delegator rows with a three-dot popover menu containing
Switch and Remove copilot access options.

Ref: Expensify/Expensify#638847
Co-authored-by: Daniel Gale-Rosen <dangrous@users.noreply.github.com>
---
 src/CONST/index.ts                            |   2 +
 src/languages/en.ts                           |   2 +
 src/languages/es.ts                           |   2 +
 .../API/parameters/RemoveDelegatorParams.ts   |   5 +
 src/libs/API/parameters/index.ts              |   1 +
 src/libs/API/types.ts                         |   2 +
 src/libs/actions/Delegate.ts                  |  75 ++++++++++++-
 src/pages/settings/Copilot/CopilotPage.tsx    | 100 ++++++++++++++----
 8 files changed, 170 insertions(+), 19 deletions(-)
 create mode 100644 src/libs/API/parameters/RemoveDelegatorParams.ts

diff --git a/src/CONST/index.ts b/src/CONST/index.ts
index c8483621b504..719cd880710c 100644
--- a/src/CONST/index.ts
+++ b/src/CONST/index.ts
@@ -8684,6 +8684,8 @@ const CONST = {
             DELEGATE_ITEM: 'SettingsSecurity-DelegateItem',
             DELEGATE_CHANGE_ACCESS: 'SettingsSecurity-DelegateChangeAccess',
             DELEGATE_REMOVE: 'SettingsSecurity-DelegateRemove',
+            DELEGATOR_ITEM: 'SettingsSecurity-DelegatorItem',
+            DELEGATOR_REMOVE: 'SettingsSecurity-DelegatorRemove',
         },
         SETTINGS_WALLET: {
             ADD_BANK_ACCOUNT: 'SettingsWallet-AddBankAccount',
diff --git a/src/languages/en.ts b/src/languages/en.ts
index 6e2b8b867939..eb0d31926d4d 100644
--- a/src/languages/en.ts
+++ b/src/languages/en.ts
@@ -9461,6 +9461,8 @@ const translations = {
         },
         removeCopilot: 'Remove copilot',
         removeCopilotConfirmation: 'Are you sure you want to remove this copilot?',
+        removeCopilotAccess: 'Remove copilot access',
+        removeCopilotAccessConfirmation: 'Are you sure you want to remove your copilot access to this account?',
         changeAccessLevel: 'Change access level',
         makeSureItIsYou: "Let's make sure it's you",
         enterMagicCode: (contactMethod: string) => `Please enter the magic code sent to ${contactMethod} to add a copilot. It should arrive within a minute or two.`,
diff --git a/src/languages/es.ts b/src/languages/es.ts
index 9913d2e15659..2577d67ac10f 100644
--- a/src/languages/es.ts
+++ b/src/languages/es.ts
@@ -9580,6 +9580,8 @@ ${amount} para ${merchant} - ${date}`,
         },
         removeCopilot: 'Eliminar copiloto',
         removeCopilotConfirmation: '¿Estás seguro de que quieres eliminar este copiloto?',
+        removeCopilotAccess: 'Eliminar acceso de copiloto',
+        removeCopilotAccessConfirmation: '¿Estás seguro de que quieres eliminar tu acceso de copiloto a esta cuenta?',
         changeAccessLevel: 'Cambiar nivel de acceso',
         makeSureItIsYou: 'Vamos a asegurarnos de que eres tú',
         enterMagicCode: (contactMethod) => `Por favor, introduce el código mágico enviado a ${contactMethod} para agregar un copiloto. Debería llegar en un par de minutos.`,
diff --git a/src/libs/API/parameters/RemoveDelegatorParams.ts b/src/libs/API/parameters/RemoveDelegatorParams.ts
new file mode 100644
index 000000000000..81e6f0441dd3
--- /dev/null
+++ b/src/libs/API/parameters/RemoveDelegatorParams.ts
@@ -0,0 +1,5 @@
+type RemoveDelegatorParams = {
+    delegatorEmail: string;
+};
+
+export default RemoveDelegatorParams;
diff --git a/src/libs/API/parameters/index.ts b/src/libs/API/parameters/index.ts
index ea8c05a42cde..c62dad8ad4da 100644
--- a/src/libs/API/parameters/index.ts
+++ b/src/libs/API/parameters/index.ts
@@ -411,6 +411,7 @@ export type {default as SetCardReconciliationBankAccountParams} from './SetCardR
 export type {default as CardDeactivateParams} from './CardDeactivateParams';
 export type {default as UpdateExpensifyCardLimitTypeParams} from './UpdateExpensifyCardLimitTypeParams';
 export type {default as RemoveDelegateParams} from './RemoveDelegateParams';
+export type {default as RemoveDelegatorParams} from './RemoveDelegatorParams';
 export type {default as SetPolicyTagApproverParams} from './SetPolicyTagApproverParams';
 export type {default as SaveSearchParams} from './SaveSearch';
 export type {default as DeleteSavedSearchParams} from './DeleteSavedSearch';
diff --git a/src/libs/API/types.ts b/src/libs/API/types.ts
index c9f41588e3f5..47206b7a16c5 100644
--- a/src/libs/API/types.ts
+++ b/src/libs/API/types.ts
@@ -519,6 +519,7 @@ const WRITE_COMMANDS = {
     QUEUE_EXPENSIFY_CARD_FOR_BILLING: 'Domain_QueueExpensifyCardForBilling',
     ADD_DELEGATE: 'AddDelegate',
     REMOVE_DELEGATE: 'RemoveDelegate',
+    REMOVE_DELEGATOR: 'RemoveDelegator',
     UPDATE_DELEGATE_ROLE: 'UpdateDelegateRole',
     TOGGLE_CARD_CONTINUOUS_RECONCILIATION: 'ToggleCardContinuousReconciliation',
     TOGGLE_CARD_CASHBACK_TO_BILL: 'ToggleCardCashbackToBill',
@@ -1199,6 +1200,7 @@ type WriteCommandParameters = {
     [WRITE_COMMANDS.ADD_DELEGATE]: Parameters.AddDelegateParams;
     [WRITE_COMMANDS.UPDATE_DELEGATE_ROLE]: Parameters.UpdateDelegateRoleParams;
     [WRITE_COMMANDS.REMOVE_DELEGATE]: Parameters.RemoveDelegateParams;
+    [WRITE_COMMANDS.REMOVE_DELEGATOR]: Parameters.RemoveDelegatorParams;
     [WRITE_COMMANDS.TOGGLE_CARD_CONTINUOUS_RECONCILIATION]: Parameters.ToggleCardContinuousReconciliationParams;
     [WRITE_COMMANDS.TOGGLE_CARD_CASHBACK_TO_BILL]: Parameters.ToggleCardCashbackToBillParams;
     [WRITE_COMMANDS.SET_CARD_RECONCILIATION_BANK_ACCOUNT]: Parameters.SetCardReconciliationBankAccountParams;
diff --git a/src/libs/actions/Delegate.ts b/src/libs/actions/Delegate.ts
index 0325a337fd17..d54715c72f3a 100644
--- a/src/libs/actions/Delegate.ts
+++ b/src/libs/actions/Delegate.ts
@@ -2,7 +2,7 @@ import HybridAppModule from '@expensify/react-native-hybrid-app';
 import Onyx from 'react-native-onyx';
 import type {OnyxEntry, OnyxKey, OnyxUpdate} from 'react-native-onyx';
 import * as API from '@libs/API';
-import type {AddDelegateParams as APIAddDelegateParams, RemoveDelegateParams as APIRemoveDelegateParams, UpdateDelegateRoleParams as APIUpdateDelegateRoleParams} from '@libs/API/parameters';
+import type {AddDelegateParams as APIAddDelegateParams, RemoveDelegateParams as APIRemoveDelegateParams, RemoveDelegatorParams as APIRemoveDelegatorParams, UpdateDelegateRoleParams as APIUpdateDelegateRoleParams} from '@libs/API/parameters';
 import {READ_COMMANDS, SIDE_EFFECT_REQUEST_COMMANDS, WRITE_COMMANDS} from '@libs/API/types';
 import * as ErrorUtils from '@libs/ErrorUtils';
 import Log from '@libs/Log';
@@ -570,6 +570,78 @@ function removeDelegate({email, delegatedAccess}: RemoveDelegateParams) {
     API.write(WRITE_COMMANDS.REMOVE_DELEGATE, parameters, {optimisticData, successData, failureData});
 }
 
+function removeDelegator({email, delegatedAccess}: RemoveDelegateParams) {
+    if (!email || !delegatedAccess?.delegators) {
+        return;
+    }
+
+    const optimisticData: Array<OnyxUpdate<typeof ONYXKEYS.ACCOUNT>> = [
+        {
+            onyxMethod: Onyx.METHOD.MERGE,
+            key: ONYXKEYS.ACCOUNT,
+            value: {
+                delegatedAccess: {
+                    errorFields: {
+                        removeDelegator: {
+                            [email]: null,
+                        },
+                    },
+                    delegators: delegatedAccess.delegators?.map((delegator) =>
+                        delegator.email === email
+                            ? {
+                                  ...delegator,
+                                  pendingAction: CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE,
+                                  pendingFields: {email: CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE, role: CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE},
+                              }
+                            : delegator,
+                    ),
+                },
+            },
+        },
+    ];
+
+    const successData: Array<OnyxUpdate<typeof ONYXKEYS.ACCOUNT>> = [
+        {
+            onyxMethod: Onyx.METHOD.MERGE,
+            key: ONYXKEYS.ACCOUNT,
+            value: {
+                delegatedAccess: {
+                    delegators: delegatedAccess.delegators?.filter((delegator) => delegator.email !== email),
+                },
+            },
+        },
+    ];
+
+    const failureData: Array<OnyxUpdate<typeof ONYXKEYS.ACCOUNT>> = [
+        {
+            onyxMethod: Onyx.METHOD.MERGE,
+            key: ONYXKEYS.ACCOUNT,
+            value: {
+                delegatedAccess: {
+                    errorFields: {
+                        removeDelegator: {
+                            [email]: null,
+                        },
+                    },
+                    delegators: delegatedAccess.delegators?.map((delegator) =>
+                        delegator.email === email
+                            ? {
+                                  ...delegator,
+                                  pendingAction: null,
+                                  pendingFields: undefined,
+                              }
+                            : delegator,
+                    ),
+                },
+            },
+        },
+    ];
+
+    const parameters: APIRemoveDelegatorParams = {delegatorEmail: email};
+
+    API.write(WRITE_COMMANDS.REMOVE_DELEGATOR, parameters, {optimisticData, successData, failureData});
+}
+
 function clearDelegateErrorsByField({email, fieldName, delegatedAccess}: ClearDelegateErrorsByFieldParams) {
     if (!delegatedAccess?.delegates) {
         return;
@@ -704,6 +776,7 @@ export {
     isConnectedAsDelegate,
     updateDelegateRole,
     removeDelegate,
+    removeDelegator,
     openSecuritySettingsPage,
     clearOnyxForDelegateTransition,
 };
diff --git a/src/pages/settings/Copilot/CopilotPage.tsx b/src/pages/settings/Copilot/CopilotPage.tsx
index fcf9918d0c4b..79e87190feee 100644
--- a/src/pages/settings/Copilot/CopilotPage.tsx
+++ b/src/pages/settings/Copilot/CopilotPage.tsx
@@ -4,7 +4,6 @@ import type {RefObject} from 'react';
 import {Dimensions, View} from 'react-native';
 import type {GestureResponderEvent} from 'react-native';
 import Badge from '@components/Badge';
-import Button from '@components/Button';
 import {useDelegateNoAccessActions, useDelegateNoAccessState} from '@components/DelegateNoAccessModalProvider';
 import HeaderWithBackButton from '@components/HeaderWithBackButton';
 import {useLockedAccountActions, useLockedAccountState} from '@components/LockedAccountModalProvider';
@@ -28,7 +27,7 @@ import usePersonalDetailsByLogin from '@hooks/usePersonalDetailsByLogin';
 import useResponsiveLayout from '@hooks/useResponsiveLayout';
 import useSwitchToDelegator from '@hooks/useSwitchToDelegator';
 import useThemeStyles from '@hooks/useThemeStyles';
-import {clearDelegateErrorsByField, clearDelegatorErrors, openSecuritySettingsPage, removeDelegate} from '@libs/actions/Delegate';
+import {clearDelegateErrorsByField, clearDelegatorErrors, openSecuritySettingsPage, removeDelegate, removeDelegator} from '@libs/actions/Delegate';
 import {getLatestError} from '@libs/ErrorUtils';
 import getClickedTargetLocation from '@libs/getClickedTargetLocation';
 import Navigation from '@libs/Navigation/Navigation';
@@ -69,6 +68,8 @@ function CopilotPage() {
     const [shouldShowDelegatePopoverMenu, setShouldShowDelegatePopoverMenu] = useState(false);
     const [selectedDelegate, setSelectedDelegate] = useState<Delegate | undefined>();
     const [selectedEmail, setSelectedEmail] = useState<string | undefined>();
+    const [shouldShowDelegatorPopoverMenu, setShouldShowDelegatorPopoverMenu] = useState(false);
+    const [selectedDelegator, setSelectedDelegator] = useState<Delegate | undefined>();
 
     const {showConfirmModal} = useConfirmModal();
     const showRemoveCopilotModal = useCallback(() => {
@@ -82,6 +83,17 @@ function CopilotPage() {
         });
     }, [showConfirmModal, translate]);
 
+    const showRemoveDelegatorModal = useCallback(() => {
+        return showConfirmModal({
+            title: translate('delegate.removeCopilotAccess'),
+            prompt: translate('delegate.removeCopilotAccessConfirmation'),
+            confirmText: translate('delegate.removeCopilotAccess'),
+            cancelText: translate('common.cancel'),
+            shouldShowCancelButton: true,
+            danger: true,
+        });
+    }, [showConfirmModal, translate]);
+
     const errorFields = account?.delegatedAccess?.errorFields ?? {};
 
     const [anchorPosition, setAnchorPosition] = useState<AnchorPosition>({
@@ -122,6 +134,17 @@ function CopilotPage() {
         [setMenuPosition],
     );
 
+    const showDelegatorPopoverMenu = useCallback(
+        (nativeEvent: GestureResponderEvent | KeyboardEvent, delegator: Delegate) => {
+            delegateButtonRef.current = nativeEvent?.currentTarget as HTMLDivElement;
+            setMenuPosition();
+            setShouldShowDelegatorPopoverMenu(true);
+            setSelectedDelegator(delegator);
+            setSelectedEmail(delegator.email);
+        },
+        [setMenuPosition],
+    );
+
     useLayoutEffect(() => {
         const popoverPositionListener = Dimensions.addEventListener('change', () => {
             debounce(setMenuPosition, CONST.TIMING.RESIZE_DEBOUNCE_TIME)();
@@ -256,37 +279,31 @@ function CopilotPage() {
                 iconType: CONST.ICON_TYPE_AVATAR,
                 wrapperStyle: [styles.sectionMenuItemTopDescription],
                 disabled: isPending || isCurrentUser,
-                onPress: () => switchToDelegator(email),
+                onPress: (e: GestureResponderEvent | KeyboardEvent) => {
+                    showDelegatorPopoverMenu(e, {email, role});
+                },
                 role: CONST.ROLE.LINK,
                 error: connectError,
                 onPendingActionDismiss: () => clearDelegatorErrors({delegatedAccess: account?.delegatedAccess}),
-                shouldShowRightComponent: true,
-                rightComponent: (
-                    <View style={[styles.ml2, styles.alignSelfCenter]}>
-                        <Button
-                            small
-                            success
-                            text={translate('delegate.switch')}
-                            isDisabled={isPending || isCurrentUser}
-                            onPress={() => switchToDelegator(email)}
-                            sentryLabel={CONST.SENTRY_LABEL.ACCOUNT_SWITCHER.SHOW_ACCOUNTS}
-                        />
-                    </View>
-                ),
+                iconRight: icons.ThreeDots,
+                shouldShowRightIcon: !isCurrentUser,
+                success: selectedEmail === email,
+                sentryLabel: CONST.SENTRY_LABEL.SETTINGS_SECURITY.DELEGATOR_ITEM,
             };
         });
     }, [
         delegators,
         styles,
-        translate,
         formatPhoneNumber,
         account?.delegatedAccess,
         personalDetailsByLogin,
         localeCompare,
         session?.email,
         errorFields,
-        switchToDelegator,
+        showDelegatorPopoverMenu,
         renderTitleWithRole,
+        selectedEmail,
+        icons.ThreeDots,
     ]);
 
     const delegatePopoverMenuItems: PopoverMenuItem[] = [
@@ -342,6 +359,39 @@ function CopilotPage() {
         },
     ];
 
+    const delegatorPopoverMenuItems: PopoverMenuItem[] = [
+        {
+            text: translate('delegate.switch'),
+            icon: icons.Pencil,
+            sentryLabel: CONST.SENTRY_LABEL.ACCOUNT_SWITCHER.SHOW_ACCOUNTS,
+            onPress: () => {
+                setShouldShowDelegatorPopoverMenu(false);
+                setSelectedDelegator(undefined);
+                setSelectedEmail(undefined);
+                switchToDelegator(selectedDelegator?.email ?? '');
+            },
+        },
+        {
+            text: translate('delegate.removeCopilotAccess'),
+            icon: icons.Trashcan,
+            sentryLabel: CONST.SENTRY_LABEL.SETTINGS_SECURITY.DELEGATOR_REMOVE,
+            onPress: () => {
+                modalClose(() => {
+                    setShouldShowDelegatorPopoverMenu(false);
+                    setSelectedEmail(undefined);
+                    showRemoveDelegatorModal().then((result) => {
+                        if (result.action === ModalActions.CLOSE) {
+                            setSelectedDelegator(undefined);
+                        } else {
+                            removeDelegator({email: selectedDelegator?.email ?? '', delegatedAccess: account?.delegatedAccess});
+                            setSelectedDelegator(undefined);
+                        }
+                    });
+                });
+            },
+        },
+    ];
+
     useEffect(() => {
         openSecuritySettingsPage();
     }, []);
@@ -440,6 +490,20 @@ function CopilotPage() {
                                     setSelectedEmail(undefined);
                                 }}
                             />
+                            <PopoverMenu
+                                isVisible={shouldShowDelegatorPopoverMenu}
+                                anchorRef={delegateButtonRef as RefObject<View | null>}
+                                anchorPosition={anchorPosition}
+                                anchorAlignment={{
+                                    horizontal: CONST.MODAL.ANCHOR_ORIGIN_HORIZONTAL.RIGHT,
+                                    vertical: CONST.MODAL.ANCHOR_ORIGIN_VERTICAL.TOP,
+                                }}
+                                menuItems={delegatorPopoverMenuItems}
+                                onClose={() => {
+                                    setShouldShowDelegatorPopoverMenu(false);
+                                    setSelectedEmail(undefined);
+                                }}
+                            />
                         </View>
                     </ScrollView>
                 </>

From ff80d61dce5c3bc1047104199f70d5305b4b3b1f Mon Sep 17 00:00:00 2001
From: "Daniel Gale-Rosen (via MelvinBot)" <infra+melvinbot@expensify.com>
Date: Thu, 28 May 2026 16:04:50 +0000
Subject: [PATCH 306/435] Fix Prettier and React Compiler compliance failures

- Run Prettier on Delegate.ts to fix formatting
- Convert delegatorMenuItems from useMemo to inline computation to fix
  React Compiler 'Cannot access refs during render' error. The compiler
  flags two useMemo hooks capturing callbacks that mutate the same ref.
  React Compiler auto-memoizes the inline computation, so manual useMemo
  is unnecessary.

Co-authored-by: Daniel Gale-Rosen <dangrous@users.noreply.github.com>
---
 src/libs/actions/Delegate.ts               |   7 +-
 src/pages/settings/Copilot/CopilotPage.tsx | 103 +++++++++------------
 2 files changed, 50 insertions(+), 60 deletions(-)

diff --git a/src/libs/actions/Delegate.ts b/src/libs/actions/Delegate.ts
index d54715c72f3a..3ac8f3a0379a 100644
--- a/src/libs/actions/Delegate.ts
+++ b/src/libs/actions/Delegate.ts
@@ -2,7 +2,12 @@ import HybridAppModule from '@expensify/react-native-hybrid-app';
 import Onyx from 'react-native-onyx';
 import type {OnyxEntry, OnyxKey, OnyxUpdate} from 'react-native-onyx';
 import * as API from '@libs/API';
-import type {AddDelegateParams as APIAddDelegateParams, RemoveDelegateParams as APIRemoveDelegateParams, RemoveDelegatorParams as APIRemoveDelegatorParams, UpdateDelegateRoleParams as APIUpdateDelegateRoleParams} from '@libs/API/parameters';
+import type {
+    AddDelegateParams as APIAddDelegateParams,
+    RemoveDelegateParams as APIRemoveDelegateParams,
+    RemoveDelegatorParams as APIRemoveDelegatorParams,
+    UpdateDelegateRoleParams as APIUpdateDelegateRoleParams,
+} from '@libs/API/parameters';
 import {READ_COMMANDS, SIDE_EFFECT_REQUEST_COMMANDS, WRITE_COMMANDS} from '@libs/API/types';
 import * as ErrorUtils from '@libs/ErrorUtils';
 import Log from '@libs/Log';
diff --git a/src/pages/settings/Copilot/CopilotPage.tsx b/src/pages/settings/Copilot/CopilotPage.tsx
index 79e87190feee..78be5ab2206f 100644
--- a/src/pages/settings/Copilot/CopilotPage.tsx
+++ b/src/pages/settings/Copilot/CopilotPage.tsx
@@ -134,17 +134,6 @@ function CopilotPage() {
         [setMenuPosition],
     );
 
-    const showDelegatorPopoverMenu = useCallback(
-        (nativeEvent: GestureResponderEvent | KeyboardEvent, delegator: Delegate) => {
-            delegateButtonRef.current = nativeEvent?.currentTarget as HTMLDivElement;
-            setMenuPosition();
-            setShouldShowDelegatorPopoverMenu(true);
-            setSelectedDelegator(delegator);
-            setSelectedEmail(delegator.email);
-        },
-        [setMenuPosition],
-    );
-
     useLayoutEffect(() => {
         const popoverPositionListener = Dimensions.addEventListener('change', () => {
             debounce(setMenuPosition, CONST.TIMING.RESIZE_DEBOUNCE_TIME)();
@@ -158,6 +147,17 @@ function CopilotPage() {
         };
     }, [setMenuPosition]);
 
+    const showDelegatorPopoverMenu = useCallback(
+        (nativeEvent: GestureResponderEvent | KeyboardEvent, delegator: Delegate) => {
+            delegateButtonRef.current = nativeEvent?.currentTarget as HTMLDivElement;
+            setMenuPosition();
+            setShouldShowDelegatorPopoverMenu(true);
+            setSelectedDelegator(delegator);
+            setSelectedEmail(delegator.email);
+        },
+        [setMenuPosition],
+    );
+
     const renderTitleWithRole = useCallback(
         (titleText: string, descriptionText: string, role: DelegateRole | undefined) => (
             <View style={[styles.flexShrink1, styles.ml3]}>
@@ -256,55 +256,40 @@ function CopilotPage() {
         actingDelegateEmail,
     ]);
 
-    const delegatorMenuItems: MenuItemProps[] = useMemo(() => {
-        const sortedDelegators = sortAlphabetically(
-            delegators.map((d) => ({...d, sortKey: personalDetailsByLogin[d.email.toLowerCase()]?.displayName ?? formatPhoneNumber(d.email)})),
-            'sortKey',
-            localeCompare,
-        );
-        return sortedDelegators.map(({email, role, pendingAction}) => {
-            const personalDetail = personalDetailsByLogin[email.toLowerCase()];
-            const formattedEmail = formatPhoneNumber(email);
-            const connectError = getLatestError(errorFields?.connect?.[email]);
-            const isCurrentUser = email === session?.email;
-            const isPending = !!pendingAction;
-            const titleText = personalDetail?.displayName ?? formattedEmail;
-            const descriptionText = personalDetail?.displayName ? formattedEmail : '';
-
-            return {
-                key: email,
-                titleComponent: renderTitleWithRole(titleText, descriptionText, role),
-                avatarID: personalDetail?.accountID ?? CONST.DEFAULT_NUMBER_ID,
-                icon: personalDetail?.avatar ?? (personalDetail ? getDefaultAvatarURL({accountID: personalDetail.accountID, accountEmail: email}) : undefined),
-                iconType: CONST.ICON_TYPE_AVATAR,
-                wrapperStyle: [styles.sectionMenuItemTopDescription],
-                disabled: isPending || isCurrentUser,
-                onPress: (e: GestureResponderEvent | KeyboardEvent) => {
-                    showDelegatorPopoverMenu(e, {email, role});
-                },
-                role: CONST.ROLE.LINK,
-                error: connectError,
-                onPendingActionDismiss: () => clearDelegatorErrors({delegatedAccess: account?.delegatedAccess}),
-                iconRight: icons.ThreeDots,
-                shouldShowRightIcon: !isCurrentUser,
-                success: selectedEmail === email,
-                sentryLabel: CONST.SENTRY_LABEL.SETTINGS_SECURITY.DELEGATOR_ITEM,
-            };
-        });
-    }, [
-        delegators,
-        styles,
-        formatPhoneNumber,
-        account?.delegatedAccess,
-        personalDetailsByLogin,
+    const sortedDelegators = sortAlphabetically(
+        delegators.map((d) => ({...d, sortKey: personalDetailsByLogin[d.email.toLowerCase()]?.displayName ?? formatPhoneNumber(d.email)})),
+        'sortKey',
         localeCompare,
-        session?.email,
-        errorFields,
-        showDelegatorPopoverMenu,
-        renderTitleWithRole,
-        selectedEmail,
-        icons.ThreeDots,
-    ]);
+    );
+    const delegatorMenuItems: MenuItemProps[] = sortedDelegators.map(({email, role, pendingAction}) => {
+        const personalDetail = personalDetailsByLogin[email.toLowerCase()];
+        const formattedEmail = formatPhoneNumber(email);
+        const connectError = getLatestError(errorFields?.connect?.[email]);
+        const isCurrentUser = email === session?.email;
+        const isPending = !!pendingAction;
+        const titleText = personalDetail?.displayName ?? formattedEmail;
+        const descriptionText = personalDetail?.displayName ? formattedEmail : '';
+
+        return {
+            key: email,
+            titleComponent: renderTitleWithRole(titleText, descriptionText, role),
+            avatarID: personalDetail?.accountID ?? CONST.DEFAULT_NUMBER_ID,
+            icon: personalDetail?.avatar ?? (personalDetail ? getDefaultAvatarURL({accountID: personalDetail.accountID, accountEmail: email}) : undefined),
+            iconType: CONST.ICON_TYPE_AVATAR,
+            wrapperStyle: [styles.sectionMenuItemTopDescription],
+            disabled: isPending || isCurrentUser,
+            onPress: (e: GestureResponderEvent | KeyboardEvent) => {
+                showDelegatorPopoverMenu(e, {email, role});
+            },
+            role: CONST.ROLE.LINK,
+            error: connectError,
+            onPendingActionDismiss: () => clearDelegatorErrors({delegatedAccess: account?.delegatedAccess}),
+            iconRight: icons.ThreeDots,
+            shouldShowRightIcon: !isCurrentUser,
+            success: selectedEmail === email,
+            sentryLabel: CONST.SENTRY_LABEL.SETTINGS_SECURITY.DELEGATOR_ITEM,
+        };
+    });
 
     const delegatePopoverMenuItems: PopoverMenuItem[] = [
         {

From 11a114c881033454988abe86e69334df3774ecbe Mon Sep 17 00:00:00 2001
From: "Daniel Gale-Rosen (via MelvinBot)" <infra+melvinbot@expensify.com>
Date: Thu, 28 May 2026 16:26:31 +0000
Subject: [PATCH 307/435] Fix typecheck and test failures

- Add removeDelegator field to DelegateErrors type
- Add removeCopilotAccess/removeCopilotAccessConfirmation translations
  to de, fr, it, ja, nl, pl, pt-BR, zh-hans
- Update CopilotPageTest to expect three-dot menu instead of Switch
  button in delegator rows
- Add removeDelegator to Delegate action mock

Co-authored-by: Daniel Gale-Rosen <dangrous@users.noreply.github.com>
---
 src/languages/de.ts                           | 2 ++
 src/languages/fr.ts                           | 2 ++
 src/languages/it.ts                           | 2 ++
 src/languages/ja.ts                           | 2 ++
 src/languages/nl.ts                           | 2 ++
 src/languages/pl.ts                           | 2 ++
 src/languages/pt-BR.ts                        | 2 ++
 src/languages/zh-hans.ts                      | 2 ++
 src/types/onyx/Account.ts                     | 3 +++
 tests/unit/pages/settings/CopilotPageTest.tsx | 5 +++--
 10 files changed, 22 insertions(+), 2 deletions(-)

diff --git a/src/languages/de.ts b/src/languages/de.ts
index 0d1e3fa4e939..9d48124bc9c4 100644
--- a/src/languages/de.ts
+++ b/src/languages/de.ts
@@ -9423,6 +9423,8 @@ Fügen Sie weitere Ausgabelimits hinzu, um den Cashflow Ihres Unternehmens zu sc
         `),
         notAllowedMessage: (accountOwnerEmail: string) =>
             `Als <a href="${CONST.DELEGATE_ROLE_HELP_DOT_ARTICLE_LINK}">Copilot</a> von ${accountOwnerEmail} hast du keine Berechtigung, diese Aktion auszuführen. Entschuldigung!`,
+        removeCopilotAccess: 'Copilot-Zugriff entfernen',
+        removeCopilotAccessConfirmation: 'Sind Sie sicher, dass Sie Ihren Copilot-Zugriff auf dieses Konto entfernen möchten?',
         copilotAccess: 'Copilot-Zugriff',
     },
     debug: {
diff --git a/src/languages/fr.ts b/src/languages/fr.ts
index ce9967cac91f..c6edf0e3265b 100644
--- a/src/languages/fr.ts
+++ b/src/languages/fr.ts
@@ -9456,6 +9456,8 @@ Ajoutez davantage de règles de dépenses pour protéger la trésorerie de l’e
         `),
         notAllowedMessage: (accountOwnerEmail: string) =>
             `En tant que <a href="${CONST.DELEGATE_ROLE_HELP_DOT_ARTICLE_LINK}">copilote</a> pour ${accountOwnerEmail}, vous n’avez pas l’autorisation d’effectuer cette action. Désolé !`,
+        removeCopilotAccess: "Supprimer l'accès copilote",
+        removeCopilotAccessConfirmation: 'Êtes-vous sûr de vouloir supprimer votre accès copilote à ce compte ?',
         copilotAccess: 'Accès Copilot',
     },
     debug: {
diff --git a/src/languages/it.ts b/src/languages/it.ts
index 56c5f51e01b6..6f80d8929765 100644
--- a/src/languages/it.ts
+++ b/src/languages/it.ts
@@ -9415,6 +9415,8 @@ Aggiungi altre regole di spesa per proteggere il flusso di cassa aziendale.`,
         `),
         notAllowedMessage: (accountOwnerEmail: string) =>
             `Come <a href="${CONST.DELEGATE_ROLE_HELP_DOT_ARTICLE_LINK}">copilota</a> per ${accountOwnerEmail}, non hai l'autorizzazione per eseguire questa azione. Spiacenti!`,
+        removeCopilotAccess: "Rimuovi l'accesso copilota",
+        removeCopilotAccessConfirmation: 'Sei sicuro di voler rimuovere il tuo accesso copilota a questo account?',
         copilotAccess: 'Accesso a Copilot',
     },
     debug: {
diff --git a/src/languages/ja.ts b/src/languages/ja.ts
index c919ff5acbd6..4729fae64c00 100644
--- a/src/languages/ja.ts
+++ b/src/languages/ja.ts
@@ -9291,6 +9291,8 @@ ${reportName}
         `),
         notAllowedMessage: (accountOwnerEmail: string) =>
             `${accountOwnerEmail} の<a href="${CONST.DELEGATE_ROLE_HELP_DOT_ARTICLE_LINK}">コパイロット</a>として、この操作を行う権限がありません。申し訳ありません。`,
+        removeCopilotAccess: 'コパイロットアクセスを削除',
+        removeCopilotAccessConfirmation: 'このアカウントへのコパイロットアクセスを削除してもよろしいですか？',
         copilotAccess: 'Copilot へのアクセス',
     },
     debug: {
diff --git a/src/languages/nl.ts b/src/languages/nl.ts
index 31241631d1a3..49e6352256c4 100644
--- a/src/languages/nl.ts
+++ b/src/languages/nl.ts
@@ -9377,6 +9377,8 @@ er bestedingsregels toe om de kasstroom van het bedrijf te beschermen.`,
         `),
         notAllowedMessage: (accountOwnerEmail: string) =>
             `Als <a href="${CONST.DELEGATE_ROLE_HELP_DOT_ARTICLE_LINK}">copiloot</a> voor ${accountOwnerEmail} heb je geen toestemming om deze actie uit te voeren. Sorry!`,
+        removeCopilotAccess: 'Copilot-toegang verwijderen',
+        removeCopilotAccessConfirmation: 'Weet je zeker dat je je copilot-toegang tot dit account wilt verwijderen?',
         copilotAccess: 'Copilot-toegang',
     },
     debug: {
diff --git a/src/languages/pl.ts b/src/languages/pl.ts
index b03bb152077e..c50880a7f709 100644
--- a/src/languages/pl.ts
+++ b/src/languages/pl.ts
@@ -9362,6 +9362,8 @@ Dodaj więcej zasad wydatków, żeby chronić płynność finansową firmy.`,
         `),
         notAllowedMessage: (accountOwnerEmail: string) =>
             `Jako <a href="${CONST.DELEGATE_ROLE_HELP_DOT_ARTICLE_LINK}">kopilot</a> dla ${accountOwnerEmail} nie masz uprawnień do wykonania tej akcji. Przepraszamy!`,
+        removeCopilotAccess: 'Usuń dostęp kopilota',
+        removeCopilotAccessConfirmation: 'Czy na pewno chcesz usunąć swój dostęp kopilota do tego konta?',
         copilotAccess: 'Dostęp do Copilota',
     },
     debug: {
diff --git a/src/languages/pt-BR.ts b/src/languages/pt-BR.ts
index 62bd0d329a96..165aabaea42d 100644
--- a/src/languages/pt-BR.ts
+++ b/src/languages/pt-BR.ts
@@ -9370,6 +9370,8 @@ Adicione mais regras de gasto para proteger o fluxo de caixa da empresa.`,
         `),
         notAllowedMessage: (accountOwnerEmail: string) =>
             `Como <a href="${CONST.DELEGATE_ROLE_HELP_DOT_ARTICLE_LINK}">copiloto</a> de ${accountOwnerEmail}, você não tem permissão para realizar esta ação. Desculpe!`,
+        removeCopilotAccess: 'Remover acesso de copiloto',
+        removeCopilotAccessConfirmation: 'Tem certeza de que deseja remover seu acesso de copiloto a esta conta?',
         copilotAccess: 'Acesso ao Copilot',
     },
     debug: {
diff --git a/src/languages/zh-hans.ts b/src/languages/zh-hans.ts
index 5d0fc73591e4..4de3e3b62417 100644
--- a/src/languages/zh-hans.ts
+++ b/src/languages/zh-hans.ts
@@ -9119,6 +9119,8 @@ ${reportName}
             作为副驾驶，你无权访问此页面。抱歉！
         `),
         notAllowedMessage: (accountOwnerEmail: string) => `作为${accountOwnerEmail}的<a href="${CONST.DELEGATE_ROLE_HELP_DOT_ARTICLE_LINK}">副驾驶</a>，你没有权限执行此操作。抱歉！`,
+        removeCopilotAccess: '移除副驾驶访问权限',
+        removeCopilotAccessConfirmation: '您确定要移除对此账户的副驾驶访问权限吗？',
         copilotAccess: 'Copilot 访问',
     },
     debug: {
diff --git a/src/types/onyx/Account.ts b/src/types/onyx/Account.ts
index 3fcc72cdb4ad..b52ba9fac852 100644
--- a/src/types/onyx/Account.ts
+++ b/src/types/onyx/Account.ts
@@ -35,6 +35,9 @@ type DelegateErrors = {
     /** Errors while removing a delegate keyed by email */
     removeDelegate?: Record<string, OnyxCommon.Errors>;
 
+    /** Errors while removing a delegator keyed by email */
+    removeDelegator?: Record<string, OnyxCommon.Errors>;
+
     /** Errors while connecting as a delegate keyed by email */
     connect?: Record<string, OnyxCommon.Errors>;
 
diff --git a/tests/unit/pages/settings/CopilotPageTest.tsx b/tests/unit/pages/settings/CopilotPageTest.tsx
index cc97e2520429..1c06a930e470 100644
--- a/tests/unit/pages/settings/CopilotPageTest.tsx
+++ b/tests/unit/pages/settings/CopilotPageTest.tsx
@@ -73,6 +73,7 @@ jest.mock('@libs/actions/Delegate', () => ({
     connect: jest.fn(),
     openSecuritySettingsPage: jest.fn(),
     removeDelegate: jest.fn(),
+    removeDelegator: jest.fn(),
 }));
 
 jest.mock('@libs/Navigation/Navigation', () => ({
@@ -158,7 +159,7 @@ describe('CopilotPage', () => {
         expect(output).toContain('delegate.addCopilot');
     });
 
-    it('renders a delegator row with a Switch button when the user has delegators', () => {
+    it('renders a delegator row with a three-dot menu when the user has delegators', () => {
         setOnyxAccount({
             validated: true,
             delegatedAccess: {
@@ -171,7 +172,7 @@ describe('CopilotPage', () => {
         const output = JSON.stringify(toJSON());
 
         expect(output).toContain('boss@example.com');
-        expect(output).toContain('delegate.switch');
+        expect(output).toContain('icon-three-dots');
         expect(output).toContain('delegate.youCanAccessTheseAccounts');
         expect(output).not.toContain('delegate.membersCanAccessYourAccount');
     });

From 022bf96f3b54deba93ad810a816697a1bcb20836 Mon Sep 17 00:00:00 2001
From: Nicolas Bonet <nicolas@expensify.com>
Date: Thu, 4 Jun 2026 16:01:12 -0500
Subject: [PATCH 308/435] Enhance copilot access removal functionality

- Update translations for remove copilot access in multiple languages (de, en, es, fr, it, ja, nl, pl, pt-BR, zh-hans) to include personalized confirmation messages.
- Modify CopilotPage to utilize new confirmation modal structure, including delegator name in prompts.
- Adjust icon usage in the delegator popover menu for improved UX.
---
 src/languages/de.ts                        |  8 +++--
 src/languages/en.ts                        |  8 +++--
 src/languages/es.ts                        |  9 ++++--
 src/languages/fr.ts                        |  8 +++--
 src/languages/it.ts                        |  8 +++--
 src/languages/ja.ts                        |  8 +++--
 src/languages/nl.ts                        |  8 +++--
 src/languages/params.ts                    |  3 ++
 src/languages/pl.ts                        |  8 +++--
 src/languages/pt-BR.ts                     |  8 +++--
 src/languages/zh-hans.ts                   |  7 +++--
 src/pages/settings/Copilot/CopilotPage.tsx | 36 +++++++++++++---------
 12 files changed, 83 insertions(+), 36 deletions(-)

diff --git a/src/languages/de.ts b/src/languages/de.ts
index 9d48124bc9c4..3111c76b2e34 100644
--- a/src/languages/de.ts
+++ b/src/languages/de.ts
@@ -40,6 +40,7 @@ import type {
     OptionalParam,
     PaidElsewhereParams,
     ParentNavigationSummaryParams,
+    RemoveCopilotAccessConfirmationParams,
     RemovedFromApprovalWorkflowParams,
     ReportArchiveReasonsClosedParams,
     ReportArchiveReasonsInvoiceReceiverPolicyDeletedParams,
@@ -9423,8 +9424,11 @@ Fügen Sie weitere Ausgabelimits hinzu, um den Cashflow Ihres Unternehmens zu sc
         `),
         notAllowedMessage: (accountOwnerEmail: string) =>
             `Als <a href="${CONST.DELEGATE_ROLE_HELP_DOT_ARTICLE_LINK}">Copilot</a> von ${accountOwnerEmail} hast du keine Berechtigung, diese Aktion auszuführen. Entschuldigung!`,
-        removeCopilotAccess: 'Copilot-Zugriff entfernen',
-        removeCopilotAccessConfirmation: 'Sind Sie sicher, dass Sie Ihren Copilot-Zugriff auf dieses Konto entfernen möchten?',
+        removeCopilotAccess: 'Meinen Copilot-Zugriff entfernen',
+        removeCopilotAccessTitle: 'Copilot-Zugriff entfernen?',
+        removeCopilotAccessConfirmation: ({delegatorName}: RemoveCopilotAccessConfirmationParams) =>
+            `Sind Sie sicher, dass Sie Ihren Copilot-Zugriff auf das Expensify-Konto von ${delegatorName} entfernen möchten? Diese Aktion kann nicht rückgängig gemacht werden.`,
+        removeCopilotAccessConfirm: 'Zugriff entfernen',
         copilotAccess: 'Copilot-Zugriff',
     },
     debug: {
diff --git a/src/languages/en.ts b/src/languages/en.ts
index eb0d31926d4d..a15a1411b57f 100644
--- a/src/languages/en.ts
+++ b/src/languages/en.ts
@@ -28,6 +28,7 @@ import type {
     OptionalParam,
     PaidElsewhereParams,
     ParentNavigationSummaryParams,
+    RemoveCopilotAccessConfirmationParams,
     RemovedFromApprovalWorkflowParams,
     ReportArchiveReasonsClosedParams,
     ReportArchiveReasonsInvoiceReceiverPolicyDeletedParams,
@@ -9461,8 +9462,11 @@ const translations = {
         },
         removeCopilot: 'Remove copilot',
         removeCopilotConfirmation: 'Are you sure you want to remove this copilot?',
-        removeCopilotAccess: 'Remove copilot access',
-        removeCopilotAccessConfirmation: 'Are you sure you want to remove your copilot access to this account?',
+        removeCopilotAccess: 'Remove my copilot access',
+        removeCopilotAccessTitle: 'Remove copilot access?',
+        removeCopilotAccessConfirmation: ({delegatorName}: RemoveCopilotAccessConfirmationParams) =>
+            `Are you sure you want to remove your copilot access to ${delegatorName}'s Expensify account? This action cannot be undone.`,
+        removeCopilotAccessConfirm: 'Remove access',
         changeAccessLevel: 'Change access level',
         makeSureItIsYou: "Let's make sure it's you",
         enterMagicCode: (contactMethod: string) => `Please enter the magic code sent to ${contactMethod} to add a copilot. It should arrive within a minute or two.`,
diff --git a/src/languages/es.ts b/src/languages/es.ts
index 2577d67ac10f..a6a140ae6828 100644
--- a/src/languages/es.ts
+++ b/src/languages/es.ts
@@ -14,7 +14,7 @@ import dedent from '@libs/StringUtils/dedent';
 import CONST from '@src/CONST';
 import type {OriginalMessageSettlementAccountLocked, PersonalRulesModifiedFields, PolicyRulesModifiedFields} from '@src/types/onyx/OriginalMessage';
 import type en from './en';
-import type {ConciergeBrokenCardConnectionParams, PaidElsewhereParams, UnsupportedFormulaValueErrorParams} from './params';
+import type {ConciergeBrokenCardConnectionParams, PaidElsewhereParams, RemoveCopilotAccessConfirmationParams, UnsupportedFormulaValueErrorParams} from './params';
 import type {TranslationDeepObject} from './types';
 
 const translations: TranslationDeepObject<typeof en> = {
@@ -9580,8 +9580,11 @@ ${amount} para ${merchant} - ${date}`,
         },
         removeCopilot: 'Eliminar copiloto',
         removeCopilotConfirmation: '¿Estás seguro de que quieres eliminar este copiloto?',
-        removeCopilotAccess: 'Eliminar acceso de copiloto',
-        removeCopilotAccessConfirmation: '¿Estás seguro de que quieres eliminar tu acceso de copiloto a esta cuenta?',
+        removeCopilotAccess: 'Eliminar mi acceso de copiloto',
+        removeCopilotAccessTitle: '¿Eliminar acceso de copiloto?',
+        removeCopilotAccessConfirmation: ({delegatorName}: RemoveCopilotAccessConfirmationParams) =>
+            `¿Estás seguro de que quieres eliminar tu acceso de copiloto a la cuenta de Expensify de ${delegatorName}? Esta acción no se puede deshacer.`,
+        removeCopilotAccessConfirm: 'Eliminar acceso',
         changeAccessLevel: 'Cambiar nivel de acceso',
         makeSureItIsYou: 'Vamos a asegurarnos de que eres tú',
         enterMagicCode: (contactMethod) => `Por favor, introduce el código mágico enviado a ${contactMethod} para agregar un copiloto. Debería llegar en un par de minutos.`,
diff --git a/src/languages/fr.ts b/src/languages/fr.ts
index c6edf0e3265b..f7becfc96f7f 100644
--- a/src/languages/fr.ts
+++ b/src/languages/fr.ts
@@ -40,6 +40,7 @@ import type {
     OptionalParam,
     PaidElsewhereParams,
     ParentNavigationSummaryParams,
+    RemoveCopilotAccessConfirmationParams,
     RemovedFromApprovalWorkflowParams,
     ReportArchiveReasonsClosedParams,
     ReportArchiveReasonsInvoiceReceiverPolicyDeletedParams,
@@ -9456,8 +9457,11 @@ Ajoutez davantage de règles de dépenses pour protéger la trésorerie de l’e
         `),
         notAllowedMessage: (accountOwnerEmail: string) =>
             `En tant que <a href="${CONST.DELEGATE_ROLE_HELP_DOT_ARTICLE_LINK}">copilote</a> pour ${accountOwnerEmail}, vous n’avez pas l’autorisation d’effectuer cette action. Désolé !`,
-        removeCopilotAccess: "Supprimer l'accès copilote",
-        removeCopilotAccessConfirmation: 'Êtes-vous sûr de vouloir supprimer votre accès copilote à ce compte ?',
+        removeCopilotAccess: 'Supprimer mon accès copilote',
+        removeCopilotAccessTitle: "Supprimer l'accès copilote ?",
+        removeCopilotAccessConfirmation: ({delegatorName}: RemoveCopilotAccessConfirmationParams) =>
+            `Êtes-vous sûr de vouloir supprimer votre accès copilote au compte Expensify de ${delegatorName} ? Cette action est irréversible.`,
+        removeCopilotAccessConfirm: "Supprimer l'accès",
         copilotAccess: 'Accès Copilot',
     },
     debug: {
diff --git a/src/languages/it.ts b/src/languages/it.ts
index 6f80d8929765..82dbbb3c891e 100644
--- a/src/languages/it.ts
+++ b/src/languages/it.ts
@@ -40,6 +40,7 @@ import type {
     OptionalParam,
     PaidElsewhereParams,
     ParentNavigationSummaryParams,
+    RemoveCopilotAccessConfirmationParams,
     RemovedFromApprovalWorkflowParams,
     ReportArchiveReasonsClosedParams,
     ReportArchiveReasonsInvoiceReceiverPolicyDeletedParams,
@@ -9415,8 +9416,11 @@ Aggiungi altre regole di spesa per proteggere il flusso di cassa aziendale.`,
         `),
         notAllowedMessage: (accountOwnerEmail: string) =>
             `Come <a href="${CONST.DELEGATE_ROLE_HELP_DOT_ARTICLE_LINK}">copilota</a> per ${accountOwnerEmail}, non hai l'autorizzazione per eseguire questa azione. Spiacenti!`,
-        removeCopilotAccess: "Rimuovi l'accesso copilota",
-        removeCopilotAccessConfirmation: 'Sei sicuro di voler rimuovere il tuo accesso copilota a questo account?',
+        removeCopilotAccess: 'Rimuovi il mio accesso copilota',
+        removeCopilotAccessTitle: "Rimuovere l'accesso copilota?",
+        removeCopilotAccessConfirmation: ({delegatorName}: RemoveCopilotAccessConfirmationParams) =>
+            `Sei sicuro di voler rimuovere il tuo accesso copilota all'account Expensify di ${delegatorName}? Questa azione non può essere annullata.`,
+        removeCopilotAccessConfirm: 'Rimuovi accesso',
         copilotAccess: 'Accesso a Copilot',
     },
     debug: {
diff --git a/src/languages/ja.ts b/src/languages/ja.ts
index 4729fae64c00..2a721fa48420 100644
--- a/src/languages/ja.ts
+++ b/src/languages/ja.ts
@@ -40,6 +40,7 @@ import type {
     OptionalParam,
     PaidElsewhereParams,
     ParentNavigationSummaryParams,
+    RemoveCopilotAccessConfirmationParams,
     RemovedFromApprovalWorkflowParams,
     ReportArchiveReasonsClosedParams,
     ReportArchiveReasonsInvoiceReceiverPolicyDeletedParams,
@@ -9291,8 +9292,11 @@ ${reportName}
         `),
         notAllowedMessage: (accountOwnerEmail: string) =>
             `${accountOwnerEmail} の<a href="${CONST.DELEGATE_ROLE_HELP_DOT_ARTICLE_LINK}">コパイロット</a>として、この操作を行う権限がありません。申し訳ありません。`,
-        removeCopilotAccess: 'コパイロットアクセスを削除',
-        removeCopilotAccessConfirmation: 'このアカウントへのコパイロットアクセスを削除してもよろしいですか？',
+        removeCopilotAccess: '自分のコパイロットアクセスを削除',
+        removeCopilotAccessTitle: 'コパイロットアクセスを削除しますか？',
+        removeCopilotAccessConfirmation: ({delegatorName}: RemoveCopilotAccessConfirmationParams) =>
+            `${delegatorName}のExpensifyアカウントへのコパイロットアクセスを削除してもよろしいですか？この操作は元に戻せません。`,
+        removeCopilotAccessConfirm: 'アクセスを削除',
         copilotAccess: 'Copilot へのアクセス',
     },
     debug: {
diff --git a/src/languages/nl.ts b/src/languages/nl.ts
index 49e6352256c4..c3badae9112f 100644
--- a/src/languages/nl.ts
+++ b/src/languages/nl.ts
@@ -40,6 +40,7 @@ import type {
     OptionalParam,
     PaidElsewhereParams,
     ParentNavigationSummaryParams,
+    RemoveCopilotAccessConfirmationParams,
     RemovedFromApprovalWorkflowParams,
     ReportArchiveReasonsClosedParams,
     ReportArchiveReasonsInvoiceReceiverPolicyDeletedParams,
@@ -9377,8 +9378,11 @@ er bestedingsregels toe om de kasstroom van het bedrijf te beschermen.`,
         `),
         notAllowedMessage: (accountOwnerEmail: string) =>
             `Als <a href="${CONST.DELEGATE_ROLE_HELP_DOT_ARTICLE_LINK}">copiloot</a> voor ${accountOwnerEmail} heb je geen toestemming om deze actie uit te voeren. Sorry!`,
-        removeCopilotAccess: 'Copilot-toegang verwijderen',
-        removeCopilotAccessConfirmation: 'Weet je zeker dat je je copilot-toegang tot dit account wilt verwijderen?',
+        removeCopilotAccess: 'Mijn copilot-toegang verwijderen',
+        removeCopilotAccessTitle: 'Copilot-toegang verwijderen?',
+        removeCopilotAccessConfirmation: ({delegatorName}: RemoveCopilotAccessConfirmationParams) =>
+            `Weet je zeker dat je je copilot-toegang tot het Expensify-account van ${delegatorName} wilt verwijderen? Deze actie kan niet ongedaan worden gemaakt.`,
+        removeCopilotAccessConfirm: 'Toegang verwijderen',
         copilotAccess: 'Copilot-toegang',
     },
     debug: {
diff --git a/src/languages/params.ts b/src/languages/params.ts
index 41610783b027..b9c0884faab4 100644
--- a/src/languages/params.ts
+++ b/src/languages/params.ts
@@ -102,6 +102,8 @@ type SyncStageNameConnectionsParams = {stage: PolicyConnectionSyncStage};
 
 type DelegateRoleParams = {role: DelegateRole};
 
+type RemoveCopilotAccessConfirmationParams = {delegatorName: string};
+
 type RemovedFromApprovalWorkflowParams = {
     submittersNames: string[];
 };
@@ -135,6 +137,7 @@ export type {
     InvalidValueParams,
     RemovedFromApprovalWorkflowParams,
     DelegateRoleParams,
+    RemoveCopilotAccessConfirmationParams,
     SyncStageNameConnectionsParams,
     IntacctMappingTitleParams,
     ExportIntegrationSelectedParams,
diff --git a/src/languages/pl.ts b/src/languages/pl.ts
index c50880a7f709..904f87fe035b 100644
--- a/src/languages/pl.ts
+++ b/src/languages/pl.ts
@@ -40,6 +40,7 @@ import type {
     OptionalParam,
     PaidElsewhereParams,
     ParentNavigationSummaryParams,
+    RemoveCopilotAccessConfirmationParams,
     RemovedFromApprovalWorkflowParams,
     ReportArchiveReasonsClosedParams,
     ReportArchiveReasonsInvoiceReceiverPolicyDeletedParams,
@@ -9362,8 +9363,11 @@ Dodaj więcej zasad wydatków, żeby chronić płynność finansową firmy.`,
         `),
         notAllowedMessage: (accountOwnerEmail: string) =>
             `Jako <a href="${CONST.DELEGATE_ROLE_HELP_DOT_ARTICLE_LINK}">kopilot</a> dla ${accountOwnerEmail} nie masz uprawnień do wykonania tej akcji. Przepraszamy!`,
-        removeCopilotAccess: 'Usuń dostęp kopilota',
-        removeCopilotAccessConfirmation: 'Czy na pewno chcesz usunąć swój dostęp kopilota do tego konta?',
+        removeCopilotAccess: 'Usuń mój dostęp kopilota',
+        removeCopilotAccessTitle: 'Usunąć dostęp kopilota?',
+        removeCopilotAccessConfirmation: ({delegatorName}: RemoveCopilotAccessConfirmationParams) =>
+            `Czy na pewno chcesz usunąć swój dostęp kopilota do konta Expensify użytkownika ${delegatorName}? Tej czynności nie można cofnąć.`,
+        removeCopilotAccessConfirm: 'Usuń dostęp',
         copilotAccess: 'Dostęp do Copilota',
     },
     debug: {
diff --git a/src/languages/pt-BR.ts b/src/languages/pt-BR.ts
index 165aabaea42d..755a20cb2f0a 100644
--- a/src/languages/pt-BR.ts
+++ b/src/languages/pt-BR.ts
@@ -40,6 +40,7 @@ import type {
     OptionalParam,
     PaidElsewhereParams,
     ParentNavigationSummaryParams,
+    RemoveCopilotAccessConfirmationParams,
     RemovedFromApprovalWorkflowParams,
     ReportArchiveReasonsClosedParams,
     ReportArchiveReasonsInvoiceReceiverPolicyDeletedParams,
@@ -9370,8 +9371,11 @@ Adicione mais regras de gasto para proteger o fluxo de caixa da empresa.`,
         `),
         notAllowedMessage: (accountOwnerEmail: string) =>
             `Como <a href="${CONST.DELEGATE_ROLE_HELP_DOT_ARTICLE_LINK}">copiloto</a> de ${accountOwnerEmail}, você não tem permissão para realizar esta ação. Desculpe!`,
-        removeCopilotAccess: 'Remover acesso de copiloto',
-        removeCopilotAccessConfirmation: 'Tem certeza de que deseja remover seu acesso de copiloto a esta conta?',
+        removeCopilotAccess: 'Remover meu acesso de copiloto',
+        removeCopilotAccessTitle: 'Remover acesso de copiloto?',
+        removeCopilotAccessConfirmation: ({delegatorName}: RemoveCopilotAccessConfirmationParams) =>
+            `Tem certeza de que deseja remover seu acesso de copiloto à conta Expensify de ${delegatorName}? Esta ação não pode ser desfeita.`,
+        removeCopilotAccessConfirm: 'Remover acesso',
         copilotAccess: 'Acesso ao Copilot',
     },
     debug: {
diff --git a/src/languages/zh-hans.ts b/src/languages/zh-hans.ts
index 4de3e3b62417..b1a8b8c88083 100644
--- a/src/languages/zh-hans.ts
+++ b/src/languages/zh-hans.ts
@@ -40,6 +40,7 @@ import type {
     OptionalParam,
     PaidElsewhereParams,
     ParentNavigationSummaryParams,
+    RemoveCopilotAccessConfirmationParams,
     RemovedFromApprovalWorkflowParams,
     ReportArchiveReasonsClosedParams,
     ReportArchiveReasonsInvoiceReceiverPolicyDeletedParams,
@@ -9119,8 +9120,10 @@ ${reportName}
             作为副驾驶，你无权访问此页面。抱歉！
         `),
         notAllowedMessage: (accountOwnerEmail: string) => `作为${accountOwnerEmail}的<a href="${CONST.DELEGATE_ROLE_HELP_DOT_ARTICLE_LINK}">副驾驶</a>，你没有权限执行此操作。抱歉！`,
-        removeCopilotAccess: '移除副驾驶访问权限',
-        removeCopilotAccessConfirmation: '您确定要移除对此账户的副驾驶访问权限吗？',
+        removeCopilotAccess: '移除我的副驾驶访问权限',
+        removeCopilotAccessTitle: '移除副驾驶访问权限？',
+        removeCopilotAccessConfirmation: ({delegatorName}: RemoveCopilotAccessConfirmationParams) => `您确定要移除对${delegatorName}的 Expensify 账户的副驾驶访问权限吗？此操作无法撤销。`,
+        removeCopilotAccessConfirm: '移除访问权限',
         copilotAccess: 'Copilot 访问',
     },
     debug: {
diff --git a/src/pages/settings/Copilot/CopilotPage.tsx b/src/pages/settings/Copilot/CopilotPage.tsx
index 78be5ab2206f..e7d2c1db8373 100644
--- a/src/pages/settings/Copilot/CopilotPage.tsx
+++ b/src/pages/settings/Copilot/CopilotPage.tsx
@@ -50,7 +50,7 @@ const accountDelegationSelector = (accountValue: Account | undefined) => ({
 });
 
 function CopilotPage() {
-    const icons = useMemoizedLazyExpensifyIcons(['Pencil', 'ThreeDots', 'Trashcan', 'UserPlus']);
+    const icons = useMemoizedLazyExpensifyIcons(['ArrowCircleClockwise', 'CircleSlash', 'Pencil', 'ThreeDots', 'UserPlus']);
     const illustrations = useMemoizedLazyIllustrations(['Copilots', 'Members']);
     const styles = useThemeStyles();
     const {localeCompare, translate, formatPhoneNumber} = useLocalize();
@@ -83,16 +83,22 @@ function CopilotPage() {
         });
     }, [showConfirmModal, translate]);
 
-    const showRemoveDelegatorModal = useCallback(() => {
-        return showConfirmModal({
-            title: translate('delegate.removeCopilotAccess'),
-            prompt: translate('delegate.removeCopilotAccessConfirmation'),
-            confirmText: translate('delegate.removeCopilotAccess'),
-            cancelText: translate('common.cancel'),
-            shouldShowCancelButton: true,
-            danger: true,
-        });
-    }, [showConfirmModal, translate]);
+    const showRemoveDelegatorModal = useCallback(
+        (delegatorEmail: string) => {
+            const personalDetail = personalDetailsByLogin[delegatorEmail.toLowerCase()];
+            const delegatorName = personalDetail?.displayName ?? formatPhoneNumber(delegatorEmail);
+
+            return showConfirmModal({
+                title: translate('delegate.removeCopilotAccessTitle'),
+                prompt: translate('delegate.removeCopilotAccessConfirmation', {delegatorName}),
+                confirmText: translate('delegate.removeCopilotAccessConfirm'),
+                cancelText: translate('common.cancel'),
+                shouldShowCancelButton: true,
+                danger: true,
+            });
+        },
+        [showConfirmModal, translate, personalDetailsByLogin, formatPhoneNumber],
+    );
 
     const errorFields = account?.delegatedAccess?.errorFields ?? {};
 
@@ -313,7 +319,7 @@ function CopilotPage() {
         },
         {
             text: translate('delegate.removeCopilot'),
-            icon: icons.Trashcan,
+            icon: icons.CircleSlash,
             sentryLabel: CONST.SENTRY_LABEL.SETTINGS_SECURITY.DELEGATE_REMOVE,
             onPress: () => {
                 if (selectedDelegate?.email !== account?.delegatedAccess?.delegate && isActingAsDelegate) {
@@ -347,7 +353,7 @@ function CopilotPage() {
     const delegatorPopoverMenuItems: PopoverMenuItem[] = [
         {
             text: translate('delegate.switch'),
-            icon: icons.Pencil,
+            icon: icons.ArrowCircleClockwise,
             sentryLabel: CONST.SENTRY_LABEL.ACCOUNT_SWITCHER.SHOW_ACCOUNTS,
             onPress: () => {
                 setShouldShowDelegatorPopoverMenu(false);
@@ -358,13 +364,13 @@ function CopilotPage() {
         },
         {
             text: translate('delegate.removeCopilotAccess'),
-            icon: icons.Trashcan,
+            icon: icons.CircleSlash,
             sentryLabel: CONST.SENTRY_LABEL.SETTINGS_SECURITY.DELEGATOR_REMOVE,
             onPress: () => {
                 modalClose(() => {
                     setShouldShowDelegatorPopoverMenu(false);
                     setSelectedEmail(undefined);
-                    showRemoveDelegatorModal().then((result) => {
+                    showRemoveDelegatorModal(selectedDelegator?.email ?? '').then((result) => {
                         if (result.action === ModalActions.CLOSE) {
                             setSelectedDelegator(undefined);
                         } else {

From 2c4fa03af5380797dca320e0391a0b3aa93f18af Mon Sep 17 00:00:00 2001
From: Nicolas Bonet <nicolas@expensify.com>
Date: Thu, 4 Jun 2026 16:05:14 -0500
Subject: [PATCH 309/435] Enhance delegate error handling in Copilot

- Add 'connect' and 'removeDelegator' fields to WithFieldName type for improved error tracking.
- Update error handling in removeDelegator function to provide more informative error messages.
- Modify CopilotPage to handle errors for both 'connect' and 'removeDelegator' actions, ensuring proper dismissal of errors on pending actions.
---
 src/libs/actions/Delegate.ts               |  6 +++---
 src/pages/settings/Copilot/CopilotPage.tsx | 13 ++++++++++---
 2 files changed, 13 insertions(+), 6 deletions(-)

diff --git a/src/libs/actions/Delegate.ts b/src/libs/actions/Delegate.ts
index 3ac8f3a0379a..86e137d4562b 100644
--- a/src/libs/actions/Delegate.ts
+++ b/src/libs/actions/Delegate.ts
@@ -84,7 +84,7 @@ type WithValidateCode = {
 
 type WithFieldName = {
     // Constrain to known keys to avoid misspells at call sites
-    fieldName: 'addDelegate' | 'updateDelegateRole'; // but string could work as well
+    fieldName: 'addDelegate' | 'updateDelegateRole' | 'connect' | 'removeDelegator' | 'removeDelegate';
 };
 
 type WithOldDotFlag = {
@@ -625,7 +625,7 @@ function removeDelegator({email, delegatedAccess}: RemoveDelegateParams) {
                 delegatedAccess: {
                     errorFields: {
                         removeDelegator: {
-                            [email]: null,
+                            [email]: ErrorUtils.getMicroSecondOnyxErrorWithTranslationKey('delegate.genericError'),
                         },
                     },
                     delegators: delegatedAccess.delegators?.map((delegator) =>
@@ -648,7 +648,7 @@ function removeDelegator({email, delegatedAccess}: RemoveDelegateParams) {
 }
 
 function clearDelegateErrorsByField({email, fieldName, delegatedAccess}: ClearDelegateErrorsByFieldParams) {
-    if (!delegatedAccess?.delegates) {
+    if (!delegatedAccess) {
         return;
     }
 
diff --git a/src/pages/settings/Copilot/CopilotPage.tsx b/src/pages/settings/Copilot/CopilotPage.tsx
index e7d2c1db8373..d05b3a69a612 100644
--- a/src/pages/settings/Copilot/CopilotPage.tsx
+++ b/src/pages/settings/Copilot/CopilotPage.tsx
@@ -27,7 +27,7 @@ import usePersonalDetailsByLogin from '@hooks/usePersonalDetailsByLogin';
 import useResponsiveLayout from '@hooks/useResponsiveLayout';
 import useSwitchToDelegator from '@hooks/useSwitchToDelegator';
 import useThemeStyles from '@hooks/useThemeStyles';
-import {clearDelegateErrorsByField, clearDelegatorErrors, openSecuritySettingsPage, removeDelegate, removeDelegator} from '@libs/actions/Delegate';
+import {clearDelegateErrorsByField, openSecuritySettingsPage, removeDelegate, removeDelegator} from '@libs/actions/Delegate';
 import {getLatestError} from '@libs/ErrorUtils';
 import getClickedTargetLocation from '@libs/getClickedTargetLocation';
 import Navigation from '@libs/Navigation/Navigation';
@@ -271,6 +271,8 @@ function CopilotPage() {
         const personalDetail = personalDetailsByLogin[email.toLowerCase()];
         const formattedEmail = formatPhoneNumber(email);
         const connectError = getLatestError(errorFields?.connect?.[email]);
+        const removeDelegatorError = getLatestError(errorFields?.removeDelegator?.[email]);
+        const error = getLatestError({...connectError, ...removeDelegatorError});
         const isCurrentUser = email === session?.email;
         const isPending = !!pendingAction;
         const titleText = personalDetail?.displayName ?? formattedEmail;
@@ -288,8 +290,13 @@ function CopilotPage() {
                 showDelegatorPopoverMenu(e, {email, role});
             },
             role: CONST.ROLE.LINK,
-            error: connectError,
-            onPendingActionDismiss: () => clearDelegatorErrors({delegatedAccess: account?.delegatedAccess}),
+            pendingAction,
+            shouldForceOpacity: !!pendingAction,
+            error,
+            onPendingActionDismiss: () => {
+                clearDelegateErrorsByField({email, fieldName: 'connect', delegatedAccess: account?.delegatedAccess});
+                clearDelegateErrorsByField({email, fieldName: 'removeDelegator', delegatedAccess: account?.delegatedAccess});
+            },
             iconRight: icons.ThreeDots,
             shouldShowRightIcon: !isCurrentUser,
             success: selectedEmail === email,

From 46c2d04565ad1bdb9b592d8175b2eed416316cd6 Mon Sep 17 00:00:00 2001
From: Nicolas Bonet <nicolas@expensify.com>
Date: Mon, 8 Jun 2026 10:20:54 -0500
Subject: [PATCH 310/435] Address PR review: drop redundant useCallbacks and
 link role on delegator row

- Convert showRemoveDelegatorModal and showDelegatorPopoverMenu to plain functions (React Compiler auto-memoizes)
- Remove role: CONST.ROLE.LINK from delegator row since it now opens a popover instead of navigating

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
---
 src/pages/settings/Copilot/CopilotPage.tsx | 45 +++++++++-------------
 1 file changed, 19 insertions(+), 26 deletions(-)

diff --git a/src/pages/settings/Copilot/CopilotPage.tsx b/src/pages/settings/Copilot/CopilotPage.tsx
index d05b3a69a612..94007d88cccd 100644
--- a/src/pages/settings/Copilot/CopilotPage.tsx
+++ b/src/pages/settings/Copilot/CopilotPage.tsx
@@ -83,22 +83,19 @@ function CopilotPage() {
         });
     }, [showConfirmModal, translate]);
 
-    const showRemoveDelegatorModal = useCallback(
-        (delegatorEmail: string) => {
-            const personalDetail = personalDetailsByLogin[delegatorEmail.toLowerCase()];
-            const delegatorName = personalDetail?.displayName ?? formatPhoneNumber(delegatorEmail);
+    const showRemoveDelegatorModal = (delegatorEmail: string) => {
+        const personalDetail = personalDetailsByLogin[delegatorEmail.toLowerCase()];
+        const delegatorName = personalDetail?.displayName ?? formatPhoneNumber(delegatorEmail);
 
-            return showConfirmModal({
-                title: translate('delegate.removeCopilotAccessTitle'),
-                prompt: translate('delegate.removeCopilotAccessConfirmation', {delegatorName}),
-                confirmText: translate('delegate.removeCopilotAccessConfirm'),
-                cancelText: translate('common.cancel'),
-                shouldShowCancelButton: true,
-                danger: true,
-            });
-        },
-        [showConfirmModal, translate, personalDetailsByLogin, formatPhoneNumber],
-    );
+        return showConfirmModal({
+            title: translate('delegate.removeCopilotAccessTitle'),
+            prompt: translate('delegate.removeCopilotAccessConfirmation', {delegatorName}),
+            confirmText: translate('delegate.removeCopilotAccessConfirm'),
+            cancelText: translate('common.cancel'),
+            shouldShowCancelButton: true,
+            danger: true,
+        });
+    };
 
     const errorFields = account?.delegatedAccess?.errorFields ?? {};
 
@@ -153,16 +150,13 @@ function CopilotPage() {
         };
     }, [setMenuPosition]);
 
-    const showDelegatorPopoverMenu = useCallback(
-        (nativeEvent: GestureResponderEvent | KeyboardEvent, delegator: Delegate) => {
-            delegateButtonRef.current = nativeEvent?.currentTarget as HTMLDivElement;
-            setMenuPosition();
-            setShouldShowDelegatorPopoverMenu(true);
-            setSelectedDelegator(delegator);
-            setSelectedEmail(delegator.email);
-        },
-        [setMenuPosition],
-    );
+    const showDelegatorPopoverMenu = (nativeEvent: GestureResponderEvent | KeyboardEvent, delegator: Delegate) => {
+        delegateButtonRef.current = nativeEvent?.currentTarget as HTMLDivElement;
+        setMenuPosition();
+        setShouldShowDelegatorPopoverMenu(true);
+        setSelectedDelegator(delegator);
+        setSelectedEmail(delegator.email);
+    };
 
     const renderTitleWithRole = useCallback(
         (titleText: string, descriptionText: string, role: DelegateRole | undefined) => (
@@ -289,7 +283,6 @@ function CopilotPage() {
             onPress: (e: GestureResponderEvent | KeyboardEvent) => {
                 showDelegatorPopoverMenu(e, {email, role});
             },
-            role: CONST.ROLE.LINK,
             pendingAction,
             shouldForceOpacity: !!pendingAction,
             error,

From ec7637c2f56b66da2548b95c083bed22cbfde4a0 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Nicol=C3=A1s=20Bonet=20=28via=20MelvinBot=29?=
 <infra+melvinbot@expensify.com>
Date: Tue, 9 Jun 2026 14:39:09 +0000
Subject: [PATCH 311/435] Fix: dedupe type assertions in CopilotPage to stay
 within eslint-seatbelt baseline
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Co-authored-by: Nicolás Bonet <NicolasBonet@users.noreply.github.com>
---
 src/pages/settings/Copilot/CopilotPage.tsx | 16 +++++++++++-----
 1 file changed, 11 insertions(+), 5 deletions(-)

diff --git a/src/pages/settings/Copilot/CopilotPage.tsx b/src/pages/settings/Copilot/CopilotPage.tsx
index 94007d88cccd..f92d288e62d4 100644
--- a/src/pages/settings/Copilot/CopilotPage.tsx
+++ b/src/pages/settings/Copilot/CopilotPage.tsx
@@ -126,15 +126,19 @@ function CopilotPage() {
         });
     }, [delegateButtonRef]);
 
+    const captureDelegateButtonRef = useCallback((nativeEvent: GestureResponderEvent | KeyboardEvent) => {
+        delegateButtonRef.current = nativeEvent?.currentTarget as HTMLDivElement;
+    }, []);
+
     const showPopoverMenu = useCallback(
         (nativeEvent: GestureResponderEvent | KeyboardEvent, delegate: Delegate) => {
-            delegateButtonRef.current = nativeEvent?.currentTarget as HTMLDivElement;
+            captureDelegateButtonRef(nativeEvent);
             setMenuPosition();
             setShouldShowDelegatePopoverMenu(true);
             setSelectedDelegate(delegate);
             setSelectedEmail(delegate.email);
         },
-        [setMenuPosition],
+        [captureDelegateButtonRef, setMenuPosition],
     );
 
     useLayoutEffect(() => {
@@ -151,7 +155,7 @@ function CopilotPage() {
     }, [setMenuPosition]);
 
     const showDelegatorPopoverMenu = (nativeEvent: GestureResponderEvent | KeyboardEvent, delegator: Delegate) => {
-        delegateButtonRef.current = nativeEvent?.currentTarget as HTMLDivElement;
+        captureDelegateButtonRef(nativeEvent);
         setMenuPosition();
         setShouldShowDelegatorPopoverMenu(true);
         setSelectedDelegator(delegator);
@@ -387,6 +391,8 @@ function CopilotPage() {
         openSecuritySettingsPage();
     }, []);
 
+    const delegateAnchorRef = delegateButtonRef as RefObject<View | null>;
+
     return (
         <ScreenWrapper
             testID="CopilotPage"
@@ -469,7 +475,7 @@ function CopilotPage() {
                             </Section>
                             <PopoverMenu
                                 isVisible={shouldShowDelegatePopoverMenu}
-                                anchorRef={delegateButtonRef as RefObject<View | null>}
+                                anchorRef={delegateAnchorRef}
                                 anchorPosition={anchorPosition}
                                 anchorAlignment={{
                                     horizontal: CONST.MODAL.ANCHOR_ORIGIN_HORIZONTAL.RIGHT,
@@ -483,7 +489,7 @@ function CopilotPage() {
                             />
                             <PopoverMenu
                                 isVisible={shouldShowDelegatorPopoverMenu}
-                                anchorRef={delegateButtonRef as RefObject<View | null>}
+                                anchorRef={delegateAnchorRef}
                                 anchorPosition={anchorPosition}
                                 anchorAlignment={{
                                     horizontal: CONST.MODAL.ANCHOR_ORIGIN_HORIZONTAL.RIGHT,

From 22f3c018b0f8a0c01202eb22da2edfef6059575b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Nicol=C3=A1s=20Bonet=20=28via=20MelvinBot=29?=
 <infra+melvinbot@expensify.com>
Date: Wed, 10 Jun 2026 20:59:22 +0000
Subject: [PATCH 312/435] Bump eslint-seatbelt baseline for
 ReportSecondaryActionUtilsTest after delegator type additions
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Co-authored-by: Nicolás Bonet <NicolasBonet@users.noreply.github.com>
---
 config/eslint/eslint.seatbelt.tsv | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/config/eslint/eslint.seatbelt.tsv b/config/eslint/eslint.seatbelt.tsv
index 1965b85b4922..69a9c6a2340e 100644
--- a/config/eslint/eslint.seatbelt.tsv
+++ b/config/eslint/eslint.seatbelt.tsv
@@ -1818,7 +1818,7 @@
 "../../tests/unit/ReportLayoutUtilsTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../tests/unit/ReportNameUtilsTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	22
 "../../tests/unit/ReportPrimaryActionUtilsTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	168
-"../../tests/unit/ReportSecondaryActionUtilsTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	450
+"../../tests/unit/ReportSecondaryActionUtilsTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	466
 "../../tests/unit/ReportSubmitUtilsTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../tests/unit/ReportTitleUtilsTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	3
 "../../tests/unit/ReportUtilsGetIconsTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	1

From 4c59211e17db8ede295436aa4cf4068f3eaddab1 Mon Sep 17 00:00:00 2001
From: Nicolas Bonet <nicolas@expensify.com>
Date: Wed, 10 Jun 2026 16:11:08 -0500
Subject: [PATCH 313/435] chore: testing

---
 config/eslint/eslint.seatbelt.tsv | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/config/eslint/eslint.seatbelt.tsv b/config/eslint/eslint.seatbelt.tsv
index 69a9c6a2340e..1965b85b4922 100644
--- a/config/eslint/eslint.seatbelt.tsv
+++ b/config/eslint/eslint.seatbelt.tsv
@@ -1818,7 +1818,7 @@
 "../../tests/unit/ReportLayoutUtilsTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../tests/unit/ReportNameUtilsTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	22
 "../../tests/unit/ReportPrimaryActionUtilsTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	168
-"../../tests/unit/ReportSecondaryActionUtilsTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	466
+"../../tests/unit/ReportSecondaryActionUtilsTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	450
 "../../tests/unit/ReportSubmitUtilsTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../tests/unit/ReportTitleUtilsTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	3
 "../../tests/unit/ReportUtilsGetIconsTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	1

From daf50d941652e644cd3a66fa4751794177370323 Mon Sep 17 00:00:00 2001
From: Alex Beaman <alexbeaman@expensify.com>
Date: Wed, 10 Jun 2026 15:12:16 -0600
Subject: [PATCH 314/435] Fix spellcheck: rename test vendor Globex -> Office
 Supplies

---
 tests/unit/ModifiedExpenseMessageTest.ts | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/tests/unit/ModifiedExpenseMessageTest.ts b/tests/unit/ModifiedExpenseMessageTest.ts
index 0fae1f042ab1..e423ec007d7d 100644
--- a/tests/unit/ModifiedExpenseMessageTest.ts
+++ b/tests/unit/ModifiedExpenseMessageTest.ts
@@ -2173,7 +2173,7 @@ describe('ModifiedExpenseMessage', () => {
                         data: {
                             vendors: [
                                 {id: 'v-acme', name: 'Acme', currency: 'USD', email: ''},
-                                {id: 'v-globex', name: 'Globex', currency: 'USD', email: ''},
+                                {id: 'v-office', name: 'Office Supplies', currency: 'USD', email: ''},
                             ],
                         },
                     },
@@ -2211,7 +2211,7 @@ describe('ModifiedExpenseMessage', () => {
                     actionName: CONST.REPORT.ACTIONS.TYPE.MODIFIED_EXPENSE,
                     originalMessage: {
                         oldVendor: {externalID: 'v-acme', isManuallySet: false},
-                        vendor: {externalID: 'v-globex', isManuallySet: true},
+                        vendor: {externalID: 'v-office', isManuallySet: true},
                     },
                 };
 
@@ -2223,7 +2223,7 @@ describe('ModifiedExpenseMessage', () => {
                         policyTags: undefined,
                         currentUserLogin: CURRENT_USER_LOGIN,
                     });
-                    expect(result).toEqual('changed the vendor to "Globex" (previously "Acme")');
+                    expect(result).toEqual('changed the vendor to "Office Supplies" (previously "Acme")');
                 });
             });
 

From 4b9e1507894e2d41da1815f46168419ee8081d8f Mon Sep 17 00:00:00 2001
From: jayeshmangwani <jayeshmangwani@gmail.com>
Date: Thu, 11 Jun 2026 02:55:55 +0530
Subject: [PATCH 315/435] removed useOnyx from DeferredActionCell

---
 .../ListItem/ActionCell/DeferredActionCell.tsx  | 17 +----------------
 .../SearchList/ListItem/ActionCell/index.tsx    |  1 +
 .../ListItem/ExpenseReportListItem.tsx          | 11 ++++++++++-
 .../ExpenseReportListItemRowWide.tsx            |  2 ++
 .../ListItem/ExpenseReportListItemRow/index.tsx |  1 +
 .../ListItem/ExpenseReportListItemRow/types.ts  |  1 +
 .../TransactionItemRowWide.tsx                  |  2 ++
 src/components/TransactionItemRow/index.tsx     | 12 +++++++++++-
 src/components/TransactionItemRow/types.ts      |  1 +
 9 files changed, 30 insertions(+), 18 deletions(-)

diff --git a/src/components/Search/SearchList/ListItem/ActionCell/DeferredActionCell.tsx b/src/components/Search/SearchList/ListItem/ActionCell/DeferredActionCell.tsx
index 85eca228b672..328112908fe4 100644
--- a/src/components/Search/SearchList/ListItem/ActionCell/DeferredActionCell.tsx
+++ b/src/components/Search/SearchList/ListItem/ActionCell/DeferredActionCell.tsx
@@ -1,13 +1,8 @@
-import {isTrackIntentUserSelector} from '@selectors/Onboarding';
 import React, {useDeferredValue} from 'react';
 import Button from '@components/Button';
 import useLocalize from '@hooks/useLocalize';
-import useOnyx from '@hooks/useOnyx';
 import useThemeStyles from '@hooks/useThemeStyles';
-import getNonEmptyStringOnyxID from '@libs/getNonEmptyStringOnyxID';
-import {shouldShowMarkAsDone} from '@libs/ReportUtils';
 import CONST from '@src/CONST';
-import ONYXKEYS from '@src/ONYXKEYS';
 import ActionCell from '.';
 import type {ActionCellProps} from '.';
 import actionTranslationsMap from './actionTranslationsMap';
@@ -16,9 +11,6 @@ function DeferredActionCell(actionCellProps: ActionCellProps) {
     const styles = useThemeStyles();
     const {translate} = useLocalize();
     const shouldRender = useDeferredValue(true, false);
-    const [isTrackIntentUser] = useOnyx(ONYXKEYS.NVP_INTRO_SELECTED, {selector: isTrackIntentUserSelector});
-    const [actionCellPolicy] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY}${getNonEmptyStringOnyxID(actionCellProps.policyID)}`);
-    const [actionCellReport] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${getNonEmptyStringOnyxID(actionCellProps.reportID)}`);
 
     if (!shouldRender) {
         const action = actionCellProps.action ?? CONST.SEARCH.ACTION_TYPES.VIEW;
@@ -28,14 +20,7 @@ function DeferredActionCell(actionCellProps: ActionCellProps) {
         if (shouldUseViewAction) {
             text = translate(actionTranslationsMap[CONST.SEARCH.ACTION_TYPES.VIEW]);
         } else {
-            const shouldUseMarkAsDone =
-                shouldShowMarkAsDone({
-                    isTrackIntentUser,
-                    report: actionCellReport,
-                    policy: actionCellPolicy,
-                }) && action === CONST.SEARCH.ACTION_TYPES.SUBMIT;
-
-            text = shouldUseMarkAsDone ? translate('common.done') : translate(actionTranslationsMap[action]);
+            text = actionCellProps.isMarkAsDone ? translate('common.done') : translate(actionTranslationsMap[action]);
         }
 
         return (
diff --git a/src/components/Search/SearchList/ListItem/ActionCell/index.tsx b/src/components/Search/SearchList/ListItem/ActionCell/index.tsx
index b2188185cd9d..a97cc8486f02 100644
--- a/src/components/Search/SearchList/ListItem/ActionCell/index.tsx
+++ b/src/components/Search/SearchList/ListItem/ActionCell/index.tsx
@@ -26,6 +26,7 @@ type ActionCellProps = {
     amount?: number;
     extraSmall?: boolean;
     shouldDisablePointerEvents?: boolean;
+    isMarkAsDone?: boolean;
 };
 
 function ActionCell({
diff --git a/src/components/Search/SearchList/ListItem/ExpenseReportListItem.tsx b/src/components/Search/SearchList/ListItem/ExpenseReportListItem.tsx
index 9eeb51f6645d..dae25ffdaabc 100644
--- a/src/components/Search/SearchList/ListItem/ExpenseReportListItem.tsx
+++ b/src/components/Search/SearchList/ListItem/ExpenseReportListItem.tsx
@@ -1,3 +1,4 @@
+import {isTrackIntentUserSelector} from '@selectors/Onboarding';
 import React, {useCallback, useMemo} from 'react';
 import {View} from 'react-native';
 // We need direct access to useOnyx to fetch live policy data at render time
@@ -29,7 +30,7 @@ import {handleActionButtonPress} from '@libs/actions/Search';
 import {syncMissingAttendeesViolation} from '@libs/AttendeeUtils';
 import getNonEmptyStringOnyxID from '@libs/getNonEmptyStringOnyxID';
 import {isAttendeeTrackingEnabled} from '@libs/PolicyUtils';
-import {getNonHeldAndFullAmount, isInvoiceReport, isOpenExpenseReport, isProcessingReport, isReportPendingDelete} from '@libs/ReportUtils';
+import {getNonHeldAndFullAmount, isInvoiceReport, isOpenExpenseReport, isProcessingReport, isReportPendingDelete, shouldShowMarkAsDone} from '@libs/ReportUtils';
 import {isOnHold, isViolationDismissed, shouldShowViolation, showPendingCardTransactionsBlockModal} from '@libs/TransactionUtils';
 import variables from '@styles/variables';
 import CONST from '@src/CONST';
@@ -84,6 +85,7 @@ function ExpenseReportListItem<TItem extends ListItem>({
     const [isActionLoading] = useOnyx(`${ONYXKEYS.COLLECTION.RAM_ONLY_REPORT_LOADING_STATE}${reportItem.reportID}`, {selector: isActionLoadingSelector});
     const expensifyIcons = useMemoizedLazyExpensifyIcons(['DotIndicator']);
     const currentUserDetails = useCurrentUserPersonalDetails();
+    const [isTrackIntentUser] = useOnyx(ONYXKEYS.NVP_INTRO_SELECTED, {selector: isTrackIntentUserSelector});
 
     // Fetch live policy categories from Onyx to sync violations at render time
     const [parentPolicy] = originalUseOnyx(`${ONYXKEYS.COLLECTION.POLICY}${getNonEmptyStringOnyxID(reportItem.policyID)}`);
@@ -91,6 +93,12 @@ function ExpenseReportListItem<TItem extends ListItem>({
     const [parentChatReport] = originalUseOnyx(`${ONYXKEYS.COLLECTION.REPORT}${getNonEmptyStringOnyxID(reportItem.parentReportID)}`);
     const [policyCategories] = originalUseOnyx(`${ONYXKEYS.COLLECTION.POLICY_CATEGORIES}${getNonEmptyStringOnyxID(reportItem.policyID)}`);
 
+    const shouldUseMarkAsDoneCopy = shouldShowMarkAsDone({
+        policy: parentPolicy,
+        report: parentReport,
+        isTrackIntentUser,
+    });
+
     const searchData = currentSearchResults?.data;
 
     const snapshotReport = useMemo(() => {
@@ -408,6 +416,7 @@ function ExpenseReportListItem<TItem extends ListItem>({
                         isHovered={hovered}
                         isFocused={isFocused}
                         isPendingDelete={isPendingDelete}
+                        isMarkAsDone={shouldUseMarkAsDoneCopy}
                     />
                     {getDescription}
                 </View>
diff --git a/src/components/Search/SearchList/ListItem/ExpenseReportListItemRow/ExpenseReportListItemRowWide.tsx b/src/components/Search/SearchList/ListItem/ExpenseReportListItemRow/ExpenseReportListItemRowWide.tsx
index ab301d389d58..1f36248f325c 100644
--- a/src/components/Search/SearchList/ListItem/ExpenseReportListItemRow/ExpenseReportListItemRowWide.tsx
+++ b/src/components/Search/SearchList/ListItem/ExpenseReportListItemRow/ExpenseReportListItemRowWide.tsx
@@ -37,6 +37,7 @@ function ExpenseReportListItemRowWide({
     isHovered = false,
     isFocused = false,
     isPendingDelete = false,
+    isMarkAsDone,
 }: ExpenseReportListItemRowWideProps) {
     const StyleUtils = useStyleUtils();
     const styles = useThemeStyles();
@@ -200,6 +201,7 @@ function ExpenseReportListItemRowWide({
                     hash={item.hash}
                     amount={item.total}
                     shouldDisablePointerEvents={isPendingDelete}
+                    isMarkAsDone={isMarkAsDone}
                 />
             </View>
         ),
diff --git a/src/components/Search/SearchList/ListItem/ExpenseReportListItemRow/index.tsx b/src/components/Search/SearchList/ListItem/ExpenseReportListItemRow/index.tsx
index 30e4854a6291..27a0204db7d9 100644
--- a/src/components/Search/SearchList/ListItem/ExpenseReportListItemRow/index.tsx
+++ b/src/components/Search/SearchList/ListItem/ExpenseReportListItemRow/index.tsx
@@ -25,6 +25,7 @@ function ExpenseReportListItemRow(props: ExpenseReportListItemRowProps) {
                 isFocused={props.isFocused}
                 isPendingDelete={props.isPendingDelete}
                 columns={props.columns}
+                isMarkAsDone={props.isMarkAsDone}
             />
         );
     }
diff --git a/src/components/Search/SearchList/ListItem/ExpenseReportListItemRow/types.ts b/src/components/Search/SearchList/ListItem/ExpenseReportListItemRow/types.ts
index 6a405152939a..fd8c786c2544 100644
--- a/src/components/Search/SearchList/ListItem/ExpenseReportListItemRow/types.ts
+++ b/src/components/Search/SearchList/ListItem/ExpenseReportListItemRow/types.ts
@@ -22,6 +22,7 @@ type ExpenseReportListItemRowWideProps = ExpenseReportListItemRowNarrowProps & {
     isFocused?: boolean;
     isPendingDelete?: boolean;
     columns?: SearchColumnType[];
+    isMarkAsDone: boolean;
 };
 
 type ExpenseReportListItemRowProps = ExpenseReportListItemRowWideProps;
diff --git a/src/components/TransactionItemRow/TransactionItemRowWide.tsx b/src/components/TransactionItemRow/TransactionItemRowWide.tsx
index 9c09063f9214..3507989a14b1 100644
--- a/src/components/TransactionItemRow/TransactionItemRowWide.tsx
+++ b/src/components/TransactionItemRow/TransactionItemRowWide.tsx
@@ -113,6 +113,7 @@ function TransactionItemRowWide({
     totalPerAttendee,
     transactionThreadReportID,
     createdAt,
+    isMarkAsDone,
 }: TransactionItemRowWideProps) {
     const styles = useThemeStyles();
     const {translate} = useLocalize();
@@ -304,6 +305,7 @@ function TransactionItemRowWide({
                                 hash={transactionItem?.hash}
                                 amount={report?.total}
                                 shouldDisablePointerEvents={isDisabled}
+                                isMarkAsDone={isMarkAsDone}
                             />
                         )}
                     </View>
diff --git a/src/components/TransactionItemRow/index.tsx b/src/components/TransactionItemRow/index.tsx
index ae0024e52a13..cebbc85f037d 100644
--- a/src/components/TransactionItemRow/index.tsx
+++ b/src/components/TransactionItemRow/index.tsx
@@ -1,12 +1,14 @@
+import {isTrackIntentUserSelector} from '@selectors/Onboarding';
 import React from 'react';
 import type {StyleProp, ViewStyle} from 'react-native';
 import useAttendees from '@hooks/useAttendees';
 import useLocalize from '@hooks/useLocalize';
+import useOnyx from '@hooks/useOnyx';
 import useThemeStyles from '@hooks/useThemeStyles';
 import {getCompanyCardDescription} from '@libs/CardUtils';
 import {getDecodedCategoryName, isCategoryMissing} from '@libs/CategoryUtils';
 import {getIOUActionForTransactionID} from '@libs/ReportActionsUtils';
-import {isExpenseReport, isSettled} from '@libs/ReportUtils';
+import {isExpenseReport, isSettled, shouldShowMarkAsDone} from '@libs/ReportUtils';
 import StringUtils from '@libs/StringUtils';
 import {
     getAmount,
@@ -22,6 +24,7 @@ import {
 } from '@libs/TransactionUtils';
 import CONST from '@src/CONST';
 import type {TranslationPaths} from '@src/languages/types';
+import ONYXKEYS from '@src/ONYXKEYS';
 import TransactionItemRowNarrow from './TransactionItemRowNarrow';
 import TransactionItemRowWide from './TransactionItemRowWide';
 import type {TransactionItemRowProps, TransactionWithOptionalSearchFields} from './types';
@@ -97,6 +100,12 @@ function TransactionItemRow({
     canEditAmount,
     canEditTag,
 }: TransactionItemRowProps) {
+    const [isTrackIntentUser] = useOnyx(ONYXKEYS.NVP_INTRO_SELECTED, {selector: isTrackIntentUserSelector});
+    const shouldUseMarkAsDoneCopy = shouldShowMarkAsDone({
+        policy,
+        report,
+        isTrackIntentUser,
+    });
     const styles = useThemeStyles();
     const {translate} = useLocalize();
     const createdAt = getTransactionCreated(transactionItem);
@@ -253,6 +262,7 @@ function TransactionItemRow({
             totalPerAttendee={!attendeesCount || totalAmount === undefined ? undefined : totalAmount / attendeesCount}
             createdAt={createdAt}
             transactionThreadReportID={transactionThreadReportID}
+            isMarkAsDone={shouldUseMarkAsDoneCopy}
         />
     );
 }
diff --git a/src/components/TransactionItemRow/types.ts b/src/components/TransactionItemRow/types.ts
index 747228ef6845..82e5001c6d79 100644
--- a/src/components/TransactionItemRow/types.ts
+++ b/src/components/TransactionItemRow/types.ts
@@ -140,6 +140,7 @@ type TransactionItemRowWideComputedData = Omit<TransactionItemRowNarrowComputedD
     transactionAttendees: Attendee[];
     shouldShowAttendees: boolean;
     totalPerAttendee: number | undefined;
+    isMarkAsDone: boolean;
 };
 
 export type {TransactionWithOptionalSearchFields, TransactionItemRowProps, TransactionItemRowNarrowComputedData, TransactionItemRowWideComputedData};

From e1e61bd9bfbafd99aaf92344e7781ed2337fe475 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Nicol=C3=A1s=20Bonet=20=28via=20MelvinBot=29?=
 <infra+melvinbot@expensify.com>
Date: Wed, 10 Jun 2026 21:42:39 +0000
Subject: [PATCH 316/435] Bump eslint-seatbelt baseline for
 ReportSecondaryActionUtilsTest after delegator type additions
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Co-authored-by: Nicolás Bonet <NicolasBonet@users.noreply.github.com>
---
 config/eslint/eslint.seatbelt.tsv | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/config/eslint/eslint.seatbelt.tsv b/config/eslint/eslint.seatbelt.tsv
index 1965b85b4922..69a9c6a2340e 100644
--- a/config/eslint/eslint.seatbelt.tsv
+++ b/config/eslint/eslint.seatbelt.tsv
@@ -1818,7 +1818,7 @@
 "../../tests/unit/ReportLayoutUtilsTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../tests/unit/ReportNameUtilsTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	22
 "../../tests/unit/ReportPrimaryActionUtilsTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	168
-"../../tests/unit/ReportSecondaryActionUtilsTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	450
+"../../tests/unit/ReportSecondaryActionUtilsTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	466
 "../../tests/unit/ReportSubmitUtilsTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../tests/unit/ReportTitleUtilsTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	3
 "../../tests/unit/ReportUtilsGetIconsTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	1

From c51201257f8b1eafcfa3385698efa6072b31e9ef Mon Sep 17 00:00:00 2001
From: Alex Beaman <alexbeaman@expensify.com>
Date: Wed, 10 Jun 2026 15:58:07 -0600
Subject: [PATCH 317/435] Bump eslint-seatbelt baseline for new vendor tests +
 merge-induced drift

---
 config/eslint/eslint.seatbelt.tsv | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/config/eslint/eslint.seatbelt.tsv b/config/eslint/eslint.seatbelt.tsv
index d04ba3ace2f3..a68b5f06efb1 100644
--- a/config/eslint/eslint.seatbelt.tsv
+++ b/config/eslint/eslint.seatbelt.tsv
@@ -1582,7 +1582,7 @@
 "../../tests/actions/IOUTest/SplitTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	21
 "../../tests/actions/IOUTest/TrackExpenseTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	10
 "../../tests/actions/IOUTest/UpdateMoneyRequestTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	4
-"../../tests/actions/IOUTest/UpdateMoneyRequestVendorTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	2
+"../../tests/actions/IOUTest/UpdateMoneyRequestVendorTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	3
 "../../tests/actions/MergeTransactionTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	10
 "../../tests/actions/OnyxUpdateManagerTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	4
 "../../tests/actions/PersonalDetailsTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	10
@@ -1786,7 +1786,7 @@
 "../../tests/unit/MentionUserRendererTest.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	8
 "../../tests/unit/MentionUtilsTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	4
 "../../tests/unit/MiddlewareTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	20
-"../../tests/unit/ModifiedExpenseMessageTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	5
+"../../tests/unit/ModifiedExpenseMessageTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	6
 "../../tests/unit/MoneyRequestReportTransactionListActiveTransactionIDsTest.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	5
 "../../tests/unit/MoneyRequestReportUtilsTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	8
 "../../tests/unit/MoneyRequestUtilsTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	3
@@ -1828,7 +1828,7 @@
 "../../tests/unit/ReportLayoutUtilsTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../tests/unit/ReportNameUtilsTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	22
 "../../tests/unit/ReportPrimaryActionUtilsTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	168
-"../../tests/unit/ReportSecondaryActionUtilsTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	450
+"../../tests/unit/ReportSecondaryActionUtilsTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	466
 "../../tests/unit/ReportSubmitUtilsTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../tests/unit/ReportTitleUtilsTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	3
 "../../tests/unit/ReportUtilsGetIconsTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	1

From 241f77465e324cca9ccded76f8754293d43ebcdb Mon Sep 17 00:00:00 2001
From: "Christina Dobrzynski (via MelvinBot)" <infra+melvinbot@expensify.com>
Date: Wed, 10 Jun 2026 21:58:11 +0000
Subject: [PATCH 318/435] Align non-English lockAccountPage translations with
 Polyglot Parrot output

Co-authored-by: Christina Dobrzynski <Christinadobrzyn@users.noreply.github.com>
---
 src/languages/de.ts      | 10 +++++-----
 src/languages/es.ts      |  8 ++++----
 src/languages/fr.ts      |  4 ++--
 src/languages/it.ts      |  6 +++---
 src/languages/ja.ts      | 10 +++++-----
 src/languages/nl.ts      | 10 +++++-----
 src/languages/pl.ts      |  6 +++---
 src/languages/pt-BR.ts   |  8 ++++----
 src/languages/zh-hans.ts |  8 ++++----
 9 files changed, 35 insertions(+), 35 deletions(-)

diff --git a/src/languages/de.ts b/src/languages/de.ts
index d4ec98d71e98..2a01bdfb9bbe 100644
--- a/src/languages/de.ts
+++ b/src/languages/de.ts
@@ -2224,14 +2224,14 @@ const translations: TranslationDeepObject<typeof en> = {
     lockAccountPage: {
         reportSuspiciousActivity: 'Verdächtige Aktivität melden',
         lockAccount: 'Konto sperren',
-        lockMyAccount: 'Mein Konto sperren',
+        lockMyAccount: 'Sperren Sie mein Konto',
         unlockAccount: 'Konto entsperren',
-        findYourSituation: 'Die meisten Probleme erfordern keine Kontosperrung! Finden Sie unten Ihre Situation:',
+        findYourSituation: 'Die meisten Probleme erfordern keine Sperrung Ihres Kontos! Finden Sie Ihre Situation unten:',
         lostCardOrCharges:
-            '<a href="https://help.expensify.com/articles/expensify-classic/expensify-card/Dispute-Transaction">Verlorene Karte oder unbekannte Abbuchungen</a>: Stornieren Sie Ihre Karte und wenden Sie sich an Concierge, um unbekannte Transaktionen anzufechten.',
+            '<a href="https://help.expensify.com/articles/expensify-classic/expensify-card/Dispute-Transaction">Karte verloren oder unbekannte Abbuchungen</a>: Sperren Sie Ihre Karte und kontaktieren Sie Concierge, um unbekannte Transaktionen anzufechten.',
         unauthorizedAccess:
-            '<a href="https://help.expensify.com/articles/expensify-classic/settings/Report-Suspicious-Activity">Unbefugter Kontozugriff</a>: Sperren Sie Ihr Konto unten. Dadurch werden neue Expensify Karte-Transaktionen, Kartenbestellungen und Kontenänderungen blockiert. Wenn Sie ein Domain-Admin sind, werden dadurch auch alle domänenweiten Kartenaktivitäten und Administratoraktionen pausiert.',
-        securityTeamFollowUp: 'Unser Sicherheitsteam meldet sich nach der Sperrung von <a href="mailto:risk@expensify.com">risk@expensify.com</a> bei Ihnen.',
+            '<a href="https://help.expensify.com/articles/expensify-classic/settings/Report-Suspicious-Activity">Unbefugter Kontozugriff</a>: Sperren Sie Ihr Konto unten. Dadurch werden neue Expensify Karte-Transaktionen, Kartenbestellungen und Kontenänderungen blockiert. Wenn Sie ein Domain-Admin sind, wird dadurch außerdem alle domänenweite Kartenaktivität und Administratoraktionen angehalten.',
+        securityTeamFollowUp: 'Unser Sicherheitsteam wird sich nach der Sperrung von <a href="mailto:risk@expensify.com">risk@expensify.com</a> bei Ihnen melden.',
         areYouSure: 'Möchtest du dein Expensify-Konto wirklich sperren?',
         onceLocked: 'Sobald Ihr Konto gesperrt ist, wird es eingeschränkt, bis eine Entsperrungsanfrage gestellt und eine Sicherheitsprüfung durchgeführt wurde',
         unlockTitle: 'Wir haben Ihre Anfrage erhalten',
diff --git a/src/languages/es.ts b/src/languages/es.ts
index 572ca5962223..ce131e498a70 100644
--- a/src/languages/es.ts
+++ b/src/languages/es.ts
@@ -2114,12 +2114,12 @@ const translations: TranslationDeepObject<typeof en> = {
         unlockAccount: 'Desbloquear cuenta',
         unlockTitle: 'Hemos recibido tu solicitud',
         unlockDescription: 'Revisaremos la cuenta para verificar que sea seguro desbloquearla y nos comunicaremos a través de Concierge si tenemos alguna pregunta.',
-        findYourSituation: '¡La mayoría de los problemas no requieren bloquear tu cuenta! Encuentra tu situación a continuación:',
+        findYourSituation: '¡La mayoría de los problemas no requieren bloquear tu cuenta! Busca tu situación a continuación:',
         lostCardOrCharges:
-            '<a href="https://help.expensify.com/articles/expensify-classic/expensify-card/Dispute-Transaction">Tarjeta perdida o cargos desconocidos</a>: Cancela tu tarjeta y contacta a Concierge para disputar transacciones desconocidas.',
+            '<a href="https://help.expensify.com/articles/expensify-classic/expensify-card/Dispute-Transaction">Tarjeta perdida o cargos desconocidos</a>: Cancela tu tarjeta y contacta con Concierge para disputar transacciones desconocidas.',
         unauthorizedAccess:
-            '<a href="https://help.expensify.com/articles/expensify-classic/settings/Report-Suspicious-Activity">Acceso no autorizado a la cuenta</a>: Bloquea tu cuenta a continuación. Esto bloquea nuevas transacciones con la Tarjeta Expensify, pedidos de tarjetas y cambios en la cuenta. Si eres administrador de dominio, esto también detiene toda la actividad de tarjetas y las acciones administrativas en todo el dominio.',
-        securityTeamFollowUp: 'Nuestro equipo de seguridad se pondrá en contacto desde <a href="mailto:risk@expensify.com">risk@expensify.com</a> después del bloqueo.',
+            '<a href="https://help.expensify.com/articles/expensify-classic/settings/Report-Suspicious-Activity">Acceso no autorizado a la cuenta</a>: Bloquea tu cuenta abajo. Esto bloquea nuevas transacciones con la Tarjeta Expensify, pedidos de tarjetas y cambios en la cuenta. Si eres administrador de dominio, esto también pausa toda la actividad de tarjetas y las acciones de administrador en todo el dominio.',
+        securityTeamFollowUp: 'Nuestro equipo de seguridad hará un seguimiento desde <a href="mailto:risk@expensify.com">risk@expensify.com</a> después del bloqueo.',
         areYouSure: '¿Estás seguro de que deseas bloquear tu cuenta de Expensify?',
         onceLocked: 'Una vez bloqueada, tu cuenta estará restringida hasta que se solicite el desbloqueo y se realice una revisión de seguridad.',
     },
diff --git a/src/languages/fr.ts b/src/languages/fr.ts
index 6fb97dc70042..dc65ee94f897 100644
--- a/src/languages/fr.ts
+++ b/src/languages/fr.ts
@@ -2236,8 +2236,8 @@ const translations: TranslationDeepObject<typeof en> = {
         lostCardOrCharges:
             '<a href="https://help.expensify.com/articles/expensify-classic/expensify-card/Dispute-Transaction">Carte perdue ou frais inconnus</a> : Annulez votre carte et contactez Concierge pour contester les transactions inconnues.',
         unauthorizedAccess:
-            '<a href="https://help.expensify.com/articles/expensify-classic/settings/Report-Suspicious-Activity">Accès non autorisé au compte</a> : Verrouillez votre compte ci-dessous. Cela bloque les nouvelles transactions avec la Carte Expensify, les commandes de carte et les modifications du compte. Si vous êtes administrateur de domaine, cela met également en pause toute l’activité de carte et toutes les actions d’administration à l’échelle du domaine.',
-        securityTeamFollowUp: 'Notre équipe de sécurité vous contactera depuis <a href="mailto:risk@expensify.com">risk@expensify.com</a> après le verrouillage.',
+            '<a href="https://help.expensify.com/articles/expensify-classic/settings/Report-Suspicious-Activity">Accès non autorisé au compte</a> : Verrouillez votre compte ci-dessous. Cela bloque les nouvelles transactions Carte Expensify, les commandes de carte et les modifications de compte. Si vous êtes administrateur de domaine, cela met également en pause toute l’activité de carte au niveau du domaine et les actions des administrateurs.',
+        securityTeamFollowUp: 'Notre équipe de sécurité effectuera un suivi depuis <a href="mailto:risk@expensify.com">risk@expensify.com</a> après le verrouillage.',
         areYouSure: 'Voulez-vous vraiment verrouiller votre compte Expensify ?',
         onceLocked: 'Une fois verrouillé, votre compte sera restreint en attendant une demande de déverrouillage et un contrôle de sécurité',
         unlockTitle: 'Nous avons bien reçu votre demande',
diff --git a/src/languages/it.ts b/src/languages/it.ts
index 832122317fdc..ae3789f03ed8 100644
--- a/src/languages/it.ts
+++ b/src/languages/it.ts
@@ -2226,10 +2226,10 @@ const translations: TranslationDeepObject<typeof en> = {
         unlockAccount: 'Sblocca conto',
         findYourSituation: 'La maggior parte dei problemi non richiede il blocco del tuo account! Trova la tua situazione qui sotto:',
         lostCardOrCharges:
-            '<a href="https://help.expensify.com/articles/expensify-classic/expensify-card/Dispute-Transaction">Carta smarrita o addebiti sconosciuti</a>: Annulla la tua carta e contatta Concierge per contestare le transazioni sconosciute.',
+            '<a href="https://help.expensify.com/articles/expensify-classic/expensify-card/Dispute-Transaction">Carta smarrita o addebiti non riconosciuti</a>: Annulla la tua carta e contatta Concierge per contestare le transazioni sconosciute.',
         unauthorizedAccess:
-            '<a href="https://help.expensify.com/articles/expensify-classic/settings/Report-Suspicious-Activity">Accesso non autorizzato all’account</a>: Blocca il tuo account qui sotto. Questo blocca le nuove transazioni con la Carta Expensify, gli ordini di carte e le modifiche all’account. Se sei un amministratore di dominio, questo mette anche in pausa tutta l’attività della carta e le azioni di amministratore in tutto il dominio.',
-        securityTeamFollowUp: 'Il nostro team di sicurezza ti contatterà da <a href="mailto:risk@expensify.com">risk@expensify.com</a> dopo il blocco.',
+            '<a href="https://help.expensify.com/articles/expensify-classic/settings/Report-Suspicious-Activity">Accesso non autorizzato all’account</a>: Blocca il tuo account qui sotto. Questo blocca le nuove transazioni con la Carta Expensify, gli ordini di carte e le modifiche all’account. Se sei un amministratore di dominio, sospende anche tutta l’attività delle carte a livello di dominio e le azioni amministrative.',
+        securityTeamFollowUp: 'Il nostro team di sicurezza ti ricontatterà da <a href="mailto:risk@expensify.com">risk@expensify.com</a> dopo il blocco.',
         areYouSure: 'Sei sicuro di voler bloccare il tuo account Expensify?',
         onceLocked: 'Una volta bloccato, il tuo account sarà limitato in attesa di una richiesta di sblocco e di una revisione di sicurezza',
         unlockTitle: 'Abbiamo ricevuto la tua richiesta',
diff --git a/src/languages/ja.ts b/src/languages/ja.ts
index 520a4bad7003..627318989fe5 100644
--- a/src/languages/ja.ts
+++ b/src/languages/ja.ts
@@ -2201,14 +2201,14 @@ const translations: TranslationDeepObject<typeof en> = {
     lockAccountPage: {
         reportSuspiciousActivity: '不審な行為を報告',
         lockAccount: 'アカウントをロック',
-        lockMyAccount: '自分のアカウントをロック',
+        lockMyAccount: 'アカウントをロックする',
         unlockAccount: 'アカウントのロック解除',
-        findYourSituation: 'ほとんどの問題はアカウントのロックを必要としません。以下からご自身の状況を見つけてください：',
+        findYourSituation: 'ほとんどの問題ではアカウントをロックする必要はありません。以下からご自身の状況をお探しください。',
         lostCardOrCharges:
-            '<a href="https://help.expensify.com/articles/expensify-classic/expensify-card/Dispute-Transaction">カードの紛失または不明な請求</a>：カードをキャンセルし、Conciergeに連絡して不明な取引に異議を申し立ててください。',
+            '<a href="https://help.expensify.com/articles/expensify-classic/expensify-card/Dispute-Transaction">カードの紛失または身に覚えのない請求</a>：カードを解約し、不明な取引について異議申し立てをするために Concierge へご連絡ください。',
         unauthorizedAccess:
-            '<a href="https://help.expensify.com/articles/expensify-classic/settings/Report-Suspicious-Activity">アカウントへの不正アクセス</a>：以下からアカウントをロックしてください。これにより、新しい Expensify カードの取引、カードの注文、アカウントの変更がブロックされます。ドメイン管理者の場合、ドメイン全体のすべてのカード利用と管理者による操作も一時停止されます。',
-        securityTeamFollowUp: '当社のセキュリティチームがロック後に <a href="mailto:risk@expensify.com">risk@expensify.com</a> からご連絡します。',
+            '<a href="https://help.expensify.com/articles/expensify-classic/settings/Report-Suspicious-Activity">不正なアカウントアクセス</a>：以下からアカウントをロックしてください。これにより、新しい Expensify カードの利用、カードの発行依頼、およびアカウントの変更ができなくなります。ドメイン管理者の場合、ドメイン全体のカードアクティビティと管理者アクションも一時停止されます。',
+        securityTeamFollowUp: 'ロック後、セキュリティチームが<a href="mailto:risk@expensify.com">risk@expensify.com</a>からご連絡します。',
         areYouSure: 'Expensify アカウントをロックしてもよろしいですか？',
         onceLocked: 'ロックされると、解除リクエストとセキュリティ審査が完了するまでアカウントは制限されます',
         unlockTitle: 'リクエストを受け付けました',
diff --git a/src/languages/nl.ts b/src/languages/nl.ts
index 5f6f10a0f56f..15ebe86af63c 100644
--- a/src/languages/nl.ts
+++ b/src/languages/nl.ts
@@ -2218,14 +2218,14 @@ const translations: TranslationDeepObject<typeof en> = {
     lockAccountPage: {
         reportSuspiciousActivity: 'Verdachte activiteit melden',
         lockAccount: 'Account vergrendelen',
-        lockMyAccount: 'Mijn account vergrendelen',
+        lockMyAccount: 'Account vergrendelen',
         unlockAccount: 'Account ontgrendelen',
-        findYourSituation: 'De meeste problemen vereisen geen vergrendeling van je account! Vind hieronder jouw situatie:',
+        findYourSituation: 'Voor de meeste problemen hoef je je account niet te blokkeren. Zoek hieronder jouw situatie:',
         lostCardOrCharges:
-            '<a href="https://help.expensify.com/articles/expensify-classic/expensify-card/Dispute-Transaction">Verloren kaart of onbekende kosten</a>: Annuleer je kaart en neem contact op met Concierge om onbekende transacties te betwisten.',
+            '<a href="https://help.expensify.com/articles/expensify-classic/expensify-card/Dispute-Transaction">Kaart kwijt of onbekende kosten</a>: Annuleer je kaart en neem contact op met Concierge om onbekende transacties te betwisten.',
         unauthorizedAccess:
-            '<a href="https://help.expensify.com/articles/expensify-classic/settings/Report-Suspicious-Activity">Ongeautoriseerde accounttoegang</a>: Vergrendel hieronder je account. Dit blokkeert nieuwe Expensify Kaart-transacties, kaartbestellingen en accountwijzigingen. Als je een domeinbeheerder bent, pauzeert dit ook alle Expensify Kaart-activiteit en beheerdersacties in je hele domein.',
-        securityTeamFollowUp: 'Ons beveiligingsteam neemt na het vergrendelen contact op via <a href="mailto:risk@expensify.com">risk@expensify.com</a>.',
+            '<a href="https://help.expensify.com/articles/expensify-classic/settings/Report-Suspicious-Activity">Onbevoegde accounttoegang</a>: Vergrendel hieronder je account. Dit blokkeert nieuwe Expensify Kaart-transacties, kaartbestellingen en accountwijzigingen. Als je domeinbeheerder bent, pauzeert dit ook alle domeinbrede kaartactiviteiten en beheerdersacties.',
+        securityTeamFollowUp: 'Ons beveiligingsteam neemt na het blokkeren contact met je op vanaf <a href="mailto:risk@expensify.com">risk@expensify.com</a>.',
         areYouSure: 'Weet je zeker dat je je Expensify-account wilt vergrendelen?',
         onceLocked: 'Zodra deze wordt vergrendeld, wordt je account beperkt in afwachting van een deblokkeringsverzoek en een beveiligingscontrole',
         unlockTitle: 'We hebben je verzoek ontvangen',
diff --git a/src/languages/pl.ts b/src/languages/pl.ts
index 55b7d9d54a80..ec796d1b8aa8 100644
--- a/src/languages/pl.ts
+++ b/src/languages/pl.ts
@@ -2222,10 +2222,10 @@ const translations: TranslationDeepObject<typeof en> = {
         unlockAccount: 'Odblokuj konto',
         findYourSituation: 'Większość problemów nie wymaga blokowania konta! Znajdź swoją sytuację poniżej:',
         lostCardOrCharges:
-            '<a href="https://help.expensify.com/articles/expensify-classic/expensify-card/Dispute-Transaction">Zgubiona karta lub nieznane obciążenia</a>: Anuluj swoją kartę i skontaktuj się z Concierge, aby zakwestionować nieznane transakcje.',
+            '<a href="https://help.expensify.com/articles/expensify-classic/expensify-card/Dispute-Transaction">Zgubiona karta lub nieznane obciążenia</a>: Anuluj swoją kartę i skontaktuj się z Concierge, żeby zakwestionować nieznane transakcje.',
         unauthorizedAccess:
-            '<a href="https://help.expensify.com/articles/expensify-classic/settings/Report-Suspicious-Activity">Nieautoryzowany dostęp do konta</a>: Zablokuj swoje konto poniżej. Blokuje to nowe transakcje Kartą Expensify, zamówienia kart i zmiany na koncie. Jeśli jesteś administratorem domeny, wstrzymuje to również całą aktywność kart i działania administracyjne w całej domenie.',
-        securityTeamFollowUp: 'Nasz zespół ds. bezpieczeństwa skontaktuje się po zablokowaniu z adresu <a href="mailto:risk@expensify.com">risk@expensify.com</a>.',
+            '<a href="https://help.expensify.com/articles/expensify-classic/settings/Report-Suspicious-Activity">Nieautoryzowany dostęp do konta</a>: Zablokuj swoje konto poniżej. To zablokuje nowe transakcje Kartą Expensify, zamówienia kart i zmiany na koncie. Jeśli jesteś administratorem domeny, to wstrzyma też całą aktywność kart i działania administratorów w obrębie domeny.',
+        securityTeamFollowUp: 'Nasz zespół ds. bezpieczeństwa skontaktuje się z tobą z adresu <a href="mailto:risk@expensify.com">risk@expensify.com</a> po zablokowaniu.',
         areYouSure: 'Czy na pewno chcesz zablokować swoje konto Expensify?',
         onceLocked: 'Po zablokowaniu Twoje konto będzie ograniczone do czasu złożenia prośby o odblokowanie i przeprowadzenia kontroli bezpieczeństwa',
         unlockTitle: 'Otrzymaliśmy Twoją prośbę',
diff --git a/src/languages/pt-BR.ts b/src/languages/pt-BR.ts
index 7c283cdc84ce..9b98483ab764 100644
--- a/src/languages/pt-BR.ts
+++ b/src/languages/pt-BR.ts
@@ -2217,12 +2217,12 @@ const translations: TranslationDeepObject<typeof en> = {
         lockAccount: 'Bloquear conta',
         lockMyAccount: 'Bloquear minha conta',
         unlockAccount: 'Desbloquear conta',
-        findYourSituation: 'A maioria dos problemas não exige o bloqueio da sua conta! Encontre a sua situação abaixo:',
+        findYourSituation: 'A maioria dos problemas não exige bloquear sua conta! Encontre sua situação abaixo:',
         lostCardOrCharges:
-            '<a href="https://help.expensify.com/articles/expensify-classic/expensify-card/Dispute-Transaction">Cartão perdido ou cobranças desconhecidas</a>: Cancele seu cartão e entre em contato com o Concierge para contestar transações desconhecidas.',
+            '<a href="https://help.expensify.com/articles/expensify-classic/expensify-card/Dispute-Transaction">Cartão perdido ou cobranças desconhecidas</a>: Cancele seu cartão e contate o Concierge para contestar transações desconhecidas.',
         unauthorizedAccess:
-            '<a href="https://help.expensify.com/articles/expensify-classic/settings/Report-Suspicious-Activity">Acesso não autorizado à conta</a>: Bloqueie sua conta abaixo. Isso impede novas transações com o Cartão Expensify, pedidos de cartão e alterações na conta. Se você for um admin de domínio, isso também pausa toda a atividade de cartão e ações de administração em todo o domínio.',
-        securityTeamFollowUp: 'Nossa equipe de segurança entrará em contato pelo <a href="mailto:risk@expensify.com">risk@expensify.com</a> após o bloqueio.',
+            '<a href="https://help.expensify.com/articles/expensify-classic/settings/Report-Suspicious-Activity">Acesso não autorizado à conta</a>: Bloqueie sua conta abaixo. Isso bloqueia novas transações com o Cartão Expensify, pedidos de cartão e alterações na conta. Se você for admin de domínio, isso também pausa toda a atividade de cartões em todo o domínio e as ações de admin.',
+        securityTeamFollowUp: 'Nossa equipe de segurança vai entrar em contato a partir de <a href="mailto:risk@expensify.com">risk@expensify.com</a> após o bloqueio.',
         areYouSure: 'Tem certeza de que deseja bloquear sua conta Expensify?',
         onceLocked: 'Depois de bloqueada, sua conta ficará restrita até que seja feita uma solicitação de desbloqueio e uma revisão de segurança',
         unlockTitle: 'Recebemos sua solicitação',
diff --git a/src/languages/zh-hans.ts b/src/languages/zh-hans.ts
index 91a76bddb963..837b356d2302 100644
--- a/src/languages/zh-hans.ts
+++ b/src/languages/zh-hans.ts
@@ -2162,12 +2162,12 @@ const translations: TranslationDeepObject<typeof en> = {
         lockAccount: '锁定账户',
         lockMyAccount: '锁定我的账户',
         unlockAccount: '解锁账户',
-        findYourSituation: '大多数问题无需锁定账户！请在下方找到您的情况：',
+        findYourSituation: '大多数问题都不需要锁定你的账户！请在以下列表中找到与你相符的情况：',
         lostCardOrCharges:
-            '<a href="https://help.expensify.com/articles/expensify-classic/expensify-card/Dispute-Transaction">卡片丢失或陌生扣款</a>：取消您的卡片并联系 Concierge 以对未知交易提出争议。',
+            '<a href="https://help.expensify.com/articles/expensify-classic/expensify-card/Dispute-Transaction">卡片遗失或出现不明扣款</a>：请挂失您的卡片，并联系 Concierge 申诉未知交易。',
         unauthorizedAccess:
-            '<a href="https://help.expensify.com/articles/expensify-classic/settings/Report-Suspicious-Activity">账户未经授权的访问</a>：在下方锁定您的账户。这会阻止新的 Expensify 卡交易、卡片订购和账户更改。如果您是域管理员，这还会暂停整个域中的所有卡活动和管理员操作。',
-        securityTeamFollowUp: '我们的安全团队将在锁定后通过 <a href="mailto:risk@expensify.com">risk@expensify.com</a> 与您联系。',
+            '<a href="https://help.expensify.com/articles/expensify-classic/settings/Report-Suspicious-Activity">未经授权的账号访问</a>：请在下方锁定你的账号。这将阻止新的 Expensify 卡交易、卡片申请和账号更改。如果你是域管理员，这也会暂停整个域的所有卡片活动和管理员操作。',
+        securityTeamFollowUp: '锁定后，我们的安全团队将通过 <a href="mailto:risk@expensify.com">risk@expensify.com</a> 与您后续联系。',
         areYouSure: '你确定要锁定你的 Expensify 账户吗？',
         onceLocked: '一旦被锁定，您的账户将受到限制，直至提交解锁请求并完成安全审查',
         unlockTitle: '我们已收到您的请求',

From ca9428840426b9d39d387a2ac0863940c3425919 Mon Sep 17 00:00:00 2001
From: Nicolas Bonet <nicolas@expensify.com>
Date: Mon, 8 Jun 2026 16:37:00 -0500
Subject: [PATCH 319/435] Enhance AI rule structure: Add optional title field
 for server-generated summaries and update prompt display logic in
 AIRulesSection. This change allows for a more descriptive title to be shown,
 improving clarity for users.

---
 src/pages/workspace/rules/AIRulesSection.tsx | 2 +-
 src/types/onyx/Policy.ts                     | 3 +++
 2 files changed, 4 insertions(+), 1 deletion(-)

diff --git a/src/pages/workspace/rules/AIRulesSection.tsx b/src/pages/workspace/rules/AIRulesSection.tsx
index e2f2929ac86f..e32b389aae5c 100644
--- a/src/pages/workspace/rules/AIRulesSection.tsx
+++ b/src/pages/workspace/rules/AIRulesSection.tsx
@@ -78,7 +78,7 @@ function AIRulesSection({policyID, canWriteRules, showReadOnlyModal}: AIRulesSec
                                     onClose={() => clearPolicyAIRuleErrors(policyID, rule.ruleID, rule)}
                                 >
                                     <MenuItemWithTopDescription
-                                        title={rule.prompt.replaceAll(/\s+/g, ' ').trim()}
+                                        title={(rule.title || rule.prompt).replace(/\s+/g, ' ').trim()}
                                         numberOfLinesTitle={1}
                                         wrapperStyle={[styles.borderedContentCard, styles.ph4, styles.pv4]}
                                         shouldShowRightIcon
diff --git a/src/types/onyx/Policy.ts b/src/types/onyx/Policy.ts
index bed2edb0e752..50c1a23057b7 100644
--- a/src/types/onyx/Policy.ts
+++ b/src/types/onyx/Policy.ts
@@ -2052,6 +2052,9 @@ type AIRule = {
     /** The AI prompt (i.e. the rule defined with natural language) */
     prompt: string;
 
+    /** Short one-line summary generated server-side from the prompt */
+    title?: string;
+
     /** When this rule was created */
     created: string;
 

From 08019cdb927ccb7f3e3f0001fe1a0e16d8ad01ae Mon Sep 17 00:00:00 2001
From: Nicolas Bonet <nicolas@expensify.com>
Date: Tue, 9 Jun 2026 10:35:16 -0500
Subject: [PATCH 320/435] Update title handling in AIRulesSection: Replace
 `rule.title` with `rule.title ?? rule.prompt` to ensure a fallback to prompt
 when title is not available, enhancing user clarity.

---
 src/pages/workspace/rules/AIRulesSection.tsx | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/pages/workspace/rules/AIRulesSection.tsx b/src/pages/workspace/rules/AIRulesSection.tsx
index e32b389aae5c..24c9a01d5036 100644
--- a/src/pages/workspace/rules/AIRulesSection.tsx
+++ b/src/pages/workspace/rules/AIRulesSection.tsx
@@ -78,7 +78,7 @@ function AIRulesSection({policyID, canWriteRules, showReadOnlyModal}: AIRulesSec
                                     onClose={() => clearPolicyAIRuleErrors(policyID, rule.ruleID, rule)}
                                 >
                                     <MenuItemWithTopDescription
-                                        title={(rule.title || rule.prompt).replace(/\s+/g, ' ').trim()}
+                                        title={(rule.title ?? rule.prompt).replaceAll(/\s+/g, ' ').trim()}
                                         numberOfLinesTitle={1}
                                         wrapperStyle={[styles.borderedContentCard, styles.ph4, styles.pv4]}
                                         shouldShowRightIcon

From 9dbf62eb280740007484aa0e1388a8f76443fa06 Mon Sep 17 00:00:00 2001
From: Nicolas Bonet <nicolas@expensify.com>
Date: Tue, 9 Jun 2026 10:51:02 -0500
Subject: [PATCH 321/435] Add AIRulesSection component tests

Cover title/prompt fallback, whitespace normalization, sort order,
pending-delete visibility online vs offline, and rule item / add
button navigation paths.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
---
 tests/ui/AIRulesSectionTest.tsx | 292 ++++++++++++++++++++++++++++++++
 1 file changed, 292 insertions(+)
 create mode 100644 tests/ui/AIRulesSectionTest.tsx

diff --git a/tests/ui/AIRulesSectionTest.tsx b/tests/ui/AIRulesSectionTest.tsx
new file mode 100644
index 000000000000..d998a31767b2
--- /dev/null
+++ b/tests/ui/AIRulesSectionTest.tsx
@@ -0,0 +1,292 @@
+import {render} from '@testing-library/react-native';
+import React from 'react';
+import MenuItem from '@components/MenuItem';
+import MenuItemWithTopDescription from '@components/MenuItemWithTopDescription';
+import useNetwork from '@hooks/useNetwork';
+import usePolicy from '@hooks/usePolicy';
+import Navigation from '@libs/Navigation/Navigation';
+import AIRulesSection from '@pages/workspace/rules/AIRulesSection';
+import CONST from '@src/CONST';
+import ROUTES from '@src/ROUTES';
+
+jest.mock('@components/Badge', () => jest.fn(() => null));
+jest.mock('@components/MenuItem', () => jest.fn(() => null));
+jest.mock('@components/MenuItemWithTopDescription', () => jest.fn(() => null));
+jest.mock(
+    '@components/OfflineWithFeedback',
+    () =>
+        ({children}: {children: React.ReactNode}) =>
+            children,
+);
+jest.mock(
+    '@components/Section',
+    () =>
+        ({children}: {children: React.ReactNode}) =>
+            children,
+);
+jest.mock('@components/Text', () => jest.fn(() => null));
+
+jest.mock('@hooks/useLazyAsset', () => ({
+    useMemoizedLazyExpensifyIcons: jest.fn(() => ({Plus: null})),
+}));
+jest.mock('@hooks/useLocalize', () =>
+    jest.fn(() => ({
+        translate: (key: string) => key,
+    })),
+);
+jest.mock('@hooks/useNetwork', () => jest.fn(() => ({isOffline: false})));
+jest.mock('@hooks/usePolicy', () => jest.fn());
+jest.mock('@hooks/useTheme', () => jest.fn(() => ({text: '#000'})));
+jest.mock('@hooks/useThemeStyles', () =>
+    jest.fn(
+        () =>
+            new Proxy(
+                {},
+                {
+                    get: () => ({}),
+                },
+            ),
+    ),
+);
+
+jest.mock('@libs/Navigation/Navigation', () => ({
+    navigate: jest.fn(),
+}));
+
+jest.mock('@userActions/Policy/Rules', () => ({
+    clearPolicyAIRuleErrors: jest.fn(),
+}));
+
+const mockedUsePolicy = jest.mocked(usePolicy);
+const mockedUseNetwork = jest.mocked(useNetwork);
+const mockedMenuItemWithTopDescription = jest.mocked(MenuItemWithTopDescription);
+const mockedMenuItem = jest.mocked(MenuItem);
+const mockedNavigate = jest.mocked(Navigation.navigate);
+
+const POLICY_ID = 'POLICY_ID_1';
+
+function setPolicyAIRules(aiRules: Record<string, unknown> | undefined) {
+    mockedUsePolicy.mockReturnValue({rules: {aiRules}} as ReturnType<typeof usePolicy>);
+}
+
+function getRuleTitles(): string[] {
+    return mockedMenuItemWithTopDescription.mock.calls.map((call) => call.at(0)?.title as string);
+}
+
+describe('AIRulesSection', () => {
+    beforeEach(() => {
+        jest.clearAllMocks();
+        mockedUseNetwork.mockReturnValue({isOffline: false} as ReturnType<typeof useNetwork>);
+    });
+
+    describe('title rendering', () => {
+        it('uses rule.title when set', () => {
+            setPolicyAIRules({
+                r1: {ruleID: 'r1', prompt: 'Long prompt text', title: 'Short title', created: '2026-01-01 00:00:00'},
+            });
+
+            render(
+                <AIRulesSection
+                    policyID={POLICY_ID}
+                    canWriteRules
+                    showReadOnlyModal={jest.fn()}
+                />,
+            );
+
+            expect(getRuleTitles()).toEqual(['Short title']);
+        });
+
+        it('falls back to rule.prompt when title is missing', () => {
+            setPolicyAIRules({
+                r1: {ruleID: 'r1', prompt: 'Prompt only', created: '2026-01-01 00:00:00'},
+            });
+
+            render(
+                <AIRulesSection
+                    policyID={POLICY_ID}
+                    canWriteRules
+                    showReadOnlyModal={jest.fn()}
+                />,
+            );
+
+            expect(getRuleTitles()).toEqual(['Prompt only']);
+        });
+
+        it('collapses whitespace and trims', () => {
+            setPolicyAIRules({
+                r1: {ruleID: 'r1', prompt: '  hello\n\n  world  \t!  ', created: '2026-01-01 00:00:00'},
+            });
+
+            render(
+                <AIRulesSection
+                    policyID={POLICY_ID}
+                    canWriteRules
+                    showReadOnlyModal={jest.fn()}
+                />,
+            );
+
+            expect(getRuleTitles()).toEqual(['hello world !']);
+        });
+    });
+
+    describe('rule list filtering and sorting', () => {
+        it('sorts rules by created desc', () => {
+            setPolicyAIRules({
+                r1: {ruleID: 'r1', prompt: 'first', title: 'A', created: '2026-01-01 00:00:00'},
+                r2: {ruleID: 'r2', prompt: 'second', title: 'B', created: '2026-02-01 00:00:00'},
+                r3: {ruleID: 'r3', prompt: 'third', title: 'C', created: '2026-03-01 00:00:00'},
+            });
+
+            render(
+                <AIRulesSection
+                    policyID={POLICY_ID}
+                    canWriteRules
+                    showReadOnlyModal={jest.fn()}
+                />,
+            );
+
+            expect(getRuleTitles()).toEqual(['C', 'B', 'A']);
+        });
+
+        it('hides pending-delete rules when online', () => {
+            setPolicyAIRules({
+                r1: {ruleID: 'r1', prompt: 'keep', title: 'Keep', created: '2026-01-01 00:00:00'},
+                r2: {
+                    ruleID: 'r2',
+                    prompt: 'goner',
+                    title: 'Goner',
+                    created: '2026-02-01 00:00:00',
+                    pendingAction: CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE,
+                },
+            });
+
+            render(
+                <AIRulesSection
+                    policyID={POLICY_ID}
+                    canWriteRules
+                    showReadOnlyModal={jest.fn()}
+                />,
+            );
+
+            expect(getRuleTitles()).toEqual(['Keep']);
+        });
+
+        it('keeps pending-delete rules when offline so OfflineWithFeedback can style them', () => {
+            mockedUseNetwork.mockReturnValue({isOffline: true} as ReturnType<typeof useNetwork>);
+            setPolicyAIRules({
+                r1: {ruleID: 'r1', prompt: 'keep', title: 'Keep', created: '2026-01-01 00:00:00'},
+                r2: {
+                    ruleID: 'r2',
+                    prompt: 'goner',
+                    title: 'Goner',
+                    created: '2026-02-01 00:00:00',
+                    pendingAction: CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE,
+                },
+            });
+
+            render(
+                <AIRulesSection
+                    policyID={POLICY_ID}
+                    canWriteRules
+                    showReadOnlyModal={jest.fn()}
+                />,
+            );
+
+            expect(getRuleTitles()).toEqual(['Goner', 'Keep']);
+        });
+
+        it('renders no rule items when policy has none', () => {
+            setPolicyAIRules(undefined);
+
+            render(
+                <AIRulesSection
+                    policyID={POLICY_ID}
+                    canWriteRules
+                    showReadOnlyModal={jest.fn()}
+                />,
+            );
+
+            expect(mockedMenuItemWithTopDescription).not.toHaveBeenCalled();
+        });
+    });
+
+    describe('add rule button', () => {
+        it('navigates to RULES_AI_NEW when user has write access', () => {
+            setPolicyAIRules(undefined);
+
+            render(
+                <AIRulesSection
+                    policyID={POLICY_ID}
+                    canWriteRules
+                    showReadOnlyModal={jest.fn()}
+                />,
+            );
+
+            const onPress = mockedMenuItem.mock.calls.at(0)?.at(0)?.onPress;
+            onPress?.({} as never);
+
+            expect(mockedNavigate).toHaveBeenCalledWith(ROUTES.RULES_AI_NEW.getRoute(POLICY_ID));
+        });
+
+        it('calls showReadOnlyModal when user lacks write access', () => {
+            const showReadOnlyModal = jest.fn();
+            setPolicyAIRules(undefined);
+
+            render(
+                <AIRulesSection
+                    policyID={POLICY_ID}
+                    canWriteRules={false}
+                    showReadOnlyModal={showReadOnlyModal}
+                />,
+            );
+
+            const onPress = mockedMenuItem.mock.calls.at(0)?.at(0)?.onPress;
+            onPress?.({} as never);
+
+            expect(showReadOnlyModal).toHaveBeenCalledTimes(1);
+            expect(mockedNavigate).not.toHaveBeenCalled();
+        });
+    });
+
+    describe('rule item press', () => {
+        it('navigates to RULES_AI_EDIT when user has write access', () => {
+            setPolicyAIRules({
+                r1: {ruleID: 'r1', prompt: 'p', title: 'T', created: '2026-01-01 00:00:00'},
+            });
+
+            render(
+                <AIRulesSection
+                    policyID={POLICY_ID}
+                    canWriteRules
+                    showReadOnlyModal={jest.fn()}
+                />,
+            );
+
+            const onPress = mockedMenuItemWithTopDescription.mock.calls.at(0)?.at(0)?.onPress;
+            onPress?.({} as never);
+
+            expect(mockedNavigate).toHaveBeenCalledWith(ROUTES.RULES_AI_EDIT.getRoute(POLICY_ID, 'r1'));
+        });
+
+        it('calls showReadOnlyModal when user lacks write access', () => {
+            const showReadOnlyModal = jest.fn();
+            setPolicyAIRules({
+                r1: {ruleID: 'r1', prompt: 'p', title: 'T', created: '2026-01-01 00:00:00'},
+            });
+
+            render(
+                <AIRulesSection
+                    policyID={POLICY_ID}
+                    canWriteRules={false}
+                    showReadOnlyModal={showReadOnlyModal}
+                />,
+            );
+
+            const onPress = mockedMenuItemWithTopDescription.mock.calls.at(0)?.at(0)?.onPress;
+            onPress?.({} as never);
+
+            expect(showReadOnlyModal).toHaveBeenCalledTimes(1);
+            expect(mockedNavigate).not.toHaveBeenCalled();
+        });
+    });
+});

From 4d76e27a5d004927aa23dac82ec4f43194882f01 Mon Sep 17 00:00:00 2001
From: Nicolas Bonet <nicolas@expensify.com>
Date: Tue, 9 Jun 2026 11:26:05 -0500
Subject: [PATCH 322/435] Fix lint errors in AIRulesSection tests

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
---
 tests/ui/AIRulesSectionTest.tsx | 14 ++++++++------
 1 file changed, 8 insertions(+), 6 deletions(-)

diff --git a/tests/ui/AIRulesSectionTest.tsx b/tests/ui/AIRulesSectionTest.tsx
index d998a31767b2..7bbc4e913b2f 100644
--- a/tests/ui/AIRulesSectionTest.tsx
+++ b/tests/ui/AIRulesSectionTest.tsx
@@ -66,13 +66,15 @@ const mockedNavigate = jest.mocked(Navigation.navigate);
 const POLICY_ID = 'POLICY_ID_1';
 
 function setPolicyAIRules(aiRules: Record<string, unknown> | undefined) {
-    mockedUsePolicy.mockReturnValue({rules: {aiRules}} as ReturnType<typeof usePolicy>);
+    (mockedUsePolicy as jest.Mock).mockReturnValue({rules: {aiRules}});
 }
 
 function getRuleTitles(): string[] {
-    return mockedMenuItemWithTopDescription.mock.calls.map((call) => call.at(0)?.title as string);
+    return mockedMenuItemWithTopDescription.mock.calls.map((call) => String(call.at(0)?.title ?? ''));
 }
 
+const mockKeyboardEvent = new KeyboardEvent('keydown');
+
 describe('AIRulesSection', () => {
     beforeEach(() => {
         jest.clearAllMocks();
@@ -223,7 +225,7 @@ describe('AIRulesSection', () => {
             );
 
             const onPress = mockedMenuItem.mock.calls.at(0)?.at(0)?.onPress;
-            onPress?.({} as never);
+            onPress?.(mockKeyboardEvent);
 
             expect(mockedNavigate).toHaveBeenCalledWith(ROUTES.RULES_AI_NEW.getRoute(POLICY_ID));
         });
@@ -241,7 +243,7 @@ describe('AIRulesSection', () => {
             );
 
             const onPress = mockedMenuItem.mock.calls.at(0)?.at(0)?.onPress;
-            onPress?.({} as never);
+            onPress?.(mockKeyboardEvent);
 
             expect(showReadOnlyModal).toHaveBeenCalledTimes(1);
             expect(mockedNavigate).not.toHaveBeenCalled();
@@ -263,7 +265,7 @@ describe('AIRulesSection', () => {
             );
 
             const onPress = mockedMenuItemWithTopDescription.mock.calls.at(0)?.at(0)?.onPress;
-            onPress?.({} as never);
+            onPress?.(mockKeyboardEvent);
 
             expect(mockedNavigate).toHaveBeenCalledWith(ROUTES.RULES_AI_EDIT.getRoute(POLICY_ID, 'r1'));
         });
@@ -283,7 +285,7 @@ describe('AIRulesSection', () => {
             );
 
             const onPress = mockedMenuItemWithTopDescription.mock.calls.at(0)?.at(0)?.onPress;
-            onPress?.({} as never);
+            onPress?.(mockKeyboardEvent);
 
             expect(showReadOnlyModal).toHaveBeenCalledTimes(1);
             expect(mockedNavigate).not.toHaveBeenCalled();

From 2869e0de9f2a6558944d8022474710b9587b58be Mon Sep 17 00:00:00 2001
From: "Carlos Alvarez (via MelvinBot)" <infra+melvinbot@expensify.com>
Date: Wed, 10 Jun 2026 22:25:01 +0000
Subject: [PATCH 323/435] Replace forEach with for...of to satisfy
 unicorn/no-array-for-each

Co-authored-by: Carlos Alvarez <cead22@users.noreply.github.com>
---
 src/libs/OptionsListUtils/index.ts | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/libs/OptionsListUtils/index.ts b/src/libs/OptionsListUtils/index.ts
index e643b7da8faf..1b62e516661c 100644
--- a/src/libs/OptionsListUtils/index.ts
+++ b/src/libs/OptionsListUtils/index.ts
@@ -2600,12 +2600,12 @@ function getValidOptions(
 
         // Build the exclusion set from the recent attendees actually shown (after filtering and the cap) so that
         // attendees that aren't displayed in "Recent" remain available in "Contacts".
-        recentReportOptions.forEach((option) => {
+        for (const option of recentReportOptions) {
             const login = option.login ?? option.displayName;
             if (login) {
                 loginsToExcludeFromSuggestions[login] = true;
             }
-        });
+        }
     }
 
     // Get valid personal details and check if we can find the current user:

From 31a49fe36f024be2fce967d172f11f5cc4bbdbde Mon Sep 17 00:00:00 2001
From: rory <rory@expensify.com>
Date: Wed, 10 Jun 2026 17:50:45 -0700
Subject: [PATCH 324/435] Remove eslint rule suppressions dropped from base
 config

Bump eslint-config-expensify to 3.0.3 and remove local overrides for
no-async-await and no-continue now that they are no longer in the base.

Co-authored-by: Cursor <cursoragent@cursor.com>
---
 config/eslint/eslint.config.mjs | 3 ---
 package-lock.json               | 9 ++++-----
 package.json                    | 2 +-
 3 files changed, 5 insertions(+), 9 deletions(-)

diff --git a/config/eslint/eslint.config.mjs b/config/eslint/eslint.config.mjs
index f41e62edc95c..c2c7737ec53b 100644
--- a/config/eslint/eslint.config.mjs
+++ b/config/eslint/eslint.config.mjs
@@ -255,8 +255,6 @@ const config = defineConfig([
 
         files: ['**/*.ts', '**/*.tsx', '**/*.js', '**/*.jsx', '**/*.mjs', '**/*.cjs'],
         rules: {
-            '@lwc/lwc/no-async-await': 'off',
-
             // TypeScript specific rules
             '@typescript-eslint/prefer-enum-initializers': 'error',
             '@typescript-eslint/no-var-requires': 'off',
@@ -336,7 +334,6 @@ const config = defineConfig([
             'es/no-optional-chaining': 'off',
             '@typescript-eslint/no-deprecated': ['error', {allow: ['translateFn']}],
             'arrow-body-style': 'off',
-            'no-continue': 'off',
             'no-empty': ['error', {allowEmptyCatch: true}],
 
             // Import specific rules
diff --git a/package-lock.json b/package-lock.json
index 620ab9bee353..6fcba0338694 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -243,7 +243,7 @@
         "dotenv": "^16.0.3",
         "eslint": "^9.36.0",
         "eslint-config-airbnb-typescript": "^18.0.0",
-        "eslint-config-expensify": "3.0.2",
+        "eslint-config-expensify": "3.0.3",
         "eslint-config-prettier": "^9.1.0",
         "eslint-plugin-file-progress": "3.0.1",
         "eslint-plugin-jest": "^29.0.1",
@@ -23200,14 +23200,13 @@
       }
     },
     "node_modules/eslint-config-expensify": {
-      "version": "3.0.2",
-      "resolved": "https://registry.npmjs.org/eslint-config-expensify/-/eslint-config-expensify-3.0.2.tgz",
-      "integrity": "sha512-ulH1Gl3Uu2fh0E918Rt2R76nMidY1BuxezBBtT20+v2K8O/bFs5v83oX1cwvg3Kz97anhf64aqpA2h2KIG8p9w==",
+      "version": "3.0.3",
+      "resolved": "https://registry.npmjs.org/eslint-config-expensify/-/eslint-config-expensify-3.0.3.tgz",
+      "integrity": "sha512-xPsrTYCE/6AthZ5rIyXCh5HjNdUXNrDnfpz3AoUmbepTAa6XS51ulZjuyoyGnAfy092RLuKi2dXgOZLmkHN1CA==",
       "dev": true,
       "license": "ISC",
       "dependencies": {
         "@babel/eslint-parser": "^7.28.4",
-        "@lwc/eslint-plugin-lwc": "^3.2.0",
         "@typescript-eslint/parser": "^8.44.1",
         "@typescript-eslint/utils": "^8.44.1",
         "confusing-browser-globals": "^1.0.11",
diff --git a/package.json b/package.json
index a6238f2779c4..b614df99d706 100644
--- a/package.json
+++ b/package.json
@@ -316,7 +316,7 @@
     "dotenv": "^16.0.3",
     "eslint": "^9.36.0",
     "eslint-config-airbnb-typescript": "^18.0.0",
-    "eslint-config-expensify": "3.0.2",
+    "eslint-config-expensify": "3.0.3",
     "eslint-config-prettier": "^9.1.0",
     "eslint-plugin-file-progress": "3.0.1",
     "eslint-plugin-jest": "^29.0.1",

From a648786912d1199845ea92dc969e7e966b2f887a Mon Sep 17 00:00:00 2001
From: krishna2323 <belivethatkg@gmail.com>
Date: Thu, 11 Jun 2026 06:57:22 +0530
Subject: [PATCH 325/435] Address PR review comments: improve type safety and
 code quality

Signed-off-by: krishna2323 <belivethatkg@gmail.com>
---
 .../ListItem/GroupChildrenContent.tsx         |  8 +--
 .../SearchList/ListItem/GroupHeader.tsx       | 70 +++++++------------
 .../Search/SearchList/ListItem/types.ts       | 35 ++++++++--
 src/components/Search/SearchList/index.tsx    | 33 +++++----
 src/hooks/useExpandCollapseAnimation.ts       |  9 ++-
 src/libs/SearchUIUtils.ts                     |  5 +-
 6 files changed, 85 insertions(+), 75 deletions(-)

diff --git a/src/components/Search/SearchList/ListItem/GroupChildrenContent.tsx b/src/components/Search/SearchList/ListItem/GroupChildrenContent.tsx
index afd7cde2d870..6f876082cd80 100644
--- a/src/components/Search/SearchList/ListItem/GroupChildrenContent.tsx
+++ b/src/components/Search/SearchList/ListItem/GroupChildrenContent.tsx
@@ -14,7 +14,7 @@ import CONST from '@src/CONST';
 import ONYXKEYS from '@src/ONYXKEYS';
 import type {Transaction, TransactionViolation, TransactionViolations} from '@src/types/onyx';
 import TransactionGroupListExpandedItem from './TransactionGroupListExpanded';
-import type {GroupChildrenContentProps, SearchListItem, TransactionGroupListItemType, TransactionListItemType} from './types';
+import type {GroupChildrenContentProps, TransactionListItemType} from './types';
 
 function GroupChildrenContent({
     item,
@@ -40,11 +40,11 @@ function GroupChildrenContent({
     const {convertToDisplayString} = useCurrencyListActions();
     const {isOffline} = useNetwork();
 
-    const groupItem = item as unknown as TransactionGroupListItemType;
+    const groupItem = item;
     const isExpenseReportType = searchType === CONST.SEARCH.DATA_TYPES.EXPENSE_REPORT;
 
     const [transactionsSnapshot] = useOnyx(`${ONYXKEYS.COLLECTION.SNAPSHOT}${groupItem.transactionsQueryJSON?.hash}`);
-    const [transactionsVisibleLimit, setTransactionsVisibleLimit] = useState(CONST.TRANSACTION.RESULTS_PAGE_SIZE as number);
+    const [transactionsVisibleLimit, setTransactionsVisibleLimit] = useState<number>(CONST.TRANSACTION.RESULTS_PAGE_SIZE);
     const isActionLoadingSet = useActionLoadingReportIDs();
     const snapshotData = transactionsSnapshot?.data;
 
@@ -192,7 +192,7 @@ function GroupChildrenContent({
     }, [snapshotData, currentUserDetails.email]);
 
     const onExpandedRowLongPress = (transaction: TransactionListItemType) => {
-        onLongPressRow?.(transaction as unknown as SearchListItem);
+        onLongPressRow?.(transaction);
     };
 
     return (
diff --git a/src/components/Search/SearchList/ListItem/GroupHeader.tsx b/src/components/Search/SearchList/ListItem/GroupHeader.tsx
index 40bd7af409a8..8278d168344c 100644
--- a/src/components/Search/SearchList/ListItem/GroupHeader.tsx
+++ b/src/components/Search/SearchList/ListItem/GroupHeader.tsx
@@ -30,7 +30,7 @@ import {getColumnsToShow} from '@libs/SearchUIUtils';
 import {isDeletedTransaction} from '@libs/TransactionUtils';
 import CONST from '@src/CONST';
 import ONYXKEYS from '@src/ONYXKEYS';
-import type {ReportAction, ReportActions} from '@src/types/onyx';
+import type {ReportAction, ReportActions, Transaction} from '@src/types/onyx';
 import type {SearchDataTypes} from '@src/types/onyx/SearchResults';
 import CardListItemHeader from './CardListItemHeader';
 import CategoryListItemHeader from './CategoryListItemHeader';
@@ -40,24 +40,7 @@ import MonthListItemHeader from './MonthListItemHeader';
 import QuarterListItemHeader from './QuarterListItemHeader';
 import ReportListItemHeader from './ReportListItemHeader';
 import TagListItemHeader from './TagListItemHeader';
-import type {
-    GroupHeaderItemType,
-    SearchListActionProps,
-    SearchListItem,
-    TransactionCardGroupListItemType,
-    TransactionCategoryGroupListItemType,
-    TransactionGroupListItemType,
-    TransactionListItemType,
-    TransactionMemberGroupListItemType,
-    TransactionMerchantGroupListItemType,
-    TransactionMonthGroupListItemType,
-    TransactionQuarterGroupListItemType,
-    TransactionReportGroupListItemType,
-    TransactionTagGroupListItemType,
-    TransactionWeekGroupListItemType,
-    TransactionWithdrawalIDGroupListItemType,
-    TransactionYearGroupListItemType,
-} from './types';
+import type {GroupHeaderItemType, SearchListActionProps, SearchListItem, TransactionListItemType} from './types';
 import WeekListItemHeader from './WeekListItemHeader';
 import WithdrawalIDListItemHeader from './WithdrawalIDListItemHeader';
 import YearListItemHeader from './YearListItemHeader';
@@ -111,7 +94,7 @@ function GroupHeader({
     const expensifyIcons = useMemoizedLazyExpensifyIcons(['UpArrow', 'DownArrow']);
     const currentUserDetails = useCurrentUserPersonalDetails();
 
-    const groupItem = item as unknown as TransactionGroupListItemType;
+    const groupItem = item;
     const isExpenseReportType = searchType === CONST.SEARCH.DATA_TYPES.EXPENSE_REPORT;
 
     const oneTransactionItem = groupItem.isOneTransactionReport ? groupItem.transactions.at(0) : undefined;
@@ -184,10 +167,6 @@ function GroupHeader({
     const isDisabled = item.pendingAction === CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE;
     const isDisabledOrEmpty = isEmpty || isDisabled;
 
-    // For non-expense-report groups, children are loaded from the snapshot
-    // rather than groupItem.transactions (which may be empty). Extract
-    // minimal transaction items from the snapshot so selection and
-    // long-press handlers operate on the actual visible children.
     const effectiveTransactions = useMemo((): TransactionListItemType[] => {
         if (isExpenseReportType || groupItem.transactions.length > 0) {
             return groupItem.transactions;
@@ -196,18 +175,19 @@ function GroupHeader({
             return [];
         }
         const items: TransactionListItemType[] = [];
-        for (const [key, value] of Object.entries(snapshotData)) {
+        for (const key of Object.keys(snapshotData)) {
             if (!key.startsWith(ONYXKEYS.COLLECTION.TRANSACTION)) {
                 continue;
             }
-            const tx = value as Record<string, unknown>;
-            if (!tx || typeof tx !== 'object' || !('transactionID' in tx)) {
+            const tx = snapshotData[key as keyof typeof snapshotData];
+            if (!tx || typeof tx !== 'object' || !('transactionID' in tx) || !('reportID' in tx)) {
                 continue;
             }
-            const report = snapshotData[`${ONYXKEYS.COLLECTION.REPORT}${tx.reportID as string}`] as TransactionListItemType['report'];
+            const transaction = tx as Transaction;
+            const report = snapshotData[`${ONYXKEYS.COLLECTION.REPORT}${transaction.reportID}`];
             items.push({
-                ...tx,
-                keyForList: tx.transactionID as string,
+                ...transaction,
+                keyForList: transaction.transactionID,
                 report,
             } as TransactionListItemType);
         }
@@ -217,7 +197,7 @@ function GroupHeader({
     const {isSelectAllChecked, isIndeterminate} = useMemo(() => {
         const selectedTransactionIDsSet = new Set(Object.keys(selectedTransactions));
         const filteredTransactions = effectiveTransactions.filter((transaction) => transaction.pendingAction !== CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE);
-        const selectedCount = effectiveTransactions.reduce((acc, transaction) => (selectedTransactionIDsSet.has(transaction.transactionID) ? acc + 1 : acc), 0);
+        const selectedCount = filteredTransactions.reduce((acc, transaction) => (selectedTransactionIDsSet.has(transaction.transactionID) ? acc + 1 : acc), 0);
         const isEmptyReportSelected = isEmpty && item.keyForList && selectedTransactions[item.keyForList]?.isSelected;
         const allChecked = !!isEmptyReportSelected || (selectedCount === filteredTransactions.length && filteredTransactions.length > 0);
         const indeterminate = selectedCount > 0 && selectedCount !== filteredTransactions.length;
@@ -248,10 +228,10 @@ function GroupHeader({
     };
 
     const renderHeader = (hovered: boolean) => {
-        if (isExpenseReportType) {
+        if (isExpenseReportType && 'groupedBy' in groupItem && groupItem.groupedBy === CONST.SEARCH.DATA_TYPES.EXPENSE_REPORT) {
             return (
                 <ReportListItemHeader
-                    report={groupItem as TransactionReportGroupListItemType}
+                    report={groupItem}
                     onSelectRow={handleSelectRow}
                     onCheckboxPress={handleSelectionButtonPress}
                     isDisabled={isDisabled}
@@ -270,7 +250,7 @@ function GroupHeader({
             );
         }
 
-        if (!groupBy) {
+        if (!('groupedBy' in groupItem)) {
             return null;
         }
 
@@ -285,11 +265,11 @@ function GroupHeader({
             isExpanded,
         } as const;
 
-        switch (groupBy) {
+        switch (groupItem.groupedBy) {
             case CONST.SEARCH.GROUP_BY.FROM:
                 return (
                     <MemberListItemHeader
-                        member={groupItem as TransactionMemberGroupListItemType}
+                        member={groupItem}
                         {...commonProps}
                         isLargeScreenWidth={isLargeScreenWidth}
                     />
@@ -297,7 +277,7 @@ function GroupHeader({
             case CONST.SEARCH.GROUP_BY.CARD:
                 return (
                     <CardListItemHeader
-                        card={groupItem as TransactionCardGroupListItemType}
+                        card={groupItem}
                         {...commonProps}
                         isFocused={isFocused}
                     />
@@ -305,56 +285,56 @@ function GroupHeader({
             case CONST.SEARCH.GROUP_BY.WITHDRAWAL_ID:
                 return (
                     <WithdrawalIDListItemHeader
-                        withdrawalID={groupItem as TransactionWithdrawalIDGroupListItemType}
+                        withdrawalID={groupItem}
                         {...commonProps}
                     />
                 );
             case CONST.SEARCH.GROUP_BY.CATEGORY:
                 return (
                     <CategoryListItemHeader
-                        category={groupItem as TransactionCategoryGroupListItemType}
+                        category={groupItem}
                         {...commonProps}
                     />
                 );
             case CONST.SEARCH.GROUP_BY.MERCHANT:
                 return (
                     <MerchantListItemHeader
-                        merchant={groupItem as TransactionMerchantGroupListItemType}
+                        merchant={groupItem}
                         {...commonProps}
                     />
                 );
             case CONST.SEARCH.GROUP_BY.TAG:
                 return (
                     <TagListItemHeader
-                        tag={groupItem as TransactionTagGroupListItemType}
+                        tag={groupItem}
                         {...commonProps}
                     />
                 );
             case CONST.SEARCH.GROUP_BY.MONTH:
                 return (
                     <MonthListItemHeader
-                        month={groupItem as TransactionMonthGroupListItemType}
+                        month={groupItem}
                         {...commonProps}
                     />
                 );
             case CONST.SEARCH.GROUP_BY.WEEK:
                 return (
                     <WeekListItemHeader
-                        week={groupItem as TransactionWeekGroupListItemType}
+                        week={groupItem}
                         {...commonProps}
                     />
                 );
             case CONST.SEARCH.GROUP_BY.YEAR:
                 return (
                     <YearListItemHeader
-                        year={groupItem as TransactionYearGroupListItemType}
+                        year={groupItem}
                         {...commonProps}
                     />
                 );
             case CONST.SEARCH.GROUP_BY.QUARTER:
                 return (
                     <QuarterListItemHeader
-                        quarter={groupItem as TransactionQuarterGroupListItemType}
+                        quarter={groupItem}
                         {...commonProps}
                     />
                 );
diff --git a/src/components/Search/SearchList/ListItem/types.ts b/src/components/Search/SearchList/ListItem/types.ts
index b0c7cd3c498b..b1c4c0f4ccd9 100644
--- a/src/components/Search/SearchList/ListItem/types.ts
+++ b/src/components/Search/SearchList/ListItem/types.ts
@@ -485,14 +485,39 @@ type TransactionGroupListExpandedProps<TItem extends ListItem> = Pick<
     hideSearchTableHeader?: boolean;
 };
 
-type GroupHeaderItemType = TransactionGroupListItemType & {
-    listItemType: 'group_header';
-};
+const GROUP_ITEM_TYPES = {
+    GROUP_HEADER: 'group_header',
+    CHILDREN_CONTAINER: 'children_container',
+} as const;
+
+type GroupHeaderListItemType = {listItemType: typeof GROUP_ITEM_TYPES.GROUP_HEADER};
+
+type GroupHeaderItemType =
+    | (TransactionReportGroupListItemType & GroupHeaderListItemType)
+    | (TransactionMemberGroupListItemType & GroupHeaderListItemType)
+    | (TransactionCardGroupListItemType & GroupHeaderListItemType)
+    | (TransactionWithdrawalIDGroupListItemType & GroupHeaderListItemType)
+    | (TransactionCategoryGroupListItemType & GroupHeaderListItemType)
+    | (TransactionMerchantGroupListItemType & GroupHeaderListItemType)
+    | (TransactionTagGroupListItemType & GroupHeaderListItemType)
+    | (TransactionMonthGroupListItemType & GroupHeaderListItemType)
+    | (TransactionWeekGroupListItemType & GroupHeaderListItemType)
+    | (TransactionYearGroupListItemType & GroupHeaderListItemType)
+    | (TransactionQuarterGroupListItemType & GroupHeaderListItemType)
+    | (TransactionGroupListItemType & GroupHeaderListItemType);
 
 type GroupChildrenContainerItemType = TransactionGroupListItemType & {
-    listItemType: 'children_container';
+    listItemType: typeof GROUP_ITEM_TYPES.CHILDREN_CONTAINER;
 };
 
+function isGroupHeaderItem(item: SearchListItem): item is GroupHeaderItemType {
+    return 'listItemType' in item && item.listItemType === GROUP_ITEM_TYPES.GROUP_HEADER;
+}
+
+function isGroupChildrenContainerItem(item: SearchListItem): item is GroupChildrenContainerItemType {
+    return 'listItemType' in item && item.listItemType === GROUP_ITEM_TYPES.CHILDREN_CONTAINER;
+}
+
 type GroupChildrenContentProps = {
     item: GroupChildrenContainerItemType;
     isExpanded: boolean;
@@ -547,3 +572,5 @@ export type {
     GroupChildrenContainerItemType,
     GroupChildrenContentProps,
 };
+
+export {GROUP_ITEM_TYPES, isGroupHeaderItem, isGroupChildrenContainerItem};
diff --git a/src/components/Search/SearchList/index.tsx b/src/components/Search/SearchList/index.tsx
index 96e1c3d6bb77..071db27d01f3 100644
--- a/src/components/Search/SearchList/index.tsx
+++ b/src/components/Search/SearchList/index.tsx
@@ -44,8 +44,6 @@ import type TaskListItem from './ListItem/TaskListItem';
 import type TransactionGroupListItem from './ListItem/TransactionGroupListItem';
 import type TransactionListItem from './ListItem/TransactionListItem';
 import type {
-    GroupChildrenContainerItemType,
-    GroupHeaderItemType,
     ReportActionListItemType,
     TaskListItemType,
     TransactionCardGroupListItemType,
@@ -58,6 +56,7 @@ import type {
     TransactionWeekGroupListItemType,
     TransactionYearGroupListItemType,
 } from './ListItem/types';
+import {isGroupChildrenContainerItem, isGroupHeaderItem} from './ListItem/types';
 import SearchSelectAllMenu from './SearchSelectAllMenu';
 
 const easing = Easing.bezier(0.76, 0.0, 0.24, 1.0);
@@ -329,17 +328,21 @@ function SearchList({
         return {splitData, stickyHeaderIndices: activeIndices.length > 0 ? activeIndices : undefined};
     }, [data, shouldSplitGroups, expandedGroups]);
 
-    const getItemType = useMemo(() => {
-        if (!shouldSplitGroups) {
-            return undefined;
-        }
-        return (item: SearchListItem) => {
-            if ('listItemType' in item) {
-                return (item as GroupHeaderItemType | GroupChildrenContainerItemType).listItemType;
+    const getItemType = useCallback(
+        (item: SearchListItem) => {
+            if (!shouldSplitGroups) {
+                return undefined;
+            }
+            if (isGroupHeaderItem(item)) {
+                return item.listItemType;
+            }
+            if (isGroupChildrenContainerItem(item)) {
+                return item.listItemType;
             }
             return 'default';
-        };
-    }, [shouldSplitGroups]);
+        },
+        [shouldSplitGroups],
+    );
 
     const [lastPaymentMethod] = useOnyx(ONYXKEYS.NVP_LAST_PAYMENT_METHOD);
     const [personalPolicyID] = useOnyx(ONYXKEYS.PERSONAL_POLICY_ID);
@@ -485,8 +488,8 @@ function SearchList({
     const renderItem = useCallback(
         (item: SearchListItem, index: number, isItemFocused: boolean, onFocus?: (event: NativeSyntheticEvent<ExtendedTargetedEvent>) => void) => {
             // Handle group header items (sticky)
-            if ('listItemType' in item && (item as GroupHeaderItemType).listItemType === 'group_header') {
-                const headerItem = item as GroupHeaderItemType;
+            if (isGroupHeaderItem(item)) {
+                const headerItem = item;
                 const originalKey = (item.keyForList ?? '').replace('header_', '');
                 return (
                     <GroupHeader
@@ -521,8 +524,8 @@ function SearchList({
             }
 
             // Handle children container items (animated expand/collapse)
-            if ('listItemType' in item && (item as GroupChildrenContainerItemType).listItemType === 'children_container') {
-                const containerItem = item as GroupChildrenContainerItemType;
+            if (isGroupChildrenContainerItem(item)) {
+                const containerItem = item;
                 const originalKey = (item.keyForList ?? '').replace('children_', '');
                 const containerNewTransactionID = item.keyForList ? newTransactionIDByItemKey.get(originalKey) : undefined;
                 const isContainerSelected =
diff --git a/src/hooks/useExpandCollapseAnimation.ts b/src/hooks/useExpandCollapseAnimation.ts
index 101fbf05d7ad..d770efa8eb11 100644
--- a/src/hooks/useExpandCollapseAnimation.ts
+++ b/src/hooks/useExpandCollapseAnimation.ts
@@ -1,4 +1,4 @@
-import {useEffect, useState} from 'react';
+import {useState} from 'react';
 import type {LayoutChangeEvent} from 'react-native';
 import {useAnimatedStyle, useDerivedValue, useSharedValue, withTiming} from 'react-native-reanimated';
 import {scheduleOnRN} from 'react-native-worklets';
@@ -11,10 +11,9 @@ function useExpandCollapseAnimation(isExpanded: boolean) {
     const hasExpanded = useSharedValue(isExpanded);
     const [isRendered, setIsRendered] = useState(isExpanded);
 
-    useEffect(() => {
-        hasExpanded.set(isExpanded);
-    }, [isExpanded, hasExpanded]);
-
+    hasExpanded.set(isExpanded);
+    // Matches the pattern in AnimatedCollapsible — mount content synchronously on expand,
+    // unmount asynchronously after collapse animation via scheduleOnRN callback.
     if (isExpanded && !isRendered) {
         setIsRendered(true);
     }
diff --git a/src/libs/SearchUIUtils.ts b/src/libs/SearchUIUtils.ts
index bbdaccb9d41c..c21b00229715 100644
--- a/src/libs/SearchUIUtils.ts
+++ b/src/libs/SearchUIUtils.ts
@@ -36,6 +36,7 @@ import type {
     TransactionWithdrawalIDGroupListItemType,
     TransactionYearGroupListItemType,
 } from '@components/Search/SearchList/ListItem/types';
+import {GROUP_ITEM_TYPES} from '@components/Search/SearchList/ListItem/types';
 import type {
     GroupedItem,
     QueryFilters,
@@ -6218,8 +6219,8 @@ function splitGroupsIntoPairs(data: SearchListItem[]): {splitData: SearchListIte
         if ('transactions' in item) {
             const key = item.keyForList ?? '';
             stickyHeaderIndices.push(splitData.length);
-            splitData.push({...item, listItemType: 'group_header', keyForList: `header_${key}`} as GroupHeaderItemType);
-            splitData.push({...item, listItemType: 'children_container', keyForList: `children_${key}`} as GroupChildrenContainerItemType);
+            splitData.push({...item, listItemType: GROUP_ITEM_TYPES.GROUP_HEADER, keyForList: `header_${key}`} as GroupHeaderItemType);
+            splitData.push({...item, listItemType: GROUP_ITEM_TYPES.CHILDREN_CONTAINER, keyForList: `children_${key}`} as GroupChildrenContainerItemType);
         } else {
             splitData.push(item);
         }

From 284bad9902250b613e24d5e56f1e51e10a70c562 Mon Sep 17 00:00:00 2001
From: krishna2323 <belivethatkg@gmail.com>
Date: Thu, 11 Jun 2026 07:37:38 +0530
Subject: [PATCH 326/435] Simplify effectiveTransactions type narrowing in
 GroupHeader

Signed-off-by: krishna2323 <belivethatkg@gmail.com>
---
 src/components/Search/SearchList/ListItem/GroupHeader.tsx | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/src/components/Search/SearchList/ListItem/GroupHeader.tsx b/src/components/Search/SearchList/ListItem/GroupHeader.tsx
index 8278d168344c..0f39e8d32728 100644
--- a/src/components/Search/SearchList/ListItem/GroupHeader.tsx
+++ b/src/components/Search/SearchList/ListItem/GroupHeader.tsx
@@ -179,11 +179,10 @@ function GroupHeader({
             if (!key.startsWith(ONYXKEYS.COLLECTION.TRANSACTION)) {
                 continue;
             }
-            const tx = snapshotData[key as keyof typeof snapshotData];
-            if (!tx || typeof tx !== 'object' || !('transactionID' in tx) || !('reportID' in tx)) {
+            const transaction = snapshotData[key as keyof typeof snapshotData] as Transaction;
+            if (!transaction?.transactionID) {
                 continue;
             }
-            const transaction = tx as Transaction;
             const report = snapshotData[`${ONYXKEYS.COLLECTION.REPORT}${transaction.reportID}`];
             items.push({
                 ...transaction,

From a98eb7a8176b470f8dd4215e31941211f91f526b Mon Sep 17 00:00:00 2001
From: krishna2323 <belivethatkg@gmail.com>
Date: Thu, 11 Jun 2026 07:38:01 +0530
Subject: [PATCH 327/435] remove as const.

Signed-off-by: krishna2323 <belivethatkg@gmail.com>
---
 src/hooks/useExpandCollapseAnimation.ts | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/hooks/useExpandCollapseAnimation.ts b/src/hooks/useExpandCollapseAnimation.ts
index d770efa8eb11..7fca790c5444 100644
--- a/src/hooks/useExpandCollapseAnimation.ts
+++ b/src/hooks/useExpandCollapseAnimation.ts
@@ -33,7 +33,7 @@ function useExpandCollapseAnimation(isExpanded: boolean) {
 
     const animatedStyle = useAnimatedStyle(() => ({
         height: animatedHeight.get(),
-        overflow: 'hidden' as const,
+        overflow: 'hidden',
     }));
 
     const onLayout = (e: LayoutChangeEvent) => {

From b2a8b73f9af4e30ea3eb8f9877dfc8b4e646418d Mon Sep 17 00:00:00 2001
From: krishna2323 <belivethatkg@gmail.com>
Date: Thu, 11 Jun 2026 07:44:41 +0530
Subject: [PATCH 328/435] Fix empty-report selection state using originalKey
 prop

Signed-off-by: krishna2323 <belivethatkg@gmail.com>
---
 src/components/Search/SearchList/ListItem/GroupHeader.tsx | 6 ++++--
 src/components/Search/SearchList/index.tsx                | 1 +
 2 files changed, 5 insertions(+), 2 deletions(-)

diff --git a/src/components/Search/SearchList/ListItem/GroupHeader.tsx b/src/components/Search/SearchList/ListItem/GroupHeader.tsx
index 0f39e8d32728..8a63181e8c27 100644
--- a/src/components/Search/SearchList/ListItem/GroupHeader.tsx
+++ b/src/components/Search/SearchList/ListItem/GroupHeader.tsx
@@ -61,6 +61,7 @@ type GroupHeaderProps = SearchListActionProps & {
     isFocused?: boolean;
     isFirstItem: boolean;
     isLastItem: boolean;
+    originalKey: string;
     visibleColumns?: SearchCustomColumnIds[];
 };
 
@@ -80,6 +81,7 @@ function GroupHeader({
     isFocused,
     isFirstItem,
     isLastItem,
+    originalKey,
     lastPaymentMethod,
     personalPolicyID,
     userBillingGracePeriodEnds,
@@ -197,11 +199,11 @@ function GroupHeader({
         const selectedTransactionIDsSet = new Set(Object.keys(selectedTransactions));
         const filteredTransactions = effectiveTransactions.filter((transaction) => transaction.pendingAction !== CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE);
         const selectedCount = filteredTransactions.reduce((acc, transaction) => (selectedTransactionIDsSet.has(transaction.transactionID) ? acc + 1 : acc), 0);
-        const isEmptyReportSelected = isEmpty && item.keyForList && selectedTransactions[item.keyForList]?.isSelected;
+        const isEmptyReportSelected = isEmpty && originalKey && selectedTransactions[originalKey]?.isSelected;
         const allChecked = !!isEmptyReportSelected || (selectedCount === filteredTransactions.length && filteredTransactions.length > 0);
         const indeterminate = selectedCount > 0 && selectedCount !== filteredTransactions.length;
         return {isSelectAllChecked: allChecked, isIndeterminate: indeterminate};
-    }, [selectedTransactions, effectiveTransactions, isEmpty, item.keyForList]);
+    }, [selectedTransactions, effectiveTransactions, isEmpty, originalKey]);
 
     const isItemSelected = isSelectAllChecked || item?.isSelected;
 
diff --git a/src/components/Search/SearchList/index.tsx b/src/components/Search/SearchList/index.tsx
index 071db27d01f3..88b42c13775c 100644
--- a/src/components/Search/SearchList/index.tsx
+++ b/src/components/Search/SearchList/index.tsx
@@ -514,6 +514,7 @@ function SearchList({
                         isFocused={isItemFocused}
                         isFirstItem={index === firstVisibleIndex}
                         isLastItem={index + 1 >= lastVisibleIndex && !ListFooterComponent}
+                        originalKey={originalKey}
                         lastPaymentMethod={lastPaymentMethod}
                         personalPolicyID={personalPolicyID}
                         userBillingGracePeriodEnds={userBillingGracePeriodEnds}

From 20aad57821b2dd14f416a438ac978cd49ca6fe3f Mon Sep 17 00:00:00 2001
From: rory <rory@expensify.com>
Date: Wed, 10 Jun 2026 19:28:37 -0700
Subject: [PATCH 329/435] Update eslint-seatbelt baseline for config bump

The eslint-config-expensify 3.0.3 upgrade invalidates the ESLint cache
and surfaces 16 additional no-unsafe-type-assertion violations in
ReportSecondaryActionUtilsTest. Update the seatbelt baseline accordingly.

Co-authored-by: Cursor <cursoragent@cursor.com>
---
 config/eslint/eslint.seatbelt.tsv | 20 +++++---------------
 1 file changed, 5 insertions(+), 15 deletions(-)

diff --git a/config/eslint/eslint.seatbelt.tsv b/config/eslint/eslint.seatbelt.tsv
index 57557c64e0ce..8866fc373521 100644
--- a/config/eslint/eslint.seatbelt.tsv
+++ b/config/eslint/eslint.seatbelt.tsv
@@ -450,7 +450,6 @@
 "../../src/components/TagPicker/index.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../src/components/TaxPicker.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../src/components/TestDrive/Modal/AdminTestDriveModal.tsx"	"no-restricted-imports"	1
-"../../src/components/TestDrive/Modal/EmployeeTestDriveModal.tsx"	"@typescript-eslint/no-deprecated/InteractionManager.runAfterInteractions"	1
 "../../src/components/TestDrive/TestDriveDemo.tsx"	"no-restricted-imports"	1
 "../../src/components/TextInput/BaseTextInput/implementation/index.native.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../src/components/TextInput/BaseTextInput/implementation/index.native.tsx"	"react-hooks/refs"	2
@@ -665,9 +664,8 @@
 "../../src/libs/Navigation/AppNavigator/Navigators/SettingsSplitNavigator.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../src/libs/Navigation/AppNavigator/Navigators/TabNavigator.native.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../src/libs/Navigation/AppNavigator/Navigators/TestToolsModalNavigator.tsx"	"no-restricted-syntax"	1
-"../../src/libs/Navigation/AppNavigator/Navigators/WorkspaceNavigator.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
-"../../src/libs/Navigation/AppNavigator/Navigators/WorkspaceSplitNavigator.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	2
-"../../src/libs/Navigation/AppNavigator/createRootStackNavigator/GetStateForActionHandlers.ts"	"@typescript-eslint/no-unsafe-type-assertion"	17
+"../../src/libs/Navigation/AppNavigator/Navigators/WorkspaceSplitNavigator.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
+"../../src/libs/Navigation/AppNavigator/createRootStackNavigator/GetStateForActionHandlers.ts"	"@typescript-eslint/no-unsafe-type-assertion"	15
 "../../src/libs/Navigation/AppNavigator/createRootStackNavigator/index.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../src/libs/Navigation/AppNavigator/createRootStackNavigator/useCustomRootStackNavigatorState/restoreTabNavigatorRoutes.ts"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../src/libs/Navigation/AppNavigator/createSplitNavigator/SplitRouter.ts"	"@typescript-eslint/no-unsafe-type-assertion"	4
@@ -688,7 +686,6 @@
 "../../src/libs/Navigation/guards/OnboardingGuard.ts"	"@typescript-eslint/no-unsafe-type-assertion"	2
 "../../src/libs/Navigation/helpers/createNormalizedConfigs.ts"	"@typescript-eslint/no-deprecated/escape"	1
 "../../src/libs/Navigation/helpers/createNormalizedConfigs.ts"	"@typescript-eslint/no-unsafe-type-assertion"	1
-"../../src/libs/Navigation/helpers/dismissModalAndOpenReportInInboxTab.ts"	"@typescript-eslint/no-deprecated/InteractionManager.runAfterInteractions"	1
 "../../src/libs/Navigation/helpers/dynamicRoutesUtils/createDynamicRoute.ts"	"@typescript-eslint/no-unsafe-type-assertion"	2
 "../../src/libs/Navigation/helpers/dynamicRoutesUtils/getDynamicRouteAdaptedState.ts"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../src/libs/Navigation/helpers/dynamicRoutesUtils/getDynamicRouteQueryParams.ts"	"@typescript-eslint/no-unsafe-type-assertion"	1
@@ -864,7 +861,6 @@
 "../../src/libs/actions/ImportTransactions.ts"	"no-restricted-syntax"	1
 "../../src/libs/actions/InputFocus/index.web.ts"	"no-restricted-imports"	1
 "../../src/libs/actions/InputFocus/index.web.ts"	"no-restricted-syntax"	1
-"../../src/libs/actions/Link.ts"	"@typescript-eslint/no-deprecated/InteractionManager.runAfterInteractions"	1
 "../../src/libs/actions/Link.ts"	"@typescript-eslint/no-unsafe-type-assertion"	4
 "../../src/libs/actions/Link.ts"	"no-restricted-syntax"	3
 "../../src/libs/actions/MapboxToken.ts"	"no-restricted-syntax"	2
@@ -908,7 +904,6 @@
 "../../src/libs/actions/ReimbursementAccount/resetNonUSDBankAccount.ts"	"no-restricted-syntax"	1
 "../../src/libs/actions/ReimbursementAccount/resetUSDBankAccount.ts"	"no-restricted-syntax"	1
 "../../src/libs/actions/Report/MarkAllMessageAsRead.tsx"	"no-restricted-syntax"	1
-"../../src/libs/actions/Report/index.ts"	"@typescript-eslint/no-deprecated/InteractionManager.runAfterInteractions"	1
 "../../src/libs/actions/Report/index.ts"	"@typescript-eslint/no-deprecated/buildNextStepNew"	3
 "../../src/libs/actions/Report/index.ts"	"@typescript-eslint/no-deprecated/reportAction.originalMessage"	1
 "../../src/libs/actions/Report/index.ts"	"@typescript-eslint/no-unsafe-type-assertion"	20
@@ -921,7 +916,6 @@
 "../../src/libs/actions/Search.ts"	"@typescript-eslint/no-unsafe-type-assertion"	19
 "../../src/libs/actions/Search.ts"	"no-restricted-syntax"	1
 "../../src/libs/actions/Session/index.ts"	"@typescript-eslint/no-unsafe-type-assertion"	3
-"../../src/libs/actions/Session/index.ts"	"no-restricted-imports"	1
 "../../src/libs/actions/Session/index.ts"	"no-restricted-syntax"	9
 "../../src/libs/actions/Session/index.ts"	"rulesdir/no-onyx-connect"	2
 "../../src/libs/actions/SplitExpenses.ts"	"@typescript-eslint/no-unsafe-type-assertion"	2
@@ -1298,7 +1292,6 @@
 "../../src/pages/signin/SignInPageLayout/FooterRow/index.native.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../src/pages/signin/ValidateCodeForm/BaseValidateCodeForm.tsx"	"react-hooks/set-state-in-effect"	4
 "../../src/pages/tasks/NewTaskPage.tsx"	"@typescript-eslint/no-deprecated/InteractionManager.runAfterInteractions"	1
-"../../src/pages/tasks/TaskAssigneeSelectorModal.tsx"	"@typescript-eslint/no-deprecated/InteractionManager.runAfterInteractions"	2
 "../../src/pages/tasks/TaskShareDestinationSelectorModal.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	2
 "../../src/pages/wallet/WalletStatementPage.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../src/pages/workspace/DynamicWorkspaceOverviewPlanTypePage.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	2
@@ -1420,7 +1413,6 @@
 "../../src/pages/workspace/copyPolicySettings/CopyPolicySettingsConfirmPage.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../src/pages/workspace/copyPolicySettings/CopyPolicySettingsSelectFeaturesPage.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	2
 "../../src/pages/workspace/distanceRates/PolicyDistanceRatesPage.tsx"	"react-hooks/preserve-manual-memoization"	1
-"../../src/pages/workspace/downgrade/WorkspaceDowngradePage.tsx"	"@typescript-eslint/no-deprecated/InteractionManager.runAfterInteractions"	1
 "../../src/pages/workspace/duplicate/WorkspaceDuplicateSelectFeaturesForm.tsx"	"react-hooks/preserve-manual-memoization"	2
 "../../src/pages/workspace/duplicate/WorkspaceDuplicateSelectFeaturesForm.tsx"	"react-hooks/set-state-in-effect"	1
 "../../src/pages/workspace/expensifyCard/DynamicExpensifyCardLimitTypePage.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
@@ -1437,7 +1429,6 @@
 "../../src/pages/workspace/members/ImportMembersPage.tsx"	"no-restricted-syntax"	1
 "../../src/pages/workspace/members/ImportMembersPage.tsx"	"rulesdir/no-default-id-values"	1
 "../../src/pages/workspace/members/ImportedMembersConfirmationPage.tsx"	"react-hooks/refs"	7
-"../../src/pages/workspace/members/ImportedMembersPage.tsx"	"@typescript-eslint/no-deprecated/InteractionManager.runAfterInteractions"	1
 "../../src/pages/workspace/members/WorkspaceInviteMessageComponent.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../src/pages/workspace/members/WorkspaceInviteMessageComponent.tsx"	"react-hooks/set-state-in-effect"	1
 "../../src/pages/workspace/members/WorkspaceMemberDetailsPage.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	4
@@ -1712,7 +1703,7 @@
 "../../tests/ui/components/SettlementButtonTest.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	3
 "../../tests/ui/components/TimePickerTest.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../tests/ui/hooks/useHtmlPasteTest/index.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	10
-"../../tests/unit/APITest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	74
+"../../tests/unit/APITest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	61
 "../../tests/unit/AddExistingExpenseSearchTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	6
 "../../tests/unit/AgentActionTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	61
 "../../tests/unit/AgentZeroStatusContextTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	5
@@ -1727,7 +1718,7 @@
 "../../tests/unit/CIGitLogicTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	5
 "../../tests/unit/CLIVariadicTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../tests/unit/CardFeedErrorsDerivedValueTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	1
-"../../tests/unit/CardFeedUtilsTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	16
+"../../tests/unit/CardFeedUtilsTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../tests/unit/CardUtilsTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	152
 "../../tests/unit/CardsSectionUtilsTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../tests/unit/CategoryUtilsTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	1
@@ -1818,7 +1809,7 @@
 "../../tests/unit/ReportLayoutUtilsTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../tests/unit/ReportNameUtilsTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	22
 "../../tests/unit/ReportPrimaryActionUtilsTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	168
-"../../tests/unit/ReportSecondaryActionUtilsTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	450
+"../../tests/unit/ReportSecondaryActionUtilsTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	466
 "../../tests/unit/ReportSubmitUtilsTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../tests/unit/ReportTitleUtilsTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	3
 "../../tests/unit/ReportUtilsGetIconsTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	1
@@ -1930,7 +1921,6 @@
 "../../tests/unit/hooks/useFreeTrial.test.ts"	"@typescript-eslint/no-unsafe-type-assertion"	8
 "../../tests/unit/hooks/useGettingStartedItems.test.ts"	"@typescript-eslint/no-unsafe-type-assertion"	11
 "../../tests/unit/hooks/useHasAnyAdminExpensifyCardFeed.test.ts"	"@typescript-eslint/no-unsafe-type-assertion"	1
-"../../tests/unit/hooks/useHoldRejectActionsTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../tests/unit/hooks/useIsAllowedToIssueCompanyCard.test.ts"	"@typescript-eslint/no-unsafe-type-assertion"	8
 "../../tests/unit/hooks/useIsBlockedToAddFeed.test.ts"	"@typescript-eslint/no-unsafe-type-assertion"	11
 "../../tests/unit/hooks/useIsSidebarRouteActive.test.ts"	"@typescript-eslint/no-unsafe-type-assertion"	2

From 2b8e1bf133ae0622495bd98b29a09c43e61b6574 Mon Sep 17 00:00:00 2001
From: Mohammad Luthfi Fathur Rahman <luthfi@expensify.com>
Date: Thu, 11 Jun 2026 10:36:23 +0700
Subject: [PATCH 330/435] Revert "Merge pull request #73887 from
 ShridharGoel/invoiceFields"

This reverts commit eb00765a2e53d721efb8533235cae438c96d53c0, reversing
changes made to 7c918556d6a7ed1670c94a108b0630145ae9d4f9.
---
 src/CONST/index.ts                            |  13 -
 src/ROUTES.ts                                 |  29 --
 src/SCREENS.ts                                |   7 -
 .../MoneyRequestViewReportFields.tsx          |   3 +-
 .../ReportActionItem/MoneyReportView.tsx      |   3 +-
 src/languages/de.ts                           |  30 --
 src/languages/en.ts                           |  30 --
 src/languages/es.ts                           |  30 --
 src/languages/fr.ts                           |  30 --
 src/languages/it.ts                           |  30 --
 src/languages/ja.ts                           |  30 --
 src/languages/nl.ts                           |  30 --
 src/languages/pl.ts                           |  30 --
 src/languages/pt-BR.ts                        |  30 --
 src/languages/zh-hans.ts                      |  30 --
 ...ateWorkspaceInvoiceFieldListValueParams.ts |  10 -
 .../CreateWorkspaceInvoiceFieldParams.ts      |  10 -
 .../parameters/DeletePolicyInvoiceField.ts    |  10 -
 .../EnablePolicyInvoiceFieldsParams.ts        |   6 -
 ...bleWorkspaceInvoiceFieldListValueParams.ts |  10 -
 ...oveWorkspaceInvoiceFieldListValueParams.ts |  10 -
 ...WorkspaceInvoiceFieldInitialValueParams.ts |  10 -
 src/libs/API/parameters/index.ts              |   7 -
 src/libs/API/types.ts                         |  16 -
 .../ModalStackNavigators/index.tsx            |   7 -
 .../RELATIONS/WORKSPACE_TO_RHP.ts             |  13 +-
 src/libs/Navigation/linkingConfig/config.ts   |  21 -
 src/libs/Navigation/types.ts                  |  28 --
 src/libs/ReportUtils.ts                       |  30 +-
 src/libs/WorkspaceReportFieldUtils.ts         |  36 +-
 src/libs/actions/Policy/Policy.ts             |  29 +-
 src/libs/actions/Policy/ReportField.ts        | 169 ++-----
 src/libs/actions/RequestConflictUtils.ts      |   1 -
 src/pages/DynamicEditReportFieldPage.tsx      |  11 +-
 .../workspace/fields/CreateFieldsPage.tsx     | 284 ------------
 .../fields/FieldsAddListValuePage.tsx         | 122 -----
 .../workspace/fields/FieldsEditValuePage.tsx  | 112 -----
 .../fields/FieldsInitialValuePage.tsx         | 171 -------
 .../workspace/fields/FieldsListValuesPage.tsx | 438 ------------------
 .../workspace/fields/FieldsSettingsPage.tsx   | 164 -------
 .../fields/FieldsValueSettingsPage.tsx        | 178 -------
 .../fields/WorkspaceFieldsSection.tsx         | 278 -----------
 .../invoices/CreateInvoiceFieldsPage.tsx      |  31 --
 .../InvoiceFieldsAddListValuePage.tsx         |  30 --
 .../invoices/InvoiceFieldsEditValuePage.tsx   |  30 --
 .../InvoiceFieldsInitialValuePage.tsx         |  30 --
 .../invoices/InvoiceFieldsListValuesPage.tsx  |  40 --
 .../invoices/InvoiceFieldsSettingsPage.tsx    |  36 --
 .../InvoiceFieldsValueSettingsPage.tsx        |  36 --
 .../WorkspaceInvoiceFieldsSection.tsx         |  42 --
 .../invoices/WorkspaceInvoicesPage.tsx        |   2 -
 .../reports/CreateReportFieldsPage.tsx        | 271 ++++++++++-
 .../reports/ReportFieldsAddListValuePage.tsx  | 102 +++-
 .../reports/ReportFieldsEditValuePage.tsx     |  95 +++-
 .../reports/ReportFieldsInitialValuePage.tsx  | 155 ++++++-
 .../reports/ReportFieldsListValuesPage.tsx    | 423 ++++++++++++++++-
 .../reports/ReportFieldsSettingsPage.tsx      | 126 ++++-
 .../reports/ReportFieldsValueSettingsPage.tsx | 156 ++++++-
 .../reports/WorkspaceReportsPage.tsx          | 212 +++++++--
 .../upgrade/WorkspaceUpgradePage.tsx          |   6 -
 src/pages/workspace/withPolicy.tsx            |  10 -
 src/types/onyx/Policy.ts                      |   3 -
 tests/actions/ReportFieldTest.ts              |  10 +-
 tests/unit/ReportUtilsTest.ts                 | 101 ----
 tests/unit/WorkspaceReportFieldUtilsTest.ts   |  74 +--
 65 files changed, 1522 insertions(+), 3035 deletions(-)
 delete mode 100644 src/libs/API/parameters/CreateWorkspaceInvoiceFieldListValueParams.ts
 delete mode 100644 src/libs/API/parameters/CreateWorkspaceInvoiceFieldParams.ts
 delete mode 100644 src/libs/API/parameters/DeletePolicyInvoiceField.ts
 delete mode 100644 src/libs/API/parameters/EnablePolicyInvoiceFieldsParams.ts
 delete mode 100644 src/libs/API/parameters/EnableWorkspaceInvoiceFieldListValueParams.ts
 delete mode 100644 src/libs/API/parameters/RemoveWorkspaceInvoiceFieldListValueParams.ts
 delete mode 100644 src/libs/API/parameters/UpdateWorkspaceInvoiceFieldInitialValueParams.ts
 delete mode 100644 src/pages/workspace/fields/CreateFieldsPage.tsx
 delete mode 100644 src/pages/workspace/fields/FieldsAddListValuePage.tsx
 delete mode 100644 src/pages/workspace/fields/FieldsEditValuePage.tsx
 delete mode 100644 src/pages/workspace/fields/FieldsInitialValuePage.tsx
 delete mode 100644 src/pages/workspace/fields/FieldsListValuesPage.tsx
 delete mode 100644 src/pages/workspace/fields/FieldsSettingsPage.tsx
 delete mode 100644 src/pages/workspace/fields/FieldsValueSettingsPage.tsx
 delete mode 100644 src/pages/workspace/fields/WorkspaceFieldsSection.tsx
 delete mode 100644 src/pages/workspace/invoices/CreateInvoiceFieldsPage.tsx
 delete mode 100644 src/pages/workspace/invoices/InvoiceFieldsAddListValuePage.tsx
 delete mode 100644 src/pages/workspace/invoices/InvoiceFieldsEditValuePage.tsx
 delete mode 100644 src/pages/workspace/invoices/InvoiceFieldsInitialValuePage.tsx
 delete mode 100644 src/pages/workspace/invoices/InvoiceFieldsListValuesPage.tsx
 delete mode 100644 src/pages/workspace/invoices/InvoiceFieldsSettingsPage.tsx
 delete mode 100644 src/pages/workspace/invoices/InvoiceFieldsValueSettingsPage.tsx
 delete mode 100644 src/pages/workspace/invoices/WorkspaceInvoiceFieldsSection.tsx

diff --git a/src/CONST/index.ts b/src/CONST/index.ts
index 93e47db3b810..ab3388bc4e3c 100644
--- a/src/CONST/index.ts
+++ b/src/CONST/index.ts
@@ -3981,7 +3981,6 @@ const CONST = {
             ARE_DISTANCE_RATES_ENABLED: 'areDistanceRatesEnabled',
             ARE_WORKFLOWS_ENABLED: 'areWorkflowsEnabled',
             ARE_REPORT_FIELDS_ENABLED: 'areReportFieldsEnabled',
-            ARE_INVOICE_FIELDS_ENABLED: 'areInvoiceFieldsEnabled',
             ARE_CONNECTIONS_ENABLED: 'areConnectionsEnabled',
             ARE_RECEIPT_PARTNERS_ENABLED: 'receiptPartners',
             ARE_COMPANY_CARDS_ENABLED: 'areCompanyCardsEnabled',
@@ -7248,14 +7247,6 @@ const CONST = {
                 description: 'workspace.upgrade.reportFields.description' as const,
                 icon: 'Pencil',
             },
-            invoiceFields: {
-                id: 'invoiceFields' as const,
-                alias: 'invoice-fields',
-                name: 'Invoice Fields',
-                title: 'workspace.upgrade.invoiceFields.title' as const,
-                description: 'workspace.upgrade.invoiceFields.description' as const,
-                icon: 'Pencil',
-            },
             policyPreventMemberChangingTitle: {
                 id: 'policyPreventMemberChangingTitle' as const,
                 alias: 'policy-prevent-member-changing-title',
@@ -7517,10 +7508,6 @@ const CONST = {
         LIST: 'dropdown',
         FORMULA: 'formula',
     },
-    REPORT_FIELD_TARGETS: {
-        EXPENSE: 'expense',
-        INVOICE: 'invoice',
-    },
 
     NAVIGATION_ACTIONS: {
         RESET: 'RESET',
diff --git a/src/ROUTES.ts b/src/ROUTES.ts
index f8e65e8cc72b..e03422189dcd 100644
--- a/src/ROUTES.ts
+++ b/src/ROUTES.ts
@@ -2428,35 +2428,6 @@ const ROUTES = {
         route: 'workspaces/:policyID/invoices/company-website',
         getRoute: (policyID: string) => `workspaces/${policyID}/invoices/company-website` as const,
     },
-    WORKSPACE_INVOICE_FIELDS_CREATE: {
-        route: 'workspaces/:policyID/invoices/newInvoiceField',
-        getRoute: (policyID: string) => `workspaces/${policyID}/invoices/newInvoiceField` as const,
-    },
-    WORKSPACE_INVOICE_FIELDS_SETTINGS: {
-        route: 'workspaces/:policyID/invoices/:reportFieldID/edit',
-        getRoute: (policyID: string, reportFieldID: string) => `workspaces/${policyID}/invoices/${encodeURIComponent(reportFieldID)}/edit` as const,
-    },
-    WORKSPACE_INVOICE_FIELDS_LIST_VALUES: {
-        route: 'workspaces/:policyID/invoices/listValues/:reportFieldID?',
-        getRoute: (policyID: string, reportFieldID?: string) => `workspaces/${policyID}/invoices/listValues/${reportFieldID ? encodeURIComponent(reportFieldID) : ''}` as const,
-    },
-    WORKSPACE_INVOICE_FIELDS_ADD_VALUE: {
-        route: 'workspaces/:policyID/invoices/addValue/:reportFieldID?',
-        getRoute: (policyID: string, reportFieldID?: string) => `workspaces/${policyID}/invoices/addValue/${reportFieldID ? encodeURIComponent(reportFieldID) : ''}` as const,
-    },
-    WORKSPACE_INVOICE_FIELDS_VALUE_SETTINGS: {
-        route: 'workspaces/:policyID/invoices/:valueIndex/:reportFieldID?',
-        getRoute: (policyID: string, valueIndex: number, reportFieldID?: string) =>
-            `workspaces/${policyID}/invoices/${valueIndex}/${reportFieldID ? encodeURIComponent(reportFieldID) : ''}` as const,
-    },
-    WORKSPACE_INVOICE_FIELDS_EDIT_VALUE: {
-        route: 'workspaces/:policyID/invoices/newInvoiceField/:valueIndex/edit',
-        getRoute: (policyID: string, valueIndex: number) => `workspaces/${policyID}/invoices/newInvoiceField/${valueIndex}/edit` as const,
-    },
-    WORKSPACE_INVOICE_FIELDS_EDIT_INITIAL_VALUE: {
-        route: 'workspaces/:policyID/invoices/:reportFieldID/edit/initialValue',
-        getRoute: (policyID: string, reportFieldID: string) => `workspaces/${policyID}/invoices/${encodeURIComponent(reportFieldID)}/edit/initialValue` as const,
-    },
     WORKSPACE_MEMBERS: {
         route: 'workspaces/:policyID/members',
         getRoute: (policyID: string | undefined) => {
diff --git a/src/SCREENS.ts b/src/SCREENS.ts
index 6066e17d3967..4bd406171f04 100644
--- a/src/SCREENS.ts
+++ b/src/SCREENS.ts
@@ -766,13 +766,6 @@ const SCREENS = {
         INVOICES_VERIFY_ACCOUNT: 'Workspace_Invoices_Verify_Account',
         INVOICES_COMPANY_NAME: 'Workspace_Invoices_Company_Name',
         INVOICES_COMPANY_WEBSITE: 'Workspace_Invoices_Company_Website',
-        INVOICE_FIELDS_CREATE: 'Workspace_InvoiceFields_Create',
-        INVOICE_FIELDS_SETTINGS: 'Workspace_InvoiceFields_Settings',
-        INVOICE_FIELDS_LIST_VALUES: 'Workspace_InvoiceFields_ListValues',
-        INVOICE_FIELDS_ADD_VALUE: 'Workspace_InvoiceFields_AddValue',
-        INVOICE_FIELDS_VALUE_SETTINGS: 'Workspace_InvoiceFields_ValueSettings',
-        INVOICE_FIELDS_EDIT_VALUE: 'Workspace_InvoiceFields_EditValue',
-        INVOICE_FIELDS_EDIT_INITIAL_VALUE: 'Workspace_InvoiceFields_EditInitialValue',
         MEMBERS: 'Workspace_Members',
         ROOMS: 'Workspace_Rooms',
         ROOM_CREATE: 'Workspace_Room_Create',
diff --git a/src/components/MoneyRequestReportView/MoneyRequestViewReportFields.tsx b/src/components/MoneyRequestReportView/MoneyRequestViewReportFields.tsx
index 4eb2be1a3425..c609af3806b9 100644
--- a/src/components/MoneyRequestReportView/MoneyRequestViewReportFields.tsx
+++ b/src/components/MoneyRequestReportView/MoneyRequestViewReportFields.tsx
@@ -121,9 +121,8 @@ function MoneyRequestViewReportFields({report, policy, isCombinedReport = false,
     const isOnlyTitleFieldEnabled = enabledReportFields.length === 1 && isReportFieldOfTypeTitle(enabledReportFields.at(0));
     const isPaidGroupPolicyExpenseReport = isPaidGroupPolicyExpenseReportUtils(report);
     const isInvoiceReport = isInvoiceReportUtils(report);
-    const areFieldsEnabledForReport = isInvoiceReport ? policy?.areInvoiceFieldsEnabled : policy?.areReportFieldsEnabled;
 
-    const shouldDisplayReportFields = (isPaidGroupPolicyExpenseReport || isInvoiceReport) && !!areFieldsEnabledForReport && (!isOnlyTitleFieldEnabled || !isCombinedReport);
+    const shouldDisplayReportFields = (isPaidGroupPolicyExpenseReport || isInvoiceReport) && !!policy?.areReportFieldsEnabled && (!isOnlyTitleFieldEnabled || !isCombinedReport);
 
     if (!shouldDisplayReportFields || !sortedPolicyReportFields.length) {
         return null;
diff --git a/src/components/ReportActionItem/MoneyReportView.tsx b/src/components/ReportActionItem/MoneyReportView.tsx
index 715931d2adc5..b3408917b50a 100644
--- a/src/components/ReportActionItem/MoneyReportView.tsx
+++ b/src/components/ReportActionItem/MoneyReportView.tsx
@@ -152,7 +152,6 @@ function MoneyReportView({
     const isPaidGroupPolicyExpenseReport = isPaidGroupPolicyExpenseReportUtils(report);
     const isInvoiceReport = isInvoiceReportUtils(report);
 
-    const areFieldsEnabledForReport = isInvoiceReport ? policy?.areInvoiceFieldsEnabled : policy?.areReportFieldsEnabled;
     const shouldShowReportField =
         !isClosedExpenseReportWithNoExpenses &&
         (isPaidGroupPolicyExpenseReport || isInvoiceReport) &&
@@ -185,7 +184,7 @@ function MoneyReportView({
                 {!isClosedExpenseReportWithNoExpenses && (
                     <>
                         {(isPaidGroupPolicyExpenseReport || isInvoiceReport) &&
-                            areFieldsEnabledForReport &&
+                            !!policy?.areReportFieldsEnabled &&
                             (!isCombinedReport || !isOnlyTitleFieldEnabled) &&
                             sortedPolicyReportFields.map((reportField) => {
                                 if (shouldHideSingleReportField(reportField)) {
diff --git a/src/languages/de.ts b/src/languages/de.ts
index 884e41cab1b3..d79c8031afb8 100644
--- a/src/languages/de.ts
+++ b/src/languages/de.ts
@@ -4340,7 +4340,6 @@ ${amount} für ${merchant} – ${date}`,
             customFieldHint: 'Füge benutzerdefinierte Codierung hinzu, die für alle Ausgaben dieses Mitglieds gilt.',
             reports: 'Berichte',
             reportFields: 'Berichtsfelder',
-            invoiceFields: 'Rechnungsfelder',
             reportTitle: 'Berichtstitel',
             reportField: 'Berichts­feld',
             taxes: 'Steuern',
@@ -6025,29 +6024,6 @@ _Für ausführlichere Anweisungen [besuchen Sie unsere Hilfeseite](${CONST.NETSU
             reportFieldInitialValueRequiredError: 'Bitte wähle einen Anfangswert für ein Berichtsfeld aus',
             genericFailureMessage: 'Beim Aktualisieren des Berichtfelds ist ein Fehler aufgetreten. Bitte versuche es erneut.',
         },
-        invoiceFields: {
-            subtitle: 'Rechnungsfelder können hilfreich sein, wenn du zusätzliche Informationen einfügen möchtest.',
-            importedFromAccountingSoftware: 'Die folgenden Rechnungsfelder werden importiert aus Ihrem',
-            disableInvoiceFields: 'Rechnungsfelder deaktivieren',
-            disableInvoiceFieldsConfirmation: 'Sind Sie sicher? Rechnungsfelder werden auf Rechnungen deaktiviert.',
-            delete: 'Rechnungsfeld löschen',
-            deleteConfirmation: 'Sind Sie sicher, dass Sie dieses Rechnungsfeld löschen möchten?',
-            findInvoiceField: 'Rechnungsfeld suchen',
-            nameInputSubtitle: 'Wähle einen Namen für das Rechnungsfeld.',
-            typeInputSubtitle: 'Wähle aus, welcher Rechnungsfeldtyp verwendet werden soll.',
-            initialValueInputSubtitle: 'Gib einen Startwert ein, der im Rechnungsfeld angezeigt werden soll.',
-            listValuesInputSubtitle: 'Diese Werte werden im Dropdown-Menü des Rechnungsfelds angezeigt. Aktivierte Werte können von Mitgliedern ausgewählt werden.',
-            listInputSubtitle: 'Diese Werte werden in der Rechnungsfeldliste angezeigt. Aktivierte Werte können von Mitgliedern ausgewählt werden.',
-            emptyInvoiceFieldsValues: {
-                title: 'Noch keine Listenwerte',
-                subtitle: 'Füge benutzerdefinierte Werte hinzu, die auf Rechnungen angezeigt werden.',
-            },
-            existingInvoiceFieldNameError: 'Ein Rechnungsfeld mit diesem Namen existiert bereits',
-            invoiceFieldNameRequiredError: 'Bitte gib einen Namen für das Rechnungsfeld ein',
-            invoiceFieldTypeRequiredError: 'Bitte wähle einen Rechnungsfeldtyp aus',
-            invoiceFieldInitialValueRequiredError: 'Bitte wähle einen Anfangswert für ein Rechnungsfeld aus',
-            addField: 'Feld hinzufügen',
-        },
         tags: {
             tagName: 'Tag-Name',
             requiresTag: 'Mitglieder müssen alle Ausgaben taggen',
@@ -6852,12 +6828,6 @@ Möchten Sie sie wirklich noch einmal exportieren?`,
                 onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
                     `<muted-text>Berichtsfelder sind nur im Control-Tarif verfügbar, ab <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `pro Mitglied und Monat.` : `pro aktivem Mitglied und Monat.`}</muted-text>`,
             },
-            invoiceFields: {
-                title: 'Rechnungsfelder',
-                description: `Mit Rechnungsfeldern kannst du zusätzliche Details auf Rechnungsebene in Rechnungen aufnehmen.`,
-                onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
-                    `<muted-text>Rechnungsfelder sind nur im Control-Tarif verfügbar, ab <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `pro Mitglied und Monat.` : `pro aktivem Mitglied und Monat.`}</muted-text>`,
-            },
             [CONST.POLICY.CONNECTIONS.NAME.NETSUITE]: {
                 title: 'NetSuite',
                 description: `Profitiere von automatischer Synchronisierung und reduziere manuelle Eingaben mit der Expensify + NetSuite-Integration. Gewinne detaillierte Finanzanalysen in Echtzeit mit nativer und benutzerdefinierter Segmentunterstützung, einschließlich Projekt- und Kundenzuordnung.`,
diff --git a/src/languages/en.ts b/src/languages/en.ts
index 6afe4e0574a8..a8106a45cf54 100644
--- a/src/languages/en.ts
+++ b/src/languages/en.ts
@@ -4429,7 +4429,6 @@ const translations = {
             customFieldHint: 'Add custom coding that applies to all spend from this member.',
             reports: 'Reports',
             reportFields: 'Report fields',
-            invoiceFields: 'Invoice fields',
             reportTitle: 'Report title',
             reportField: 'Report field',
             taxes: 'Taxes',
@@ -6072,29 +6071,6 @@ const translations = {
             reportFieldInitialValueRequiredError: 'Please choose a report field initial value',
             genericFailureMessage: 'An error occurred while updating the report field. Please try again.',
         },
-        invoiceFields: {
-            subtitle: "Invoice fields can be helpful when you'd like to include extra information.",
-            importedFromAccountingSoftware: 'The invoice fields below are imported from your',
-            disableInvoiceFields: 'Disable invoice fields',
-            disableInvoiceFieldsConfirmation: 'Are you sure? Invoice fields will be disabled on invoices.',
-            delete: 'Delete invoice field',
-            deleteConfirmation: 'Are you sure you want to delete this invoice field?',
-            findInvoiceField: 'Find invoice field',
-            nameInputSubtitle: 'Choose a name for the invoice field.',
-            typeInputSubtitle: 'Choose what type of invoice field to use.',
-            initialValueInputSubtitle: 'Enter a starting value to show in the invoice field.',
-            listValuesInputSubtitle: 'These values will appear in your invoice field dropdown. Enabled values can be selected by members.',
-            listInputSubtitle: 'These values will appear in your invoice field list. Enabled values can be selected by members.',
-            emptyInvoiceFieldsValues: {
-                title: 'No list values yet',
-                subtitle: 'Add custom values to appear on invoices.',
-            },
-            existingInvoiceFieldNameError: 'An invoice field with this name already exists',
-            invoiceFieldNameRequiredError: 'Please enter an invoice field name',
-            invoiceFieldTypeRequiredError: 'Please choose an invoice field type',
-            invoiceFieldInitialValueRequiredError: 'Please choose an invoice field initial value',
-            addField: 'Add field',
-        },
         tags: {
             tagName: 'Tag name',
             requiresTag: 'Members must tag all expenses',
@@ -6975,12 +6951,6 @@ const translations = {
                 onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
                     `<muted-text>Report fields are only available on the Control plan, starting at <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `per member per month.` : `per active member per month.`}</muted-text>`,
             },
-            invoiceFields: {
-                title: 'Invoice fields',
-                description: `Invoice fields let you include extra invoice-level details on invoices.`,
-                onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
-                    `<muted-text>Invoice fields are only available on the Control plan, starting at <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `per member per month.` : `per active member per month.`}</muted-text>`,
-            },
             [CONST.POLICY.CONNECTIONS.NAME.NETSUITE]: {
                 title: 'NetSuite',
                 description: `Enjoy automated syncing and reduce manual entries with the Expensify + NetSuite integration. Gain in-depth, realtime financial insights with native and custom segment support, including project and customer mapping.`,
diff --git a/src/languages/es.ts b/src/languages/es.ts
index dcdb87c44509..993bff088397 100644
--- a/src/languages/es.ts
+++ b/src/languages/es.ts
@@ -4222,7 +4222,6 @@ ${amount} para ${merchant} - ${date}`,
             customFieldHint: 'Añade una codificación personalizada que se aplique a todos los gastos de este miembro.',
             reports: 'Informes',
             reportFields: 'Campos de informe',
-            invoiceFields: 'Campos de factura',
             reportTitle: 'El título del informe.',
             taxes: 'Impuestos',
             bills: 'Pagar facturas',
@@ -5865,29 +5864,6 @@ ${amount} para ${merchant} - ${date}`,
             reportFieldInitialValueRequiredError: 'Elige un valor inicial de campo de informe',
             genericFailureMessage: 'Se ha producido un error al actualizar el campo de informe. Por favor, inténtalo de nuevo.',
         },
-        invoiceFields: {
-            subtitle: 'Los campos de factura pueden ayudarte cuando quieras incluir información adicional.',
-            importedFromAccountingSoftware: 'Campos de factura importados desde',
-            disableInvoiceFields: 'Desactivar campos de factura',
-            disableInvoiceFieldsConfirmation: '¿Estás seguro? Los campos de factura se desactivarán en las facturas.',
-            delete: 'Eliminar campo de factura',
-            deleteConfirmation: '¿Seguro que deseas eliminar este campo de factura?',
-            findInvoiceField: 'Buscar campo de factura',
-            nameInputSubtitle: 'Elige un nombre para el campo de factura.',
-            typeInputSubtitle: 'Elige qué tipo de campo de factura usar.',
-            initialValueInputSubtitle: 'Ingresa un valor inicial para mostrar en el campo de factura.',
-            listValuesInputSubtitle: 'Estos valores aparecerán en el menú desplegable del campo de factura. Los miembros pueden seleccionar los valores activados.',
-            listInputSubtitle: 'Estos valores aparecerán en la lista del campo de factura. Los miembros pueden seleccionar los valores activados.',
-            emptyInvoiceFieldsValues: {
-                title: 'Aún no hay valores de lista',
-                subtitle: 'Agrega valores personalizados para que aparezcan en las facturas.',
-            },
-            existingInvoiceFieldNameError: 'Ya existe un campo de factura con este nombre',
-            invoiceFieldNameRequiredError: 'Ingresa un nombre para el campo de factura',
-            invoiceFieldTypeRequiredError: 'Elige un tipo de campo de factura',
-            invoiceFieldInitialValueRequiredError: 'Elige un valor inicial para el campo de factura',
-            addField: 'Añadir campo',
-        },
         tags: {
             tagName: 'Nombre de etiqueta',
             requiresTag: 'Los miembros deben etiquetar todos los gastos',
@@ -6784,12 +6760,6 @@ ${amount} para ${merchant} - ${date}`,
                 onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}) =>
                     `<muted-text>Los campos de informe sólo están disponibles en el plan Controlar, a partir de <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `por miembro al mes.` : `por miembro activo al mes.`}</muted-text>`,
             },
-            invoiceFields: {
-                title: 'Campos de factura',
-                description: `Los campos de factura te permiten incluir detalles adicionales a nivel de factura.`,
-                onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}) =>
-                    `<muted-text>Los campos de factura sólo están disponibles en el plan Controlar, a partir de <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `por miembro al mes.` : `por miembro activo al mes.`}</muted-text>`,
-            },
             [CONST.POLICY.CONNECTIONS.NAME.NETSUITE]: {
                 title: 'NetSuite',
                 description: `Disfruta de la sincronización automática y reduce las entradas manuales con la integración Expensify + NetSuite. Obtén información financiera en profundidad y en tiempo real con la compatibilidad nativa y personalizada con segmentos, incluida la asignación de proyectos y clientes.`,
diff --git a/src/languages/fr.ts b/src/languages/fr.ts
index cae4d17519d5..2b9e857d6851 100644
--- a/src/languages/fr.ts
+++ b/src/languages/fr.ts
@@ -4352,7 +4352,6 @@ ${amount} pour ${merchant} - ${date}`,
             customFieldHint: 'Ajoutez un codage personnalisé qui s’applique à toutes les dépenses de ce membre.',
             reports: 'Notes de frais',
             reportFields: 'Champs de note de frais',
-            invoiceFields: 'Champs de facture',
             reportTitle: 'Titre de la note de frais',
             reportField: 'Champ de note de frais',
             taxes: 'Taxes',
@@ -6051,29 +6050,6 @@ _Pour des instructions plus détaillées, [visitez notre site d’aide](${CONST.
             reportFieldInitialValueRequiredError: 'Veuillez choisir une valeur initiale pour le champ de note de frais',
             genericFailureMessage: 'Une erreur s’est produite lors de la mise à jour du champ de note de frais. Veuillez réessayer.',
         },
-        invoiceFields: {
-            subtitle: 'Les champs de facture peuvent être utiles lorsque vous souhaitez inclure des informations supplémentaires.',
-            importedFromAccountingSoftware: 'Les champs de facture ci-dessous sont importés depuis votre',
-            disableInvoiceFields: 'Désactiver les champs de facture',
-            disableInvoiceFieldsConfirmation: 'Êtes-vous sûr ? Les champs de facture seront désactivés sur les factures.',
-            delete: 'Supprimer le champ de facture',
-            deleteConfirmation: 'Voulez-vous vraiment supprimer ce champ de facture ?',
-            findInvoiceField: 'Trouver un champ de facture',
-            nameInputSubtitle: 'Choisissez un nom pour le champ de facture.',
-            typeInputSubtitle: 'Choisissez le type de champ de facture à utiliser.',
-            initialValueInputSubtitle: 'Saisissez une valeur de départ à afficher dans le champ de facture.',
-            listValuesInputSubtitle: 'Ces valeurs apparaîtront dans la liste déroulante du champ de facture. Les valeurs activées peuvent être sélectionnées par les membres.',
-            listInputSubtitle: 'Ces valeurs apparaîtront dans la liste du champ de facture. Les valeurs activées peuvent être sélectionnées par les membres.',
-            emptyInvoiceFieldsValues: {
-                title: 'Aucune valeur de liste pour le moment',
-                subtitle: 'Ajoutez des valeurs personnalisées à afficher sur les factures.',
-            },
-            existingInvoiceFieldNameError: 'Un champ de facture portant ce nom existe déjà',
-            invoiceFieldNameRequiredError: 'Veuillez saisir un nom de champ de facture',
-            invoiceFieldTypeRequiredError: 'Veuillez choisir un type de champ de facture',
-            invoiceFieldInitialValueRequiredError: 'Veuillez choisir une valeur initiale de champ de facture',
-            addField: 'Ajouter un champ',
-        },
         tags: {
             tagName: 'Nom du tag',
             requiresTag: 'Les membres doivent taguer toutes les dépenses',
@@ -6879,12 +6855,6 @@ Voulez-vous vraiment les exporter à nouveau ?`,
                 onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
                     `<muted-text>Les champs de note de frais sont uniquement disponibles avec l’offre Control, à partir de <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `par membre et par mois.` : `par membre actif et par mois.`}</muted-text>`,
             },
-            invoiceFields: {
-                title: 'Champs de facture',
-                description: `Les champs de facture vous permettent d'inclure des détails supplémentaires au niveau de la facture.`,
-                onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
-                    `<muted-text>Les champs de facture sont uniquement disponibles avec l’offre Control, à partir de <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `par membre et par mois.` : `par membre actif et par mois.`}</muted-text>`,
-            },
             [CONST.POLICY.CONNECTIONS.NAME.NETSUITE]: {
                 title: 'NetSuite',
                 description: `Profitez de la synchronisation automatisée et réduisez les saisies manuelles grâce à l’intégration Expensify + NetSuite. Obtenez des informations financières détaillées et en temps réel avec la prise en charge des segments natifs et personnalisés, y compris la correspondance des projets et des clients.`,
diff --git a/src/languages/it.ts b/src/languages/it.ts
index 0fcfffdb73b7..7ea012d6f9d3 100644
--- a/src/languages/it.ts
+++ b/src/languages/it.ts
@@ -4326,7 +4326,6 @@ ${amount} per ${merchant} - ${date}`,
             customFieldHint: 'Aggiungi una codifica personalizzata che si applichi a tutte le spese di questo membro.',
             reports: 'Report',
             reportFields: 'Campi del report',
-            invoiceFields: 'Campi fattura',
             reportTitle: 'Titolo del report',
             reportField: 'Campo report',
             taxes: 'Tasse',
@@ -6015,29 +6014,6 @@ _Per istruzioni più dettagliate, [visita il nostro sito di assistenza](${CONST.
             reportFieldInitialValueRequiredError: 'Scegli un valore iniziale per il campo del resoconto',
             genericFailureMessage: 'Si è verificato un errore durante l’aggiornamento del campo del report. Riprova.',
         },
-        invoiceFields: {
-            subtitle: 'I campi della fattura possono essere utili quando vuoi includere informazioni aggiuntive.',
-            importedFromAccountingSoftware: 'I campi della fattura riportati di seguito sono importati dal tuo',
-            disableInvoiceFields: 'Disattiva i campi della fattura',
-            disableInvoiceFieldsConfirmation: 'Sei sicuro? I campi della fattura verranno disattivati nelle fatture.',
-            delete: 'Elimina campo della fattura',
-            deleteConfirmation: 'Sei sicuro di voler eliminare questo campo della fattura?',
-            findInvoiceField: 'Trova campo della fattura',
-            nameInputSubtitle: 'Scegli un nome per il campo della fattura.',
-            typeInputSubtitle: 'Scegli il tipo di campo della fattura da utilizzare.',
-            initialValueInputSubtitle: 'Inserisci un valore iniziale da mostrare nel campo della fattura.',
-            listValuesInputSubtitle: 'Questi valori appariranno nel menu a discesa del campo della fattura. I valori abilitati possono essere selezionati dai membri.',
-            listInputSubtitle: 'Questi valori appariranno nell’elenco del campo della fattura. I valori abilitati possono essere selezionati dai membri.',
-            emptyInvoiceFieldsValues: {
-                title: 'Nessun valore elenco ancora',
-                subtitle: 'Aggiungi valori personalizzati da mostrare sulle fatture.',
-            },
-            existingInvoiceFieldNameError: 'Esiste già un campo della fattura con questo nome',
-            invoiceFieldNameRequiredError: 'Inserisci un nome per il campo della fattura',
-            invoiceFieldTypeRequiredError: 'Scegli un tipo di campo della fattura',
-            invoiceFieldInitialValueRequiredError: 'Scegli un valore iniziale per il campo della fattura',
-            addField: 'Aggiungi campo',
-        },
         tags: {
             tagName: 'Nome tag',
             requiresTag: 'I membri devono etichettare tutte le spese',
@@ -6836,12 +6812,6 @@ Vuoi davvero esportarli di nuovo?`,
                 onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
                     `<muted-text>I campi del report sono disponibili solo con il piano Control, a partire da <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `per utente al mese.` : `per membro attivo al mese.`}</muted-text>`,
             },
-            invoiceFields: {
-                title: 'Campi fattura',
-                description: `I campi fattura ti consentono di includere dettagli aggiuntivi a livello di fattura.`,
-                onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
-                    `<muted-text>I campi fattura sono disponibili solo con il piano Control, a partire da <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `per utente al mese.` : `per membro attivo al mese.`}</muted-text>`,
-            },
             [CONST.POLICY.CONNECTIONS.NAME.NETSUITE]: {
                 title: 'NetSuite',
                 description: `Approfitta della sincronizzazione automatica e riduci le registrazioni manuali con l’integrazione Expensify + NetSuite. Ottieni approfondimenti finanziari dettagliati e in tempo reale grazie al supporto di segmenti nativi e personalizzati, inclusa la mappatura di progetti e clienti.`,
diff --git a/src/languages/ja.ts b/src/languages/ja.ts
index 98aae61a7580..88866bc10c68 100644
--- a/src/languages/ja.ts
+++ b/src/languages/ja.ts
@@ -4297,7 +4297,6 @@ ${integrationName === CONST.ONBOARDING_ACCOUNTING_MAPPING.other ? 'あなたの'
             customFieldHint: 'このメンバーのすべての支出に適用されるカスタムコードを追加します。',
             reports: 'レポート',
             reportFields: 'レポート項目',
-            invoiceFields: '請求書項目',
             reportTitle: 'レポートタイトル',
             reportField: 'レポート項目',
             taxes: '税金',
@@ -5946,29 +5945,6 @@ _詳しい手順については、[ヘルプサイトをご覧ください](${CO
             reportFieldInitialValueRequiredError: 'レポート項目の初期値を選択してください',
             genericFailureMessage: 'レポートフィールドの更新中にエラーが発生しました。もう一度お試しください。',
         },
-        invoiceFields: {
-            subtitle: '追加情報を含めたい場合、請求書フィールドが役立ちます。',
-            importedFromAccountingSoftware: '以下の請求書フィールドは、次からインポートされます',
-            disableInvoiceFields: '請求書フィールドを無効にする',
-            disableInvoiceFieldsConfirmation: 'よろしいですか？請求書フィールドは請求書で無効になります。',
-            delete: '請求書フィールドを削除',
-            deleteConfirmation: 'この請求書フィールドを削除してもよろしいですか？',
-            findInvoiceField: '請求書フィールドを検索',
-            nameInputSubtitle: '請求書フィールドの名前を選択してください。',
-            typeInputSubtitle: '使用する請求書フィールドの種類を選択してください。',
-            initialValueInputSubtitle: '請求書フィールドに表示する開始値を入力してください。',
-            listValuesInputSubtitle: 'これらの値は請求書フィールドのドロップダウンに表示されます。有効な値はメンバーが選択できます。',
-            listInputSubtitle: 'これらの値は請求書フィールドのリストに表示されます。有効な値はメンバーが選択できます。',
-            emptyInvoiceFieldsValues: {
-                title: 'リスト値はまだありません',
-                subtitle: '請求書に表示するカスタム値を追加します。',
-            },
-            existingInvoiceFieldNameError: 'この名前の請求書フィールドは既に存在します',
-            invoiceFieldNameRequiredError: '請求書フィールド名を入力してください',
-            invoiceFieldTypeRequiredError: '請求書フィールドの種類を選択してください',
-            invoiceFieldInitialValueRequiredError: '請求書フィールドの初期値を選択してください',
-            addField: 'フィールドを追加',
-        },
         tags: {
             tagName: 'タグ名',
             requiresTag: 'メンバーはすべての経費にタグを付ける必要があります',
@@ -6764,12 +6740,6 @@ ${reportName}
                 onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
                     `<muted-text>レポートフィールドは、<strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `メンバー1人あたり月額` : `アクティブメンバー1人あたり月額`}からのControlプランでのみ利用できます</muted-text>`,
             },
-            invoiceFields: {
-                title: '請求書項目',
-                description: `請求書フィールドを使うと、請求書レベルの追加情報を請求書に含めることができます。`,
-                onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
-                    `<muted-text>請求書フィールドは、<strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `メンバー1人あたり月額` : `アクティブメンバー1人あたり月額`}からのControlプランでのみ利用できます</muted-text>`,
-            },
             [CONST.POLICY.CONNECTIONS.NAME.NETSUITE]: {
                 title: 'NetSuite',
                 description: `Expensify と NetSuite の連携により、自動同期を活用して手入力を減らしましょう。プロジェクトや顧客のマッピングを含むネイティブおよびカスタムセグメントのサポートで、詳細かつリアルタイムな財務インサイトを得られます。`,
diff --git a/src/languages/nl.ts b/src/languages/nl.ts
index ba3d4b5b121c..249a3f75538d 100644
--- a/src/languages/nl.ts
+++ b/src/languages/nl.ts
@@ -4321,7 +4321,6 @@ ${amount} voor ${merchant} - ${date}`,
             customFieldHint: 'Voeg aangepaste codering toe die van toepassing is op alle uitgaven van dit lid.',
             reports: 'Rapporten',
             reportFields: 'Rapportvelden',
-            invoiceFields: 'Factuurvelden',
             reportTitle: 'Rapporttitel',
             reportField: 'Rapportveld',
             taxes: 'Belastingen',
@@ -5993,29 +5992,6 @@ _Voor meer gedetailleerde instructies, [bezoek onze help-site](${CONST.NETSUITE_
             reportFieldInitialValueRequiredError: 'Kies een beginwaarde voor een rapportveld',
             genericFailureMessage: 'Er is een fout opgetreden bij het bijwerken van het rapportveld. Probeer het opnieuw.',
         },
-        invoiceFields: {
-            subtitle: 'Factuurvelden kunnen handig zijn als je extra informatie wilt toevoegen.',
-            importedFromAccountingSoftware: 'De onderstaande factuurvelden zijn geïmporteerd uit je',
-            disableInvoiceFields: 'Factuurvelden uitschakelen',
-            disableInvoiceFieldsConfirmation: 'Weet je het zeker? Factuurvelden worden uitgeschakeld op facturen.',
-            delete: 'Factuurveld verwijderen',
-            deleteConfirmation: 'Weet je zeker dat je dit factuurveld wilt verwijderen?',
-            findInvoiceField: 'Factuurveld zoeken',
-            nameInputSubtitle: 'Kies een naam voor het factuurveld.',
-            typeInputSubtitle: 'Kies welk type factuurveld je wilt gebruiken.',
-            initialValueInputSubtitle: 'Voer een beginwaarde in om in het factuurveld weer te geven.',
-            listValuesInputSubtitle: 'Deze waarden verschijnen in de vervolgkeuzelijst van je factuurveld. Ingeschakelde waarden kunnen door leden worden geselecteerd.',
-            listInputSubtitle: 'Deze waarden verschijnen in je factuurveldenlijst. Ingeschakelde waarden kunnen door leden worden geselecteerd.',
-            emptyInvoiceFieldsValues: {
-                title: 'Nog geen lijstwaarden',
-                subtitle: 'Voeg aangepaste waarden toe om op facturen te tonen.',
-            },
-            existingInvoiceFieldNameError: 'Er bestaat al een factuurveld met deze naam',
-            invoiceFieldNameRequiredError: 'Voer een naam voor een factuurveld in',
-            invoiceFieldTypeRequiredError: 'Kies een veldtype voor de factuur',
-            invoiceFieldInitialValueRequiredError: 'Kies een beginwaarde voor een factuurveld',
-            addField: 'Veld toevoegen',
-        },
         tags: {
             tagName: 'Tagnaam',
             requiresTag: 'Leden moeten alle uitgaven taggen',
@@ -6815,12 +6791,6 @@ Weet je zeker dat je ze opnieuw wilt exporteren?`,
                 onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
                     `<muted-text>Rapportvelden zijn alleen beschikbaar in het Control-abonnement, vanaf <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `per lid per maand.` : `per actieve deelnemer per maand.`}</muted-text>`,
             },
-            invoiceFields: {
-                title: 'Factuurvelden',
-                description: `Met factuurvelden kun je extra gegevens op factuurniveau toevoegen aan facturen.`,
-                onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
-                    `<muted-text>Factuurvelden zijn alleen beschikbaar in het Control-abonnement, vanaf <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `per lid per maand.` : `per actieve deelnemer per maand.`}</muted-text>`,
-            },
             [CONST.POLICY.CONNECTIONS.NAME.NETSUITE]: {
                 title: 'NetSuite',
                 description: `Profiteer van automatische synchronisatie en verminder handmatige invoer met de Expensify + NetSuite-integratie. Krijg diepgaande realtime financiële inzichten met ondersteuning voor native en aangepaste segmenten, inclusief project- en klanttoewijzing.`,
diff --git a/src/languages/pl.ts b/src/languages/pl.ts
index 29f9591d54bf..c0557f5a5a8b 100644
--- a/src/languages/pl.ts
+++ b/src/languages/pl.ts
@@ -4313,7 +4313,6 @@ ${amount} dla ${merchant} - ${date}`,
             customFieldHint: 'Dodaj niestandardowe kodowanie, które będzie stosowane do wszystkich wydatków tego członka.',
             reports: 'Raporty',
             reportFields: 'Pola raportu',
-            invoiceFields: 'Pola faktury',
             reportTitle: 'Tytuł raportu',
             reportField: 'Pole raportu',
             taxes: 'Podatki',
@@ -5987,29 +5986,6 @@ _Aby uzyskać bardziej szczegółowe instrukcje, [odwiedź naszą stronę pomocy
             reportFieldInitialValueRequiredError: 'Wybierz początkową wartość pola raportu',
             genericFailureMessage: 'Wystąpił błąd podczas aktualizowania pola raportu. Spróbuj ponownie.',
         },
-        invoiceFields: {
-            subtitle: 'Pola faktury mogą być pomocne, gdy chcesz dodać dodatkowe informacje.',
-            importedFromAccountingSoftware: 'Poniższe pola faktury są importowane z Twojego',
-            disableInvoiceFields: 'Wyłącz pola faktury',
-            disableInvoiceFieldsConfirmation: 'Czy na pewno? Pola faktury zostaną wyłączone na fakturach.',
-            delete: 'Usuń pole faktury',
-            deleteConfirmation: 'Czy na pewno chcesz usunąć to pole faktury?',
-            findInvoiceField: 'Znajdź pole faktury',
-            nameInputSubtitle: 'Wybierz nazwę pola faktury.',
-            typeInputSubtitle: 'Wybierz typ pola faktury, którego chcesz użyć.',
-            initialValueInputSubtitle: 'Wprowadź wartość początkową, która ma być wyświetlana w polu faktury.',
-            listValuesInputSubtitle: 'Te wartości pojawią się na liście rozwijanej pola faktury. Członkowie mogą wybierać włączone wartości.',
-            listInputSubtitle: 'Te wartości pojawią się na liście pola faktury. Członkowie mogą wybierać włączone wartości.',
-            emptyInvoiceFieldsValues: {
-                title: 'Brak wartości listy',
-                subtitle: 'Dodaj niestandardowe wartości, które mają pojawiać się na fakturach.',
-            },
-            existingInvoiceFieldNameError: 'Pole faktury o tej nazwie już istnieje',
-            invoiceFieldNameRequiredError: 'Wprowadź nazwę pola faktury',
-            invoiceFieldTypeRequiredError: 'Wybierz typ pola faktury',
-            invoiceFieldInitialValueRequiredError: 'Wybierz początkową wartość pola faktury',
-            addField: 'Dodaj pole',
-        },
         tags: {
             tagName: 'Nazwa tagu',
             requiresTag: 'Członkowie muszą otagować wszystkie wydatki',
@@ -6808,12 +6784,6 @@ Czy na pewno chcesz wyeksportować je ponownie?`,
                 onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
                     `<muted-text>Pola raportu są dostępne tylko w planie Control, od <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `za użytkownika miesięcznie.` : `na aktywnego członka miesięcznie.`}</muted-text>`,
             },
-            invoiceFields: {
-                title: 'Pola faktury',
-                description: `Pola faktury pozwalają dodać dodatkowe szczegóły na poziomie faktury.`,
-                onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
-                    `<muted-text>Pola faktury są dostępne tylko w planie Control, od <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `za użytkownika miesięcznie.` : `na aktywnego członka miesięcznie.`}</muted-text>`,
-            },
             [CONST.POLICY.CONNECTIONS.NAME.NETSUITE]: {
                 title: 'NetSuite',
                 description: `Korzystaj z automatycznej synchronizacji i ograniczaj ręczne wprowadzanie danych dzięki integracji Expensify + NetSuite. Uzyskaj dogłębny, aktualny w czasie rzeczywistym wgląd w finanse dzięki obsłudze natywnych i niestandardowych segmentów, w tym mapowaniu projektów i klientów.`,
diff --git a/src/languages/pt-BR.ts b/src/languages/pt-BR.ts
index aa19d8aceaf8..aa340873d559 100644
--- a/src/languages/pt-BR.ts
+++ b/src/languages/pt-BR.ts
@@ -4316,7 +4316,6 @@ ${amount} para ${merchant} - ${date}`,
             reportFields: 'Campos do relatório',
             reportTitle: 'Título do relatório',
             reportField: 'Campo de relatório',
-            invoiceFields: 'Campos de fatura',
             taxes: 'Impostos',
             bills: 'Contas',
             invoices: 'Faturas',
@@ -5992,29 +5991,6 @@ _Para instruções mais detalhadas, [visite nossa central de ajuda](${CONST.NETS
             reportFieldInitialValueRequiredError: 'Escolha um valor inicial para o campo de relatório',
             genericFailureMessage: 'Ocorreu um erro ao atualizar o campo do relatório. Tente novamente.',
         },
-        invoiceFields: {
-            subtitle: 'Os campos da fatura podem ser úteis quando você quiser incluir informações extras.',
-            importedFromAccountingSoftware: 'Os campos da fatura abaixo são importados do seu',
-            disableInvoiceFields: 'Desativar campos da fatura',
-            disableInvoiceFieldsConfirmation: 'Tem certeza? Os campos da fatura serão desativados nas faturas.',
-            delete: 'Excluir campo da fatura',
-            deleteConfirmation: 'Tem certeza de que deseja excluir este campo da fatura?',
-            findInvoiceField: 'Encontrar campo da fatura',
-            nameInputSubtitle: 'Escolha um nome para o campo da fatura.',
-            typeInputSubtitle: 'Escolha o tipo de campo da fatura que deseja usar.',
-            initialValueInputSubtitle: 'Insira um valor inicial para mostrar no campo da fatura.',
-            listValuesInputSubtitle: 'Esses valores aparecerão no menu suspenso do campo da fatura. Valores ativados podem ser selecionados pelos membros.',
-            listInputSubtitle: 'Esses valores aparecerão na lista do campo da fatura. Valores ativados podem ser selecionados pelos membros.',
-            emptyInvoiceFieldsValues: {
-                title: 'Ainda não há valores de lista',
-                subtitle: 'Adicione valores personalizados para aparecerem nas faturas.',
-            },
-            existingInvoiceFieldNameError: 'Já existe um campo da fatura com este nome',
-            invoiceFieldNameRequiredError: 'Insira um nome para o campo da fatura',
-            invoiceFieldTypeRequiredError: 'Escolha um tipo de campo da fatura',
-            invoiceFieldInitialValueRequiredError: 'Escolha um valor inicial para o campo da fatura',
-            addField: 'Adicionar campo',
-        },
         tags: {
             tagName: 'Nome da tag',
             requiresTag: 'Membros devem marcar todas as despesas',
@@ -6813,12 +6789,6 @@ Tem certeza de que deseja exportá-los novamente?`,
                 onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
                     `<muted-text>Os campos de relatório estão disponíveis apenas no plano Control, a partir de <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `por membro por mês.` : `por membro ativo por mês.`}</muted-text>`,
             },
-            invoiceFields: {
-                title: 'Campos de fatura',
-                description: `Os campos da fatura permitem incluir detalhes extras no nível da fatura.`,
-                onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
-                    `<muted-text>Os campos da fatura estão disponíveis apenas no plano Control, a partir de <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `por membro por mês.` : `por membro ativo por mês.`}</muted-text>`,
-            },
             [CONST.POLICY.CONNECTIONS.NAME.NETSUITE]: {
                 title: 'NetSuite',
                 description: `Aproveite a sincronização automática e reduza lançamentos manuais com a integração Expensify + NetSuite. Obtenha insights financeiros profundos e em tempo real com suporte a segmentos nativos e personalizados, incluindo mapeamento de projetos e clientes.`,
diff --git a/src/languages/zh-hans.ts b/src/languages/zh-hans.ts
index 9bb7121b54b8..c77d4e5a39a1 100644
--- a/src/languages/zh-hans.ts
+++ b/src/languages/zh-hans.ts
@@ -4221,7 +4221,6 @@ ${amount}，商户：${merchant} - 日期：${date}`,
             customFieldHint: '为该成员的所有支出添加适用的自定义编码。',
             reports: '报表',
             reportFields: '报表字段',
-            invoiceFields: '发票字段',
             reportTitle: '报表标题',
             reportField: '报表字段',
             taxes: '税费',
@@ -5837,29 +5836,6 @@ _如需更详细的说明，请[访问我们的帮助网站](${CONST.NETSUITE_IM
             reportFieldInitialValueRequiredError: '请选择报表字段的初始值',
             genericFailureMessage: '更新报表字段时出错。请重试。',
         },
-        invoiceFields: {
-            subtitle: '当你想添加更多信息时，发票字段会很有帮助。',
-            importedFromAccountingSoftware: '以下发票字段是从你的',
-            disableInvoiceFields: '禁用发票字段',
-            disableInvoiceFieldsConfirmation: '确定吗？发票字段将在发票中被禁用。',
-            delete: '删除发票字段',
-            deleteConfirmation: '确定要删除此发票字段吗？',
-            findInvoiceField: '查找发票字段',
-            nameInputSubtitle: '为发票字段选择一个名称。',
-            typeInputSubtitle: '选择要使用的发票字段类型。',
-            initialValueInputSubtitle: '输入要在发票字段中显示的起始值。',
-            listValuesInputSubtitle: '这些值将显示在你的发票字段下拉菜单中。成员可以选择已启用的值。',
-            listInputSubtitle: '这些值将显示在你的发票字段列表中。成员可以选择已启用的值。',
-            emptyInvoiceFieldsValues: {
-                title: '还没有列表值',
-                subtitle: '添加要显示在发票上的自定义值。',
-            },
-            existingInvoiceFieldNameError: '已存在同名发票字段',
-            invoiceFieldNameRequiredError: '请输入发票字段名称',
-            invoiceFieldTypeRequiredError: '请选择发票字段类型',
-            invoiceFieldInitialValueRequiredError: '请选择发票字段的初始值',
-            addField: '添加字段',
-        },
         tags: {
             tagName: '标签名称',
             requiresTag: '成员必须为所有报销添加标签',
@@ -6640,12 +6616,6 @@ ${reportName}
                 onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
                     `<muted-text>报表字段仅在 Control 方案中提供，起价为 <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `每位成员每月。` : `每位活跃成员每月。`}</muted-text>`,
             },
-            invoiceFields: {
-                title: '发票字段',
-                description: `发票字段可用于在发票上包含额外的发票级别详情。`,
-                onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
-                    `<muted-text>发票字段仅在 Control 方案中提供，起价为 <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `每位成员每月。` : `每位活跃成员每月。`}</muted-text>`,
-            },
             [CONST.POLICY.CONNECTIONS.NAME.NETSUITE]: {
                 title: 'NetSuite',
                 description: `通过 Expensify + NetSuite 集成实现自动同步，减少手动录入。借助对原生和自定义维度的支持（包括项目和客户映射），获取深入的实时财务洞察。`,
diff --git a/src/libs/API/parameters/CreateWorkspaceInvoiceFieldListValueParams.ts b/src/libs/API/parameters/CreateWorkspaceInvoiceFieldListValueParams.ts
deleted file mode 100644
index fa22805f4e71..000000000000
--- a/src/libs/API/parameters/CreateWorkspaceInvoiceFieldListValueParams.ts
+++ /dev/null
@@ -1,10 +0,0 @@
-type CreateWorkspaceInvoiceFieldListValueParams = {
-    policyID: string;
-    /**
-     * Stringified JSON object with type of following structure:
-     * Array<string>
-     */
-    invoiceFields: string;
-};
-
-export default CreateWorkspaceInvoiceFieldListValueParams;
diff --git a/src/libs/API/parameters/CreateWorkspaceInvoiceFieldParams.ts b/src/libs/API/parameters/CreateWorkspaceInvoiceFieldParams.ts
deleted file mode 100644
index 5cce12e49273..000000000000
--- a/src/libs/API/parameters/CreateWorkspaceInvoiceFieldParams.ts
+++ /dev/null
@@ -1,10 +0,0 @@
-type CreateWorkspaceInvoiceFieldParams = {
-    policyID: string;
-    /**
-     * Stringified JSON object with type of following structure:
-     * Array<string>
-     */
-    invoiceFields: string;
-};
-
-export default CreateWorkspaceInvoiceFieldParams;
diff --git a/src/libs/API/parameters/DeletePolicyInvoiceField.ts b/src/libs/API/parameters/DeletePolicyInvoiceField.ts
deleted file mode 100644
index 5b3c37fb1e07..000000000000
--- a/src/libs/API/parameters/DeletePolicyInvoiceField.ts
+++ /dev/null
@@ -1,10 +0,0 @@
-type DeletePolicyInvoiceField = {
-    policyID: string;
-    /**
-     * Stringified JSON object with type of following structure:
-     * Array<string>
-     */
-    invoiceFields: string;
-};
-
-export default DeletePolicyInvoiceField;
diff --git a/src/libs/API/parameters/EnablePolicyInvoiceFieldsParams.ts b/src/libs/API/parameters/EnablePolicyInvoiceFieldsParams.ts
deleted file mode 100644
index 5afc5c912d90..000000000000
--- a/src/libs/API/parameters/EnablePolicyInvoiceFieldsParams.ts
+++ /dev/null
@@ -1,6 +0,0 @@
-type EnablePolicyInvoiceFieldsParams = {
-    policyID: string;
-    enabled: boolean;
-};
-
-export default EnablePolicyInvoiceFieldsParams;
diff --git a/src/libs/API/parameters/EnableWorkspaceInvoiceFieldListValueParams.ts b/src/libs/API/parameters/EnableWorkspaceInvoiceFieldListValueParams.ts
deleted file mode 100644
index a52405efad54..000000000000
--- a/src/libs/API/parameters/EnableWorkspaceInvoiceFieldListValueParams.ts
+++ /dev/null
@@ -1,10 +0,0 @@
-type EnableWorkspaceInvoiceFieldListValueParams = {
-    policyID: string;
-    /**
-     * Stringified JSON object with type of following structure:
-     * Array<string>
-     */
-    invoiceFields: string;
-};
-
-export default EnableWorkspaceInvoiceFieldListValueParams;
diff --git a/src/libs/API/parameters/RemoveWorkspaceInvoiceFieldListValueParams.ts b/src/libs/API/parameters/RemoveWorkspaceInvoiceFieldListValueParams.ts
deleted file mode 100644
index c793b4bdf10a..000000000000
--- a/src/libs/API/parameters/RemoveWorkspaceInvoiceFieldListValueParams.ts
+++ /dev/null
@@ -1,10 +0,0 @@
-type RemoveWorkspaceInvoiceFieldListValueParams = {
-    policyID: string;
-    /**
-     * Stringified JSON object with type of following structure:
-     * Array<string>
-     */
-    invoiceFields: string;
-};
-
-export default RemoveWorkspaceInvoiceFieldListValueParams;
diff --git a/src/libs/API/parameters/UpdateWorkspaceInvoiceFieldInitialValueParams.ts b/src/libs/API/parameters/UpdateWorkspaceInvoiceFieldInitialValueParams.ts
deleted file mode 100644
index eeb3cd5106aa..000000000000
--- a/src/libs/API/parameters/UpdateWorkspaceInvoiceFieldInitialValueParams.ts
+++ /dev/null
@@ -1,10 +0,0 @@
-type UpdateWorkspaceInvoiceFieldInitialValueParams = {
-    policyID: string;
-    /**
-     * Stringified JSON object with type of following structure:
-     * Array<string>
-     */
-    invoiceFields: string;
-};
-
-export default UpdateWorkspaceInvoiceFieldInitialValueParams;
diff --git a/src/libs/API/parameters/index.ts b/src/libs/API/parameters/index.ts
index ea8c05a42cde..a7aeebdd4390 100644
--- a/src/libs/API/parameters/index.ts
+++ b/src/libs/API/parameters/index.ts
@@ -259,7 +259,6 @@ export type {default as SetPolicyTravelSettingsParams} from './SetPolicyTravelSe
 export type {default as EnablePolicyTagsParams} from './EnablePolicyTagsParams';
 export type {default as SetPolicyTagsEnabled} from './SetPolicyTagsEnabled';
 export type {default as EnablePolicyWorkflowsParams} from './EnablePolicyWorkflowsParams';
-export type {default as EnablePolicyInvoiceFieldsParams} from './EnablePolicyInvoiceFieldsParams';
 export type {default as EnablePolicyReportFieldsParams} from './EnablePolicyReportFieldsParams';
 export type {default as EnablePolicyExpensifyCardsParams} from './EnablePolicyExpensifyCardsParams';
 export type {default as UpdateGustoApprovalModeParams} from './UpdateGustoApprovalModeParams';
@@ -338,21 +337,15 @@ export type {default as DowngradeToTeamParams} from './DowngradeToTeamParams';
 export type {default as RejectMoneyRequestInBulkParams} from './RejectMoneyRequestInBulkParams';
 export type {default as ApproveMoneyRequestOnSearchParams} from './ApproveMoneyRequestOnSearchParams';
 export type {default as UpdateNetSuiteSubsidiaryParams} from './UpdateNetSuiteSubsidiaryParams';
-export type {default as DeletePolicyInvoiceField} from './DeletePolicyInvoiceField';
 export type {default as DeletePolicyReportField} from './DeletePolicyReportField';
 export type {default as ConnectPolicyToNetSuiteParams} from './ConnectPolicyToNetSuiteParams';
 export type {default as CreateWorkspaceReportFieldParams} from './CreateWorkspaceReportFieldParams';
-export type {default as CreateWorkspaceInvoiceFieldParams} from './CreateWorkspaceInvoiceFieldParams';
 export type {default as UpdateWorkspaceReportFieldInitialValueParams} from './UpdateWorkspaceReportFieldInitialValueParams';
-export type {default as UpdateWorkspaceInvoiceFieldInitialValueParams} from './UpdateWorkspaceInvoiceFieldInitialValueParams';
 export type {default as EnableWorkspaceReportFieldListValueParams} from './EnableWorkspaceReportFieldListValueParams';
-export type {default as EnableWorkspaceInvoiceFieldListValueParams} from './EnableWorkspaceInvoiceFieldListValueParams';
 export type {default as EnablePolicyInvoicingParams} from './EnablePolicyInvoicingParams';
 export type {default as EnablePolicyTimeTrackingParams} from './EnablePolicyTimeTrackingParams';
 export type {default as CreateWorkspaceReportFieldListValueParams} from './CreateWorkspaceReportFieldListValueParams';
-export type {default as CreateWorkspaceInvoiceFieldListValueParams} from './CreateWorkspaceInvoiceFieldListValueParams';
 export type {default as RemoveWorkspaceReportFieldListValueParams} from './RemoveWorkspaceReportFieldListValueParams';
-export type {default as RemoveWorkspaceInvoiceFieldListValueParams} from './RemoveWorkspaceInvoiceFieldListValueParams';
 export type {default as OpenPolicyExpensifyCardsPageParams} from './OpenPolicyExpensifyCardsPageParams';
 export type {default as OpenPolicyTravelPageParams} from './OpenPolicyTravelPageParams';
 export type {default as OpenPolicyEditCardLimitTypePageParams} from './OpenPolicyEditCardLimitTypePageParams';
diff --git a/src/libs/API/types.ts b/src/libs/API/types.ts
index 0bdcd9ff6228..195fa744daa9 100644
--- a/src/libs/API/types.ts
+++ b/src/libs/API/types.ts
@@ -193,7 +193,6 @@ const WRITE_COMMANDS = {
     UPDATE_POLICY_CATEGORY_GL_CODE: 'UpdatePolicyCategoryGLCode',
     DELETE_WORKSPACE_CATEGORIES: 'DeleteWorkspaceCategories',
     DELETE_POLICY_REPORT_FIELD: 'DeletePolicyReportField',
-    DELETE_POLICY_INVOICE_FIELD: 'DeletePolicyInvoiceField',
     SET_POLICY_TAGS_REQUIRED: 'SetPolicyTagsRequired',
     SET_POLICY_TAG_LISTS_REQUIRED: 'SetPolicyTagListsRequired',
     SET_POLICY_REQUIRES_TAG: 'SetPolicyRequiresTag',
@@ -271,7 +270,6 @@ const WRITE_COMMANDS = {
     ENABLE_POLICY_TAXES: 'EnablePolicyTaxes',
     ENABLE_POLICY_WORKFLOWS: 'EnablePolicyWorkflows',
     ENABLE_POLICY_REPORT_FIELDS: 'EnablePolicyReportFields',
-    ENABLE_POLICY_INVOICE_FIELDS: 'EnablePolicyInvoiceFields',
     ENABLE_POLICY_EXPENSIFY_CARDS: 'EnablePolicyExpensifyCards',
     TOGGLE_POLICY_PER_DIEM: 'TogglePolicyPerDiem',
     ENABLE_POLICY_COMPANY_CARDS: 'EnablePolicyCompanyCards',
@@ -411,14 +409,9 @@ const WRITE_COMMANDS = {
     OPEN_SIDE_PANEL: 'OpenSidePanel',
     CLOSE_SIDE_PANEL: 'CloseSidePanel',
     UPDATE_NETSUITE_SUBSIDIARY: 'UpdateNetSuiteSubsidiary',
-    CREATE_WORKSPACE_INVOICE_FIELD: 'CreatePolicyInvoiceField',
-    CREATE_WORKSPACE_INVOICE_FIELD_LIST_VALUE: 'CreatePolicyInvoiceFieldOption',
     CREATE_WORKSPACE_REPORT_FIELD: 'CreatePolicyReportField',
-    UPDATE_WORKSPACE_INVOICE_FIELD_INITIAL_VALUE: 'SetPolicyInvoiceFieldDefault',
     UPDATE_WORKSPACE_REPORT_FIELD_INITIAL_VALUE: 'SetPolicyReportFieldDefault',
-    ENABLE_WORKSPACE_INVOICE_FIELD_LIST_VALUE: 'EnablePolicyInvoiceFieldOption',
     ENABLE_WORKSPACE_REPORT_FIELD_LIST_VALUE: 'EnablePolicyReportFieldOption',
-    REMOVE_WORKSPACE_INVOICE_FIELD_LIST_VALUE: 'RemovePolicyInvoiceFieldOption',
     CREATE_WORKSPACE_REPORT_FIELD_LIST_VALUE: 'CreatePolicyReportFieldOption',
     REMOVE_WORKSPACE_REPORT_FIELD_LIST_VALUE: 'RemovePolicyReportFieldOption',
     UPDATE_NETSUITE_SYNC_TAX_CONFIGURATION: 'UpdateNetSuiteSyncTaxConfiguration',
@@ -821,7 +814,6 @@ type WriteCommandParameters = {
     [WRITE_COMMANDS.UPDATE_POLICY_CATEGORY_PAYROLL_CODE]: Parameters.UpdatePolicyCategoryPayrollCodeParams;
     [WRITE_COMMANDS.UPDATE_POLICY_CATEGORY_GL_CODE]: Parameters.UpdatePolicyCategoryGLCodeParams;
     [WRITE_COMMANDS.DELETE_POLICY_REPORT_FIELD]: Parameters.DeletePolicyReportField;
-    [WRITE_COMMANDS.DELETE_POLICY_INVOICE_FIELD]: Parameters.DeletePolicyInvoiceField;
     [WRITE_COMMANDS.SET_POLICY_REQUIRES_TAG]: Parameters.SetPolicyRequiresTag;
     [WRITE_COMMANDS.SET_POLICY_TAGS_REQUIRED]: Parameters.SetPolicyTagsRequired;
     [WRITE_COMMANDS.SET_POLICY_TAG_LISTS_REQUIRED]: Parameters.SetPolicyTagListsRequired;
@@ -918,7 +910,6 @@ type WriteCommandParameters = {
     [WRITE_COMMANDS.ENABLE_POLICY_TAXES]: Parameters.EnablePolicyTaxesParams;
     [WRITE_COMMANDS.ENABLE_POLICY_WORKFLOWS]: Parameters.EnablePolicyWorkflowsParams;
     [WRITE_COMMANDS.ENABLE_POLICY_REPORT_FIELDS]: Parameters.EnablePolicyReportFieldsParams;
-    [WRITE_COMMANDS.ENABLE_POLICY_INVOICE_FIELDS]: Parameters.EnablePolicyInvoiceFieldsParams;
     [WRITE_COMMANDS.ENABLE_POLICY_EXPENSIFY_CARDS]: Parameters.EnablePolicyExpensifyCardsParams;
     [WRITE_COMMANDS.TOGGLE_POLICY_PER_DIEM]: Parameters.TogglePolicyPerDiemParams;
     [WRITE_COMMANDS.ENABLE_POLICY_COMPANY_CARDS]: Parameters.EnablePolicyCompanyCardsParams;
@@ -1131,15 +1122,10 @@ type WriteCommandParameters = {
 
     // Workspace report field parameters
     [WRITE_COMMANDS.CREATE_WORKSPACE_REPORT_FIELD]: Parameters.CreateWorkspaceReportFieldParams;
-    [WRITE_COMMANDS.CREATE_WORKSPACE_INVOICE_FIELD]: Parameters.CreateWorkspaceInvoiceFieldParams;
     [WRITE_COMMANDS.UPDATE_WORKSPACE_REPORT_FIELD_INITIAL_VALUE]: Parameters.UpdateWorkspaceReportFieldInitialValueParams;
-    [WRITE_COMMANDS.UPDATE_WORKSPACE_INVOICE_FIELD_INITIAL_VALUE]: Parameters.UpdateWorkspaceInvoiceFieldInitialValueParams;
     [WRITE_COMMANDS.ENABLE_WORKSPACE_REPORT_FIELD_LIST_VALUE]: Parameters.EnableWorkspaceReportFieldListValueParams;
-    [WRITE_COMMANDS.ENABLE_WORKSPACE_INVOICE_FIELD_LIST_VALUE]: Parameters.EnableWorkspaceInvoiceFieldListValueParams;
     [WRITE_COMMANDS.CREATE_WORKSPACE_REPORT_FIELD_LIST_VALUE]: Parameters.CreateWorkspaceReportFieldListValueParams;
-    [WRITE_COMMANDS.CREATE_WORKSPACE_INVOICE_FIELD_LIST_VALUE]: Parameters.CreateWorkspaceInvoiceFieldListValueParams;
     [WRITE_COMMANDS.REMOVE_WORKSPACE_REPORT_FIELD_LIST_VALUE]: Parameters.RemoveWorkspaceReportFieldListValueParams;
-    [WRITE_COMMANDS.REMOVE_WORKSPACE_INVOICE_FIELD_LIST_VALUE]: Parameters.RemoveWorkspaceInvoiceFieldListValueParams;
 
     [WRITE_COMMANDS.UPDATE_NETSUITE_SYNC_TAX_CONFIGURATION]: Parameters.UpdateNetSuiteGenericTypeParams<'enabled', boolean>;
     [WRITE_COMMANDS.UPDATE_SAGE_INTACCT_TAX_SOLUTION_ID]: Parameters.UpdateNetSuiteGenericTypeParams<'taxSolutionID', string>;
@@ -1369,7 +1355,6 @@ const READ_COMMANDS = {
     OPEN_POLICY_TAGS_PAGE: 'OpenPolicyTagsPage',
     OPEN_POLICY_TAXES_PAGE: 'OpenPolicyTaxesPage',
     OPEN_POLICY_REPORT_FIELDS_PAGE: 'OpenPolicyReportFieldsPage',
-    OPEN_POLICY_INVOICES_PAGE: 'OpenPolicyInvoicesPage',
     OPEN_POLICY_RULES_PAGE: 'OpenPolicyRulesPage',
     OPEN_POLICY_EXPENSIFY_CARDS_PAGE: 'OpenPolicyExpensifyCardsPage',
     OPEN_POLICY_TRAVEL_PAGE: 'OpenPolicyTravelPage',
@@ -1474,7 +1459,6 @@ type ReadCommandParameters = {
     [READ_COMMANDS.OPEN_POLICY_TAGS_PAGE]: Parameters.OpenPolicyTagsPageParams;
     [READ_COMMANDS.OPEN_POLICY_TAXES_PAGE]: Parameters.OpenPolicyTaxesPageParams;
     [READ_COMMANDS.OPEN_POLICY_REPORT_FIELDS_PAGE]: Parameters.OpenPolicyReportFieldsPageParams;
-    [READ_COMMANDS.OPEN_POLICY_INVOICES_PAGE]: Parameters.OpenPolicyReportFieldsPageParams;
     [READ_COMMANDS.OPEN_POLICY_RULES_PAGE]: Parameters.OpenPolicyRulesPageParams;
     [READ_COMMANDS.OPEN_WORKSPACE_INVITE_PAGE]: Parameters.OpenWorkspaceInvitePageParams;
     [READ_COMMANDS.OPEN_DRAFT_WORKSPACE_REQUEST]: Parameters.OpenDraftWorkspaceRequestParams;
diff --git a/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx b/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx
index 6a86b048a5dc..094b8b7bf072 100644
--- a/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx
+++ b/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx
@@ -999,13 +999,6 @@ const SettingsModalStackNavigator = createModalStackNavigator<SettingsNavigatorP
     [SCREENS.WORKSPACE.REPORT_FIELDS_VALUE_SETTINGS]: () => require<ReactComponentModule>('../../../../pages/workspace/reports/ReportFieldsValueSettingsPage').default,
     [SCREENS.WORKSPACE.REPORT_FIELDS_EDIT_INITIAL_VALUE]: () => require<ReactComponentModule>('../../../../pages/workspace/reports/ReportFieldsInitialValuePage').default,
     [SCREENS.WORKSPACE.REPORT_FIELDS_EDIT_VALUE]: () => require<ReactComponentModule>('../../../../pages/workspace/reports/ReportFieldsEditValuePage').default,
-    [SCREENS.WORKSPACE.INVOICE_FIELDS_CREATE]: () => require<ReactComponentModule>('../../../../pages/workspace/invoices/CreateInvoiceFieldsPage').default,
-    [SCREENS.WORKSPACE.INVOICE_FIELDS_SETTINGS]: () => require<ReactComponentModule>('../../../../pages/workspace/invoices/InvoiceFieldsSettingsPage').default,
-    [SCREENS.WORKSPACE.INVOICE_FIELDS_LIST_VALUES]: () => require<ReactComponentModule>('../../../../pages/workspace/invoices/InvoiceFieldsListValuesPage').default,
-    [SCREENS.WORKSPACE.INVOICE_FIELDS_ADD_VALUE]: () => require<ReactComponentModule>('../../../../pages/workspace/invoices/InvoiceFieldsAddListValuePage').default,
-    [SCREENS.WORKSPACE.INVOICE_FIELDS_VALUE_SETTINGS]: () => require<ReactComponentModule>('../../../../pages/workspace/invoices/InvoiceFieldsValueSettingsPage').default,
-    [SCREENS.WORKSPACE.INVOICE_FIELDS_EDIT_INITIAL_VALUE]: () => require<ReactComponentModule>('../../../../pages/workspace/invoices/InvoiceFieldsInitialValuePage').default,
-    [SCREENS.WORKSPACE.INVOICE_FIELDS_EDIT_VALUE]: () => require<ReactComponentModule>('../../../../pages/workspace/invoices/InvoiceFieldsEditValuePage').default,
     [SCREENS.WORKSPACE.ACCOUNTING.CERTINIA_IMPORT]: () => require<ReactComponentModule>('../../../../pages/workspace/accounting/certinia/import/CertiniaImportPage').default,
     [SCREENS.WORKSPACE.ACCOUNTING.CERTINIA_DIMENSION_MAPPING]: () =>
         require<ReactComponentModule>('../../../../pages/workspace/accounting/certinia/import/CertiniaDimensionMappingPage').default,
diff --git a/src/libs/Navigation/linkingConfig/RELATIONS/WORKSPACE_TO_RHP.ts b/src/libs/Navigation/linkingConfig/RELATIONS/WORKSPACE_TO_RHP.ts
index d826e3285910..a1d83a6686b7 100755
--- a/src/libs/Navigation/linkingConfig/RELATIONS/WORKSPACE_TO_RHP.ts
+++ b/src/libs/Navigation/linkingConfig/RELATIONS/WORKSPACE_TO_RHP.ts
@@ -297,18 +297,7 @@ const WORKSPACE_TO_RHP: Partial<Record<keyof WorkspaceSplitNavigatorParamList, s
         SCREENS.WORKSPACE.REPORT_FIELDS_EDIT_VALUE,
         SCREENS.WORKSPACE.REPORT_FIELDS_EDIT_INITIAL_VALUE,
     ],
-    [SCREENS.WORKSPACE.INVOICES]: [
-        SCREENS.WORKSPACE.INVOICES_COMPANY_NAME,
-        SCREENS.WORKSPACE.INVOICES_COMPANY_WEBSITE,
-        SCREENS.WORKSPACE.INVOICES_VERIFY_ACCOUNT,
-        SCREENS.WORKSPACE.INVOICE_FIELDS_CREATE,
-        SCREENS.WORKSPACE.INVOICE_FIELDS_SETTINGS,
-        SCREENS.WORKSPACE.INVOICE_FIELDS_LIST_VALUES,
-        SCREENS.WORKSPACE.INVOICE_FIELDS_ADD_VALUE,
-        SCREENS.WORKSPACE.INVOICE_FIELDS_VALUE_SETTINGS,
-        SCREENS.WORKSPACE.INVOICE_FIELDS_EDIT_VALUE,
-        SCREENS.WORKSPACE.INVOICE_FIELDS_EDIT_INITIAL_VALUE,
-    ],
+    [SCREENS.WORKSPACE.INVOICES]: [SCREENS.WORKSPACE.INVOICES_COMPANY_NAME, SCREENS.WORKSPACE.INVOICES_COMPANY_WEBSITE, SCREENS.WORKSPACE.INVOICES_VERIFY_ACCOUNT],
     [SCREENS.WORKSPACE.COMPANY_CARDS]: [
         SCREENS.WORKSPACE.DYNAMIC_WORKSPACE_COMPANY_CARDS_ADD_NEW,
         SCREENS.WORKSPACE.COMPANY_CARDS_IMPORT_SPREADSHEET,
diff --git a/src/libs/Navigation/linkingConfig/config.ts b/src/libs/Navigation/linkingConfig/config.ts
index 5709ca05c881..f1e6742a8883 100644
--- a/src/libs/Navigation/linkingConfig/config.ts
+++ b/src/libs/Navigation/linkingConfig/config.ts
@@ -833,27 +833,6 @@ const config: LinkingOptions<RootNavigatorParamList>['config'] = {
                             path: ROUTES.WORKSPACE_INVOICES_VERIFY_ACCOUNT.route,
                             exact: true,
                         },
-                        [SCREENS.WORKSPACE.INVOICE_FIELDS_CREATE]: {
-                            path: ROUTES.WORKSPACE_INVOICE_FIELDS_CREATE.route,
-                        },
-                        [SCREENS.WORKSPACE.INVOICE_FIELDS_LIST_VALUES]: {
-                            path: ROUTES.WORKSPACE_INVOICE_FIELDS_LIST_VALUES.route,
-                        },
-                        [SCREENS.WORKSPACE.INVOICE_FIELDS_ADD_VALUE]: {
-                            path: ROUTES.WORKSPACE_INVOICE_FIELDS_ADD_VALUE.route,
-                        },
-                        [SCREENS.WORKSPACE.INVOICE_FIELDS_VALUE_SETTINGS]: {
-                            path: ROUTES.WORKSPACE_INVOICE_FIELDS_VALUE_SETTINGS.route,
-                        },
-                        [SCREENS.WORKSPACE.INVOICE_FIELDS_EDIT_VALUE]: {
-                            path: ROUTES.WORKSPACE_INVOICE_FIELDS_EDIT_VALUE.route,
-                        },
-                        [SCREENS.WORKSPACE.INVOICE_FIELDS_SETTINGS]: {
-                            path: ROUTES.WORKSPACE_INVOICE_FIELDS_SETTINGS.route,
-                        },
-                        [SCREENS.WORKSPACE.INVOICE_FIELDS_EDIT_INITIAL_VALUE]: {
-                            path: ROUTES.WORKSPACE_INVOICE_FIELDS_EDIT_INITIAL_VALUE.route,
-                        },
                         [SCREENS.WORKSPACE.COMPANY_CARDS_SELECT_FEED]: {
                             path: ROUTES.WORKSPACE_COMPANY_CARDS_SELECT_FEED.route,
                         },
diff --git a/src/libs/Navigation/types.ts b/src/libs/Navigation/types.ts
index f74a385b909c..8419fbef5844 100644
--- a/src/libs/Navigation/types.ts
+++ b/src/libs/Navigation/types.ts
@@ -644,59 +644,31 @@ type SettingsNavigatorParamList = {
     [SCREENS.WORKSPACE.REPORT_FIELDS_CREATE]: {
         policyID: string;
     };
-    [SCREENS.WORKSPACE.INVOICE_FIELDS_CREATE]: {
-        policyID: string;
-    };
     [SCREENS.WORKSPACE.REPORT_FIELDS_LIST_VALUES]: {
         policyID: string;
         reportFieldID?: string;
     };
-    [SCREENS.WORKSPACE.INVOICE_FIELDS_LIST_VALUES]: {
-        policyID: string;
-        reportFieldID?: string;
-    };
     [SCREENS.WORKSPACE.REPORT_FIELDS_ADD_VALUE]: {
         policyID: string;
         reportFieldID?: string;
     };
-    [SCREENS.WORKSPACE.INVOICE_FIELDS_ADD_VALUE]: {
-        policyID: string;
-        reportFieldID?: string;
-    };
     [SCREENS.WORKSPACE.REPORT_FIELDS_VALUE_SETTINGS]: {
         policyID: string;
         valueIndex: number;
         reportFieldID?: string;
     };
-    [SCREENS.WORKSPACE.INVOICE_FIELDS_VALUE_SETTINGS]: {
-        policyID: string;
-        valueIndex: number;
-        reportFieldID?: string;
-    };
     [SCREENS.WORKSPACE.REPORT_FIELDS_EDIT_VALUE]: {
         policyID: string;
         valueIndex: number;
     };
-    [SCREENS.WORKSPACE.INVOICE_FIELDS_EDIT_VALUE]: {
-        policyID: string;
-        valueIndex: number;
-    };
     [SCREENS.WORKSPACE.REPORT_FIELDS_SETTINGS]: {
         policyID: string;
         reportFieldID: string;
     };
-    [SCREENS.WORKSPACE.INVOICE_FIELDS_SETTINGS]: {
-        policyID: string;
-        reportFieldID: string;
-    };
     [SCREENS.WORKSPACE.REPORT_FIELDS_EDIT_INITIAL_VALUE]: {
         policyID: string;
         reportFieldID: string;
     };
-    [SCREENS.WORKSPACE.INVOICE_FIELDS_EDIT_INITIAL_VALUE]: {
-        policyID: string;
-        reportFieldID: string;
-    };
     [SCREENS.WORKSPACE.MEMBER_DETAILS]: {
         policyID: string;
         accountID: string;
diff --git a/src/libs/ReportUtils.ts b/src/libs/ReportUtils.ts
index a00a0a03aff4..effe2e58e972 100644
--- a/src/libs/ReportUtils.ts
+++ b/src/libs/ReportUtils.ts
@@ -4459,6 +4459,9 @@ function isHoldCreator(transaction: OnyxEntry<Transaction>, reportID: string | u
  * 2. Report is settled, closed, approved, or submitted and already forwarded for review
  */
 function isReportFieldDisabled(report: OnyxEntry<Report>, reportField: OnyxEntry<PolicyReportField>, policy: OnyxEntry<Policy>): boolean {
+    if (isInvoiceReport(report)) {
+        return true;
+    }
     const isReportSettled = isSettled(report?.reportID);
     const isReportClosed = isClosedReport(report);
     const isTitleField = isReportFieldOfTypeTitle(reportField);
@@ -4577,7 +4580,7 @@ function getAvailableReportFields(report: OnyxEntry<Report>, policyReportFields:
     const mergedFieldIds = Array.from(new Set([...policyReportFields.map(({fieldID}) => fieldID), ...reportFields.map(({fieldID}) => fieldID)]));
 
     const fields = mergedFieldIds.map((id) => {
-        const field = report?.fieldList?.[getReportFieldKey(id)] ?? report?.fieldList?.[id];
+        const field = report?.fieldList?.[getReportFieldKey(id)];
         const policyReportField = policyReportFields.find(({fieldID}) => fieldID === id);
 
         if (field) {
@@ -12889,39 +12892,19 @@ function shouldHideSingleReportField(reportField: PolicyReportField) {
     return isReportFieldOfTypeTitle(reportField) || !hasEnableOption;
 }
 
-function isReportNameValuePairField(value: unknown): value is PolicyReportField {
-    return typeof value === 'object' && value !== null && 'fieldID' in value && typeof value.fieldID === 'string' && 'name' in value && typeof value.name === 'string';
-}
-
-function getReportFieldFromReportNameValuePairs(reportNameValuePairs: OnyxEntry<ReportNameValuePairs>, reportFieldIDOrKey: string): PolicyReportField | undefined {
-    for (const [key, value] of Object.entries(reportNameValuePairs ?? {})) {
-        if (key === reportFieldIDOrKey && isReportNameValuePairField(value)) {
-            return value;
-        }
-    }
-
-    return undefined;
-}
-
 /**
  * Get both field values map and fields-by-name map in a single pass
  */
 function getReportFieldMaps(report: OnyxEntry<Report>, fieldList: Record<string, PolicyReportField>): {fieldValues: Record<string, string>; fieldsByName: Record<string, PolicyReportField>} {
     const fields = getAvailableReportFields(report, Object.values(fieldList ?? {}));
-    const reportNameValuePairs = allReportNameValuePair?.[`${ONYXKEYS.COLLECTION.REPORT_NAME_VALUE_PAIRS}${report?.reportID}`];
     const fieldValues: Record<string, string> = {};
     const fieldsByName: Record<string, PolicyReportField> = {};
 
     for (const field of fields) {
         if (field.name) {
-            const fieldKey = getReportFieldKey(field.fieldID);
-            const shouldReadReportNameValuePair = report?.type === CONST.REPORT.TYPE.INVOICE && field.target === CONST.REPORT_FIELD_TARGETS.INVOICE;
-            const reportNameValuePairField = shouldReadReportNameValuePair
-                ? (getReportFieldFromReportNameValuePairs(reportNameValuePairs, fieldKey) ?? getReportFieldFromReportNameValuePairs(reportNameValuePairs, field.fieldID))
-                : undefined;
             const key = field.name.toLowerCase();
-            fieldValues[key] = reportNameValuePairField?.value ?? field.value ?? field.defaultValue ?? '';
-            fieldsByName[key] = reportNameValuePairField ? {...field, value: reportNameValuePairField.value} : field;
+            fieldValues[key] = field.value ?? field.defaultValue ?? '';
+            fieldsByName[key] = field;
         }
     }
 
@@ -13355,7 +13338,6 @@ export {
     buildOptimisticResolvedDuplicatesReportAction,
     getTitleReportField,
     getTitleFieldWithFallback,
-    getReportFieldFromReportNameValuePairs,
     getReportFieldsByPolicyID,
     getChatListItemReportName,
     buildOptimisticMovedTransactionAction,
diff --git a/src/libs/WorkspaceReportFieldUtils.ts b/src/libs/WorkspaceReportFieldUtils.ts
index 306bd7048a3c..a7d127e9d728 100644
--- a/src/libs/WorkspaceReportFieldUtils.ts
+++ b/src/libs/WorkspaceReportFieldUtils.ts
@@ -1,4 +1,3 @@
-import type {ValueOf} from 'type-fest';
 import type {FormInputErrors} from '@components/Form/types';
 import type {LocalizedTranslate} from '@components/LocaleContextProvider';
 import CONST from '@src/CONST';
@@ -64,9 +63,8 @@ function validateReportFieldListValueName(
 /**
  * Generates a field ID based on the field name.
  */
-function generateFieldID(name: string, target?: ValueOf<typeof CONST.REPORT_FIELD_TARGETS>) {
-    const targetPrefix = target ? `${target.toUpperCase()}_` : '';
-    return `field_id_${targetPrefix}${name.replaceAll(CONST.REGEX.ANY_SPACE, '_').toUpperCase()}`;
+function generateFieldID(name: string) {
+    return `field_id_${name.replaceAll(CONST.REGEX.ANY_SPACE, '_').toUpperCase()}`;
 }
 
 /**
@@ -108,33 +106,8 @@ function hasFormulaPartsInInitialValue(initialValue?: string): boolean {
 /**
  * Checks if a report field name already exists in the policy's field list (case-insensitive).
  */
-function isReportFieldNameExisting(fieldList: Record<string, PolicyReportField> | undefined, fieldName: string, expectedTarget?: ValueOf<typeof CONST.REPORT_FIELD_TARGETS>): boolean {
-    return Object.values(fieldList ?? {}).some((reportField) => {
-        if (!isReportFieldTargetValid(reportField, expectedTarget)) {
-            return false;
-        }
-
-        return reportField.name.toLowerCase() === fieldName.toLowerCase();
-    });
-}
-
-/**
- * Determines whether a report field matches the expected target.
- */
-function isReportFieldTargetValid(reportField: PolicyReportField | null, expectedTarget?: ValueOf<typeof CONST.REPORT_FIELD_TARGETS>): boolean {
-    if (!reportField) {
-        return false;
-    }
-
-    if (expectedTarget === CONST.REPORT_FIELD_TARGETS.INVOICE) {
-        return reportField.target === CONST.REPORT_FIELD_TARGETS.INVOICE;
-    }
-
-    if (expectedTarget === CONST.REPORT_FIELD_TARGETS.EXPENSE) {
-        return !reportField.target || reportField.target === CONST.REPORT_FIELD_TARGETS.EXPENSE;
-    }
-
-    return true;
+function isReportFieldNameExisting(fieldList: Record<string, PolicyReportField> | undefined, fieldName: string): boolean {
+    return Object.values(fieldList ?? {}).some((reportField) => reportField.name.toLowerCase() === fieldName.toLowerCase());
 }
 
 /**
@@ -245,5 +218,4 @@ export {
     getUnsupportedReportFieldFormulaParts,
     hasFormulaPartsInInitialValue,
     isReportFieldNameExisting,
-    isReportFieldTargetValid,
 };
diff --git a/src/libs/actions/Policy/Policy.ts b/src/libs/actions/Policy/Policy.ts
index 887e7f1d1951..ad7bfe87022b 100644
--- a/src/libs/actions/Policy/Policy.ts
+++ b/src/libs/actions/Policy/Policy.ts
@@ -29,7 +29,6 @@ import type {
     EnablePolicyConnectionsParams,
     EnablePolicyExpensifyCardsParams,
     EnablePolicyHRParams,
-    EnablePolicyInvoiceFieldsParams,
     EnablePolicyInvoicingParams,
     EnablePolicyReportFieldsParams,
     EnablePolicyTaxesParams,
@@ -4902,19 +4901,16 @@ function enableCompanyCards(policyID: string, enabled: boolean, shouldGoBack = t
     }
 }
 
-function enablePolicyFields(policyID: string, enabled: boolean, command: typeof WRITE_COMMANDS.ENABLE_POLICY_REPORT_FIELDS | typeof WRITE_COMMANDS.ENABLE_POLICY_INVOICE_FIELDS) {
-    const enableFieldKey =
-        command === WRITE_COMMANDS.ENABLE_POLICY_INVOICE_FIELDS ? CONST.POLICY.MORE_FEATURES.ARE_INVOICE_FIELDS_ENABLED : CONST.POLICY.MORE_FEATURES.ARE_REPORT_FIELDS_ENABLED;
-
+function enablePolicyReportFields(policyID: string, enabled: boolean) {
     const onyxData: OnyxData<typeof ONYXKEYS.COLLECTION.POLICY> = {
         optimisticData: [
             {
                 onyxMethod: Onyx.METHOD.MERGE,
                 key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`,
                 value: {
-                    [enableFieldKey]: enabled,
+                    areReportFieldsEnabled: enabled,
                     pendingFields: {
-                        [enableFieldKey]: CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE,
+                        areReportFieldsEnabled: CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE,
                     },
                 },
             },
@@ -4925,7 +4921,7 @@ function enablePolicyFields(policyID: string, enabled: boolean, command: typeof
                 key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`,
                 value: {
                     pendingFields: {
-                        [enableFieldKey]: null,
+                        areReportFieldsEnabled: null,
                     },
                 },
             },
@@ -4935,26 +4931,18 @@ function enablePolicyFields(policyID: string, enabled: boolean, command: typeof
                 onyxMethod: Onyx.METHOD.MERGE,
                 key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`,
                 value: {
-                    [enableFieldKey]: !enabled,
+                    areReportFieldsEnabled: !enabled,
                     pendingFields: {
-                        [enableFieldKey]: null,
+                        areReportFieldsEnabled: null,
                     },
                 },
             },
         ],
     };
 
-    const parameters: EnablePolicyReportFieldsParams | EnablePolicyInvoiceFieldsParams = {policyID, enabled};
-
-    API.writeWithNoDuplicatesEnableFeatureConflicts(command, parameters, onyxData);
-}
-
-function enablePolicyReportFields(policyID: string, enabled: boolean) {
-    enablePolicyFields(policyID, enabled, WRITE_COMMANDS.ENABLE_POLICY_REPORT_FIELDS);
-}
+    const parameters: EnablePolicyReportFieldsParams = {policyID, enabled};
 
-function enablePolicyInvoiceFields(policyID: string, enabled: boolean) {
-    enablePolicyFields(policyID, enabled, WRITE_COMMANDS.ENABLE_POLICY_INVOICE_FIELDS);
+    API.writeWithNoDuplicatesEnableFeatureConflicts(WRITE_COMMANDS.ENABLE_POLICY_REPORT_FIELDS, parameters, onyxData);
 }
 
 function enablePolicyTaxes(policyID: string, enabled: true, currentTaxRates: TaxRatesWithDefault | undefined): void;
@@ -7544,7 +7532,6 @@ export {
     enablePolicyHR,
     enablePolicyReceiptPartners,
     enablePolicyReportFields,
-    enablePolicyInvoiceFields,
     enablePolicyTaxes,
     enablePolicyWorkflows,
     enablePolicyTimeTracking,
diff --git a/src/libs/actions/Policy/ReportField.ts b/src/libs/actions/Policy/ReportField.ts
index 27d182329f0c..b802d6a4a1d2 100644
--- a/src/libs/actions/Policy/ReportField.ts
+++ b/src/libs/actions/Policy/ReportField.ts
@@ -3,18 +3,12 @@ import type {OnyxEntry, OnyxUpdate} from 'react-native-onyx';
 import Onyx from 'react-native-onyx';
 import * as API from '@libs/API';
 import type {
-    CreateWorkspaceInvoiceFieldListValueParams,
-    CreateWorkspaceInvoiceFieldParams,
     CreateWorkspaceReportFieldListValueParams,
     CreateWorkspaceReportFieldParams,
-    DeletePolicyInvoiceField,
     DeletePolicyReportField,
-    EnableWorkspaceInvoiceFieldListValueParams,
     EnableWorkspaceReportFieldListValueParams,
     OpenPolicyReportFieldsPageParams,
-    RemoveWorkspaceInvoiceFieldListValueParams,
     RemoveWorkspaceReportFieldListValueParams,
-    UpdateWorkspaceInvoiceFieldInitialValueParams,
     UpdateWorkspaceReportFieldInitialValueParams,
 } from '@libs/API/parameters';
 import {READ_COMMANDS, WRITE_COMMANDS} from '@libs/API/types';
@@ -57,8 +51,7 @@ type DeleteReportFieldsListValueParams = {
 type CreateReportFieldParams = Pick<WorkspaceReportFieldForm, 'name' | 'type' | 'initialValue'> & {
     listValues: string[];
     disabledListValues: boolean[];
-    policyReportIDs: Array<string | undefined> | undefined;
-    isInvoiceField?: boolean;
+    policyExpenseReportIDs: Array<string | undefined> | undefined;
     policy: OnyxEntry<Policy>;
 };
 
@@ -105,19 +98,6 @@ function openPolicyReportFieldsPage(policyID: string) {
     API.read(READ_COMMANDS.OPEN_POLICY_REPORT_FIELDS_PAGE, params);
 }
 
-function openPolicyInvoicesPage(policyID: string) {
-    if (!policyID) {
-        Log.warn('openPolicyInvoicesPage invalid params', {policyID});
-        return;
-    }
-
-    const params: OpenPolicyReportFieldsPageParams = {
-        policyID,
-    };
-
-    API.read(READ_COMMANDS.OPEN_POLICY_INVOICES_PAGE, params);
-}
-
 /**
  * Sets the initial form values for the workspace report fields form.
  */
@@ -185,19 +165,14 @@ function deleteReportFieldsListValue({valueIndexes, listValues, disabledListValu
 /**
  * Creates a new report field.
  */
-function createReportField({name, type, initialValue, listValues, disabledListValues, policyReportIDs, isInvoiceField = false, policy}: CreateReportFieldParams) {
+function createReportField({name, type, initialValue, listValues, disabledListValues, policyExpenseReportIDs, policy}: CreateReportFieldParams) {
     if (!policy) {
         Log.warn('Policy data is not present');
         return;
     }
 
     const previousFieldList = policy?.fieldList ?? {};
-    const target = isInvoiceField ? CONST.REPORT_FIELD_TARGETS.INVOICE : CONST.REPORT_FIELD_TARGETS.EXPENSE;
-    const defaultFieldID = WorkspaceReportFieldUtils.generateFieldID(name);
-    const defaultFieldKey = ReportUtils.getReportFieldKey(defaultFieldID);
-    const defaultField = previousFieldList[defaultFieldKey];
-    const shouldUseTargetSpecificFieldID = isInvoiceField || (defaultField && !WorkspaceReportFieldUtils.isReportFieldTargetValid(defaultField, target));
-    const fieldID = shouldUseTargetSpecificFieldID ? WorkspaceReportFieldUtils.generateFieldID(name, target) : defaultFieldID;
+    const fieldID = WorkspaceReportFieldUtils.generateFieldID(name);
     const fieldKey = ReportUtils.getReportFieldKey(fieldID);
 
     // User selected type Text but entered a formula Initial value, treat it as a Formula type for optimistic UI
@@ -207,7 +182,7 @@ function createReportField({name, type, initialValue, listValues, disabledListVa
     const optimisticReportFieldDataForPolicy: Omit<OnyxValueWithOfflineFeedback<PolicyReportField>, 'value'> = {
         name,
         type: optimisticType,
-        target,
+        target: 'expense',
         defaultValue: initialValue,
         values: listValues,
         disabledOptions: disabledListValues,
@@ -230,7 +205,7 @@ function createReportField({name, type, initialValue, listValues, disabledListVa
                 errorFields: null,
             },
         },
-        ...(policyReportIDs ?? []).map(
+        ...(policyExpenseReportIDs ?? []).map(
             (reportID): OnyxUpdate<typeof ONYXKEYS.COLLECTION.REPORT> => ({
                 key: `${ONYXKEYS.COLLECTION.REPORT}${reportID}`,
                 onyxMethod: Onyx.METHOD.MERGE,
@@ -256,7 +231,7 @@ function createReportField({name, type, initialValue, listValues, disabledListVa
                 },
             },
         },
-        ...(policyReportIDs ?? []).map(
+        ...(policyExpenseReportIDs ?? []).map(
             (reportID): OnyxUpdate<typeof ONYXKEYS.COLLECTION.REPORT> => ({
                 key: `${ONYXKEYS.COLLECTION.REPORT}${reportID}`,
                 onyxMethod: Onyx.METHOD.MERGE,
@@ -286,18 +261,12 @@ function createReportField({name, type, initialValue, listValues, disabledListVa
         failureData,
     };
 
-    const parameters: CreateWorkspaceReportFieldParams | CreateWorkspaceInvoiceFieldParams = isInvoiceField
-        ? {
-              policyID: policy?.id,
-              invoiceFields: JSON.stringify([optimisticReportFieldDataForPolicy]),
-          }
-        : {
-              policyID: policy?.id,
-              reportFields: JSON.stringify([optimisticReportFieldDataForPolicy]),
-          };
-
-    const createCommand = isInvoiceField ? WRITE_COMMANDS.CREATE_WORKSPACE_INVOICE_FIELD : WRITE_COMMANDS.CREATE_WORKSPACE_REPORT_FIELD;
-    API.write(createCommand, parameters, onyxData);
+    const parameters: CreateWorkspaceReportFieldParams = {
+        policyID: policy?.id,
+        reportFields: JSON.stringify([optimisticReportFieldDataForPolicy]),
+    };
+
+    API.write(WRITE_COMMANDS.CREATE_WORKSPACE_REPORT_FIELD, parameters, onyxData);
 }
 
 function deleteReportFields({policy, reportFieldsToUpdate}: DeleteReportFieldsParams) {
@@ -307,24 +276,19 @@ function deleteReportFields({policy, reportFieldsToUpdate}: DeleteReportFieldsPa
     }
 
     const allReportFields = policy?.fieldList ?? {};
-    const resolvedReportFieldKeys = reportFieldsToUpdate.filter((reportFieldKey) => !!allReportFields[reportFieldKey]);
-    if (resolvedReportFieldKeys.length === 0) {
-        Log.warn('No valid report fields to delete', {reportFieldsToUpdate});
-        return;
-    }
 
-    const updatedReportFields = Object.fromEntries(Object.entries(allReportFields).filter(([key]) => !resolvedReportFieldKeys.includes(key)));
-    const optimisticReportFields = resolvedReportFieldKeys.reduce<Record<string, Partial<OnyxValueWithOfflineFeedback<PolicyReportField>>>>((acc, reportFieldKey) => {
+    const updatedReportFields = Object.fromEntries(Object.entries(allReportFields).filter(([key]) => !reportFieldsToUpdate.includes(key)));
+    const optimisticReportFields = reportFieldsToUpdate.reduce<Record<string, Partial<OnyxValueWithOfflineFeedback<PolicyReportField>>>>((acc, reportFieldKey) => {
         acc[reportFieldKey] = {pendingAction: CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE};
         return acc;
     }, {});
 
-    const successReportFields = resolvedReportFieldKeys.reduce<Record<string, null>>((acc, reportFieldKey) => {
+    const successReportFields = reportFieldsToUpdate.reduce<Record<string, null>>((acc, reportFieldKey) => {
         acc[reportFieldKey] = null;
         return acc;
     }, {});
 
-    const failureReportFields = resolvedReportFieldKeys.reduce<Record<string, Partial<OnyxValueWithOfflineFeedback<PolicyReportField>>>>((acc, reportFieldKey) => {
+    const failureReportFields = reportFieldsToUpdate.reduce<Record<string, Partial<OnyxValueWithOfflineFeedback<PolicyReportField>>>>((acc, reportFieldKey) => {
         acc[reportFieldKey] = {pendingAction: null};
         return acc;
     }, {});
@@ -363,24 +327,12 @@ function deleteReportFields({policy, reportFieldsToUpdate}: DeleteReportFieldsPa
         ],
     };
 
-    const fieldsToDelete = resolvedReportFieldKeys.map((reportFieldKey) => allReportFields[reportFieldKey]).filter((reportField): reportField is PolicyReportField => !!reportField);
-    const isInvoiceField = fieldsToDelete.length > 0 && fieldsToDelete.every((reportField) => reportField.target === CONST.REPORT_FIELD_TARGETS.INVOICE);
-    const updatedReportFieldsValues = Object.values(updatedReportFields);
-    const remainingInvoiceFields = updatedReportFieldsValues.filter((reportField) => reportField.target === CONST.REPORT_FIELD_TARGETS.INVOICE);
-    const remainingExpenseFields = updatedReportFieldsValues.filter((reportField) => !reportField.target || reportField.target === CONST.REPORT_FIELD_TARGETS.EXPENSE);
-    const invoiceFieldsPayload = remainingInvoiceFields;
-    const parameters: DeletePolicyReportField | DeletePolicyInvoiceField = isInvoiceField
-        ? {
-              policyID: policy?.id,
-              invoiceFields: JSON.stringify(invoiceFieldsPayload),
-          }
-        : {
-              policyID: policy?.id,
-              reportFields: JSON.stringify(remainingExpenseFields),
-          };
-    const deleteCommand = isInvoiceField ? WRITE_COMMANDS.DELETE_POLICY_INVOICE_FIELD : WRITE_COMMANDS.DELETE_POLICY_REPORT_FIELD;
-
-    API.write(deleteCommand, parameters, onyxData);
+    const parameters: DeletePolicyReportField = {
+        policyID: policy?.id,
+        reportFields: JSON.stringify(Object.values(updatedReportFields)),
+    };
+
+    API.write(WRITE_COMMANDS.DELETE_POLICY_REPORT_FIELD, parameters, onyxData);
 }
 
 /**
@@ -448,19 +400,12 @@ function updateReportFieldInitialValue({policy, reportFieldID, newInitialValue}:
             },
         ],
     };
-    const isInvoiceField = updatedReportField?.target === CONST.REPORT_FIELD_TARGETS.INVOICE;
-    const parameters: UpdateWorkspaceReportFieldInitialValueParams | UpdateWorkspaceInvoiceFieldInitialValueParams = isInvoiceField
-        ? {
-              policyID: policy?.id,
-              invoiceFields: JSON.stringify([updatedReportField]),
-          }
-        : {
-              policyID: policy?.id,
-              reportFields: JSON.stringify([updatedReportField]),
-          };
-    const updateCommand = isInvoiceField ? WRITE_COMMANDS.UPDATE_WORKSPACE_INVOICE_FIELD_INITIAL_VALUE : WRITE_COMMANDS.UPDATE_WORKSPACE_REPORT_FIELD_INITIAL_VALUE;
-
-    API.write(updateCommand, parameters, onyxData);
+    const parameters: UpdateWorkspaceReportFieldInitialValueParams = {
+        policyID: policy?.id,
+        reportFields: JSON.stringify([updatedReportField]),
+    };
+
+    API.write(WRITE_COMMANDS.UPDATE_WORKSPACE_REPORT_FIELD_INITIAL_VALUE, parameters, onyxData);
 }
 
 function updateReportFieldListValueEnabled({policy, reportFieldID, valueIndexes, enabled}: UpdateReportFieldListValueEnabledParams) {
@@ -499,19 +444,12 @@ function updateReportFieldListValueEnabled({policy, reportFieldID, valueIndexes,
         ],
     };
 
-    const isInvoiceField = reportField?.target === CONST.REPORT_FIELD_TARGETS.INVOICE;
-    const parameters: EnableWorkspaceReportFieldListValueParams | EnableWorkspaceInvoiceFieldListValueParams = isInvoiceField
-        ? {
-              policyID: policy?.id,
-              invoiceFields: JSON.stringify([updatedReportField]),
-          }
-        : {
-              policyID: policy?.id,
-              reportFields: JSON.stringify([updatedReportField]),
-          };
-    const enableCommand = isInvoiceField ? WRITE_COMMANDS.ENABLE_WORKSPACE_INVOICE_FIELD_LIST_VALUE : WRITE_COMMANDS.ENABLE_WORKSPACE_REPORT_FIELD_LIST_VALUE;
-
-    API.write(enableCommand, parameters, onyxData);
+    const parameters: EnableWorkspaceReportFieldListValueParams = {
+        policyID: policy?.id,
+        reportFields: JSON.stringify([updatedReportField]),
+    };
+
+    API.write(WRITE_COMMANDS.ENABLE_WORKSPACE_REPORT_FIELD_LIST_VALUE, parameters, onyxData);
 }
 
 /**
@@ -546,19 +484,12 @@ function addReportFieldListValue({policy, reportFieldID, valueName}: AddReportFi
         ],
     };
 
-    const isInvoiceField = reportField?.target === CONST.REPORT_FIELD_TARGETS.INVOICE;
-    const parameters: CreateWorkspaceReportFieldListValueParams | CreateWorkspaceInvoiceFieldListValueParams = isInvoiceField
-        ? {
-              policyID: policy?.id,
-              invoiceFields: JSON.stringify([updatedReportField]),
-          }
-        : {
-              policyID: policy?.id,
-              reportFields: JSON.stringify([updatedReportField]),
-          };
-    const createCommand = isInvoiceField ? WRITE_COMMANDS.CREATE_WORKSPACE_INVOICE_FIELD_LIST_VALUE : WRITE_COMMANDS.CREATE_WORKSPACE_REPORT_FIELD_LIST_VALUE;
-
-    API.write(createCommand, parameters, onyxData);
+    const parameters: CreateWorkspaceReportFieldListValueParams = {
+        policyID: policy?.id,
+        reportFields: JSON.stringify([updatedReportField]),
+    };
+
+    API.write(WRITE_COMMANDS.CREATE_WORKSPACE_REPORT_FIELD_LIST_VALUE, parameters, onyxData);
 }
 
 /**
@@ -601,19 +532,12 @@ function removeReportFieldListValue({policy, reportFieldID, valueIndexes}: Remov
         ],
     };
 
-    const isInvoiceField = reportField?.target === CONST.REPORT_FIELD_TARGETS.INVOICE;
-    const parameters: RemoveWorkspaceReportFieldListValueParams | RemoveWorkspaceInvoiceFieldListValueParams = isInvoiceField
-        ? {
-              policyID: policy?.id,
-              invoiceFields: JSON.stringify([updatedReportField]),
-          }
-        : {
-              policyID: policy?.id,
-              reportFields: JSON.stringify([updatedReportField]),
-          };
-    const removeCommand = isInvoiceField ? WRITE_COMMANDS.REMOVE_WORKSPACE_INVOICE_FIELD_LIST_VALUE : WRITE_COMMANDS.REMOVE_WORKSPACE_REPORT_FIELD_LIST_VALUE;
-
-    API.write(removeCommand, parameters, onyxData);
+    const parameters: RemoveWorkspaceReportFieldListValueParams = {
+        policyID: policy?.id,
+        reportFields: JSON.stringify([updatedReportField]),
+    };
+
+    API.write(WRITE_COMMANDS.REMOVE_WORKSPACE_REPORT_FIELD_LIST_VALUE, parameters, onyxData);
 }
 
 export type {CreateReportFieldParams};
@@ -629,7 +553,6 @@ export {
     updateReportFieldInitialValue,
     updateReportFieldListValueEnabled,
     openPolicyReportFieldsPage,
-    openPolicyInvoicesPage,
     addReportFieldListValue,
     removeReportFieldListValue,
 };
diff --git a/src/libs/actions/RequestConflictUtils.ts b/src/libs/actions/RequestConflictUtils.ts
index f5b052d99230..b554ccdf42ec 100644
--- a/src/libs/actions/RequestConflictUtils.ts
+++ b/src/libs/actions/RequestConflictUtils.ts
@@ -32,7 +32,6 @@ const enablePolicyFeatureCommand = [
     WRITE_COMMANDS.ENABLE_POLICY_TAGS,
     WRITE_COMMANDS.ENABLE_POLICY_TAXES,
     WRITE_COMMANDS.ENABLE_POLICY_REPORT_FIELDS,
-    WRITE_COMMANDS.ENABLE_POLICY_INVOICE_FIELDS,
     WRITE_COMMANDS.ENABLE_POLICY_WORKFLOWS,
     WRITE_COMMANDS.SET_POLICY_RULES_ENABLED,
     WRITE_COMMANDS.ENABLE_POLICY_INVOICING,
diff --git a/src/pages/DynamicEditReportFieldPage.tsx b/src/pages/DynamicEditReportFieldPage.tsx
index d0aeb95db2ce..42cc4164dd24 100644
--- a/src/pages/DynamicEditReportFieldPage.tsx
+++ b/src/pages/DynamicEditReportFieldPage.tsx
@@ -23,7 +23,6 @@ import type {EditRequestNavigatorParamList} from '@libs/Navigation/types';
 import {isPolicyFieldListEmpty} from '@libs/PolicyUtils';
 import {getReportName as getReportNameFromReportNameUtils} from '@libs/ReportNameUtils';
 import {
-    getReportFieldFromReportNameValuePairs,
     getReportFieldKey,
     getTitleFieldWithFallback,
     hasViolations as hasViolationsReportUtils,
@@ -49,7 +48,6 @@ function DynamicEditReportFieldPage({route}: DynamicEditReportFieldPageProps) {
     const fieldKey = getReportFieldKey(route.params.fieldID);
     const backPath = useDynamicBackPath(DYNAMIC_ROUTES.EDIT_REPORT_FIELD.path);
     const [report] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${reportID}`);
-    const [reportNameValuePairs] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT_NAME_VALUE_PAIRS}${reportID}`);
     const [policy] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY}${policyID}`);
     const reportAttributesSelector = useCallback((attributes: OnyxEntry<ReportAttributesDerivedValue>) => reportByIDsSelector([reportID])(attributes), [reportID]);
     const [reportAttributesByReportID] = useOnyx(ONYXKEYS.DERIVED.REPORT_ATTRIBUTES, {
@@ -58,10 +56,8 @@ function DynamicEditReportFieldPage({route}: DynamicEditReportFieldPageProps) {
     const [recentlyUsedReportFields] = useOnyx(ONYXKEYS.RECENTLY_USED_REPORT_FIELDS);
 
     const isTitleField = route.params.fieldID === CONST.REPORT_FIELD_TITLE_FIELD_ID;
-    const reportFieldFromNVP = getReportFieldFromReportNameValuePairs(reportNameValuePairs, fieldKey) ?? getReportFieldFromReportNameValuePairs(reportNameValuePairs, route.params.fieldID);
-    let reportField =
-        reportFieldFromNVP ?? report?.fieldList?.[fieldKey] ?? report?.fieldList?.[route.params.fieldID] ?? policy?.fieldList?.[fieldKey] ?? policy?.fieldList?.[route.params.fieldID];
-    let policyField = policy?.fieldList?.[fieldKey] ?? policy?.fieldList?.[route.params.fieldID] ?? reportField;
+    let reportField = report?.fieldList?.[fieldKey] ?? policy?.fieldList?.[fieldKey];
+    let policyField = policy?.fieldList?.[fieldKey] ?? reportField;
 
     // If the title field is missing, use fallback so that it can still be edited and matches the OldDot behavior.
     if (isTitleField && !reportField && !policyField) {
@@ -81,8 +77,7 @@ function DynamicEditReportFieldPage({route}: DynamicEditReportFieldPageProps) {
     const {showConfirmModal} = useConfirmModal();
     const icons = useMemoizedLazyExpensifyIcons(['Trashcan']);
     const isReportFieldTitle = isReportFieldOfTypeTitle(reportField);
-    const isReportFieldsFeatureEnabled = report?.type === CONST.REPORT.TYPE.INVOICE ? policy?.areInvoiceFieldsEnabled : policy?.areReportFieldsEnabled;
-    const reportFieldsEnabled = ((isPaidGroupPolicyExpenseReport(report) || isInvoiceReport(report)) && !!isReportFieldsFeatureEnabled) || isReportFieldTitle;
+    const reportFieldsEnabled = ((isPaidGroupPolicyExpenseReport(report) || isInvoiceReport(report)) && !!policy?.areReportFieldsEnabled) || isReportFieldTitle;
     const hasOtherViolations =
         report?.fieldList && Object.entries(report.fieldList).some(([key, field]) => key !== fieldKey && field.value === '' && !isReportFieldDisabled(report, reportField, policy));
 
diff --git a/src/pages/workspace/fields/CreateFieldsPage.tsx b/src/pages/workspace/fields/CreateFieldsPage.tsx
deleted file mode 100644
index 31e063ec3206..000000000000
--- a/src/pages/workspace/fields/CreateFieldsPage.tsx
+++ /dev/null
@@ -1,284 +0,0 @@
-import React, {useCallback, useEffect, useMemo, useRef} from 'react';
-import {View} from 'react-native';
-import type {OnyxCollection, OnyxEntry} from 'react-native-onyx';
-import type {ValueOf} from 'type-fest';
-import FormProvider from '@components/Form/FormProvider';
-import InputWrapper from '@components/Form/InputWrapper';
-import type {FormInputErrors, FormOnyxValues, FormRef} from '@components/Form/types';
-import HeaderWithBackButton from '@components/HeaderWithBackButton';
-import MenuItemWithTopDescription from '@components/MenuItemWithTopDescription';
-import ScreenWrapper from '@components/ScreenWrapper';
-import TextPicker from '@components/TextPicker';
-import useLocalize from '@hooks/useLocalize';
-import useOnyx from '@hooks/useOnyx';
-import useThemeStyles from '@hooks/useThemeStyles';
-import DateUtils from '@libs/DateUtils';
-import {addErrorMessage} from '@libs/ErrorUtils';
-import {hasCircularReferences} from '@libs/Formula';
-import Navigation from '@libs/Navigation/Navigation';
-import {hasAccountingConnections} from '@libs/PolicyUtils';
-import {isRequiredFulfilled} from '@libs/ValidationUtils';
-import {getUnsupportedReportFieldFormulaParts, hasFormulaPartsInInitialValue, isReportFieldNameExisting} from '@libs/WorkspaceReportFieldUtils';
-import AccessOrNotFoundWrapper from '@pages/workspace/AccessOrNotFoundWrapper';
-import InitialListValueSelector from '@pages/workspace/reports/InitialListValueSelector';
-import TypeSelector from '@pages/workspace/reports/TypeSelector';
-import {createReportField, setInitialCreateReportFieldsForm} from '@userActions/Policy/ReportField';
-import CONST from '@src/CONST';
-import ONYXKEYS from '@src/ONYXKEYS';
-import type {Route as Routes} from '@src/ROUTES';
-import INPUT_IDS from '@src/types/form/WorkspaceReportFieldForm';
-import type {Policy, Report} from '@src/types/onyx';
-
-type CreateFieldsPageProps = {
-    policy: OnyxEntry<Policy>;
-    policyID: string;
-    isInvoiceField: boolean;
-    listValuesRoute: Routes;
-    featureName: ValueOf<typeof CONST.POLICY.MORE_FEATURES>;
-    testID: string;
-};
-
-const defaultDate = DateUtils.extractDate(new Date().toString());
-
-function CreateFieldsPage({policy, policyID, isInvoiceField, listValuesRoute, featureName, testID}: CreateFieldsPageProps) {
-    const styles = useThemeStyles();
-    const {translate, localeCompare} = useLocalize();
-    const formRef = useRef<FormRef>(null);
-    const [formDraft] = useOnyx(ONYXKEYS.FORMS.WORKSPACE_REPORT_FIELDS_FORM_DRAFT);
-
-    const reportTypeForTarget = useMemo(() => (isInvoiceField ? CONST.REPORT.TYPE.INVOICE : CONST.REPORT.TYPE.EXPENSE), [isInvoiceField]);
-    const fieldTarget = useMemo(() => (isInvoiceField ? CONST.REPORT_FIELD_TARGETS.INVOICE : CONST.REPORT_FIELD_TARGETS.EXPENSE), [isInvoiceField]);
-
-    const policyReportIDsSelector = useCallback(
-        (reports: OnyxCollection<Report>) =>
-            Object.values(reports ?? {})
-                .filter((report) => report?.policyID === policyID && report.type === reportTypeForTarget)
-                .map((report) => report?.reportID),
-        [policyID, reportTypeForTarget],
-    );
-
-    const [policyReportIDs] = useOnyx(ONYXKEYS.COLLECTION.REPORT, {selector: policyReportIDsSelector});
-
-    const availableListValuesLength = (formDraft?.[INPUT_IDS.DISABLED_LIST_VALUES] ?? []).filter((disabledListValue) => !disabledListValue).length;
-
-    const submitForm = useCallback(
-        (values: FormOnyxValues<typeof ONYXKEYS.FORMS.WORKSPACE_REPORT_FIELDS_FORM>) => {
-            const shouldClearListInitialValue = values[INPUT_IDS.TYPE] === CONST.REPORT_FIELD_TYPES.LIST && availableListValuesLength === 0;
-            createReportField({
-                policy,
-                name: values[INPUT_IDS.NAME],
-                type: values[INPUT_IDS.TYPE],
-                initialValue: shouldClearListInitialValue ? '' : values[INPUT_IDS.INITIAL_VALUE],
-                listValues: formDraft?.[INPUT_IDS.LIST_VALUES] ?? [],
-                disabledListValues: formDraft?.[INPUT_IDS.DISABLED_LIST_VALUES] ?? [],
-                policyReportIDs,
-                isInvoiceField,
-            });
-            Navigation.goBack();
-        },
-        [availableListValuesLength, formDraft, isInvoiceField, policy, policyReportIDs],
-    );
-
-    const validateForm = useCallback(
-        (values: FormOnyxValues<typeof ONYXKEYS.FORMS.WORKSPACE_REPORT_FIELDS_FORM>): FormInputErrors<typeof ONYXKEYS.FORMS.WORKSPACE_REPORT_FIELDS_FORM> => {
-            const {name, type, initialValue: formInitialValue} = values;
-            const errors: FormInputErrors<typeof ONYXKEYS.FORMS.WORKSPACE_REPORT_FIELDS_FORM> = {};
-
-            if (!isRequiredFulfilled(name)) {
-                errors[INPUT_IDS.NAME] = translate(isInvoiceField ? 'workspace.invoiceFields.invoiceFieldNameRequiredError' : 'workspace.reportFields.reportFieldNameRequiredError');
-            } else if (isReportFieldNameExisting(policy?.fieldList, name, fieldTarget)) {
-                errors[INPUT_IDS.NAME] = translate(isInvoiceField ? 'workspace.invoiceFields.existingInvoiceFieldNameError' : 'workspace.reportFields.existingReportFieldNameError');
-            } else if ([...name].length > CONST.WORKSPACE_REPORT_FIELD_POLICY_MAX_LENGTH) {
-                addErrorMessage(errors, INPUT_IDS.NAME, translate('common.error.characterLimitExceedCounter', [...name].length, CONST.WORKSPACE_REPORT_FIELD_POLICY_MAX_LENGTH));
-            }
-
-            if (!isRequiredFulfilled(type)) {
-                errors[INPUT_IDS.TYPE] = translate(isInvoiceField ? 'workspace.invoiceFields.invoiceFieldTypeRequiredError' : 'workspace.reportFields.reportFieldTypeRequiredError');
-            }
-
-            if (type === CONST.REPORT_FIELD_TYPES.TEXT && !!formInitialValue && formInitialValue.length > CONST.WORKSPACE_REPORT_FIELD_POLICY_MAX_LENGTH) {
-                errors[INPUT_IDS.INITIAL_VALUE] = translate('common.error.characterLimitExceedCounter', formInitialValue.length, CONST.WORKSPACE_REPORT_FIELD_POLICY_MAX_LENGTH);
-            }
-
-            if ((type === CONST.REPORT_FIELD_TYPES.TEXT || type === CONST.REPORT_FIELD_TYPES.FORMULA) && hasCircularReferences(formInitialValue, name, policy?.fieldList)) {
-                errors[INPUT_IDS.INITIAL_VALUE] = translate('workspace.reportFields.circularReferenceError');
-            }
-
-            if ((type === CONST.REPORT_FIELD_TYPES.TEXT || type === CONST.REPORT_FIELD_TYPES.FORMULA) && !!formInitialValue && !errors[INPUT_IDS.INITIAL_VALUE]) {
-                const unsupportedFormulaParts = getUnsupportedReportFieldFormulaParts(formInitialValue);
-                if (unsupportedFormulaParts.length > 0) {
-                    errors[INPUT_IDS.INITIAL_VALUE] = translate('workspace.reportFields.unsupportedFormulaValueError', {
-                        value: unsupportedFormulaParts.join(', '),
-                    });
-                }
-            }
-
-            if (type === CONST.REPORT_FIELD_TYPES.LIST && availableListValuesLength > 0 && !isRequiredFulfilled(formInitialValue)) {
-                errors[INPUT_IDS.INITIAL_VALUE] = translate(
-                    isInvoiceField ? 'workspace.invoiceFields.invoiceFieldInitialValueRequiredError' : 'workspace.reportFields.reportFieldInitialValueRequiredError',
-                );
-            }
-
-            return errors;
-        },
-        [availableListValuesLength, fieldTarget, isInvoiceField, policy?.fieldList, translate],
-    );
-
-    const validateName = useCallback(
-        (values: Record<string, string>) => {
-            const errors: Record<string, string> = {};
-            const name = values[INPUT_IDS.NAME];
-            if (isReportFieldNameExisting(policy?.fieldList, name, fieldTarget)) {
-                errors[INPUT_IDS.NAME] = translate(isInvoiceField ? 'workspace.invoiceFields.existingInvoiceFieldNameError' : 'workspace.reportFields.existingReportFieldNameError');
-            }
-            return errors;
-        },
-        [fieldTarget, isInvoiceField, policy?.fieldList, translate],
-    );
-
-    const handleOnValueCommitted = useCallback(
-        (inputValues: FormOnyxValues<typeof ONYXKEYS.FORMS.WORKSPACE_REPORT_FIELDS_FORM>) => (initialValue: string) => {
-            const isFormula = hasFormulaPartsInInitialValue(initialValue);
-            if (isFormula) {
-                formRef.current?.resetForm({
-                    ...inputValues,
-                    [INPUT_IDS.TYPE]: CONST.REPORT_FIELD_TYPES.FORMULA,
-                    [INPUT_IDS.INITIAL_VALUE]: initialValue,
-                });
-            } else {
-                formRef.current?.resetForm({
-                    ...inputValues,
-                    [INPUT_IDS.TYPE]: CONST.REPORT_FIELD_TYPES.TEXT,
-                    [INPUT_IDS.INITIAL_VALUE]: initialValue,
-                });
-            }
-        },
-        [],
-    );
-
-    useEffect(() => {
-        setInitialCreateReportFieldsForm();
-    }, []);
-
-    const listValues = [...(formDraft?.[INPUT_IDS.LIST_VALUES] ?? [])].sort(localeCompare).join(', ');
-
-    return (
-        <AccessOrNotFoundWrapper
-            accessVariants={[CONST.POLICY.ACCESS_VARIANTS.ADMIN, CONST.POLICY.ACCESS_VARIANTS.PAID]}
-            policyID={policyID}
-            featureName={featureName}
-            shouldBeBlocked={hasAccountingConnections(policy)}
-        >
-            <ScreenWrapper
-                enableEdgeToEdgeBottomSafeAreaPadding
-                style={styles.defaultModalContainer}
-                testID={testID}
-                shouldEnableMaxHeight
-            >
-                <HeaderWithBackButton
-                    title={translate(isInvoiceField ? 'workspace.invoiceFields.addField' : 'workspace.reportFields.addField')}
-                    onBackButtonPress={Navigation.goBack}
-                />
-                <FormProvider
-                    ref={formRef}
-                    style={[styles.mh5, styles.flex1]}
-                    formID={ONYXKEYS.FORMS.WORKSPACE_REPORT_FIELDS_FORM}
-                    onSubmit={submitForm}
-                    validate={validateForm}
-                    submitButtonText={translate('common.save')}
-                    enabledWhenOffline
-                    shouldValidateOnBlur={false}
-                    addBottomSafeAreaPadding
-                    shouldUseStrictHtmlTagValidation
-                >
-                    {({inputValues}) => (
-                        <View style={styles.mhn5}>
-                            <InputWrapper
-                                InputComponent={TextPicker}
-                                inputID={INPUT_IDS.NAME}
-                                label={translate('common.name')}
-                                subtitle={translate(isInvoiceField ? 'workspace.invoiceFields.nameInputSubtitle' : 'workspace.reportFields.nameInputSubtitle')}
-                                description={translate('common.name')}
-                                rightLabel={translate('common.required')}
-                                accessibilityLabel={translate('workspace.editor.nameInputLabel')}
-                                maxLength={CONST.WORKSPACE_REPORT_FIELD_POLICY_MAX_LENGTH}
-                                multiline={false}
-                                role={CONST.ROLE.PRESENTATION}
-                                required
-                                customValidate={validateName}
-                                shouldUseStrictHtmlTagValidation
-                            />
-                            <InputWrapper
-                                InputComponent={TypeSelector}
-                                inputID={INPUT_IDS.TYPE}
-                                label={translate('common.type')}
-                                subtitle={translate(isInvoiceField ? 'workspace.invoiceFields.typeInputSubtitle' : 'workspace.reportFields.typeInputSubtitle')}
-                                rightLabel={translate('common.required')}
-                                onTypeSelected={(type) => {
-                                    let initialValue;
-                                    if (type === CONST.REPORT_FIELD_TYPES.DATE) {
-                                        initialValue = defaultDate;
-                                    } else if (type === CONST.REPORT_FIELD_TYPES.FORMULA) {
-                                        initialValue = '{report:id}';
-                                    } else {
-                                        initialValue = '';
-                                    }
-
-                                    formRef.current?.resetForm({
-                                        ...inputValues,
-                                        type,
-                                        initialValue,
-                                    });
-                                }}
-                            />
-
-                            {inputValues[INPUT_IDS.TYPE] === CONST.REPORT_FIELD_TYPES.LIST && (
-                                <MenuItemWithTopDescription
-                                    description={translate('workspace.reportFields.listValues')}
-                                    shouldShowRightIcon
-                                    onPress={() => Navigation.navigate(listValuesRoute)}
-                                    title={listValues}
-                                    numberOfLinesTitle={5}
-                                />
-                            )}
-
-                            {(inputValues[INPUT_IDS.TYPE] === CONST.REPORT_FIELD_TYPES.TEXT || inputValues[INPUT_IDS.TYPE] === CONST.REPORT_FIELD_TYPES.FORMULA) && (
-                                <InputWrapper
-                                    InputComponent={TextPicker}
-                                    inputID={INPUT_IDS.INITIAL_VALUE}
-                                    label={translate('common.initialValue')}
-                                    subtitle={translate(isInvoiceField ? 'workspace.invoiceFields.initialValueInputSubtitle' : 'workspace.reportFields.initialValueInputSubtitle')}
-                                    description={translate('common.initialValue')}
-                                    accessibilityLabel={translate('workspace.editor.initialValueInputLabel')}
-                                    maxLength={CONST.WORKSPACE_REPORT_FIELD_POLICY_MAX_LENGTH}
-                                    multiline={false}
-                                    role={CONST.ROLE.PRESENTATION}
-                                    onValueCommitted={handleOnValueCommitted(inputValues)}
-                                />
-                            )}
-
-                            {inputValues[INPUT_IDS.TYPE] === CONST.REPORT_FIELD_TYPES.DATE && (
-                                <MenuItemWithTopDescription
-                                    description={translate('common.initialValue')}
-                                    title={translate('common.currentDate')}
-                                    rightLabel={translate('common.required')}
-                                    interactive={false}
-                                />
-                            )}
-
-                            {inputValues[INPUT_IDS.TYPE] === CONST.REPORT_FIELD_TYPES.LIST && availableListValuesLength > 0 && (
-                                <InputWrapper
-                                    InputComponent={InitialListValueSelector}
-                                    inputID={INPUT_IDS.INITIAL_VALUE}
-                                    label={translate('common.initialValue')}
-                                />
-                            )}
-                        </View>
-                    )}
-                </FormProvider>
-            </ScreenWrapper>
-        </AccessOrNotFoundWrapper>
-    );
-}
-
-export default CreateFieldsPage;
diff --git a/src/pages/workspace/fields/FieldsAddListValuePage.tsx b/src/pages/workspace/fields/FieldsAddListValuePage.tsx
deleted file mode 100644
index 48bceb9f0166..000000000000
--- a/src/pages/workspace/fields/FieldsAddListValuePage.tsx
+++ /dev/null
@@ -1,122 +0,0 @@
-import React, {useCallback, useMemo} from 'react';
-import {Keyboard} from 'react-native';
-import type {OnyxEntry} from 'react-native-onyx';
-import type {ValueOf} from 'type-fest';
-import FormProvider from '@components/Form/FormProvider';
-import InputWrapper from '@components/Form/InputWrapper';
-import type {FormOnyxValues} from '@components/Form/types';
-import HeaderWithBackButton from '@components/HeaderWithBackButton';
-import ScreenWrapper from '@components/ScreenWrapper';
-import TextInput from '@components/TextInput';
-import useAutoFocusInput from '@hooks/useAutoFocusInput';
-import useLocalize from '@hooks/useLocalize';
-import useOnyx from '@hooks/useOnyx';
-import usePolicyFeatureWriteAccess from '@hooks/usePolicyFeatureWriteAccess';
-import useThemeStyles from '@hooks/useThemeStyles';
-import Navigation from '@libs/Navigation/Navigation';
-import {hasAccountingConnections} from '@libs/PolicyUtils';
-import type {PolicyFeature} from '@libs/PolicyUtils';
-import {getReportFieldKey} from '@libs/ReportUtils';
-import {validateReportFieldListValueName} from '@libs/WorkspaceReportFieldUtils';
-import AccessOrNotFoundWrapper from '@pages/workspace/AccessOrNotFoundWrapper';
-import {addReportFieldListValue, createReportFieldsListValue} from '@userActions/Policy/ReportField';
-import CONST from '@src/CONST';
-import ONYXKEYS from '@src/ONYXKEYS';
-import INPUT_IDS from '@src/types/form/WorkspaceReportFieldForm';
-import type {Policy} from '@src/types/onyx';
-
-type FieldsAddListValuePageProps = {
-    policy: OnyxEntry<Policy>;
-    policyID: string;
-    reportFieldID?: string;
-    featureName: ValueOf<typeof CONST.POLICY.MORE_FEATURES>;
-    policyFeature: PolicyFeature;
-    testID: string;
-};
-
-function FieldsAddListValuePage({policy, policyID, reportFieldID, featureName, policyFeature, testID}: FieldsAddListValuePageProps) {
-    const styles = useThemeStyles();
-    const {translate} = useLocalize();
-    const {inputCallbackRef} = useAutoFocusInput();
-    const [formDraft] = useOnyx(ONYXKEYS.FORMS.WORKSPACE_REPORT_FIELDS_FORM_DRAFT);
-    const {canWrite} = usePolicyFeatureWriteAccess(policy, policyFeature);
-
-    const listValues = useMemo(() => {
-        let reportFieldListValues: string[];
-        if (reportFieldID) {
-            const reportFieldKey = getReportFieldKey(reportFieldID);
-            reportFieldListValues = Object.values(policy?.fieldList?.[reportFieldKey]?.values ?? {});
-        } else {
-            reportFieldListValues = formDraft?.[INPUT_IDS.LIST_VALUES] ?? [];
-        }
-        return reportFieldListValues;
-    }, [formDraft, policy?.fieldList, reportFieldID]);
-
-    const validate = useCallback(
-        (values: FormOnyxValues<typeof ONYXKEYS.FORMS.WORKSPACE_REPORT_FIELDS_FORM>) =>
-            validateReportFieldListValueName(values[INPUT_IDS.VALUE_NAME].trim(), '', listValues, INPUT_IDS.VALUE_NAME, translate),
-        [listValues, translate],
-    );
-
-    const createValue = useCallback(
-        (values: FormOnyxValues<typeof ONYXKEYS.FORMS.WORKSPACE_REPORT_FIELDS_FORM>) => {
-            if (reportFieldID) {
-                addReportFieldListValue({policy, reportFieldID, valueName: values[INPUT_IDS.VALUE_NAME]});
-            } else {
-                createReportFieldsListValue({
-                    valueName: values[INPUT_IDS.VALUE_NAME],
-                    listValues: formDraft?.[INPUT_IDS.LIST_VALUES] ?? [],
-                    disabledListValues: formDraft?.[INPUT_IDS.DISABLED_LIST_VALUES] ?? [],
-                });
-            }
-            Keyboard.dismiss();
-            Navigation.goBack();
-        },
-        [formDraft, policy, reportFieldID],
-    );
-
-    return (
-        <AccessOrNotFoundWrapper
-            accessVariants={[CONST.POLICY.ACCESS_VARIANTS.ADMIN, CONST.POLICY.ACCESS_VARIANTS.PAID]}
-            policyID={policyID}
-            featureName={featureName}
-            policyFeature={policyFeature}
-            shouldBeBlocked={hasAccountingConnections(policy)}
-        >
-            <ScreenWrapper
-                enableEdgeToEdgeBottomSafeAreaPadding
-                style={styles.defaultModalContainer}
-                testID={testID}
-                shouldEnableMaxHeight
-            >
-                <HeaderWithBackButton
-                    title={translate('workspace.reportFields.addValue')}
-                    onBackButtonPress={Navigation.goBack}
-                />
-                <FormProvider
-                    formID={ONYXKEYS.FORMS.WORKSPACE_REPORT_FIELDS_FORM}
-                    onSubmit={createValue}
-                    submitButtonText={translate('common.save')}
-                    validate={validate}
-                    style={[styles.mh5, styles.flex1]}
-                    enabledWhenOffline
-                    isSubmitButtonVisible={canWrite}
-                    shouldHideFixErrorsAlert
-                    addBottomSafeAreaPadding
-                >
-                    <InputWrapper
-                        InputComponent={TextInput}
-                        label={translate('common.value')}
-                        accessibilityLabel={translate('common.value')}
-                        inputID={INPUT_IDS.VALUE_NAME}
-                        role={CONST.ROLE.PRESENTATION}
-                        ref={inputCallbackRef}
-                        disabled={!canWrite}
-                    />
-                </FormProvider>
-            </ScreenWrapper>
-        </AccessOrNotFoundWrapper>
-    );
-}
-
-export default FieldsAddListValuePage;
diff --git a/src/pages/workspace/fields/FieldsEditValuePage.tsx b/src/pages/workspace/fields/FieldsEditValuePage.tsx
deleted file mode 100644
index dcd021dd23a0..000000000000
--- a/src/pages/workspace/fields/FieldsEditValuePage.tsx
+++ /dev/null
@@ -1,112 +0,0 @@
-import React, {useCallback} from 'react';
-import {Keyboard} from 'react-native';
-import type {OnyxEntry} from 'react-native-onyx';
-import type {ValueOf} from 'type-fest';
-import FormProvider from '@components/Form/FormProvider';
-import InputWrapper from '@components/Form/InputWrapper';
-import type {FormOnyxValues} from '@components/Form/types';
-import HeaderWithBackButton from '@components/HeaderWithBackButton';
-import ScreenWrapper from '@components/ScreenWrapper';
-import TextInput from '@components/TextInput';
-import useAutoFocusInput from '@hooks/useAutoFocusInput';
-import useLocalize from '@hooks/useLocalize';
-import useOnyx from '@hooks/useOnyx';
-import usePolicyFeatureWriteAccess from '@hooks/usePolicyFeatureWriteAccess';
-import useThemeStyles from '@hooks/useThemeStyles';
-import Navigation from '@libs/Navigation/Navigation';
-import {hasAccountingConnections} from '@libs/PolicyUtils';
-import type {PolicyFeature} from '@libs/PolicyUtils';
-import {validateReportFieldListValueName} from '@libs/WorkspaceReportFieldUtils';
-import AccessOrNotFoundWrapper from '@pages/workspace/AccessOrNotFoundWrapper';
-import {renameReportFieldsListValue} from '@userActions/Policy/ReportField';
-import CONST from '@src/CONST';
-import ONYXKEYS from '@src/ONYXKEYS';
-import INPUT_IDS from '@src/types/form/WorkspaceReportFieldForm';
-import type {Policy} from '@src/types/onyx';
-
-type FieldsEditValuePageProps = {
-    policy: OnyxEntry<Policy>;
-    policyID: string;
-    valueIndex: number;
-    featureName: ValueOf<typeof CONST.POLICY.MORE_FEATURES>;
-    policyFeature: PolicyFeature;
-    testID: string;
-};
-
-function FieldsEditValuePage({policy, policyID, valueIndex, featureName, policyFeature, testID}: FieldsEditValuePageProps) {
-    const styles = useThemeStyles();
-    const {translate} = useLocalize();
-    const {inputCallbackRef} = useAutoFocusInput();
-    const [formDraft] = useOnyx(ONYXKEYS.FORMS.WORKSPACE_REPORT_FIELDS_FORM_DRAFT);
-    const {canWrite} = usePolicyFeatureWriteAccess(policy, policyFeature);
-
-    const currentValueName = formDraft?.listValues?.[valueIndex] ?? '';
-
-    const validate = useCallback(
-        (values: FormOnyxValues<typeof ONYXKEYS.FORMS.WORKSPACE_REPORT_FIELDS_FORM>) =>
-            validateReportFieldListValueName(values[INPUT_IDS.NEW_VALUE_NAME].trim(), currentValueName, formDraft?.[INPUT_IDS.LIST_VALUES] ?? [], INPUT_IDS.NEW_VALUE_NAME, translate),
-        [currentValueName, formDraft, translate],
-    );
-
-    const editValue = useCallback(
-        (values: FormOnyxValues<typeof ONYXKEYS.FORMS.WORKSPACE_REPORT_FIELDS_FORM>) => {
-            const valueName = values[INPUT_IDS.NEW_VALUE_NAME]?.trim();
-            if (currentValueName !== valueName) {
-                renameReportFieldsListValue({
-                    valueIndex,
-                    newValueName: valueName,
-                    listValues: formDraft?.[INPUT_IDS.LIST_VALUES] ?? [],
-                });
-            }
-            Keyboard.dismiss();
-            Navigation.goBack();
-        },
-        [currentValueName, formDraft, valueIndex],
-    );
-
-    return (
-        <AccessOrNotFoundWrapper
-            accessVariants={[CONST.POLICY.ACCESS_VARIANTS.ADMIN, CONST.POLICY.ACCESS_VARIANTS.PAID]}
-            policyID={policyID}
-            featureName={featureName}
-            policyFeature={policyFeature}
-            shouldBeBlocked={hasAccountingConnections(policy)}
-        >
-            <ScreenWrapper
-                enableEdgeToEdgeBottomSafeAreaPadding
-                style={styles.defaultModalContainer}
-                testID={testID}
-                shouldEnableMaxHeight
-            >
-                <HeaderWithBackButton
-                    title={translate('workspace.reportFields.editValue')}
-                    onBackButtonPress={Navigation.goBack}
-                />
-                <FormProvider
-                    formID={ONYXKEYS.FORMS.WORKSPACE_REPORT_FIELDS_FORM}
-                    onSubmit={editValue}
-                    submitButtonText={translate('common.save')}
-                    validate={validate}
-                    style={[styles.mh5, styles.flex1]}
-                    enabledWhenOffline
-                    isSubmitButtonVisible={canWrite}
-                    shouldHideFixErrorsAlert
-                    addBottomSafeAreaPadding
-                >
-                    <InputWrapper
-                        InputComponent={TextInput}
-                        defaultValue={currentValueName}
-                        label={translate('common.value')}
-                        accessibilityLabel={translate('common.value')}
-                        inputID={INPUT_IDS.NEW_VALUE_NAME}
-                        role={CONST.ROLE.PRESENTATION}
-                        ref={inputCallbackRef}
-                        disabled={!canWrite}
-                    />
-                </FormProvider>
-            </ScreenWrapper>
-        </AccessOrNotFoundWrapper>
-    );
-}
-
-export default FieldsEditValuePage;
diff --git a/src/pages/workspace/fields/FieldsInitialValuePage.tsx b/src/pages/workspace/fields/FieldsInitialValuePage.tsx
deleted file mode 100644
index c4ab5c8562c9..000000000000
--- a/src/pages/workspace/fields/FieldsInitialValuePage.tsx
+++ /dev/null
@@ -1,171 +0,0 @@
-import React, {useCallback, useState} from 'react';
-import {View} from 'react-native';
-import type {OnyxEntry} from 'react-native-onyx';
-import type {ValueOf} from 'type-fest';
-import FormProvider from '@components/Form/FormProvider';
-import InputWrapper from '@components/Form/InputWrapper';
-import type {FormInputErrors, FormOnyxValues} from '@components/Form/types';
-import HeaderWithBackButton from '@components/HeaderWithBackButton';
-import ScreenWrapper from '@components/ScreenWrapper';
-import Text from '@components/Text';
-import TextInput from '@components/TextInput';
-import useAutoFocusInput from '@hooks/useAutoFocusInput';
-import useLocalize from '@hooks/useLocalize';
-import useThemeStyles from '@hooks/useThemeStyles';
-import {hasCircularReferences} from '@libs/Formula';
-import Navigation from '@libs/Navigation/Navigation';
-import {getReportFieldKey} from '@libs/ReportUtils';
-import {isRequiredFulfilled} from '@libs/ValidationUtils';
-import {getReportFieldInitialValue, getUnsupportedReportFieldFormulaParts} from '@libs/WorkspaceReportFieldUtils';
-import NotFoundPage from '@pages/ErrorPage/NotFoundPage';
-import AccessOrNotFoundWrapper from '@pages/workspace/AccessOrNotFoundWrapper';
-import ReportFieldsInitialListValuePicker from '@pages/workspace/reports/InitialListValueSelector/ReportFieldsInitialListValuePicker';
-import {updateReportFieldInitialValue} from '@userActions/Policy/ReportField';
-import CONST from '@src/CONST';
-import ONYXKEYS from '@src/ONYXKEYS';
-import INPUT_IDS from '@src/types/form/WorkspaceReportFieldForm';
-import type {Policy} from '@src/types/onyx';
-
-type FieldsInitialValuePageProps = {
-    policy: OnyxEntry<Policy>;
-    policyID: string;
-    reportFieldID: string;
-    featureName: ValueOf<typeof CONST.POLICY.MORE_FEATURES>;
-    testID: string;
-};
-
-function FieldsInitialValuePage({policy, policyID, reportFieldID, featureName, testID}: FieldsInitialValuePageProps) {
-    const styles = useThemeStyles();
-    const {translate} = useLocalize();
-    const {inputCallbackRef} = useAutoFocusInput();
-
-    const reportField = policy?.fieldList?.[getReportFieldKey(reportFieldID)] ?? null;
-    const isInvoiceField = reportField?.target === CONST.REPORT_FIELD_TARGETS.INVOICE;
-    const availableListValuesLength = (reportField?.disabledOptions ?? []).filter((disabledListValue) => !disabledListValue).length;
-    const currentInitialValue = getReportFieldInitialValue(reportField, translate);
-    const [initialValue, setInitialValue] = useState(currentInitialValue);
-
-    const submitForm = useCallback(
-        (values: FormOnyxValues<typeof ONYXKEYS.FORMS.WORKSPACE_REPORT_FIELDS_FORM>) => {
-            if (currentInitialValue !== values.initialValue) {
-                updateReportFieldInitialValue({policy, reportFieldID, newInitialValue: values.initialValue});
-            }
-            Navigation.goBack();
-        },
-        [currentInitialValue, policy, reportFieldID],
-    );
-
-    const submitListValueUpdate = (value: string) => {
-        updateReportFieldInitialValue({policy, reportFieldID, newInitialValue: currentInitialValue === value ? '' : value});
-        Navigation.goBack();
-    };
-
-    const validateForm = useCallback(
-        (values: FormOnyxValues<typeof ONYXKEYS.FORMS.WORKSPACE_REPORT_FIELDS_FORM>): FormInputErrors<typeof ONYXKEYS.FORMS.WORKSPACE_REPORT_FIELDS_FORM> => {
-            const {initialValue: formInitialValue} = values;
-            const errors: FormInputErrors<typeof ONYXKEYS.FORMS.WORKSPACE_REPORT_FIELDS_FORM> = {};
-
-            if (formInitialValue.length > CONST.WORKSPACE_REPORT_FIELD_POLICY_MAX_LENGTH) {
-                errors[INPUT_IDS.INITIAL_VALUE] = translate('common.error.characterLimitExceedCounter', formInitialValue.length, CONST.WORKSPACE_REPORT_FIELD_POLICY_MAX_LENGTH);
-            }
-
-            if (
-                (reportField?.type === CONST.REPORT_FIELD_TYPES.TEXT || reportField?.type === CONST.REPORT_FIELD_TYPES.FORMULA) &&
-                hasCircularReferences(formInitialValue, reportField?.name, policy?.fieldList)
-            ) {
-                errors[INPUT_IDS.INITIAL_VALUE] = translate('workspace.reportFields.circularReferenceError');
-            }
-
-            if ((reportField?.type === CONST.REPORT_FIELD_TYPES.TEXT || reportField?.type === CONST.REPORT_FIELD_TYPES.FORMULA) && !!formInitialValue && !errors[INPUT_IDS.INITIAL_VALUE]) {
-                const unsupportedFormulaParts = getUnsupportedReportFieldFormulaParts(formInitialValue);
-                if (unsupportedFormulaParts.length > 0) {
-                    errors[INPUT_IDS.INITIAL_VALUE] = translate('workspace.reportFields.unsupportedFormulaValueError', {
-                        value: unsupportedFormulaParts.join(', '),
-                    });
-                }
-            }
-
-            if (reportField?.type === CONST.REPORT_FIELD_TYPES.LIST && availableListValuesLength > 0 && !isRequiredFulfilled(formInitialValue)) {
-                errors[INPUT_IDS.INITIAL_VALUE] = translate(
-                    isInvoiceField ? 'workspace.invoiceFields.invoiceFieldInitialValueRequiredError' : 'workspace.reportFields.reportFieldInitialValueRequiredError',
-                );
-            }
-
-            return errors;
-        },
-        [availableListValuesLength, isInvoiceField, reportField?.name, reportField?.type, policy?.fieldList, translate],
-    );
-
-    if (!reportField) {
-        return <NotFoundPage />;
-    }
-
-    const isTextFieldType = reportField.type === CONST.REPORT_FIELD_TYPES.TEXT;
-    const isFormulaFieldType = reportField.type === CONST.REPORT_FIELD_TYPES.FORMULA;
-    const isListFieldType = reportField.type === CONST.REPORT_FIELD_TYPES.LIST;
-
-    return (
-        <AccessOrNotFoundWrapper
-            accessVariants={[CONST.POLICY.ACCESS_VARIANTS.ADMIN, CONST.POLICY.ACCESS_VARIANTS.PAID]}
-            policyID={policyID}
-            featureName={featureName}
-        >
-            <ScreenWrapper
-                enableEdgeToEdgeBottomSafeAreaPadding
-                style={styles.defaultModalContainer}
-                testID={testID}
-                shouldEnableMaxHeight
-            >
-                <HeaderWithBackButton
-                    title={translate('common.initialValue')}
-                    onBackButtonPress={Navigation.goBack}
-                />
-                {isListFieldType && (
-                    <View style={[styles.ph5, styles.pb4]}>
-                        <Text style={[styles.sidebarLinkText, styles.optionAlternateText]}>
-                            {translate(isInvoiceField ? 'workspace.invoiceFields.listValuesInputSubtitle' : 'workspace.reportFields.listValuesInputSubtitle')}
-                        </Text>
-                    </View>
-                )}
-
-                {(isTextFieldType || isFormulaFieldType) && (
-                    <FormProvider
-                        addBottomSafeAreaPadding
-                        formID={ONYXKEYS.FORMS.WORKSPACE_REPORT_FIELDS_FORM}
-                        onSubmit={submitForm}
-                        submitButtonText={translate('common.save')}
-                        validate={validateForm}
-                        style={styles.flex1}
-                        enabledWhenOffline
-                        isSubmitButtonVisible
-                        submitButtonStyles={styles.mh5}
-                        shouldHideFixErrorsAlert
-                    >
-                        <InputWrapper
-                            containerStyles={styles.mh5}
-                            InputComponent={TextInput}
-                            inputID={INPUT_IDS.INITIAL_VALUE}
-                            label={translate('common.initialValue')}
-                            accessibilityLabel={translate('workspace.editor.initialValueInputLabel')}
-                            multiline={false}
-                            value={initialValue}
-                            role={CONST.ROLE.PRESENTATION}
-                            ref={inputCallbackRef}
-                            onChangeText={setInitialValue}
-                        />
-                    </FormProvider>
-                )}
-                {isListFieldType && (
-                    <ReportFieldsInitialListValuePicker
-                        listValues={reportField.values}
-                        disabledOptions={reportField.disabledOptions}
-                        value={initialValue}
-                        onValueChange={submitListValueUpdate}
-                    />
-                )}
-            </ScreenWrapper>
-        </AccessOrNotFoundWrapper>
-    );
-}
-
-export default FieldsInitialValuePage;
diff --git a/src/pages/workspace/fields/FieldsListValuesPage.tsx b/src/pages/workspace/fields/FieldsListValuesPage.tsx
deleted file mode 100644
index 9e7f2386bfd8..000000000000
--- a/src/pages/workspace/fields/FieldsListValuesPage.tsx
+++ /dev/null
@@ -1,438 +0,0 @@
-import React, {useCallback, useMemo, useState} from 'react';
-import {View} from 'react-native';
-import type {OnyxEntry} from 'react-native-onyx';
-import type {ValueOf} from 'type-fest';
-import Button from '@components/Button';
-import ButtonWithDropdownMenu from '@components/ButtonWithDropdownMenu';
-import type {DropdownOption} from '@components/ButtonWithDropdownMenu/types';
-import EmptyStateComponent from '@components/EmptyStateComponent';
-import HeaderWithBackButton from '@components/HeaderWithBackButton';
-import {ModalActions} from '@components/Modal/Global/ModalContext';
-import ScreenWrapper from '@components/ScreenWrapper';
-import ScrollView from '@components/ScrollView';
-import SearchBar from '@components/SearchBar';
-import TableListItem from '@components/SelectionList/ListItem/TableListItem';
-import type {ListItem} from '@components/SelectionList/types';
-import SelectionListWithModal from '@components/SelectionListWithModal';
-import CustomListHeader from '@components/SelectionListWithModal/CustomListHeader';
-import Switch from '@components/Switch';
-import Text from '@components/Text';
-import useConfirmModal from '@hooks/useConfirmModal';
-import {useMemoizedLazyExpensifyIcons, useMemoizedLazyIllustrations} from '@hooks/useLazyAsset';
-import useLocalize from '@hooks/useLocalize';
-import useMobileSelectionMode from '@hooks/useMobileSelectionMode';
-import useOnyx from '@hooks/useOnyx';
-import usePolicyFeatureWriteAccess from '@hooks/usePolicyFeatureWriteAccess';
-import useResponsiveLayout from '@hooks/useResponsiveLayout';
-import useSearchBackPress from '@hooks/useSearchBackPress';
-import useSearchResults from '@hooks/useSearchResults';
-import useShouldDisplayButtonsInSeparateLine from '@hooks/useShouldDisplayButtonsInSeparateLine';
-import useThemeStyles from '@hooks/useThemeStyles';
-import {turnOffMobileSelectionMode} from '@libs/actions/MobileSelectionMode';
-import {
-    deleteReportFieldsListValue,
-    removeReportFieldListValue,
-    setReportFieldsListValueEnabled,
-    updateReportFieldListValueEnabled as updateReportFieldListValueEnabledReportField,
-} from '@libs/actions/Policy/ReportField';
-import {canUseTouchScreen} from '@libs/DeviceCapabilities';
-import Navigation from '@libs/Navigation/Navigation';
-import {hasAccountingConnections as hasAccountingConnectionsPolicyUtils} from '@libs/PolicyUtils';
-import type {PolicyFeature} from '@libs/PolicyUtils';
-import {getReportFieldKey} from '@libs/ReportUtils';
-import StringUtils from '@libs/StringUtils';
-import AccessOrNotFoundWrapper from '@pages/workspace/AccessOrNotFoundWrapper';
-import CONST from '@src/CONST';
-import ONYXKEYS from '@src/ONYXKEYS';
-import type {Route as Routes} from '@src/ROUTES';
-import type {Policy} from '@src/types/onyx';
-import type DeepValueOf from '@src/types/utils/DeepValueOf';
-
-type ValueListItem = ListItem & {
-    /** The value */
-    value: string;
-
-    /** Whether the value is enabled */
-    enabled: boolean;
-
-    /** The value order weight in the list */
-    orderWeight?: number;
-};
-
-type FieldsListValuesPageProps = {
-    policy: OnyxEntry<Policy>;
-    policyID: string;
-    reportFieldID?: string;
-    isInvoicePage: boolean;
-    featureName: ValueOf<typeof CONST.POLICY.MORE_FEATURES>;
-    policyFeature: PolicyFeature;
-    getValueSettingsRoute: (isInvoiceRoute: boolean, policyID: string, valueIndex: number, reportFieldID?: string) => Routes;
-    getAddValueRoute: (isInvoiceRoute: boolean, policyID: string, reportFieldID?: string) => Routes;
-    testID: string;
-};
-
-function FieldsListValuesPage({policy, policyID, reportFieldID, isInvoicePage, featureName, policyFeature, getValueSettingsRoute, getAddValueRoute, testID}: FieldsListValuesPageProps) {
-    const styles = useThemeStyles();
-    const {translate, localeCompare} = useLocalize();
-    // We need to use isSmallScreenWidth instead of shouldUseNarrowLayout here to use the mobile selection mode on small screens only
-    // See https://github.com/Expensify/App/issues/48724 for more details
-    // eslint-disable-next-line rulesdir/prefer-shouldUseNarrowLayout-instead-of-isSmallScreenWidth
-    const {isSmallScreenWidth} = useResponsiveLayout();
-    const [formDraft] = useOnyx(ONYXKEYS.FORMS.WORKSPACE_REPORT_FIELDS_FORM_DRAFT);
-    const isMobileSelectionModeEnabled = useMobileSelectionMode();
-    const icons = useMemoizedLazyExpensifyIcons(['Checkmark', 'Close', 'Plus', 'Trashcan']);
-    const illustrations = useMemoizedLazyIllustrations(['FolderWithPapers']);
-    const {showConfirmModal} = useConfirmModal();
-    const {canWrite, withReadOnlyFallback} = usePolicyFeatureWriteAccess(policy, policyFeature);
-
-    const [selectedValues, setSelectedValues] = useState<Record<string, boolean>>({});
-    const hasAccountingConnections = hasAccountingConnectionsPolicyUtils(policy);
-    const reportField = reportFieldID ? policy?.fieldList?.[getReportFieldKey(reportFieldID)] : undefined;
-    const shouldUseInvoiceRoutes = isInvoicePage || reportField?.target === CONST.REPORT_FIELD_TARGETS.INVOICE;
-    const listInputSubtitleKey = shouldUseInvoiceRoutes ? 'workspace.invoiceFields.listInputSubtitle' : 'workspace.reportFields.listInputSubtitle';
-    const findFieldKey = shouldUseInvoiceRoutes ? 'workspace.invoiceFields.findInvoiceField' : 'workspace.reportFields.findReportField';
-    const emptyValuesSubtitleKey = shouldUseInvoiceRoutes ? 'workspace.invoiceFields.emptyInvoiceFieldsValues.subtitle' : 'workspace.reportFields.emptyReportFieldsValues.subtitle';
-
-    const canSelectMultiple = canWrite && (isSmallScreenWidth ? isMobileSelectionModeEnabled : true);
-
-    const [listValues, disabledListValues] = useMemo(() => {
-        let reportFieldValues: string[];
-        let reportFieldDisabledValues: boolean[];
-
-        if (reportFieldID) {
-            const reportFieldKey = getReportFieldKey(reportFieldID);
-
-            reportFieldValues = Object.values(policy?.fieldList?.[reportFieldKey]?.values ?? {});
-            reportFieldDisabledValues = Object.values(policy?.fieldList?.[reportFieldKey]?.disabledOptions ?? {});
-        } else {
-            reportFieldValues = formDraft?.listValues ?? [];
-            reportFieldDisabledValues = formDraft?.disabledListValues ?? [];
-        }
-
-        return [reportFieldValues, reportFieldDisabledValues];
-    }, [formDraft?.disabledListValues, formDraft?.listValues, policy?.fieldList, reportFieldID]);
-
-    const updateReportFieldListValueEnabled = useCallback(
-        (value: boolean, valueIndex: number) => {
-            if (reportFieldID) {
-                updateReportFieldListValueEnabledReportField({policy, reportFieldID, valueIndexes: [Number(valueIndex)], enabled: value});
-                return;
-            }
-
-            setReportFieldsListValueEnabled({
-                valueIndexes: [valueIndex],
-                enabled: value,
-                disabledListValues,
-            });
-        },
-        [disabledListValues, policy, reportFieldID],
-    );
-
-    useSearchBackPress({
-        onClearSelection: () => {
-            setSelectedValues({});
-        },
-        onNavigationCallBack: () => Navigation.goBack(),
-    });
-
-    const data = useMemo(
-        () =>
-            listValues.map<ValueListItem>((value, index) => ({
-                value,
-                index,
-                text: value,
-                keyForList: value,
-                isSelected: selectedValues[value] && canSelectMultiple,
-                enabled: !disabledListValues.at(index),
-                rightElement: (
-                    <Switch
-                        isOn={!disabledListValues.at(index)}
-                        accessibilityLabel={translate('workspace.distanceRates.trackTax')}
-                        onToggle={(newValue: boolean) => updateReportFieldListValueEnabled(newValue, index)}
-                        disabled={!canWrite}
-                        disabledAction={withReadOnlyFallback()}
-                        showLockIcon={!canWrite}
-                    />
-                ),
-            })),
-        [canSelectMultiple, canWrite, disabledListValues, listValues, selectedValues, translate, updateReportFieldListValueEnabled, withReadOnlyFallback],
-    );
-
-    const filterListValue = useCallback((item: ValueListItem, searchInput: string) => {
-        const itemText = StringUtils.normalize(item.text?.toLowerCase() ?? '');
-        const normalizedSearchInput = StringUtils.normalize(searchInput.toLowerCase());
-        return itemText.includes(normalizedSearchInput);
-    }, []);
-    const sortListValues = useCallback((values: ValueListItem[]) => values.sort((a, b) => localeCompare(a.value, b.value)), [localeCompare]);
-    const [inputValue, setInputValue, filteredListValues] = useSearchResults(data, filterListValue, sortListValues);
-    const shouldDisplayButtonsInSeparateLine = useShouldDisplayButtonsInSeparateLine();
-
-    const filteredListValuesArray = filteredListValues.map((item) => item.value);
-
-    const shouldShowEmptyState = Object.values(listValues ?? {}).length <= 0;
-    const selectedValuesArray = Object.keys(selectedValues).filter((key) => selectedValues[key] && listValues.includes(key));
-
-    const toggleValue = (valueItem: ValueListItem) => {
-        setSelectedValues((prev) => ({
-            ...prev,
-            [valueItem.value]: !prev[valueItem.value],
-        }));
-    };
-
-    const toggleAllValues = () => {
-        setSelectedValues(selectedValuesArray.length > 0 ? {} : Object.fromEntries(filteredListValuesArray.map((value) => [value, true])));
-    };
-
-    const handleDeleteValues = () => {
-        const valuesToDelete = selectedValuesArray.reduce<number[]>((acc, valueName) => {
-            const index = listValues?.indexOf(valueName) ?? -1;
-
-            if (index !== -1) {
-                acc.push(index);
-            }
-
-            return acc;
-        }, []);
-
-        if (reportFieldID) {
-            removeReportFieldListValue({policy, reportFieldID, valueIndexes: valuesToDelete});
-        } else {
-            deleteReportFieldsListValue({
-                valueIndexes: valuesToDelete,
-                listValues,
-                disabledListValues,
-            });
-        }
-
-        setSelectedValues({});
-    };
-
-    const openListValuePage = (valueItem: ValueListItem) => {
-        if (valueItem.index === undefined) {
-            return;
-        }
-
-        Navigation.navigate(getValueSettingsRoute(shouldUseInvoiceRoutes, policyID, valueItem.index, reportFieldID));
-    };
-
-    const getCustomListHeader = () => {
-        if (filteredListValues.length === 0) {
-            return null;
-        }
-        return (
-            <CustomListHeader
-                canSelectMultiple={canSelectMultiple}
-                leftHeaderText={translate('common.name')}
-                rightHeaderText={translate('common.enabled')}
-                shouldShowRightCaret
-            />
-        );
-    };
-
-    const getHeaderButtons = () => {
-        const options: Array<DropdownOption<DeepValueOf<typeof CONST.POLICY.BULK_ACTION_TYPES>>> = [];
-        if (canWrite && (isSmallScreenWidth ? isMobileSelectionModeEnabled : selectedValuesArray.length > 0)) {
-            if (selectedValuesArray.length > 0 && !hasAccountingConnections) {
-                options.push({
-                    icon: icons.Trashcan,
-                    text: translate(selectedValuesArray.length === 1 ? 'workspace.reportFields.deleteValue' : 'workspace.reportFields.deleteValues'),
-                    value: CONST.POLICY.BULK_ACTION_TYPES.DELETE,
-                    onSelected: () => {
-                        showConfirmModal({
-                            danger: true,
-                            title: translate(selectedValuesArray.length === 1 ? 'workspace.reportFields.deleteValue' : 'workspace.reportFields.deleteValues'),
-                            prompt: translate(selectedValuesArray.length === 1 ? 'workspace.reportFields.deleteValuePrompt' : 'workspace.reportFields.deleteValuesPrompt'),
-                            confirmText: translate('common.delete'),
-                            cancelText: translate('common.cancel'),
-                        }).then((result) => {
-                            if (result.action !== ModalActions.CONFIRM) {
-                                return;
-                            }
-
-                            handleDeleteValues();
-                        });
-                    },
-                });
-            }
-            const enabledValues = selectedValuesArray.filter((valueName) => {
-                const index = listValues?.indexOf(valueName) ?? -1;
-                return !disabledListValues?.at(index);
-            });
-
-            if (enabledValues.length > 0) {
-                const valuesToDisable = selectedValuesArray.reduce<number[]>((acc, valueName) => {
-                    const index = listValues?.indexOf(valueName) ?? -1;
-                    if (!disabledListValues?.at(index) && index !== -1) {
-                        acc.push(index);
-                    }
-
-                    return acc;
-                }, []);
-
-                options.push({
-                    icon: icons.Close,
-                    text: translate(enabledValues.length === 1 ? 'workspace.reportFields.disableValue' : 'workspace.reportFields.disableValues'),
-                    value: CONST.POLICY.BULK_ACTION_TYPES.DISABLE,
-                    onSelected: () => {
-                        setSelectedValues({});
-
-                        if (reportFieldID) {
-                            updateReportFieldListValueEnabledReportField({policy, reportFieldID, valueIndexes: valuesToDisable, enabled: false});
-                            return;
-                        }
-
-                        setReportFieldsListValueEnabled({
-                            valueIndexes: valuesToDisable,
-                            enabled: false,
-                            disabledListValues,
-                        });
-                    },
-                });
-            }
-
-            const disabledValues = selectedValuesArray.filter((valueName) => {
-                const index = listValues?.indexOf(valueName) ?? -1;
-                return disabledListValues?.at(index);
-            });
-
-            if (disabledValues.length > 0) {
-                const valuesToEnable = selectedValuesArray.reduce<number[]>((acc, valueName) => {
-                    const index = listValues?.indexOf(valueName) ?? -1;
-                    if (disabledListValues?.at(index) && index !== -1) {
-                        acc.push(index);
-                    }
-
-                    return acc;
-                }, []);
-
-                options.push({
-                    icon: icons.Checkmark,
-                    text: translate(disabledValues.length === 1 ? 'workspace.reportFields.enableValue' : 'workspace.reportFields.enableValues'),
-                    value: CONST.POLICY.BULK_ACTION_TYPES.ENABLE,
-                    onSelected: () => {
-                        setSelectedValues({});
-
-                        if (reportFieldID) {
-                            updateReportFieldListValueEnabledReportField({policy, reportFieldID, valueIndexes: valuesToEnable, enabled: true});
-                            return;
-                        }
-
-                        setReportFieldsListValueEnabled({
-                            valueIndexes: valuesToEnable,
-                            enabled: true,
-                            disabledListValues,
-                        });
-                    },
-                });
-            }
-
-            return (
-                <ButtonWithDropdownMenu
-                    onPress={() => null}
-                    shouldAlwaysShowDropdownMenu
-                    buttonSize={CONST.DROPDOWN_BUTTON_SIZE.MEDIUM}
-                    customText={translate('workspace.common.selected', {count: selectedValuesArray.length})}
-                    options={options}
-                    isSplitButton={false}
-                    style={[shouldDisplayButtonsInSeparateLine && styles.flexGrow1, shouldDisplayButtonsInSeparateLine && styles.mb3]}
-                    isDisabled={!selectedValuesArray.length}
-                />
-            );
-        }
-
-        if (canWrite && !hasAccountingConnections) {
-            return (
-                <Button
-                    style={[shouldDisplayButtonsInSeparateLine && styles.flexGrow1, shouldDisplayButtonsInSeparateLine && styles.mb3]}
-                    success
-                    icon={icons.Plus}
-                    text={translate('workspace.reportFields.addValue')}
-                    onPress={() => Navigation.navigate(getAddValueRoute(shouldUseInvoiceRoutes, policyID, reportFieldID))}
-                />
-            );
-        }
-    };
-
-    const selectionModeHeader = isMobileSelectionModeEnabled && isSmallScreenWidth;
-
-    const headerContent = (
-        <>
-            <View style={[styles.ph5, styles.pv4]}>
-                <Text style={[styles.sidebarLinkText, styles.optionAlternateText]}>{translate(listInputSubtitleKey)}</Text>
-            </View>
-            {data.length >= CONST.STANDARD_LIST_ITEM_LIMIT && (
-                <SearchBar
-                    label={translate(findFieldKey)}
-                    inputValue={inputValue}
-                    onChangeText={setInputValue}
-                    shouldShowEmptyState={!shouldShowEmptyState && filteredListValues.length === 0}
-                />
-            )}
-        </>
-    );
-
-    return (
-        <AccessOrNotFoundWrapper
-            accessVariants={[CONST.POLICY.ACCESS_VARIANTS.ADMIN, CONST.POLICY.ACCESS_VARIANTS.PAID]}
-            policyID={policyID}
-            featureName={featureName}
-            policyFeature={policyFeature}
-        >
-            <ScreenWrapper
-                enableEdgeToEdgeBottomSafeAreaPadding
-                style={styles.defaultModalContainer}
-                testID={testID}
-                shouldEnableMaxHeight
-            >
-                <HeaderWithBackButton
-                    title={translate(selectionModeHeader ? 'common.selectMultiple' : 'workspace.reportFields.listValues')}
-                    onBackButtonPress={() => {
-                        if (isMobileSelectionModeEnabled) {
-                            setSelectedValues({});
-                            turnOffMobileSelectionMode();
-                            return;
-                        }
-                        Navigation.goBack();
-                    }}
-                >
-                    {!shouldDisplayButtonsInSeparateLine && getHeaderButtons()}
-                </HeaderWithBackButton>
-                {shouldDisplayButtonsInSeparateLine && <View style={[styles.pl5, styles.pr5]}>{getHeaderButtons()}</View>}
-                {shouldShowEmptyState && (
-                    <ScrollView contentContainerStyle={[styles.flexGrow1, styles.flexShrink0]}>
-                        {headerContent}
-                        <EmptyStateComponent
-                            title={translate('workspace.reportFields.emptyReportFieldsValues.title')}
-                            subtitle={translate(emptyValuesSubtitleKey)}
-                            headerMedia={illustrations.FolderWithPapers}
-                            headerStyles={styles.emptyStateCardIllustrationContainer}
-                            headerContentStyles={styles.emptyStateFolderWithPaperIconSize}
-                        />
-                    </ScrollView>
-                )}
-                {!shouldShowEmptyState && (
-                    <SelectionListWithModal
-                        data={filteredListValues}
-                        ListItem={TableListItem}
-                        onSelectRow={openListValuePage}
-                        selectedItems={selectedValuesArray}
-                        onSelectAll={canWrite && filteredListValues.length > 0 ? toggleAllValues : undefined}
-                        onTurnOnSelectionMode={(item) => item && canWrite && toggleValue(item)}
-                        shouldPreventDefaultFocusOnSelectRow={!canUseTouchScreen()}
-                        customListHeader={getCustomListHeader()}
-                        customListHeaderContent={headerContent}
-                        canSelectMultiple={canSelectMultiple}
-                        onSelectionButtonPress={toggleValue}
-                        shouldShowListEmptyContent={false}
-                        showScrollIndicator={false}
-                        turnOnSelectionModeOnLongPress={canWrite}
-                        shouldHeaderBeInsideList
-                        shouldShowRightCaret
-                    />
-                )}
-            </ScreenWrapper>
-        </AccessOrNotFoundWrapper>
-    );
-}
-
-export default FieldsListValuesPage;
diff --git a/src/pages/workspace/fields/FieldsSettingsPage.tsx b/src/pages/workspace/fields/FieldsSettingsPage.tsx
deleted file mode 100644
index ccba8c0093e5..000000000000
--- a/src/pages/workspace/fields/FieldsSettingsPage.tsx
+++ /dev/null
@@ -1,164 +0,0 @@
-import {Str} from 'expensify-common';
-import React from 'react';
-import {View} from 'react-native';
-import type {OnyxEntry} from 'react-native-onyx';
-import type {ValueOf} from 'type-fest';
-import HeaderWithBackButton from '@components/HeaderWithBackButton';
-import MenuItem from '@components/MenuItem';
-import MenuItemWithTopDescription from '@components/MenuItemWithTopDescription';
-import {ModalActions} from '@components/Modal/Global/ModalContext';
-import ScreenWrapper from '@components/ScreenWrapper';
-import useConfirmModal from '@hooks/useConfirmModal';
-import {useMemoizedLazyExpensifyIcons} from '@hooks/useLazyAsset';
-import useLocalize from '@hooks/useLocalize';
-import usePolicyFeatureWriteAccess from '@hooks/usePolicyFeatureWriteAccess';
-import useThemeStyles from '@hooks/useThemeStyles';
-import Navigation from '@libs/Navigation/Navigation';
-import {hasAccountingConnections as hasAccountingConnectionsPolicyUtils} from '@libs/PolicyUtils';
-import type {PolicyFeature} from '@libs/PolicyUtils';
-import {getReportFieldKey} from '@libs/ReportUtils';
-import {getReportFieldInitialValue, getReportFieldTypeTranslationKey, isReportFieldTargetValid} from '@libs/WorkspaceReportFieldUtils';
-import NotFoundPage from '@pages/ErrorPage/NotFoundPage';
-import AccessOrNotFoundWrapper from '@pages/workspace/AccessOrNotFoundWrapper';
-import {deleteReportFields} from '@userActions/Policy/ReportField';
-import CONST from '@src/CONST';
-import type {Route as Routes} from '@src/ROUTES';
-import type {Policy} from '@src/types/onyx';
-
-type FieldsSettingsPageProps = {
-    policy: OnyxEntry<Policy>;
-    policyID: string;
-    reportFieldID: string;
-    featureName: ValueOf<typeof CONST.POLICY.MORE_FEATURES>;
-    policyFeature: PolicyFeature;
-    expectedTarget?: ValueOf<typeof CONST.REPORT_FIELD_TARGETS>;
-    getListValuesRoute: (policyID: string, reportFieldID: string) => Routes;
-    getInitialValueRoute: (policyID: string, reportFieldID: string) => Routes;
-    deleteTitleKey?: 'workspace.reportFields.delete' | 'workspace.invoiceFields.delete';
-    deletePromptKey?: 'workspace.reportFields.deleteConfirmation' | 'workspace.invoiceFields.deleteConfirmation';
-    testID: string;
-};
-
-function FieldsSettingsPage({
-    policy,
-    policyID,
-    reportFieldID,
-    featureName,
-    policyFeature,
-    expectedTarget,
-    getListValuesRoute,
-    getInitialValueRoute,
-    deleteTitleKey = 'workspace.reportFields.delete',
-    deletePromptKey = 'workspace.reportFields.deleteConfirmation',
-    testID,
-}: FieldsSettingsPageProps) {
-    const styles = useThemeStyles();
-    const {translate, localeCompare} = useLocalize();
-    const icons = useMemoizedLazyExpensifyIcons(['Trashcan']);
-    const {showConfirmModal} = useConfirmModal();
-    const {canWrite} = usePolicyFeatureWriteAccess(policy, policyFeature);
-
-    const hasAccountingConnections = hasAccountingConnectionsPolicyUtils(policy);
-    const reportFieldKey = getReportFieldKey(reportFieldID);
-    const reportField = policy?.fieldList?.[reportFieldKey] ?? null;
-
-    if (!reportField || !isReportFieldTargetValid(reportField, expectedTarget)) {
-        return <NotFoundPage />;
-    }
-
-    const isDateFieldType = reportField.type === CONST.REPORT_FIELD_TYPES.DATE;
-    const isListFieldType = reportField.type === CONST.REPORT_FIELD_TYPES.LIST;
-    const isListFieldEmpty = isListFieldType && reportField.disabledOptions.filter((disabledListValue) => !disabledListValue).length <= 0;
-    const listValues = Object.values(policy?.fieldList?.[reportFieldKey]?.values ?? {})?.sort(localeCompare);
-
-    const deleteReportFieldAndHideModal = () => {
-        deleteReportFields({policy, reportFieldsToUpdate: [reportFieldKey]});
-        Navigation.goBack();
-    };
-
-    const showDeleteModal = () => {
-        showConfirmModal({
-            danger: true,
-            title: translate(deleteTitleKey),
-            prompt: translate(deletePromptKey),
-            confirmText: translate('common.delete'),
-            cancelText: translate('common.cancel'),
-        }).then((result) => {
-            if (result.action !== ModalActions.CONFIRM) {
-                return;
-            }
-
-            deleteReportFieldAndHideModal();
-        });
-    };
-
-    return (
-        <AccessOrNotFoundWrapper
-            accessVariants={[CONST.POLICY.ACCESS_VARIANTS.ADMIN, CONST.POLICY.ACCESS_VARIANTS.PAID]}
-            policyID={policyID}
-            featureName={featureName}
-            policyFeature={policyFeature}
-        >
-            <ScreenWrapper
-                enableEdgeToEdgeBottomSafeAreaPadding
-                style={[styles.defaultModalContainer]}
-                testID={testID}
-            >
-                <HeaderWithBackButton
-                    title={reportField.name}
-                    shouldSetModalVisibility={false}
-                />
-                <View style={styles.flexGrow1}>
-                    <MenuItemWithTopDescription
-                        style={[styles.moneyRequestMenuItem]}
-                        titleStyle={styles.flex1}
-                        title={reportField.name}
-                        description={translate('common.name')}
-                        interactive={false}
-                    />
-                    <MenuItemWithTopDescription
-                        style={[styles.moneyRequestMenuItem]}
-                        titleStyle={styles.flex1}
-                        title={Str.recapitalize(translate(getReportFieldTypeTranslationKey(reportField.type)))}
-                        description={translate('common.type')}
-                        interactive={false}
-                    />
-                    {isListFieldType && (
-                        <MenuItemWithTopDescription
-                            style={[styles.moneyRequestMenuItem]}
-                            titleStyle={styles.flex1}
-                            description={translate('workspace.reportFields.listValues')}
-                            shouldShowRightIcon={canWrite}
-                            interactive={canWrite}
-                            onPress={() => Navigation.navigate(getListValuesRoute(policyID, reportFieldID))}
-                            title={listValues.join(', ')}
-                            numberOfLinesTitle={5}
-                        />
-                    )}
-                    {!isListFieldEmpty && (
-                        <MenuItemWithTopDescription
-                            style={[styles.moneyRequestMenuItem]}
-                            titleStyle={styles.flex1}
-                            title={getReportFieldInitialValue(reportField, translate)}
-                            description={translate('common.initialValue')}
-                            shouldShowRightIcon={canWrite && !isDateFieldType}
-                            interactive={canWrite && !isDateFieldType}
-                            onPress={() => Navigation.navigate(getInitialValueRoute(policyID, reportFieldID))}
-                        />
-                    )}
-                    {canWrite && !hasAccountingConnections && (
-                        <View style={styles.flexGrow1}>
-                            <MenuItem
-                                icon={icons.Trashcan}
-                                title={translate('common.delete')}
-                                onPress={showDeleteModal}
-                            />
-                        </View>
-                    )}
-                </View>
-            </ScreenWrapper>
-        </AccessOrNotFoundWrapper>
-    );
-}
-
-export default FieldsSettingsPage;
diff --git a/src/pages/workspace/fields/FieldsValueSettingsPage.tsx b/src/pages/workspace/fields/FieldsValueSettingsPage.tsx
deleted file mode 100644
index bdb6a0320398..000000000000
--- a/src/pages/workspace/fields/FieldsValueSettingsPage.tsx
+++ /dev/null
@@ -1,178 +0,0 @@
-import React, {useMemo} from 'react';
-import {View} from 'react-native';
-import type {OnyxEntry} from 'react-native-onyx';
-import type {ValueOf} from 'type-fest';
-import HeaderWithBackButton from '@components/HeaderWithBackButton';
-import MenuItem from '@components/MenuItem';
-import MenuItemWithTopDescription from '@components/MenuItemWithTopDescription';
-import {ModalActions} from '@components/Modal/Global/ModalContext';
-import ScreenWrapper from '@components/ScreenWrapper';
-import Switch from '@components/Switch';
-import Text from '@components/Text';
-import useConfirmModal from '@hooks/useConfirmModal';
-import {useMemoizedLazyExpensifyIcons} from '@hooks/useLazyAsset';
-import useLocalize from '@hooks/useLocalize';
-import useOnyx from '@hooks/useOnyx';
-import usePolicyFeatureWriteAccess from '@hooks/usePolicyFeatureWriteAccess';
-import usePrevious from '@hooks/usePrevious';
-import useThemeStyles from '@hooks/useThemeStyles';
-import {deleteReportFieldsListValue, removeReportFieldListValue, setReportFieldsListValueEnabled, updateReportFieldListValueEnabled} from '@libs/actions/Policy/ReportField';
-import Navigation from '@libs/Navigation/Navigation';
-import {hasAccountingConnections as hasAccountingConnectionsUtil} from '@libs/PolicyUtils';
-import type {PolicyFeature} from '@libs/PolicyUtils';
-import {getReportFieldKey} from '@libs/ReportUtils';
-import NotFoundPage from '@pages/ErrorPage/NotFoundPage';
-import AccessOrNotFoundWrapper from '@pages/workspace/AccessOrNotFoundWrapper';
-import CONST from '@src/CONST';
-import ONYXKEYS from '@src/ONYXKEYS';
-import type {Route as Routes} from '@src/ROUTES';
-import type {Policy} from '@src/types/onyx';
-
-type FieldsValueSettingsPageProps = {
-    policy: OnyxEntry<Policy>;
-    policyID: string;
-    valueIndex: number;
-    reportFieldID?: string;
-    isInvoicePage: boolean;
-    featureName: ValueOf<typeof CONST.POLICY.MORE_FEATURES>;
-    policyFeature: PolicyFeature;
-    getEditValueRoute: (isInvoiceRoute: boolean, policyID: string, valueIndex: number) => Routes;
-    testID: string;
-};
-
-function FieldsValueSettingsPage({policy, policyID, valueIndex, reportFieldID, isInvoicePage, featureName, policyFeature, getEditValueRoute, testID}: FieldsValueSettingsPageProps) {
-    const styles = useThemeStyles();
-    const {translate} = useLocalize();
-    const icons = useMemoizedLazyExpensifyIcons(['Trashcan']);
-    const {showConfirmModal} = useConfirmModal();
-    const [formDraft] = useOnyx(ONYXKEYS.FORMS.WORKSPACE_REPORT_FIELDS_FORM_DRAFT);
-    const {canWrite, withReadOnlyFallback} = usePolicyFeatureWriteAccess(policy, policyFeature);
-
-    const [currentValueName, currentValueDisabled] = useMemo(() => {
-        let reportFieldValue: string;
-        let reportFieldDisabledValue: boolean;
-
-        if (reportFieldID) {
-            const reportFieldKey = getReportFieldKey(reportFieldID);
-
-            reportFieldValue = Object.values(policy?.fieldList?.[reportFieldKey]?.values ?? {})?.at(valueIndex) ?? '';
-            reportFieldDisabledValue = Object.values(policy?.fieldList?.[reportFieldKey]?.disabledOptions ?? {})?.at(valueIndex) ?? false;
-        } else {
-            reportFieldValue = formDraft?.listValues?.[valueIndex] ?? '';
-            reportFieldDisabledValue = formDraft?.disabledListValues?.[valueIndex] ?? false;
-        }
-
-        return [reportFieldValue, reportFieldDisabledValue];
-    }, [formDraft?.disabledListValues, formDraft?.listValues, policy?.fieldList, reportFieldID, valueIndex]);
-
-    const hasAccountingConnections = hasAccountingConnectionsUtil(policy);
-    const oldValueName = usePrevious(currentValueName);
-    const reportField = reportFieldID ? policy?.fieldList?.[getReportFieldKey(reportFieldID)] : undefined;
-    const shouldUseInvoiceRoutes = isInvoicePage || reportField?.target === CONST.REPORT_FIELD_TARGETS.INVOICE;
-
-    if (!currentValueName && !oldValueName) {
-        return <NotFoundPage />;
-    }
-
-    const deleteListValueAndHideModal = () => {
-        if (reportFieldID) {
-            removeReportFieldListValue({policy, reportFieldID, valueIndexes: [valueIndex]});
-        } else {
-            deleteReportFieldsListValue({
-                valueIndexes: [valueIndex],
-                listValues: formDraft?.listValues ?? [],
-                disabledListValues: formDraft?.disabledListValues ?? [],
-            });
-        }
-        Navigation.goBack();
-    };
-
-    const showDeleteModal = () => {
-        showConfirmModal({
-            danger: true,
-            title: translate('workspace.reportFields.deleteValue'),
-            prompt: translate('workspace.reportFields.deleteValuePrompt'),
-            confirmText: translate('common.delete'),
-            cancelText: translate('common.cancel'),
-        }).then((result) => {
-            if (result.action !== ModalActions.CONFIRM) {
-                return;
-            }
-
-            deleteListValueAndHideModal();
-        });
-    };
-
-    const updateListValueEnabled = (value: boolean) => {
-        if (reportFieldID) {
-            updateReportFieldListValueEnabled({policy, reportFieldID, valueIndexes: [Number(valueIndex)], enabled: value});
-            return;
-        }
-
-        setReportFieldsListValueEnabled({
-            valueIndexes: [valueIndex],
-            enabled: value,
-            disabledListValues: formDraft?.disabledListValues ?? [],
-        });
-    };
-
-    const navigateToEditValue = () => {
-        Navigation.navigate(getEditValueRoute(shouldUseInvoiceRoutes, policyID, valueIndex));
-    };
-
-    return (
-        <AccessOrNotFoundWrapper
-            accessVariants={[CONST.POLICY.ACCESS_VARIANTS.ADMIN, CONST.POLICY.ACCESS_VARIANTS.PAID]}
-            policyID={policyID}
-            featureName={featureName}
-            policyFeature={policyFeature}
-        >
-            <ScreenWrapper
-                enableEdgeToEdgeBottomSafeAreaPadding
-                style={styles.defaultModalContainer}
-                testID={testID}
-            >
-                <HeaderWithBackButton
-                    title={currentValueName ?? oldValueName}
-                    shouldSetModalVisibility={false}
-                />
-                <View style={styles.flexGrow1}>
-                    <View style={[styles.mt2, styles.mh5]}>
-                        <View style={[styles.flexRow, styles.mb5, styles.mr2, styles.alignItemsCenter, styles.justifyContentBetween]}>
-                            <Text
-                                accessible={false}
-                                aria-hidden
-                            >
-                                {translate('workspace.reportFields.enableValue')}
-                            </Text>
-                            <Switch
-                                isOn={!currentValueDisabled}
-                                accessibilityLabel={translate('workspace.reportFields.enableValue')}
-                                onToggle={updateListValueEnabled}
-                                disabled={!canWrite}
-                                disabledAction={withReadOnlyFallback()}
-                                showLockIcon={!canWrite}
-                            />
-                        </View>
-                    </View>
-                    <MenuItemWithTopDescription
-                        title={currentValueName ?? oldValueName}
-                        description={translate('common.value')}
-                        shouldShowRightIcon={canWrite && !reportFieldID}
-                        interactive={canWrite && !reportFieldID}
-                        onPress={navigateToEditValue}
-                    />
-                    {canWrite && !hasAccountingConnections && (
-                        <MenuItem
-                            icon={icons.Trashcan}
-                            title={translate('common.delete')}
-                            onPress={showDeleteModal}
-                        />
-                    )}
-                </View>
-            </ScreenWrapper>
-        </AccessOrNotFoundWrapper>
-    );
-}
-
-export default FieldsValueSettingsPage;
diff --git a/src/pages/workspace/fields/WorkspaceFieldsSection.tsx b/src/pages/workspace/fields/WorkspaceFieldsSection.tsx
deleted file mode 100644
index 3d21a54f3147..000000000000
--- a/src/pages/workspace/fields/WorkspaceFieldsSection.tsx
+++ /dev/null
@@ -1,278 +0,0 @@
-import {FlashList} from '@shopify/flash-list';
-import type {ListRenderItemInfo} from '@shopify/flash-list';
-import {Str} from 'expensify-common';
-import React, {useCallback, useEffect, useMemo} from 'react';
-import {View} from 'react-native';
-import type {OnyxEntry} from 'react-native-onyx';
-import ImportedFromAccountingSoftware from '@components/ImportedFromAccountingSoftware';
-import MenuItem from '@components/MenuItem';
-import {ModalActions} from '@components/Modal/Global/ModalContext';
-import OfflineWithFeedback from '@components/OfflineWithFeedback';
-import Section from '@components/Section';
-import Text from '@components/Text';
-import useConfirmModal from '@hooks/useConfirmModal';
-import {useMemoizedLazyExpensifyIcons} from '@hooks/useLazyAsset';
-import useLocalize from '@hooks/useLocalize';
-import useNetwork from '@hooks/useNetwork';
-import useOnyx from '@hooks/useOnyx';
-import usePolicyFeatureWriteAccess from '@hooks/usePolicyFeatureWriteAccess';
-import useResponsiveLayout from '@hooks/useResponsiveLayout';
-import useThemeStyles from '@hooks/useThemeStyles';
-import {isConnectionInProgress, isConnectionUnverified} from '@libs/actions/connections';
-import Navigation from '@libs/Navigation/Navigation';
-import {getConnectedIntegration, getCurrentConnectionName, hasAccountingConnections as hasAccountingConnectionsPolicyUtils, isControlPolicy, shouldShowSyncError} from '@libs/PolicyUtils';
-import type {PolicyFeature} from '@libs/PolicyUtils';
-import {getReportFieldTypeTranslationKey} from '@libs/WorkspaceReportFieldUtils';
-import ToggleSettingOptionRow from '@pages/workspace/workflows/ToggleSettingsOptionRow';
-import CONST from '@src/CONST';
-import type {TranslationPaths} from '@src/languages/types';
-import ONYXKEYS from '@src/ONYXKEYS';
-import ROUTES from '@src/ROUTES';
-import type {Route} from '@src/ROUTES';
-import type {Policy, PolicyConnectionName} from '@src/types/onyx';
-import type {PendingAction} from '@src/types/onyx/OnyxCommon';
-
-type FieldListValue = NonNullable<Policy['fieldList']>[string];
-
-type FieldListItem = {
-    fieldID: string;
-    isDisabled: boolean;
-    keyForList: string;
-    pendingAction?: PendingAction;
-    rightLabel: string;
-    text: string;
-};
-
-type WorkspaceFieldsSectionProps = {
-    policy: OnyxEntry<Policy>;
-    policyID: string;
-    isEnabled: boolean;
-    pendingAction?: PendingAction | null;
-    fieldFilter: (field: FieldListValue) => boolean;
-    titleKey: TranslationPaths;
-    subtitleKey: TranslationPaths;
-    importedFromAccountingSoftwareKey: TranslationPaths;
-    disableTitleKey: TranslationPaths;
-    disablePromptKey: TranslationPaths;
-    addFieldKey: TranslationPaths;
-    createRoute: Route;
-    getSettingsRoute: (policyID: string, fieldID: string) => Route;
-    upgradeFeatureAlias: string;
-    upgradeBackToRoute: Route;
-    enableFields: (policyID: string, enabled: boolean) => void;
-    openFieldsPage: (policyID: string) => void;
-    policyFeature: PolicyFeature;
-    syncErrorConnectionNames?: readonly PolicyConnectionName[];
-    titleAccessibilityRole?: typeof CONST.ROLE.HEADER;
-};
-
-function keyExtractor(item: FieldListItem) {
-    return item.keyForList;
-}
-
-function WorkspaceFieldsSection({
-    policy,
-    policyID,
-    isEnabled,
-    pendingAction,
-    fieldFilter,
-    titleKey,
-    subtitleKey,
-    importedFromAccountingSoftwareKey,
-    disableTitleKey,
-    disablePromptKey,
-    addFieldKey,
-    createRoute,
-    getSettingsRoute,
-    upgradeFeatureAlias,
-    upgradeBackToRoute,
-    enableFields,
-    openFieldsPage,
-    policyFeature,
-    syncErrorConnectionNames,
-    titleAccessibilityRole,
-}: WorkspaceFieldsSectionProps) {
-    const styles = useThemeStyles();
-    const {translate, localeCompare} = useLocalize();
-    const icons = useMemoizedLazyExpensifyIcons(['Plus']);
-    const {shouldUseNarrowLayout} = useResponsiveLayout();
-    const {showConfirmModal} = useConfirmModal();
-    const [connectionSyncProgress] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY_CONNECTION_SYNC_PROGRESS}${policyID}`);
-    const isSyncInProgress = isConnectionInProgress(connectionSyncProgress, policy);
-    const syncingAccountingIntegration = CONST.POLICY.CONNECTIONS.ACCOUNTING_CONNECTION_NAMES.find((connectionName) => connectionName === connectionSyncProgress?.connectionName);
-    const hasSyncError = shouldShowSyncError(policy, isSyncInProgress, syncErrorConnectionNames);
-    const connectedIntegration = getConnectedIntegration(policy) ?? syncingAccountingIntegration;
-    const isConnectionVerified = connectedIntegration && !isConnectionUnverified(policy, connectedIntegration);
-    const currentConnectionName = getCurrentConnectionName(policy);
-    const hasAccountingConnections = hasAccountingConnectionsPolicyUtils(policy);
-    const fieldList = policy?.fieldList;
-    const {canWrite, withReadOnlyFallback} = usePolicyFeatureWriteAccess(policy, policyFeature);
-
-    const fetchFields = useCallback(() => {
-        openFieldsPage(policyID);
-    }, [openFieldsPage, policyID]);
-
-    const {isOffline} = useNetwork({onReconnect: fetchFields});
-
-    useEffect(() => {
-        fetchFields();
-    }, [fetchFields]);
-
-    const fields = useMemo<FieldListItem[]>(() => {
-        if (!fieldList) {
-            return [];
-        }
-
-        return Object.values(fieldList)
-            .filter(fieldFilter)
-            .sort((a, b) => localeCompare(a.name, b.name))
-            .map((field) => ({
-                text: field.name,
-                keyForList: String(field.fieldID),
-                fieldID: field.fieldID,
-                pendingAction: field.pendingAction,
-                isDisabled: field.pendingAction === CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE,
-                rightLabel: Str.recapitalize(translate(getReportFieldTypeTranslationKey(field.type ?? CONST.REPORT_FIELD_TYPES.TEXT))),
-            }));
-    }, [fieldFilter, fieldList, localeCompare, translate]);
-
-    const navigateToFieldSettings = useCallback(
-        (item: FieldListItem) => {
-            if (!canWrite) {
-                return;
-            }
-
-            Navigation.navigate(getSettingsRoute(policyID, item.fieldID));
-        },
-        [canWrite, getSettingsRoute, policyID],
-    );
-
-    const renderItem = useCallback(
-        ({item}: ListRenderItemInfo<FieldListItem>) => (
-            <OfflineWithFeedback pendingAction={item.pendingAction}>
-                <MenuItem
-                    style={shouldUseNarrowLayout ? styles.ph5 : styles.ph8}
-                    onPress={() => navigateToFieldSettings(item)}
-                    description={item.text}
-                    disabled={item.isDisabled}
-                    shouldShowRightIcon={!item.isDisabled && canWrite}
-                    interactive={!item.isDisabled && canWrite}
-                    rightLabel={item.rightLabel}
-                    descriptionTextStyle={[styles.popoverMenuText, styles.textStrong]}
-                />
-            </OfflineWithFeedback>
-        ),
-        [canWrite, navigateToFieldSettings, shouldUseNarrowLayout, styles.ph5, styles.ph8, styles.popoverMenuText, styles.textStrong],
-    );
-
-    const headerText =
-        !hasSyncError && isConnectionVerified && currentConnectionName ? (
-            <Text style={[styles.mr5, styles.mt1]}>
-                <ImportedFromAccountingSoftware
-                    policyID={policyID}
-                    currentConnectionName={currentConnectionName}
-                    connectedIntegration={connectedIntegration}
-                    translatedText={translate(importedFromAccountingSoftwareKey)}
-                />
-            </Text>
-        ) : (
-            <Text style={[styles.textNormal, styles.colorMuted, styles.mr5, styles.mt1]}>{translate(subtitleKey)}</Text>
-        );
-
-    const switchAccessibilityLabel =
-        !hasSyncError && isConnectionVerified && currentConnectionName
-            ? `${translate(titleKey)}, ${translate(importedFromAccountingSoftwareKey)} ${currentConnectionName} ${translate('workspace.accounting.settings')}`
-            : `${translate(titleKey)}, ${translate(subtitleKey)}`;
-
-    const isLoading = !isOffline && policy === undefined;
-
-    const onDisabledOrganizeSwitchPress = () => {
-        if (!hasAccountingConnections) {
-            return;
-        }
-
-        showConfirmModal({
-            title: translate('workspace.moreFeatures.connectionsWarningModal.featureEnabledTitle'),
-            prompt: translate('workspace.moreFeatures.connectionsWarningModal.featureEnabledText'),
-            confirmText: translate('workspace.moreFeatures.connectionsWarningModal.manageSettings'),
-            cancelText: translate('common.cancel'),
-        }).then((result) => {
-            if (result.action !== ModalActions.CONFIRM) {
-                return;
-            }
-
-            Navigation.navigate(ROUTES.POLICY_ACCOUNTING.getRoute(policyID));
-        });
-    };
-
-    return (
-        <Section
-            isCentralPane
-            containerStyles={shouldUseNarrowLayout ? styles.p5 : styles.p8}
-        >
-            <ToggleSettingOptionRow
-                pendingAction={pendingAction}
-                title={translate(titleKey)}
-                switchAccessibilityLabel={switchAccessibilityLabel}
-                subtitle={headerText}
-                titleStyle={[styles.textHeadline, styles.cardSectionTitle, styles.accountSettingsSectionTitle, styles.mb1]}
-                titleAccessibilityRole={titleAccessibilityRole}
-                isActive={isEnabled}
-                onToggle={(enabled) => {
-                    if (!enabled) {
-                        showConfirmModal({
-                            danger: true,
-                            title: translate(disableTitleKey),
-                            prompt: translate(disablePromptKey),
-                            confirmText: translate('common.disable'),
-                            cancelText: translate('common.cancel'),
-                        }).then((result) => {
-                            if (result.action !== ModalActions.CONFIRM) {
-                                return;
-                            }
-
-                            enableFields(policyID, false);
-                        });
-                        return;
-                    }
-
-                    if (!isControlPolicy(policy)) {
-                        Navigation.navigate(ROUTES.WORKSPACE_UPGRADE.getRoute(policyID, upgradeFeatureAlias, upgradeBackToRoute));
-                        return;
-                    }
-
-                    enableFields(policyID, true);
-                }}
-                disabled={hasAccountingConnections || !canWrite}
-                disabledAction={withReadOnlyFallback(onDisabledOrganizeSwitchPress)}
-                showLockIcon={!canWrite}
-                subMenuItems={
-                    isEnabled && (
-                        <>
-                            <View style={[shouldUseNarrowLayout ? styles.mhn5 : styles.mhn8, styles.mt6]}>
-                                {!isLoading && (
-                                    <FlashList
-                                        data={fields}
-                                        renderItem={renderItem}
-                                        keyExtractor={keyExtractor}
-                                        maintainVisibleContentPosition={{disabled: true}}
-                                    />
-                                )}
-                            </View>
-                            {!hasAccountingConnections && canWrite && (
-                                <MenuItem
-                                    onPress={() => Navigation.navigate(createRoute)}
-                                    title={translate(addFieldKey)}
-                                    icon={icons.Plus}
-                                    style={[styles.sectionMenuItemTopDescription]}
-                                />
-                            )}
-                        </>
-                    )
-                }
-            />
-        </Section>
-    );
-}
-
-export default WorkspaceFieldsSection;
diff --git a/src/pages/workspace/invoices/CreateInvoiceFieldsPage.tsx b/src/pages/workspace/invoices/CreateInvoiceFieldsPage.tsx
deleted file mode 100644
index 09d2fcfb6220..000000000000
--- a/src/pages/workspace/invoices/CreateInvoiceFieldsPage.tsx
+++ /dev/null
@@ -1,31 +0,0 @@
-import React from 'react';
-import type {PlatformStackScreenProps} from '@libs/Navigation/PlatformStackNavigation/types';
-import type {SettingsNavigatorParamList} from '@navigation/types';
-import CreateFieldsPage from '@pages/workspace/fields/CreateFieldsPage';
-import type {WithPolicyAndFullscreenLoadingProps} from '@pages/workspace/withPolicyAndFullscreenLoading';
-import withPolicyAndFullscreenLoading from '@pages/workspace/withPolicyAndFullscreenLoading';
-import CONST from '@src/CONST';
-import ROUTES from '@src/ROUTES';
-import type SCREENS from '@src/SCREENS';
-
-type CreateInvoiceFieldsPageProps = WithPolicyAndFullscreenLoadingProps & PlatformStackScreenProps<SettingsNavigatorParamList, typeof SCREENS.WORKSPACE.INVOICE_FIELDS_CREATE>;
-
-function CreateInvoiceFieldsPage({
-    policy,
-    route: {
-        params: {policyID},
-    },
-}: CreateInvoiceFieldsPageProps) {
-    return (
-        <CreateFieldsPage
-            policy={policy}
-            policyID={policyID}
-            isInvoiceField
-            listValuesRoute={ROUTES.WORKSPACE_INVOICE_FIELDS_LIST_VALUES.getRoute(policyID)}
-            featureName={CONST.POLICY.MORE_FEATURES.ARE_INVOICE_FIELDS_ENABLED}
-            testID="CreateInvoiceFieldsPage"
-        />
-    );
-}
-
-export default withPolicyAndFullscreenLoading(CreateInvoiceFieldsPage);
diff --git a/src/pages/workspace/invoices/InvoiceFieldsAddListValuePage.tsx b/src/pages/workspace/invoices/InvoiceFieldsAddListValuePage.tsx
deleted file mode 100644
index 2c5903371e3a..000000000000
--- a/src/pages/workspace/invoices/InvoiceFieldsAddListValuePage.tsx
+++ /dev/null
@@ -1,30 +0,0 @@
-import React from 'react';
-import type {PlatformStackScreenProps} from '@libs/Navigation/PlatformStackNavigation/types';
-import type {SettingsNavigatorParamList} from '@navigation/types';
-import FieldsAddListValuePage from '@pages/workspace/fields/FieldsAddListValuePage';
-import type {WithPolicyAndFullscreenLoadingProps} from '@pages/workspace/withPolicyAndFullscreenLoading';
-import withPolicyAndFullscreenLoading from '@pages/workspace/withPolicyAndFullscreenLoading';
-import CONST from '@src/CONST';
-import type SCREENS from '@src/SCREENS';
-
-type InvoiceFieldsAddListValuePageProps = WithPolicyAndFullscreenLoadingProps & PlatformStackScreenProps<SettingsNavigatorParamList, typeof SCREENS.WORKSPACE.INVOICE_FIELDS_ADD_VALUE>;
-
-function InvoiceFieldsAddListValuePage({
-    policy,
-    route: {
-        params: {policyID, reportFieldID},
-    },
-}: InvoiceFieldsAddListValuePageProps) {
-    return (
-        <FieldsAddListValuePage
-            policy={policy}
-            policyID={policyID}
-            reportFieldID={reportFieldID}
-            featureName={CONST.POLICY.MORE_FEATURES.ARE_INVOICE_FIELDS_ENABLED}
-            policyFeature={CONST.POLICY.POLICY_FEATURE.MORE_FEATURES}
-            testID="InvoiceFieldsAddListValuePage"
-        />
-    );
-}
-
-export default withPolicyAndFullscreenLoading(InvoiceFieldsAddListValuePage);
diff --git a/src/pages/workspace/invoices/InvoiceFieldsEditValuePage.tsx b/src/pages/workspace/invoices/InvoiceFieldsEditValuePage.tsx
deleted file mode 100644
index fa85ea322669..000000000000
--- a/src/pages/workspace/invoices/InvoiceFieldsEditValuePage.tsx
+++ /dev/null
@@ -1,30 +0,0 @@
-import React from 'react';
-import type {PlatformStackScreenProps} from '@libs/Navigation/PlatformStackNavigation/types';
-import type {SettingsNavigatorParamList} from '@navigation/types';
-import FieldsEditValuePage from '@pages/workspace/fields/FieldsEditValuePage';
-import type {WithPolicyAndFullscreenLoadingProps} from '@pages/workspace/withPolicyAndFullscreenLoading';
-import withPolicyAndFullscreenLoading from '@pages/workspace/withPolicyAndFullscreenLoading';
-import CONST from '@src/CONST';
-import type SCREENS from '@src/SCREENS';
-
-type InvoiceFieldsEditValuePageProps = WithPolicyAndFullscreenLoadingProps & PlatformStackScreenProps<SettingsNavigatorParamList, typeof SCREENS.WORKSPACE.INVOICE_FIELDS_EDIT_VALUE>;
-
-function InvoiceFieldsEditValuePage({
-    policy,
-    route: {
-        params: {policyID, valueIndex},
-    },
-}: InvoiceFieldsEditValuePageProps) {
-    return (
-        <FieldsEditValuePage
-            policy={policy}
-            policyID={policyID}
-            valueIndex={valueIndex}
-            featureName={CONST.POLICY.MORE_FEATURES.ARE_INVOICE_FIELDS_ENABLED}
-            policyFeature={CONST.POLICY.POLICY_FEATURE.MORE_FEATURES}
-            testID="InvoiceFieldsEditValuePage"
-        />
-    );
-}
-
-export default withPolicyAndFullscreenLoading(InvoiceFieldsEditValuePage);
diff --git a/src/pages/workspace/invoices/InvoiceFieldsInitialValuePage.tsx b/src/pages/workspace/invoices/InvoiceFieldsInitialValuePage.tsx
deleted file mode 100644
index 37d848eb6ec4..000000000000
--- a/src/pages/workspace/invoices/InvoiceFieldsInitialValuePage.tsx
+++ /dev/null
@@ -1,30 +0,0 @@
-import React from 'react';
-import type {PlatformStackScreenProps} from '@libs/Navigation/PlatformStackNavigation/types';
-import type {SettingsNavigatorParamList} from '@navigation/types';
-import FieldsInitialValuePage from '@pages/workspace/fields/FieldsInitialValuePage';
-import type {WithPolicyAndFullscreenLoadingProps} from '@pages/workspace/withPolicyAndFullscreenLoading';
-import withPolicyAndFullscreenLoading from '@pages/workspace/withPolicyAndFullscreenLoading';
-import CONST from '@src/CONST';
-import type SCREENS from '@src/SCREENS';
-
-type InvoiceFieldsInitialValuePageProps = WithPolicyAndFullscreenLoadingProps &
-    PlatformStackScreenProps<SettingsNavigatorParamList, typeof SCREENS.WORKSPACE.INVOICE_FIELDS_EDIT_INITIAL_VALUE>;
-
-function InvoiceFieldsInitialValuePage({
-    policy,
-    route: {
-        params: {policyID, reportFieldID},
-    },
-}: InvoiceFieldsInitialValuePageProps) {
-    return (
-        <FieldsInitialValuePage
-            policy={policy}
-            policyID={policyID}
-            reportFieldID={reportFieldID}
-            featureName={CONST.POLICY.MORE_FEATURES.ARE_INVOICE_FIELDS_ENABLED}
-            testID="InvoiceFieldsInitialValuePage"
-        />
-    );
-}
-
-export default withPolicyAndFullscreenLoading(InvoiceFieldsInitialValuePage);
diff --git a/src/pages/workspace/invoices/InvoiceFieldsListValuesPage.tsx b/src/pages/workspace/invoices/InvoiceFieldsListValuesPage.tsx
deleted file mode 100644
index faad02a12da1..000000000000
--- a/src/pages/workspace/invoices/InvoiceFieldsListValuesPage.tsx
+++ /dev/null
@@ -1,40 +0,0 @@
-import React from 'react';
-import type {PlatformStackScreenProps} from '@libs/Navigation/PlatformStackNavigation/types';
-import type {SettingsNavigatorParamList} from '@navigation/types';
-import FieldsListValuesPage from '@pages/workspace/fields/FieldsListValuesPage';
-import type {WithPolicyAndFullscreenLoadingProps} from '@pages/workspace/withPolicyAndFullscreenLoading';
-import withPolicyAndFullscreenLoading from '@pages/workspace/withPolicyAndFullscreenLoading';
-import CONST from '@src/CONST';
-import ROUTES from '@src/ROUTES';
-import type SCREENS from '@src/SCREENS';
-
-type InvoiceFieldsListValuesPageProps = WithPolicyAndFullscreenLoadingProps & PlatformStackScreenProps<SettingsNavigatorParamList, typeof SCREENS.WORKSPACE.INVOICE_FIELDS_LIST_VALUES>;
-
-function InvoiceFieldsListValuesPage({
-    policy,
-    route: {
-        params: {policyID, reportFieldID},
-    },
-}: InvoiceFieldsListValuesPageProps) {
-    return (
-        <FieldsListValuesPage
-            policy={policy}
-            policyID={policyID}
-            reportFieldID={reportFieldID}
-            isInvoicePage
-            featureName={CONST.POLICY.MORE_FEATURES.ARE_INVOICE_FIELDS_ENABLED}
-            policyFeature={CONST.POLICY.POLICY_FEATURE.MORE_FEATURES}
-            getValueSettingsRoute={(isInvoiceRoute, id, valueIndex, fieldID) =>
-                isInvoiceRoute
-                    ? ROUTES.WORKSPACE_INVOICE_FIELDS_VALUE_SETTINGS.getRoute(id, valueIndex, fieldID)
-                    : ROUTES.WORKSPACE_REPORT_FIELDS_VALUE_SETTINGS.getRoute(id, valueIndex, fieldID)
-            }
-            getAddValueRoute={(isInvoiceRoute, id, fieldID) =>
-                isInvoiceRoute ? ROUTES.WORKSPACE_INVOICE_FIELDS_ADD_VALUE.getRoute(id, fieldID) : ROUTES.WORKSPACE_REPORT_FIELDS_ADD_VALUE.getRoute(id, fieldID)
-            }
-            testID="InvoiceFieldsListValuesPage"
-        />
-    );
-}
-
-export default withPolicyAndFullscreenLoading(InvoiceFieldsListValuesPage);
diff --git a/src/pages/workspace/invoices/InvoiceFieldsSettingsPage.tsx b/src/pages/workspace/invoices/InvoiceFieldsSettingsPage.tsx
deleted file mode 100644
index 34d2d62452f7..000000000000
--- a/src/pages/workspace/invoices/InvoiceFieldsSettingsPage.tsx
+++ /dev/null
@@ -1,36 +0,0 @@
-import React from 'react';
-import type {PlatformStackScreenProps} from '@libs/Navigation/PlatformStackNavigation/types';
-import type {SettingsNavigatorParamList} from '@navigation/types';
-import FieldsSettingsPage from '@pages/workspace/fields/FieldsSettingsPage';
-import type {WithPolicyAndFullscreenLoadingProps} from '@pages/workspace/withPolicyAndFullscreenLoading';
-import withPolicyAndFullscreenLoading from '@pages/workspace/withPolicyAndFullscreenLoading';
-import CONST from '@src/CONST';
-import ROUTES from '@src/ROUTES';
-import type SCREENS from '@src/SCREENS';
-
-type InvoiceFieldsSettingsPageProps = WithPolicyAndFullscreenLoadingProps & PlatformStackScreenProps<SettingsNavigatorParamList, typeof SCREENS.WORKSPACE.INVOICE_FIELDS_SETTINGS>;
-
-function InvoiceFieldsSettingsPage({
-    policy,
-    route: {
-        params: {policyID, reportFieldID},
-    },
-}: InvoiceFieldsSettingsPageProps) {
-    return (
-        <FieldsSettingsPage
-            policy={policy}
-            policyID={policyID}
-            reportFieldID={reportFieldID}
-            featureName={CONST.POLICY.MORE_FEATURES.ARE_INVOICE_FIELDS_ENABLED}
-            policyFeature={CONST.POLICY.POLICY_FEATURE.MORE_FEATURES}
-            expectedTarget={CONST.REPORT_FIELD_TARGETS.INVOICE}
-            getListValuesRoute={(id, fieldID) => ROUTES.WORKSPACE_INVOICE_FIELDS_LIST_VALUES.getRoute(id, fieldID)}
-            getInitialValueRoute={(id, fieldID) => ROUTES.WORKSPACE_INVOICE_FIELDS_EDIT_INITIAL_VALUE.getRoute(id, fieldID)}
-            deleteTitleKey="workspace.invoiceFields.delete"
-            deletePromptKey="workspace.invoiceFields.deleteConfirmation"
-            testID="InvoiceFieldsSettingsPage"
-        />
-    );
-}
-
-export default withPolicyAndFullscreenLoading(InvoiceFieldsSettingsPage);
diff --git a/src/pages/workspace/invoices/InvoiceFieldsValueSettingsPage.tsx b/src/pages/workspace/invoices/InvoiceFieldsValueSettingsPage.tsx
deleted file mode 100644
index aa11fd1d4423..000000000000
--- a/src/pages/workspace/invoices/InvoiceFieldsValueSettingsPage.tsx
+++ /dev/null
@@ -1,36 +0,0 @@
-import React from 'react';
-import type {PlatformStackScreenProps} from '@libs/Navigation/PlatformStackNavigation/types';
-import type {SettingsNavigatorParamList} from '@navigation/types';
-import FieldsValueSettingsPage from '@pages/workspace/fields/FieldsValueSettingsPage';
-import type {WithPolicyAndFullscreenLoadingProps} from '@pages/workspace/withPolicyAndFullscreenLoading';
-import withPolicyAndFullscreenLoading from '@pages/workspace/withPolicyAndFullscreenLoading';
-import CONST from '@src/CONST';
-import ROUTES from '@src/ROUTES';
-import type SCREENS from '@src/SCREENS';
-
-type InvoiceFieldsValueSettingsPageProps = WithPolicyAndFullscreenLoadingProps & PlatformStackScreenProps<SettingsNavigatorParamList, typeof SCREENS.WORKSPACE.INVOICE_FIELDS_VALUE_SETTINGS>;
-
-function InvoiceFieldsValueSettingsPage({
-    policy,
-    route: {
-        params: {policyID, valueIndex, reportFieldID},
-    },
-}: InvoiceFieldsValueSettingsPageProps) {
-    return (
-        <FieldsValueSettingsPage
-            policy={policy}
-            policyID={policyID}
-            valueIndex={valueIndex}
-            reportFieldID={reportFieldID}
-            isInvoicePage
-            featureName={CONST.POLICY.MORE_FEATURES.ARE_INVOICE_FIELDS_ENABLED}
-            policyFeature={CONST.POLICY.POLICY_FEATURE.MORE_FEATURES}
-            getEditValueRoute={(isInvoiceRoute, id, index) =>
-                isInvoiceRoute ? ROUTES.WORKSPACE_INVOICE_FIELDS_EDIT_VALUE.getRoute(id, index) : ROUTES.WORKSPACE_REPORT_FIELDS_EDIT_VALUE.getRoute(id, index)
-            }
-            testID="InvoiceFieldsValueSettingsPage"
-        />
-    );
-}
-
-export default withPolicyAndFullscreenLoading(InvoiceFieldsValueSettingsPage);
diff --git a/src/pages/workspace/invoices/WorkspaceInvoiceFieldsSection.tsx b/src/pages/workspace/invoices/WorkspaceInvoiceFieldsSection.tsx
deleted file mode 100644
index b3f3b8ef0510..000000000000
--- a/src/pages/workspace/invoices/WorkspaceInvoiceFieldsSection.tsx
+++ /dev/null
@@ -1,42 +0,0 @@
-import React from 'react';
-import usePolicy from '@hooks/usePolicy';
-import {enablePolicyInvoiceFields} from '@libs/actions/Policy/Policy';
-import WorkspaceFieldsSection from '@pages/workspace/fields/WorkspaceFieldsSection';
-import {openPolicyInvoicesPage} from '@userActions/Policy/ReportField';
-import CONST from '@src/CONST';
-import ROUTES from '@src/ROUTES';
-
-type WorkspaceInvoiceFieldsSectionProps = {
-    policyID: string;
-};
-
-function WorkspaceInvoiceFieldsSection({policyID}: WorkspaceInvoiceFieldsSectionProps) {
-    const policy = usePolicy(policyID);
-
-    return (
-        <WorkspaceFieldsSection
-            policy={policy}
-            policyID={policyID}
-            isEnabled={!!policy?.areInvoiceFieldsEnabled}
-            pendingAction={policy?.pendingFields?.areInvoiceFieldsEnabled}
-            fieldFilter={(field) => field.target === CONST.REPORT_FIELD_TARGETS.INVOICE}
-            titleKey="workspace.common.invoiceFields"
-            subtitleKey="workspace.invoiceFields.subtitle"
-            importedFromAccountingSoftwareKey="workspace.invoiceFields.importedFromAccountingSoftware"
-            disableTitleKey="workspace.invoiceFields.disableInvoiceFields"
-            disablePromptKey="workspace.invoiceFields.disableInvoiceFieldsConfirmation"
-            addFieldKey="workspace.invoiceFields.addField"
-            createRoute={ROUTES.WORKSPACE_INVOICE_FIELDS_CREATE.getRoute(policyID)}
-            getSettingsRoute={ROUTES.WORKSPACE_INVOICE_FIELDS_SETTINGS.getRoute}
-            upgradeFeatureAlias={CONST.UPGRADE_FEATURE_INTRO_MAPPING.invoiceFields.alias}
-            upgradeBackToRoute={ROUTES.WORKSPACE_INVOICES.getRoute(policyID)}
-            enableFields={enablePolicyInvoiceFields}
-            openFieldsPage={openPolicyInvoicesPage}
-            policyFeature={CONST.POLICY.POLICY_FEATURE.MORE_FEATURES}
-        />
-    );
-}
-
-WorkspaceInvoiceFieldsSection.displayName = 'WorkspaceInvoiceFieldsSection';
-
-export default WorkspaceInvoiceFieldsSection;
diff --git a/src/pages/workspace/invoices/WorkspaceInvoicesPage.tsx b/src/pages/workspace/invoices/WorkspaceInvoicesPage.tsx
index 1cd2bd91961a..836b4dbff4c6 100644
--- a/src/pages/workspace/invoices/WorkspaceInvoicesPage.tsx
+++ b/src/pages/workspace/invoices/WorkspaceInvoicesPage.tsx
@@ -14,7 +14,6 @@ import WorkspacePageWithSections from '@pages/workspace/WorkspacePageWithSection
 import CONST from '@src/CONST';
 import type SCREENS from '@src/SCREENS';
 import WorkspaceInvoiceBalanceSection from './WorkspaceInvoiceBalanceSection';
-import WorkspaceInvoiceFieldsSection from './WorkspaceInvoiceFieldsSection';
 import WorkspaceInvoiceVBASection from './WorkspaceInvoiceVBASection';
 import WorkspaceInvoicingDetailsSection from './WorkspaceInvoicingDetailsSection';
 
@@ -61,7 +60,6 @@ function WorkspaceInvoicesPage({route}: WorkspaceInvoicesPageProps) {
                                 canWriteMoreFeatures={canWriteMoreFeatures}
                             />
                         )}
-                        {!!policyID && <WorkspaceInvoiceFieldsSection policyID={policyID} />}
                     </View>
                 )}
             </WorkspacePageWithSections>
diff --git a/src/pages/workspace/reports/CreateReportFieldsPage.tsx b/src/pages/workspace/reports/CreateReportFieldsPage.tsx
index 0b068a78a6b7..5b5deafe055a 100644
--- a/src/pages/workspace/reports/CreateReportFieldsPage.tsx
+++ b/src/pages/workspace/reports/CreateReportFieldsPage.tsx
@@ -1,30 +1,285 @@
-import React from 'react';
+import React, {useCallback, useEffect, useRef} from 'react';
+import {View} from 'react-native';
+import type {OnyxCollection} from 'react-native-onyx';
+import FormProvider from '@components/Form/FormProvider';
+import InputWrapper from '@components/Form/InputWrapper';
+import type {FormInputErrors, FormOnyxValues, FormRef} from '@components/Form/types';
+import HeaderWithBackButton from '@components/HeaderWithBackButton';
+import MenuItemWithTopDescription from '@components/MenuItemWithTopDescription';
+import ScreenWrapper from '@components/ScreenWrapper';
+import TextPicker from '@components/TextPicker';
+import useLocalize from '@hooks/useLocalize';
+import useOnyx from '@hooks/useOnyx';
+import useThemeStyles from '@hooks/useThemeStyles';
+import DateUtils from '@libs/DateUtils';
+import {addErrorMessage} from '@libs/ErrorUtils';
+import {hasCircularReferences} from '@libs/Formula';
+import Navigation from '@libs/Navigation/Navigation';
 import type {PlatformStackScreenProps} from '@libs/Navigation/PlatformStackNavigation/types';
+import {hasAccountingConnections} from '@libs/PolicyUtils';
+import {isRequiredFulfilled} from '@libs/ValidationUtils';
+import {getUnsupportedReportFieldFormulaParts, hasFormulaPartsInInitialValue, isReportFieldNameExisting} from '@libs/WorkspaceReportFieldUtils';
 import type {SettingsNavigatorParamList} from '@navigation/types';
-import CreateFieldsPage from '@pages/workspace/fields/CreateFieldsPage';
+import AccessOrNotFoundWrapper from '@pages/workspace/AccessOrNotFoundWrapper';
 import type {WithPolicyAndFullscreenLoadingProps} from '@pages/workspace/withPolicyAndFullscreenLoading';
 import withPolicyAndFullscreenLoading from '@pages/workspace/withPolicyAndFullscreenLoading';
+import {createReportField, setInitialCreateReportFieldsForm} from '@userActions/Policy/ReportField';
 import CONST from '@src/CONST';
+import ONYXKEYS from '@src/ONYXKEYS';
 import ROUTES from '@src/ROUTES';
 import type SCREENS from '@src/SCREENS';
+import INPUT_IDS from '@src/types/form/WorkspaceReportFieldForm';
+import type {Report} from '@src/types/onyx';
+import InitialListValueSelector from './InitialListValueSelector';
+import TypeSelector from './TypeSelector';
 
 type CreateReportFieldsPageProps = WithPolicyAndFullscreenLoadingProps & PlatformStackScreenProps<SettingsNavigatorParamList, typeof SCREENS.WORKSPACE.REPORT_FIELDS_CREATE>;
 
+const defaultDate = DateUtils.extractDate(new Date().toString());
+
 function WorkspaceCreateReportFieldsPage({
     policy,
     route: {
         params: {policyID},
     },
 }: CreateReportFieldsPageProps) {
+    const styles = useThemeStyles();
+    const {translate, localeCompare} = useLocalize();
+    const formRef = useRef<FormRef>(null);
+    const [formDraft] = useOnyx(ONYXKEYS.FORMS.WORKSPACE_REPORT_FIELDS_FORM_DRAFT);
+
+    const policyExpenseReportIDsSelector = useCallback(
+        (reports: OnyxCollection<Report>) =>
+            Object.values(reports ?? {})
+                .filter((report) => report?.policyID === policyID && report.type === CONST.REPORT.TYPE.EXPENSE)
+                .map((report) => report?.reportID),
+        [policyID],
+    );
+
+    const [policyExpenseReportIDs] = useOnyx(ONYXKEYS.COLLECTION.REPORT, {
+        selector: policyExpenseReportIDsSelector,
+    });
+
+    const availableListValuesLength = (formDraft?.[INPUT_IDS.DISABLED_LIST_VALUES] ?? []).filter((disabledListValue) => !disabledListValue).length;
+
+    const submitForm = useCallback(
+        (values: FormOnyxValues<typeof ONYXKEYS.FORMS.WORKSPACE_REPORT_FIELDS_FORM>) => {
+            createReportField({
+                policy,
+                name: values[INPUT_IDS.NAME],
+                type: values[INPUT_IDS.TYPE],
+                initialValue: !(values[INPUT_IDS.TYPE] === CONST.REPORT_FIELD_TYPES.LIST && availableListValuesLength === 0) ? values[INPUT_IDS.INITIAL_VALUE] : '',
+                listValues: formDraft?.[INPUT_IDS.LIST_VALUES] ?? [],
+                disabledListValues: formDraft?.[INPUT_IDS.DISABLED_LIST_VALUES] ?? [],
+                policyExpenseReportIDs,
+            });
+            Navigation.goBack();
+        },
+        [availableListValuesLength, formDraft, policy, policyExpenseReportIDs],
+    );
+
+    const validateForm = useCallback(
+        (values: FormOnyxValues<typeof ONYXKEYS.FORMS.WORKSPACE_REPORT_FIELDS_FORM>): FormInputErrors<typeof ONYXKEYS.FORMS.WORKSPACE_REPORT_FIELDS_FORM> => {
+            const {name, type, initialValue: formInitialValue} = values;
+            const errors: FormInputErrors<typeof ONYXKEYS.FORMS.WORKSPACE_REPORT_FIELDS_FORM> = {};
+
+            if (!isRequiredFulfilled(name)) {
+                errors[INPUT_IDS.NAME] = translate('workspace.reportFields.reportFieldNameRequiredError');
+            } else if (isReportFieldNameExisting(policy?.fieldList, name)) {
+                errors[INPUT_IDS.NAME] = translate('workspace.reportFields.existingReportFieldNameError');
+            } else if ([...name].length > CONST.WORKSPACE_REPORT_FIELD_POLICY_MAX_LENGTH) {
+                // Uses the spread syntax to count the number of Unicode code points instead of the number of UTF-16 code units.
+                addErrorMessage(errors, INPUT_IDS.NAME, translate('common.error.characterLimitExceedCounter', [...name].length, CONST.WORKSPACE_REPORT_FIELD_POLICY_MAX_LENGTH));
+            }
+
+            if (!isRequiredFulfilled(type)) {
+                errors[INPUT_IDS.TYPE] = translate('workspace.reportFields.reportFieldTypeRequiredError');
+            }
+
+            // formInitialValue can be undefined because the InitialValue component is rendered conditionally.
+            // If it's not been rendered when the validation is executed, formInitialValue will be undefined.
+            if (type === CONST.REPORT_FIELD_TYPES.TEXT && !!formInitialValue && formInitialValue.length > CONST.WORKSPACE_REPORT_FIELD_POLICY_MAX_LENGTH) {
+                errors[INPUT_IDS.INITIAL_VALUE] = translate('common.error.characterLimitExceedCounter', formInitialValue.length, CONST.WORKSPACE_REPORT_FIELD_POLICY_MAX_LENGTH);
+            }
+
+            if ((type === CONST.REPORT_FIELD_TYPES.TEXT || type === CONST.REPORT_FIELD_TYPES.FORMULA) && hasCircularReferences(formInitialValue, name, policy?.fieldList)) {
+                errors[INPUT_IDS.INITIAL_VALUE] = translate('workspace.reportFields.circularReferenceError');
+            }
+
+            if ((type === CONST.REPORT_FIELD_TYPES.TEXT || type === CONST.REPORT_FIELD_TYPES.FORMULA) && !!formInitialValue && !errors[INPUT_IDS.INITIAL_VALUE]) {
+                const unsupportedFormulaParts = getUnsupportedReportFieldFormulaParts(formInitialValue);
+                if (unsupportedFormulaParts.length > 0) {
+                    errors[INPUT_IDS.INITIAL_VALUE] = translate('workspace.reportFields.unsupportedFormulaValueError', {
+                        value: unsupportedFormulaParts.join(', '),
+                    });
+                }
+            }
+
+            if (type === CONST.REPORT_FIELD_TYPES.LIST && availableListValuesLength > 0 && !isRequiredFulfilled(formInitialValue)) {
+                errors[INPUT_IDS.INITIAL_VALUE] = translate('workspace.reportFields.reportFieldInitialValueRequiredError');
+            }
+
+            return errors;
+        },
+        [availableListValuesLength, policy?.fieldList, translate],
+    );
+
+    const validateName = useCallback(
+        (values: Record<string, string>) => {
+            const errors: Record<string, string> = {};
+            const name = values[INPUT_IDS.NAME];
+            if (isReportFieldNameExisting(policy?.fieldList, name)) {
+                errors[INPUT_IDS.NAME] = translate('workspace.reportFields.existingReportFieldNameError');
+            }
+            return errors;
+        },
+        [policy?.fieldList, translate],
+    );
+
+    const handleOnValueCommitted = useCallback(
+        (inputValues: FormOnyxValues<typeof ONYXKEYS.FORMS.WORKSPACE_REPORT_FIELDS_FORM>) => (initialValue: string) => {
+            // Mirror optimisticType logic from createReportField: if user enters a formula
+            // while type is Text, automatically switch the type to Formula in the form, otherwise back to Text.
+            const isFormula = hasFormulaPartsInInitialValue(initialValue);
+            if (isFormula) {
+                formRef.current?.resetForm({
+                    ...inputValues,
+                    [INPUT_IDS.TYPE]: CONST.REPORT_FIELD_TYPES.FORMULA,
+                    [INPUT_IDS.INITIAL_VALUE]: initialValue,
+                });
+            } else {
+                formRef.current?.resetForm({
+                    ...inputValues,
+                    [INPUT_IDS.TYPE]: CONST.REPORT_FIELD_TYPES.TEXT,
+                    [INPUT_IDS.INITIAL_VALUE]: initialValue,
+                });
+            }
+        },
+        [],
+    );
+
+    useEffect(() => {
+        setInitialCreateReportFieldsForm();
+    }, []);
+
+    const listValues = [...(formDraft?.[INPUT_IDS.LIST_VALUES] ?? [])].sort(localeCompare).join(', ');
+
     return (
-        <CreateFieldsPage
-            policy={policy}
+        <AccessOrNotFoundWrapper
+            accessVariants={[CONST.POLICY.ACCESS_VARIANTS.ADMIN, CONST.POLICY.ACCESS_VARIANTS.PAID]}
             policyID={policyID}
-            isInvoiceField={false}
-            listValuesRoute={ROUTES.WORKSPACE_REPORT_FIELDS_LIST_VALUES.getRoute(policyID)}
             featureName={CONST.POLICY.MORE_FEATURES.ARE_REPORT_FIELDS_ENABLED}
-            testID="WorkspaceCreateReportFieldsPage"
-        />
+            shouldBeBlocked={hasAccountingConnections(policy)}
+        >
+            <ScreenWrapper
+                enableEdgeToEdgeBottomSafeAreaPadding
+                style={styles.defaultModalContainer}
+                testID="WorkspaceCreateReportFieldsPage"
+                shouldEnableMaxHeight
+            >
+                <HeaderWithBackButton
+                    title={translate('workspace.reportFields.addField')}
+                    onBackButtonPress={Navigation.goBack}
+                />
+                <FormProvider
+                    ref={formRef}
+                    style={[styles.mh5, styles.flex1]}
+                    formID={ONYXKEYS.FORMS.WORKSPACE_REPORT_FIELDS_FORM}
+                    onSubmit={submitForm}
+                    validate={validateForm}
+                    submitButtonText={translate('common.save')}
+                    enabledWhenOffline
+                    shouldValidateOnBlur={false}
+                    addBottomSafeAreaPadding
+                    shouldUseStrictHtmlTagValidation
+                >
+                    {({inputValues}) => (
+                        <View style={styles.mhn5}>
+                            <InputWrapper
+                                InputComponent={TextPicker}
+                                inputID={INPUT_IDS.NAME}
+                                label={translate('common.name')}
+                                subtitle={translate('workspace.reportFields.nameInputSubtitle')}
+                                description={translate('common.name')}
+                                rightLabel={translate('common.required')}
+                                accessibilityLabel={translate('workspace.editor.nameInputLabel')}
+                                maxLength={CONST.WORKSPACE_REPORT_FIELD_POLICY_MAX_LENGTH}
+                                multiline={false}
+                                role={CONST.ROLE.PRESENTATION}
+                                required
+                                customValidate={validateName}
+                                shouldUseStrictHtmlTagValidation
+                            />
+                            <InputWrapper
+                                InputComponent={TypeSelector}
+                                inputID={INPUT_IDS.TYPE}
+                                label={translate('common.type')}
+                                subtitle={translate('workspace.reportFields.typeInputSubtitle')}
+                                rightLabel={translate('common.required')}
+                                onTypeSelected={(type) => {
+                                    let initialValue;
+                                    if (type === CONST.REPORT_FIELD_TYPES.DATE) {
+                                        initialValue = defaultDate;
+                                    } else if (type === CONST.REPORT_FIELD_TYPES.FORMULA) {
+                                        initialValue = '{report:id}';
+                                    } else {
+                                        initialValue = '';
+                                    }
+
+                                    formRef.current?.resetForm({
+                                        ...inputValues,
+                                        type,
+                                        initialValue,
+                                    });
+                                }}
+                            />
+
+                            {inputValues[INPUT_IDS.TYPE] === CONST.REPORT_FIELD_TYPES.LIST && (
+                                <MenuItemWithTopDescription
+                                    description={translate('workspace.reportFields.listValues')}
+                                    shouldShowRightIcon
+                                    onPress={() => Navigation.navigate(ROUTES.WORKSPACE_REPORT_FIELDS_LIST_VALUES.getRoute(policyID))}
+                                    title={listValues}
+                                    numberOfLinesTitle={5}
+                                />
+                            )}
+
+                            {(inputValues[INPUT_IDS.TYPE] === CONST.REPORT_FIELD_TYPES.TEXT || inputValues[INPUT_IDS.TYPE] === CONST.REPORT_FIELD_TYPES.FORMULA) && (
+                                <InputWrapper
+                                    InputComponent={TextPicker}
+                                    inputID={INPUT_IDS.INITIAL_VALUE}
+                                    label={translate('common.initialValue')}
+                                    subtitle={translate('workspace.reportFields.initialValueInputSubtitle')}
+                                    description={translate('common.initialValue')}
+                                    accessibilityLabel={translate('workspace.editor.initialValueInputLabel')}
+                                    maxLength={CONST.WORKSPACE_REPORT_FIELD_POLICY_MAX_LENGTH}
+                                    multiline={false}
+                                    role={CONST.ROLE.PRESENTATION}
+                                    onValueCommitted={handleOnValueCommitted(inputValues)}
+                                />
+                            )}
+
+                            {inputValues[INPUT_IDS.TYPE] === CONST.REPORT_FIELD_TYPES.DATE && (
+                                <MenuItemWithTopDescription
+                                    title={translate('common.currentDate')}
+                                    description={translate('common.initialValue')}
+                                    rightLabel={translate('common.required')}
+                                    interactive={false}
+                                />
+                            )}
+
+                            {inputValues[INPUT_IDS.TYPE] === CONST.REPORT_FIELD_TYPES.LIST && availableListValuesLength > 0 && (
+                                <InputWrapper
+                                    InputComponent={InitialListValueSelector}
+                                    inputID={INPUT_IDS.INITIAL_VALUE}
+                                    label={translate('common.initialValue')}
+                                />
+                            )}
+                        </View>
+                    )}
+                </FormProvider>
+            </ScreenWrapper>
+        </AccessOrNotFoundWrapper>
     );
 }
 
diff --git a/src/pages/workspace/reports/ReportFieldsAddListValuePage.tsx b/src/pages/workspace/reports/ReportFieldsAddListValuePage.tsx
index 9d2539e51100..6e4aa986b611 100644
--- a/src/pages/workspace/reports/ReportFieldsAddListValuePage.tsx
+++ b/src/pages/workspace/reports/ReportFieldsAddListValuePage.tsx
@@ -1,11 +1,29 @@
-import React from 'react';
+import React, {useCallback, useMemo} from 'react';
+import {Keyboard} from 'react-native';
+import FormProvider from '@components/Form/FormProvider';
+import InputWrapper from '@components/Form/InputWrapper';
+import type {FormOnyxValues} from '@components/Form/types';
+import HeaderWithBackButton from '@components/HeaderWithBackButton';
+import ScreenWrapper from '@components/ScreenWrapper';
+import TextInput from '@components/TextInput';
+import useAutoFocusInput from '@hooks/useAutoFocusInput';
+import useLocalize from '@hooks/useLocalize';
+import useOnyx from '@hooks/useOnyx';
+import useThemeStyles from '@hooks/useThemeStyles';
+import Navigation from '@libs/Navigation/Navigation';
 import type {PlatformStackScreenProps} from '@libs/Navigation/PlatformStackNavigation/types';
+import {hasAccountingConnections} from '@libs/PolicyUtils';
+import {getReportFieldKey} from '@libs/ReportUtils';
+import {validateReportFieldListValueName} from '@libs/WorkspaceReportFieldUtils';
 import type {SettingsNavigatorParamList} from '@navigation/types';
-import FieldsAddListValuePage from '@pages/workspace/fields/FieldsAddListValuePage';
+import AccessOrNotFoundWrapper from '@pages/workspace/AccessOrNotFoundWrapper';
 import type {WithPolicyAndFullscreenLoadingProps} from '@pages/workspace/withPolicyAndFullscreenLoading';
 import withPolicyAndFullscreenLoading from '@pages/workspace/withPolicyAndFullscreenLoading';
+import {addReportFieldListValue, createReportFieldsListValue} from '@userActions/Policy/ReportField';
 import CONST from '@src/CONST';
+import ONYXKEYS from '@src/ONYXKEYS';
 import type SCREENS from '@src/SCREENS';
+import INPUT_IDS from '@src/types/form/WorkspaceReportFieldForm';
 
 type ReportFieldsAddListValuePageProps = WithPolicyAndFullscreenLoadingProps & PlatformStackScreenProps<SettingsNavigatorParamList, typeof SCREENS.WORKSPACE.REPORT_FIELDS_ADD_VALUE>;
 
@@ -15,15 +33,83 @@ function ReportFieldsAddListValuePage({
         params: {policyID, reportFieldID},
     },
 }: ReportFieldsAddListValuePageProps) {
+    const styles = useThemeStyles();
+    const {translate} = useLocalize();
+    const {inputCallbackRef} = useAutoFocusInput();
+    const [formDraft] = useOnyx(ONYXKEYS.FORMS.WORKSPACE_REPORT_FIELDS_FORM_DRAFT);
+
+    const listValues = useMemo(() => {
+        let reportFieldListValues: string[];
+        if (reportFieldID) {
+            const reportFieldKey = getReportFieldKey(reportFieldID);
+            reportFieldListValues = Object.values(policy?.fieldList?.[reportFieldKey]?.values ?? {});
+        } else {
+            reportFieldListValues = formDraft?.[INPUT_IDS.LIST_VALUES] ?? [];
+        }
+        return reportFieldListValues;
+    }, [formDraft, policy?.fieldList, reportFieldID]);
+
+    const validate = useCallback(
+        (values: FormOnyxValues<typeof ONYXKEYS.FORMS.WORKSPACE_REPORT_FIELDS_FORM>) =>
+            validateReportFieldListValueName(values[INPUT_IDS.VALUE_NAME].trim(), '', listValues, INPUT_IDS.VALUE_NAME, translate),
+        [listValues, translate],
+    );
+
+    const createValue = useCallback(
+        (values: FormOnyxValues<typeof ONYXKEYS.FORMS.WORKSPACE_REPORT_FIELDS_FORM>) => {
+            if (reportFieldID) {
+                addReportFieldListValue({policy, reportFieldID, valueName: values[INPUT_IDS.VALUE_NAME]});
+            } else {
+                createReportFieldsListValue({
+                    valueName: values[INPUT_IDS.VALUE_NAME],
+                    listValues: formDraft?.[INPUT_IDS.LIST_VALUES] ?? [],
+                    disabledListValues: formDraft?.[INPUT_IDS.DISABLED_LIST_VALUES] ?? [],
+                });
+            }
+            Keyboard.dismiss();
+            Navigation.goBack();
+        },
+        [formDraft, policy, reportFieldID],
+    );
+
     return (
-        <FieldsAddListValuePage
-            policy={policy}
+        <AccessOrNotFoundWrapper
+            accessVariants={[CONST.POLICY.ACCESS_VARIANTS.ADMIN, CONST.POLICY.ACCESS_VARIANTS.PAID]}
             policyID={policyID}
-            reportFieldID={reportFieldID}
             featureName={CONST.POLICY.MORE_FEATURES.ARE_REPORT_FIELDS_ENABLED}
-            policyFeature={CONST.POLICY.POLICY_FEATURE.REPORT_FIELDS}
-            testID="ReportFieldsAddListValuePage"
-        />
+            shouldBeBlocked={hasAccountingConnections(policy)}
+        >
+            <ScreenWrapper
+                enableEdgeToEdgeBottomSafeAreaPadding
+                style={styles.defaultModalContainer}
+                testID="ReportFieldsAddListValuePage"
+                shouldEnableMaxHeight
+            >
+                <HeaderWithBackButton
+                    title={translate('workspace.reportFields.addValue')}
+                    onBackButtonPress={Navigation.goBack}
+                />
+                <FormProvider
+                    formID={ONYXKEYS.FORMS.WORKSPACE_REPORT_FIELDS_FORM}
+                    onSubmit={createValue}
+                    submitButtonText={translate('common.save')}
+                    validate={validate}
+                    style={[styles.mh5, styles.flex1]}
+                    enabledWhenOffline
+                    shouldHideFixErrorsAlert
+                    addBottomSafeAreaPadding
+                >
+                    <InputWrapper
+                        InputComponent={TextInput}
+                        label={translate('common.value')}
+                        accessibilityLabel={translate('common.value')}
+                        inputID={INPUT_IDS.VALUE_NAME}
+                        role={CONST.ROLE.PRESENTATION}
+                        ref={inputCallbackRef}
+                    />
+                </FormProvider>
+            </ScreenWrapper>
+        </AccessOrNotFoundWrapper>
     );
 }
 
diff --git a/src/pages/workspace/reports/ReportFieldsEditValuePage.tsx b/src/pages/workspace/reports/ReportFieldsEditValuePage.tsx
index a6e560eea958..4a9247b6071f 100644
--- a/src/pages/workspace/reports/ReportFieldsEditValuePage.tsx
+++ b/src/pages/workspace/reports/ReportFieldsEditValuePage.tsx
@@ -1,11 +1,29 @@
-import React from 'react';
+import React, {useCallback} from 'react';
+import {Keyboard} from 'react-native';
+import FormProvider from '@components/Form/FormProvider';
+import InputWrapper from '@components/Form/InputWrapper';
+import type {FormOnyxValues} from '@components/Form/types';
+import HeaderWithBackButton from '@components/HeaderWithBackButton';
+import ScreenWrapper from '@components/ScreenWrapper';
+import TextInput from '@components/TextInput';
+import useAutoFocusInput from '@hooks/useAutoFocusInput';
+import useLocalize from '@hooks/useLocalize';
+import useOnyx from '@hooks/useOnyx';
+import usePolicyFeatureWriteAccess from '@hooks/usePolicyFeatureWriteAccess';
+import useThemeStyles from '@hooks/useThemeStyles';
+import Navigation from '@libs/Navigation/Navigation';
 import type {PlatformStackScreenProps} from '@libs/Navigation/PlatformStackNavigation/types';
+import {hasAccountingConnections} from '@libs/PolicyUtils';
+import {validateReportFieldListValueName} from '@libs/WorkspaceReportFieldUtils';
 import type {SettingsNavigatorParamList} from '@navigation/types';
-import FieldsEditValuePage from '@pages/workspace/fields/FieldsEditValuePage';
+import AccessOrNotFoundWrapper from '@pages/workspace/AccessOrNotFoundWrapper';
 import type {WithPolicyAndFullscreenLoadingProps} from '@pages/workspace/withPolicyAndFullscreenLoading';
 import withPolicyAndFullscreenLoading from '@pages/workspace/withPolicyAndFullscreenLoading';
+import {renameReportFieldsListValue} from '@userActions/Policy/ReportField';
 import CONST from '@src/CONST';
+import ONYXKEYS from '@src/ONYXKEYS';
 import type SCREENS from '@src/SCREENS';
+import INPUT_IDS from '@src/types/form/WorkspaceReportFieldForm';
 
 type ReportFieldsEditValuePageProps = WithPolicyAndFullscreenLoadingProps & PlatformStackScreenProps<SettingsNavigatorParamList, typeof SCREENS.WORKSPACE.REPORT_FIELDS_EDIT_VALUE>;
 
@@ -15,15 +33,78 @@ function ReportFieldsEditValuePage({
         params: {policyID, valueIndex},
     },
 }: ReportFieldsEditValuePageProps) {
+    const styles = useThemeStyles();
+    const {translate} = useLocalize();
+    const {inputCallbackRef} = useAutoFocusInput();
+    const [formDraft] = useOnyx(ONYXKEYS.FORMS.WORKSPACE_REPORT_FIELDS_FORM_DRAFT);
+    const {canWrite: canWriteReportFields} = usePolicyFeatureWriteAccess(policy, CONST.POLICY.POLICY_FEATURE.REPORT_FIELDS);
+
+    const currentValueName = formDraft?.listValues?.[valueIndex] ?? '';
+
+    const validate = useCallback(
+        (values: FormOnyxValues<typeof ONYXKEYS.FORMS.WORKSPACE_REPORT_FIELDS_FORM>) =>
+            validateReportFieldListValueName(values[INPUT_IDS.NEW_VALUE_NAME].trim(), currentValueName, formDraft?.[INPUT_IDS.LIST_VALUES] ?? [], INPUT_IDS.NEW_VALUE_NAME, translate),
+        [currentValueName, formDraft, translate],
+    );
+
+    const editValue = useCallback(
+        (values: FormOnyxValues<typeof ONYXKEYS.FORMS.WORKSPACE_REPORT_FIELDS_FORM>) => {
+            const valueName = values[INPUT_IDS.NEW_VALUE_NAME]?.trim();
+            if (currentValueName !== valueName) {
+                renameReportFieldsListValue({
+                    valueIndex,
+                    newValueName: valueName,
+                    listValues: formDraft?.[INPUT_IDS.LIST_VALUES] ?? [],
+                });
+            }
+            Keyboard.dismiss();
+            Navigation.goBack();
+        },
+        [currentValueName, formDraft, valueIndex],
+    );
+
     return (
-        <FieldsEditValuePage
-            policy={policy}
+        <AccessOrNotFoundWrapper
+            accessVariants={[CONST.POLICY.ACCESS_VARIANTS.ADMIN, CONST.POLICY.ACCESS_VARIANTS.PAID]}
             policyID={policyID}
-            valueIndex={valueIndex}
             featureName={CONST.POLICY.MORE_FEATURES.ARE_REPORT_FIELDS_ENABLED}
             policyFeature={CONST.POLICY.POLICY_FEATURE.REPORT_FIELDS}
-            testID="ReportFieldsEditValuePage"
-        />
+            shouldBeBlocked={hasAccountingConnections(policy)}
+        >
+            <ScreenWrapper
+                enableEdgeToEdgeBottomSafeAreaPadding
+                style={styles.defaultModalContainer}
+                testID="ReportFieldsEditValuePage"
+                shouldEnableMaxHeight
+            >
+                <HeaderWithBackButton
+                    title={translate('workspace.reportFields.editValue')}
+                    onBackButtonPress={Navigation.goBack}
+                />
+                <FormProvider
+                    formID={ONYXKEYS.FORMS.WORKSPACE_REPORT_FIELDS_FORM}
+                    onSubmit={editValue}
+                    submitButtonText={translate('common.save')}
+                    validate={validate}
+                    style={[styles.mh5, styles.flex1]}
+                    enabledWhenOffline
+                    shouldHideFixErrorsAlert
+                    addBottomSafeAreaPadding
+                    isSubmitButtonVisible={canWriteReportFields}
+                >
+                    <InputWrapper
+                        InputComponent={TextInput}
+                        defaultValue={currentValueName}
+                        label={translate('common.value')}
+                        accessibilityLabel={translate('common.value')}
+                        inputID={INPUT_IDS.NEW_VALUE_NAME}
+                        role={CONST.ROLE.PRESENTATION}
+                        ref={inputCallbackRef}
+                        disabled={!canWriteReportFields}
+                    />
+                </FormProvider>
+            </ScreenWrapper>
+        </AccessOrNotFoundWrapper>
     );
 }
 
diff --git a/src/pages/workspace/reports/ReportFieldsInitialValuePage.tsx b/src/pages/workspace/reports/ReportFieldsInitialValuePage.tsx
index 68fbc55020bf..00e5f16fc426 100644
--- a/src/pages/workspace/reports/ReportFieldsInitialValuePage.tsx
+++ b/src/pages/workspace/reports/ReportFieldsInitialValuePage.tsx
@@ -1,29 +1,166 @@
-import React from 'react';
+import React, {useCallback, useState} from 'react';
+import {View} from 'react-native';
+import FormProvider from '@components/Form/FormProvider';
+import InputWrapper from '@components/Form/InputWrapper';
+import type {FormInputErrors, FormOnyxValues} from '@components/Form/types';
+import HeaderWithBackButton from '@components/HeaderWithBackButton';
+import ScreenWrapper from '@components/ScreenWrapper';
+import Text from '@components/Text';
+import TextInput from '@components/TextInput';
+import useAutoFocusInput from '@hooks/useAutoFocusInput';
+import useLocalize from '@hooks/useLocalize';
+import useThemeStyles from '@hooks/useThemeStyles';
+import {hasCircularReferences} from '@libs/Formula';
+import Navigation from '@libs/Navigation/Navigation';
 import type {PlatformStackScreenProps} from '@libs/Navigation/PlatformStackNavigation/types';
-import type {SettingsNavigatorParamList} from '@navigation/types';
-import FieldsInitialValuePage from '@pages/workspace/fields/FieldsInitialValuePage';
+import type {SettingsNavigatorParamList} from '@libs/Navigation/types';
+import {getReportFieldKey} from '@libs/ReportUtils';
+import {isRequiredFulfilled} from '@libs/ValidationUtils';
+import {getReportFieldInitialValue, getUnsupportedReportFieldFormulaParts} from '@libs/WorkspaceReportFieldUtils';
+import NotFoundPage from '@pages/ErrorPage/NotFoundPage';
+import AccessOrNotFoundWrapper from '@pages/workspace/AccessOrNotFoundWrapper';
 import type {WithPolicyAndFullscreenLoadingProps} from '@pages/workspace/withPolicyAndFullscreenLoading';
 import withPolicyAndFullscreenLoading from '@pages/workspace/withPolicyAndFullscreenLoading';
+import {updateReportFieldInitialValue} from '@userActions/Policy/ReportField';
 import CONST from '@src/CONST';
+import ONYXKEYS from '@src/ONYXKEYS';
 import type SCREENS from '@src/SCREENS';
+import INPUT_IDS from '@src/types/form/WorkspaceReportFieldForm';
+import ReportFieldsInitialListValuePicker from './InitialListValueSelector/ReportFieldsInitialListValuePicker';
 
 type ReportFieldsInitialValuePageProps = WithPolicyAndFullscreenLoadingProps &
     PlatformStackScreenProps<SettingsNavigatorParamList, typeof SCREENS.WORKSPACE.REPORT_FIELDS_EDIT_INITIAL_VALUE>;
-
 function ReportFieldsInitialValuePage({
     policy,
     route: {
         params: {policyID, reportFieldID},
     },
 }: ReportFieldsInitialValuePageProps) {
+    const styles = useThemeStyles();
+    const {translate} = useLocalize();
+    const {inputCallbackRef} = useAutoFocusInput();
+
+    const reportField = policy?.fieldList?.[getReportFieldKey(reportFieldID)] ?? null;
+    const availableListValuesLength = (reportField?.disabledOptions ?? []).filter((disabledListValue) => !disabledListValue).length;
+    const currentInitialValue = getReportFieldInitialValue(reportField, translate);
+    const [initialValue, setInitialValue] = useState(currentInitialValue);
+
+    const submitForm = useCallback(
+        (values: FormOnyxValues<typeof ONYXKEYS.FORMS.WORKSPACE_REPORT_FIELDS_FORM>) => {
+            if (currentInitialValue !== values.initialValue) {
+                updateReportFieldInitialValue({policy, reportFieldID, newInitialValue: values.initialValue});
+            }
+            Navigation.goBack();
+        },
+        [currentInitialValue, policy, reportFieldID],
+    );
+
+    const submitListValueUpdate = (value: string) => {
+        updateReportFieldInitialValue({policy, reportFieldID, newInitialValue: currentInitialValue === value ? '' : value});
+        Navigation.goBack();
+    };
+
+    const validateForm = useCallback(
+        (values: FormOnyxValues<typeof ONYXKEYS.FORMS.WORKSPACE_REPORT_FIELDS_FORM>): FormInputErrors<typeof ONYXKEYS.FORMS.WORKSPACE_REPORT_FIELDS_FORM> => {
+            const {initialValue: formInitialValue} = values;
+            const errors: FormInputErrors<typeof ONYXKEYS.FORMS.WORKSPACE_REPORT_FIELDS_FORM> = {};
+
+            if (formInitialValue.length > CONST.WORKSPACE_REPORT_FIELD_POLICY_MAX_LENGTH) {
+                errors[INPUT_IDS.INITIAL_VALUE] = translate('common.error.characterLimitExceedCounter', formInitialValue.length, CONST.WORKSPACE_REPORT_FIELD_POLICY_MAX_LENGTH);
+            }
+
+            if (
+                (reportField?.type === CONST.REPORT_FIELD_TYPES.TEXT || reportField?.type === CONST.REPORT_FIELD_TYPES.FORMULA) &&
+                hasCircularReferences(formInitialValue, reportField?.name, policy?.fieldList)
+            ) {
+                errors[INPUT_IDS.INITIAL_VALUE] = translate('workspace.reportFields.circularReferenceError');
+            }
+
+            if ((reportField?.type === CONST.REPORT_FIELD_TYPES.TEXT || reportField?.type === CONST.REPORT_FIELD_TYPES.FORMULA) && !!formInitialValue && !errors[INPUT_IDS.INITIAL_VALUE]) {
+                const unsupportedFormulaParts = getUnsupportedReportFieldFormulaParts(formInitialValue);
+                if (unsupportedFormulaParts.length > 0) {
+                    errors[INPUT_IDS.INITIAL_VALUE] = translate('workspace.reportFields.unsupportedFormulaValueError', {
+                        value: unsupportedFormulaParts.join(', '),
+                    });
+                }
+            }
+
+            if (reportField?.type === CONST.REPORT_FIELD_TYPES.LIST && availableListValuesLength > 0 && !isRequiredFulfilled(formInitialValue)) {
+                errors[INPUT_IDS.INITIAL_VALUE] = translate('workspace.reportFields.reportFieldInitialValueRequiredError');
+            }
+
+            return errors;
+        },
+        [availableListValuesLength, reportField?.name, reportField?.type, policy?.fieldList, translate],
+    );
+
+    if (!reportField) {
+        return <NotFoundPage />;
+    }
+
+    const isTextFieldType = reportField.type === CONST.REPORT_FIELD_TYPES.TEXT;
+    const isFormulaFieldType = reportField.type === CONST.REPORT_FIELD_TYPES.FORMULA;
+    const isListFieldType = reportField.type === CONST.REPORT_FIELD_TYPES.LIST;
+
     return (
-        <FieldsInitialValuePage
-            policy={policy}
+        <AccessOrNotFoundWrapper
+            accessVariants={[CONST.POLICY.ACCESS_VARIANTS.ADMIN, CONST.POLICY.ACCESS_VARIANTS.PAID]}
             policyID={policyID}
-            reportFieldID={reportFieldID}
             featureName={CONST.POLICY.MORE_FEATURES.ARE_REPORT_FIELDS_ENABLED}
-            testID="ReportFieldsInitialValuePage"
-        />
+        >
+            <ScreenWrapper
+                enableEdgeToEdgeBottomSafeAreaPadding
+                style={styles.defaultModalContainer}
+                testID="ReportFieldsInitialValuePage"
+                shouldEnableMaxHeight
+            >
+                <HeaderWithBackButton
+                    title={translate('common.initialValue')}
+                    onBackButtonPress={Navigation.goBack}
+                />
+                {isListFieldType && (
+                    <View style={[styles.ph5, styles.pb4]}>
+                        <Text style={[styles.sidebarLinkText, styles.optionAlternateText]}>{translate('workspace.reportFields.listValuesInputSubtitle')}</Text>
+                    </View>
+                )}
+
+                {(isTextFieldType || isFormulaFieldType) && (
+                    <FormProvider
+                        addBottomSafeAreaPadding
+                        formID={ONYXKEYS.FORMS.WORKSPACE_REPORT_FIELDS_FORM}
+                        onSubmit={submitForm}
+                        submitButtonText={translate('common.save')}
+                        validate={validateForm}
+                        style={styles.flex1}
+                        enabledWhenOffline
+                        isSubmitButtonVisible
+                        submitButtonStyles={styles.mh5}
+                        shouldHideFixErrorsAlert
+                    >
+                        <InputWrapper
+                            containerStyles={styles.mh5}
+                            InputComponent={TextInput}
+                            inputID={INPUT_IDS.INITIAL_VALUE}
+                            label={translate('common.initialValue')}
+                            accessibilityLabel={translate('workspace.editor.initialValueInputLabel')}
+                            multiline={false}
+                            value={initialValue}
+                            role={CONST.ROLE.PRESENTATION}
+                            ref={inputCallbackRef}
+                            onChangeText={setInitialValue}
+                        />
+                    </FormProvider>
+                )}
+                {isListFieldType && (
+                    <ReportFieldsInitialListValuePicker
+                        listValues={reportField.values}
+                        disabledOptions={reportField.disabledOptions}
+                        value={initialValue}
+                        onValueChange={submitListValueUpdate}
+                    />
+                )}
+            </ScreenWrapper>
+        </AccessOrNotFoundWrapper>
     );
 }
 
diff --git a/src/pages/workspace/reports/ReportFieldsListValuesPage.tsx b/src/pages/workspace/reports/ReportFieldsListValuesPage.tsx
index 4d422631c213..ddb277d4f350 100644
--- a/src/pages/workspace/reports/ReportFieldsListValuesPage.tsx
+++ b/src/pages/workspace/reports/ReportFieldsListValuesPage.tsx
@@ -1,12 +1,64 @@
-import React from 'react';
+import React, {useCallback, useMemo, useState} from 'react';
+import {View} from 'react-native';
+import Button from '@components/Button';
+import ButtonWithDropdownMenu from '@components/ButtonWithDropdownMenu';
+import type {DropdownOption} from '@components/ButtonWithDropdownMenu/types';
+import EmptyStateComponent from '@components/EmptyStateComponent';
+import HeaderWithBackButton from '@components/HeaderWithBackButton';
+import {ModalActions} from '@components/Modal/Global/ModalContext';
+import ScreenWrapper from '@components/ScreenWrapper';
+import ScrollView from '@components/ScrollView';
+import SearchBar from '@components/SearchBar';
+import TableListItem from '@components/SelectionList/ListItem/TableListItem';
+import type {ListItem} from '@components/SelectionList/types';
+import SelectionListWithModal from '@components/SelectionListWithModal';
+import CustomListHeader from '@components/SelectionListWithModal/CustomListHeader';
+import Switch from '@components/Switch';
+import Text from '@components/Text';
+import useConfirmModal from '@hooks/useConfirmModal';
+import {useMemoizedLazyExpensifyIcons, useMemoizedLazyIllustrations} from '@hooks/useLazyAsset';
+import useLocalize from '@hooks/useLocalize';
+import useMobileSelectionMode from '@hooks/useMobileSelectionMode';
+import useOnyx from '@hooks/useOnyx';
+import usePolicyFeatureWriteAccess from '@hooks/usePolicyFeatureWriteAccess';
+import useResponsiveLayout from '@hooks/useResponsiveLayout';
+import useSearchBackPress from '@hooks/useSearchBackPress';
+import useSearchResults from '@hooks/useSearchResults';
+import useShouldDisplayButtonsInSeparateLine from '@hooks/useShouldDisplayButtonsInSeparateLine';
+import useThemeStyles from '@hooks/useThemeStyles';
+import {turnOffMobileSelectionMode} from '@libs/actions/MobileSelectionMode';
+import {
+    deleteReportFieldsListValue,
+    removeReportFieldListValue,
+    setReportFieldsListValueEnabled,
+    updateReportFieldListValueEnabled as updateReportFieldListValueEnabledReportField,
+} from '@libs/actions/Policy/ReportField';
+import {canUseTouchScreen} from '@libs/DeviceCapabilities';
+import Navigation from '@libs/Navigation/Navigation';
 import type {PlatformStackScreenProps} from '@libs/Navigation/PlatformStackNavigation/types';
+import {hasAccountingConnections as hasAccountingConnectionsPolicyUtils} from '@libs/PolicyUtils';
+import {getReportFieldKey} from '@libs/ReportUtils';
+import StringUtils from '@libs/StringUtils';
 import type {SettingsNavigatorParamList} from '@navigation/types';
-import FieldsListValuesPage from '@pages/workspace/fields/FieldsListValuesPage';
+import AccessOrNotFoundWrapper from '@pages/workspace/AccessOrNotFoundWrapper';
 import type {WithPolicyAndFullscreenLoadingProps} from '@pages/workspace/withPolicyAndFullscreenLoading';
 import withPolicyAndFullscreenLoading from '@pages/workspace/withPolicyAndFullscreenLoading';
 import CONST from '@src/CONST';
+import ONYXKEYS from '@src/ONYXKEYS';
 import ROUTES from '@src/ROUTES';
 import type SCREENS from '@src/SCREENS';
+import type DeepValueOf from '@src/types/utils/DeepValueOf';
+
+type ValueListItem = ListItem & {
+    /** The value */
+    value: string;
+
+    /** Whether the value is enabled */
+    enabled: boolean;
+
+    /** The value order weight in the list */
+    orderWeight?: number;
+};
 
 type ReportFieldsListValuesPageProps = WithPolicyAndFullscreenLoadingProps & PlatformStackScreenProps<SettingsNavigatorParamList, typeof SCREENS.WORKSPACE.REPORT_FIELDS_LIST_VALUES>;
 
@@ -16,24 +68,363 @@ function ReportFieldsListValuesPage({
         params: {policyID, reportFieldID},
     },
 }: ReportFieldsListValuesPageProps) {
+    const styles = useThemeStyles();
+    const {translate, localeCompare} = useLocalize();
+    // We need to use isSmallScreenWidth instead of shouldUseNarrowLayout here to use the mobile selection mode on small screens only
+    // See https://github.com/Expensify/App/issues/48724 for more details
+    // eslint-disable-next-line rulesdir/prefer-shouldUseNarrowLayout-instead-of-isSmallScreenWidth
+    const {isSmallScreenWidth} = useResponsiveLayout();
+    const [formDraft] = useOnyx(ONYXKEYS.FORMS.WORKSPACE_REPORT_FIELDS_FORM_DRAFT);
+    const isMobileSelectionModeEnabled = useMobileSelectionMode();
+    const illustrations = useMemoizedLazyIllustrations(['FolderWithPapers']);
+    const {showConfirmModal} = useConfirmModal();
+    const {canWrite: canWriteReportFields, withReadOnlyFallback} = usePolicyFeatureWriteAccess(policy, CONST.POLICY.POLICY_FEATURE.REPORT_FIELDS);
+
+    const [selectedValues, setSelectedValues] = useState<Record<string, boolean>>({});
+    const hasAccountingConnections = hasAccountingConnectionsPolicyUtils(policy);
+
+    const canSelectMultiple = canWriteReportFields && (isSmallScreenWidth ? isMobileSelectionModeEnabled : true);
+
+    const [listValues, disabledListValues] = useMemo(() => {
+        let reportFieldValues: string[];
+        let reportFieldDisabledValues: boolean[];
+
+        if (reportFieldID) {
+            const reportFieldKey = getReportFieldKey(reportFieldID);
+
+            reportFieldValues = Object.values(policy?.fieldList?.[reportFieldKey]?.values ?? {});
+            reportFieldDisabledValues = Object.values(policy?.fieldList?.[reportFieldKey]?.disabledOptions ?? {});
+        } else {
+            reportFieldValues = formDraft?.listValues ?? [];
+            reportFieldDisabledValues = formDraft?.disabledListValues ?? [];
+        }
+
+        return [reportFieldValues, reportFieldDisabledValues];
+    }, [formDraft?.disabledListValues, formDraft?.listValues, policy?.fieldList, reportFieldID]);
+
+    const updateReportFieldListValueEnabled = useCallback(
+        (value: boolean, valueIndex: number) => {
+            if (reportFieldID) {
+                updateReportFieldListValueEnabledReportField({policy, reportFieldID, valueIndexes: [Number(valueIndex)], enabled: value});
+                return;
+            }
+
+            setReportFieldsListValueEnabled({
+                valueIndexes: [valueIndex],
+                enabled: value,
+                disabledListValues,
+            });
+        },
+        [disabledListValues, policy, reportFieldID],
+    );
+
+    useSearchBackPress({
+        onClearSelection: () => {
+            setSelectedValues({});
+        },
+        onNavigationCallBack: () => Navigation.goBack(),
+    });
+
+    const data = useMemo(
+        () =>
+            listValues.map<ValueListItem>((value, index) => ({
+                value,
+                index,
+                text: value,
+                keyForList: value,
+                isSelected: selectedValues[value] && canSelectMultiple,
+                enabled: !disabledListValues.at(index),
+                rightElement: (
+                    <Switch
+                        isOn={!disabledListValues.at(index)}
+                        accessibilityLabel={translate('workspace.distanceRates.trackTax')}
+                        onToggle={(newValue: boolean) => updateReportFieldListValueEnabled(newValue, index)}
+                        disabled={!canWriteReportFields}
+                        disabledAction={withReadOnlyFallback()}
+                        showLockIcon={!canWriteReportFields}
+                    />
+                ),
+            })),
+        [canSelectMultiple, canWriteReportFields, disabledListValues, withReadOnlyFallback, listValues, selectedValues, translate, updateReportFieldListValueEnabled],
+    );
+
+    const filterListValue = useCallback((item: ValueListItem, searchInput: string) => {
+        const itemText = StringUtils.normalize(item.text?.toLowerCase() ?? '');
+        const normalizedSearchInput = StringUtils.normalize(searchInput.toLowerCase());
+        return itemText.includes(normalizedSearchInput);
+    }, []);
+    const sortListValues = useCallback((values: ValueListItem[]) => values.sort((a, b) => localeCompare(a.value, b.value)), [localeCompare]);
+    const [inputValue, setInputValue, filteredListValues] = useSearchResults(data, filterListValue, sortListValues);
+    const icons = useMemoizedLazyExpensifyIcons(['Checkmark', 'Close', 'Plus', 'Trashcan']);
+
+    const filteredListValuesArray = filteredListValues.map((item) => item.value);
+
+    const shouldShowEmptyState = Object.values(listValues ?? {}).length <= 0;
+    const selectedValuesArray = Object.keys(selectedValues).filter((key) => selectedValues[key] && listValues.includes(key));
+
+    const toggleValue = (valueItem: ValueListItem) => {
+        setSelectedValues((prev) => ({
+            ...prev,
+            [valueItem.value]: !prev[valueItem.value],
+        }));
+    };
+
+    const toggleAllValues = () => {
+        setSelectedValues(selectedValuesArray.length > 0 ? {} : Object.fromEntries(filteredListValuesArray.map((value) => [value, true])));
+    };
+
+    const handleDeleteValues = () => {
+        const valuesToDelete = selectedValuesArray.reduce<number[]>((acc, valueName) => {
+            const index = listValues?.indexOf(valueName) ?? -1;
+
+            if (index !== -1) {
+                acc.push(index);
+            }
+
+            return acc;
+        }, []);
+
+        if (reportFieldID) {
+            removeReportFieldListValue({policy, reportFieldID, valueIndexes: valuesToDelete});
+        } else {
+            deleteReportFieldsListValue({
+                valueIndexes: valuesToDelete,
+                listValues,
+                disabledListValues,
+            });
+        }
+
+        setSelectedValues({});
+    };
+
+    const openListValuePage = (valueItem: ValueListItem) => {
+        if (valueItem.index === undefined) {
+            return;
+        }
+
+        Navigation.navigate(ROUTES.WORKSPACE_REPORT_FIELDS_VALUE_SETTINGS.getRoute(policyID, valueItem.index, reportFieldID));
+    };
+
+    const getCustomListHeader = () => {
+        if (filteredListValues.length === 0) {
+            return null;
+        }
+        return (
+            <CustomListHeader
+                canSelectMultiple={canSelectMultiple}
+                leftHeaderText={translate('common.name')}
+                rightHeaderText={translate('common.enabled')}
+                shouldShowRightCaret
+            />
+        );
+    };
+
+    const shouldDisplayButtonsInSeparateLine = useShouldDisplayButtonsInSeparateLine();
+
+    const getHeaderButtons = () => {
+        const options: Array<DropdownOption<DeepValueOf<typeof CONST.POLICY.BULK_ACTION_TYPES>>> = [];
+        if (canWriteReportFields && (isSmallScreenWidth ? isMobileSelectionModeEnabled : selectedValuesArray.length > 0)) {
+            if (selectedValuesArray.length > 0 && !hasAccountingConnections) {
+                options.push({
+                    icon: icons.Trashcan,
+                    text: translate(selectedValuesArray.length === 1 ? 'workspace.reportFields.deleteValue' : 'workspace.reportFields.deleteValues'),
+                    value: CONST.POLICY.BULK_ACTION_TYPES.DELETE,
+                    onSelected: () => {
+                        showConfirmModal({
+                            danger: true,
+                            title: translate(selectedValuesArray.length === 1 ? 'workspace.reportFields.deleteValue' : 'workspace.reportFields.deleteValues'),
+                            prompt: translate(selectedValuesArray.length === 1 ? 'workspace.reportFields.deleteValuePrompt' : 'workspace.reportFields.deleteValuesPrompt'),
+                            confirmText: translate('common.delete'),
+                            cancelText: translate('common.cancel'),
+                        }).then((result) => {
+                            if (result.action !== ModalActions.CONFIRM) {
+                                return;
+                            }
+
+                            handleDeleteValues();
+                        });
+                    },
+                });
+            }
+            const enabledValues = selectedValuesArray.filter((valueName) => {
+                const index = listValues?.indexOf(valueName) ?? -1;
+                return !disabledListValues?.at(index);
+            });
+
+            if (enabledValues.length > 0) {
+                const valuesToDisable = selectedValuesArray.reduce<number[]>((acc, valueName) => {
+                    const index = listValues?.indexOf(valueName) ?? -1;
+                    if (!disabledListValues?.at(index) && index !== -1) {
+                        acc.push(index);
+                    }
+
+                    return acc;
+                }, []);
+
+                options.push({
+                    icon: icons.Close,
+                    text: translate(enabledValues.length === 1 ? 'workspace.reportFields.disableValue' : 'workspace.reportFields.disableValues'),
+                    value: CONST.POLICY.BULK_ACTION_TYPES.DISABLE,
+                    onSelected: () => {
+                        setSelectedValues({});
+
+                        if (reportFieldID) {
+                            updateReportFieldListValueEnabledReportField({policy, reportFieldID, valueIndexes: valuesToDisable, enabled: false});
+                            return;
+                        }
+
+                        setReportFieldsListValueEnabled({
+                            valueIndexes: valuesToDisable,
+                            enabled: false,
+                            disabledListValues,
+                        });
+                    },
+                });
+            }
+
+            const disabledValues = selectedValuesArray.filter((valueName) => {
+                const index = listValues?.indexOf(valueName) ?? -1;
+                return disabledListValues?.at(index);
+            });
+
+            if (disabledValues.length > 0) {
+                const valuesToEnable = selectedValuesArray.reduce<number[]>((acc, valueName) => {
+                    const index = listValues?.indexOf(valueName) ?? -1;
+                    if (disabledListValues?.at(index) && index !== -1) {
+                        acc.push(index);
+                    }
+
+                    return acc;
+                }, []);
+
+                options.push({
+                    icon: icons.Checkmark,
+                    text: translate(disabledValues.length === 1 ? 'workspace.reportFields.enableValue' : 'workspace.reportFields.enableValues'),
+                    value: CONST.POLICY.BULK_ACTION_TYPES.ENABLE,
+                    onSelected: () => {
+                        setSelectedValues({});
+
+                        if (reportFieldID) {
+                            updateReportFieldListValueEnabledReportField({policy, reportFieldID, valueIndexes: valuesToEnable, enabled: true});
+                            return;
+                        }
+
+                        setReportFieldsListValueEnabled({
+                            valueIndexes: valuesToEnable,
+                            enabled: true,
+                            disabledListValues,
+                        });
+                    },
+                });
+            }
+
+            return (
+                <ButtonWithDropdownMenu
+                    onPress={() => null}
+                    shouldAlwaysShowDropdownMenu
+                    buttonSize={CONST.DROPDOWN_BUTTON_SIZE.MEDIUM}
+                    customText={translate('workspace.common.selected', {count: selectedValuesArray.length})}
+                    options={options}
+                    isSplitButton={false}
+                    style={[shouldDisplayButtonsInSeparateLine && styles.flexGrow1, shouldDisplayButtonsInSeparateLine && styles.mb3]}
+                    isDisabled={!selectedValuesArray.length}
+                />
+            );
+        }
+
+        if (canWriteReportFields && !hasAccountingConnections) {
+            return (
+                <Button
+                    style={[shouldDisplayButtonsInSeparateLine && styles.flexGrow1, shouldDisplayButtonsInSeparateLine && styles.mb3]}
+                    success
+                    icon={icons.Plus}
+                    text={translate('workspace.reportFields.addValue')}
+                    onPress={() => Navigation.navigate(ROUTES.WORKSPACE_REPORT_FIELDS_ADD_VALUE.getRoute(policyID, reportFieldID))}
+                />
+            );
+        }
+    };
+
+    const selectionModeHeader = isMobileSelectionModeEnabled && isSmallScreenWidth;
+
+    const headerContent = (
+        <>
+            <View style={[styles.ph5, styles.pv4]}>
+                <Text style={[styles.sidebarLinkText, styles.optionAlternateText]}>{translate('workspace.reportFields.listInputSubtitle')}</Text>
+            </View>
+            {data.length >= CONST.STANDARD_LIST_ITEM_LIMIT && (
+                <SearchBar
+                    label={translate('workspace.reportFields.findReportField')}
+                    inputValue={inputValue}
+                    onChangeText={setInputValue}
+                    shouldShowEmptyState={!shouldShowEmptyState && filteredListValues.length === 0}
+                />
+            )}
+        </>
+    );
+
     return (
-        <FieldsListValuesPage
-            policy={policy}
+        <AccessOrNotFoundWrapper
+            accessVariants={[CONST.POLICY.ACCESS_VARIANTS.ADMIN, CONST.POLICY.ACCESS_VARIANTS.PAID]}
             policyID={policyID}
-            reportFieldID={reportFieldID}
-            isInvoicePage={false}
             featureName={CONST.POLICY.MORE_FEATURES.ARE_REPORT_FIELDS_ENABLED}
             policyFeature={CONST.POLICY.POLICY_FEATURE.REPORT_FIELDS}
-            getValueSettingsRoute={(isInvoiceRoute, id, valueIndex, fieldID) =>
-                isInvoiceRoute
-                    ? ROUTES.WORKSPACE_INVOICE_FIELDS_VALUE_SETTINGS.getRoute(id, valueIndex, fieldID)
-                    : ROUTES.WORKSPACE_REPORT_FIELDS_VALUE_SETTINGS.getRoute(id, valueIndex, fieldID)
-            }
-            getAddValueRoute={(isInvoiceRoute, id, fieldID) =>
-                isInvoiceRoute ? ROUTES.WORKSPACE_INVOICE_FIELDS_ADD_VALUE.getRoute(id, fieldID) : ROUTES.WORKSPACE_REPORT_FIELDS_ADD_VALUE.getRoute(id, fieldID)
-            }
-            testID="ReportFieldsListValuesPage"
-        />
+        >
+            <ScreenWrapper
+                enableEdgeToEdgeBottomSafeAreaPadding
+                style={styles.defaultModalContainer}
+                testID="ReportFieldsListValuesPage"
+                shouldEnableMaxHeight
+            >
+                <HeaderWithBackButton
+                    title={translate(selectionModeHeader ? 'common.selectMultiple' : 'workspace.reportFields.listValues')}
+                    onBackButtonPress={() => {
+                        if (isMobileSelectionModeEnabled) {
+                            setSelectedValues({});
+                            turnOffMobileSelectionMode();
+                            return;
+                        }
+                        Navigation.goBack();
+                    }}
+                >
+                    {!shouldDisplayButtonsInSeparateLine && getHeaderButtons()}
+                </HeaderWithBackButton>
+                {shouldDisplayButtonsInSeparateLine && <View style={[styles.pl5, styles.pr5]}>{getHeaderButtons()}</View>}
+                {shouldShowEmptyState && (
+                    <ScrollView contentContainerStyle={[styles.flexGrow1, styles.flexShrink0]}>
+                        {headerContent}
+                        <EmptyStateComponent
+                            title={translate('workspace.reportFields.emptyReportFieldsValues.title')}
+                            subtitle={translate('workspace.reportFields.emptyReportFieldsValues.subtitle')}
+                            headerMedia={illustrations.FolderWithPapers}
+                            headerStyles={styles.emptyStateCardIllustrationContainer}
+                            headerContentStyles={styles.emptyStateFolderWithPaperIconSize}
+                        />
+                    </ScrollView>
+                )}
+                {!shouldShowEmptyState && (
+                    <SelectionListWithModal
+                        data={filteredListValues}
+                        ListItem={TableListItem}
+                        onSelectRow={openListValuePage}
+                        selectedItems={selectedValuesArray}
+                        onSelectAll={canWriteReportFields && filteredListValues.length > 0 ? toggleAllValues : undefined}
+                        onTurnOnSelectionMode={(item) => item && canWriteReportFields && toggleValue(item)}
+                        shouldPreventDefaultFocusOnSelectRow={!canUseTouchScreen()}
+                        customListHeader={getCustomListHeader()}
+                        customListHeaderContent={headerContent}
+                        canSelectMultiple={canSelectMultiple}
+                        selectAllAccessibilityLabel={translate('accessibilityHints.selectAllValues')}
+                        onSelectionButtonPress={toggleValue}
+                        shouldShowListEmptyContent={false}
+                        showScrollIndicator={false}
+                        turnOnSelectionModeOnLongPress={canWriteReportFields}
+                        shouldHeaderBeInsideList
+                        shouldShowRightCaret
+                    />
+                )}
+            </ScreenWrapper>
+        </AccessOrNotFoundWrapper>
     );
 }
 
diff --git a/src/pages/workspace/reports/ReportFieldsSettingsPage.tsx b/src/pages/workspace/reports/ReportFieldsSettingsPage.tsx
index b68eeda0dd55..443c46529177 100644
--- a/src/pages/workspace/reports/ReportFieldsSettingsPage.tsx
+++ b/src/pages/workspace/reports/ReportFieldsSettingsPage.tsx
@@ -1,9 +1,27 @@
+import {Str} from 'expensify-common';
 import React from 'react';
+import {View} from 'react-native';
+import HeaderWithBackButton from '@components/HeaderWithBackButton';
+import MenuItem from '@components/MenuItem';
+import MenuItemWithTopDescription from '@components/MenuItemWithTopDescription';
+import {ModalActions} from '@components/Modal/Global/ModalContext';
+import ScreenWrapper from '@components/ScreenWrapper';
+import useConfirmModal from '@hooks/useConfirmModal';
+import {useMemoizedLazyExpensifyIcons} from '@hooks/useLazyAsset';
+import useLocalize from '@hooks/useLocalize';
+import usePolicyFeatureWriteAccess from '@hooks/usePolicyFeatureWriteAccess';
+import useThemeStyles from '@hooks/useThemeStyles';
+import Navigation from '@libs/Navigation/Navigation';
 import type {PlatformStackScreenProps} from '@libs/Navigation/PlatformStackNavigation/types';
+import {hasAccountingConnections as hasAccountingConnectionsPolicyUtils} from '@libs/PolicyUtils';
+import {getReportFieldKey} from '@libs/ReportUtils';
+import {getReportFieldInitialValue, getReportFieldTypeTranslationKey} from '@libs/WorkspaceReportFieldUtils';
 import type {SettingsNavigatorParamList} from '@navigation/types';
-import FieldsSettingsPage from '@pages/workspace/fields/FieldsSettingsPage';
+import NotFoundPage from '@pages/ErrorPage/NotFoundPage';
+import AccessOrNotFoundWrapper from '@pages/workspace/AccessOrNotFoundWrapper';
 import type {WithPolicyAndFullscreenLoadingProps} from '@pages/workspace/withPolicyAndFullscreenLoading';
 import withPolicyAndFullscreenLoading from '@pages/workspace/withPolicyAndFullscreenLoading';
+import {deleteReportFields} from '@userActions/Policy/ReportField';
 import CONST from '@src/CONST';
 import ROUTES from '@src/ROUTES';
 import type SCREENS from '@src/SCREENS';
@@ -16,18 +34,108 @@ function ReportFieldsSettingsPage({
         params: {policyID, reportFieldID},
     },
 }: ReportFieldsSettingsPageProps) {
+    const styles = useThemeStyles();
+    const {translate, localeCompare} = useLocalize();
+    const {showConfirmModal} = useConfirmModal();
+    const icons = useMemoizedLazyExpensifyIcons(['Trashcan']);
+    const {canWrite: canWriteReportFields} = usePolicyFeatureWriteAccess(policy, CONST.POLICY.POLICY_FEATURE.REPORT_FIELDS);
+
+    const hasAccountingConnections = hasAccountingConnectionsPolicyUtils(policy);
+    const reportFieldKey = getReportFieldKey(reportFieldID);
+    const reportField = policy?.fieldList?.[reportFieldKey] ?? null;
+
+    if (!reportField) {
+        return <NotFoundPage />;
+    }
+
+    const isDateFieldType = reportField.type === CONST.REPORT_FIELD_TYPES.DATE;
+    const isListFieldType = reportField.type === CONST.REPORT_FIELD_TYPES.LIST;
+    const isListFieldEmpty = isListFieldType && reportField.disabledOptions.filter((disabledListValue) => !disabledListValue).length <= 0;
+    const listValues = Object.values(policy?.fieldList?.[reportFieldKey]?.values ?? {})?.sort(localeCompare);
+
+    const confirmAndDeleteReportField = async () => {
+        const result = await showConfirmModal({
+            danger: true,
+            title: translate('workspace.reportFields.delete'),
+            prompt: translate('workspace.reportFields.deleteConfirmation'),
+            confirmText: translate('common.delete'),
+            cancelText: translate('common.cancel'),
+            shouldSetModalVisibility: false,
+        });
+
+        if (result.action !== ModalActions.CONFIRM) {
+            return;
+        }
+
+        deleteReportFields({policy, reportFieldsToUpdate: [reportFieldKey]});
+        Navigation.goBack();
+    };
+
     return (
-        <FieldsSettingsPage
-            policy={policy}
+        <AccessOrNotFoundWrapper
+            accessVariants={[CONST.POLICY.ACCESS_VARIANTS.ADMIN, CONST.POLICY.ACCESS_VARIANTS.PAID]}
             policyID={policyID}
-            reportFieldID={reportFieldID}
             featureName={CONST.POLICY.MORE_FEATURES.ARE_REPORT_FIELDS_ENABLED}
             policyFeature={CONST.POLICY.POLICY_FEATURE.REPORT_FIELDS}
-            expectedTarget={CONST.REPORT_FIELD_TARGETS.EXPENSE}
-            getListValuesRoute={(id, fieldID) => ROUTES.WORKSPACE_REPORT_FIELDS_LIST_VALUES.getRoute(id, fieldID)}
-            getInitialValueRoute={(id, fieldID) => ROUTES.WORKSPACE_EDIT_REPORT_FIELDS_INITIAL_VALUE.getRoute(id, fieldID)}
-            testID="ReportFieldsSettingsPage"
-        />
+        >
+            <ScreenWrapper
+                enableEdgeToEdgeBottomSafeAreaPadding
+                style={[styles.defaultModalContainer]}
+                testID="ReportFieldsSettingsPage"
+            >
+                <HeaderWithBackButton
+                    title={reportField.name}
+                    shouldSetModalVisibility={false}
+                />
+                <View style={styles.flexGrow1}>
+                    <MenuItemWithTopDescription
+                        style={[styles.moneyRequestMenuItem]}
+                        titleStyle={styles.flex1}
+                        title={reportField.name}
+                        description={translate('common.name')}
+                        interactive={false}
+                    />
+                    <MenuItemWithTopDescription
+                        style={[styles.moneyRequestMenuItem]}
+                        titleStyle={styles.flex1}
+                        title={Str.recapitalize(translate(getReportFieldTypeTranslationKey(reportField.type)))}
+                        description={translate('common.type')}
+                        interactive={false}
+                    />
+                    {isListFieldType && (
+                        <MenuItemWithTopDescription
+                            style={[styles.moneyRequestMenuItem]}
+                            titleStyle={styles.flex1}
+                            description={translate('workspace.reportFields.listValues')}
+                            shouldShowRightIcon
+                            onPress={() => Navigation.navigate(ROUTES.WORKSPACE_REPORT_FIELDS_LIST_VALUES.getRoute(policyID, reportFieldID))}
+                            title={listValues.join(', ')}
+                            numberOfLinesTitle={5}
+                        />
+                    )}
+                    {!isListFieldEmpty && (
+                        <MenuItemWithTopDescription
+                            style={[styles.moneyRequestMenuItem]}
+                            titleStyle={styles.flex1}
+                            title={getReportFieldInitialValue(reportField, translate)}
+                            description={translate('common.initialValue')}
+                            shouldShowRightIcon={canWriteReportFields && !isDateFieldType}
+                            interactive={canWriteReportFields && !isDateFieldType}
+                            onPress={() => Navigation.navigate(ROUTES.WORKSPACE_EDIT_REPORT_FIELDS_INITIAL_VALUE.getRoute(policyID, reportFieldID))}
+                        />
+                    )}
+                    {canWriteReportFields && !hasAccountingConnections && (
+                        <View style={styles.flexGrow1}>
+                            <MenuItem
+                                icon={icons.Trashcan}
+                                title={translate('common.delete')}
+                                onPress={confirmAndDeleteReportField}
+                            />
+                        </View>
+                    )}
+                </View>
+            </ScreenWrapper>
+        </AccessOrNotFoundWrapper>
     );
 }
 
diff --git a/src/pages/workspace/reports/ReportFieldsValueSettingsPage.tsx b/src/pages/workspace/reports/ReportFieldsValueSettingsPage.tsx
index aca3618eeab0..e3b4f33f358f 100644
--- a/src/pages/workspace/reports/ReportFieldsValueSettingsPage.tsx
+++ b/src/pages/workspace/reports/ReportFieldsValueSettingsPage.tsx
@@ -1,10 +1,31 @@
-import React from 'react';
+import React, {useMemo} from 'react';
+import {View} from 'react-native';
+import HeaderWithBackButton from '@components/HeaderWithBackButton';
+import MenuItem from '@components/MenuItem';
+import MenuItemWithTopDescription from '@components/MenuItemWithTopDescription';
+import {ModalActions} from '@components/Modal/Global/ModalContext';
+import ScreenWrapper from '@components/ScreenWrapper';
+import Switch from '@components/Switch';
+import Text from '@components/Text';
+import useConfirmModal from '@hooks/useConfirmModal';
+import {useMemoizedLazyExpensifyIcons} from '@hooks/useLazyAsset';
+import useLocalize from '@hooks/useLocalize';
+import useOnyx from '@hooks/useOnyx';
+import usePolicyFeatureWriteAccess from '@hooks/usePolicyFeatureWriteAccess';
+import usePrevious from '@hooks/usePrevious';
+import useThemeStyles from '@hooks/useThemeStyles';
+import {deleteReportFieldsListValue, removeReportFieldListValue, setReportFieldsListValueEnabled, updateReportFieldListValueEnabled} from '@libs/actions/Policy/ReportField';
+import Navigation from '@libs/Navigation/Navigation';
 import type {PlatformStackScreenProps} from '@libs/Navigation/PlatformStackNavigation/types';
+import {hasAccountingConnections as hasAccountingConnectionsUtil} from '@libs/PolicyUtils';
+import {getReportFieldKey} from '@libs/ReportUtils';
 import type {SettingsNavigatorParamList} from '@navigation/types';
-import FieldsValueSettingsPage from '@pages/workspace/fields/FieldsValueSettingsPage';
+import NotFoundPage from '@pages/ErrorPage/NotFoundPage';
+import AccessOrNotFoundWrapper from '@pages/workspace/AccessOrNotFoundWrapper';
 import type {WithPolicyAndFullscreenLoadingProps} from '@pages/workspace/withPolicyAndFullscreenLoading';
 import withPolicyAndFullscreenLoading from '@pages/workspace/withPolicyAndFullscreenLoading';
 import CONST from '@src/CONST';
+import ONYXKEYS from '@src/ONYXKEYS';
 import ROUTES from '@src/ROUTES';
 import type SCREENS from '@src/SCREENS';
 
@@ -16,20 +37,131 @@ function ReportFieldsValueSettingsPage({
         params: {policyID, valueIndex, reportFieldID},
     },
 }: ReportFieldsValueSettingsPageProps) {
+    const styles = useThemeStyles();
+    const {translate} = useLocalize();
+    const [formDraft] = useOnyx(ONYXKEYS.FORMS.WORKSPACE_REPORT_FIELDS_FORM_DRAFT);
+    const {showConfirmModal} = useConfirmModal();
+    const {canWrite: canWriteReportFields, withReadOnlyFallback} = usePolicyFeatureWriteAccess(policy, CONST.POLICY.POLICY_FEATURE.REPORT_FIELDS);
+
+    const [currentValueName, currentValueDisabled] = useMemo(() => {
+        let reportFieldValue: string;
+        let reportFieldDisabledValue: boolean;
+
+        if (reportFieldID) {
+            const reportFieldKey = getReportFieldKey(reportFieldID);
+
+            reportFieldValue = Object.values(policy?.fieldList?.[reportFieldKey]?.values ?? {})?.at(valueIndex) ?? '';
+            reportFieldDisabledValue = Object.values(policy?.fieldList?.[reportFieldKey]?.disabledOptions ?? {})?.at(valueIndex) ?? false;
+        } else {
+            reportFieldValue = formDraft?.listValues?.[valueIndex] ?? '';
+            reportFieldDisabledValue = formDraft?.disabledListValues?.[valueIndex] ?? false;
+        }
+
+        return [reportFieldValue, reportFieldDisabledValue];
+    }, [formDraft?.disabledListValues, formDraft?.listValues, policy?.fieldList, reportFieldID, valueIndex]);
+
+    const hasAccountingConnections = hasAccountingConnectionsUtil(policy);
+    const oldValueName = usePrevious(currentValueName);
+    const icons = useMemoizedLazyExpensifyIcons(['Trashcan']);
+
+    if (!currentValueName && !oldValueName) {
+        return <NotFoundPage />;
+    }
+    const confirmAndDeleteListValue = async () => {
+        const result = await showConfirmModal({
+            danger: true,
+            title: translate('workspace.reportFields.deleteValue'),
+            prompt: translate('workspace.reportFields.deleteValuePrompt'),
+            confirmText: translate('common.delete'),
+            cancelText: translate('common.cancel'),
+            shouldSetModalVisibility: false,
+        });
+
+        if (result.action !== ModalActions.CONFIRM) {
+            return;
+        }
+
+        if (reportFieldID) {
+            removeReportFieldListValue({policy, reportFieldID, valueIndexes: [valueIndex]});
+        } else {
+            deleteReportFieldsListValue({
+                valueIndexes: [valueIndex],
+                listValues: formDraft?.listValues ?? [],
+                disabledListValues: formDraft?.disabledListValues ?? [],
+            });
+        }
+        Navigation.goBack();
+    };
+
+    const updateListValueEnabled = (value: boolean) => {
+        if (reportFieldID) {
+            updateReportFieldListValueEnabled({policy, reportFieldID, valueIndexes: [Number(valueIndex)], enabled: value});
+            return;
+        }
+
+        setReportFieldsListValueEnabled({
+            valueIndexes: [valueIndex],
+            enabled: value,
+            disabledListValues: formDraft?.disabledListValues ?? [],
+        });
+    };
+
+    const navigateToEditValue = () => {
+        Navigation.navigate(ROUTES.WORKSPACE_REPORT_FIELDS_EDIT_VALUE.getRoute(policyID, valueIndex));
+    };
+
     return (
-        <FieldsValueSettingsPage
-            policy={policy}
+        <AccessOrNotFoundWrapper
+            accessVariants={[CONST.POLICY.ACCESS_VARIANTS.ADMIN, CONST.POLICY.ACCESS_VARIANTS.PAID]}
             policyID={policyID}
-            valueIndex={valueIndex}
-            reportFieldID={reportFieldID}
-            isInvoicePage={false}
             featureName={CONST.POLICY.MORE_FEATURES.ARE_REPORT_FIELDS_ENABLED}
             policyFeature={CONST.POLICY.POLICY_FEATURE.REPORT_FIELDS}
-            getEditValueRoute={(isInvoiceRoute, id, index) =>
-                isInvoiceRoute ? ROUTES.WORKSPACE_INVOICE_FIELDS_EDIT_VALUE.getRoute(id, index) : ROUTES.WORKSPACE_REPORT_FIELDS_EDIT_VALUE.getRoute(id, index)
-            }
-            testID="ReportFieldsValueSettingsPage"
-        />
+        >
+            <ScreenWrapper
+                enableEdgeToEdgeBottomSafeAreaPadding
+                style={styles.defaultModalContainer}
+                testID="ReportFieldsValueSettingsPage"
+            >
+                <HeaderWithBackButton
+                    title={currentValueName ?? oldValueName}
+                    shouldSetModalVisibility={false}
+                />
+                <View style={styles.flexGrow1}>
+                    <View style={[styles.mt2, styles.mh5]}>
+                        <View style={[styles.flexRow, styles.mb5, styles.mr2, styles.alignItemsCenter, styles.justifyContentBetween]}>
+                            <Text
+                                accessible={false}
+                                aria-hidden
+                            >
+                                {translate('workspace.reportFields.enableValue')}
+                            </Text>
+                            <Switch
+                                isOn={!currentValueDisabled}
+                                accessibilityLabel={translate('workspace.reportFields.enableValue')}
+                                onToggle={updateListValueEnabled}
+                                disabled={!canWriteReportFields}
+                                disabledAction={withReadOnlyFallback()}
+                                showLockIcon={!canWriteReportFields}
+                            />
+                        </View>
+                    </View>
+                    <MenuItemWithTopDescription
+                        title={currentValueName ?? oldValueName}
+                        description={translate('common.value')}
+                        shouldShowRightIcon={canWriteReportFields && !reportFieldID}
+                        interactive={canWriteReportFields && !reportFieldID}
+                        onPress={navigateToEditValue}
+                    />
+                    {canWriteReportFields && !hasAccountingConnections && (
+                        <MenuItem
+                            icon={icons.Trashcan}
+                            title={translate('common.delete')}
+                            onPress={confirmAndDeleteListValue}
+                        />
+                    )}
+                </View>
+            </ScreenWrapper>
+        </AccessOrNotFoundWrapper>
     );
 }
 
diff --git a/src/pages/workspace/reports/WorkspaceReportsPage.tsx b/src/pages/workspace/reports/WorkspaceReportsPage.tsx
index 821ff50b3bb9..3d921fe63dda 100644
--- a/src/pages/workspace/reports/WorkspaceReportsPage.tsx
+++ b/src/pages/workspace/reports/WorkspaceReportsPage.tsx
@@ -1,61 +1,168 @@
+import {FlashList} from '@shopify/flash-list';
+import type {ListRenderItemInfo} from '@shopify/flash-list';
 import {Str} from 'expensify-common';
-import React from 'react';
+import React, {useEffect, useMemo} from 'react';
+import {View} from 'react-native';
 import ActivityIndicator from '@components/ActivityIndicator';
 import HeaderWithBackButton from '@components/HeaderWithBackButton';
+import ImportedFromAccountingSoftware from '@components/ImportedFromAccountingSoftware';
+import MenuItem from '@components/MenuItem';
 import MenuItemWithTopDescription from '@components/MenuItemWithTopDescription';
+import {ModalActions} from '@components/Modal/Global/ModalContext';
 import OfflineWithFeedback from '@components/OfflineWithFeedback';
 import ScreenWrapper from '@components/ScreenWrapper';
 import ScrollView from '@components/ScrollView';
 import Section from '@components/Section';
 import SectionSubtitleHTML from '@components/SectionSubtitleHTML';
+import type {ListItem} from '@components/SelectionList/types';
 import Text from '@components/Text';
-import {useMemoizedLazyIllustrations} from '@hooks/useLazyAsset';
+import useConfirmModal from '@hooks/useConfirmModal';
+import {useMemoizedLazyExpensifyIcons, useMemoizedLazyIllustrations} from '@hooks/useLazyAsset';
 import useLocalize from '@hooks/useLocalize';
 import useNetwork from '@hooks/useNetwork';
+import useOnyx from '@hooks/useOnyx';
 import usePolicy from '@hooks/usePolicy';
 import usePolicyFeatureWriteAccess from '@hooks/usePolicyFeatureWriteAccess';
 import useResponsiveLayout from '@hooks/useResponsiveLayout';
 import useThemeStyles from '@hooks/useThemeStyles';
 import useWorkspaceDocumentTitle from '@hooks/useWorkspaceDocumentTitle';
+import {isConnectionInProgress, isConnectionUnverified} from '@libs/actions/connections';
 import {clearPolicyTitleFieldError, enablePolicyReportFields, setPolicyPreventMemberCreatedTitle} from '@libs/actions/Policy/Policy';
 import {getLatestErrorField} from '@libs/ErrorUtils';
 import Navigation from '@libs/Navigation/Navigation';
 import type {PlatformStackScreenProps} from '@libs/Navigation/PlatformStackNavigation/types';
 import type {WorkspaceSplitNavigatorParamList} from '@libs/Navigation/types';
-import {isControlPolicy} from '@libs/PolicyUtils';
+import {getConnectedIntegration, getCurrentConnectionName, hasAccountingConnections as hasAccountingConnectionsPolicyUtils, isControlPolicy, shouldShowSyncError} from '@libs/PolicyUtils';
 import {getTitleFieldWithFallback} from '@libs/ReportUtils';
 import type {SkeletonSpanReasonAttributes} from '@libs/telemetry/useSkeletonSpan';
+import {getReportFieldTypeTranslationKey} from '@libs/WorkspaceReportFieldUtils';
 import AccessOrNotFoundWrapper from '@pages/workspace/AccessOrNotFoundWrapper';
-import WorkspaceFieldsSection from '@pages/workspace/fields/WorkspaceFieldsSection';
 import ToggleSettingOptionRow from '@pages/workspace/workflows/ToggleSettingsOptionRow';
 import {openPolicyReportFieldsPage} from '@userActions/Policy/ReportField';
 import CONST from '@src/CONST';
+import ONYXKEYS from '@src/ONYXKEYS';
 import ROUTES from '@src/ROUTES';
 import type SCREENS from '@src/SCREENS';
 
+type ReportFieldForList = ListItem & {
+    fieldID: string;
+    rightLabel: string;
+    isDisabled: boolean;
+};
+
 type WorkspaceReportFieldsPageProps = PlatformStackScreenProps<WorkspaceSplitNavigatorParamList, typeof SCREENS.WORKSPACE.REPORTS>;
 
+function keyExtractor(item: ReportFieldForList) {
+    return item.keyForList ?? '';
+}
+
 function WorkspaceReportFieldsPage({
     route: {
         params: {policyID},
     },
 }: WorkspaceReportFieldsPageProps) {
+    // We need to use isSmallScreenWidth instead of shouldUseNarrowLayout for the small screen selection mode
+
     const {shouldUseNarrowLayout} = useResponsiveLayout();
     const styles = useThemeStyles();
-    const {translate} = useLocalize();
+    const {translate, localeCompare} = useLocalize();
     const policy = usePolicy(policyID);
+    const {showConfirmModal} = useConfirmModal();
     const {canWrite: canWriteReportFields, withReadOnlyFallback} = usePolicyFeatureWriteAccess(policy, CONST.POLICY.POLICY_FEATURE.REPORT_FIELDS);
     useWorkspaceDocumentTitle(policy?.name, 'workspace.common.reports');
+    const [connectionSyncProgress] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY_CONNECTION_SYNC_PROGRESS}${policyID}`);
+    const isSyncInProgress = isConnectionInProgress(connectionSyncProgress, policy);
+    const syncingAccountingIntegration = CONST.POLICY.CONNECTIONS.ACCOUNTING_CONNECTION_NAMES.find((connectionName) => connectionName === connectionSyncProgress?.connectionName);
+    const hasSyncError = shouldShowSyncError(policy, isSyncInProgress, CONST.POLICY.CONNECTIONS.ACCOUNTING_CONNECTION_NAMES);
+    const connectedIntegration = getConnectedIntegration(policy) ?? syncingAccountingIntegration;
+    const isConnectionVerified = connectedIntegration && !isConnectionUnverified(policy, connectedIntegration);
+    const currentConnectionName = getCurrentConnectionName(policy);
+    const hasAccountingConnections = hasAccountingConnectionsPolicyUtils(policy);
 
     const illustrations = useMemoizedLazyIllustrations(['ReportReceipt']);
+    const icons = useMemoizedLazyExpensifyIcons(['Plus']);
+
+    const onDisabledOrganizeSwitchPress = () => {
+        if (!hasAccountingConnections) {
+            return;
+        }
 
-    const {isOffline} = useNetwork();
+        showConfirmModal({
+            title: translate('workspace.moreFeatures.connectionsWarningModal.featureEnabledTitle'),
+            prompt: translate('workspace.moreFeatures.connectionsWarningModal.featureEnabledText'),
+            confirmText: translate('workspace.moreFeatures.connectionsWarningModal.manageSettings'),
+            cancelText: translate('common.cancel'),
+        }).then((result) => {
+            if (result.action !== ModalActions.CONFIRM || !policyID) {
+                return;
+            }
+
+            Navigation.navigate(ROUTES.POLICY_ACCOUNTING.getRoute(policyID));
+        });
+    };
+
+    const {isOffline} = useNetwork({onReconnect: () => openPolicyReportFieldsPage(policyID)});
+
+    useEffect(() => {
+        openPolicyReportFieldsPage(policyID);
+    }, [policyID]);
 
     const titleField = getTitleFieldWithFallback(policy);
 
+    const reportFieldsSections: ReportFieldForList[] = policy?.fieldList
+        ? Object.entries(policy.fieldList)
+              .filter(([, value]) => value.fieldID !== 'text_title')
+              .map(([, reportField]) => ({
+                  text: reportField.name,
+                  keyForList: String(reportField.fieldID),
+                  fieldID: reportField.fieldID,
+                  pendingAction: reportField.pendingAction,
+                  isDisabled: reportField.pendingAction === CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE,
+                  rightLabel: Str.recapitalize(translate(getReportFieldTypeTranslationKey(reportField.type ?? CONST.REPORT_FIELD_TYPES.TEXT))),
+              }))
+              .sort((a, b) => localeCompare(a.text, b.text))
+        : [];
+
+    const navigateToReportFieldsSettings = (reportField: ReportFieldForList) => {
+        if (!canWriteReportFields) {
+            return;
+        }
+
+        Navigation.navigate(ROUTES.WORKSPACE_REPORT_FIELDS_SETTINGS.getRoute(policyID, reportField.fieldID));
+    };
+
+    const getHeaderText = () =>
+        !hasSyncError && isConnectionVerified && currentConnectionName ? (
+            <Text style={[styles.mr5, styles.mt1]}>
+                <ImportedFromAccountingSoftware
+                    policyID={policyID}
+                    currentConnectionName={currentConnectionName}
+                    connectedIntegration={connectedIntegration}
+                    translatedText={translate('workspace.reportFields.importedFromAccountingSoftware')}
+                />
+            </Text>
+        ) : (
+            <Text style={[styles.textNormal, styles.colorMuted, styles.mr5, styles.mt1]}>{translate('workspace.reportFields.subtitle')}</Text>
+        );
+
     const isLoading = !isOffline && policy === undefined;
     const reasonAttributes: SkeletonSpanReasonAttributes = {context: 'WorkspaceReportFieldsPage', isOffline, isPolicyUndefined: policy === undefined};
 
+    const renderItem = ({item}: ListRenderItemInfo<ReportFieldForList>) => (
+        <OfflineWithFeedback pendingAction={item.pendingAction}>
+            <MenuItem
+                style={shouldUseNarrowLayout ? styles.ph5 : styles.ph8}
+                onPress={() => navigateToReportFieldsSettings(item)}
+                description={item.text}
+                disabled={item.isDisabled}
+                shouldShowRightIcon={!item.isDisabled && canWriteReportFields}
+                interactive={!item.isDisabled && canWriteReportFields}
+                rightLabel={item.rightLabel}
+                descriptionTextStyle={[styles.popoverMenuText, styles.textStrong]}
+            />
+        </OfflineWithFeedback>
+    );
+
     const titleFieldError = policy?.errorFields?.fieldList?.[CONST.POLICY.FIELDS.FIELD_LIST_TITLE];
     const reportTitleErrors = getLatestErrorField({errorFields: titleFieldError ?? {}}, 'defaultValue');
 
@@ -88,6 +195,13 @@ function WorkspaceReportFieldsPage({
         </OfflineWithFeedback>
     );
 
+    const reportFieldsAccessibilityLabel = useMemo(() => {
+        if (!hasSyncError && isConnectionVerified && currentConnectionName) {
+            return `${translate('workspace.common.reportFields')}, ${translate('workspace.reportFields.importedFromAccountingSoftware')} ${currentConnectionName} ${translate('workspace.accounting.settings')}`;
+        }
+        return `${translate('workspace.common.reportFields')}, ${translate('workspace.reportFields.subtitle')}`;
+    }, [hasSyncError, isConnectionVerified, currentConnectionName, translate]);
+
     return (
         <AccessOrNotFoundWrapper
             policyID={policyID}
@@ -167,28 +281,70 @@ function WorkspaceReportFieldsPage({
                                 showLockIcon={!canWriteReportFields}
                             />
                         </Section>
-                        <WorkspaceFieldsSection
-                            policy={policy}
-                            policyID={policyID}
-                            isEnabled={!!policy?.areReportFieldsEnabled}
-                            pendingAction={policy?.pendingFields?.areReportFieldsEnabled}
-                            fieldFilter={(field) => field.fieldID !== CONST.REPORT_FIELD_TITLE_FIELD_ID && (!field.target || field.target === CONST.REPORT_FIELD_TARGETS.EXPENSE)}
-                            titleKey="workspace.common.reportFields"
-                            subtitleKey="workspace.reportFields.subtitle"
-                            importedFromAccountingSoftwareKey="workspace.reportFields.importedFromAccountingSoftware"
-                            disableTitleKey="workspace.reportFields.disableReportFields"
-                            disablePromptKey="workspace.reportFields.disableReportFieldsConfirmation"
-                            addFieldKey="workspace.reportFields.addField"
-                            createRoute={ROUTES.WORKSPACE_CREATE_REPORT_FIELD.getRoute(policyID)}
-                            getSettingsRoute={ROUTES.WORKSPACE_REPORT_FIELDS_SETTINGS.getRoute}
-                            upgradeFeatureAlias={CONST.UPGRADE_FEATURE_INTRO_MAPPING.reportFields.alias}
-                            upgradeBackToRoute={ROUTES.WORKSPACE_REPORTS.getRoute(policyID)}
-                            enableFields={enablePolicyReportFields}
-                            openFieldsPage={openPolicyReportFieldsPage}
-                            policyFeature={CONST.POLICY.POLICY_FEATURE.REPORT_FIELDS}
-                            syncErrorConnectionNames={CONST.POLICY.CONNECTIONS.ACCOUNTING_CONNECTION_NAMES}
-                            titleAccessibilityRole={CONST.ROLE.HEADER}
-                        />
+                        <Section
+                            isCentralPane
+                            containerStyles={shouldUseNarrowLayout ? styles.p5 : styles.p8}
+                        >
+                            <ToggleSettingOptionRow
+                                pendingAction={policy?.pendingFields?.areReportFieldsEnabled}
+                                title={translate('workspace.common.reportFields')}
+                                switchAccessibilityLabel={reportFieldsAccessibilityLabel}
+                                subtitle={getHeaderText()}
+                                titleStyle={[styles.textHeadline, styles.cardSectionTitle, styles.accountSettingsSectionTitle, styles.mb1]}
+                                titleAccessibilityRole={CONST.ROLE.HEADER}
+                                isActive={!!policy?.areReportFieldsEnabled}
+                                onToggle={(isEnabled) => {
+                                    if (!isEnabled) {
+                                        showConfirmModal({
+                                            danger: true,
+                                            title: translate('workspace.reportFields.disableReportFields'),
+                                            prompt: translate('workspace.reportFields.disableReportFieldsConfirmation'),
+                                            confirmText: translate('common.disable'),
+                                            cancelText: translate('common.cancel'),
+                                        }).then((result) => {
+                                            if (result.action !== ModalActions.CONFIRM || !policyID) {
+                                                return;
+                                            }
+
+                                            enablePolicyReportFields(policyID, false);
+                                        });
+                                        return;
+                                    }
+                                    if (!isControlPolicy(policy)) {
+                                        Navigation.navigate(
+                                            ROUTES.WORKSPACE_UPGRADE.getRoute(policyID, CONST.UPGRADE_FEATURE_INTRO_MAPPING.reportFields.alias, ROUTES.WORKSPACE_REPORTS.getRoute(policyID)),
+                                        );
+                                        return;
+                                    }
+                                    enablePolicyReportFields(policyID, isEnabled);
+                                }}
+                                disabled={hasAccountingConnections || !canWriteReportFields}
+                                disabledAction={withReadOnlyFallback(onDisabledOrganizeSwitchPress)}
+                                showLockIcon={!canWriteReportFields}
+                                subMenuItems={
+                                    !!policy?.areReportFieldsEnabled && (
+                                        <>
+                                            <View style={[shouldUseNarrowLayout ? styles.mhn5 : styles.mhn8, styles.mt6]}>
+                                                <FlashList
+                                                    data={reportFieldsSections}
+                                                    renderItem={renderItem}
+                                                    keyExtractor={keyExtractor}
+                                                    maintainVisibleContentPosition={{disabled: true}}
+                                                />
+                                            </View>
+                                            {!hasAccountingConnections && canWriteReportFields && (
+                                                <MenuItem
+                                                    onPress={() => Navigation.navigate(ROUTES.WORKSPACE_CREATE_REPORT_FIELD.getRoute(policyID))}
+                                                    title={translate('workspace.reportFields.addField')}
+                                                    icon={icons.Plus}
+                                                    style={[styles.sectionMenuItemTopDescription]}
+                                                />
+                                            )}
+                                        </>
+                                    )
+                                }
+                            />
+                        </Section>
                     </ScrollView>
                 )}
             </ScreenWrapper>
diff --git a/src/pages/workspace/upgrade/WorkspaceUpgradePage.tsx b/src/pages/workspace/upgrade/WorkspaceUpgradePage.tsx
index 5b7c496ea4fe..03024b295094 100644
--- a/src/pages/workspace/upgrade/WorkspaceUpgradePage.tsx
+++ b/src/pages/workspace/upgrade/WorkspaceUpgradePage.tsx
@@ -38,7 +38,6 @@ import {
     enablePolicyAutoReimbursementLimit,
     enablePolicyConnections,
     enablePolicyHR,
-    enablePolicyInvoiceFields,
     enablePolicyInvoicing,
     enablePolicyReportFields,
     enablePolicyRules,
@@ -153,8 +152,6 @@ function WorkspaceUpgradePage({route}: WorkspaceUpgradePageProps) {
                         return;
                     }
                 }
-            case CONST.UPGRADE_FEATURE_INTRO_MAPPING.invoiceFields.id:
-                return Navigation.goBack(ROUTES.WORKSPACE_INVOICES.getRoute(policyID));
             case CONST.UPGRADE_FEATURE_INTRO_MAPPING.companyCards.id:
                 Navigation.navigate(createDynamicRoute(DYNAMIC_ROUTES.WORKSPACE_COMPANY_CARDS_ADD_NEW.path, ROUTES.WORKSPACE_COMPANY_CARDS_SELECT_FEED.getRoute(policyID)));
                 return;
@@ -235,9 +232,6 @@ function WorkspaceUpgradePage({route}: WorkspaceUpgradePageProps) {
                     }
                 }
                 break;
-            case CONST.UPGRADE_FEATURE_INTRO_MAPPING.invoiceFields.id:
-                enablePolicyInvoiceFields(policyID, true);
-                break;
             case CONST.UPGRADE_FEATURE_INTRO_MAPPING.rules.id:
                 enablePolicyRules(policy, true, false, policyDataRef.current);
                 break;
diff --git a/src/pages/workspace/withPolicy.tsx b/src/pages/workspace/withPolicy.tsx
index 2093b0b19062..b28cb2dacfca 100644
--- a/src/pages/workspace/withPolicy.tsx
+++ b/src/pages/workspace/withPolicy.tsx
@@ -47,19 +47,9 @@ type PolicyRouteName =
     | typeof SCREENS.WORKSPACE.DISTANCE_RATE_TAX_RATE_EDIT
     | typeof SCREENS.WORKSPACE.DISTANCE_RATE_TAX_RECLAIMABLE_ON_EDIT
     | typeof SCREENS.WORKSPACE.REPORT_FIELDS_CREATE
-    | typeof SCREENS.WORKSPACE.REPORT_FIELDS_SETTINGS
     | typeof SCREENS.WORKSPACE.REPORT_FIELDS_LIST_VALUES
-    | typeof SCREENS.WORKSPACE.REPORT_FIELDS_ADD_VALUE
-    | typeof SCREENS.WORKSPACE.REPORT_FIELDS_EDIT_VALUE
     | typeof SCREENS.WORKSPACE.REPORT_FIELDS_EDIT_INITIAL_VALUE
     | typeof SCREENS.WORKSPACE.REPORT_FIELDS_VALUE_SETTINGS
-    | typeof SCREENS.WORKSPACE.INVOICE_FIELDS_CREATE
-    | typeof SCREENS.WORKSPACE.INVOICE_FIELDS_SETTINGS
-    | typeof SCREENS.WORKSPACE.INVOICE_FIELDS_LIST_VALUES
-    | typeof SCREENS.WORKSPACE.INVOICE_FIELDS_ADD_VALUE
-    | typeof SCREENS.WORKSPACE.INVOICE_FIELDS_EDIT_VALUE
-    | typeof SCREENS.WORKSPACE.INVOICE_FIELDS_EDIT_INITIAL_VALUE
-    | typeof SCREENS.WORKSPACE.INVOICE_FIELDS_VALUE_SETTINGS
     | typeof SCREENS.WORKSPACE.ACCOUNTING.CARD_RECONCILIATION
     | typeof SCREENS.WORKSPACE.RULES
     | typeof SCREENS.WORKSPACE.DYNAMIC_WORKSPACE_EXPENSIFY_CARD_ISSUE_NEW
diff --git a/src/types/onyx/Policy.ts b/src/types/onyx/Policy.ts
index bed2edb0e752..45ff41d4e23a 100644
--- a/src/types/onyx/Policy.ts
+++ b/src/types/onyx/Policy.ts
@@ -2328,9 +2328,6 @@ type Policy = OnyxCommon.OnyxValueWithOfflineFeedback<
         /** Whether the Report Fields feature is enabled */
         areReportFieldsEnabled?: boolean;
 
-        /** Whether the Invoice Fields feature is enabled */
-        areInvoiceFieldsEnabled?: boolean;
-
         /** Whether the Connections feature is enabled */
         areConnectionsEnabled?: boolean;
 
diff --git a/tests/actions/ReportFieldTest.ts b/tests/actions/ReportFieldTest.ts
index 836af094171b..a3d605a4304a 100644
--- a/tests/actions/ReportFieldTest.ts
+++ b/tests/actions/ReportFieldTest.ts
@@ -91,7 +91,7 @@ describe('actions/ReportField', () => {
                 initialValue: 'Default Value',
                 listValues: [],
                 disabledListValues: [],
-                policyReportIDs: [],
+                policyExpenseReportIDs: [],
             };
 
             ReportField.createReportField(createReportFieldArguments);
@@ -146,7 +146,7 @@ describe('actions/ReportField', () => {
                 initialValue: defaultDate,
                 listValues: [],
                 disabledListValues: [],
-                policyReportIDs: [],
+                policyExpenseReportIDs: [],
             };
 
             ReportField.createReportField(createReportFieldArguments);
@@ -203,7 +203,7 @@ describe('actions/ReportField', () => {
                 initialValue: '',
                 listValues: ['Value 1', 'Value 2'],
                 disabledListValues: [false, true],
-                policyReportIDs: [],
+                policyExpenseReportIDs: [],
             };
 
             ReportField.createReportField(createReportFieldArguments);
@@ -259,7 +259,7 @@ describe('actions/ReportField', () => {
             initialValue: formulaInitialValue,
             listValues: [],
             disabledListValues: [],
-            policyReportIDs: [],
+            policyExpenseReportIDs: [],
         };
 
         ReportField.createReportField(createReportFieldArguments);
@@ -496,7 +496,7 @@ describe('actions/ReportField', () => {
                 initialValue: '{report:id}',
                 listValues: [],
                 disabledListValues: [],
-                policyReportIDs: [],
+                policyExpenseReportIDs: [],
             });
             await waitForBatchedUpdates();
 
diff --git a/tests/unit/ReportUtilsTest.ts b/tests/unit/ReportUtilsTest.ts
index 85c94e02fe0f..e086b3393d4c 100644
--- a/tests/unit/ReportUtilsTest.ts
+++ b/tests/unit/ReportUtilsTest.ts
@@ -109,7 +109,6 @@ import {
     getPolicyName,
     getReasonAndReportActionThatRequiresAttention,
     getReportActionWithSmartscanError,
-    getReportFieldMaps,
     getReportFieldsByPolicyID,
     getReportIDFromLink,
     getReportOrDraftReport,
@@ -14632,106 +14631,6 @@ describe('ReportUtils', () => {
         });
     });
 
-    describe('getReportFieldMaps', () => {
-        it('should read invoice field values from report name value pairs keyed by raw field ID', async () => {
-            const reportID = 'getReportFieldMapsRawKey';
-            const report: Report = {
-                reportID,
-                policyID: '1',
-                type: CONST.REPORT.TYPE.INVOICE,
-                fieldList: {},
-            };
-            const policyFieldList: Record<string, PolicyReportField> = {
-                expensify_field_id_LIST: {
-                    type: 'dropdown',
-                    values: ['policy default'],
-                    disabledOptions: [false],
-                    fieldID: 'field_id_LIST',
-                    name: 'Client',
-                    defaultValue: 'policy default',
-                    orderWeight: 0,
-                    deletable: true,
-                    keys: [],
-                    externalIDs: [],
-                    isTax: false,
-                    target: CONST.REPORT_FIELD_TARGETS.INVOICE,
-                },
-            };
-            const reportNameValuePairField: PolicyReportField = {
-                type: 'dropdown',
-                values: ['policy default'],
-                disabledOptions: [false],
-                fieldID: 'field_id_LIST',
-                name: 'Client',
-                defaultValue: 'policy default',
-                orderWeight: 0,
-                deletable: true,
-                keys: [],
-                externalIDs: [],
-                isTax: false,
-                value: 'persisted value',
-                target: CONST.REPORT_FIELD_TARGETS.INVOICE,
-            };
-
-            await Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT}${reportID}`, report);
-            await Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT_NAME_VALUE_PAIRS}${reportID}`, Object.fromEntries([['field_id_LIST', reportNameValuePairField]]));
-
-            const {fieldValues, fieldsByName} = getReportFieldMaps(report, policyFieldList);
-
-            expect(fieldValues.client).toBe('persisted value');
-            expect(fieldsByName.client.value).toBe('persisted value');
-        });
-
-        it('should not read expense field values from report name value pairs', async () => {
-            const reportID = 'getReportFieldMapsExpenseField';
-            const report: Report = {
-                reportID,
-                policyID: '1',
-                type: CONST.REPORT.TYPE.EXPENSE,
-                fieldList: {},
-            };
-            const policyFieldList: Record<string, PolicyReportField> = {
-                expensify_field_id_LIST: {
-                    type: 'dropdown',
-                    values: ['policy default'],
-                    disabledOptions: [false],
-                    fieldID: 'field_id_LIST',
-                    name: 'Client',
-                    defaultValue: 'policy default',
-                    orderWeight: 0,
-                    deletable: true,
-                    keys: [],
-                    externalIDs: [],
-                    isTax: false,
-                    target: CONST.REPORT_FIELD_TARGETS.EXPENSE,
-                },
-            };
-            const reportNameValuePairField: PolicyReportField = {
-                type: 'dropdown',
-                values: ['policy default'],
-                disabledOptions: [false],
-                fieldID: 'field_id_LIST',
-                name: 'Client',
-                defaultValue: 'policy default',
-                orderWeight: 0,
-                deletable: true,
-                keys: [],
-                externalIDs: [],
-                isTax: false,
-                value: 'persisted value',
-                target: CONST.REPORT_FIELD_TARGETS.EXPENSE,
-            };
-
-            await Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT}${reportID}`, report);
-            await Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT_NAME_VALUE_PAIRS}${reportID}`, Object.fromEntries([['field_id_LIST', reportNameValuePairField]]));
-
-            const {fieldValues, fieldsByName} = getReportFieldMaps(report, policyFieldList);
-
-            expect(fieldValues.client).toBe('policy default');
-            expect(fieldsByName.client.value).toBeUndefined();
-        });
-    });
-
     describe('canEditReportTitle', () => {
         const getTitleField = (deletable: boolean): PolicyReportField => ({
             fieldID: CONST.REPORT_FIELD_TITLE_FIELD_ID,
diff --git a/tests/unit/WorkspaceReportFieldUtilsTest.ts b/tests/unit/WorkspaceReportFieldUtilsTest.ts
index 5c9f7e8cecca..6a02ca2f75aa 100644
--- a/tests/unit/WorkspaceReportFieldUtilsTest.ts
+++ b/tests/unit/WorkspaceReportFieldUtilsTest.ts
@@ -1,5 +1,4 @@
-import {generateFieldID, getUnsupportedReportFieldFormulaParts, hasFormulaPartsInInitialValue, isReportFieldNameExisting, isReportFieldTargetValid} from '@libs/WorkspaceReportFieldUtils';
-import CONST from '@src/CONST';
+import {getUnsupportedReportFieldFormulaParts, hasFormulaPartsInInitialValue, isReportFieldNameExisting} from '@libs/WorkspaceReportFieldUtils';
 import type {PolicyReportField} from '@src/types/onyx/Policy';
 
 describe('WorkspaceReportFieldUtils.hasFormulaPartsInInitialValue', () => {
@@ -84,28 +83,13 @@ describe('WorkspaceReportFieldUtils.getUnsupportedReportFieldFormulaParts', () =
 });
 
 describe('WorkspaceReportFieldUtils.isReportFieldNameExisting', () => {
-    const baseNameField: PolicyReportField = {
-        fieldID: '',
-        name: '',
-        type: 'text',
-        values: [],
-        disabledOptions: [],
-        defaultValue: '',
-        orderWeight: 0,
-        deletable: false,
-        keys: [],
-        externalIDs: [],
-        isTax: false,
-    };
     const fieldList: Record<string, PolicyReportField> = {
-        field1: {...baseNameField, name: 'Field1', type: 'text'},
-        field2: {...baseNameField, name: 'Field2', type: 'date'},
-        field3: {...baseNameField, name: 'Field3', type: 'text', target: CONST.REPORT_FIELD_TARGETS.EXPENSE},
-        field4: {...baseNameField, name: 'Field3', type: 'text', target: CONST.REPORT_FIELD_TARGETS.INVOICE},
+        field1: {name: 'Field1', type: 'text'} as PolicyReportField,
+        field2: {name: 'Field2', type: 'date'} as PolicyReportField,
     };
 
     it('should return false when field name does not exist', () => {
-        expect(isReportFieldNameExisting(fieldList, 'Field5')).toBe(false);
+        expect(isReportFieldNameExisting(fieldList, 'Field3')).toBe(false);
     });
 
     it('should return true when field name exists with exact case match', () => {
@@ -116,54 +100,4 @@ describe('WorkspaceReportFieldUtils.isReportFieldNameExisting', () => {
         expect(isReportFieldNameExisting(fieldList, 'FIELD1')).toBe(true);
         expect(isReportFieldNameExisting(fieldList, 'field1')).toBe(true);
     });
-
-    it('checks existing names only within the expected target', () => {
-        expect(isReportFieldNameExisting(fieldList, 'Field1', CONST.REPORT_FIELD_TARGETS.INVOICE)).toBe(false);
-        expect(isReportFieldNameExisting(fieldList, 'Field1', CONST.REPORT_FIELD_TARGETS.EXPENSE)).toBe(true);
-        expect(isReportFieldNameExisting(fieldList, 'Field3', CONST.REPORT_FIELD_TARGETS.INVOICE)).toBe(true);
-        expect(isReportFieldNameExisting(fieldList, 'Field3', CONST.REPORT_FIELD_TARGETS.EXPENSE)).toBe(true);
-    });
-});
-
-describe('WorkspaceReportFieldUtils.generateFieldID', () => {
-    it('keeps the existing field ID format when no target is provided', () => {
-        expect(generateFieldID('Field A')).toBe('field_id_FIELD_A');
-    });
-
-    it('can include target in the field ID to avoid cross-target collisions', () => {
-        expect(generateFieldID('Field A', CONST.REPORT_FIELD_TARGETS.INVOICE)).toBe('field_id_INVOICE_FIELD_A');
-        expect(generateFieldID('Field A', CONST.REPORT_FIELD_TARGETS.EXPENSE)).toBe('field_id_EXPENSE_FIELD_A');
-    });
-});
-
-describe('WorkspaceReportFieldUtils.isReportFieldTargetValid', () => {
-    const baseField: PolicyReportField = {
-        fieldID: 'field_id_1',
-        name: 'Field A',
-        type: CONST.REPORT_FIELD_TYPES.TEXT,
-        values: [],
-        disabledOptions: [],
-        defaultValue: '',
-        orderWeight: 1,
-        deletable: true,
-        keys: [],
-        externalIDs: [],
-        isTax: false,
-    };
-
-    it('allows expense fields without target', () => {
-        expect(isReportFieldTargetValid(baseField, CONST.REPORT_FIELD_TARGETS.EXPENSE)).toBe(true);
-    });
-
-    it('blocks expense settings for invoice-targeted fields', () => {
-        expect(isReportFieldTargetValid({...baseField, target: CONST.REPORT_FIELD_TARGETS.INVOICE}, CONST.REPORT_FIELD_TARGETS.EXPENSE)).toBe(false);
-    });
-
-    it('allows invoice settings for invoice-targeted fields', () => {
-        expect(isReportFieldTargetValid({...baseField, target: CONST.REPORT_FIELD_TARGETS.INVOICE}, CONST.REPORT_FIELD_TARGETS.INVOICE)).toBe(true);
-    });
-
-    it('blocks invoice settings for fields without target', () => {
-        expect(isReportFieldTargetValid(baseField, CONST.REPORT_FIELD_TARGETS.INVOICE)).toBe(false);
-    });
 });

From 8204aa8bf09bc8c46a096b35ce31969fa254f772 Mon Sep 17 00:00:00 2001
From: "dmkt9 (via MelvinBot)" <infra+melvinbot@expensify.com>
Date: Thu, 11 Jun 2026 04:15:42 +0000
Subject: [PATCH 331/435] Wrap each RenderHTML in its own View to prevent text
 overlap

Co-authored-by: dmkt9 <dmkt9@users.noreply.github.com>
---
 .../Security/LockAccount/LockAccountPage.tsx     | 16 ++++++++++++----
 1 file changed, 12 insertions(+), 4 deletions(-)

diff --git a/src/pages/settings/Security/LockAccount/LockAccountPage.tsx b/src/pages/settings/Security/LockAccount/LockAccountPage.tsx
index 798abe7d416c..459c8bb349d9 100644
--- a/src/pages/settings/Security/LockAccount/LockAccountPage.tsx
+++ b/src/pages/settings/Security/LockAccount/LockAccountPage.tsx
@@ -34,10 +34,18 @@ function LockAccountPage() {
 
     const lockAccountPagePrompt = (
         <View style={[styles.renderHTML, styles.gap4]}>
-            <RenderHTML html={translate('lockAccountPage.findYourSituation')} />
-            <RenderHTML html={translate('lockAccountPage.lostCardOrCharges')} />
-            <RenderHTML html={translate('lockAccountPage.unauthorizedAccess')} />
-            <RenderHTML html={translate('lockAccountPage.securityTeamFollowUp')} />
+            <View>
+                <RenderHTML html={translate('lockAccountPage.findYourSituation')} />
+            </View>
+            <View>
+                <RenderHTML html={translate('lockAccountPage.lostCardOrCharges')} />
+            </View>
+            <View>
+                <RenderHTML html={translate('lockAccountPage.unauthorizedAccess')} />
+            </View>
+            <View>
+                <RenderHTML html={translate('lockAccountPage.securityTeamFollowUp')} />
+            </View>
         </View>
     );
 

From e3446dfb573cb3ec0c943c94d335fa36e0693cf9 Mon Sep 17 00:00:00 2001
From: krishna2323 <belivethatkg@gmail.com>
Date: Thu, 11 Jun 2026 09:51:24 +0530
Subject: [PATCH 332/435] Fix doubled border on sticky group headers with
 absolute-positioned cover

Signed-off-by: krishna2323 <belivethatkg@gmail.com>
---
 src/components/Search/SearchList/index.tsx |  2 ++
 src/styles/index.ts                        | 14 ++++++++++++++
 2 files changed, 16 insertions(+)

diff --git a/src/components/Search/SearchList/index.tsx b/src/components/Search/SearchList/index.tsx
index 88b42c13775c..d3dd9cdbb75f 100644
--- a/src/components/Search/SearchList/index.tsx
+++ b/src/components/Search/SearchList/index.tsx
@@ -642,6 +642,7 @@ function SearchList({
                     style={[
                         styles.searchListHeaderContainerStyle,
                         isLargeScreenWidth ? [styles.listTableHeaderCompact, styles.searchListHeaderTableStyle, styles.mh5] : styles.listTableHeader,
+                        isLargeScreenWidth && shouldSplitGroups && styles.searchListHeaderTableStickyOverlap,
                     ]}
                 >
                     {canSelectMultiple && (
@@ -656,6 +657,7 @@ function SearchList({
                     )}
 
                     {SearchTableHeader}
+                    {isLargeScreenWidth && shouldSplitGroups && <View style={styles.searchListHeaderBorderCover} />}
                 </View>
             )}
             <BaseSearchList
diff --git a/src/styles/index.ts b/src/styles/index.ts
index 2ca46949f522..4049b8fe3540 100644
--- a/src/styles/index.ts
+++ b/src/styles/index.ts
@@ -3611,6 +3611,20 @@ const staticStyles = (theme: ThemeColors) =>
             paddingBottom: 8,
         },
 
+        searchListHeaderTableStickyOverlap: {
+            position: 'relative',
+            zIndex: 10,
+        },
+
+        searchListHeaderBorderCover: {
+            position: 'absolute',
+            bottom: -2,
+            left: 0,
+            right: 0,
+            height: 1,
+            backgroundColor: theme.highlightBG,
+        },
+
         groupSearchListTableContainerStyle: {
             minHeight: variables.h28,
             paddingBottom: 0,

From 05b6d294ea55a422544af5a69dc22aaed6b8ef6d Mon Sep 17 00:00:00 2001
From: krishna2323 <belivethatkg@gmail.com>
Date: Thu, 11 Jun 2026 09:54:28 +0530
Subject: [PATCH 333/435] Fix intermittent missing sub-header border with
 marginTop overlap

Signed-off-by: krishna2323 <belivethatkg@gmail.com>
---
 src/components/Search/SearchList/ListItem/GroupHeader.tsx | 2 +-
 src/styles/index.ts                                       | 4 ++++
 2 files changed, 5 insertions(+), 1 deletion(-)

diff --git a/src/components/Search/SearchList/ListItem/GroupHeader.tsx b/src/components/Search/SearchList/ListItem/GroupHeader.tsx
index 8a63181e8c27..42afe29f4666 100644
--- a/src/components/Search/SearchList/ListItem/GroupHeader.tsx
+++ b/src/components/Search/SearchList/ListItem/GroupHeader.tsx
@@ -462,7 +462,7 @@ function GroupHeader({
                                                 isActionColumnWide={isSubHeaderActionColumnWide}
                                             />
                                         </View>
-                                        <View style={styles.ph3}>
+                                        <View style={[styles.ph3, styles.groupSubHeaderBorderOverlap]}>
                                             <View style={StyleUtils.getSelectedBorderBottomStyle(isItemSelected)} />
                                         </View>
                                     </View>
diff --git a/src/styles/index.ts b/src/styles/index.ts
index 4049b8fe3540..3cee793677e4 100644
--- a/src/styles/index.ts
+++ b/src/styles/index.ts
@@ -3625,6 +3625,10 @@ const staticStyles = (theme: ThemeColors) =>
             backgroundColor: theme.highlightBG,
         },
 
+        groupSubHeaderBorderOverlap: {
+            marginTop: -1,
+        },
+
         groupSearchListTableContainerStyle: {
             minHeight: variables.h28,
             paddingBottom: 0,

From b3f767b64d5afd75e80a097d2e02f01137578605 Mon Sep 17 00:00:00 2001
From: nabi-ebrahimi <nabi.zarin.work@gmail.com>
Date: Thu, 11 Jun 2026 09:35:55 +0430
Subject: [PATCH 334/435] fix test lint for per diem submit flow

---
 tests/unit/hooks/useExpenseSubmission.test.ts | 25 +++++++++++--------
 1 file changed, 15 insertions(+), 10 deletions(-)

diff --git a/tests/unit/hooks/useExpenseSubmission.test.ts b/tests/unit/hooks/useExpenseSubmission.test.ts
index ea97574cda20..7a89126b3d97 100644
--- a/tests/unit/hooks/useExpenseSubmission.test.ts
+++ b/tests/unit/hooks/useExpenseSubmission.test.ts
@@ -113,6 +113,15 @@ function buildTransaction(overrides: Partial<Transaction> = {}): Transaction {
     } as Transaction;
 }
 
+function buildReportAction(overrides: Partial<ReportAction> = {}): ReportAction {
+    return {
+        reportActionID: 'report-action-1',
+        actionName: CONST.REPORT.ACTIONS.TYPE.IOU,
+        created: '2026-04-24',
+        ...overrides,
+    };
+}
+
 function buildPerDiemTransaction(overrides: Partial<Transaction> = {}): Transaction {
     return buildTransaction({
         amount: 200,
@@ -133,7 +142,7 @@ function buildPerDiemTransaction(overrides: Partial<Transaction> = {}): Transact
             },
         },
         ...overrides,
-    } as Transaction);
+    });
 }
 
 function buildParams(overrides: Partial<Parameters<typeof useExpenseSubmission>[0]> = {}): Parameters<typeof useExpenseSubmission>[0] {
@@ -220,16 +229,14 @@ describe('useExpenseSubmission orchestrator-suppressed cleanup', () => {
             // Move-from-track SUBMIT: the action writes the transaction under the EXISTING tracked transaction id,
             // so cleanup must reference that same id — not a fresh rand64() optimistic one.
             const EXISTING_TRACKED_TRANSACTION_ID = 'tracked-transaction-99';
-            const linkedTrackedExpenseReportAction = {
+            const linkedTrackedExpenseReportAction = buildReportAction({
                 reportActionID: 'linked-action-1',
-                actionName: CONST.REPORT.ACTIONS.TYPE.IOU,
-                created: '2026-04-24',
                 originalMessage: {
                     IOUTransactionID: EXISTING_TRACKED_TRANSACTION_ID,
                     IOUReportID: 'tracked-report-1',
                     type: CONST.IOU.REPORT_ACTION_TYPE.CREATE,
                 },
-            } as unknown as ReportAction;
+            });
             const movedTransaction = buildTransaction({
                 linkedTrackedExpenseReportAction,
                 linkedTrackedExpenseReportID: 'tracked-report-1',
@@ -277,17 +284,15 @@ describe('useExpenseSubmission orchestrator-suppressed cleanup', () => {
 
         it('routes tracked per diem SUBMIT through requestMoney so the original tracked expense is moved', async () => {
             const existingTrackedTransactionID = 'tracked-per-diem-transaction-1';
-            const linkedTrackedExpenseReportAction = {
+            const linkedTrackedExpenseReportAction = buildReportAction({
                 reportActionID: 'tracked-per-diem-action-1',
-                actionName: CONST.REPORT.ACTIONS.TYPE.IOU,
                 childReportID: 'tracked-per-diem-thread-1',
-                created: '2026-04-24',
                 originalMessage: {
                     IOUTransactionID: existingTrackedTransactionID,
                     IOUReportID: 'tracked-per-diem-report-1',
                     type: CONST.IOU.REPORT_ACTION_TYPE.CREATE,
                 },
-            } as unknown as ReportAction;
+            });
             const perDiemTransaction = buildPerDiemTransaction({
                 linkedTrackedExpenseReportAction,
                 linkedTrackedExpenseReportID: 'tracked-per-diem-report-1',
@@ -431,7 +436,7 @@ describe('useExpenseSubmission action-bailout safety', () => {
 
     it('skips cleanup/nav when a multi-transaction SUBMIT batch has any iteration that bails (defense-in-depth — preserves the failed item draft)', async () => {
         // Cast keeps the fixture minimal — pre-validation only needs truthy presence.
-        const linkedTracked = {linkedTrackedExpenseReportAction: {reportActionID: 'a-1'} as unknown as ReportAction, linkedTrackedExpenseReportID: 'r-1'};
+        const linkedTracked = {linkedTrackedExpenseReportAction: buildReportAction({reportActionID: 'a-1'}), linkedTrackedExpenseReportID: 'r-1'};
         const transaction1 = buildTransaction({transactionID: 't-1', ...linkedTracked});
         const transaction2 = buildTransaction({transactionID: 't-2', ...linkedTracked});
         mockRequestMoneyAction.mockReturnValueOnce({iouReport: {reportID: 'iou-1'}}).mockReturnValueOnce({});

From 53938159cfb3869d52e622f738817a9957ced5b8 Mon Sep 17 00:00:00 2001
From: Mohammad Luthfi Fathur Rahman <luthfi@expensify.com>
Date: Thu, 11 Jun 2026 13:38:54 +0700
Subject: [PATCH 335/435] fix eslint-seatbelt drift for
 ReportSecondaryActionUtilsTest.ts

---
 config/eslint/eslint.seatbelt.tsv | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/config/eslint/eslint.seatbelt.tsv b/config/eslint/eslint.seatbelt.tsv
index 57557c64e0ce..89858fb0a12c 100644
--- a/config/eslint/eslint.seatbelt.tsv
+++ b/config/eslint/eslint.seatbelt.tsv
@@ -1818,7 +1818,7 @@
 "../../tests/unit/ReportLayoutUtilsTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../tests/unit/ReportNameUtilsTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	22
 "../../tests/unit/ReportPrimaryActionUtilsTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	168
-"../../tests/unit/ReportSecondaryActionUtilsTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	450
+"../../tests/unit/ReportSecondaryActionUtilsTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	466
 "../../tests/unit/ReportSubmitUtilsTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../tests/unit/ReportTitleUtilsTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	3
 "../../tests/unit/ReportUtilsGetIconsTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	1

From 26a319d35a38b20255a96932875f3bf61c1c3d17 Mon Sep 17 00:00:00 2001
From: Mohammad Luthfi Fathur Rahman <luthfi@expensify.com>
Date: Thu, 11 Jun 2026 14:02:04 +0700
Subject: [PATCH 336/435] restore eslint-seatbelt baseline for
 WorkspaceReportFieldUtilsTest

---
 config/eslint/eslint.seatbelt.tsv | 1 +
 1 file changed, 1 insertion(+)

diff --git a/config/eslint/eslint.seatbelt.tsv b/config/eslint/eslint.seatbelt.tsv
index 57557c64e0ce..cbeb05a6e449 100644
--- a/config/eslint/eslint.seatbelt.tsv
+++ b/config/eslint/eslint.seatbelt.tsv
@@ -1869,6 +1869,7 @@
 "../../tests/unit/ViolationUtilsTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	20
 "../../tests/unit/WhisperContentMentionContextTest.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	3
 "../../tests/unit/WorkflowUtilsTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	8
+"../../tests/unit/WorkspaceReportFieldUtilsTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	2
 "../../tests/unit/WorkspacesSettingsUtilsTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	15
 "../../tests/unit/awaitStagingDeploysTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	3
 "../../tests/unit/canEditFieldOfMoneyRequestTest.ts"	"@typescript-eslint/no-deprecated/randomReportAction.originalMessage"	3

From 687c32b882cccd1948caa58d050f09069ecac9a1 Mon Sep 17 00:00:00 2001
From: OSBotify <infra+osbotify@expensify.com>
Date: Thu, 11 Jun 2026 07:17:11 +0000
Subject: [PATCH 337/435] Auto-tighten eslint-seatbelt baseline

---
 config/eslint/eslint.seatbelt.tsv | 18 ++++--------------
 1 file changed, 4 insertions(+), 14 deletions(-)

diff --git a/config/eslint/eslint.seatbelt.tsv b/config/eslint/eslint.seatbelt.tsv
index 89858fb0a12c..8866fc373521 100644
--- a/config/eslint/eslint.seatbelt.tsv
+++ b/config/eslint/eslint.seatbelt.tsv
@@ -450,7 +450,6 @@
 "../../src/components/TagPicker/index.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../src/components/TaxPicker.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../src/components/TestDrive/Modal/AdminTestDriveModal.tsx"	"no-restricted-imports"	1
-"../../src/components/TestDrive/Modal/EmployeeTestDriveModal.tsx"	"@typescript-eslint/no-deprecated/InteractionManager.runAfterInteractions"	1
 "../../src/components/TestDrive/TestDriveDemo.tsx"	"no-restricted-imports"	1
 "../../src/components/TextInput/BaseTextInput/implementation/index.native.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../src/components/TextInput/BaseTextInput/implementation/index.native.tsx"	"react-hooks/refs"	2
@@ -665,9 +664,8 @@
 "../../src/libs/Navigation/AppNavigator/Navigators/SettingsSplitNavigator.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../src/libs/Navigation/AppNavigator/Navigators/TabNavigator.native.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../src/libs/Navigation/AppNavigator/Navigators/TestToolsModalNavigator.tsx"	"no-restricted-syntax"	1
-"../../src/libs/Navigation/AppNavigator/Navigators/WorkspaceNavigator.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
-"../../src/libs/Navigation/AppNavigator/Navigators/WorkspaceSplitNavigator.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	2
-"../../src/libs/Navigation/AppNavigator/createRootStackNavigator/GetStateForActionHandlers.ts"	"@typescript-eslint/no-unsafe-type-assertion"	17
+"../../src/libs/Navigation/AppNavigator/Navigators/WorkspaceSplitNavigator.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
+"../../src/libs/Navigation/AppNavigator/createRootStackNavigator/GetStateForActionHandlers.ts"	"@typescript-eslint/no-unsafe-type-assertion"	15
 "../../src/libs/Navigation/AppNavigator/createRootStackNavigator/index.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../src/libs/Navigation/AppNavigator/createRootStackNavigator/useCustomRootStackNavigatorState/restoreTabNavigatorRoutes.ts"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../src/libs/Navigation/AppNavigator/createSplitNavigator/SplitRouter.ts"	"@typescript-eslint/no-unsafe-type-assertion"	4
@@ -688,7 +686,6 @@
 "../../src/libs/Navigation/guards/OnboardingGuard.ts"	"@typescript-eslint/no-unsafe-type-assertion"	2
 "../../src/libs/Navigation/helpers/createNormalizedConfigs.ts"	"@typescript-eslint/no-deprecated/escape"	1
 "../../src/libs/Navigation/helpers/createNormalizedConfigs.ts"	"@typescript-eslint/no-unsafe-type-assertion"	1
-"../../src/libs/Navigation/helpers/dismissModalAndOpenReportInInboxTab.ts"	"@typescript-eslint/no-deprecated/InteractionManager.runAfterInteractions"	1
 "../../src/libs/Navigation/helpers/dynamicRoutesUtils/createDynamicRoute.ts"	"@typescript-eslint/no-unsafe-type-assertion"	2
 "../../src/libs/Navigation/helpers/dynamicRoutesUtils/getDynamicRouteAdaptedState.ts"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../src/libs/Navigation/helpers/dynamicRoutesUtils/getDynamicRouteQueryParams.ts"	"@typescript-eslint/no-unsafe-type-assertion"	1
@@ -864,7 +861,6 @@
 "../../src/libs/actions/ImportTransactions.ts"	"no-restricted-syntax"	1
 "../../src/libs/actions/InputFocus/index.web.ts"	"no-restricted-imports"	1
 "../../src/libs/actions/InputFocus/index.web.ts"	"no-restricted-syntax"	1
-"../../src/libs/actions/Link.ts"	"@typescript-eslint/no-deprecated/InteractionManager.runAfterInteractions"	1
 "../../src/libs/actions/Link.ts"	"@typescript-eslint/no-unsafe-type-assertion"	4
 "../../src/libs/actions/Link.ts"	"no-restricted-syntax"	3
 "../../src/libs/actions/MapboxToken.ts"	"no-restricted-syntax"	2
@@ -908,7 +904,6 @@
 "../../src/libs/actions/ReimbursementAccount/resetNonUSDBankAccount.ts"	"no-restricted-syntax"	1
 "../../src/libs/actions/ReimbursementAccount/resetUSDBankAccount.ts"	"no-restricted-syntax"	1
 "../../src/libs/actions/Report/MarkAllMessageAsRead.tsx"	"no-restricted-syntax"	1
-"../../src/libs/actions/Report/index.ts"	"@typescript-eslint/no-deprecated/InteractionManager.runAfterInteractions"	1
 "../../src/libs/actions/Report/index.ts"	"@typescript-eslint/no-deprecated/buildNextStepNew"	3
 "../../src/libs/actions/Report/index.ts"	"@typescript-eslint/no-deprecated/reportAction.originalMessage"	1
 "../../src/libs/actions/Report/index.ts"	"@typescript-eslint/no-unsafe-type-assertion"	20
@@ -921,7 +916,6 @@
 "../../src/libs/actions/Search.ts"	"@typescript-eslint/no-unsafe-type-assertion"	19
 "../../src/libs/actions/Search.ts"	"no-restricted-syntax"	1
 "../../src/libs/actions/Session/index.ts"	"@typescript-eslint/no-unsafe-type-assertion"	3
-"../../src/libs/actions/Session/index.ts"	"no-restricted-imports"	1
 "../../src/libs/actions/Session/index.ts"	"no-restricted-syntax"	9
 "../../src/libs/actions/Session/index.ts"	"rulesdir/no-onyx-connect"	2
 "../../src/libs/actions/SplitExpenses.ts"	"@typescript-eslint/no-unsafe-type-assertion"	2
@@ -1298,7 +1292,6 @@
 "../../src/pages/signin/SignInPageLayout/FooterRow/index.native.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../src/pages/signin/ValidateCodeForm/BaseValidateCodeForm.tsx"	"react-hooks/set-state-in-effect"	4
 "../../src/pages/tasks/NewTaskPage.tsx"	"@typescript-eslint/no-deprecated/InteractionManager.runAfterInteractions"	1
-"../../src/pages/tasks/TaskAssigneeSelectorModal.tsx"	"@typescript-eslint/no-deprecated/InteractionManager.runAfterInteractions"	2
 "../../src/pages/tasks/TaskShareDestinationSelectorModal.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	2
 "../../src/pages/wallet/WalletStatementPage.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../src/pages/workspace/DynamicWorkspaceOverviewPlanTypePage.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	2
@@ -1420,7 +1413,6 @@
 "../../src/pages/workspace/copyPolicySettings/CopyPolicySettingsConfirmPage.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../src/pages/workspace/copyPolicySettings/CopyPolicySettingsSelectFeaturesPage.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	2
 "../../src/pages/workspace/distanceRates/PolicyDistanceRatesPage.tsx"	"react-hooks/preserve-manual-memoization"	1
-"../../src/pages/workspace/downgrade/WorkspaceDowngradePage.tsx"	"@typescript-eslint/no-deprecated/InteractionManager.runAfterInteractions"	1
 "../../src/pages/workspace/duplicate/WorkspaceDuplicateSelectFeaturesForm.tsx"	"react-hooks/preserve-manual-memoization"	2
 "../../src/pages/workspace/duplicate/WorkspaceDuplicateSelectFeaturesForm.tsx"	"react-hooks/set-state-in-effect"	1
 "../../src/pages/workspace/expensifyCard/DynamicExpensifyCardLimitTypePage.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
@@ -1437,7 +1429,6 @@
 "../../src/pages/workspace/members/ImportMembersPage.tsx"	"no-restricted-syntax"	1
 "../../src/pages/workspace/members/ImportMembersPage.tsx"	"rulesdir/no-default-id-values"	1
 "../../src/pages/workspace/members/ImportedMembersConfirmationPage.tsx"	"react-hooks/refs"	7
-"../../src/pages/workspace/members/ImportedMembersPage.tsx"	"@typescript-eslint/no-deprecated/InteractionManager.runAfterInteractions"	1
 "../../src/pages/workspace/members/WorkspaceInviteMessageComponent.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../src/pages/workspace/members/WorkspaceInviteMessageComponent.tsx"	"react-hooks/set-state-in-effect"	1
 "../../src/pages/workspace/members/WorkspaceMemberDetailsPage.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	4
@@ -1712,7 +1703,7 @@
 "../../tests/ui/components/SettlementButtonTest.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	3
 "../../tests/ui/components/TimePickerTest.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../tests/ui/hooks/useHtmlPasteTest/index.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	10
-"../../tests/unit/APITest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	74
+"../../tests/unit/APITest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	61
 "../../tests/unit/AddExistingExpenseSearchTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	6
 "../../tests/unit/AgentActionTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	61
 "../../tests/unit/AgentZeroStatusContextTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	5
@@ -1727,7 +1718,7 @@
 "../../tests/unit/CIGitLogicTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	5
 "../../tests/unit/CLIVariadicTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../tests/unit/CardFeedErrorsDerivedValueTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	1
-"../../tests/unit/CardFeedUtilsTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	16
+"../../tests/unit/CardFeedUtilsTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../tests/unit/CardUtilsTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	152
 "../../tests/unit/CardsSectionUtilsTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../tests/unit/CategoryUtilsTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	1
@@ -1930,7 +1921,6 @@
 "../../tests/unit/hooks/useFreeTrial.test.ts"	"@typescript-eslint/no-unsafe-type-assertion"	8
 "../../tests/unit/hooks/useGettingStartedItems.test.ts"	"@typescript-eslint/no-unsafe-type-assertion"	11
 "../../tests/unit/hooks/useHasAnyAdminExpensifyCardFeed.test.ts"	"@typescript-eslint/no-unsafe-type-assertion"	1
-"../../tests/unit/hooks/useHoldRejectActionsTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../tests/unit/hooks/useIsAllowedToIssueCompanyCard.test.ts"	"@typescript-eslint/no-unsafe-type-assertion"	8
 "../../tests/unit/hooks/useIsBlockedToAddFeed.test.ts"	"@typescript-eslint/no-unsafe-type-assertion"	11
 "../../tests/unit/hooks/useIsSidebarRouteActive.test.ts"	"@typescript-eslint/no-unsafe-type-assertion"	2

From 109a21e91ef3cfd1853a145725bbab79e55468c0 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Micha=C5=82=20Jasikowski?= <michal@expensify.com>
Date: Thu, 11 Jun 2026 10:10:37 +0200
Subject: [PATCH 338/435] Revert "Merge pull request #92161 from
 huult/83858-migrate-money-request-part-3"

This reverts commit 6ed5f7a6ee14a780838eec1d5117aa4249741934, reversing
changes made to e785d143685fbcb0a483b18b1a1e1770cca4d126.
---
 config/eslint/eslint.seatbelt.tsv             |   3 +
 src/ROUTES.ts                                 | 184 ++++++------------
 src/SCREENS.ts                                |  12 +-
 .../sections/AttendeeField.tsx                |   5 +-
 .../sections/CategoryField.tsx                |  24 ++-
 .../sections/RateField.tsx                    |  22 +--
 .../sections/TaxFields.tsx                    |   7 +-
 .../MoneyRequestHeaderSecondaryActions.tsx    |  19 +-
 .../QuickCreationActionsBar/index.tsx         |  19 +-
 .../ReportActionItem/MoneyRequestView.tsx     |  99 +++++-----
 .../SearchActionsBarCreateButton.tsx          |  16 +-
 src/hooks/useCreateReport.tsx                 |  16 +-
 src/hooks/useParticipantSubmission.ts         |  10 +-
 .../ModalStackNavigators/index.tsx            |  12 +-
 src/libs/Navigation/linkingConfig/config.ts   |  12 +-
 src/libs/Navigation/types.ts                  |  26 ++-
 src/libs/ReportUtils.ts                       |  36 ++--
 .../Search/SearchTransactionsChangeReport.tsx |  32 ++-
 src/pages/iou/SplitExpenseEditPage.tsx        |  49 +++--
 ...tPage.tsx => IOURequestStepAccountant.tsx} |  18 +-
 ...esPage.tsx => IOURequestStepAttendees.tsx} |  19 +-
 ...oryPage.tsx => IOURequestStepCategory.tsx} |  44 +++--
 .../step/IOURequestStepCategoryCreate.tsx     |   4 +-
 ...ge.tsx => IOURequestStepTaxAmountPage.tsx} |  30 ++-
 ...Page.tsx => IOURequestStepTaxRatePage.tsx} |  17 +-
 ...radePage.tsx => IOURequestStepUpgrade.tsx} |  33 ++--
 .../step/withFullTransactionOrNotFound.tsx    |   6 +-
 .../step/withWritableReportOrNotFound.tsx     |  12 +-
 tests/unit/ReportUtilsTest.ts                 |  77 +++-----
 29 files changed, 374 insertions(+), 489 deletions(-)
 rename src/pages/iou/request/step/{DynamicIOURequestStepAccountantPage.tsx => IOURequestStepAccountant.tsx} (82%)
 rename src/pages/iou/request/step/{DynamicIOURequestStepAttendeesPage.tsx => IOURequestStepAttendees.tsx} (90%)
 rename src/pages/iou/request/step/{DynamicIOURequestStepCategoryPage.tsx => IOURequestStepCategory.tsx} (90%)
 rename src/pages/iou/request/step/{DynamicIOURequestStepTaxAmountPage.tsx => IOURequestStepTaxAmountPage.tsx} (88%)
 rename src/pages/iou/request/step/{DynamicIOURequestStepTaxRatePage.tsx => IOURequestStepTaxRatePage.tsx} (90%)
 rename src/pages/iou/request/step/{DynamicIOURequestStepUpgradePage.tsx => IOURequestStepUpgrade.tsx} (93%)

diff --git a/config/eslint/eslint.seatbelt.tsv b/config/eslint/eslint.seatbelt.tsv
index 59f3ce4aa639..a1eff506b188 100644
--- a/config/eslint/eslint.seatbelt.tsv
+++ b/config/eslint/eslint.seatbelt.tsv
@@ -1178,6 +1178,7 @@
 "../../src/pages/iou/request/step/IOURequestEditReportCommon.tsx"	"@typescript-eslint/no-deprecated/ConfirmModal"	1
 "../../src/pages/iou/request/step/IOURequestEditReportCommon.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../src/pages/iou/request/step/IOURequestStepAmount.tsx"	"react-hooks/set-state-in-effect"	1
+"../../src/pages/iou/request/step/IOURequestStepCategory.tsx"	"@typescript-eslint/no-deprecated/InteractionManager.runAfterInteractions"	1
 "../../src/pages/iou/request/step/IOURequestStepConfirmation.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	3
 "../../src/pages/iou/request/step/IOURequestStepConfirmation.tsx"	"react-hooks/preserve-manual-memoization"	1
 "../../src/pages/iou/request/step/IOURequestStepDestination.tsx"	"@typescript-eslint/no-deprecated/InteractionManager.runAfterInteractions"	1
@@ -1203,6 +1204,8 @@
 "../../src/pages/iou/request/step/IOURequestStepSubrate.tsx"	"@typescript-eslint/no-deprecated/InteractionManager.runAfterInteractions"	1
 "../../src/pages/iou/request/step/IOURequestStepSubrate.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../src/pages/iou/request/step/IOURequestStepSubrate.tsx"	"react-hooks/set-state-in-effect"	1
+"../../src/pages/iou/request/step/IOURequestStepUpgrade.tsx"	"@typescript-eslint/no-deprecated/ConfirmModal"	1
+"../../src/pages/iou/request/step/IOURequestStepUpgrade.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	2
 "../../src/pages/iou/request/step/IOURequestStepWaypoint.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	2
 "../../src/pages/iou/request/step/StepScreenWrapper.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../src/pages/iou/request/step/confirmation/submitDismissStrategies.ts"	"no-restricted-imports"	1
diff --git a/src/ROUTES.ts b/src/ROUTES.ts
index e03422189dcd..0a2d5e3b8f7e 100644
--- a/src/ROUTES.ts
+++ b/src/ROUTES.ts
@@ -180,126 +180,6 @@ const DYNAMIC_ROUTES = {
         entryScreens: ['*'],
         getRoute: (accountID: number) => `avatar/${accountID}` as const,
     },
-    MONEY_REQUEST_STEP_TAX_RATE: {
-        path: 'money-request/tax-rate/:action/:iouType/:transactionID/:reportID?',
-        entryScreens: [
-            SCREENS.MONEY_REQUEST.STEP_CONFIRMATION,
-            SCREENS.REPORT,
-            SCREENS.RIGHT_MODAL.EXPENSE_REPORT,
-            SCREENS.RIGHT_MODAL.SEARCH_REPORT,
-            SCREENS.RIGHT_MODAL.SEARCH_REPORT_ACTIONS,
-            SCREENS.RIGHT_MODAL.SEARCH_MONEY_REQUEST_REPORT,
-        ],
-        getRoute: (action: IOUAction, iouType: IOUType, transactionID: string | undefined, reportID?: string) => {
-            if (!transactionID || !reportID) {
-                Log.warn('Invalid transactionID or reportID is used to build the MONEY_REQUEST_STEP_TAX_RATE dynamic route');
-            }
-
-            return `money-request/tax-rate/${action as string}/${iouType as string}/${transactionID}${reportID ? `/${reportID}` : ''}` as const;
-        },
-    },
-    MONEY_REQUEST_STEP_TAX_AMOUNT: {
-        path: 'money-request/tax-amount/:action/:iouType/:transactionID/:reportID?',
-        entryScreens: [
-            SCREENS.MONEY_REQUEST.STEP_CONFIRMATION,
-            SCREENS.REPORT,
-            SCREENS.RIGHT_MODAL.EXPENSE_REPORT,
-            SCREENS.RIGHT_MODAL.SEARCH_REPORT,
-            SCREENS.RIGHT_MODAL.SEARCH_REPORT_ACTIONS,
-            SCREENS.RIGHT_MODAL.SEARCH_MONEY_REQUEST_REPORT,
-        ],
-        getRoute: (action: IOUAction, iouType: IOUType, transactionID: string | undefined, reportID?: string) => {
-            if (!transactionID || !reportID) {
-                Log.warn('Invalid transactionID or reportID is used to build the MONEY_REQUEST_STEP_TAX_AMOUNT dynamic route');
-            }
-
-            return `money-request/tax-amount/${action as string}/${iouType as string}/${transactionID}${reportID ? `/${reportID}` : ''}` as const;
-        },
-    },
-    MONEY_REQUEST_STEP_CATEGORY: {
-        path: 'money-request/category/:action/:iouType/:transactionID/:reportID/:reportActionID?',
-        entryScreens: [
-            SCREENS.MONEY_REQUEST.STEP_CONFIRMATION,
-            SCREENS.MONEY_REQUEST.SPLIT_EXPENSE_EDIT,
-            SCREENS.REPORT,
-            SCREENS.RIGHT_MODAL.EXPENSE_REPORT,
-            SCREENS.RIGHT_MODAL.SEARCH_REPORT,
-            SCREENS.RIGHT_MODAL.SEARCH_REPORT_ACTIONS,
-            SCREENS.RIGHT_MODAL.SEARCH_MONEY_REQUEST_REPORT,
-        ],
-        getRoute: (action: IOUAction, iouType: IOUType, transactionID: string | undefined, reportID: string | undefined, reportActionID?: string) => {
-            if (!transactionID || !reportID) {
-                Log.warn('Invalid transactionID or reportID is used to build the MONEY_REQUEST_STEP_CATEGORY dynamic route');
-            }
-
-            return `money-request/category/${action as string}/${iouType as string}/${transactionID}/${reportID}${reportActionID ? `/${reportActionID}` : ''}` as const;
-        },
-    },
-    MONEY_REQUEST_ATTENDEE: {
-        path: 'money-request/attendees/:action/:iouType/:transactionID/:reportID',
-        entryScreens: [
-            SCREENS.MONEY_REQUEST.STEP_CONFIRMATION,
-            SCREENS.REPORT,
-            SCREENS.RIGHT_MODAL.EXPENSE_REPORT,
-            SCREENS.RIGHT_MODAL.SEARCH_REPORT,
-            SCREENS.RIGHT_MODAL.SEARCH_REPORT_ACTIONS,
-            SCREENS.RIGHT_MODAL.SEARCH_MONEY_REQUEST_REPORT,
-        ],
-        getRoute: (action: IOUAction, iouType: IOUType, transactionID: string | undefined, reportID: string | undefined) => {
-            if (!transactionID || !reportID) {
-                Log.warn('Invalid transactionID or reportID is used to build the MONEY_REQUEST_ATTENDEE dynamic route');
-            }
-
-            return `money-request/attendees/${action as string}/${iouType as string}/${transactionID}/${reportID}` as const;
-        },
-    },
-    MONEY_REQUEST_ACCOUNTANT: {
-        path: 'money-request/accountant/:action/:iouType/:transactionID/:reportID',
-        entryScreens: [
-            SCREENS.MONEY_REQUEST.STEP_CONFIRMATION,
-            SCREENS.REPORT,
-            SCREENS.REPORT_DETAILS.DYNAMIC_ROOT,
-            SCREENS.RIGHT_MODAL.EXPENSE_REPORT,
-            SCREENS.RIGHT_MODAL.SEARCH_REPORT,
-            SCREENS.RIGHT_MODAL.SEARCH_REPORT_ACTIONS,
-            SCREENS.RIGHT_MODAL.SEARCH_MONEY_REQUEST_REPORT,
-        ],
-        getRoute: (action: IOUAction, iouType: IOUType, transactionID: string | undefined, reportID: string | undefined) => {
-            if (!transactionID || !reportID) {
-                Log.warn('Invalid transactionID or reportID is used to build the MONEY_REQUEST_ACCOUNTANT dynamic route');
-            }
-
-            return `money-request/accountant/${action as string}/${iouType as string}/${transactionID}/${reportID}` as const;
-        },
-    },
-    MONEY_REQUEST_UPGRADE: {
-        path: 'money-request/upgrade/:action/:iouType/:transactionID/:reportID/:upgradePath?',
-        entryScreens: [
-            SCREENS.MONEY_REQUEST.STEP_CONFIRMATION,
-            SCREENS.MONEY_REQUEST.SPLIT_EXPENSE_EDIT,
-            SCREENS.HOME,
-            SCREENS.INBOX,
-            SCREENS.REPORT,
-            SCREENS.RIGHT_MODAL.EXPENSE_REPORT,
-            SCREENS.RIGHT_MODAL.SEARCH_REPORT,
-            SCREENS.RIGHT_MODAL.SEARCH_REPORT_ACTIONS,
-            SCREENS.RIGHT_MODAL.SEARCH_MONEY_REQUEST_REPORT,
-            SCREENS.SEARCH.ROOT,
-            SCREENS.SEARCH.TRANSACTIONS_CHANGE_REPORT_SEARCH_RHP,
-        ],
-        getRoute: (params: {action: IOUAction; iouType: IOUType; transactionID: string; reportID: string; upgradePath?: string; shouldSubmitExpense?: boolean}) => {
-            const {action, iouType, transactionID, reportID, upgradePath, shouldSubmitExpense} = params;
-            const upgradePathParam = upgradePath ? `/${upgradePath}` : '';
-            const basePath = `money-request/upgrade/${action as string}/${iouType as string}/${transactionID}/${reportID}${upgradePathParam}` as const;
-
-            if (shouldSubmitExpense) {
-                return `${basePath}?shouldSubmitExpense=true` as const;
-            }
-
-            return basePath;
-        },
-        queryParams: ['shouldSubmitExpense'],
-    },
     NEW_REPORT_WORKSPACE_SELECTION: {
         path: 'new-report-workspace-selection',
         entryScreens: ['*'],
@@ -1749,6 +1629,26 @@ const ROUTES = {
             return getUrlWithBackToParam(`${action as string}/${iouType as string}/amount/${transactionID}/${reportID}/${reportActionID ? `${reportActionID}/` : ''}${pageIndex}`, backTo);
         },
     },
+    MONEY_REQUEST_STEP_TAX_RATE: {
+        route: ':action/:iouType/taxRate/:transactionID/:reportID?',
+        getRoute: (action: IOUAction, iouType: IOUType, transactionID: string | undefined, reportID: string | undefined, backTo = '') => {
+            if (!transactionID || !reportID) {
+                Log.warn('Invalid transactionID or reportID is used to build the MONEY_REQUEST_STEP_TAX_RATE route');
+            }
+
+            return getUrlWithBackToParam(`${action as string}/${iouType as string}/taxRate/${transactionID}/${reportID}`, backTo);
+        },
+    },
+    MONEY_REQUEST_STEP_TAX_AMOUNT: {
+        route: ':action/:iouType/taxAmount/:transactionID/:reportID?',
+        getRoute: (action: IOUAction, iouType: IOUType, transactionID: string | undefined, reportID: string | undefined, backTo = '') => {
+            if (!transactionID || !reportID) {
+                Log.warn('Invalid transactionID or reportID is used to build the MONEY_REQUEST_STEP_TAX_AMOUNT route');
+            }
+
+            return getUrlWithBackToParam(`${action as string}/${iouType as string}/taxAmount/${transactionID}/${reportID}`, backTo);
+        },
+    },
     MONEY_REQUEST_STEP_CATEGORY_CREATE: {
         route: ':action/:iouType/category/new/:transactionID/:reportID/:reportActionID?',
         getRoute: (action: IOUAction, iouType: IOUType, transactionID: string | undefined, reportID: string | undefined, reportActionID?: string, backTo = '') => {
@@ -1759,6 +1659,50 @@ const ROUTES = {
             return getUrlWithBackToParam(`${action as string}/${iouType as string}/category/new/${transactionID}/${reportID}${reportActionID ? `/${reportActionID}` : ''}`, backTo);
         },
     },
+    MONEY_REQUEST_STEP_CATEGORY: {
+        route: ':action/:iouType/category/:transactionID/:reportID/:reportActionID?',
+        getRoute: (action: IOUAction, iouType: IOUType, transactionID: string | undefined, reportID: string | undefined, backTo = '', reportActionID?: string) => {
+            if (!transactionID || !reportID) {
+                Log.warn('Invalid transactionID or reportID is used to build the MONEY_REQUEST_STEP_CATEGORY route');
+            }
+
+            return getUrlWithBackToParam(`${action as string}/${iouType as string}/category/${transactionID}/${reportID}${reportActionID ? `/${reportActionID}` : ''}`, backTo);
+        },
+    },
+    MONEY_REQUEST_ATTENDEE: {
+        route: ':action/:iouType/attendees/:transactionID/:reportID',
+        getRoute: (action: IOUAction, iouType: IOUType, transactionID: string | undefined, reportID: string | undefined, backTo = '') => {
+            if (!transactionID || !reportID) {
+                Log.warn('Invalid transactionID or reportID is used to build the MONEY_REQUEST_ATTENDEE route');
+            }
+
+            return getUrlWithBackToParam(`${action as string}/${iouType as string}/attendees/${transactionID}/${reportID}`, backTo);
+        },
+    },
+    MONEY_REQUEST_ACCOUNTANT: {
+        route: ':action/:iouType/accountant/:transactionID/:reportID',
+        getRoute: (action: IOUAction, iouType: IOUType, transactionID: string | undefined, reportID: string | undefined, backTo = '') => {
+            if (!transactionID || !reportID) {
+                Log.warn('Invalid transactionID or reportID is used to build the MONEY_REQUEST_ACCOUNTANT route');
+            }
+
+            return getUrlWithBackToParam(`${action as string}/${iouType as string}/accountant/${transactionID}/${reportID}`, backTo);
+        },
+    },
+    MONEY_REQUEST_UPGRADE: {
+        route: ':action/:iouType/upgrade/:transactionID/:reportID/:upgradePath?',
+        getRoute: (params: {action: IOUAction; iouType: IOUType; transactionID: string; reportID: string; backTo?: string; shouldSubmitExpense?: boolean; upgradePath?: string}) => {
+            const {action, iouType, transactionID, reportID, backTo = '', shouldSubmitExpense = false, upgradePath} = params;
+            const upgradePathParam = upgradePath ? `/${upgradePath}` : '';
+            const baseURL = `${action as string}/${iouType as string}/upgrade/${transactionID}/${reportID}${upgradePathParam}` as const;
+
+            if (shouldSubmitExpense) {
+                return getUrlWithBackToParam(`${baseURL}?shouldSubmitExpense=${shouldSubmitExpense}` as const, backTo);
+            }
+
+            return getUrlWithBackToParam(baseURL, backTo);
+        },
+    },
     MONEY_REQUEST_STEP_DESTINATION: {
         route: ':action/:iouType/destination/:transactionID/:reportID',
         getRoute: (action: IOUAction, iouType: IOUType, transactionID: string, reportID: string, backTo = '') =>
diff --git a/src/SCREENS.ts b/src/SCREENS.ts
index 4bd406171f04..4d1adeea0198 100644
--- a/src/SCREENS.ts
+++ b/src/SCREENS.ts
@@ -373,9 +373,9 @@ const SCREENS = {
         STEP_CONFIRMATION: 'Money_Request_Step_Confirmation',
         STEP_CONFIRMATION_VERIFY_ACCOUNT: 'Money_Request_Step_Confirmation_Verify_Account',
         START: 'Money_Request_Start',
-        DYNAMIC_STEP_UPGRADE: 'Dynamic_Money_Request_Step_Upgrade',
+        STEP_UPGRADE: 'Money_Request_Step_Upgrade',
         STEP_AMOUNT: 'Money_Request_Step_Amount',
-        DYNAMIC_STEP_CATEGORY: 'Dynamic_Money_Request_Step_Category',
+        STEP_CATEGORY: 'Money_Request_Step_Category',
         STEP_CATEGORY_CREATE: 'Money_Request_Step_Category_Create',
         STEP_DATE: 'Money_Request_Step_Date',
         STEP_DESCRIPTION: 'Money_Request_Step_Description',
@@ -386,8 +386,8 @@ const SCREENS = {
         STEP_SCAN: 'Money_Request_Step_Scan',
         STEP_TAG: 'Money_Request_Step_Tag',
         STEP_WAYPOINT: 'Money_Request_Step_Waypoint',
-        DYNAMIC_STEP_TAX_AMOUNT: 'Dynamic_Money_Request_Step_Tax_Amount',
-        DYNAMIC_STEP_TAX_RATE: 'Dynamic_Money_Request_Step_Tax_Rate',
+        STEP_TAX_AMOUNT: 'Money_Request_Step_Tax_Amount',
+        STEP_TAX_RATE: 'Money_Request_Step_Tax_Rate',
         RECEIPT_VIEW: 'Money_Request_Receipt_View',
         STEP_SEND_FROM: 'Money_Request_Step_Send_From',
         STEP_COMPANY_INFO: 'Money_Request_Step_Company_Info',
@@ -396,8 +396,8 @@ const SCREENS = {
         EDIT_WAYPOINT: 'Money_Request_Edit_Waypoint',
         RECEIPT: 'Money_Request_Receipt',
         STATE_SELECTOR: 'Money_Request_State_Selector',
-        DYNAMIC_STEP_ATTENDEES: 'Dynamic_Money_Request_Attendee',
-        DYNAMIC_STEP_ACCOUNTANT: 'Dynamic_Money_Request_Step_Accountant',
+        STEP_ATTENDEES: 'Money_Request_Attendee',
+        STEP_ACCOUNTANT: 'Money_Request_Accountant',
         STEP_DESTINATION: 'Money_Request_Destination',
         STEP_TIME: 'Money_Request_Time',
         STEP_SUBRATE: 'Money_Request_SubRate',
diff --git a/src/components/MoneyRequestConfirmationList/sections/AttendeeField.tsx b/src/components/MoneyRequestConfirmationList/sections/AttendeeField.tsx
index 90d4d5cd27a3..2252f0df716f 100644
--- a/src/components/MoneyRequestConfirmationList/sections/AttendeeField.tsx
+++ b/src/components/MoneyRequestConfirmationList/sections/AttendeeField.tsx
@@ -7,13 +7,12 @@ import useAttendees from '@hooks/useAttendees';
 import useLocalize from '@hooks/useLocalize';
 import useThemeStyles from '@hooks/useThemeStyles';
 import {enrichAndSortAttendees} from '@libs/AttendeeUtils';
-import createDynamicRoute from '@libs/Navigation/helpers/dynamicRoutesUtils/createDynamicRoute';
 import Navigation from '@libs/Navigation/Navigation';
 import {getAttendeesListDisplayString} from '@libs/TransactionUtils';
 import CONST from '@src/CONST';
 import type {IOUAction, IOUType} from '@src/CONST';
 import type {TranslationPaths} from '@src/languages/types';
-import {DYNAMIC_ROUTES} from '@src/ROUTES';
+import ROUTES from '@src/ROUTES';
 import type * as OnyxTypes from '@src/types/onyx';
 import {attendeeSliceSelector} from './selectors';
 import useTransactionSelector from './useTransactionSelector';
@@ -68,7 +67,7 @@ function AttendeeField({formattedAmountPerAttendee, isReadOnly, transactionID, a
                     return;
                 }
 
-                Navigation.navigate(createDynamicRoute(DYNAMIC_ROUTES.MONEY_REQUEST_ATTENDEE.getRoute(action, iouType, transactionID, reportID)));
+                Navigation.navigate(ROUTES.MONEY_REQUEST_ATTENDEE.getRoute(action, iouType, transactionID, reportID, Navigation.getActiveRoute()));
             }}
             interactive={!isReadOnly}
             brickRoadIndicator={shouldDisplayAttendeesError ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR : undefined}
diff --git a/src/components/MoneyRequestConfirmationList/sections/CategoryField.tsx b/src/components/MoneyRequestConfirmationList/sections/CategoryField.tsx
index 4f70942ac203..098a4d5225f7 100644
--- a/src/components/MoneyRequestConfirmationList/sections/CategoryField.tsx
+++ b/src/components/MoneyRequestConfirmationList/sections/CategoryField.tsx
@@ -5,12 +5,11 @@ import {useMemoizedLazyExpensifyIcons} from '@hooks/useLazyAsset';
 import useLocalize from '@hooks/useLocalize';
 import useThemeStyles from '@hooks/useThemeStyles';
 import {getDecodedLeafCategoryName} from '@libs/CategoryUtils';
-import createDynamicRoute from '@libs/Navigation/helpers/dynamicRoutesUtils/createDynamicRoute';
 import Navigation from '@libs/Navigation/Navigation';
 import CONST from '@src/CONST';
 import type {IOUAction, IOUType} from '@src/CONST';
 import type {TranslationPaths} from '@src/languages/types';
-import ROUTES, {DYNAMIC_ROUTES} from '@src/ROUTES';
+import ROUTES from '@src/ROUTES';
 import type * as OnyxTypes from '@src/types/onyx';
 import {categoryStateSelector} from './selectors';
 import useTransactionSelector from './useTransactionSelector';
@@ -79,24 +78,23 @@ function CategoryField({
 
                 if (shouldNavigateToUpgradePath) {
                     Navigation.navigate(
-                        createDynamicRoute(
-                            DYNAMIC_ROUTES.MONEY_REQUEST_UPGRADE.getRoute({
-                                action,
-                                iouType,
-                                transactionID,
-                                reportID,
-                                upgradePath: CONST.UPGRADE_PATHS.CATEGORIES,
-                            }),
-                        ),
+                        ROUTES.MONEY_REQUEST_UPGRADE.getRoute({
+                            action,
+                            iouType,
+                            transactionID,
+                            reportID,
+                            backTo: ROUTES.MONEY_REQUEST_STEP_CATEGORY.getRoute(action, iouType, transactionID, reportID, Navigation.getActiveRoute(), reportActionID),
+                            upgradePath: CONST.UPGRADE_PATHS.CATEGORIES,
+                        }),
                     );
                 } else if (!policy && shouldSelectPolicy) {
                     Navigation.navigate(
                         ROUTES.SET_DEFAULT_WORKSPACE.getRoute(
-                            createDynamicRoute(DYNAMIC_ROUTES.MONEY_REQUEST_STEP_CATEGORY.getRoute(action, iouType, transactionID, reportID, reportActionID)),
+                            ROUTES.MONEY_REQUEST_STEP_CATEGORY.getRoute(action, iouType, transactionID, reportID, Navigation.getActiveRoute(), reportActionID),
                         ),
                     );
                 } else {
-                    Navigation.navigate(createDynamicRoute(DYNAMIC_ROUTES.MONEY_REQUEST_STEP_CATEGORY.getRoute(action, iouType, transactionID, reportID, reportActionID)));
+                    Navigation.navigate(ROUTES.MONEY_REQUEST_STEP_CATEGORY.getRoute(action, iouType, transactionID, reportID, Navigation.getActiveRoute(), reportActionID));
                 }
             }}
             style={[styles.moneyRequestMenuItem]}
diff --git a/src/components/MoneyRequestConfirmationList/sections/RateField.tsx b/src/components/MoneyRequestConfirmationList/sections/RateField.tsx
index da1c2bcfbd0a..46c64a8dafdb 100644
--- a/src/components/MoneyRequestConfirmationList/sections/RateField.tsx
+++ b/src/components/MoneyRequestConfirmationList/sections/RateField.tsx
@@ -6,11 +6,10 @@ import useLocalize from '@hooks/useLocalize';
 import useNetwork from '@hooks/useNetwork';
 import useThemeStyles from '@hooks/useThemeStyles';
 import DistanceRequestUtils from '@libs/DistanceRequestUtils';
-import createDynamicRoute from '@libs/Navigation/helpers/dynamicRoutesUtils/createDynamicRoute';
 import Navigation from '@libs/Navigation/Navigation';
 import CONST from '@src/CONST';
 import type {IOUAction, IOUType} from '@src/CONST';
-import ROUTES, {DYNAMIC_ROUTES} from '@src/ROUTES';
+import ROUTES from '@src/ROUTES';
 import type * as OnyxTypes from '@src/types/onyx';
 import type {Unit} from '@src/types/onyx/Policy';
 
@@ -76,16 +75,15 @@ function RateField({
 
                 if ((!isPolicyExpenseChat && !isTrackExpense) || (shouldNavigateToUpgradePath && isTrackExpense)) {
                     Navigation.navigate(
-                        createDynamicRoute(
-                            DYNAMIC_ROUTES.MONEY_REQUEST_UPGRADE.getRoute({
-                                action,
-                                iouType,
-                                transactionID,
-                                reportID,
-                                upgradePath: CONST.UPGRADE_PATHS.DISTANCE_RATES,
-                                shouldSubmitExpense: !isTrackExpense,
-                            }),
-                        ),
+                        ROUTES.MONEY_REQUEST_UPGRADE.getRoute({
+                            action,
+                            iouType,
+                            transactionID,
+                            reportID,
+                            upgradePath: CONST.UPGRADE_PATHS.DISTANCE_RATES,
+                            backTo: Navigation.getActiveRoute(),
+                            shouldSubmitExpense: !isTrackExpense,
+                        }),
                     );
                 } else if (!policy && shouldSelectPolicy && isTrackExpense) {
                     Navigation.navigate(
diff --git a/src/components/MoneyRequestConfirmationList/sections/TaxFields.tsx b/src/components/MoneyRequestConfirmationList/sections/TaxFields.tsx
index fdc67c1ce3c8..c1a23e52decb 100644
--- a/src/components/MoneyRequestConfirmationList/sections/TaxFields.tsx
+++ b/src/components/MoneyRequestConfirmationList/sections/TaxFields.tsx
@@ -12,7 +12,6 @@ import useThemeStyles from '@hooks/useThemeStyles';
 import {setMoneyRequestTaxAmount} from '@libs/actions/IOU/MoneyRequest';
 import {convertToBackendAmount, convertToFrontendAmountAsString, getLocalizedCurrencySymbol} from '@libs/CurrencyUtils';
 import {isMovingTransactionFromTrackExpense} from '@libs/IOUUtils';
-import createDynamicRoute from '@libs/Navigation/helpers/dynamicRoutesUtils/createDynamicRoute';
 import Navigation from '@libs/Navigation/Navigation';
 import {getCalculatedTaxAmount, getTaxAmount, getTaxRateTitle} from '@libs/TransactionUtils';
 import {setDraftSplitTransaction} from '@userActions/IOU/Split';
@@ -20,7 +19,7 @@ import CONST from '@src/CONST';
 import type {IOUAction, IOUType} from '@src/CONST';
 import type {TranslationPaths} from '@src/languages/types';
 import ONYXKEYS from '@src/ONYXKEYS';
-import {DYNAMIC_ROUTES} from '@src/ROUTES';
+import ROUTES from '@src/ROUTES';
 import type * as OnyxTypes from '@src/types/onyx';
 import {taxSliceSelector} from './selectors';
 import useTransactionSelector from './useTransactionSelector';
@@ -118,7 +117,7 @@ function TaxFields({policy, policyForMovingExpenses, iouCurrencyCode, canModifyT
                         return;
                     }
 
-                    Navigation.navigate(createDynamicRoute(DYNAMIC_ROUTES.MONEY_REQUEST_STEP_TAX_RATE.getRoute(action, iouType, transactionID, reportID)));
+                    Navigation.navigate(ROUTES.MONEY_REQUEST_STEP_TAX_RATE.getRoute(action, iouType, transactionID, reportID, Navigation.getActiveRoute()));
                 }}
                 disabled={didConfirm}
                 interactive={canModifyTaxFields}
@@ -157,7 +156,7 @@ function TaxFields({policy, policyForMovingExpenses, iouCurrencyCode, canModifyT
                             return;
                         }
 
-                        Navigation.navigate(createDynamicRoute(DYNAMIC_ROUTES.MONEY_REQUEST_STEP_TAX_AMOUNT.getRoute(action, iouType, transactionID, reportID)));
+                        Navigation.navigate(ROUTES.MONEY_REQUEST_STEP_TAX_AMOUNT.getRoute(action, iouType, transactionID, reportID, Navigation.getActiveRoute()));
                     }}
                     disabled={didConfirm}
                     interactive={canModifyTaxFields}
diff --git a/src/components/MoneyRequestHeaderSecondaryActions.tsx b/src/components/MoneyRequestHeaderSecondaryActions.tsx
index 27cfc63a232f..d826ac98d2c6 100644
--- a/src/components/MoneyRequestHeaderSecondaryActions.tsx
+++ b/src/components/MoneyRequestHeaderSecondaryActions.tsx
@@ -35,7 +35,6 @@ import initSplitExpense from '@libs/actions/SplitExpenses';
 import {setNameValuePair} from '@libs/actions/User';
 import getNonEmptyStringOnyxID from '@libs/getNonEmptyStringOnyxID';
 import {getExistingTransactionID} from '@libs/IOUUtils';
-import createDynamicRoute from '@libs/Navigation/helpers/dynamicRoutesUtils/createDynamicRoute';
 import Navigation from '@libs/Navigation/Navigation';
 import type {PlatformStackRouteProp} from '@libs/Navigation/PlatformStackNavigation/types';
 import type {ReportsSplitNavigatorParamList, RightModalNavigatorParamList} from '@libs/Navigation/types';
@@ -67,7 +66,7 @@ import {dismissRejectUseExplanation} from '@userActions/IOU/RejectMoneyRequest';
 import {setDeleteTransactionNavigateBackUrl} from '@userActions/Report';
 import CONST from '@src/CONST';
 import ONYXKEYS from '@src/ONYXKEYS';
-import ROUTES, {DYNAMIC_ROUTES} from '@src/ROUTES';
+import ROUTES from '@src/ROUTES';
 import SCREENS from '@src/SCREENS';
 import type {Transaction} from '@src/types/onyx';
 import ButtonWithDropdownMenu from './ButtonWithDropdownMenu';
@@ -522,15 +521,13 @@ function MoneyRequestHeaderSecondaryActions({reportID, onBackButtonPress}: Money
                 const iouType = isExpenseReport(parentReport) ? CONST.IOU.TYPE.SUBMIT : CONST.IOU.TYPE.TRACK;
                 if (shouldNavigateToUpgradePath && reportID) {
                     Navigation.navigate(
-                        createDynamicRoute(
-                            DYNAMIC_ROUTES.MONEY_REQUEST_UPGRADE.getRoute({
-                                action: CONST.IOU.ACTION.EDIT,
-                                iouType,
-                                transactionID: transaction.transactionID,
-                                reportID,
-                                upgradePath: CONST.UPGRADE_PATHS.REPORTS,
-                            }),
-                        ),
+                        ROUTES.MONEY_REQUEST_UPGRADE.getRoute({
+                            action: CONST.IOU.ACTION.EDIT,
+                            iouType,
+                            transactionID: transaction.transactionID,
+                            reportID,
+                            upgradePath: CONST.UPGRADE_PATHS.REPORTS,
+                        }),
                     );
                     return;
                 }
diff --git a/src/components/Navigation/QuickCreationActionsBar/index.tsx b/src/components/Navigation/QuickCreationActionsBar/index.tsx
index 1b7253be6e06..b48df3c493b0 100644
--- a/src/components/Navigation/QuickCreationActionsBar/index.tsx
+++ b/src/components/Navigation/QuickCreationActionsBar/index.tsx
@@ -17,7 +17,6 @@ import useThemeStyles from '@hooks/useThemeStyles';
 import {startDistanceRequest, startMoneyRequest} from '@libs/actions/IOU/MoneyRequest';
 import {createNewReport} from '@libs/actions/Report';
 import interceptAnonymousUser from '@libs/interceptAnonymousUser';
-import createDynamicRoute from '@libs/Navigation/helpers/dynamicRoutesUtils/createDynamicRoute';
 import getCreateReportRoute, {getReportsRootRoute, navigateToCreateReportWorkspaceSelection} from '@libs/Navigation/helpers/getCreateReportRoute';
 import Navigation from '@libs/Navigation/Navigation';
 import {openTravelDotLink} from '@libs/openTravelDotLink';
@@ -27,7 +26,7 @@ import {generateReportID, hasViolations as hasViolationsReportUtils} from '@libs
 import {shouldRestrictUserBillableActions} from '@libs/SubscriptionUtils';
 import CONST from '@src/CONST';
 import ONYXKEYS from '@src/ONYXKEYS';
-import ROUTES, {DYNAMIC_ROUTES} from '@src/ROUTES';
+import ROUTES from '@src/ROUTES';
 import {primaryLoginSelector} from '@src/selectors/Account';
 import type * as OnyxTypes from '@src/types/onyx';
 
@@ -132,15 +131,13 @@ function QuickCreationActionsBar() {
                     const freshReportID = generateReportID();
                     const freshTransactionID = generateReportID();
                     Navigation.navigate(
-                        createDynamicRoute(
-                            DYNAMIC_ROUTES.MONEY_REQUEST_UPGRADE.getRoute({
-                                action: CONST.IOU.ACTION.CREATE,
-                                iouType: CONST.IOU.TYPE.CREATE,
-                                transactionID: freshTransactionID,
-                                reportID: freshReportID,
-                                upgradePath: CONST.UPGRADE_PATHS.REPORTS,
-                            }),
-                        ),
+                        ROUTES.MONEY_REQUEST_UPGRADE.getRoute({
+                            action: CONST.IOU.ACTION.CREATE,
+                            iouType: CONST.IOU.TYPE.CREATE,
+                            transactionID: freshTransactionID,
+                            reportID: freshReportID,
+                            upgradePath: CONST.UPGRADE_PATHS.REPORTS,
+                        }),
                     );
                     return;
                 }
diff --git a/src/components/ReportActionItem/MoneyRequestView.tsx b/src/components/ReportActionItem/MoneyRequestView.tsx
index 3f569d589e51..9122a1255933 100644
--- a/src/components/ReportActionItem/MoneyRequestView.tsx
+++ b/src/components/ReportActionItem/MoneyRequestView.tsx
@@ -57,7 +57,6 @@ import DistanceRequestUtils from '@libs/DistanceRequestUtils';
 import getNonEmptyStringOnyxID from '@libs/getNonEmptyStringOnyxID';
 import {getRateFromMerchant} from '@libs/MergeTransactionUtils';
 import {isBillableEnabledOnPolicy, isSingleTransactionReport} from '@libs/MoneyRequestReportUtils';
-import createDynamicRoute from '@libs/Navigation/helpers/dynamicRoutesUtils/createDynamicRoute';
 import {hasEnabledOptions} from '@libs/OptionsListUtils';
 import Parser from '@libs/Parser';
 import {
@@ -131,7 +130,7 @@ import AnimatedEmptyStateBackground from '@pages/inbox/report/AnimatedEmptyState
 import CONST from '@src/CONST';
 import type {TranslationPaths} from '@src/languages/types';
 import ONYXKEYS from '@src/ONYXKEYS';
-import ROUTES, {DYNAMIC_ROUTES} from '@src/ROUTES';
+import ROUTES from '@src/ROUTES';
 import type * as OnyxTypes from '@src/types/onyx';
 import type {TransactionPendingFieldsKey} from '@src/types/onyx/Transaction';
 import {isEmptyObject} from '@src/types/utils/EmptyObject';
@@ -815,15 +814,13 @@ function MoneyRequestView({
                         if (isTrackExpense) {
                             if (shouldNavigateToUpgradePath && transactionThreadReport) {
                                 Navigation.navigate(
-                                    createDynamicRoute(
-                                        DYNAMIC_ROUTES.MONEY_REQUEST_UPGRADE.getRoute({
-                                            action: CONST.IOU.ACTION.EDIT,
-                                            iouType,
-                                            transactionID: transaction.transactionID,
-                                            reportID: transactionThreadReport?.reportID,
-                                            upgradePath: CONST.UPGRADE_PATHS.DISTANCE_RATES,
-                                        }),
-                                    ),
+                                    ROUTES.MONEY_REQUEST_UPGRADE.getRoute({
+                                        action: CONST.IOU.ACTION.EDIT,
+                                        iouType,
+                                        transactionID: transaction.transactionID,
+                                        reportID: transactionThreadReport?.reportID,
+                                        upgradePath: CONST.UPGRADE_PATHS.DISTANCE_RATES,
+                                    }),
                                 );
                                 return;
                             }
@@ -1121,33 +1118,41 @@ function MoneyRequestView({
                             onPress={() => {
                                 if (shouldNavigateToUpgradePath && transactionThreadReport) {
                                     Navigation.navigate(
-                                        createDynamicRoute(
-                                            DYNAMIC_ROUTES.MONEY_REQUEST_UPGRADE.getRoute({
-                                                action: CONST.IOU.ACTION.EDIT,
+                                        ROUTES.MONEY_REQUEST_UPGRADE.getRoute({
+                                            action: CONST.IOU.ACTION.EDIT,
+                                            iouType,
+                                            transactionID: transaction.transactionID,
+                                            reportID: transactionThreadReport?.reportID,
+                                            upgradePath: CONST.UPGRADE_PATHS.CATEGORIES,
+                                            backTo: ROUTES.MONEY_REQUEST_STEP_CATEGORY.getRoute(
+                                                CONST.IOU.ACTION.EDIT,
                                                 iouType,
-                                                transactionID: transaction.transactionID,
-                                                reportID: transactionThreadReport?.reportID,
-                                                upgradePath: CONST.UPGRADE_PATHS.CATEGORIES,
-                                            }),
-                                        ),
+                                                transaction.transactionID,
+                                                transactionThreadReport?.reportID,
+                                                Navigation.getActiveRoute(),
+                                            ),
+                                        }),
                                     );
                                 } else if (!policy && shouldSelectPolicy) {
                                     Navigation.navigate(
                                         ROUTES.SET_DEFAULT_WORKSPACE.getRoute(
-                                            createDynamicRoute(
-                                                DYNAMIC_ROUTES.MONEY_REQUEST_STEP_CATEGORY.getRoute(
-                                                    CONST.IOU.ACTION.EDIT,
-                                                    iouType,
-                                                    transaction.transactionID,
-                                                    transactionThreadReport?.reportID,
-                                                ),
+                                            ROUTES.MONEY_REQUEST_STEP_CATEGORY.getRoute(
+                                                CONST.IOU.ACTION.EDIT,
+                                                iouType,
+                                                transaction.transactionID,
+                                                transactionThreadReport?.reportID,
+                                                Navigation.getActiveRoute(),
                                             ),
                                         ),
                                     );
                                 } else {
                                     Navigation.navigate(
-                                        createDynamicRoute(
-                                            DYNAMIC_ROUTES.MONEY_REQUEST_STEP_CATEGORY.getRoute(CONST.IOU.ACTION.EDIT, iouType, transaction.transactionID, transactionThreadReport?.reportID),
+                                        ROUTES.MONEY_REQUEST_STEP_CATEGORY.getRoute(
+                                            CONST.IOU.ACTION.EDIT,
+                                            iouType,
+                                            transaction.transactionID,
+                                            transactionThreadReport?.reportID,
+                                            Navigation.getActiveRoute(),
                                         ),
                                     );
                                 }
@@ -1189,8 +1194,12 @@ function MoneyRequestView({
                                 }
 
                                 Navigation.navigate(
-                                    createDynamicRoute(
-                                        DYNAMIC_ROUTES.MONEY_REQUEST_STEP_TAX_RATE.getRoute(CONST.IOU.ACTION.EDIT, iouType, transaction.transactionID, transactionThreadReport?.reportID),
+                                    ROUTES.MONEY_REQUEST_STEP_TAX_RATE.getRoute(
+                                        CONST.IOU.ACTION.EDIT,
+                                        iouType,
+                                        transaction.transactionID,
+                                        transactionThreadReport?.reportID,
+                                        getReportRHPActiveRoute(),
                                     ),
                                 );
                             }}
@@ -1217,8 +1226,12 @@ function MoneyRequestView({
                                 }
 
                                 Navigation.navigate(
-                                    createDynamicRoute(
-                                        DYNAMIC_ROUTES.MONEY_REQUEST_STEP_TAX_AMOUNT.getRoute(CONST.IOU.ACTION.EDIT, iouType, transaction.transactionID, transactionThreadReport?.reportID),
+                                    ROUTES.MONEY_REQUEST_STEP_TAX_AMOUNT.getRoute(
+                                        CONST.IOU.ACTION.EDIT,
+                                        iouType,
+                                        transaction.transactionID,
+                                        transactionThreadReport?.reportID,
+                                        getReportRHPActiveRoute(),
                                     ),
                                 );
                             }}
@@ -1254,11 +1267,7 @@ function MoneyRequestView({
                             style={[styles.moneyRequestMenuItem]}
                             titleStyle={styles.flex1}
                             onPress={() => {
-                                Navigation.navigate(
-                                    createDynamicRoute(
-                                        DYNAMIC_ROUTES.MONEY_REQUEST_ATTENDEE.getRoute(CONST.IOU.ACTION.EDIT, iouType, transaction.transactionID, transactionThreadReport?.reportID),
-                                    ),
-                                );
+                                Navigation.navigate(ROUTES.MONEY_REQUEST_ATTENDEE.getRoute(CONST.IOU.ACTION.EDIT, iouType, transaction.transactionID, transactionThreadReport?.reportID));
                             }}
                             brickRoadIndicator={getErrorForField('attendees') ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR : undefined}
                             errorText={getErrorForField('attendees')}
@@ -1339,15 +1348,13 @@ function MoneyRequestView({
                                 }
                                 if (shouldNavigateToUpgradePath) {
                                     Navigation.navigate(
-                                        createDynamicRoute(
-                                            DYNAMIC_ROUTES.MONEY_REQUEST_UPGRADE.getRoute({
-                                                iouType,
-                                                action: CONST.IOU.ACTION.EDIT,
-                                                transactionID: transaction?.transactionID,
-                                                reportID: transactionThreadReport?.reportID,
-                                                upgradePath: CONST.UPGRADE_PATHS.REPORTS,
-                                            }),
-                                        ),
+                                        ROUTES.MONEY_REQUEST_UPGRADE.getRoute({
+                                            iouType,
+                                            action: CONST.IOU.ACTION.EDIT,
+                                            transactionID: transaction?.transactionID,
+                                            reportID: transactionThreadReport?.reportID,
+                                            upgradePath: CONST.UPGRADE_PATHS.REPORTS,
+                                        }),
                                     );
                                     return;
                                 }
diff --git a/src/components/Search/SearchPageHeader/SearchActionsBarCreateButton.tsx b/src/components/Search/SearchPageHeader/SearchActionsBarCreateButton.tsx
index eeafcf7f3065..13ccdacd59db 100644
--- a/src/components/Search/SearchPageHeader/SearchActionsBarCreateButton.tsx
+++ b/src/components/Search/SearchPageHeader/SearchActionsBarCreateButton.tsx
@@ -142,15 +142,13 @@ function SearchActionsBarCreateButton() {
                             const freshReportID = generateReportID();
                             const freshTransactionID = generateReportID();
                             Navigation.navigate(
-                                createDynamicRoute(
-                                    DYNAMIC_ROUTES.MONEY_REQUEST_UPGRADE.getRoute({
-                                        action: CONST.IOU.ACTION.CREATE,
-                                        iouType: CONST.IOU.TYPE.CREATE,
-                                        transactionID: freshTransactionID,
-                                        reportID: freshReportID,
-                                        upgradePath: CONST.UPGRADE_PATHS.REPORTS,
-                                    }),
-                                ),
+                                ROUTES.MONEY_REQUEST_UPGRADE.getRoute({
+                                    action: CONST.IOU.ACTION.CREATE,
+                                    iouType: CONST.IOU.TYPE.CREATE,
+                                    transactionID: freshTransactionID,
+                                    reportID: freshReportID,
+                                    upgradePath: CONST.UPGRADE_PATHS.REPORTS,
+                                }),
                             );
                             return;
                         }
diff --git a/src/hooks/useCreateReport.tsx b/src/hooks/useCreateReport.tsx
index 91e545b6aa5a..65df7e71255b 100644
--- a/src/hooks/useCreateReport.tsx
+++ b/src/hooks/useCreateReport.tsx
@@ -87,15 +87,13 @@ export default function useCreateReport({
                 const freshReportID = generateReportID();
                 const freshTransactionID = generateReportID();
                 Navigation.navigate(
-                    createDynamicRoute(
-                        DYNAMIC_ROUTES.MONEY_REQUEST_UPGRADE.getRoute({
-                            action: CONST.IOU.ACTION.CREATE,
-                            iouType: CONST.IOU.TYPE.CREATE,
-                            transactionID: freshTransactionID,
-                            reportID: freshReportID,
-                            upgradePath: CONST.UPGRADE_PATHS.REPORTS,
-                        }),
-                    ),
+                    ROUTES.MONEY_REQUEST_UPGRADE.getRoute({
+                        action: CONST.IOU.ACTION.CREATE,
+                        iouType: CONST.IOU.TYPE.CREATE,
+                        transactionID: freshTransactionID,
+                        reportID: freshReportID,
+                        upgradePath: CONST.UPGRADE_PATHS.REPORTS,
+                    }),
                 );
                 return;
             }
diff --git a/src/hooks/useParticipantSubmission.ts b/src/hooks/useParticipantSubmission.ts
index 751802e0cb01..63b59d7e8759 100644
--- a/src/hooks/useParticipantSubmission.ts
+++ b/src/hooks/useParticipantSubmission.ts
@@ -4,7 +4,6 @@ import {setTransactionReport} from '@libs/actions/Transaction';
 import {READ_COMMANDS} from '@libs/API/types';
 import DistanceRequestUtils from '@libs/DistanceRequestUtils';
 import HttpUtils from '@libs/HttpUtils';
-import createDynamicRoute from '@libs/Navigation/helpers/dynamicRoutesUtils/createDynamicRoute';
 import Navigation from '@libs/Navigation/Navigation';
 import {isPaidGroupPolicy} from '@libs/PolicyUtils';
 import {findSelfDMReportID, generateReportID, isInvoiceRoomWithID} from '@libs/ReportUtils';
@@ -23,7 +22,7 @@ import {createDraftWorkspace, generateDefaultWorkspaceName} from '@userActions/P
 import CONST from '@src/CONST';
 import type {IOUAction, IOUType} from '@src/CONST';
 import ONYXKEYS from '@src/ONYXKEYS';
-import ROUTES, {DYNAMIC_ROUTES} from '@src/ROUTES';
+import ROUTES from '@src/ROUTES';
 import {lastWorkspaceNumberSelector} from '@src/selectors/Policy';
 import type {Policy, Transaction} from '@src/types/onyx';
 import type {Participant} from '@src/types/onyx/IOU';
@@ -354,10 +353,7 @@ function useParticipantSubmission({
             }
             Navigation.setNavigationActionToMicrotaskQueue(() => {
                 if (isCategorizing) {
-                    const confirmationRoute = ROUTES.MONEY_REQUEST_STEP_CONFIRMATION.getRoute(action, CONST.IOU.TYPE.SUBMIT, initialTransactionID, expenseChatReportID, undefined, true);
-                    Navigation.navigate(
-                        createDynamicRoute(DYNAMIC_ROUTES.MONEY_REQUEST_STEP_CATEGORY.getRoute(action, CONST.IOU.TYPE.SUBMIT, initialTransactionID, expenseChatReportID), confirmationRoute),
-                    );
+                    Navigation.navigate(ROUTES.MONEY_REQUEST_STEP_CATEGORY.getRoute(action, CONST.IOU.TYPE.SUBMIT, initialTransactionID, expenseChatReportID));
                 } else {
                     Navigation.navigate(ROUTES.MONEY_REQUEST_STEP_CONFIRMATION.getRoute(action, CONST.IOU.TYPE.SUBMIT, initialTransactionID, expenseChatReportID, undefined, true));
                 }
@@ -376,7 +372,7 @@ function useParticipantSubmission({
         );
 
         const route = isCategorizing
-            ? createDynamicRoute(DYNAMIC_ROUTES.MONEY_REQUEST_STEP_CATEGORY.getRoute(action, iouType, initialTransactionID, selectedReportID.current || reportID), iouConfirmationPageRoute)
+            ? ROUTES.MONEY_REQUEST_STEP_CATEGORY.getRoute(action, iouType, initialTransactionID, selectedReportID.current || reportID, iouConfirmationPageRoute)
             : iouConfirmationPageRoute;
 
         KeyboardUtils.dismissKeyboardAndExecute(() => {
diff --git a/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx b/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx
index 094b8b7bf072..52b09cbe105d 100644
--- a/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx
+++ b/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx
@@ -174,9 +174,9 @@ const MoneyRequestModalStackNavigator = createModalStackNavigator<MoneyRequestNa
     [SCREENS.MONEY_REQUEST.STEP_CONFIRMATION]: () => require<ReactComponentModule>('../../../../pages/iou/request/step/IOURequestStepConfirmation').default,
     [SCREENS.MONEY_REQUEST.STEP_CONFIRMATION_VERIFY_ACCOUNT]: () => require<ReactComponentModule>('../../../../pages/iou/request/step/MoneyRequestStepConfirmationVerifyAccountPage').default,
     [SCREENS.MONEY_REQUEST.STEP_AMOUNT]: () => require<ReactComponentModule>('../../../../pages/iou/request/step/IOURequestStepAmount').default,
-    [SCREENS.MONEY_REQUEST.DYNAMIC_STEP_TAX_AMOUNT]: () => require<ReactComponentModule>('../../../../pages/iou/request/step/DynamicIOURequestStepTaxAmountPage').default,
-    [SCREENS.MONEY_REQUEST.DYNAMIC_STEP_TAX_RATE]: () => require<ReactComponentModule>('../../../../pages/iou/request/step/DynamicIOURequestStepTaxRatePage').default,
-    [SCREENS.MONEY_REQUEST.DYNAMIC_STEP_CATEGORY]: () => require<ReactComponentModule>('../../../../pages/iou/request/step/DynamicIOURequestStepCategoryPage').default,
+    [SCREENS.MONEY_REQUEST.STEP_TAX_AMOUNT]: () => require<ReactComponentModule>('../../../../pages/iou/request/step/IOURequestStepTaxAmountPage').default,
+    [SCREENS.MONEY_REQUEST.STEP_TAX_RATE]: () => require<ReactComponentModule>('../../../../pages/iou/request/step/IOURequestStepTaxRatePage').default,
+    [SCREENS.MONEY_REQUEST.STEP_CATEGORY]: () => require<ReactComponentModule>('../../../../pages/iou/request/step/IOURequestStepCategory').default,
     [SCREENS.MONEY_REQUEST.STEP_CATEGORY_CREATE]: () => require<ReactComponentModule>('../../../../pages/iou/request/step/IOURequestStepCategoryCreate').default,
     [SCREENS.MONEY_REQUEST.STEP_DATE]: () => require<ReactComponentModule>('../../../../pages/iou/request/step/IOURequestStepDate').default,
     [SCREENS.MONEY_REQUEST.STEP_DESCRIPTION]: () => require<ReactComponentModule>('../../../../pages/iou/request/step/IOURequestStepDescription').default,
@@ -200,9 +200,9 @@ const MoneyRequestModalStackNavigator = createModalStackNavigator<MoneyRequestNa
     [SCREENS.IOU_SEND.ADD_DEBIT_CARD]: () => require<ReactComponentModule>('../../../../pages/settings/Wallet/AddDebitCardPage').default,
     [SCREENS.IOU_SEND.ENABLE_PAYMENTS]: () => require<ReactComponentModule>('../../../../pages/EnablePayments/Pay/EnablePaymentsPage').default,
     [SCREENS.MONEY_REQUEST.STATE_SELECTOR]: () => require<ReactComponentModule>('../../../../pages/settings/Profile/PersonalDetails/StateSelectionPage').default,
-    [SCREENS.MONEY_REQUEST.DYNAMIC_STEP_ATTENDEES]: () => require<ReactComponentModule>('../../../../pages/iou/request/step/DynamicIOURequestStepAttendeesPage').default,
-    [SCREENS.MONEY_REQUEST.DYNAMIC_STEP_ACCOUNTANT]: () => require<ReactComponentModule>('../../../../pages/iou/request/step/DynamicIOURequestStepAccountantPage').default,
-    [SCREENS.MONEY_REQUEST.DYNAMIC_STEP_UPGRADE]: () => require<ReactComponentModule>('../../../../pages/iou/request/step/DynamicIOURequestStepUpgradePage').default,
+    [SCREENS.MONEY_REQUEST.STEP_ATTENDEES]: () => require<ReactComponentModule>('../../../../pages/iou/request/step/IOURequestStepAttendees').default,
+    [SCREENS.MONEY_REQUEST.STEP_ACCOUNTANT]: () => require<ReactComponentModule>('../../../../pages/iou/request/step/IOURequestStepAccountant').default,
+    [SCREENS.MONEY_REQUEST.STEP_UPGRADE]: () => require<ReactComponentModule>('../../../../pages/iou/request/step/IOURequestStepUpgrade').default,
     [SCREENS.MONEY_REQUEST.STEP_DESTINATION]: () => require<ReactComponentModule>('../../../../pages/iou/request/step/IOURequestStepDestination').default,
     [SCREENS.MONEY_REQUEST.STEP_TIME]: () => require<ReactComponentModule>('../../../../pages/iou/request/step/IOURequestStepTime').default,
     [SCREENS.MONEY_REQUEST.STEP_SUBRATE]: () => require<ReactComponentModule>('../../../../pages/iou/request/step/IOURequestStepSubrate').default,
diff --git a/src/libs/Navigation/linkingConfig/config.ts b/src/libs/Navigation/linkingConfig/config.ts
index f1e6742a8883..b6bff52d25a7 100644
--- a/src/libs/Navigation/linkingConfig/config.ts
+++ b/src/libs/Navigation/linkingConfig/config.ts
@@ -1751,7 +1751,7 @@ const config: LinkingOptions<RootNavigatorParamList>['config'] = {
                         [SCREENS.MONEY_REQUEST.STEP_REPORT]: ROUTES.MONEY_REQUEST_STEP_REPORT.route,
                         [SCREENS.MONEY_REQUEST.STEP_COMPANY_INFO]: ROUTES.MONEY_REQUEST_STEP_COMPANY_INFO.route,
                         [SCREENS.MONEY_REQUEST.STEP_AMOUNT]: ROUTES.MONEY_REQUEST_STEP_AMOUNT.route,
-                        [SCREENS.MONEY_REQUEST.DYNAMIC_STEP_CATEGORY]: DYNAMIC_ROUTES.MONEY_REQUEST_STEP_CATEGORY.path,
+                        [SCREENS.MONEY_REQUEST.STEP_CATEGORY]: ROUTES.MONEY_REQUEST_STEP_CATEGORY.route,
                         [SCREENS.MONEY_REQUEST.STEP_CATEGORY_CREATE]: ROUTES.MONEY_REQUEST_STEP_CATEGORY_CREATE.route,
                         [SCREENS.MONEY_REQUEST.STEP_CONFIRMATION]: ROUTES.MONEY_REQUEST_STEP_CONFIRMATION.route,
                         [SCREENS.MONEY_REQUEST.STEP_CONFIRMATION_VERIFY_ACCOUNT]: ROUTES.MONEY_REQUEST_STEP_CONFIRMATION_VERIFY_ACCOUNT.route,
@@ -1771,15 +1771,15 @@ const config: LinkingOptions<RootNavigatorParamList>['config'] = {
                         [SCREENS.MONEY_REQUEST.RECEIPT_VIEW]: ROUTES.MONEY_REQUEST_RECEIPT_VIEW.route,
                         [SCREENS.MONEY_REQUEST.STEP_TAG]: ROUTES.MONEY_REQUEST_STEP_TAG.route,
                         [SCREENS.MONEY_REQUEST.STEP_WAYPOINT]: ROUTES.MONEY_REQUEST_STEP_WAYPOINT.route,
-                        [SCREENS.MONEY_REQUEST.DYNAMIC_STEP_TAX_AMOUNT]: DYNAMIC_ROUTES.MONEY_REQUEST_STEP_TAX_AMOUNT.path,
-                        [SCREENS.MONEY_REQUEST.DYNAMIC_STEP_TAX_RATE]: DYNAMIC_ROUTES.MONEY_REQUEST_STEP_TAX_RATE.path,
+                        [SCREENS.MONEY_REQUEST.STEP_TAX_AMOUNT]: ROUTES.MONEY_REQUEST_STEP_TAX_AMOUNT.route,
+                        [SCREENS.MONEY_REQUEST.STEP_TAX_RATE]: ROUTES.MONEY_REQUEST_STEP_TAX_RATE.route,
                         [SCREENS.MONEY_REQUEST.STATE_SELECTOR]: {
                             path: ROUTES.MONEY_REQUEST_STATE_SELECTOR.route,
                             exact: true,
                         },
-                        [SCREENS.MONEY_REQUEST.DYNAMIC_STEP_ATTENDEES]: DYNAMIC_ROUTES.MONEY_REQUEST_ATTENDEE.path,
-                        [SCREENS.MONEY_REQUEST.DYNAMIC_STEP_ACCOUNTANT]: DYNAMIC_ROUTES.MONEY_REQUEST_ACCOUNTANT.path,
-                        [SCREENS.MONEY_REQUEST.DYNAMIC_STEP_UPGRADE]: DYNAMIC_ROUTES.MONEY_REQUEST_UPGRADE.path,
+                        [SCREENS.MONEY_REQUEST.STEP_ATTENDEES]: ROUTES.MONEY_REQUEST_ATTENDEE.route,
+                        [SCREENS.MONEY_REQUEST.STEP_ACCOUNTANT]: ROUTES.MONEY_REQUEST_ACCOUNTANT.route,
+                        [SCREENS.MONEY_REQUEST.STEP_UPGRADE]: ROUTES.MONEY_REQUEST_UPGRADE.route,
                         [SCREENS.MONEY_REQUEST.STEP_DESTINATION]: ROUTES.MONEY_REQUEST_STEP_DESTINATION.route,
                         [SCREENS.MONEY_REQUEST.STEP_TIME]: ROUTES.MONEY_REQUEST_STEP_TIME.route,
                         [SCREENS.MONEY_REQUEST.STEP_SUBRATE]: ROUTES.MONEY_REQUEST_STEP_SUBRATE.route,
diff --git a/src/libs/Navigation/types.ts b/src/libs/Navigation/types.ts
index 8419fbef5844..79fa978eca54 100644
--- a/src/libs/Navigation/types.ts
+++ b/src/libs/Navigation/types.ts
@@ -1904,12 +1904,14 @@ type MoneyRequestNavigatorParamList = {
         backTo: Routes;
         reportActionID: string;
     };
-    [SCREENS.MONEY_REQUEST.DYNAMIC_STEP_CATEGORY]: {
+    [SCREENS.MONEY_REQUEST.STEP_CATEGORY]: {
         action: IOUAction;
         iouType: Exclude<IOUType, typeof CONST.IOU.TYPE.REQUEST | typeof CONST.IOU.TYPE.SEND>;
         transactionID: string;
+        reportActionID: string;
         reportID: string;
-        reportActionID?: string;
+        // eslint-disable-next-line no-restricted-syntax -- `backTo` usages in this file are legacy. Do not add new `backTo` params to screens. See contributingGuides/NAVIGATION.md
+        backTo: Routes;
     };
     [SCREENS.MONEY_REQUEST.STEP_CATEGORY_CREATE]: {
         action: IOUAction;
@@ -1920,11 +1922,13 @@ type MoneyRequestNavigatorParamList = {
         // eslint-disable-next-line no-restricted-syntax -- backTo is needed to track where editing was initiated from (search/view or r/:reportID)
         backTo?: Routes;
     };
-    [SCREENS.MONEY_REQUEST.DYNAMIC_STEP_TAX_AMOUNT]: {
+    [SCREENS.MONEY_REQUEST.STEP_TAX_AMOUNT]: {
         action: IOUAction;
         iouType: Exclude<IOUType, typeof CONST.IOU.TYPE.REQUEST | typeof CONST.IOU.TYPE.SEND>;
         transactionID: string;
         reportID: string;
+        // eslint-disable-next-line no-restricted-syntax -- `backTo` usages in this file are legacy. Do not add new `backTo` params to screens. See contributingGuides/NAVIGATION.md
+        backTo: Routes;
     };
     [SCREENS.MONEY_REQUEST.STEP_TAG]: {
         action: IOUAction;
@@ -1936,11 +1940,13 @@ type MoneyRequestNavigatorParamList = {
         reportActionID: string;
         orderWeight: string;
     };
-    [SCREENS.MONEY_REQUEST.DYNAMIC_STEP_TAX_RATE]: {
+    [SCREENS.MONEY_REQUEST.STEP_TAX_RATE]: {
         action: IOUAction;
         iouType: Exclude<IOUType, typeof CONST.IOU.TYPE.REQUEST | typeof CONST.IOU.TYPE.SEND>;
         transactionID: string;
         reportID: string;
+        // eslint-disable-next-line no-restricted-syntax -- `backTo` usages in this file are legacy. Do not add new `backTo` params to screens. See contributingGuides/NAVIGATION.md
+        backTo: Routes;
     };
     [SCREENS.MONEY_REQUEST.STEP_WAYPOINT]: {
         iouType: IOUType;
@@ -2126,23 +2132,29 @@ type MoneyRequestNavigatorParamList = {
         /** ID of the expense report being rejected */
         reportID: string;
     };
-    [SCREENS.MONEY_REQUEST.DYNAMIC_STEP_ATTENDEES]: {
+    [SCREENS.MONEY_REQUEST.STEP_ATTENDEES]: {
         action: IOUAction;
         iouType: Exclude<IOUType, typeof CONST.IOU.TYPE.REQUEST | typeof CONST.IOU.TYPE.SEND>;
         transactionID: string;
         reportID: string;
+        // eslint-disable-next-line no-restricted-syntax -- `backTo` usages in this file are legacy. Do not add new `backTo` params to screens. See contributingGuides/NAVIGATION.md
+        backTo: Routes;
     };
-    [SCREENS.MONEY_REQUEST.DYNAMIC_STEP_ACCOUNTANT]: {
+    [SCREENS.MONEY_REQUEST.STEP_ACCOUNTANT]: {
         action: IOUAction;
         iouType: Exclude<IOUType, typeof CONST.IOU.TYPE.REQUEST | typeof CONST.IOU.TYPE.SEND>;
         transactionID: string;
         reportID: string;
+        // eslint-disable-next-line no-restricted-syntax -- `backTo` usages in this file are legacy. Do not add new `backTo` params to screens. See contributingGuides/NAVIGATION.md
+        backTo: Routes;
     };
-    [SCREENS.MONEY_REQUEST.DYNAMIC_STEP_UPGRADE]: {
+    [SCREENS.MONEY_REQUEST.STEP_UPGRADE]: {
         action: IOUAction;
         iouType: Exclude<IOUType, typeof CONST.IOU.TYPE.REQUEST | typeof CONST.IOU.TYPE.SEND>;
         transactionID: string;
         reportID: string;
+        // eslint-disable-next-line no-restricted-syntax -- `backTo` usages in this file are legacy. Do not add new `backTo` params to screens. See contributingGuides/NAVIGATION.md
+        backTo: Routes;
         upgradePath?: ValueOf<typeof CONST.UPGRADE_PATHS>;
         shouldSubmitExpense?: boolean;
     };
diff --git a/src/libs/ReportUtils.ts b/src/libs/ReportUtils.ts
index 587ed0d16947..bbddf966a7a5 100644
--- a/src/libs/ReportUtils.ts
+++ b/src/libs/ReportUtils.ts
@@ -11057,10 +11057,7 @@ function createDraftWorkspaceAndNavigateToConfirmationScreen(
     ]);
     setMoneyRequestReportID(transactionID, expenseChatReportID);
     if (isCategorizing) {
-        const confirmationRoute = ROUTES.MONEY_REQUEST_STEP_CONFIRMATION.getRoute(actionName, CONST.IOU.TYPE.SUBMIT, transactionID, expenseChatReportID, undefined, true);
-        Navigation.navigate(
-            createDynamicRoute(DYNAMIC_ROUTES.MONEY_REQUEST_STEP_CATEGORY.getRoute(actionName, CONST.IOU.TYPE.SUBMIT, transactionID, expenseChatReportID), confirmationRoute),
-        );
+        Navigation.navigate(ROUTES.MONEY_REQUEST_STEP_CATEGORY.getRoute(actionName, CONST.IOU.TYPE.SUBMIT, transactionID, expenseChatReportID));
     } else {
         Navigation.navigate(ROUTES.MONEY_REQUEST_STEP_CONFIRMATION.getRoute(actionName, CONST.IOU.TYPE.SUBMIT, transactionID, expenseChatReportID, undefined, true));
     }
@@ -11185,10 +11182,7 @@ function createDraftTransactionAndNavigateToParticipantSelector({
                 },
             ]);
             if (policyExpenseReportID) {
-                const confirmationRoute = ROUTES.MONEY_REQUEST_STEP_CONFIRMATION.getRoute(actionName, CONST.IOU.TYPE.SUBMIT, transactionID, policyExpenseReportID, undefined, true);
-                Navigation.navigate(
-                    createDynamicRoute(DYNAMIC_ROUTES.MONEY_REQUEST_STEP_CATEGORY.getRoute(actionName, CONST.IOU.TYPE.SUBMIT, transactionID, policyExpenseReportID), confirmationRoute),
-                );
+                Navigation.navigate(ROUTES.MONEY_REQUEST_STEP_CATEGORY.getRoute(actionName, CONST.IOU.TYPE.SUBMIT, transactionID, policyExpenseReportID));
             } else {
                 Log.warn('policyExpenseReportID is not valid during expense categorizing');
             }
@@ -11196,16 +11190,15 @@ function createDraftTransactionAndNavigateToParticipantSelector({
         }
         if (filteredPoliciesCount === 0 || filteredPoliciesCount > 1) {
             Navigation.navigate(
-                createDynamicRoute(
-                    DYNAMIC_ROUTES.MONEY_REQUEST_UPGRADE.getRoute({
-                        action: actionName,
-                        iouType: CONST.IOU.TYPE.SUBMIT,
-                        transactionID,
-                        reportID,
-                        upgradePath: actionName === CONST.IOU.ACTION.CATEGORIZE ? CONST.UPGRADE_PATHS.CATEGORIES : '',
-                        shouldSubmitExpense: true,
-                    }),
-                ),
+                ROUTES.MONEY_REQUEST_UPGRADE.getRoute({
+                    action: actionName,
+                    iouType: CONST.IOU.TYPE.SUBMIT,
+                    transactionID,
+                    reportID,
+                    backTo: '',
+                    upgradePath: actionName === CONST.IOU.ACTION.CATEGORIZE ? CONST.UPGRADE_PATHS.CATEGORIES : '',
+                    shouldSubmitExpense: true,
+                }),
             );
             return;
         }
@@ -11223,10 +11216,7 @@ function createDraftTransactionAndNavigateToParticipantSelector({
             },
         ]);
         if (policyExpenseReportID) {
-            const confirmationRoute = ROUTES.MONEY_REQUEST_STEP_CONFIRMATION.getRoute(actionName, CONST.IOU.TYPE.SUBMIT, transactionID, policyExpenseReportID, undefined, true);
-            Navigation.navigate(
-                createDynamicRoute(DYNAMIC_ROUTES.MONEY_REQUEST_STEP_CATEGORY.getRoute(actionName, CONST.IOU.TYPE.SUBMIT, transactionID, policyExpenseReportID), confirmationRoute),
-            );
+            Navigation.navigate(ROUTES.MONEY_REQUEST_STEP_CATEGORY.getRoute(actionName, CONST.IOU.TYPE.SUBMIT, transactionID, policyExpenseReportID));
         } else {
             Log.warn('policyExpenseReportID is not valid during expense categorizing');
         }
@@ -11234,7 +11224,7 @@ function createDraftTransactionAndNavigateToParticipantSelector({
     }
 
     if (actionName === CONST.IOU.ACTION.SHARE) {
-        Navigation.navigate(createDynamicRoute(DYNAMIC_ROUTES.MONEY_REQUEST_ACCOUNTANT.getRoute(actionName, CONST.IOU.TYPE.SUBMIT, transactionID, reportID), Navigation.getActiveRoute()));
+        Navigation.navigate(ROUTES.MONEY_REQUEST_ACCOUNTANT.getRoute(actionName, CONST.IOU.TYPE.SUBMIT, transactionID, reportID, Navigation.getActiveRoute()));
         return;
     }
 
diff --git a/src/pages/Search/SearchTransactionsChangeReport.tsx b/src/pages/Search/SearchTransactionsChangeReport.tsx
index 6a2a8f0eb190..de20d2bc120a 100644
--- a/src/pages/Search/SearchTransactionsChangeReport.tsx
+++ b/src/pages/Search/SearchTransactionsChangeReport.tsx
@@ -140,15 +140,13 @@ function SearchTransactionsChangeReport() {
             const firstTransactionID = selectedTransactionsKeys.at(0);
             if (firstTransactionID) {
                 Navigation.navigate(
-                    createDynamicRoute(
-                        DYNAMIC_ROUTES.MONEY_REQUEST_UPGRADE.getRoute({
-                            action: CONST.IOU.ACTION.EDIT,
-                            iouType: CONST.IOU.TYPE.SUBMIT,
-                            transactionID: firstTransactionID,
-                            reportID: selectedTransactions[firstTransactionID]?.reportID ?? CONST.REPORT.UNREPORTED_REPORT_ID,
-                            upgradePath: CONST.UPGRADE_PATHS.REPORTS,
-                        }),
-                    ),
+                    ROUTES.MONEY_REQUEST_UPGRADE.getRoute({
+                        action: CONST.IOU.ACTION.EDIT,
+                        iouType: CONST.IOU.TYPE.SUBMIT,
+                        transactionID: firstTransactionID,
+                        reportID: selectedTransactions[firstTransactionID]?.reportID ?? CONST.REPORT.UNREPORTED_REPORT_ID,
+                        upgradePath: CONST.UPGRADE_PATHS.REPORTS,
+                    }),
                 );
             }
             return;
@@ -160,15 +158,13 @@ function SearchTransactionsChangeReport() {
         }
         if (!policyForMovingExpensesID) {
             Navigation.navigate(
-                createDynamicRoute(
-                    DYNAMIC_ROUTES.MONEY_REQUEST_UPGRADE.getRoute({
-                        action: CONST.IOU.ACTION.CREATE,
-                        iouType: CONST.IOU.TYPE.CREATE,
-                        transactionID: generateReportID(),
-                        reportID: generateReportID(),
-                        upgradePath: CONST.UPGRADE_PATHS.REPORTS,
-                    }),
-                ),
+                ROUTES.MONEY_REQUEST_UPGRADE.getRoute({
+                    action: CONST.IOU.ACTION.CREATE,
+                    iouType: CONST.IOU.TYPE.CREATE,
+                    transactionID: generateReportID(),
+                    reportID: generateReportID(),
+                    upgradePath: CONST.UPGRADE_PATHS.REPORTS,
+                }),
             );
             return;
         }
diff --git a/src/pages/iou/SplitExpenseEditPage.tsx b/src/pages/iou/SplitExpenseEditPage.tsx
index b71687aaed46..a1aab1bf4f9b 100644
--- a/src/pages/iou/SplitExpenseEditPage.tsx
+++ b/src/pages/iou/SplitExpenseEditPage.tsx
@@ -30,7 +30,6 @@ import {openPolicyTagsPage} from '@libs/actions/Policy/Tag';
 import {getDecodedLeafCategoryName, isCategoryDescriptionRequired, isCategoryMissing} from '@libs/CategoryUtils';
 import DistanceRequestUtils from '@libs/DistanceRequestUtils';
 import getNonEmptyStringOnyxID from '@libs/getNonEmptyStringOnyxID';
-import createDynamicRoute from '@libs/Navigation/helpers/dynamicRoutesUtils/createDynamicRoute';
 import Navigation from '@libs/Navigation/Navigation';
 import type {PlatformStackScreenProps} from '@libs/Navigation/PlatformStackNavigation/types';
 import type {SplitExpenseParamList} from '@libs/Navigation/types';
@@ -45,7 +44,7 @@ import {getTagVisibility, hasEnabledTags} from '@libs/TagsOptionsListUtils';
 import {getDistanceInMeters, getRateID, getTag, getTagForDisplay, isDistanceRequest, isManualDistanceRequest, isOdometerDistanceRequest} from '@libs/TransactionUtils';
 import CONST from '@src/CONST';
 import ONYXKEYS from '@src/ONYXKEYS';
-import ROUTES, {DYNAMIC_ROUTES} from '@src/ROUTES';
+import ROUTES from '@src/ROUTES';
 import type SCREENS from '@src/SCREENS';
 import {isEmptyObject} from '@src/types/utils/EmptyObject';
 
@@ -271,15 +270,13 @@ function SplitExpenseEditPage({route}: SplitExpensePageProps) {
                     // up the same SPLIT_TRANSACTION_DRAFT this screen reads from (see line 57 above).
                     if (isSelfDMSplit && !effectivePolicy && !hasAnyPaidWorkspace && reportID) {
                         Navigation.navigate(
-                            createDynamicRoute(
-                                DYNAMIC_ROUTES.MONEY_REQUEST_UPGRADE.getRoute({
-                                    action: CONST.IOU.ACTION.EDIT,
-                                    iouType: CONST.IOU.TYPE.SPLIT_EXPENSE,
-                                    transactionID: CONST.IOU.OPTIMISTIC_TRANSACTION_ID,
-                                    reportID,
-                                    upgradePath: CONST.UPGRADE_PATHS.DISTANCE_RATES,
-                                }),
-                            ),
+                            ROUTES.MONEY_REQUEST_UPGRADE.getRoute({
+                                action: CONST.IOU.ACTION.EDIT,
+                                iouType: CONST.IOU.TYPE.SPLIT_EXPENSE,
+                                transactionID: CONST.IOU.OPTIMISTIC_TRANSACTION_ID,
+                                reportID,
+                                upgradePath: CONST.UPGRADE_PATHS.DISTANCE_RATES,
+                            }),
                         );
                         return;
                     }
@@ -338,25 +335,23 @@ function SplitExpenseEditPage({route}: SplitExpensePageProps) {
                                 numberOfLinesTitle={2}
                                 rightLabel={isCategoryRequired ? translate('common.required') : ''}
                                 onPress={() => {
-                                    const categoryRoute = createDynamicRoute(
-                                        DYNAMIC_ROUTES.MONEY_REQUEST_STEP_CATEGORY.getRoute(
-                                            CONST.IOU.ACTION.EDIT,
-                                            CONST.IOU.TYPE.SPLIT_EXPENSE,
-                                            CONST.IOU.OPTIMISTIC_TRANSACTION_ID,
-                                            reportID,
-                                        ),
+                                    const categoryRoute = ROUTES.MONEY_REQUEST_STEP_CATEGORY.getRoute(
+                                        CONST.IOU.ACTION.EDIT,
+                                        CONST.IOU.TYPE.SPLIT_EXPENSE,
+                                        CONST.IOU.OPTIMISTIC_TRANSACTION_ID,
+                                        reportID,
+                                        Navigation.getActiveRoute(),
                                     );
                                     if (shouldNavigateToUpgradePath) {
                                         Navigation.navigate(
-                                            createDynamicRoute(
-                                                DYNAMIC_ROUTES.MONEY_REQUEST_UPGRADE.getRoute({
-                                                    action: CONST.IOU.ACTION.EDIT,
-                                                    iouType: CONST.IOU.TYPE.SPLIT_EXPENSE,
-                                                    transactionID: CONST.IOU.OPTIMISTIC_TRANSACTION_ID,
-                                                    reportID,
-                                                    upgradePath: CONST.UPGRADE_PATHS.CATEGORIES,
-                                                }),
-                                            ),
+                                            ROUTES.MONEY_REQUEST_UPGRADE.getRoute({
+                                                action: CONST.IOU.ACTION.EDIT,
+                                                iouType: CONST.IOU.TYPE.SPLIT_EXPENSE,
+                                                transactionID: CONST.IOU.OPTIMISTIC_TRANSACTION_ID,
+                                                reportID,
+                                                upgradePath: CONST.UPGRADE_PATHS.CATEGORIES,
+                                                backTo: categoryRoute,
+                                            }),
                                         );
                                         return;
                                     }
diff --git a/src/pages/iou/request/step/DynamicIOURequestStepAccountantPage.tsx b/src/pages/iou/request/step/IOURequestStepAccountant.tsx
similarity index 82%
rename from src/pages/iou/request/step/DynamicIOURequestStepAccountantPage.tsx
rename to src/pages/iou/request/step/IOURequestStepAccountant.tsx
index a944b4ec531f..b5cc69def42a 100644
--- a/src/pages/iou/request/step/DynamicIOURequestStepAccountantPage.tsx
+++ b/src/pages/iou/request/step/IOURequestStepAccountant.tsx
@@ -2,7 +2,6 @@ import {activeAdminPoliciesSelector} from '@selectors/Policy';
 import React from 'react';
 import type {OnyxCollection} from 'react-native-onyx';
 import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails';
-import useDynamicBackPath from '@hooks/useDynamicBackPath';
 import useLastWorkspaceNumber from '@hooks/useLastWorkspaceNumber';
 import useLocalize from '@hooks/useLocalize';
 import useOnyx from '@hooks/useOnyx';
@@ -13,7 +12,7 @@ import {createDraftWorkspaceAndNavigateToConfirmationScreen} from '@libs/ReportU
 import MoneyRequestAccountantSelector from '@pages/iou/request/MoneyRequestAccountantSelector';
 import CONST from '@src/CONST';
 import ONYXKEYS from '@src/ONYXKEYS';
-import ROUTES, {DYNAMIC_ROUTES} from '@src/ROUTES';
+import ROUTES from '@src/ROUTES';
 import type SCREENS from '@src/SCREENS';
 import type {Policy} from '@src/types/onyx';
 import type {Accountant} from '@src/types/onyx/IOU';
@@ -21,20 +20,19 @@ import StepScreenWrapper from './StepScreenWrapper';
 import withWritableReportOrNotFound from './withWritableReportOrNotFound';
 import type {WithWritableReportOrNotFoundProps} from './withWritableReportOrNotFound';
 
-type DynamicIOURequestStepAccountantPageProps = WithWritableReportOrNotFoundProps<typeof SCREENS.MONEY_REQUEST.DYNAMIC_STEP_ACCOUNTANT>;
+type IOURequestStepAccountantProps = WithWritableReportOrNotFoundProps<typeof SCREENS.MONEY_REQUEST.STEP_ACCOUNTANT>;
 
-function DynamicIOURequestStepAccountantPage({
+function IOURequestStepAccountant({
     route: {
-        params: {transactionID, reportID, iouType, action},
+        params: {transactionID, reportID, iouType, backTo, action},
     },
-}: DynamicIOURequestStepAccountantPageProps) {
+}: IOURequestStepAccountantProps) {
     const {translate} = useLocalize();
     const {accountID, login, email = '', localCurrencyCode} = useCurrentUserPersonalDetails();
     const selector = (policies: OnyxCollection<Policy>) => activeAdminPoliciesSelector(policies, login ?? '');
     const [adminPolicies] = useOnyx(ONYXKEYS.COLLECTION.POLICY, {selector});
     const [introSelected] = useOnyx(ONYXKEYS.NVP_INTRO_SELECTED);
     const lastWorkspaceNumber = useLastWorkspaceNumber();
-    const backPath = useDynamicBackPath(DYNAMIC_ROUTES.MONEY_REQUEST_ACCOUNTANT.path);
 
     const setAccountant = (accountant: Accountant) => {
         setMoneyRequestAccountant(transactionID, accountant, true);
@@ -60,7 +58,7 @@ function DynamicIOURequestStepAccountantPage({
     };
 
     const navigateBack = () => {
-        Navigation.goBack(backPath);
+        Navigation.goBack(backTo);
     };
 
     return (
@@ -68,7 +66,7 @@ function DynamicIOURequestStepAccountantPage({
             headerTitle={translate('iou.whoIsYourAccountant')}
             onBackButtonPress={navigateBack}
             shouldShowWrapper
-            testID="DynamicIOURequestStepAccountantPage"
+            testID="IOURequestStepAccountant"
         >
             <MoneyRequestAccountantSelector
                 onFinish={navigateToNextStep}
@@ -79,4 +77,4 @@ function DynamicIOURequestStepAccountantPage({
     );
 }
 
-export default withWritableReportOrNotFound(DynamicIOURequestStepAccountantPage);
+export default withWritableReportOrNotFound(IOURequestStepAccountant);
diff --git a/src/pages/iou/request/step/DynamicIOURequestStepAttendeesPage.tsx b/src/pages/iou/request/step/IOURequestStepAttendees.tsx
similarity index 90%
rename from src/pages/iou/request/step/DynamicIOURequestStepAttendeesPage.tsx
rename to src/pages/iou/request/step/IOURequestStepAttendees.tsx
index 4b5e2f516d33..b09435894918 100644
--- a/src/pages/iou/request/step/DynamicIOURequestStepAttendeesPage.tsx
+++ b/src/pages/iou/request/step/IOURequestStepAttendees.tsx
@@ -2,7 +2,6 @@ import {deepEqual} from 'fast-equals';
 import React, {useCallback, useState} from 'react';
 import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails';
 import useDelegateAccountID from '@hooks/useDelegateAccountID';
-import useDynamicBackPath from '@hooks/useDynamicBackPath';
 import useLocalize from '@hooks/useLocalize';
 import useNetwork from '@hooks/useNetwork';
 import useOnyx from '@hooks/useOnyx';
@@ -19,18 +18,17 @@ import {getOriginalAttendees} from '@libs/TransactionUtils';
 import MoneyRequestAttendeeSelector from '@pages/iou/request/MoneyRequestAttendeeSelector';
 import CONST from '@src/CONST';
 import ONYXKEYS from '@src/ONYXKEYS';
-import {DYNAMIC_ROUTES} from '@src/ROUTES';
 import type SCREENS from '@src/SCREENS';
 import type {Attendee} from '@src/types/onyx/IOU';
 import StepScreenWrapper from './StepScreenWrapper';
 import type {WithWritableReportOrNotFoundProps} from './withWritableReportOrNotFound';
 import withWritableReportOrNotFound from './withWritableReportOrNotFound';
 
-type IOURequestStepAttendeesProps = WithWritableReportOrNotFoundProps<typeof SCREENS.MONEY_REQUEST.DYNAMIC_STEP_ATTENDEES>;
+type IOURequestStepAttendeesProps = WithWritableReportOrNotFoundProps<typeof SCREENS.MONEY_REQUEST.STEP_ATTENDEES>;
 
-function DynamicIOURequestStepAttendeesPage({
+function IOURequestStepAttendees({
     route: {
-        params: {transactionID, reportID, iouType, action},
+        params: {transactionID, reportID, iouType, backTo, action},
     },
 }: IOURequestStepAttendeesProps) {
     const currentUserPersonalDetails = useCurrentUserPersonalDetails();
@@ -55,7 +53,6 @@ function DynamicIOURequestStepAttendeesPage({
     const delegateAccountID = useDelegateAccountID();
     const {isBetaEnabled} = usePermissions();
     const isASAPSubmitBetaEnabled = isBetaEnabled(CONST.BETAS.ASAP_SUBMIT);
-    const backPath = useDynamicBackPath(DYNAMIC_ROUTES.MONEY_REQUEST_ATTENDEE.path);
     const {isOffline} = useNetwork();
 
     const saveAttendees = useCallback(() => {
@@ -85,10 +82,11 @@ function DynamicIOURequestStepAttendeesPage({
             }
         }
 
-        Navigation.goBack(backPath);
+        Navigation.goBack(backTo);
     }, [
         attendees,
         previousAttendees,
+        backTo,
         transactionID,
         isEditing,
         report,
@@ -103,11 +101,10 @@ function DynamicIOURequestStepAttendeesPage({
         parentReportNextStep,
         isOffline,
         delegateAccountID,
-        backPath,
     ]);
 
     const navigateBack = () => {
-        Navigation.goBack(backPath);
+        Navigation.goBack(backTo);
     };
 
     return (
@@ -115,7 +112,7 @@ function DynamicIOURequestStepAttendeesPage({
             headerTitle={translate('iou.attendees')}
             onBackButtonPress={navigateBack}
             shouldShowWrapper
-            testID="DynamicIOURequestStepAttendeesPage"
+            testID="IOURequestStepAttendees"
         >
             <MoneyRequestAttendeeSelector
                 onFinish={saveAttendees}
@@ -128,4 +125,4 @@ function DynamicIOURequestStepAttendeesPage({
     );
 }
 
-export default withWritableReportOrNotFound(DynamicIOURequestStepAttendeesPage);
+export default withWritableReportOrNotFound(IOURequestStepAttendees);
diff --git a/src/pages/iou/request/step/DynamicIOURequestStepCategoryPage.tsx b/src/pages/iou/request/step/IOURequestStepCategory.tsx
similarity index 90%
rename from src/pages/iou/request/step/DynamicIOURequestStepCategoryPage.tsx
rename to src/pages/iou/request/step/IOURequestStepCategory.tsx
index f532394d851e..ec838d8580bb 100644
--- a/src/pages/iou/request/step/DynamicIOURequestStepCategoryPage.tsx
+++ b/src/pages/iou/request/step/IOURequestStepCategory.tsx
@@ -12,7 +12,6 @@ import type {ListItem} from '@components/SelectionList/types';
 import WorkspaceEmptyStateSection from '@components/WorkspaceEmptyStateSection';
 import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails';
 import useDelegateAccountID from '@hooks/useDelegateAccountID';
-import useDynamicBackPath from '@hooks/useDynamicBackPath';
 import {useMemoizedLazyExpensifyIcons, useMemoizedLazyIllustrations} from '@hooks/useLazyAsset';
 import useLocalize from '@hooks/useLocalize';
 import useNetwork from '@hooks/useNetwork';
@@ -39,7 +38,7 @@ import type {SkeletonSpanReasonAttributes} from '@libs/telemetry/useSkeletonSpan
 import {getRequestType} from '@libs/TransactionUtils';
 import CONST from '@src/CONST';
 import ONYXKEYS from '@src/ONYXKEYS';
-import ROUTES, {DYNAMIC_ROUTES} from '@src/ROUTES';
+import ROUTES from '@src/ROUTES';
 import type SCREENS from '@src/SCREENS';
 import StepScreenWrapper from './StepScreenWrapper';
 import type {WithFullTransactionOrNotFoundProps} from './withFullTransactionOrNotFound';
@@ -47,14 +46,17 @@ import withFullTransactionOrNotFound from './withFullTransactionOrNotFound';
 import type {WithWritableReportOrNotFoundProps} from './withWritableReportOrNotFound';
 import withWritableReportOrNotFound from './withWritableReportOrNotFound';
 
-type IOURequestStepCategoryProps = WithWritableReportOrNotFoundProps<typeof SCREENS.MONEY_REQUEST.DYNAMIC_STEP_CATEGORY> &
-    WithFullTransactionOrNotFoundProps<typeof SCREENS.MONEY_REQUEST.DYNAMIC_STEP_CATEGORY>;
-
-function DynamicIOURequestStepCategoryPage({report: reportReal, reportDraft, route, transaction}: IOURequestStepCategoryProps) {
-    const {
-        params: {transactionID, action, iouType, reportActionID, reportID: routeReportID},
-    } = route;
+type IOURequestStepCategoryProps = WithWritableReportOrNotFoundProps<typeof SCREENS.MONEY_REQUEST.STEP_CATEGORY> &
+    WithFullTransactionOrNotFoundProps<typeof SCREENS.MONEY_REQUEST.STEP_CATEGORY>;
 
+function IOURequestStepCategory({
+    report: reportReal,
+    reportDraft,
+    route: {
+        params: {transactionID, backTo, action, iouType, reportActionID, reportID: routeReportID},
+    },
+    transaction,
+}: IOURequestStepCategoryProps) {
     const styles = useThemeStyles();
     const {translate} = useLocalize();
     const illustrations = useMemoizedLazyIllustrations(['EmptyStateExpenses']);
@@ -95,8 +97,6 @@ function DynamicIOURequestStepCategoryPage({report: reportReal, reportDraft, rou
     const isASAPSubmitBetaEnabled = isBetaEnabled(CONST.BETAS.ASAP_SUBMIT);
 
     const categoryForDisplay = isCategoryMissing(transactionCategory) ? '' : transactionCategory;
-    const backPath = useDynamicBackPath(DYNAMIC_ROUTES.MONEY_REQUEST_STEP_CATEGORY.path);
-    const shouldReturnToPreviousScreen = backPath !== ROUTES.HOME;
 
     const canCreateCategoryInSitu = isPolicyAdmin(policy) && !hasAccountingConnections(policy) && !!policy?.areCategoriesEnabled;
 
@@ -110,7 +110,7 @@ function DynamicIOURequestStepCategoryPage({report: reportReal, reportDraft, rou
                       if (!policyID || !reportID) {
                           return;
                       }
-                      Navigation.navigate(ROUTES.MONEY_REQUEST_STEP_CATEGORY_CREATE.getRoute(action, iouType, transactionID, reportID, reportActionID, Navigation.getActiveRoute()));
+                      Navigation.navigate(ROUTES.MONEY_REQUEST_STEP_CATEGORY_CREATE.getRoute(action, iouType, transactionID, reportID, reportActionID, backTo));
                   },
               },
           ]
@@ -147,7 +147,7 @@ function DynamicIOURequestStepCategoryPage({report: reportReal, reportDraft, rou
     }, [policyID]);
 
     const navigateBack = () => {
-        Navigation.goBack(backPath);
+        Navigation.goBack(backTo);
     };
 
     const updateCategory = (category: ListItem) => {
@@ -187,7 +187,7 @@ function DynamicIOURequestStepCategoryPage({report: reportReal, reportDraft, rou
 
         setMoneyRequestCategory(transactionID, updatedCategory, policy);
 
-        if (action === CONST.IOU.ACTION.CATEGORIZE && !shouldReturnToPreviousScreen) {
+        if (action === CONST.IOU.ACTION.CATEGORIZE && !backTo) {
             if (report?.reportID) {
                 Navigation.navigate(ROUTES.MONEY_REQUEST_STEP_CONFIRMATION.getRoute(action, iouType, transactionID, report.reportID));
             }
@@ -204,7 +204,7 @@ function DynamicIOURequestStepCategoryPage({report: reportReal, reportDraft, rou
             shouldShowWrapper
             shouldShowNotFoundPage={shouldShowNotFoundPage}
             shouldShowOfflineIndicator={policyCategories !== undefined}
-            testID="DynamicIOURequestStepCategoryPage"
+            testID="IOURequestStepCategory"
             shouldEnableKeyboardAvoidingView={false}
             threeDotsMenuItems={createCategoryMenuItems}
             shouldMinimizeMenuButton
@@ -241,7 +241,12 @@ function DynamicIOURequestStepCategoryPage({report: reportReal, reportDraft, rou
                                         enablePolicyCategories({...policyData, categories: policyCategories}, true, false);
                                     }
                                     InteractionManager.runAfterInteractions(() => {
-                                        Navigation.navigate(ROUTES.SETTINGS_CATEGORIES_ROOT.getRoute(policyID, Navigation.getActiveRoute()));
+                                        Navigation.navigate(
+                                            ROUTES.SETTINGS_CATEGORIES_ROOT.getRoute(
+                                                policyID,
+                                                ROUTES.MONEY_REQUEST_STEP_CATEGORY.getRoute(action, iouType, transactionID, report.reportID, backTo, reportActionID),
+                                            ),
+                                        );
                                     });
                                 }}
                                 text={translate('workspace.categories.editCategories')}
@@ -263,6 +268,7 @@ function DynamicIOURequestStepCategoryPage({report: reportReal, reportDraft, rou
     );
 }
 
-const DynamicIOURequestStepCategoryPageWithFullTransactionOrNotFound = withFullTransactionOrNotFound(DynamicIOURequestStepCategoryPage);
-const DynamicIOURequestStepCategoryPageWithWritableReportOrNotFound = withWritableReportOrNotFound(DynamicIOURequestStepCategoryPageWithFullTransactionOrNotFound);
-export default DynamicIOURequestStepCategoryPageWithWritableReportOrNotFound;
+const IOURequestStepCategoryWithFullTransactionOrNotFound = withFullTransactionOrNotFound(IOURequestStepCategory);
+
+const IOURequestStepCategoryWithWritableReportOrNotFound = withWritableReportOrNotFound(IOURequestStepCategoryWithFullTransactionOrNotFound);
+export default IOURequestStepCategoryWithWritableReportOrNotFound;
diff --git a/src/pages/iou/request/step/IOURequestStepCategoryCreate.tsx b/src/pages/iou/request/step/IOURequestStepCategoryCreate.tsx
index 9e6f7ee5ed29..b9cb603d444b 100644
--- a/src/pages/iou/request/step/IOURequestStepCategoryCreate.tsx
+++ b/src/pages/iou/request/step/IOURequestStepCategoryCreate.tsx
@@ -35,7 +35,7 @@ function IOURequestStepCategoryCreate({
     report: reportReal,
     reportDraft,
     route: {
-        params: {transactionID, action, iouType, reportID, backTo},
+        params: {transactionID, action, iouType, reportID, reportActionID, backTo},
     },
     transaction,
 }: IOURequestStepCategoryCreateProps) {
@@ -163,7 +163,7 @@ function IOURequestStepCategoryCreate({
         >
             <StepScreenWrapper
                 headerTitle={translate('workspace.categories.addCategory')}
-                onBackButtonPress={() => Navigation.goBack(backTo)}
+                onBackButtonPress={() => Navigation.goBack(ROUTES.MONEY_REQUEST_STEP_CATEGORY.getRoute(action, iouType, transactionID, reportID, backTo, reportActionID))}
                 shouldShowWrapper
                 testID="IOURequestStepCategoryCreate"
             >
diff --git a/src/pages/iou/request/step/DynamicIOURequestStepTaxAmountPage.tsx b/src/pages/iou/request/step/IOURequestStepTaxAmountPage.tsx
similarity index 88%
rename from src/pages/iou/request/step/DynamicIOURequestStepTaxAmountPage.tsx
rename to src/pages/iou/request/step/IOURequestStepTaxAmountPage.tsx
index 476f7e12658c..a9aa927413d5 100644
--- a/src/pages/iou/request/step/DynamicIOURequestStepTaxAmountPage.tsx
+++ b/src/pages/iou/request/step/IOURequestStepTaxAmountPage.tsx
@@ -4,7 +4,6 @@ import type {OnyxEntry} from 'react-native-onyx';
 import type {BaseTextInputRef} from '@components/TextInput/BaseTextInput/types';
 import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails';
 import useDelegateAccountID from '@hooks/useDelegateAccountID';
-import useDynamicBackPath from '@hooks/useDynamicBackPath';
 import useLocalize from '@hooks/useLocalize';
 import useOnyx from '@hooks/useOnyx';
 import usePermissions from '@hooks/usePermissions';
@@ -22,7 +21,7 @@ import type {CurrentMoney} from '@pages/iou/MoneyRequestAmountForm';
 import MoneyRequestAmountForm from '@pages/iou/MoneyRequestAmountForm';
 import CONST from '@src/CONST';
 import ONYXKEYS from '@src/ONYXKEYS';
-import ROUTES, {DYNAMIC_ROUTES} from '@src/ROUTES';
+import ROUTES from '@src/ROUTES';
 import type SCREENS from '@src/SCREENS';
 import type {Policy, Transaction} from '@src/types/onyx';
 import {isEmptyObject} from '@src/types/utils/EmptyObject';
@@ -31,7 +30,7 @@ import withFullTransactionOrNotFound from './withFullTransactionOrNotFound';
 import type {WithWritableReportOrNotFoundProps} from './withWritableReportOrNotFound';
 import withWritableReportOrNotFound from './withWritableReportOrNotFound';
 
-type IOURequestStepTaxAmountPageProps = WithWritableReportOrNotFoundProps<typeof SCREENS.MONEY_REQUEST.DYNAMIC_STEP_TAX_AMOUNT> & {
+type IOURequestStepTaxAmountPageProps = WithWritableReportOrNotFoundProps<typeof SCREENS.MONEY_REQUEST.STEP_TAX_AMOUNT> & {
     transaction: OnyxEntry<Transaction>;
 };
 
@@ -52,7 +51,7 @@ function getTaxAmount(transaction: OnyxEntry<Transaction>, policy: OnyxEntry<Pol
 
 function IOURequestStepTaxAmountPage({
     route: {
-        params: {action, iouType, reportID, transactionID},
+        params: {action, iouType, reportID, transactionID, backTo},
     },
     transaction,
     report,
@@ -77,9 +76,6 @@ function IOURequestStepTaxAmountPage({
     const delegateAccountID = useDelegateAccountID();
     const {isBetaEnabled} = usePermissions();
     const isASAPSubmitBetaEnabled = isBetaEnabled(CONST.BETAS.ASAP_SUBMIT);
-    const backPath = useDynamicBackPath(DYNAMIC_ROUTES.MONEY_REQUEST_STEP_TAX_AMOUNT.path);
-    const shouldReturnToPreviousScreen = backPath !== ROUTES.HOME;
-    const isEditingOrReturning = isEditing || shouldReturnToPreviousScreen;
 
     const currentTransaction = isEditingSplitBill && !isEmptyObject(splitDraftTransaction) ? splitDraftTransaction : transaction;
     const transactionDetails = getTransactionDetails(currentTransaction);
@@ -99,7 +95,7 @@ function IOURequestStepTaxAmountPage({
     );
 
     const navigateBack = () => {
-        Navigation.goBack(backPath);
+        Navigation.goBack(backTo);
     };
 
     const updateTaxAmount = (currentAmount: CurrentMoney) => {
@@ -139,8 +135,8 @@ function IOURequestStepTaxAmountPage({
         // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
         setMoneyRequestCurrency(transactionID, currency || CONST.CURRENCY.USD);
 
-        if (shouldReturnToPreviousScreen) {
-            navigateBack();
+        if (backTo) {
+            Navigation.goBack(backTo);
             return;
         }
 
@@ -163,15 +159,15 @@ function IOURequestStepTaxAmountPage({
         <StepScreenWrapper
             headerTitle={translate('iou.taxAmount')}
             onBackButtonPress={navigateBack}
-            testID="DynamicIOURequestStepTaxAmountPage"
-            shouldShowWrapper={isEditingOrReturning}
+            testID="IOURequestStepTaxAmountPage"
+            shouldShowWrapper={!!(backTo || isEditing)}
             includeSafeAreaPaddingBottom
         >
             <MoneyRequestAmountForm
-                isEditing={isEditingOrReturning}
+                isEditing={!!(backTo || isEditing)}
                 currency={currency}
                 amount={Math.abs(transactionDetails?.taxAmount ?? 0)}
-                taxAmount={getTaxAmount(currentTransaction, policy, currency, decimals, isEditingOrReturning)}
+                taxAmount={getTaxAmount(currentTransaction, policy, currency, decimals, !!(backTo || isEditing))}
                 ref={(e) => {
                     textInput.current = e;
                 }}
@@ -185,8 +181,8 @@ function IOURequestStepTaxAmountPage({
     );
 }
 
-const DynamicIOURequestStepTaxAmountPageWithWritableReportOrNotFound = withWritableReportOrNotFound(IOURequestStepTaxAmountPage);
+const IOURequestStepTaxAmountPageWithWritableReportOrNotFound = withWritableReportOrNotFound(IOURequestStepTaxAmountPage);
 
-const DynamicIOURequestStepTaxAmountPageWithFullTransactionOrNotFound = withFullTransactionOrNotFound(DynamicIOURequestStepTaxAmountPageWithWritableReportOrNotFound);
+const IOURequestStepTaxAmountPageWithFullTransactionOrNotFound = withFullTransactionOrNotFound(IOURequestStepTaxAmountPageWithWritableReportOrNotFound);
 
-export default DynamicIOURequestStepTaxAmountPageWithFullTransactionOrNotFound;
+export default IOURequestStepTaxAmountPageWithFullTransactionOrNotFound;
diff --git a/src/pages/iou/request/step/DynamicIOURequestStepTaxRatePage.tsx b/src/pages/iou/request/step/IOURequestStepTaxRatePage.tsx
similarity index 90%
rename from src/pages/iou/request/step/DynamicIOURequestStepTaxRatePage.tsx
rename to src/pages/iou/request/step/IOURequestStepTaxRatePage.tsx
index 8d954a6f1399..0c464308f063 100644
--- a/src/pages/iou/request/step/DynamicIOURequestStepTaxRatePage.tsx
+++ b/src/pages/iou/request/step/IOURequestStepTaxRatePage.tsx
@@ -4,7 +4,6 @@ import TaxPicker from '@components/TaxPicker';
 import {useCurrencyListActions} from '@hooks/useCurrencyList';
 import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails';
 import useDelegateAccountID from '@hooks/useDelegateAccountID';
-import useDynamicBackPath from '@hooks/useDynamicBackPath';
 import useLocalize from '@hooks/useLocalize';
 import useOnyx from '@hooks/useOnyx';
 import usePermissions from '@hooks/usePermissions';
@@ -22,7 +21,6 @@ import {setDraftSplitTransaction} from '@userActions/IOU/Split';
 import {updateMoneyRequestTaxRate} from '@userActions/IOU/UpdateMoneyRequest';
 import CONST from '@src/CONST';
 import ONYXKEYS from '@src/ONYXKEYS';
-import {DYNAMIC_ROUTES} from '@src/ROUTES';
 import type SCREENS from '@src/SCREENS';
 import type {Policy, Transaction} from '@src/types/onyx';
 import {isEmptyObject} from '@src/types/utils/EmptyObject';
@@ -31,7 +29,7 @@ import withFullTransactionOrNotFound from './withFullTransactionOrNotFound';
 import withWritableReportOrNotFound from './withWritableReportOrNotFound';
 import type {WithWritableReportOrNotFoundProps} from './withWritableReportOrNotFound';
 
-type IOURequestStepTaxRatePageProps = WithWritableReportOrNotFoundProps<typeof SCREENS.MONEY_REQUEST.DYNAMIC_STEP_TAX_RATE> & {
+type IOURequestStepTaxRatePageProps = WithWritableReportOrNotFoundProps<typeof SCREENS.MONEY_REQUEST.STEP_TAX_RATE> & {
     transaction: OnyxEntry<Transaction>;
 };
 
@@ -44,7 +42,7 @@ function getTaxAmount(policy: OnyxEntry<Policy>, transaction: OnyxEntry<Transact
 
 function IOURequestStepTaxRatePage({
     route: {
-        params: {action, iouType, transactionID, reportID: reportIDFromRoute},
+        params: {action, backTo, iouType, transactionID, reportID: reportIDFromRoute},
     },
     transaction,
     report,
@@ -74,10 +72,9 @@ function IOURequestStepTaxRatePage({
     const {policyForMovingExpenses} = usePolicyForMovingExpenses();
     const {isBetaEnabled} = usePermissions();
     const isASAPSubmitBetaEnabled = isBetaEnabled(CONST.BETAS.ASAP_SUBMIT);
-    const backPath = useDynamicBackPath(DYNAMIC_ROUTES.MONEY_REQUEST_STEP_TAX_RATE.path);
 
     const navigateBack = () => {
-        Navigation.goBack(backPath);
+        Navigation.goBack(backTo);
     };
 
     const taxRateTitle = getTaxRateTitle(policy, currentTransaction, isMovingTransactionFromTrackExpense(action), policyForMovingExpenses);
@@ -148,7 +145,7 @@ function IOURequestStepTaxRatePage({
             headerTitle={translate('iou.taxRate')}
             onBackButtonPress={navigateBack}
             shouldShowWrapper
-            testID="DynamicIOURequestStepTaxRatePage"
+            testID="IOURequestStepTaxRatePage"
         >
             <TaxPicker
                 selectedTaxRate={taxRateTitle}
@@ -163,8 +160,8 @@ function IOURequestStepTaxRatePage({
     );
 }
 
-const DynamicIOURequestStepTaxRatePageWithWritableReportOrNotFound = withWritableReportOrNotFound(IOURequestStepTaxRatePage);
+const IOURequestStepTaxRatePageWithWritableReportOrNotFound = withWritableReportOrNotFound(IOURequestStepTaxRatePage);
 
-const DynamicIOURequestStepTaxRatePageWithFullTransactionOrNotFound = withFullTransactionOrNotFound(DynamicIOURequestStepTaxRatePageWithWritableReportOrNotFound);
+const IOURequestStepTaxRatePageWithFullTransactionOrNotFound = withFullTransactionOrNotFound(IOURequestStepTaxRatePageWithWritableReportOrNotFound);
 
-export default DynamicIOURequestStepTaxRatePageWithFullTransactionOrNotFound;
+export default IOURequestStepTaxRatePageWithFullTransactionOrNotFound;
diff --git a/src/pages/iou/request/step/DynamicIOURequestStepUpgradePage.tsx b/src/pages/iou/request/step/IOURequestStepUpgrade.tsx
similarity index 93%
rename from src/pages/iou/request/step/DynamicIOURequestStepUpgradePage.tsx
rename to src/pages/iou/request/step/IOURequestStepUpgrade.tsx
index 1b932707b101..2614106b1ea3 100644
--- a/src/pages/iou/request/step/DynamicIOURequestStepUpgradePage.tsx
+++ b/src/pages/iou/request/step/IOURequestStepUpgrade.tsx
@@ -12,7 +12,6 @@ import type {WorkspaceConfirmationSubmitFunctionParams} from '@components/Worksp
 import useActivePolicy from '@hooks/useActivePolicy';
 import useCreateNewReport from '@hooks/useCreateNewReport';
 import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails';
-import useDynamicBackPath from '@hooks/useDynamicBackPath';
 import useHasActiveAdminPolicies from '@hooks/useHasActiveAdminPolicies';
 import useLastWorkspaceNumber from '@hooks/useLastWorkspaceNumber';
 import useLocalize from '@hooks/useLocalize';
@@ -25,7 +24,6 @@ import {createNewReport} from '@libs/actions/Report';
 import {changeTransactionsReport, setTransactionReport} from '@libs/actions/Transaction';
 import type CreateWorkspaceParams from '@libs/API/parameters/CreateWorkspaceParams';
 import getPlatform from '@libs/getPlatform';
-import createDynamicRoute from '@libs/Navigation/helpers/dynamicRoutesUtils/createDynamicRoute';
 import {navigateToCreatedReportInReports} from '@libs/Navigation/helpers/getCreateReportRoute';
 import Navigation from '@libs/Navigation/Navigation';
 import type {PlatformStackScreenProps} from '@libs/Navigation/PlatformStackNavigation/types';
@@ -39,17 +37,17 @@ import CONST from '@src/CONST';
 import * as Policy from '@src/libs/actions/Policy/Policy';
 import ONYXKEYS from '@src/ONYXKEYS';
 import type {Route} from '@src/ROUTES';
-import ROUTES, {DYNAMIC_ROUTES} from '@src/ROUTES';
+import ROUTES from '@src/ROUTES';
 import type SCREENS from '@src/SCREENS';
 import type {PersonalDetails, Transaction} from '@src/types/onyx';
 
-type DynamicIOURequestStepUpgradePageProps = PlatformStackScreenProps<MoneyRequestNavigatorParamList, typeof SCREENS.MONEY_REQUEST.DYNAMIC_STEP_UPGRADE>;
+type IOURequestStepUpgradeProps = PlatformStackScreenProps<MoneyRequestNavigatorParamList, typeof SCREENS.MONEY_REQUEST.STEP_UPGRADE>;
 
-function DynamicIOURequestStepUpgradePage({
+function IOURequestStepUpgrade({
     route: {
-        params: {transactionID, action, reportID, shouldSubmitExpense, upgradePath, iouType},
+        params: {transactionID, action, reportID, shouldSubmitExpense, upgradePath, iouType, backTo},
     },
-}: DynamicIOURequestStepUpgradePageProps) {
+}: IOURequestStepUpgradeProps) {
     const styles = useThemeStyles();
 
     const {translate} = useLocalize();
@@ -59,7 +57,6 @@ function DynamicIOURequestStepUpgradePage({
     const activePolicy = useActivePolicy();
     const hasActiveAdminPolicies = useHasActiveAdminPolicies();
     const lastWorkspaceNumber = useLastWorkspaceNumber();
-    const backPath = useDynamicBackPath(DYNAMIC_ROUTES.MONEY_REQUEST_UPGRADE.path);
 
     const [transaction] = useOnyx(`${ONYXKEYS.COLLECTION.TRANSACTION_DRAFT}${transactionID}`);
     const [selectedReport] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${reportID}`);
@@ -179,13 +176,13 @@ function DynamicIOURequestStepUpgradePage({
         switch (upgradePath) {
             case CONST.UPGRADE_PATHS.DISTANCE_RATES: {
                 if (!policyID || !reportID) {
-                    Navigation.goBack(backPath);
+                    Navigation.goBack();
                     return;
                 }
 
                 // In case we get here from /:action/track/... route we need to navigate to
                 // /:action/submit/... when shouldSubmitExpense === true as transaction is not selfDM anymore
-                const backToRoute = shouldSubmitExpense ? ROUTES.MONEY_REQUEST_STEP_CONFIRMATION.getRoute(action, CONST.IOU.TYPE.SUBMIT, transactionID, reportID) : backPath;
+                const backToRoute = shouldSubmitExpense ? ROUTES.MONEY_REQUEST_STEP_CONFIRMATION.getRoute(action, CONST.IOU.TYPE.SUBMIT, transactionID, reportID) : undefined;
 
                 Navigation.goBack(backToRoute, {compareParams: false});
 
@@ -208,28 +205,28 @@ function DynamicIOURequestStepUpgradePage({
             case CONST.UPGRADE_PATHS.REPORTS:
                 if (action === CONST.IOU.ACTION.CREATE && policyID) {
                     const {reportID: newReportID} = createReportForCurrentUser(policyID);
-                    Navigation.goBack(backPath);
+                    Navigation.goBack();
                     // Wait until the upgrade RHP is closed before opening the created report from Reports.
                     Navigation.setNavigationActionToMicrotaskQueue(() => {
                         navigateToCreatedReportInReports(newReportID);
                     });
                 } else {
-                    Navigation.goBack(backPath);
+                    Navigation.goBack();
                     navigateWithMicrotask(ROUTES.MONEY_REQUEST_STEP_REPORT.getRoute(action, CONST.IOU.TYPE.SUBMIT, transactionID, reportID));
                 }
 
                 break;
             case CONST.UPGRADE_PATHS.CATEGORIES:
-                Navigation.goBack(backPath);
-                navigateWithMicrotask(createDynamicRoute(DYNAMIC_ROUTES.MONEY_REQUEST_STEP_CATEGORY.getRoute(action, CONST.IOU.TYPE.SUBMIT, transactionID, reportID)));
+                Navigation.goBack();
+                navigateWithMicrotask(backTo ?? ROUTES.MONEY_REQUEST_STEP_CATEGORY.getRoute(action, CONST.IOU.TYPE.SUBMIT, transactionID, reportID));
 
                 break;
             default:
-                Navigation.goBack(backPath);
+                Navigation.goBack();
         }
     }, [
         action,
-        backPath,
+        backTo,
         navigateWithMicrotask,
         reportID,
         shouldSubmitExpense,
@@ -334,7 +331,7 @@ function DynamicIOURequestStepUpgradePage({
             {(!!isUpgraded || !showConfirmationForm) && (
                 <HeaderWithBackButton
                     title={translate('common.upgrade')}
-                    onBackButtonPress={() => Navigation.goBack(backPath)}
+                    onBackButtonPress={() => Navigation.goBack()}
                 />
             )}
             {!showConfirmationForm && (
@@ -382,4 +379,4 @@ function DynamicIOURequestStepUpgradePage({
     );
 }
 
-export default DynamicIOURequestStepUpgradePage;
+export default IOURequestStepUpgrade;
diff --git a/src/pages/iou/request/step/withFullTransactionOrNotFound.tsx b/src/pages/iou/request/step/withFullTransactionOrNotFound.tsx
index 8d72efbdf76e..f37b4127d942 100644
--- a/src/pages/iou/request/step/withFullTransactionOrNotFound.tsx
+++ b/src/pages/iou/request/step/withFullTransactionOrNotFound.tsx
@@ -32,14 +32,14 @@ type MoneyRequestRouteName =
     | typeof SCREENS.MONEY_REQUEST.STEP_WAYPOINT
     | typeof SCREENS.MONEY_REQUEST.STEP_DESCRIPTION
     | typeof SCREENS.MONEY_REQUEST.STEP_DATE
-    | typeof SCREENS.MONEY_REQUEST.DYNAMIC_STEP_TAX_AMOUNT
+    | typeof SCREENS.MONEY_REQUEST.STEP_TAX_AMOUNT
     | typeof SCREENS.MONEY_REQUEST.STEP_PARTICIPANTS
     | typeof SCREENS.MONEY_REQUEST.STEP_MERCHANT
     | typeof SCREENS.MONEY_REQUEST.STEP_TAG
     | typeof SCREENS.MONEY_REQUEST.STEP_DISTANCE_RATE
     | typeof SCREENS.MONEY_REQUEST.STEP_CONFIRMATION
-    | typeof SCREENS.MONEY_REQUEST.DYNAMIC_STEP_CATEGORY
-    | typeof SCREENS.MONEY_REQUEST.DYNAMIC_STEP_TAX_RATE
+    | typeof SCREENS.MONEY_REQUEST.STEP_CATEGORY
+    | typeof SCREENS.MONEY_REQUEST.STEP_TAX_RATE
     | typeof SCREENS.MONEY_REQUEST.STEP_SCAN
     | typeof SCREENS.MONEY_REQUEST.STEP_SEND_FROM
     | typeof SCREENS.MONEY_REQUEST.STEP_REPORT
diff --git a/src/pages/iou/request/step/withWritableReportOrNotFound.tsx b/src/pages/iou/request/step/withWritableReportOrNotFound.tsx
index c506e864272e..5eb13936ed83 100644
--- a/src/pages/iou/request/step/withWritableReportOrNotFound.tsx
+++ b/src/pages/iou/request/step/withWritableReportOrNotFound.tsx
@@ -28,10 +28,10 @@ type MoneyRequestRouteName =
     | typeof SCREENS.MONEY_REQUEST.STEP_WAYPOINT
     | typeof SCREENS.MONEY_REQUEST.STEP_DESCRIPTION
     | typeof SCREENS.MONEY_REQUEST.STEP_DATE
-    | typeof SCREENS.MONEY_REQUEST.DYNAMIC_STEP_CATEGORY
+    | typeof SCREENS.MONEY_REQUEST.STEP_CATEGORY
     | typeof SCREENS.MONEY_REQUEST.STEP_DISTANCE_RATE
     | typeof SCREENS.MONEY_REQUEST.STEP_CONFIRMATION
-    | typeof SCREENS.MONEY_REQUEST.DYNAMIC_STEP_TAX_RATE
+    | typeof SCREENS.MONEY_REQUEST.STEP_TAX_RATE
     | typeof SCREENS.MONEY_REQUEST.STEP_AMOUNT
     | typeof SCREENS.MONEY_REQUEST.STEP_DISTANCE
     | typeof SCREENS.MONEY_REQUEST.CREATE
@@ -39,14 +39,14 @@ type MoneyRequestRouteName =
     | typeof SCREENS.MONEY_REQUEST.STEP_TAG
     | typeof SCREENS.MONEY_REQUEST.STEP_PARTICIPANTS
     | typeof SCREENS.MONEY_REQUEST.STEP_MERCHANT
-    | typeof SCREENS.MONEY_REQUEST.DYNAMIC_STEP_TAX_AMOUNT
+    | typeof SCREENS.MONEY_REQUEST.STEP_TAX_AMOUNT
     | typeof SCREENS.MONEY_REQUEST.STEP_SCAN
     | typeof SCREENS.MONEY_REQUEST.STEP_SEND_FROM
     | typeof SCREENS.MONEY_REQUEST.STEP_REPORT
     | typeof SCREENS.MONEY_REQUEST.STEP_COMPANY_INFO
-    | typeof SCREENS.MONEY_REQUEST.DYNAMIC_STEP_ATTENDEES
-    | typeof SCREENS.MONEY_REQUEST.DYNAMIC_STEP_ACCOUNTANT
-    | typeof SCREENS.MONEY_REQUEST.DYNAMIC_STEP_UPGRADE
+    | typeof SCREENS.MONEY_REQUEST.STEP_ATTENDEES
+    | typeof SCREENS.MONEY_REQUEST.STEP_ACCOUNTANT
+    | typeof SCREENS.MONEY_REQUEST.STEP_UPGRADE
     | typeof SCREENS.MONEY_REQUEST.STEP_DESTINATION
     | typeof SCREENS.MONEY_REQUEST.STEP_TIME
     | typeof SCREENS.MONEY_REQUEST.STEP_TIME_EDIT
diff --git a/tests/unit/ReportUtilsTest.ts b/tests/unit/ReportUtilsTest.ts
index aecbdc86a7e4..8411688716d2 100644
--- a/tests/unit/ReportUtilsTest.ts
+++ b/tests/unit/ReportUtilsTest.ts
@@ -21,7 +21,6 @@ import type {FormulaContext} from '@libs/Formula';
 import getBase62ReportID from '@libs/getBase62ReportID';
 import {translate} from '@libs/Localize';
 import Log from '@libs/Log';
-import createDynamicRoute from '@libs/Navigation/helpers/dynamicRoutesUtils/createDynamicRoute';
 import getReportURLForCurrentContext from '@libs/Navigation/helpers/getReportURLForCurrentContext';
 import isSearchTopmostFullScreenRoute from '@libs/Navigation/helpers/isSearchTopmostFullScreenRoute';
 import Navigation from '@libs/Navigation/Navigation';
@@ -174,7 +173,7 @@ import {buildOptimisticTransaction} from '@libs/TransactionUtils';
 import CONST from '@src/CONST';
 import IntlStore from '@src/languages/IntlStore';
 import ONYXKEYS from '@src/ONYXKEYS';
-import ROUTES, {DYNAMIC_ROUTES} from '@src/ROUTES';
+import ROUTES from '@src/ROUTES';
 import type {
     BankAccountList,
     Beta,
@@ -15711,17 +15710,7 @@ describe('ReportUtils', () => {
 
                 // Then it should navigate to the category step
                 expect(Navigation.navigate).toHaveBeenCalledWith(
-                    createDynamicRoute(
-                        DYNAMIC_ROUTES.MONEY_REQUEST_STEP_CATEGORY.getRoute(CONST.IOU.ACTION.CATEGORIZE, CONST.IOU.TYPE.SUBMIT, transaction.transactionID, policyExpenseReport.reportID),
-                        ROUTES.MONEY_REQUEST_STEP_CONFIRMATION.getRoute(
-                            CONST.IOU.ACTION.CATEGORIZE,
-                            CONST.IOU.TYPE.SUBMIT,
-                            transaction.transactionID,
-                            policyExpenseReport.reportID,
-                            undefined,
-                            true,
-                        ),
-                    ),
+                    ROUTES.MONEY_REQUEST_STEP_CATEGORY.getRoute(CONST.IOU.ACTION.CATEGORIZE, CONST.IOU.TYPE.SUBMIT, transaction.transactionID, policyExpenseReport.reportID),
                 );
             });
 
@@ -15764,17 +15753,7 @@ describe('ReportUtils', () => {
 
                 // Then it should automatically pick the available policy and navigate to the category step
                 expect(Navigation.navigate).toHaveBeenCalledWith(
-                    createDynamicRoute(
-                        DYNAMIC_ROUTES.MONEY_REQUEST_STEP_CATEGORY.getRoute(CONST.IOU.ACTION.CATEGORIZE, CONST.IOU.TYPE.SUBMIT, transaction.transactionID, policyExpenseReport.reportID),
-                        ROUTES.MONEY_REQUEST_STEP_CONFIRMATION.getRoute(
-                            CONST.IOU.ACTION.CATEGORIZE,
-                            CONST.IOU.TYPE.SUBMIT,
-                            transaction.transactionID,
-                            policyExpenseReport.reportID,
-                            undefined,
-                            true,
-                        ),
-                    ),
+                    ROUTES.MONEY_REQUEST_STEP_CATEGORY.getRoute(CONST.IOU.ACTION.CATEGORIZE, CONST.IOU.TYPE.SUBMIT, transaction.transactionID, policyExpenseReport.reportID),
                 );
             });
 
@@ -15804,16 +15783,15 @@ describe('ReportUtils', () => {
 
                 // Then it should navigate to the upgrade page because no policies were found to categorize with
                 expect(Navigation.navigate).toHaveBeenCalledWith(
-                    createDynamicRoute(
-                        DYNAMIC_ROUTES.MONEY_REQUEST_UPGRADE.getRoute({
-                            action: CONST.IOU.ACTION.CATEGORIZE,
-                            iouType: CONST.IOU.TYPE.SUBMIT,
-                            transactionID: transaction.transactionID,
-                            reportID: '1',
-                            upgradePath: CONST.UPGRADE_PATHS.CATEGORIES,
-                            shouldSubmitExpense: true,
-                        }),
-                    ),
+                    ROUTES.MONEY_REQUEST_UPGRADE.getRoute({
+                        action: CONST.IOU.ACTION.CATEGORIZE,
+                        iouType: CONST.IOU.TYPE.SUBMIT,
+                        transactionID: transaction.transactionID,
+                        reportID: '1',
+                        backTo: '',
+                        upgradePath: CONST.UPGRADE_PATHS.CATEGORIES,
+                        shouldSubmitExpense: true,
+                    }),
                 );
             });
 
@@ -15856,16 +15834,15 @@ describe('ReportUtils', () => {
 
                 // Then it should navigate to the upgrade page because it's ambiguous which policy to use
                 expect(Navigation.navigate).toHaveBeenCalledWith(
-                    createDynamicRoute(
-                        DYNAMIC_ROUTES.MONEY_REQUEST_UPGRADE.getRoute({
-                            action: CONST.IOU.ACTION.CATEGORIZE,
-                            iouType: CONST.IOU.TYPE.SUBMIT,
-                            transactionID: transaction.transactionID,
-                            reportID: '1',
-                            upgradePath: CONST.UPGRADE_PATHS.CATEGORIES,
-                            shouldSubmitExpense: true,
-                        }),
-                    ),
+                    ROUTES.MONEY_REQUEST_UPGRADE.getRoute({
+                        action: CONST.IOU.ACTION.CATEGORIZE,
+                        iouType: CONST.IOU.TYPE.SUBMIT,
+                        transactionID: transaction.transactionID,
+                        reportID: '1',
+                        backTo: '',
+                        upgradePath: CONST.UPGRADE_PATHS.CATEGORIES,
+                        shouldSubmitExpense: true,
+                    }),
                 );
             });
 
@@ -15952,17 +15929,7 @@ describe('ReportUtils', () => {
                 // Then it should NOT navigate to restricted action page, but to category step
                 expect(Navigation.navigate).not.toHaveBeenCalledWith(ROUTES.RESTRICTED_ACTION.getRoute(activePolicy.id));
                 expect(Navigation.navigate).toHaveBeenCalledWith(
-                    createDynamicRoute(
-                        DYNAMIC_ROUTES.MONEY_REQUEST_STEP_CATEGORY.getRoute(CONST.IOU.ACTION.CATEGORIZE, CONST.IOU.TYPE.SUBMIT, transaction.transactionID, policyExpenseReport.reportID),
-                        ROUTES.MONEY_REQUEST_STEP_CONFIRMATION.getRoute(
-                            CONST.IOU.ACTION.CATEGORIZE,
-                            CONST.IOU.TYPE.SUBMIT,
-                            transaction.transactionID,
-                            policyExpenseReport.reportID,
-                            undefined,
-                            true,
-                        ),
-                    ),
+                    ROUTES.MONEY_REQUEST_STEP_CATEGORY.getRoute(CONST.IOU.ACTION.CATEGORIZE, CONST.IOU.TYPE.SUBMIT, transaction.transactionID, policyExpenseReport.reportID),
                 );
             });
 

From 990f64a68586092b634e4b9e337736a9202de9aa Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Micha=C5=82=20Jasikowski?= <michal@expensify.com>
Date: Thu, 11 Jun 2026 11:13:34 +0200
Subject: [PATCH 339/435] Fix eslint seatbelt after revert of #92161

Update ROUTES.ts getUrlWithBackToParam count from 132 to 139 to match
the restored usages. Remove stale Dynamic* seatbelt entries for files
that no longer exist after the revert.
---
 config/eslint/eslint.seatbelt.tsv | 5 +----
 1 file changed, 1 insertion(+), 4 deletions(-)

diff --git a/config/eslint/eslint.seatbelt.tsv b/config/eslint/eslint.seatbelt.tsv
index a1eff506b188..5480410a8b7c 100644
--- a/config/eslint/eslint.seatbelt.tsv
+++ b/config/eslint/eslint.seatbelt.tsv
@@ -68,7 +68,7 @@
 "../../src/Expensify.tsx"	"react-hooks/set-state-in-effect"	1
 "../../src/GlobalModals.tsx"	"no-restricted-syntax"	2
 "../../src/ONYXKEYS.ts"	"no-restricted-syntax"	2
-"../../src/ROUTES.ts"	"@typescript-eslint/no-deprecated/getUrlWithBackToParam"	132
+"../../src/ROUTES.ts"	"@typescript-eslint/no-deprecated/getUrlWithBackToParam"	139
 "../../src/ROUTES.ts"	"@typescript-eslint/no-unsafe-type-assertion"	3
 "../../src/TIMEZONES.ts"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../src/components/AccountingConnectionConfirmationModal.tsx"	"@typescript-eslint/no-deprecated/ConfirmModal"	1
@@ -1171,9 +1171,6 @@
 "../../src/pages/iou/request/MoneyRequestAttendeeSelector.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	2
 "../../src/pages/iou/request/ParticipantSearchResults.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	4
 "../../src/pages/iou/request/step/DistanceManualTabContent.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
-"../../src/pages/iou/request/step/DynamicIOURequestStepCategoryPage.tsx"	"@typescript-eslint/no-deprecated/InteractionManager.runAfterInteractions"	1
-"../../src/pages/iou/request/step/DynamicIOURequestStepUpgradePage.tsx"	"@typescript-eslint/no-deprecated/ConfirmModal"	1
-"../../src/pages/iou/request/step/DynamicIOURequestStepUpgradePage.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	2
 "../../src/pages/iou/request/step/IOURequestEditReport.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../src/pages/iou/request/step/IOURequestEditReportCommon.tsx"	"@typescript-eslint/no-deprecated/ConfirmModal"	1
 "../../src/pages/iou/request/step/IOURequestEditReportCommon.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1

From 30ca9653e9aad6cce2affdd446a78c0d8fd3d522 Mon Sep 17 00:00:00 2001
From: Yehor Kharchenko <yehorkharchenko4@gmail.com>
Date: Thu, 11 Jun 2026 11:19:34 +0200
Subject: [PATCH 340/435] add timeouts for report/expense deletions

---
 config/eslint/eslint.seatbelt.tsv             |  1 +
 .../MoneyRequestHeaderSecondaryActions.tsx    |  2 +-
 src/hooks/useExpenseActions.ts                | 56 +++++++++++--------
 3 files changed, 34 insertions(+), 25 deletions(-)

diff --git a/config/eslint/eslint.seatbelt.tsv b/config/eslint/eslint.seatbelt.tsv
index fc1110c7a1ec..43cb52ac81f6 100644
--- a/config/eslint/eslint.seatbelt.tsv
+++ b/config/eslint/eslint.seatbelt.tsv
@@ -532,6 +532,7 @@
 "../../src/hooks/useDragAndDrop/types.ts"	"@typescript-eslint/no-deprecated/React.MutableRefObject"	1
 "../../src/hooks/useDynamicBackPath.ts"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../src/hooks/useExpenseActions.ts"	"@typescript-eslint/no-deprecated/InteractionManager.runAfterInteractions"	3
+"../../src/hooks/useExpenseActions.ts"	"no-restricted-imports"	1
 "../../src/hooks/useExportActions.ts"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../src/hooks/useExportedToFilterOptions.ts"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../src/hooks/useFilesValidation.tsx"	"@typescript-eslint/no-deprecated/ConfirmModal"	1
diff --git a/src/components/MoneyRequestHeaderSecondaryActions.tsx b/src/components/MoneyRequestHeaderSecondaryActions.tsx
index c4b2001a5723..28b15b4bde51 100644
--- a/src/components/MoneyRequestHeaderSecondaryActions.tsx
+++ b/src/components/MoneyRequestHeaderSecondaryActions.tsx
@@ -481,7 +481,7 @@ function MoneyRequestHeaderSecondaryActions({reportID, onBackButtonPress}: Money
                         };
                     }
                     if (isInNarrowPaneModal) {
-                        Navigation.navigateBackToLastSuperWideRHPScreen({afterTransition: afterDelete});
+                        Navigation.navigateBackToLastSuperWideRHPScreen({afterTransition: () => setTimeout(() => afterDelete?.(), 300)});
                         return;
                     }
 
diff --git a/src/hooks/useExpenseActions.ts b/src/hooks/useExpenseActions.ts
index 5524591417ec..89b65c3af5a7 100644
--- a/src/hooks/useExpenseActions.ts
+++ b/src/hooks/useExpenseActions.ts
@@ -19,6 +19,7 @@ import {getExistingTransactionID} from '@libs/IOUUtils';
 import Log from '@libs/Log';
 import createDynamicRoute from '@libs/Navigation/helpers/dynamicRoutesUtils/createDynamicRoute';
 import Navigation from '@libs/Navigation/Navigation';
+import TransitionTracker from '@libs/Navigation/TransitionTracker';
 import {isPolicyAccessible} from '@libs/PolicyUtils';
 import {getIOUActionForTransactionID} from '@libs/ReportActionsUtils';
 import {
@@ -512,20 +513,25 @@ function useExpenseActions({reportID, isReportInSearch = false, backTo, onDuplic
                         if (goBackRoute) {
                             navigateOnDeleteExpense(goBackRoute);
                         }
-                        InteractionManager.runAfterInteractions(() => {
-                            const deleteResult = deleteTransactions(
-                                [transaction.transactionID],
-                                duplicateTransactions,
-                                duplicateTransactionViolations,
-                                isReportInSearch ? currentSearchHash : undefined,
-                                false,
-                            );
-
-                            if (deleteResult.action === 'redirected') {
-                                return;
-                            }
-
-                            removeTransaction(transaction.transactionID);
+                        TransitionTracker.runAfterTransitions({
+                            callback: () => {
+                                setTimeout(() => {
+                                    const deleteResult = deleteTransactions(
+                                        [transaction.transactionID],
+                                        duplicateTransactions,
+                                        duplicateTransactionViolations,
+                                        isReportInSearch ? currentSearchHash : undefined,
+                                        false,
+                                    );
+
+                                    if (deleteResult.action === 'redirected') {
+                                        return;
+                                    }
+
+                                    removeTransaction(transaction.transactionID);
+                                }, 300);
+                            },
+                            waitForUpcomingTransition: true,
                         });
                     }
                     return;
@@ -548,16 +554,18 @@ function useExpenseActions({reportID, isReportInSearch = false, backTo, onDuplic
                 Navigation.setNavigationActionToMicrotaskQueue(() => {
                     Navigation.goBack(backToRoute, {
                         afterTransition: () => {
-                            deleteAppReport({
-                                report: moneyRequestReport,
-                                selfDMReport,
-                                currentUserEmailParam: email ?? '',
-                                currentUserAccountIDParam: accountID,
-                                reportTransactions,
-                                allTransactionViolations,
-                                bankAccountList,
-                                hash: currentSearchHash,
-                            });
+                            setTimeout(() => {
+                                deleteAppReport({
+                                    report: moneyRequestReport,
+                                    selfDMReport,
+                                    currentUserEmailParam: email ?? '',
+                                    currentUserAccountIDParam: accountID,
+                                    reportTransactions,
+                                    allTransactionViolations,
+                                    bankAccountList,
+                                    hash: currentSearchHash,
+                                });
+                            }, 300);
                         },
                     });
                 });

From ba461726f00dc479cd5da371c88bd74505350545 Mon Sep 17 00:00:00 2001
From: Jakub Korytko <jakub@korytko.me>
Date: Thu, 11 Jun 2026 12:16:49 +0200
Subject: [PATCH 341/435] use isModalActiveSelector in useHRSyncResultsModal

---
 src/hooks/useHRSyncResultsModal.ts | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/src/hooks/useHRSyncResultsModal.ts b/src/hooks/useHRSyncResultsModal.ts
index 97e33dd88058..af9ca2ba372d 100644
--- a/src/hooks/useHRSyncResultsModal.ts
+++ b/src/hooks/useHRSyncResultsModal.ts
@@ -1,3 +1,4 @@
+import {isModalActiveSelector} from '@selectors/Modal';
 import {useEffect, useEffectEvent, useRef} from 'react';
 import type {OnyxEntry} from 'react-native-onyx';
 import HRSyncResultsModal from '@components/HRSyncResultsModal';
@@ -18,7 +19,7 @@ function useHRSyncResultsModal(policyID: string, connectionSyncProgress: OnyxEnt
     const modal = useModal();
     const previousSyncProgress = usePrevious(connectionSyncProgress);
     const pendingSyncResultRef = useRef<Pick<PolicyConnectionSyncProgress, 'connectionName' | 'result'> | null>(null);
-    const [isAnyModalActive] = useOnyx(ONYXKEYS.MODAL, {selector: (activeModal) => !!activeModal?.isVisible || !!activeModal?.willAlertModalBecomeVisible});
+    const [isAnyModalActive] = useOnyx(ONYXKEYS.MODAL, {selector: isModalActiveSelector});
 
     const connectionName = connectionSyncProgress?.connectionName;
     const showSyncResultsModal = useEffectEvent((syncResult: PolicyConnectionSyncProgress['result'], syncConnectionName: PolicyConnectionSyncProgress['connectionName']) => {

From 5e0a920fcbf470dde67ef86b210bb3904f529e9c Mon Sep 17 00:00:00 2001
From: Uzaifm127 <uzaifm127@gmail.com>
Date: Thu, 11 Jun 2026 16:03:37 +0530
Subject: [PATCH 342/435] Modified the tag and category name limit to 5

---
 src/CONST/index.ts | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/CONST/index.ts b/src/CONST/index.ts
index 4ddb58279187..288559afe85c 100644
--- a/src/CONST/index.ts
+++ b/src/CONST/index.ts
@@ -369,7 +369,7 @@ const CONST = {
 
     API_TRANSACTION_TAG_MAX_LENGTH: 255,
 
-    TRANSACTION_TAG_AND_CATEGORY_PICKER_MAX_TITLE_LINES: 15,
+    TRANSACTION_TAG_AND_CATEGORY_PICKER_MAX_TITLE_LINES: 5,
 
     AUTO_AUTH_STATE: {
         NOT_STARTED: 'not-started',

From 98154a94ecb0b7eebb22213d06e4bdced61fd3f2 Mon Sep 17 00:00:00 2001
From: Issa Nimaga <inimaga@expensify.com>
Date: Thu, 11 Jun 2026 11:43:02 +0100
Subject: [PATCH 343/435] prettier

---
 src/pages/inbox/usePusherDraftPacing.ts | 22 ++++++++++++++++------
 1 file changed, 16 insertions(+), 6 deletions(-)

diff --git a/src/pages/inbox/usePusherDraftPacing.ts b/src/pages/inbox/usePusherDraftPacing.ts
index 5621097f99f5..3ee5da4e84b5 100644
--- a/src/pages/inbox/usePusherDraftPacing.ts
+++ b/src/pages/inbox/usePusherDraftPacing.ts
@@ -857,15 +857,25 @@ function usePusherDraftPacing(reportID: string) {
         const draftEventSubscriptions = [
             {
                 eventType: Pusher.TYPE.CONCIERGE_DRAFT_EVENTS,
-                listener: Pusher.subscribe(channelName, Pusher.TYPE.CONCIERGE_DRAFT_EVENTS, (eventData: ConciergeDraftEventsEvent) => {
-                    handlePusherDraftEvents(runtime, eventData);
-                }, handleResubscribe),
+                listener: Pusher.subscribe(
+                    channelName,
+                    Pusher.TYPE.CONCIERGE_DRAFT_EVENTS,
+                    (eventData: ConciergeDraftEventsEvent) => {
+                        handlePusherDraftEvents(runtime, eventData);
+                    },
+                    handleResubscribe,
+                ),
             },
             ...PUSHER_DRAFT_EVENT_TYPES.map((eventType) => ({
                 eventType,
-                listener: Pusher.subscribe(channelName, eventType, (eventData: ConciergeDraftEvent) => {
-                    handlePusherDraftEvent(runtime, eventData);
-                }, handleResubscribe),
+                listener: Pusher.subscribe(
+                    channelName,
+                    eventType,
+                    (eventData: ConciergeDraftEvent) => {
+                        handlePusherDraftEvent(runtime, eventData);
+                    },
+                    handleResubscribe,
+                ),
             })),
         ];
 

From 9860a744b58411e06e6a8ac7418c53ebb13aedda Mon Sep 17 00:00:00 2001
From: Abdelrahman Khattab <abzokhattab@gmail.com>
Date: Thu, 11 Jun 2026 13:18:08 +0200
Subject: [PATCH 344/435] Pin Mobile-Expensify submodule to main (no submodule
 change in this PR)

---
 Mobile-Expensify | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Mobile-Expensify b/Mobile-Expensify
index eef367224ec1..42ad9da8bfde 160000
--- a/Mobile-Expensify
+++ b/Mobile-Expensify
@@ -1 +1 @@
-Subproject commit eef367224ec12b2fc9496daf967e41c59f146f40
+Subproject commit 42ad9da8bfde582b57b2e66dc30e22757e06deea

From ed5033dd82e76eb03f29c907d60900c4976be2de Mon Sep 17 00:00:00 2001
From: "truph01 (via MelvinBot)" <infra+melvinbot@expensify.com>
Date: Thu, 11 Jun 2026 11:27:13 +0000
Subject: [PATCH 345/435] Add PR link as PR introducing patch in details.md

Co-authored-by: truph01 <truph01@users.noreply.github.com>
---
 patches/react-native-draggable-flatlist/details.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/patches/react-native-draggable-flatlist/details.md b/patches/react-native-draggable-flatlist/details.md
index c12b0dffcbf6..0f72087f6309 100644
--- a/patches/react-native-draggable-flatlist/details.md
+++ b/patches/react-native-draggable-flatlist/details.md
@@ -21,4 +21,4 @@
 - Reason: On iOS, `scrollToOffset({animated: true})` does not emit intermediate `onScroll` events, so the `scrollOffset` shared value never updates mid-scroll. This blocks the autoscroll feedback loop (`hasScrolledToTarget` stays false), preventing waypoint reordering beyond the visible viewport. The fix manually advances `scrollOffset` after each `scrollToOffset` call to keep the loop alive.
 - Upstream PR/issue: https://github.com/computerjazz/react-native-draggable-flatlist/issues/509
 - E/App issue: [#87362](https://github.com/Expensify/App/issues/87362)
-- PR Introducing Patch: 🛑
+- PR Introducing Patch: [#90617](https://github.com/Expensify/App/pull/90617)

From 7c28309679958849ccc73b3d485b3e782fa8316d Mon Sep 17 00:00:00 2001
From: Dariusz Biela <dariusz.biela.dev@gmail.com>
Date: Thu, 11 Jun 2026 13:39:36 +0200
Subject: [PATCH 346/435] Fix stuck MFA cancel-confirm modal by not
 intercepting outside clicks

The MFA screens overrode allowOutsideClick and clickOutsideDeactivates to
intercept outside clicks at the document level (requestCancel + swallow the
event). Once the modal's own focus trap deactivated, the still-active screen
trap treated every click on the portal-rendered cancel-confirm modal as an
outside click and swallowed it, leaving the modal impossible to close.

Keep only the Escape override and let outside clicks follow the default
focus-trap behavior (deactivate the trap and pass through, like RHP screens):
they reach the MFA navigator's backdrop pressable, which requests the cancel
flow, and the modal stays fully interactive.
---
 src/pages/MultifactorAuthentication/PromptPage.tsx       | 8 ++++----
 src/pages/MultifactorAuthentication/ValidateCodePage.tsx | 8 ++++----
 2 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/src/pages/MultifactorAuthentication/PromptPage.tsx b/src/pages/MultifactorAuthentication/PromptPage.tsx
index 329e27432e81..dc15b0d3932c 100644
--- a/src/pages/MultifactorAuthentication/PromptPage.tsx
+++ b/src/pages/MultifactorAuthentication/PromptPage.tsx
@@ -33,8 +33,10 @@ function MultifactorAuthenticationPromptPage({route}: MultifactorAuthenticationP
         dispatch({type: 'SET_SOFT_PROMPT_APPROVED', payload: true});
     };
 
-    // Outside-clicks and Escape route through the central cancel handler; return
-    // false to keep the focus trap intact while the confirm modal opens.
+    // Escape routes through the central cancel handler; returning false keeps the trap active.
+    // Outside clicks must keep the default behavior (deactivate the trap and pass through, like
+    // RHP screens): they reach the navigator's backdrop, which requests the cancel flow, and an
+    // intercepting trap would swallow every click aimed at the portal-rendered cancel-confirm modal.
     const interceptFocusTrapEscape = () => {
         requestCancel();
         return false;
@@ -45,8 +47,6 @@ function MultifactorAuthenticationPromptPage({route}: MultifactorAuthenticationP
             testID={MultifactorAuthenticationPromptPage.displayName}
             focusTrapSettings={{
                 focusTrapOptions: {
-                    allowOutsideClick: interceptFocusTrapEscape,
-                    clickOutsideDeactivates: interceptFocusTrapEscape,
                     escapeDeactivates: interceptFocusTrapEscape,
                 },
             }}
diff --git a/src/pages/MultifactorAuthentication/ValidateCodePage.tsx b/src/pages/MultifactorAuthentication/ValidateCodePage.tsx
index 55b02952184c..7db6789005b7 100644
--- a/src/pages/MultifactorAuthentication/ValidateCodePage.tsx
+++ b/src/pages/MultifactorAuthentication/ValidateCodePage.tsx
@@ -198,8 +198,10 @@ function MultifactorAuthenticationValidateCodePage() {
         dispatch({type: 'SET_VALIDATE_CODE', payload: inputCode});
     };
 
-    // Outside-clicks and Escape route through the central cancel handler; return
-    // false to keep the focus trap intact while the confirm modal opens.
+    // Escape routes through the central cancel handler; returning false keeps the trap active.
+    // Outside clicks must keep the default behavior (deactivate the trap and pass through, like
+    // RHP screens): they reach the navigator's backdrop, which requests the cancel flow, and an
+    // intercepting trap would swallow every click aimed at the portal-rendered cancel-confirm modal.
     const interceptFocusTrapEscape = () => {
         requestCancel();
         return false;
@@ -210,8 +212,6 @@ function MultifactorAuthenticationValidateCodePage() {
             testID={MultifactorAuthenticationValidateCodePage.displayName}
             focusTrapSettings={{
                 focusTrapOptions: {
-                    allowOutsideClick: interceptFocusTrapEscape,
-                    clickOutsideDeactivates: interceptFocusTrapEscape,
                     escapeDeactivates: interceptFocusTrapEscape,
                 },
             }}

From 45e726313ac6d9c443537b79622f6b936bb0b87c Mon Sep 17 00:00:00 2001
From: Yehor Kharchenko <yehorkharchenko4@gmail.com>
Date: Thu, 11 Jun 2026 13:46:12 +0200
Subject: [PATCH 347/435] add explanatory comments

---
 src/CONST/index.ts                                 |  1 +
 .../MoneyRequestHeaderSecondaryActions.tsx         |  7 ++++++-
 src/hooks/useExpenseActions.ts                     | 14 ++++++++++++--
 3 files changed, 19 insertions(+), 3 deletions(-)

diff --git a/src/CONST/index.ts b/src/CONST/index.ts
index b252784da175..90ade804bc83 100644
--- a/src/CONST/index.ts
+++ b/src/CONST/index.ts
@@ -253,6 +253,7 @@ const CONST = {
     COMPOSER_FOCUS_DELAY: 150,
     MAX_TRANSITION_DURATION_MS: 1000,
     MAX_TRANSITION_START_WAIT_MS: 1000,
+    EXPENSE_REPORT_DELETE_DELAY_MS: 300,
     ANIMATION_DIRECTION: {
         IN: 'in',
         OUT: 'out',
diff --git a/src/components/MoneyRequestHeaderSecondaryActions.tsx b/src/components/MoneyRequestHeaderSecondaryActions.tsx
index 28b15b4bde51..06853e7011b7 100644
--- a/src/components/MoneyRequestHeaderSecondaryActions.tsx
+++ b/src/components/MoneyRequestHeaderSecondaryActions.tsx
@@ -481,7 +481,12 @@ function MoneyRequestHeaderSecondaryActions({reportID, onBackButtonPress}: Money
                         };
                     }
                     if (isInNarrowPaneModal) {
-                        Navigation.navigateBackToLastSuperWideRHPScreen({afterTransition: () => setTimeout(() => afterDelete?.(), 300)});
+                        // The super wide RHP close animation was changed, and because of that the report was deleted right after
+                        // the animation finished, which caused flickering in the reports list. We want the user to see
+                        // the expense in the list for a little bit longer, so we wait for the animation to finish and then
+                        // add an additional delay before removing it.
+                        // See https://github.com/Expensify/App/issues/92036
+                        Navigation.navigateBackToLastSuperWideRHPScreen({afterTransition: () => setTimeout(() => afterDelete?.(), CONST.EXPENSE_REPORT_DELETE_DELAY_MS)});
                         return;
                     }
 
diff --git a/src/hooks/useExpenseActions.ts b/src/hooks/useExpenseActions.ts
index 89b65c3af5a7..3950ae6fae7b 100644
--- a/src/hooks/useExpenseActions.ts
+++ b/src/hooks/useExpenseActions.ts
@@ -513,6 +513,11 @@ function useExpenseActions({reportID, isReportInSearch = false, backTo, onDuplic
                         if (goBackRoute) {
                             navigateOnDeleteExpense(goBackRoute);
                         }
+                        // The wide RHP close animation was changed, and because of that the expense was deleted right after
+                        // the animation finished, which caused flickering in the expenses list. We want the user to see
+                        // the expense in the list for a little bit longer, so we wait for the animation to finish and then
+                        // add an additional delay before removing it.
+                        // See https://github.com/Expensify/App/issues/92036
                         TransitionTracker.runAfterTransitions({
                             callback: () => {
                                 setTimeout(() => {
@@ -529,7 +534,7 @@ function useExpenseActions({reportID, isReportInSearch = false, backTo, onDuplic
                                     }
 
                                     removeTransaction(transaction.transactionID);
-                                }, 300);
+                                }, CONST.EXPENSE_REPORT_DELETE_DELAY_MS);
                             },
                             waitForUpcomingTransition: true,
                         });
@@ -551,6 +556,11 @@ function useExpenseActions({reportID, isReportInSearch = false, backTo, onDuplic
                 const deleteNavigateBackUrl = backToRoute ?? Navigation.getActiveRoute();
                 setDeleteTransactionNavigateBackUrl(deleteNavigateBackUrl);
 
+                // The wide RHP close animation was changed, and because of that the report was deleted right after
+                // the animation finished, which caused flickering in the reports list. We want the user to see
+                // the report in the list for a little bit longer, so we wait for the animation to finish and then
+                // add an additional delay before removing it.
+                // See https://github.com/Expensify/App/issues/92036
                 Navigation.setNavigationActionToMicrotaskQueue(() => {
                     Navigation.goBack(backToRoute, {
                         afterTransition: () => {
@@ -565,7 +575,7 @@ function useExpenseActions({reportID, isReportInSearch = false, backTo, onDuplic
                                     bankAccountList,
                                     hash: currentSearchHash,
                                 });
-                            }, 300);
+                            }, CONST.EXPENSE_REPORT_DELETE_DELAY_MS);
                         },
                     });
                 });

From fe6c5fe33795373f3565a54275763cb40bbf3210 Mon Sep 17 00:00:00 2001
From: nabi-ebrahimi <nabi.zarin.work@gmail.com>
Date: Wed, 20 May 2026 14:42:26 +0430
Subject: [PATCH 348/435] fix(invoice): allow adding a second bank account to
 invoices

---
 .../workspace/invoices/WorkspaceInvoiceVBASection.tsx    | 9 +++++++--
 1 file changed, 7 insertions(+), 2 deletions(-)

diff --git a/src/pages/workspace/invoices/WorkspaceInvoiceVBASection.tsx b/src/pages/workspace/invoices/WorkspaceInvoiceVBASection.tsx
index 849baa0567a4..d743a10a982d 100644
--- a/src/pages/workspace/invoices/WorkspaceInvoiceVBASection.tsx
+++ b/src/pages/workspace/invoices/WorkspaceInvoiceVBASection.tsx
@@ -53,11 +53,16 @@ function WorkspaceInvoiceVBASection({policyID, canWriteMoreFeatures, showReadOnl
     const {showConfirmModal} = useConfirmModal();
     // Determines whether or not the modal popup is mounted from the bottom of the screen instead of the side mount on Web screen
     const isPopoverBottomMount = shouldUseNarrowLayout;
-    const shouldShowMakeDefaultButton = !paymentMethod.isSelectedPaymentMethodDefault;
     const transferBankAccountID = policy?.invoice?.bankAccount?.transferBankAccountID ?? CONST.DEFAULT_NUMBER_ID;
     const [reimbursementAccount] = useOnyx(ONYXKEYS.REIMBURSEMENT_ACCOUNT);
 
-    const hasValidExistingAccounts = getEligibleExistingBusinessBankAccounts(bankAccountList, policy?.outputCurrency).length > 0;
+    const eligibleBusinessBankAccounts = getEligibleExistingBusinessBankAccounts(bankAccountList, policy?.outputCurrency);
+    const hasValidExistingAccounts = eligibleBusinessBankAccounts.length > 0;
+    const hasMultipleEligibleBankAccounts = eligibleBusinessBankAccounts.length > 1;
+    const hasInvoiceDefaultBankAccount = transferBankAccountID !== CONST.DEFAULT_NUMBER_ID;
+    const isInvoiceDefaultBankAccountMissing =
+        hasInvoiceDefaultBankAccount && !eligibleBusinessBankAccounts.some((account) => account.accountData?.bankAccountID === transferBankAccountID);
+    const shouldShowMakeDefaultButton = !paymentMethod.isSelectedPaymentMethodDefault && (hasMultipleEligibleBankAccounts || isInvoiceDefaultBankAccountMissing);
     const isSupportedGlobalReimbursement = isCurrencySupportedForGlobalReimbursement((policy?.outputCurrency ?? '') as CurrencyType);
 
     const isNonUSDWorkspace = policy?.outputCurrency !== CONST.CURRENCY.USD;

From e5545eccbce644c73fce4ed82684a6c76922ada4 Mon Sep 17 00:00:00 2001
From: nabi-ebrahimi <nabi.zarin.work@gmail.com>
Date: Wed, 20 May 2026 17:48:27 +0430
Subject: [PATCH 349/435] prettier fixed

---
 src/pages/workspace/invoices/WorkspaceInvoiceVBASection.tsx | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/src/pages/workspace/invoices/WorkspaceInvoiceVBASection.tsx b/src/pages/workspace/invoices/WorkspaceInvoiceVBASection.tsx
index d743a10a982d..957b42360424 100644
--- a/src/pages/workspace/invoices/WorkspaceInvoiceVBASection.tsx
+++ b/src/pages/workspace/invoices/WorkspaceInvoiceVBASection.tsx
@@ -60,8 +60,7 @@ function WorkspaceInvoiceVBASection({policyID, canWriteMoreFeatures, showReadOnl
     const hasValidExistingAccounts = eligibleBusinessBankAccounts.length > 0;
     const hasMultipleEligibleBankAccounts = eligibleBusinessBankAccounts.length > 1;
     const hasInvoiceDefaultBankAccount = transferBankAccountID !== CONST.DEFAULT_NUMBER_ID;
-    const isInvoiceDefaultBankAccountMissing =
-        hasInvoiceDefaultBankAccount && !eligibleBusinessBankAccounts.some((account) => account.accountData?.bankAccountID === transferBankAccountID);
+    const isInvoiceDefaultBankAccountMissing = hasInvoiceDefaultBankAccount && !eligibleBusinessBankAccounts.some((account) => account.accountData?.bankAccountID === transferBankAccountID);
     const shouldShowMakeDefaultButton = !paymentMethod.isSelectedPaymentMethodDefault && (hasMultipleEligibleBankAccounts || isInvoiceDefaultBankAccountMissing);
     const isSupportedGlobalReimbursement = isCurrencySupportedForGlobalReimbursement((policy?.outputCurrency ?? '') as CurrencyType);
 

From 71e75dad33b089e325ece5356df55e0e549e583f Mon Sep 17 00:00:00 2001
From: nabi-ebrahimi <nabi.zarin.work@gmail.com>
Date: Sat, 23 May 2026 12:55:05 +0430
Subject: [PATCH 350/435] Fix add new invoice bank account flow

---
 .../ConnectExistingBusinessBankAccountPage.tsx         | 10 +++++++++-
 1 file changed, 9 insertions(+), 1 deletion(-)

diff --git a/src/pages/workspace/ConnectExistingBusinessBankAccountPage.tsx b/src/pages/workspace/ConnectExistingBusinessBankAccountPage.tsx
index ab01c80178b9..19ecb3faceeb 100644
--- a/src/pages/workspace/ConnectExistingBusinessBankAccountPage.tsx
+++ b/src/pages/workspace/ConnectExistingBusinessBankAccountPage.tsx
@@ -9,6 +9,7 @@ import useOnyx from '@hooks/useOnyx';
 import useResponsiveLayout from '@hooks/useResponsiveLayout';
 import useThemeStyles from '@hooks/useThemeStyles';
 import {isBankAccountPartiallySetup} from '@libs/BankAccountUtils';
+import {REIMBURSEMENT_ACCOUNT_ROUTE_NAMES} from '@libs/ReimbursementAccountUtils';
 import Navigation from '@navigation/Navigation';
 import type {PlatformStackScreenProps} from '@navigation/PlatformStackNavigation/types';
 import type {ConnectExistingBankAccountNavigatorParamList} from '@navigation/types';
@@ -19,6 +20,7 @@ import {setWorkspaceReimbursement} from '@userActions/Policy/Policy';
 import {navigateToBankAccountRoute} from '@userActions/ReimbursementAccount';
 import CONST from '@src/CONST';
 import ONYXKEYS from '@src/ONYXKEYS';
+import ROUTES from '@src/ROUTES';
 import type SCREENS from '@src/SCREENS';
 
 type ConnectExistingBusinessBankAccountPageProps = PlatformStackScreenProps<ConnectExistingBankAccountNavigatorParamList, typeof SCREENS.CONNECT_EXISTING_BUSINESS_BANK_ACCOUNT_ROOT>;
@@ -38,7 +40,13 @@ function ConnectExistingBusinessBankAccountPage({route}: ConnectExistingBusiness
     const {translate} = useLocalize();
 
     const handleAddBankAccountPress = () => {
-        navigateToBankAccountRoute({policyID, backTo});
+        Navigation.navigate(
+            ROUTES.BANK_ACCOUNT_WITH_STEP_TO_OPEN.getRoute({
+                policyID,
+                stepToOpen: REIMBURSEMENT_ACCOUNT_ROUTE_NAMES.NEW,
+                backTo,
+            }),
+        );
     };
 
     const handleItemPress = ({methodID, accountData}: PaymentMethodPressHandlerParams) => {

From fd105f66a25206ae31bb4bd1799d4448c654bb65 Mon Sep 17 00:00:00 2001
From: nabi-ebrahimi <nabi.zarin.work@gmail.com>
Date: Tue, 2 Jun 2026 10:30:53 +0430
Subject: [PATCH 351/435] fix: allow adding additional invoice bank accounts

---
 .../ReimbursementAccountPage.tsx                     | 10 ++++++++--
 .../ConnectExistingBusinessBankAccountPage.tsx       | 12 +++++-------
 2 files changed, 13 insertions(+), 9 deletions(-)

diff --git a/src/pages/ReimbursementAccount/ReimbursementAccountPage.tsx b/src/pages/ReimbursementAccount/ReimbursementAccountPage.tsx
index 59924eca1837..f93e797ba791 100644
--- a/src/pages/ReimbursementAccount/ReimbursementAccountPage.tsx
+++ b/src/pages/ReimbursementAccount/ReimbursementAccountPage.tsx
@@ -28,7 +28,7 @@ import Navigation from '@libs/Navigation/Navigation';
 import type {PlatformStackScreenProps} from '@libs/Navigation/PlatformStackNavigation/types';
 import type {ReimbursementAccountNavigatorParamList} from '@libs/Navigation/types';
 import {goBackFromInvalidPolicy, isPendingDeletePolicy, isPolicyAdmin} from '@libs/PolicyUtils';
-import {hasInProgressUSDVBBA, hasInProgressVBBA} from '@libs/ReimbursementAccountUtils';
+import {hasInProgressUSDVBBA, hasInProgressVBBA, REIMBURSEMENT_ACCOUNT_ROUTE_NAMES} from '@libs/ReimbursementAccountUtils';
 import shouldReopenOnfido from '@libs/shouldReopenOnfido';
 import type {SkeletonSpanReasonAttributes} from '@libs/telemetry/useSkeletonSpan';
 import {isFullScreenName} from '@navigation/helpers/isNavigatorName';
@@ -97,6 +97,7 @@ function ReimbursementAccountPage({route, policy, isLoadingPolicy}: Reimbursemen
     const {translate} = useLocalize();
     const {isOffline} = useNetwork();
     const requestorStepRef = useRef<View>(null);
+    const hasRequestedNewBankAccountRef = useRef(false);
     const prevReimbursementAccount = usePrevious(reimbursementAccount);
     const prevIsOffline = usePrevious(isOffline);
     const achData = reimbursementAccount?.achData;
@@ -230,7 +231,9 @@ function ReimbursementAccountPage({route, policy, isLoadingPolicy}: Reimbursemen
     }
 
     useEffect(() => {
-        if ((isPreviousPolicy && !!reimbursementAccount) || isLoadingOnyxValue(reimbursementAccountMetadata)) {
+        // Consume this route intent only once so the response changing isPreviousPolicy does not trigger another request.
+        const shouldOpenNewBankAccount = route.params.stepToOpen === REIMBURSEMENT_ACCOUNT_ROUTE_NAMES.NEW && !hasRequestedNewBankAccountRef.current;
+        if ((!shouldOpenNewBankAccount && isPreviousPolicy && !!reimbursementAccount) || isLoadingOnyxValue(reimbursementAccountMetadata)) {
             return;
         }
 
@@ -245,6 +248,9 @@ function ReimbursementAccountPage({route, policy, isLoadingPolicy}: Reimbursemen
             setBankAccountSubStep(null);
             setPlaidEvent(null);
         }
+        if (shouldOpenNewBankAccount) {
+            hasRequestedNewBankAccountRef.current = true;
+        }
         fetchData();
         // eslint-disable-next-line react-hooks/exhaustive-deps
     }, [isPreviousPolicy]); // Only re-run this effect when isPreviousPolicy changes, which happens once when the component first loads
diff --git a/src/pages/workspace/ConnectExistingBusinessBankAccountPage.tsx b/src/pages/workspace/ConnectExistingBusinessBankAccountPage.tsx
index 19ecb3faceeb..9481aba9e13d 100644
--- a/src/pages/workspace/ConnectExistingBusinessBankAccountPage.tsx
+++ b/src/pages/workspace/ConnectExistingBusinessBankAccountPage.tsx
@@ -10,6 +10,7 @@ import useResponsiveLayout from '@hooks/useResponsiveLayout';
 import useThemeStyles from '@hooks/useThemeStyles';
 import {isBankAccountPartiallySetup} from '@libs/BankAccountUtils';
 import {REIMBURSEMENT_ACCOUNT_ROUTE_NAMES} from '@libs/ReimbursementAccountUtils';
+import {appendParam} from '@libs/Url';
 import Navigation from '@navigation/Navigation';
 import type {PlatformStackScreenProps} from '@navigation/PlatformStackNavigation/types';
 import type {ConnectExistingBankAccountNavigatorParamList} from '@navigation/types';
@@ -40,13 +41,10 @@ function ConnectExistingBusinessBankAccountPage({route}: ConnectExistingBusiness
     const {translate} = useLocalize();
 
     const handleAddBankAccountPress = () => {
-        Navigation.navigate(
-            ROUTES.BANK_ACCOUNT_WITH_STEP_TO_OPEN.getRoute({
-                policyID,
-                stepToOpen: REIMBURSEMENT_ACCOUNT_ROUTE_NAMES.NEW,
-                backTo,
-            }),
-        );
+        setReimbursementAccountLoading(true);
+        Navigation.setNavigationActionToMicrotaskQueue(() => {
+            Navigation.navigate(appendParam(ROUTES.BANK_ACCOUNT_WITH_STEP_TO_OPEN.getRoute({policyID, backTo}), 'stepToOpen', REIMBURSEMENT_ACCOUNT_ROUTE_NAMES.NEW));
+        });
     };
 
     const handleItemPress = ({methodID, accountData}: PaymentMethodPressHandlerParams) => {

From a1e42abe170fa327d346f831d2dabec1773caa71 Mon Sep 17 00:00:00 2001
From: nabi-ebrahimi <nabi.zarin.work@gmail.com>
Date: Sat, 6 Jun 2026 14:37:48 +0430
Subject: [PATCH 352/435] fix: update invoice default after deleting bank
 account

---
 .../invoices/WorkspaceInvoiceVBASection.tsx         | 13 ++++++++++---
 1 file changed, 10 insertions(+), 3 deletions(-)

diff --git a/src/pages/workspace/invoices/WorkspaceInvoiceVBASection.tsx b/src/pages/workspace/invoices/WorkspaceInvoiceVBASection.tsx
index 957b42360424..4766790eb1b8 100644
--- a/src/pages/workspace/invoices/WorkspaceInvoiceVBASection.tsx
+++ b/src/pages/workspace/invoices/WorkspaceInvoiceVBASection.tsx
@@ -110,10 +110,17 @@ function WorkspaceInvoiceVBASection({policyID, canWriteMoreFeatures, showReadOnl
 
     const deletePaymentMethod = useCallback(() => {
         const bankAccountID = paymentMethod.selectedPaymentMethod.bankAccountID;
-        if (paymentMethod.selectedPaymentMethodType === CONST.PAYMENT_METHODS.PERSONAL_BANK_ACCOUNT && bankAccountID) {
-            deletePaymentBankAccount(bankAccountID, personalPolicyID);
+        if (paymentMethod.selectedPaymentMethodType !== CONST.PAYMENT_METHODS.PERSONAL_BANK_ACCOUNT || !bankAccountID) {
+            return;
+        }
+
+        const remainingEligibleBankAccountID = eligibleBusinessBankAccounts.find((account) => account.accountData?.bankAccountID !== bankAccountID)?.accountData?.bankAccountID;
+        if (transferBankAccountID === bankAccountID && remainingEligibleBankAccountID) {
+            setInvoicingTransferBankAccount(remainingEligibleBankAccountID, policyID, bankAccountID);
         }
-    }, [paymentMethod.selectedPaymentMethod.bankAccountID, paymentMethod.selectedPaymentMethodType, personalPolicyID]);
+
+        deletePaymentBankAccount(bankAccountID, personalPolicyID);
+    }, [eligibleBusinessBankAccounts, paymentMethod.selectedPaymentMethod.bankAccountID, paymentMethod.selectedPaymentMethodType, personalPolicyID, policyID, transferBankAccountID]);
 
     const makeDefaultPaymentMethod = useCallback(() => {
         // Find the previous default payment method so we can revert if the MakeDefaultPaymentMethod command errors

From c03de11e714fa608755211b66c0795810bc20f8f Mon Sep 17 00:00:00 2001
From: krishna2323 <belivethatkg@gmail.com>
Date: Thu, 11 Jun 2026 17:23:25 +0530
Subject: [PATCH 353/435] Add seatbelt entries for GroupChildrenContent and
 GroupHeader type assertions

Signed-off-by: krishna2323 <belivethatkg@gmail.com>
---
 config/eslint/eslint.seatbelt.tsv | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/config/eslint/eslint.seatbelt.tsv b/config/eslint/eslint.seatbelt.tsv
index 57557c64e0ce..2fec366097e9 100644
--- a/config/eslint/eslint.seatbelt.tsv
+++ b/config/eslint/eslint.seatbelt.tsv
@@ -378,6 +378,8 @@
 "../../src/components/Search/SearchList/ListItem/ExpenseReportListItem.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	5
 "../../src/components/Search/SearchList/ListItem/ExpenseReportListItemRow/ExpenseReportListItemRowWide.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../src/components/Search/SearchList/ListItem/MemberListItemHeader.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	2
+"../../src/components/Search/SearchList/ListItem/GroupChildrenContent.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	4
+"../../src/components/Search/SearchList/ListItem/GroupHeader.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	3
 "../../src/components/Search/SearchList/ListItem/ReportListItemHeader.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	4
 "../../src/components/Search/SearchList/ListItem/TaskListItem.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../src/components/Search/SearchList/ListItem/TransactionGroupListExpanded.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	3

From 996de87a068424763683a5192a3487d6d3548e56 Mon Sep 17 00:00:00 2001
From: thelullabyy <182625428+thelullabyy@users.noreply.github.com>
Date: Thu, 11 Jun 2026 07:02:37 -0500
Subject: [PATCH 354/435] fix: typescript check

---
 src/libs/actions/connections/FinancialForce.ts | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/src/libs/actions/connections/FinancialForce.ts b/src/libs/actions/connections/FinancialForce.ts
index 2a421db93360..14230aa74776 100644
--- a/src/libs/actions/connections/FinancialForce.ts
+++ b/src/libs/actions/connections/FinancialForce.ts
@@ -11,6 +11,7 @@ import ONYXKEYS from '@src/ONYXKEYS';
 import type {FinancialForceConnectionConfig} from '@src/types/onyx/Policy';
 
 type FinancialForceFFAExportStatus = typeof CONST.CERTINIA_EXPORT_STATUS.APPROVED | typeof CONST.CERTINIA_EXPORT_STATUS.IN_PROGRESS;
+type FinancialForceReportExportStatus = typeof CONST.CERTINIA_EXPORT_STATUS.APPROVED | typeof CONST.CERTINIA_EXPORT_STATUS.SUBMITTED;
 
 function prepareOnyxDataForFinancialForceCodingUpdate<K extends keyof FinancialForceConnectionConfig['coding']>(
     policyID: string,
@@ -519,14 +520,14 @@ function updateFinancialForceSyncMilestones(policyID: string, enabled: boolean,
     write(WRITE_COMMANDS.UPDATE_FINANCIAL_FORCE_SYNC_MILESTONES, {policyID, enabled}, {optimisticData, failureData, successData});
 }
 
-function updateFinancialForceReportExportStatus(policyID: string, status: ValueOf<typeof CONST.CERTINIA_EXPORT_STATUS>, previousStatus: ValueOf<typeof CONST.CERTINIA_EXPORT_STATUS> | null) {
+function updateFinancialForceReportExportStatus(policyID: string, status: FinancialForceReportExportStatus, previousStatus: ValueOf<typeof CONST.CERTINIA_EXPORT_STATUS> | null) {
     const {optimisticData, failureData, successData} = prepareOnyxDataForFinancialForceExportUpdate(
         policyID,
         CONST.CERTINIA_CONFIG.REPORT_EXPORT_STATUS,
         status,
         previousStatus ?? undefined,
     );
-    write(WRITE_COMMANDS.UPDATE_FINANCIAL_FORCE_REPORT_EXPORT_STATUS, {policyID, reportExportStatus: status}, {optimisticData, failureData, successData});
+    write(WRITE_COMMANDS.UPDATE_FINANCIAL_FORCE_REPORT_EXPORT_STATUS, {policyID, exportStatus: status}, {optimisticData, failureData, successData});
 }
 
 function updateFinancialForceTaxNonBillable(policyID: string, enabled: boolean, previousValue?: boolean) {

From c00034caf956788a9bfd8e1ae3660c843af42b81 Mon Sep 17 00:00:00 2001
From: eliran goshen <elirangoshen@gmail.com>
Date: Thu, 11 Jun 2026 14:08:39 +0200
Subject: [PATCH 355/435] Bump Onyx to 3.0.83

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
---
 package-lock.json | 8 ++++----
 package.json      | 2 +-
 2 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/package-lock.json b/package-lock.json
index 620ab9bee353..569b70f78aee 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -120,7 +120,7 @@
         "react-native-localize": "^3.5.4",
         "react-native-nitro-modules": "0.35.0",
         "react-native-nitro-sqlite": "9.6.0",
-        "react-native-onyx": "3.0.80",
+        "react-native-onyx": "3.0.83",
         "react-native-pager-view": "8.0.0",
         "react-native-pdf": "7.0.2",
         "react-native-permissions": "^5.4.0",
@@ -35673,9 +35673,9 @@
       }
     },
     "node_modules/react-native-onyx": {
-      "version": "3.0.80",
-      "resolved": "https://registry.npmjs.org/react-native-onyx/-/react-native-onyx-3.0.80.tgz",
-      "integrity": "sha512-rXcHgLi0V7LkkPsim7P+ULQKHCWzWqER+Hx4fDmt+omwtVD3n0LpuV63Fq91/g8cEl6PT4okmYseMVDUUSQPLA==",
+      "version": "3.0.83",
+      "resolved": "https://registry.npmjs.org/react-native-onyx/-/react-native-onyx-3.0.83.tgz",
+      "integrity": "sha512-/OIwvQeXkVaKNsdHWbS1T/16o0iWOlX5KOMF6USKq3ePRVfhBzEOczNgtchAZ5MDStqnZMLNbOsTLwFjLJu56w==",
       "license": "MIT",
       "dependencies": {
         "ascii-table": "0.0.9",
diff --git a/package.json b/package.json
index a6238f2779c4..59ba7ddee2c2 100644
--- a/package.json
+++ b/package.json
@@ -193,7 +193,7 @@
     "react-native-localize": "^3.5.4",
     "react-native-nitro-modules": "0.35.0",
     "react-native-nitro-sqlite": "9.6.0",
-    "react-native-onyx": "3.0.80",
+    "react-native-onyx": "3.0.83",
     "react-native-pager-view": "8.0.0",
     "react-native-pdf": "7.0.2",
     "react-native-permissions": "^5.4.0",

From f0ef5942fa234958681837f6ad43430558eceb4f Mon Sep 17 00:00:00 2001
From: OSBotify <infra+osbotify@expensify.com>
Date: Thu, 11 Jun 2026 12:16:56 +0000
Subject: [PATCH 356/435] Auto-tighten eslint-seatbelt baseline

---
 config/eslint/eslint.seatbelt.tsv | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/config/eslint/eslint.seatbelt.tsv b/config/eslint/eslint.seatbelt.tsv
index 2ca211aa316d..fecbf24e69bc 100644
--- a/config/eslint/eslint.seatbelt.tsv
+++ b/config/eslint/eslint.seatbelt.tsv
@@ -1912,7 +1912,7 @@
 "../../tests/unit/hooks/useDraftMessageVideoAttributeCache.test.ts"	"@typescript-eslint/no-unsafe-type-assertion"	2
 "../../tests/unit/hooks/useEditComposerToggle.test.ts"	"@typescript-eslint/no-unsafe-type-assertion"	2
 "../../tests/unit/hooks/useEditMessage.test.ts"	"@typescript-eslint/no-unsafe-type-assertion"	2
-"../../tests/unit/hooks/useExpenseSubmission.test.ts"	"@typescript-eslint/no-unsafe-type-assertion"	3
+"../../tests/unit/hooks/useExpenseSubmission.test.ts"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../tests/unit/hooks/useExpensifyCardFeedsForFeedSelector.test.ts"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../tests/unit/hooks/useExportedToFilterOptions.test.ts"	"@typescript-eslint/no-unsafe-type-assertion"	5
 "../../tests/unit/hooks/useFilterFeedDataTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	2

From 568a52e978e34ed03f7f908c988a2ad2e50c7e04 Mon Sep 17 00:00:00 2001
From: jayeshmangwani <jayeshmangwani@gmail.com>
Date: Thu, 11 Jun 2026 17:48:07 +0530
Subject: [PATCH 357/435] removed Mobile-Expensify changes

---
 Mobile-Expensify | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Mobile-Expensify b/Mobile-Expensify
index 3ae1b55b0890..42ad9da8bfde 160000
--- a/Mobile-Expensify
+++ b/Mobile-Expensify
@@ -1 +1 @@
-Subproject commit 3ae1b55b0890c20d9307455ccc1da984bf005805
+Subproject commit 42ad9da8bfde582b57b2e66dc30e22757e06deea

From bdb8ca3a9ab3112ce2fd4cff7090a4000fb6e45c Mon Sep 17 00:00:00 2001
From: Yehor Kharchenko <yehorkharchenko4@gmail.com>
Date: Thu, 11 Jun 2026 14:45:39 +0200
Subject: [PATCH 358/435] add info to interaction manager migration doc +
 remove lint rule

---
 config/eslint/eslint.config.mjs           |  5 -----
 contributingGuides/INTERACTION_MANAGER.md | 18 +++++++++++++++++-
 2 files changed, 17 insertions(+), 6 deletions(-)

diff --git a/config/eslint/eslint.config.mjs b/config/eslint/eslint.config.mjs
index f41e62edc95c..d1b79f37f579 100644
--- a/config/eslint/eslint.config.mjs
+++ b/config/eslint/eslint.config.mjs
@@ -157,11 +157,6 @@ const restrictedImportPaths = [
 ];
 
 const restrictedImportPatterns = [
-    {
-        group: ['**/TransitionTracker', './TransitionTracker', '../TransitionTracker'],
-        message:
-            "TransitionTracker is an internal primitive. Please use higher-level APIs (Navigation with 'afterTransition'/'waitForTransition', KeyboardUtils, useConfirmModal). See contributingGuides/INTERACTION_MANAGER.md.",
-    },
     {
         group: ['**/assets/animations/**/*.json'],
         message: "Do not import animations directly. Please use the '@components/LottieAnimations' import instead.",
diff --git a/contributingGuides/INTERACTION_MANAGER.md b/contributingGuides/INTERACTION_MANAGER.md
index 08008b0b42ad..e4fe289b58a6 100644
--- a/contributingGuides/INTERACTION_MANAGER.md
+++ b/contributingGuides/INTERACTION_MANAGER.md
@@ -29,7 +29,23 @@ On top of TransitionTracker, existing APIs gain transition-aware callbacks:
 
 This makes the code self-descriptive: instead of a generic `runAfterInteractions`, each call site says exactly what it's waiting for and why.
 
-> **Note:** `TransitionTracker.runAfterTransitions` is an internal primitive. Application code should use the higher-level APIs (`Navigation`, `useConfirmModal`, etc.) rather than importing TransitionTracker directly.
+### When to use `runAfterTransitions` directly
+
+Prefer higher-level APIs (`Navigation` with `afterTransition`/`waitForTransition`, `KeyboardUtils`, `useConfirmModal`) whenever possible. Use `TransitionTracker.runAfterTransitions` directly **only** when:
+
+- There is no specific navigation/keyboard/modal action you can attach a callback to, or
+- There are too many concurrent actions and it's impossible to bind the callback to a particular one.
+
+### How `runAfterTransitions` works
+
+1. If there are ongoing transitions at the time of the call, the callback is enqueued and waits until all current transitions complete.
+2. If there are no ongoing transitions, the callback executes in the same tick.
+
+### The same-tick race condition
+
+Sometimes a transition starts in the same tick as the `runAfterTransitions` call. Because TransitionTracker hasn't registered the transition yet, the callback fires immediately - before the transition even begins.
+
+To fix this, pass the `waitForUpcomingTransition` flag along with the callback. This tells TransitionTracker to wait for a transition that hasn't started yet, ensuring the callback truly runs after the transition completes.
 
 ## How
 The migration is split into 9 issues. Current status of the migration can be found in the parent Github issue [here](https://github.com/Expensify/App/issues/71913). 

From d3028dde169a43be68699f76feace487e94507e9 Mon Sep 17 00:00:00 2001
From: Dariusz Biela <dariusz.biela.dev@gmail.com>
Date: Thu, 11 Jun 2026 15:19:35 +0200
Subject: [PATCH 359/435] Reactivate MFA screen focus trap after cancel
 confirmation closes

An outside click deactivates the screen trap by design (RHP behavior), which
left Tab able to move focus outside the MFA panel for the rest of the screen's
lifetime. Drive the trap's active prop from the cancel-confirmation visibility:
the trap is off while the modal is up (so it can't swallow the modal's clicks)
and the prop flip on close reactivates it.
---
 src/pages/MultifactorAuthentication/PromptPage.tsx    | 11 ++++++-----
 .../MultifactorAuthentication/ValidateCodePage.tsx    | 10 +++++-----
 2 files changed, 11 insertions(+), 10 deletions(-)

diff --git a/src/pages/MultifactorAuthentication/PromptPage.tsx b/src/pages/MultifactorAuthentication/PromptPage.tsx
index dc15b0d3932c..35588b068fb3 100644
--- a/src/pages/MultifactorAuthentication/PromptPage.tsx
+++ b/src/pages/MultifactorAuthentication/PromptPage.tsx
@@ -5,7 +5,7 @@ import Button from '@components/Button';
 import FixedFooter from '@components/FixedFooter';
 import HeaderWithBackButton from '@components/HeaderWithBackButton';
 import LoadingIndicator from '@components/LoadingIndicator';
-import {useMultifactorAuthentication, useMultifactorAuthenticationActions, usePromptContent} from '@components/MultifactorAuthentication/Context';
+import {useMultifactorAuthentication, useMultifactorAuthenticationActions, useMultifactorAuthenticationState, usePromptContent} from '@components/MultifactorAuthentication/Context';
 import MultifactorAuthenticationPromptContent from '@components/MultifactorAuthentication/PromptContent';
 import ScreenWrapper from '@components/ScreenWrapper';
 import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails';
@@ -24,6 +24,7 @@ function MultifactorAuthenticationPromptPage({route}: MultifactorAuthenticationP
     const styles = useThemeStyles();
     const {requestCancel} = useMultifactorAuthentication();
     const {dispatch} = useMultifactorAuthenticationActions();
+    const {isCancelConfirmVisible} = useMultifactorAuthenticationState();
     const {accountID} = useCurrentUserPersonalDetails();
 
     const {illustration, title, subtitle, shouldDisplayConfirmButton} = usePromptContent(route.params.promptType);
@@ -33,10 +34,7 @@ function MultifactorAuthenticationPromptPage({route}: MultifactorAuthenticationP
         dispatch({type: 'SET_SOFT_PROMPT_APPROVED', payload: true});
     };
 
-    // Escape routes through the central cancel handler; returning false keeps the trap active.
-    // Outside clicks must keep the default behavior (deactivate the trap and pass through, like
-    // RHP screens): they reach the navigator's backdrop, which requests the cancel flow, and an
-    // intercepting trap would swallow every click aimed at the portal-rendered cancel-confirm modal.
+    // Escape opens the cancel confirmation; returning false keeps the trap active.
     const interceptFocusTrapEscape = () => {
         requestCancel();
         return false;
@@ -46,6 +44,9 @@ function MultifactorAuthenticationPromptPage({route}: MultifactorAuthenticationP
         <ScreenWrapper
             testID={MultifactorAuthenticationPromptPage.displayName}
             focusTrapSettings={{
+                // Turn the trap off while the cancel confirmation modal is up so it can't swallow
+                // the modal's clicks, and back on when it closes. See https://github.com/Expensify/App/issues/93193
+                active: isCancelConfirmVisible ? false : undefined,
                 focusTrapOptions: {
                     escapeDeactivates: interceptFocusTrapEscape,
                 },
diff --git a/src/pages/MultifactorAuthentication/ValidateCodePage.tsx b/src/pages/MultifactorAuthentication/ValidateCodePage.tsx
index 7db6789005b7..5b4cffba0195 100644
--- a/src/pages/MultifactorAuthentication/ValidateCodePage.tsx
+++ b/src/pages/MultifactorAuthentication/ValidateCodePage.tsx
@@ -50,7 +50,7 @@ function MultifactorAuthenticationValidateCodePage() {
     const {requestCancel} = useMultifactorAuthentication();
 
     const {dispatch} = useMultifactorAuthenticationActions();
-    const {continuableError} = useMultifactorAuthenticationState();
+    const {continuableError, isCancelConfirmVisible} = useMultifactorAuthenticationState();
 
     // Refs
     const inputRef = useRef<MagicCodeInputHandle>(null);
@@ -198,10 +198,7 @@ function MultifactorAuthenticationValidateCodePage() {
         dispatch({type: 'SET_VALIDATE_CODE', payload: inputCode});
     };
 
-    // Escape routes through the central cancel handler; returning false keeps the trap active.
-    // Outside clicks must keep the default behavior (deactivate the trap and pass through, like
-    // RHP screens): they reach the navigator's backdrop, which requests the cancel flow, and an
-    // intercepting trap would swallow every click aimed at the portal-rendered cancel-confirm modal.
+    // Escape opens the cancel confirmation; returning false keeps the trap active.
     const interceptFocusTrapEscape = () => {
         requestCancel();
         return false;
@@ -211,6 +208,9 @@ function MultifactorAuthenticationValidateCodePage() {
         <ScreenWrapper
             testID={MultifactorAuthenticationValidateCodePage.displayName}
             focusTrapSettings={{
+                // Turn the trap off while the cancel confirmation modal is up so it can't swallow
+                // the modal's clicks, and back on when it closes. See https://github.com/Expensify/App/issues/93193
+                active: isCancelConfirmVisible ? false : undefined,
                 focusTrapOptions: {
                     escapeDeactivates: interceptFocusTrapEscape,
                 },

From 329037348df8c8b3cbc7576c898944e967b7174d Mon Sep 17 00:00:00 2001
From: krishna2323 <belivethatkg@gmail.com>
Date: Thu, 11 Jun 2026 18:50:00 +0530
Subject: [PATCH 360/435] Move clear-on-deselect logic into selection
 middleware

Signed-off-by: krishna2323 <belivethatkg@gmail.com>
---
 src/components/Table/middlewares/selection.ts             | 8 ++++++++
 .../workspace/categories/WorkspaceCategoriesPage.tsx      | 8 --------
 .../workspace/distanceRates/PolicyDistanceRatesPage.tsx   | 8 --------
 3 files changed, 8 insertions(+), 16 deletions(-)

diff --git a/src/components/Table/middlewares/selection.ts b/src/components/Table/middlewares/selection.ts
index 3bfefd6efff1..b757664079fd 100644
--- a/src/components/Table/middlewares/selection.ts
+++ b/src/components/Table/middlewares/selection.ts
@@ -70,6 +70,14 @@ export default function useSelection<DataType extends TableData>({data, selected
         turnOffMobileSelectionMode();
     }, [selectableKeys.length, isSelectionModeEnabled]);
 
+    const prevSelectionModeEnabledRef = useRef(isSelectionModeEnabled);
+    useEffect(() => {
+        if (prevSelectionModeEnabledRef.current && !isSelectionModeEnabled) {
+            onRowSelectionChange?.([]);
+        }
+        prevSelectionModeEnabledRef.current = isSelectionModeEnabled;
+    }, [isSelectionModeEnabled, onRowSelectionChange]);
+
     /**
      * Clear all of the currently selected keys
      */
diff --git a/src/pages/workspace/categories/WorkspaceCategoriesPage.tsx b/src/pages/workspace/categories/WorkspaceCategoriesPage.tsx
index 3e5e4626d8a8..c0a611a302f3 100644
--- a/src/pages/workspace/categories/WorkspaceCategoriesPage.tsx
+++ b/src/pages/workspace/categories/WorkspaceCategoriesPage.tsx
@@ -564,14 +564,6 @@ function WorkspaceCategoriesPage({route}: WorkspaceCategoriesPageProps) {
     const isLoading = !isOffline && policyCategories === undefined;
     const reasonAttributes: SkeletonSpanReasonAttributes = {context: 'WorkspaceCategoriesPage', isOffline, isPolicyCategoriesUndefined: policyCategories === undefined};
 
-    useEffect(() => {
-        if (isMobileSelectionModeEnabled) {
-            return;
-        }
-
-        clearTableSelection();
-    }, [clearTableSelection, isMobileSelectionModeEnabled]);
-
     const selectionModeHeader = isMobileSelectionModeEnabled && shouldUseNarrowLayout;
 
     const headerContent = (
diff --git a/src/pages/workspace/distanceRates/PolicyDistanceRatesPage.tsx b/src/pages/workspace/distanceRates/PolicyDistanceRatesPage.tsx
index 378d1078c2f3..de5121011e58 100644
--- a/src/pages/workspace/distanceRates/PolicyDistanceRatesPage.tsx
+++ b/src/pages/workspace/distanceRates/PolicyDistanceRatesPage.tsx
@@ -148,14 +148,6 @@ function PolicyDistanceRatesPage({
 
     useCleanupSelectedOptions(clearTableSelection);
 
-    useEffect(() => {
-        if (isMobileSelectionModeEnabled) {
-            return;
-        }
-
-        clearTableSelection();
-    }, [clearTableSelection, isMobileSelectionModeEnabled]);
-
     const canDisableOrDeleteSelectedRates = useMemo(
         () =>
             Object.keys(selectableRates)

From 8e0989e003d3d844761cf5453d2a970936e866c8 Mon Sep 17 00:00:00 2001
From: mhawryluk <marcinhawrylukxx@gmail.com>
Date: Thu, 11 Jun 2026 15:20:55 +0200
Subject: [PATCH 361/435] fix: Multiple "No merchant" labels in pie chart after
 switching languages

---
 src/components/Charts/PieChart/PieChartContent.tsx | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/components/Charts/PieChart/PieChartContent.tsx b/src/components/Charts/PieChart/PieChartContent.tsx
index 9f60500949eb..8dac9f1946f0 100644
--- a/src/components/Charts/PieChart/PieChartContent.tsx
+++ b/src/components/Charts/PieChart/PieChartContent.tsx
@@ -131,7 +131,7 @@ function PieChartContent({data, isLoading, valueUnit, valueUnitPosition, onSlice
     const renderLegendItem = (slice: PieSlice) => {
         return (
             <View
-                key={`legend-${slice.label}`}
+                key={`legend-${slice.originalIndex}`}
                 style={[styles.flexRow, styles.alignItemsCenter, styles.mr4, styles.mb2]}
                 onMouseEnter={() => {
                     tooltipPosition.set(slice.tooltipPosition);

From 3635a6a50c99a6cf134ffc57bd87663fa0e5dfc9 Mon Sep 17 00:00:00 2001
From: sumo_slonik <jakub.nowakowski@swmansion.com>
Date: Thu, 11 Jun 2026 15:22:25 +0200
Subject: [PATCH 362/435] Remove Created by column from workspace Rooms page

---
 .../WorkspaceRoomsTableRow.tsx                | 34 +------------------
 .../Tables/WorkspaceRoomsTable/index.tsx      |  7 +---
 src/languages/de.ts                           |  1 -
 src/languages/en.ts                           |  1 -
 src/languages/es.ts                           |  1 -
 src/languages/fr.ts                           |  1 -
 src/languages/it.ts                           |  1 -
 src/languages/ja.ts                           |  1 -
 src/languages/nl.ts                           |  1 -
 src/languages/pl.ts                           |  1 -
 src/languages/pt-BR.ts                        |  1 -
 src/languages/zh-hans.ts                      |  1 -
 .../workspace/rooms/WorkspaceRoomsPage.tsx    | 27 ++++++---------
 13 files changed, 12 insertions(+), 66 deletions(-)

diff --git a/src/components/Tables/WorkspaceRoomsTable/WorkspaceRoomsTableRow.tsx b/src/components/Tables/WorkspaceRoomsTable/WorkspaceRoomsTableRow.tsx
index aac049417db3..b7afb850a51b 100644
--- a/src/components/Tables/WorkspaceRoomsTable/WorkspaceRoomsTableRow.tsx
+++ b/src/components/Tables/WorkspaceRoomsTable/WorkspaceRoomsTableRow.tsx
@@ -1,6 +1,5 @@
 import React from 'react';
 import {View} from 'react-native';
-import Avatar from '@components/Avatar';
 import Icon from '@components/Icon';
 import ReportActionAvatars from '@components/ReportActionAvatars';
 import type {TableData} from '@components/Table';
@@ -11,7 +10,6 @@ import {useMemoizedLazyExpensifyIcons} from '@hooks/useLazyAsset';
 import useLocalize from '@hooks/useLocalize';
 import useTheme from '@hooks/useTheme';
 import useThemeStyles from '@hooks/useThemeStyles';
-import type {AvatarSource} from '@libs/UserUtils';
 import variables from '@styles/variables';
 import CONST from '@src/CONST';
 
@@ -22,15 +20,6 @@ type WorkspaceRoomRowData = TableData & {
     /** The room display name */
     name: string;
 
-    /** Owner accountID for resolving the avatar */
-    ownerAccountID?: number;
-
-    /** Owner avatar source */
-    ownerAvatar?: AvatarSource;
-
-    /** Pre-formatted owner display name */
-    ownerDisplayName: string;
-
     /** Number of members in the room */
     memberCount: number;
 
@@ -59,7 +48,6 @@ function WorkspaceRoomsTableRow({item, rowIndex, shouldUseNarrowTableLayout, sho
     const icons = useMemoizedLazyExpensifyIcons(['ArrowRight']);
 
     const memberCountSubtitle = translate('domain.groups.memberCount', {count: item.memberCount});
-    const narrowSubtitle = item.ownerDisplayName ? `${translate('common.createdBy')}: ${item.ownerDisplayName} • ${memberCountSubtitle}` : memberCountSubtitle;
 
     return (
         <Table.Row
@@ -91,7 +79,7 @@ function WorkspaceRoomsTableRow({item, rowIndex, shouldUseNarrowTableLayout, sho
                                     numberOfLines={1}
                                     style={styles.textLabelSupporting}
                                 >
-                                    {narrowSubtitle}
+                                    {memberCountSubtitle}
                                 </Text>
                             </View>
                             <Icon
@@ -121,26 +109,6 @@ function WorkspaceRoomsTableRow({item, rowIndex, shouldUseNarrowTableLayout, sho
                                 />
                             </View>
 
-                            <View style={[styles.flex1, styles.flexRow, styles.gap2, styles.alignItemsCenter]}>
-                                {!!item.ownerDisplayName && (
-                                    <>
-                                        {!!item.ownerAccountID && (
-                                            <Avatar
-                                                source={item.ownerAvatar}
-                                                avatarID={item.ownerAccountID}
-                                                type={CONST.ICON_TYPE_AVATAR}
-                                                size={CONST.AVATAR_SIZE.MID_SUBSCRIPT}
-                                            />
-                                        )}
-                                        <TextWithTooltip
-                                            shouldShowTooltip
-                                            text={item.ownerDisplayName}
-                                            style={styles.flexShrink1}
-                                        />
-                                    </>
-                                )}
-                            </View>
-
                             <View style={styles.flex1}>
                                 <Text numberOfLines={1}>{item.memberCount}</Text>
                             </View>
diff --git a/src/components/Tables/WorkspaceRoomsTable/index.tsx b/src/components/Tables/WorkspaceRoomsTable/index.tsx
index b8466bc88907..2030d43de85e 100644
--- a/src/components/Tables/WorkspaceRoomsTable/index.tsx
+++ b/src/components/Tables/WorkspaceRoomsTable/index.tsx
@@ -10,7 +10,7 @@ import variables from '@styles/variables';
 import WorkspaceRoomsTableRow from './WorkspaceRoomsTableRow';
 import type {WorkspaceRoomRowData} from './WorkspaceRoomsTableRow';
 
-type WorkspaceRoomsTableColumnKey = 'name' | 'createdBy' | 'members' | 'actions';
+type WorkspaceRoomsTableColumnKey = 'name' | 'members' | 'actions';
 
 type WorkspaceRoomsTableProps = {
     /** Pre-built row data for each room */
@@ -46,7 +46,6 @@ function WorkspaceRoomsTable({rooms, highlightedReportID}: WorkspaceRoomsTablePr
 
     const columns: Array<TableColumn<WorkspaceRoomsTableColumnKey>> = [
         {key: 'name', label: translate('common.name'), sortable: true},
-        {key: 'createdBy', label: translate('common.createdBy'), sortable: true},
         {key: 'members', label: translate('common.members'), width: variables.workspaceRoomsMembersColumnWidth, sortable: true},
         {key: 'actions', label: '', width: variables.workspaceRoomsActionsColumnWidth, styling: {containerStyles: [styles.justifyContentEnd, styles.pr3]}, sortable: false},
     ];
@@ -54,10 +53,6 @@ function WorkspaceRoomsTable({rooms, highlightedReportID}: WorkspaceRoomsTablePr
     const compareItems: CompareItemsCallback<WorkspaceRoomRowData, WorkspaceRoomsTableColumnKey> = (a, b, activeSorting) => {
         const orderMultiplier = activeSorting.order === 'asc' ? 1 : -1;
 
-        if (activeSorting.columnKey === 'createdBy') {
-            return orderMultiplier * localeCompare(a.ownerDisplayName, b.ownerDisplayName);
-        }
-
         if (activeSorting.columnKey === 'members') {
             return orderMultiplier * (a.memberCount - b.memberCount);
         }
diff --git a/src/languages/de.ts b/src/languages/de.ts
index 80fc275a1192..8cc9b06bb078 100644
--- a/src/languages/de.ts
+++ b/src/languages/de.ts
@@ -294,7 +294,6 @@ const translations: TranslationDeepObject<typeof en> = {
         description: 'Beschreibung',
         title: 'Titel',
         assignee: 'Zuständige Person',
-        createdBy: 'Erstellt von',
         with: 'mit',
         shareCode: 'Code teilen',
         share: 'Teilen',
diff --git a/src/languages/en.ts b/src/languages/en.ts
index 7a591d68824b..103e36647e87 100644
--- a/src/languages/en.ts
+++ b/src/languages/en.ts
@@ -308,7 +308,6 @@ const translations = {
         description: 'Description',
         title: 'Title',
         assignee: 'Assignee',
-        createdBy: 'Created by',
         with: 'with',
         shareCode: 'Share code',
         share: 'Share',
diff --git a/src/languages/es.ts b/src/languages/es.ts
index ce3647332029..100a7a803377 100644
--- a/src/languages/es.ts
+++ b/src/languages/es.ts
@@ -249,7 +249,6 @@ const translations: TranslationDeepObject<typeof en> = {
         description: 'Descripción',
         title: 'Título',
         assignee: 'Asignado a',
-        createdBy: 'Creado por',
         with: 'con',
         shareCode: 'Compartir código',
         share: 'Compartir',
diff --git a/src/languages/fr.ts b/src/languages/fr.ts
index b6b5208996d1..f8cc3a17fa06 100644
--- a/src/languages/fr.ts
+++ b/src/languages/fr.ts
@@ -294,7 +294,6 @@ const translations: TranslationDeepObject<typeof en> = {
         description: 'Description',
         title: 'Titre',
         assignee: 'Attribué',
-        createdBy: 'Créé par',
         with: 'avec',
         shareCode: 'Partager le code',
         share: 'Partager',
diff --git a/src/languages/it.ts b/src/languages/it.ts
index 03739d9dac38..90243851dea0 100644
--- a/src/languages/it.ts
+++ b/src/languages/it.ts
@@ -294,7 +294,6 @@ const translations: TranslationDeepObject<typeof en> = {
         description: 'Descrizione',
         title: 'Titolo',
         assignee: 'Assegnatario',
-        createdBy: 'Creato da',
         with: 'con',
         shareCode: 'Condividi codice',
         share: 'Condividi',
diff --git a/src/languages/ja.ts b/src/languages/ja.ts
index 0c9cfba5500c..9b00dff43f91 100644
--- a/src/languages/ja.ts
+++ b/src/languages/ja.ts
@@ -294,7 +294,6 @@ const translations: TranslationDeepObject<typeof en> = {
         description: '説明',
         title: 'タイトル',
         assignee: '担当者',
-        createdBy: '作成者',
         with: '〜で',
         shareCode: 'コードを共有',
         share: '共有',
diff --git a/src/languages/nl.ts b/src/languages/nl.ts
index 9437a6e7e3bc..b1a2301e65ac 100644
--- a/src/languages/nl.ts
+++ b/src/languages/nl.ts
@@ -294,7 +294,6 @@ const translations: TranslationDeepObject<typeof en> = {
         description: 'Beschrijving',
         title: 'Titel',
         assignee: 'Toegewezene',
-        createdBy: 'Gemaakt door',
         with: 'met',
         shareCode: 'Code delen',
         share: 'Delen',
diff --git a/src/languages/pl.ts b/src/languages/pl.ts
index 17f55a003160..c064ac440db8 100644
--- a/src/languages/pl.ts
+++ b/src/languages/pl.ts
@@ -294,7 +294,6 @@ const translations: TranslationDeepObject<typeof en> = {
         description: 'Opis',
         title: 'Tytuł',
         assignee: 'Osoba przypisana',
-        createdBy: 'Utworzone przez',
         with: 'z',
         shareCode: 'Udostępnij kod',
         share: 'Udostępnij',
diff --git a/src/languages/pt-BR.ts b/src/languages/pt-BR.ts
index 7cfa67f9d691..1e80399d070c 100644
--- a/src/languages/pt-BR.ts
+++ b/src/languages/pt-BR.ts
@@ -294,7 +294,6 @@ const translations: TranslationDeepObject<typeof en> = {
         description: 'Descrição',
         title: 'Título',
         assignee: 'Responsável',
-        createdBy: 'Criado por',
         with: 'com',
         shareCode: 'Compartilhar código',
         share: 'Compartilhar',
diff --git a/src/languages/zh-hans.ts b/src/languages/zh-hans.ts
index c60fe5de58fc..9c2b496bb542 100644
--- a/src/languages/zh-hans.ts
+++ b/src/languages/zh-hans.ts
@@ -294,7 +294,6 @@ const translations: TranslationDeepObject<typeof en> = {
         description: '描述',
         title: '标题',
         assignee: '受托人',
-        createdBy: '创建者',
         with: '与',
         shareCode: '共享代码',
         share: '分享',
diff --git a/src/pages/workspace/rooms/WorkspaceRoomsPage.tsx b/src/pages/workspace/rooms/WorkspaceRoomsPage.tsx
index a605db3500fc..d1d38618e0aa 100644
--- a/src/pages/workspace/rooms/WorkspaceRoomsPage.tsx
+++ b/src/pages/workspace/rooms/WorkspaceRoomsPage.tsx
@@ -22,7 +22,6 @@ import {openPolicyRoomsPage} from '@libs/actions/Policy/Room';
 import createDynamicRoute from '@libs/Navigation/helpers/dynamicRoutesUtils/createDynamicRoute';
 import Navigation from '@libs/Navigation/Navigation';
 import type {PlatformStackScreenProps} from '@libs/Navigation/PlatformStackNavigation/types';
-import {getDisplayNameOrDefault} from '@libs/PersonalDetailsUtils';
 import {isPolicyAdmin} from '@libs/PolicyUtils';
 import {getReportName} from '@libs/ReportNameUtils';
 import {getParticipantsAccountIDsForDisplay} from '@libs/ReportUtils';
@@ -64,22 +63,16 @@ function WorkspaceRoomsPage({route}: WorkspaceRoomsPageProps) {
     const [roomIDToHighlight] = useOnyx(ONYXKEYS.ROOM_ID_HIGHLIGHT_ON_ROOMS_PAGE);
     const highlightedReportID = roomIDToHighlight ?? undefined;
 
-    const rooms: WorkspaceRoomRowData[] = (policyReports ?? []).map((report) => {
-        const ownerDetails = report.ownerAccountID ? personalDetails?.[report.ownerAccountID] : undefined;
-        return {
-            keyForList: report.reportID,
-            reportID: report.reportID,
-            name: getReportName(report, reportAttributes),
-            ownerAccountID: report.ownerAccountID,
-            ownerAvatar: ownerDetails?.avatar,
-            ownerDisplayName: ownerDetails ? getDisplayNameOrDefault(ownerDetails) : '',
-            memberCount: getParticipantsAccountIDsForDisplay(report, true, false, false, undefined, personalDetails).length,
-            action: () => {
-                const targetRoute = isAdmin ? createDynamicRoute(DYNAMIC_ROUTES.REPORT_DETAILS.getRoute(report.reportID)) : ROUTES.REPORT_WITH_ID.getRoute(report.reportID);
-                Navigation.navigate(targetRoute);
-            },
-        };
-    });
+    const rooms: WorkspaceRoomRowData[] = (policyReports ?? []).map((report) => ({
+        keyForList: report.reportID,
+        reportID: report.reportID,
+        name: getReportName(report, reportAttributes),
+        memberCount: getParticipantsAccountIDsForDisplay(report, true, false, false, undefined, personalDetails).length,
+        action: () => {
+            const targetRoute = isAdmin ? createDynamicRoute(DYNAMIC_ROUTES.REPORT_DETAILS.getRoute(report.reportID)) : ROUTES.REPORT_WITH_ID.getRoute(report.reportID);
+            Navigation.navigate(targetRoute);
+        },
+    }));
 
     useFocusEffect(() => {
         openPolicyRoomsPage(policyID);

From 2b091663f4117429f3a93421c231e9f122670dff Mon Sep 17 00:00:00 2001
From: Yehor Kharchenko <yehorkharchenko4@gmail.com>
Date: Thu, 11 Jun 2026 15:26:25 +0200
Subject: [PATCH 363/435] add more details when not to use runAfterTransitions

---
 contributingGuides/INTERACTION_MANAGER.md | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/contributingGuides/INTERACTION_MANAGER.md b/contributingGuides/INTERACTION_MANAGER.md
index e4fe289b58a6..2ecdeb95836d 100644
--- a/contributingGuides/INTERACTION_MANAGER.md
+++ b/contributingGuides/INTERACTION_MANAGER.md
@@ -29,6 +29,14 @@ On top of TransitionTracker, existing APIs gain transition-aware callbacks:
 
 This makes the code self-descriptive: instead of a generic `runAfterInteractions`, each call site says exactly what it's waiting for and why.
 
+### What TransitionTracker actually tracks
+
+TransitionTracker registers transitions **only** in the following cases:
+
+1. **Navigation transitions** — screen push/pop/replace animations (via `transitionStart`/`transitionEnd` events in `ScreenLayout`)
+2. **Modal transitions** — modal open/close animations (via `ReanimatedModal`)
+3. **Keyboard transitions** — keyboard dismiss animations (via `KeyboardUtils.dismiss`)
+
 ### When to use `runAfterTransitions` directly
 
 Prefer higher-level APIs (`Navigation` with `afterTransition`/`waitForTransition`, `KeyboardUtils`, `useConfirmModal`) whenever possible. Use `TransitionTracker.runAfterTransitions` directly **only** when:
@@ -36,6 +44,10 @@ Prefer higher-level APIs (`Navigation` with `afterTransition`/`waitForTransition
 - There is no specific navigation/keyboard/modal action you can attach a callback to, or
 - There are too many concurrent actions and it's impossible to bind the callback to a particular one.
 
+### When NOT to use `runAfterTransitions`
+
+If you are not waiting for any of the tracked events (navigation, modal, keyboard), adding `runAfterTransitions` is meaningless - TransitionTracker will have no active transitions and the callback will fire synchronously in the same tick. For example, scroll events, layout animations, or Lottie playback are **not** tracked, so wrapping post-scroll logic in `runAfterTransitions` provides no benefit.
+
 ### How `runAfterTransitions` works
 
 1. If there are ongoing transitions at the time of the call, the callback is enqueued and waits until all current transitions complete.

From 126116a81d9f14846e044f0a1c21f5cf981e038b Mon Sep 17 00:00:00 2001
From: jayeshmangwani <jayeshmangwani@gmail.com>
Date: Thu, 11 Jun 2026 18:58:21 +0530
Subject: [PATCH 364/435] fixed lint

---
 .../SearchList/ListItem/ActionCell/DeferredActionCell.tsx     | 4 +++-
 .../Search/SearchList/ListItem/ActionCell/index.tsx           | 1 -
 2 files changed, 3 insertions(+), 2 deletions(-)

diff --git a/src/components/Search/SearchList/ListItem/ActionCell/DeferredActionCell.tsx b/src/components/Search/SearchList/ListItem/ActionCell/DeferredActionCell.tsx
index 328112908fe4..7d7c6f015c9e 100644
--- a/src/components/Search/SearchList/ListItem/ActionCell/DeferredActionCell.tsx
+++ b/src/components/Search/SearchList/ListItem/ActionCell/DeferredActionCell.tsx
@@ -7,7 +7,9 @@ import ActionCell from '.';
 import type {ActionCellProps} from '.';
 import actionTranslationsMap from './actionTranslationsMap';
 
-function DeferredActionCell(actionCellProps: ActionCellProps) {
+type DeferredActionCellProps = ActionCellProps & {isMarkAsDone?: boolean};
+
+function DeferredActionCell(actionCellProps: DeferredActionCellProps) {
     const styles = useThemeStyles();
     const {translate} = useLocalize();
     const shouldRender = useDeferredValue(true, false);
diff --git a/src/components/Search/SearchList/ListItem/ActionCell/index.tsx b/src/components/Search/SearchList/ListItem/ActionCell/index.tsx
index a97cc8486f02..b2188185cd9d 100644
--- a/src/components/Search/SearchList/ListItem/ActionCell/index.tsx
+++ b/src/components/Search/SearchList/ListItem/ActionCell/index.tsx
@@ -26,7 +26,6 @@ type ActionCellProps = {
     amount?: number;
     extraSmall?: boolean;
     shouldDisablePointerEvents?: boolean;
-    isMarkAsDone?: boolean;
 };
 
 function ActionCell({

From b5cff973c185a37a4b104c998a116f4f7c1d5a4b Mon Sep 17 00:00:00 2001
From: Yehor Kharchenko <yehorkharchenko4@gmail.com>
Date: Thu, 11 Jun 2026 15:40:18 +0200
Subject: [PATCH 365/435] fix propagation of afterTransition

---
 src/components/MoneyRequestHeader.tsx        |  2 +-
 src/components/MoneyRequestHeaderActions.tsx |  2 +-
 src/pages/inbox/ReportHeader.tsx             | 12 ++++++------
 3 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/src/components/MoneyRequestHeader.tsx b/src/components/MoneyRequestHeader.tsx
index 65d29db40798..5b1f63c17214 100644
--- a/src/components/MoneyRequestHeader.tsx
+++ b/src/components/MoneyRequestHeader.tsx
@@ -48,7 +48,7 @@ type MoneyRequestHeaderProps = {
     reportID: string | undefined;
 
     /** Method to trigger when pressing close button of the header */
-    onBackButtonPress: (prioritizeBackTo?: boolean) => void;
+    onBackButtonPress: (prioritizeBackTo?: boolean, options?: {afterTransition?: () => void}) => void;
 };
 
 function MoneyRequestHeader({reportID: reportIDProp, onBackButtonPress}: MoneyRequestHeaderProps) {
diff --git a/src/components/MoneyRequestHeaderActions.tsx b/src/components/MoneyRequestHeaderActions.tsx
index 4dd5a2f42231..bdf2909d8011 100644
--- a/src/components/MoneyRequestHeaderActions.tsx
+++ b/src/components/MoneyRequestHeaderActions.tsx
@@ -16,7 +16,7 @@ type MoneyRequestHeaderActionsProps = {
     reportID: string | undefined;
 
     /** Method to trigger when pressing close button of the header */
-    onBackButtonPress: (prioritizeBackTo?: boolean) => void;
+    onBackButtonPress: (prioritizeBackTo?: boolean, options?: {afterTransition?: () => void}) => void;
 };
 
 function MoneyRequestHeaderActions({reportID, onBackButtonPress}: MoneyRequestHeaderActionsProps) {
diff --git a/src/pages/inbox/ReportHeader.tsx b/src/pages/inbox/ReportHeader.tsx
index 76d67178ab85..cfccefcd5b90 100644
--- a/src/pages/inbox/ReportHeader.tsx
+++ b/src/pages/inbox/ReportHeader.tsx
@@ -46,28 +46,28 @@ function ReportHeader() {
     const {reportPendingAction, reportErrors} = getReportOfflinePendingActionAndErrors(report);
     const pendingAction = reportPendingAction ?? report?.pendingFields?.reimbursed;
 
-    const onBackButtonPress = (prioritizeBackTo = false) => {
+    const onBackButtonPress = (prioritizeBackTo = false, options?: {afterTransition?: () => void}) => {
         if (isInSidePanel) {
             closeSidePanel();
             return;
         }
         if (backTo === SCREENS.RIGHT_MODAL.SEARCH_REPORT) {
-            Navigation.goBack();
+            Navigation.goBack(undefined, options);
             return;
         }
         if (prioritizeBackTo && backTo) {
-            Navigation.goBack(backTo as Route);
+            Navigation.goBack(backTo as Route, options);
             return;
         }
         if (isInNarrowPaneModal) {
-            Navigation.goBack();
+            Navigation.goBack(undefined, options);
             return;
         }
         if (backTo) {
-            Navigation.goBack(backTo as Route);
+            Navigation.goBack(backTo as Route, options);
             return;
         }
-        Navigation.goBack();
+        Navigation.goBack(undefined, options);
     };
 
     if (isTransactionThreadView) {

From c1610a362be6940d2e3f5baa982522591870e75d Mon Sep 17 00:00:00 2001
From: OSBotify <infra+osbotify@expensify.com>
Date: Thu, 11 Jun 2026 13:51:30 +0000
Subject: [PATCH 366/435] Auto-tighten eslint-seatbelt baseline

---
 config/eslint/eslint.seatbelt.tsv | 1 -
 1 file changed, 1 deletion(-)

diff --git a/config/eslint/eslint.seatbelt.tsv b/config/eslint/eslint.seatbelt.tsv
index 394759349b7c..c1369f5a1e4c 100644
--- a/config/eslint/eslint.seatbelt.tsv
+++ b/config/eslint/eslint.seatbelt.tsv
@@ -531,7 +531,6 @@
 "../../src/hooks/useFilesValidation.tsx"	"@typescript-eslint/no-deprecated/ConfirmModal"	1
 "../../src/hooks/useFilterFormValues.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	3
 "../../src/hooks/useGeographicalStateAndCountryFromRoute.ts"	"@typescript-eslint/no-unsafe-type-assertion"	3
-"../../src/hooks/useHRSyncResultsModal.ts"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../src/hooks/useHtmlPaste/index.ts"	"@typescript-eslint/no-unsafe-type-assertion"	2
 "../../src/hooks/useImportSpreadsheetConfirmModal.ts"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../src/hooks/useInitial.ts"	"react-hooks/refs"	4

From 42dea817006f06983bfd2295e680ad533b9809a1 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Micha=C5=82=20Jasikowski=20=28via=20MelvinBot=29?=
 <infra+melvinbot@expensify.com>
Date: Thu, 11 Jun 2026 14:15:55 +0000
Subject: [PATCH 367/435] Prefetch default P2P mileage rate when starting a
 money request
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Splitting a distance expense goes through startMoneyRequest, which never
prefetched the default P2P mileage rate the way startDistanceRequest does.
The Distance tab then loaded with a malformed rate, causing the split to
fail with an unexpected error.

Co-authored-by: Michał Jasikowski <mjasikowski@users.noreply.github.com>
---
 src/libs/actions/IOU/MoneyRequest.ts    |  2 ++
 tests/unit/DefaultP2PMileageRateTest.ts | 16 ++++++++++++++++
 2 files changed, 18 insertions(+)

diff --git a/src/libs/actions/IOU/MoneyRequest.ts b/src/libs/actions/IOU/MoneyRequest.ts
index 42f178ff3df9..9c48f01525c4 100644
--- a/src/libs/actions/IOU/MoneyRequest.ts
+++ b/src/libs/actions/IOU/MoneyRequest.ts
@@ -407,6 +407,8 @@ function startMoneyRequest(
     isFromFloatingActionButton?: boolean,
 ) {
     const sourceRoute = Navigation.getActiveRoute();
+    // Prefetch the default P2P mileage rate so it's available if the user picks the Distance tab (e.g. when splitting a distance expense).
+    getDefaultP2PMileageRate();
     startSpan(CONST.TELEMETRY.SPAN_OPEN_CREATE_EXPENSE, {
         name: '/money-request-create',
         op: CONST.TELEMETRY.SPAN_OPEN_CREATE_EXPENSE,
diff --git a/tests/unit/DefaultP2PMileageRateTest.ts b/tests/unit/DefaultP2PMileageRateTest.ts
index 820a10480f01..1db9ed47f7c6 100644
--- a/tests/unit/DefaultP2PMileageRateTest.ts
+++ b/tests/unit/DefaultP2PMileageRateTest.ts
@@ -1,4 +1,5 @@
 import Onyx from 'react-native-onyx';
+import {startMoneyRequest} from '@libs/actions/IOU/MoneyRequest';
 import {getDefaultP2PMileageRate} from '@libs/actions/Transaction';
 import * as API from '@libs/API';
 import {READ_COMMANDS} from '@libs/API/types';
@@ -9,6 +10,9 @@ import ONYXKEYS from '@src/ONYXKEYS';
 import createRandomTransaction from '../utils/collections/transaction';
 import waitForBatchedUpdates from '../utils/waitForBatchedUpdates';
 
+jest.mock('@libs/Navigation/Navigation');
+jest.mock('@libs/telemetry/activeSpans');
+
 describe('Default P2P mileage rate', () => {
     beforeAll(() => {
         Onyx.init({
@@ -34,6 +38,18 @@ describe('Default P2P mileage rate', () => {
         });
     });
 
+    describe('startMoneyRequest', () => {
+        // Splitting a distance expense goes through startMoneyRequest, so it must prefetch the default P2P mileage rate
+        // (the same way startDistanceRequest does) or the Distance tab loads with a malformed rate.
+        it('prefetches the default P2P mileage rate when starting a split distance request', () => {
+            const readSpy = jest.spyOn(API, 'read').mockImplementation(() => {});
+
+            startMoneyRequest(CONST.IOU.TYPE.SPLIT, '1', [], CONST.IOU.REQUEST_TYPE.DISTANCE);
+
+            expect(readSpy).toHaveBeenCalledWith(READ_COMMANDS.GET_DEFAULT_P2P_MILEAGE_RATE, null);
+        });
+    });
+
     describe('getRateForP2P', () => {
         it('falls back to USD 67¢/mile when no rate has been stored in Onyx', () => {
             const result = DistanceRequestUtils.getRateForP2P('EUR', undefined);

From db0efc89a064de61a751d57a6762658c888d0fe8 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Micha=C5=82=20Jasikowski=20=28via=20MelvinBot=29?=
 <infra+melvinbot@expensify.com>
Date: Thu, 11 Jun 2026 14:19:03 +0000
Subject: [PATCH 368/435] Disable no-multiple-api-calls for the regression test
 API spy
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

The new test spies on API.read to assert the prefetch fires; this is a
second API.read reference in the file, which the lint rule flags. The
rule targets production call-chaining, not test spies.

Co-authored-by: Michał Jasikowski <mjasikowski@users.noreply.github.com>
---
 tests/unit/DefaultP2PMileageRateTest.ts | 1 +
 1 file changed, 1 insertion(+)

diff --git a/tests/unit/DefaultP2PMileageRateTest.ts b/tests/unit/DefaultP2PMileageRateTest.ts
index 1db9ed47f7c6..bf98b41f5770 100644
--- a/tests/unit/DefaultP2PMileageRateTest.ts
+++ b/tests/unit/DefaultP2PMileageRateTest.ts
@@ -42,6 +42,7 @@ describe('Default P2P mileage rate', () => {
         // Splitting a distance expense goes through startMoneyRequest, so it must prefetch the default P2P mileage rate
         // (the same way startDistanceRequest does) or the Distance tab loads with a malformed rate.
         it('prefetches the default P2P mileage rate when starting a split distance request', () => {
+            // eslint-disable-next-line rulesdir/no-multiple-api-calls
             const readSpy = jest.spyOn(API, 'read').mockImplementation(() => {});
 
             startMoneyRequest(CONST.IOU.TYPE.SPLIT, '1', [], CONST.IOU.REQUEST_TYPE.DISTANCE);

From 549432e7eee702acfff3b5c52143941079950687 Mon Sep 17 00:00:00 2001
From: OSBotify <infra+osbotify@expensify.com>
Date: Thu, 11 Jun 2026 14:23:25 +0000
Subject: [PATCH 369/435] Auto-tighten eslint-seatbelt baseline

---
 config/eslint/eslint.seatbelt.tsv | 2 --
 1 file changed, 2 deletions(-)

diff --git a/config/eslint/eslint.seatbelt.tsv b/config/eslint/eslint.seatbelt.tsv
index c1369f5a1e4c..355098943f66 100644
--- a/config/eslint/eslint.seatbelt.tsv
+++ b/config/eslint/eslint.seatbelt.tsv
@@ -1161,7 +1161,6 @@
 "../../src/pages/inbox/sidebar/FABPopoverContent/menuItems/QuickActionMenuItem.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	3
 "../../src/pages/inbox/sidebar/FABPopoverContent/useScanActions.ts"	"@typescript-eslint/no-unsafe-type-assertion"	2
 "../../src/pages/inbox/sidebar/SidebarLinksData.tsx"	"react-hooks/refs"	1
-"../../src/pages/inbox/usePusherDraftPacing.ts"	"@typescript-eslint/no-unsafe-type-assertion"	2
 "../../src/pages/iou/MoneyRequestAmountForm.tsx"	"react-hooks/set-state-in-effect"	3
 "../../src/pages/iou/SplitExpensePage.tsx"	"@typescript-eslint/no-deprecated/InteractionManager.runAfterInteractions"	1
 "../../src/pages/iou/SplitExpensePage.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	2
@@ -1970,7 +1969,6 @@
 "../../tests/unit/navigateAfterOnboardingTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../tests/unit/navigateToWorkspacesPageTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	14
 "../../tests/unit/pages/home/GettingStartedSection/GettingStartedSectionTest.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	11
-"../../tests/unit/pages/inbox/ConciergeDraftContext.test.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../tests/unit/pages/inbox/report/ReportActionEditMessageContext.test.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	2
 "../../tests/unit/pages/settings/AddAgentAvatarPageTest.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../tests/unit/pages/settings/AddAgentPageTest.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	11

From 8495e91cef9b70839ed1dd7ec3d72a6e0b95e3a1 Mon Sep 17 00:00:00 2001
From: OSBotify <infra+osbotify@expensify.com>
Date: Thu, 11 Jun 2026 15:09:39 +0000
Subject: [PATCH 370/435] Auto-tighten eslint-seatbelt baseline

---
 config/eslint/eslint.seatbelt.tsv | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/config/eslint/eslint.seatbelt.tsv b/config/eslint/eslint.seatbelt.tsv
index b187a04ae009..f8ef1b0fa88f 100644
--- a/config/eslint/eslint.seatbelt.tsv
+++ b/config/eslint/eslint.seatbelt.tsv
@@ -769,7 +769,6 @@
 "../../src/libs/ReportNameUtils.ts"	"@typescript-eslint/no-deprecated/translateLocal"	12
 "../../src/libs/ReportNameUtils.ts"	"@typescript-eslint/no-unsafe-type-assertion"	2
 "../../src/libs/ReportPrimaryActionUtils.ts"	"no-restricted-imports"	1
-"../../src/libs/ReportSecondaryActionUtils.ts"	"no-restricted-imports"	1
 "../../src/libs/ReportTitleUtils.ts"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../src/libs/ReportUtils.ts"	"@typescript-eslint/no-deprecated/getPolicy"	28
 "../../src/libs/ReportUtils.ts"	"@typescript-eslint/no-deprecated/translateLocal"	34
@@ -789,7 +788,6 @@
 "../../src/libs/StatusBar/types.ts"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../src/libs/StringUtils/index.ts"	"@typescript-eslint/no-unsafe-type-assertion"	2
 "../../src/libs/TransactionPreviewUtils.ts"	"@typescript-eslint/no-unsafe-type-assertion"	1
-"../../src/libs/TransactionPreviewUtils.ts"	"no-restricted-imports"	1
 "../../src/libs/TransactionUtils/index.ts"	"@typescript-eslint/no-deprecated/translateLocal"	5
 "../../src/libs/TransactionUtils/index.ts"	"@typescript-eslint/no-unsafe-type-assertion"	8
 "../../src/libs/UnreadIndicatorUpdater/index.ts"	"no-restricted-imports"	1
@@ -1929,7 +1927,6 @@
 "../../tests/unit/TelemetrySynchronizerTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	9
 "../../tests/unit/TransactionNavigationUtilsTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	6
 "../../tests/unit/TransactionPreviewUtils.test.ts"	"@typescript-eslint/no-unsafe-type-assertion"	7
-"../../tests/unit/TransactionPreviewUtils.test.ts"	"no-restricted-imports"	1
 "../../tests/unit/TransactionTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	12
 "../../tests/unit/TransactionUtilsTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	20
 "../../tests/unit/TranslateTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	9

From 1343a8073f3c00b37e92064505065fb661b984f8 Mon Sep 17 00:00:00 2001
From: Yehor Kharchenko <yehorkharchenko4@gmail.com>
Date: Thu, 11 Jun 2026 17:29:24 +0200
Subject: [PATCH 371/435] remove direct usage of TransitionTracker and refactor
 navigation function

---
 config/eslint/eslint.seatbelt.tsv |  1 -
 src/hooks/useExpenseActions.ts    | 46 +++++++++++++++----------------
 src/libs/ReportUtils.ts           |  8 +++---
 3 files changed, 26 insertions(+), 29 deletions(-)

diff --git a/config/eslint/eslint.seatbelt.tsv b/config/eslint/eslint.seatbelt.tsv
index bceb4ea5dd89..c84c993cedc7 100644
--- a/config/eslint/eslint.seatbelt.tsv
+++ b/config/eslint/eslint.seatbelt.tsv
@@ -526,7 +526,6 @@
 "../../src/hooks/useDragAndDrop/types.ts"	"@typescript-eslint/no-deprecated/React.MutableRefObject"	1
 "../../src/hooks/useDynamicBackPath.ts"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../src/hooks/useExpenseActions.ts"	"@typescript-eslint/no-deprecated/InteractionManager.runAfterInteractions"	3
-"../../src/hooks/useExpenseActions.ts"	"no-restricted-imports"	1
 "../../src/hooks/useExportActions.ts"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../src/hooks/useExportedToFilterOptions.ts"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../src/hooks/useFilesValidation.tsx"	"@typescript-eslint/no-deprecated/ConfirmModal"	1
diff --git a/src/hooks/useExpenseActions.ts b/src/hooks/useExpenseActions.ts
index a58c14f8f60b..b7fcb7b92195 100644
--- a/src/hooks/useExpenseActions.ts
+++ b/src/hooks/useExpenseActions.ts
@@ -19,7 +19,6 @@ import {getExistingTransactionID} from '@libs/IOUUtils';
 import Log from '@libs/Log';
 import createDynamicRoute from '@libs/Navigation/helpers/dynamicRoutesUtils/createDynamicRoute';
 import Navigation from '@libs/Navigation/Navigation';
-import TransitionTracker from '@libs/Navigation/TransitionTracker';
 import {isPolicyAccessible} from '@libs/PolicyUtils';
 import {getIOUActionForTransactionID} from '@libs/ReportActionsUtils';
 import {
@@ -511,34 +510,33 @@ function useExpenseActions({reportID, isReportInSearch = false, backTo, onDuplic
                         );
                         const deleteNavigateBackUrl = goBackRoute ?? backTo ?? Navigation.getActiveRoute();
                         setDeleteTransactionNavigateBackUrl(deleteNavigateBackUrl);
-                        if (goBackRoute) {
-                            navigateOnDeleteExpense(goBackRoute);
-                        }
                         // The wide RHP close animation was changed, and because of that the expense was deleted right after
                         // the animation finished, which caused flickering in the expenses list. We want the user to see
                         // the expense in the list for a little bit longer, so we wait for the animation to finish and then
                         // add an additional delay before removing it.
                         // See https://github.com/Expensify/App/issues/92036
-                        TransitionTracker.runAfterTransitions({
-                            callback: () => {
-                                setTimeout(() => {
-                                    const deleteResult = deleteTransactions(
-                                        [transaction.transactionID],
-                                        duplicateTransactions,
-                                        duplicateTransactionViolations,
-                                        isReportInSearch ? currentSearchHash : undefined,
-                                        false,
-                                    );
-
-                                    if (deleteResult.action === 'redirected') {
-                                        return;
-                                    }
-
-                                    removeTransaction(transaction.transactionID);
-                                }, CONST.EXPENSE_REPORT_DELETE_DELAY_MS);
-                            },
-                            waitForUpcomingTransition: true,
-                        });
+                        const afterTransition = () => {
+                            setTimeout(() => {
+                                const deleteResult = deleteTransactions(
+                                    [transaction.transactionID],
+                                    duplicateTransactions,
+                                    duplicateTransactionViolations,
+                                    isReportInSearch ? currentSearchHash : undefined,
+                                    false,
+                                );
+
+                                if (deleteResult.action === 'redirected') {
+                                    return;
+                                }
+
+                                removeTransaction(transaction.transactionID);
+                            }, CONST.EXPENSE_REPORT_DELETE_DELAY_MS);
+                        };
+                        if (goBackRoute) {
+                            navigateOnDeleteExpense(goBackRoute, afterTransition);
+                        } else {
+                            afterTransition();
+                        }
                     }
                     return;
                 }
diff --git a/src/libs/ReportUtils.ts b/src/libs/ReportUtils.ts
index 1b857fee6aec..197a5ff1e621 100644
--- a/src/libs/ReportUtils.ts
+++ b/src/libs/ReportUtils.ts
@@ -5956,20 +5956,20 @@ function goBackFromPrivateNotes(report: OnyxEntry<Report>, accountID?: number) {
     Navigation.goBack();
 }
 
-function navigateOnDeleteExpense(backToRoute: Route) {
+function navigateOnDeleteExpense(backToRoute: Route, afterTransition?: () => void) {
     if (isSearchTopmostFullScreenRoute()) {
-        Navigation.dismissModal();
+        Navigation.dismissModal({afterTransition});
         return;
     }
 
     const rootState = navigationRef.getRootState();
     const focusedRoute = findFocusedRoute(rootState);
     if (focusedRoute?.params && 'backTo' in focusedRoute.params) {
-        Navigation.goBack(focusedRoute.params.backTo as Route);
+        Navigation.goBack(focusedRoute.params.backTo as Route, {afterTransition});
         return;
     }
 
-    Navigation.goBack(backToRoute);
+    Navigation.goBack(backToRoute, {afterTransition});
 }
 
 /**

From efcc5962778769402960b429966a15961d622363 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Micha=C5=82=20Jasikowski=20=28via=20MelvinBot=29?=
 <infra+melvinbot@expensify.com>
Date: Thu, 11 Jun 2026 15:38:52 +0000
Subject: [PATCH 372/435] Gate default P2P mileage rate prefetch to split flows
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Only the split flow exposes a Distance tab from startMoneyRequest, so
restrict the getDefaultP2PMileageRate() prefetch to split requests to
avoid an unnecessary uncached API.read on manual/scan/pay/invoice starts.

Co-authored-by: Michał Jasikowski <mjasikowski@users.noreply.github.com>
---
 src/libs/actions/IOU/MoneyRequest.ts    |  6 ++++--
 tests/unit/DefaultP2PMileageRateTest.ts | 10 ++++++++++
 2 files changed, 14 insertions(+), 2 deletions(-)

diff --git a/src/libs/actions/IOU/MoneyRequest.ts b/src/libs/actions/IOU/MoneyRequest.ts
index 9c48f01525c4..4aa02dd5cc74 100644
--- a/src/libs/actions/IOU/MoneyRequest.ts
+++ b/src/libs/actions/IOU/MoneyRequest.ts
@@ -407,8 +407,10 @@ function startMoneyRequest(
     isFromFloatingActionButton?: boolean,
 ) {
     const sourceRoute = Navigation.getActiveRoute();
-    // Prefetch the default P2P mileage rate so it's available if the user picks the Distance tab (e.g. when splitting a distance expense).
-    getDefaultP2PMileageRate();
+    // Only the split flow exposes a Distance tab from here, so prefetch the default P2P mileage rate solely for splits to avoid an unnecessary read on other flows.
+    if (iouType === CONST.IOU.TYPE.SPLIT) {
+        getDefaultP2PMileageRate();
+    }
     startSpan(CONST.TELEMETRY.SPAN_OPEN_CREATE_EXPENSE, {
         name: '/money-request-create',
         op: CONST.TELEMETRY.SPAN_OPEN_CREATE_EXPENSE,
diff --git a/tests/unit/DefaultP2PMileageRateTest.ts b/tests/unit/DefaultP2PMileageRateTest.ts
index bf98b41f5770..c077cbbe9b9c 100644
--- a/tests/unit/DefaultP2PMileageRateTest.ts
+++ b/tests/unit/DefaultP2PMileageRateTest.ts
@@ -49,6 +49,16 @@ describe('Default P2P mileage rate', () => {
 
             expect(readSpy).toHaveBeenCalledWith(READ_COMMANDS.GET_DEFAULT_P2P_MILEAGE_RATE, null);
         });
+
+        // Non-split flows never expose a Distance tab, so they must not issue the (uncached) prefetch read.
+        it('does not prefetch the default P2P mileage rate for non-split requests', () => {
+            // eslint-disable-next-line rulesdir/no-multiple-api-calls
+            const readSpy = jest.spyOn(API, 'read').mockImplementation(() => {});
+
+            startMoneyRequest(CONST.IOU.TYPE.SUBMIT, '1', [], CONST.IOU.REQUEST_TYPE.MANUAL);
+
+            expect(readSpy).not.toHaveBeenCalledWith(READ_COMMANDS.GET_DEFAULT_P2P_MILEAGE_RATE, null);
+        });
     });
 
     describe('getRateForP2P', () => {

From 2d06a1a3799c59249ada096c274bd6b37bb429c8 Mon Sep 17 00:00:00 2001
From: Yehor Kharchenko <yehorkharchenko4@gmail.com>
Date: Thu, 11 Jun 2026 17:44:02 +0200
Subject: [PATCH 373/435] add info about the delay

---
 contributingGuides/INTERACTION_MANAGER.md | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/contributingGuides/INTERACTION_MANAGER.md b/contributingGuides/INTERACTION_MANAGER.md
index 2ecdeb95836d..5d152fc04532 100644
--- a/contributingGuides/INTERACTION_MANAGER.md
+++ b/contributingGuides/INTERACTION_MANAGER.md
@@ -59,6 +59,8 @@ Sometimes a transition starts in the same tick as the `runAfterTransitions` call
 
 To fix this, pass the `waitForUpcomingTransition` flag along with the callback. This tells TransitionTracker to wait for a transition that hasn't started yet, ensuring the callback truly runs after the transition completes.
 
+> **Important:** `waitForUpcomingTransition` waits up to 1 second for a transition to begin. If no transition starts within that window, the callback fires anyway — effectively acting as a 1-second timeout. When using this flag, always make sure that TransitionTracker actually picks up the transition (i.e. the transition is registered within the 1-second window). Otherwise you're not waiting for a real transition, just adding an arbitrary delay.
+
 ## How
 The migration is split into 9 issues. Current status of the migration can be found in the parent Github issue [here](https://github.com/Expensify/App/issues/71913). 
 

From dfa251717722fa3376b27bcc705071db66c00ff5 Mon Sep 17 00:00:00 2001
From: Yehor Kharchenko <yehorkharchenko4@gmail.com>
Date: Thu, 11 Jun 2026 17:50:56 +0200
Subject: [PATCH 374/435] remove eslint-disable lines

---
 src/hooks/useMergeHRInitialSyncingModal.ts                       | 1 -
 src/hooks/useOnboardingFlow.ts                                   | 1 -
 src/libs/Navigation/helpers/navigateToWorkspacesPage.ts          | 1 -
 .../BaseOnboardingInterestedFeatures.tsx                         | 1 -
 src/pages/workspace/taxes/WorkspaceCreateTaxValuePage.tsx        | 1 -
 tests/unit/hooks/useRestoreWorkspacesTabOnNavigate.test.ts       | 1 -
 tests/unit/navigateToWorkspacesPageTest.ts                       | 1 -
 7 files changed, 7 deletions(-)

diff --git a/src/hooks/useMergeHRInitialSyncingModal.ts b/src/hooks/useMergeHRInitialSyncingModal.ts
index db0bbaabcb6d..d710022f8889 100644
--- a/src/hooks/useMergeHRInitialSyncingModal.ts
+++ b/src/hooks/useMergeHRInitialSyncingModal.ts
@@ -1,6 +1,5 @@
 import {useEffect, useEffectEvent, useState} from 'react';
 import {setMergeHRInitialSyncModalShown} from '@libs/actions/connections/MergeHR';
-// eslint-disable-next-line no-restricted-imports -- the hook does not use React Navigation hooks internally (isFocused is passed in as a parameter), so there is no navigation instance available to use navigation.addListener for transition detection.
 import TransitionTracker from '@libs/Navigation/TransitionTracker';
 import Visibility from '@libs/Visibility';
 import CONST from '@src/CONST';
diff --git a/src/hooks/useOnboardingFlow.ts b/src/hooks/useOnboardingFlow.ts
index 4845a30cdd7d..82f17e6c3552 100644
--- a/src/hooks/useOnboardingFlow.ts
+++ b/src/hooks/useOnboardingFlow.ts
@@ -4,7 +4,6 @@ import {emailSelector} from '@selectors/Session';
 import {useEffect} from 'react';
 import getCurrentUrl from '@libs/Navigation/currentUrl';
 import Navigation from '@libs/Navigation/Navigation';
-// eslint-disable-next-line no-restricted-imports
 import TransitionTracker from '@libs/Navigation/TransitionTracker';
 import {isLoggingInAsNewUser} from '@libs/SessionUtils';
 import {startOnboardingFlow} from '@userActions/Welcome/OnboardingFlow';
diff --git a/src/libs/Navigation/helpers/navigateToWorkspacesPage.ts b/src/libs/Navigation/helpers/navigateToWorkspacesPage.ts
index 852f69b32c01..331e5e4f8cc1 100644
--- a/src/libs/Navigation/helpers/navigateToWorkspacesPage.ts
+++ b/src/libs/Navigation/helpers/navigateToWorkspacesPage.ts
@@ -3,7 +3,6 @@ import {findFocusedRoute, StackActions, TabActions} from '@react-navigation/nati
 import interceptAnonymousUser from '@libs/interceptAnonymousUser';
 import Navigation from '@libs/Navigation/Navigation';
 import navigationRef from '@libs/Navigation/navigationRef';
-// eslint-disable-next-line no-restricted-imports -- TransitionTracker is needed here to sequence the tab jump after the popToTop transition completes, so WorkspaceInitialPage appears before the tab becomes visible.
 import TransitionTracker from '@libs/Navigation/TransitionTracker';
 import {isPendingDeletePolicy, shouldShowPolicy as shouldShowPolicyUtil} from '@libs/PolicyUtils';
 import NAVIGATORS from '@src/NAVIGATORS';
diff --git a/src/pages/OnboardingInterestedFeatures/BaseOnboardingInterestedFeatures.tsx b/src/pages/OnboardingInterestedFeatures/BaseOnboardingInterestedFeatures.tsx
index 2dbd5c0cf89e..07bb165bde75 100644
--- a/src/pages/OnboardingInterestedFeatures/BaseOnboardingInterestedFeatures.tsx
+++ b/src/pages/OnboardingInterestedFeatures/BaseOnboardingInterestedFeatures.tsx
@@ -32,7 +32,6 @@ import {setOnboardingAdminsChatReportID, setOnboardingPolicyID} from '@libs/acti
 import Log from '@libs/Log';
 import {navigateAfterOnboardingWithMicrotaskQueue} from '@libs/navigateAfterOnboarding';
 import Navigation from '@libs/Navigation/Navigation';
-// eslint-disable-next-line no-restricted-imports
 import TransitionTracker from '@libs/Navigation/TransitionTracker';
 import {isPaidGroupPolicy, isPolicyAdmin} from '@libs/PolicyUtils';
 import CONST from '@src/CONST';
diff --git a/src/pages/workspace/taxes/WorkspaceCreateTaxValuePage.tsx b/src/pages/workspace/taxes/WorkspaceCreateTaxValuePage.tsx
index 6acc7d6dc7e1..b073dc8ab8c7 100644
--- a/src/pages/workspace/taxes/WorkspaceCreateTaxValuePage.tsx
+++ b/src/pages/workspace/taxes/WorkspaceCreateTaxValuePage.tsx
@@ -13,7 +13,6 @@ import useThemeStyles from '@hooks/useThemeStyles';
 import {setDraftValues} from '@libs/actions/FormActions';
 import Navigation from '@libs/Navigation/Navigation';
 import type {PlatformStackScreenProps} from '@libs/Navigation/PlatformStackNavigation/types';
-// eslint-disable-next-line no-restricted-imports -- The input ref doesn't exist at the navigate() call site, so we can't use Navigation's afterTransition callback
 import TransitionTracker from '@libs/Navigation/TransitionTracker';
 import type {SettingsNavigatorParamList} from '@libs/Navigation/types';
 import variables from '@styles/variables';
diff --git a/tests/unit/hooks/useRestoreWorkspacesTabOnNavigate.test.ts b/tests/unit/hooks/useRestoreWorkspacesTabOnNavigate.test.ts
index 464d507ae18a..ea75a8c57023 100644
--- a/tests/unit/hooks/useRestoreWorkspacesTabOnNavigate.test.ts
+++ b/tests/unit/hooks/useRestoreWorkspacesTabOnNavigate.test.ts
@@ -2,7 +2,6 @@ import {StackActions, TabActions} from '@react-navigation/native';
 import {renderHook} from '@testing-library/react-native';
 import Navigation from '@libs/Navigation/Navigation';
 import navigationRef from '@libs/Navigation/navigationRef';
-// eslint-disable-next-line no-restricted-imports -- TransitionTracker is mocked here to assert the tab-jump sequencing after popToTop in navigateToWorkspacesPage.
 import TransitionTracker from '@libs/Navigation/TransitionTracker';
 import NAVIGATORS from '@src/NAVIGATORS';
 import ONYXKEYS from '@src/ONYXKEYS';
diff --git a/tests/unit/navigateToWorkspacesPageTest.ts b/tests/unit/navigateToWorkspacesPageTest.ts
index 05cff0353dda..ac3ab3b618b7 100644
--- a/tests/unit/navigateToWorkspacesPageTest.ts
+++ b/tests/unit/navigateToWorkspacesPageTest.ts
@@ -4,7 +4,6 @@ import interceptAnonymousUser from '@libs/interceptAnonymousUser';
 import navigateToWorkspacesPage from '@libs/Navigation/helpers/navigateToWorkspacesPage';
 import Navigation from '@libs/Navigation/Navigation';
 import navigationRef from '@libs/Navigation/navigationRef';
-// eslint-disable-next-line no-restricted-imports -- TransitionTracker is mocked here to assert the tab-jump sequencing after popToTop in navigateToWorkspacesPage.
 import TransitionTracker from '@libs/Navigation/TransitionTracker';
 import * as PolicyUtils from '@libs/PolicyUtils';
 import NAVIGATORS from '@src/NAVIGATORS';

From 248f4367b5435c9d9aa485e14adf5d1e285282f8 Mon Sep 17 00:00:00 2001
From: ShridharGoel <35566748+ShridharGoel@users.noreply.github.com>
Date: Thu, 11 Jun 2026 21:22:54 +0530
Subject: [PATCH 375/435] Fix translation generation for plural functions

---
 scripts/utils/TSCompilerUtils.ts | 34 ++++++++++++++++++++++++++++++--
 1 file changed, 32 insertions(+), 2 deletions(-)

diff --git a/scripts/utils/TSCompilerUtils.ts b/scripts/utils/TSCompilerUtils.ts
index 6c2431608da5..e0664966fb7a 100644
--- a/scripts/utils/TSCompilerUtils.ts
+++ b/scripts/utils/TSCompilerUtils.ts
@@ -448,16 +448,46 @@ function injectDeepObjectValue(objectLiteral: ts.ObjectLiteralExpression, dotPat
             return ts.factory.createObjectLiteralExpression(updatedProperties);
         }
 
-        // Recursively inject into the existing nested structure
-        // Handle both direct ObjectLiteralExpression and SatisfiesExpression wrapping an object
+        // Recursively inject into the existing nested structure.
+        // Handle direct ObjectLiteralExpression, SatisfiesExpression wrapping an object, and plural translation functions like `key: () => ({one, other})`.
         let nestedObject: ts.ObjectLiteralExpression | undefined;
         let satisfiesType: ts.TypeNode | undefined;
+        let updatedPluralFunction: ts.ArrowFunction | undefined;
 
         if (ts.isObjectLiteralExpression(existingProperty.initializer)) {
             nestedObject = existingProperty.initializer;
         } else if (ts.isSatisfiesExpression(existingProperty.initializer) && ts.isObjectLiteralExpression(existingProperty.initializer.expression)) {
             nestedObject = existingProperty.initializer.expression;
             satisfiesType = existingProperty.initializer.type;
+        } else if (ts.isArrowFunction(existingProperty.initializer)) {
+            let pluralObject: ts.ObjectLiteralExpression | undefined;
+            let shouldWrapInParentheses = false;
+
+            if (ts.isObjectLiteralExpression(existingProperty.initializer.body)) {
+                pluralObject = existingProperty.initializer.body;
+            } else if (ts.isParenthesizedExpression(existingProperty.initializer.body) && ts.isObjectLiteralExpression(existingProperty.initializer.body.expression)) {
+                pluralObject = existingProperty.initializer.body.expression;
+                shouldWrapInParentheses = true;
+            }
+
+            if (pluralObject) {
+                const updatedPluralObject = injectDeepObjectValue(pluralObject, remainingPath, value);
+                updatedPluralFunction = ts.factory.updateArrowFunction(
+                    existingProperty.initializer,
+                    existingProperty.initializer.modifiers,
+                    existingProperty.initializer.typeParameters,
+                    existingProperty.initializer.parameters,
+                    existingProperty.initializer.type,
+                    existingProperty.initializer.equalsGreaterThanToken,
+                    shouldWrapInParentheses ? ts.factory.createParenthesizedExpression(updatedPluralObject) : updatedPluralObject,
+                );
+            }
+        }
+
+        if (updatedPluralFunction) {
+            const updatedProperty = ts.factory.createPropertyAssignment(topLevelKey, updatedPluralFunction);
+            const updatedProperties = objectLiteral.properties.map((prop) => (prop === existingProperty ? updatedProperty : prop));
+            return ts.factory.createObjectLiteralExpression(updatedProperties);
         }
 
         if (!nestedObject) {

From d5ff838bb94ab01a7f6b408abf24435f5fdc6fca Mon Sep 17 00:00:00 2001
From: ShridharGoel <35566748+ShridharGoel@users.noreply.github.com>
Date: Thu, 11 Jun 2026 21:32:30 +0530
Subject: [PATCH 376/435] Keep role translation changes in English only

---
 scripts/utils/TSCompilerUtils.ts |   34 +-
 src/languages/IntlStore.ts       |    2 +-
 src/languages/de.ts              | 2952 ++++++++----------------------
 src/languages/es.ts              | 2618 ++++++--------------------
 src/languages/fr.ts              | 2893 ++++++++---------------------
 src/languages/it.ts              | 2935 ++++++++---------------------
 src/languages/ja.ts              | 2891 ++++++++---------------------
 src/languages/nl.ts              | 2944 ++++++++---------------------
 src/languages/params.ts          |  606 +++++-
 src/languages/pl.ts              | 2904 ++++++++---------------------
 src/languages/pt-BR.ts           | 2912 ++++++++---------------------
 src/languages/types.ts           |    1 +
 src/languages/zh-hans.ts         | 2828 ++++++++--------------------
 13 files changed, 7495 insertions(+), 19025 deletions(-)

diff --git a/scripts/utils/TSCompilerUtils.ts b/scripts/utils/TSCompilerUtils.ts
index e0664966fb7a..6c2431608da5 100644
--- a/scripts/utils/TSCompilerUtils.ts
+++ b/scripts/utils/TSCompilerUtils.ts
@@ -448,46 +448,16 @@ function injectDeepObjectValue(objectLiteral: ts.ObjectLiteralExpression, dotPat
             return ts.factory.createObjectLiteralExpression(updatedProperties);
         }
 
-        // Recursively inject into the existing nested structure.
-        // Handle direct ObjectLiteralExpression, SatisfiesExpression wrapping an object, and plural translation functions like `key: () => ({one, other})`.
+        // Recursively inject into the existing nested structure
+        // Handle both direct ObjectLiteralExpression and SatisfiesExpression wrapping an object
         let nestedObject: ts.ObjectLiteralExpression | undefined;
         let satisfiesType: ts.TypeNode | undefined;
-        let updatedPluralFunction: ts.ArrowFunction | undefined;
 
         if (ts.isObjectLiteralExpression(existingProperty.initializer)) {
             nestedObject = existingProperty.initializer;
         } else if (ts.isSatisfiesExpression(existingProperty.initializer) && ts.isObjectLiteralExpression(existingProperty.initializer.expression)) {
             nestedObject = existingProperty.initializer.expression;
             satisfiesType = existingProperty.initializer.type;
-        } else if (ts.isArrowFunction(existingProperty.initializer)) {
-            let pluralObject: ts.ObjectLiteralExpression | undefined;
-            let shouldWrapInParentheses = false;
-
-            if (ts.isObjectLiteralExpression(existingProperty.initializer.body)) {
-                pluralObject = existingProperty.initializer.body;
-            } else if (ts.isParenthesizedExpression(existingProperty.initializer.body) && ts.isObjectLiteralExpression(existingProperty.initializer.body.expression)) {
-                pluralObject = existingProperty.initializer.body.expression;
-                shouldWrapInParentheses = true;
-            }
-
-            if (pluralObject) {
-                const updatedPluralObject = injectDeepObjectValue(pluralObject, remainingPath, value);
-                updatedPluralFunction = ts.factory.updateArrowFunction(
-                    existingProperty.initializer,
-                    existingProperty.initializer.modifiers,
-                    existingProperty.initializer.typeParameters,
-                    existingProperty.initializer.parameters,
-                    existingProperty.initializer.type,
-                    existingProperty.initializer.equalsGreaterThanToken,
-                    shouldWrapInParentheses ? ts.factory.createParenthesizedExpression(updatedPluralObject) : updatedPluralObject,
-                );
-            }
-        }
-
-        if (updatedPluralFunction) {
-            const updatedProperty = ts.factory.createPropertyAssignment(topLevelKey, updatedPluralFunction);
-            const updatedProperties = objectLiteral.properties.map((prop) => (prop === existingProperty ? updatedProperty : prop));
-            return ts.factory.createObjectLiteralExpression(updatedProperties);
         }
 
         if (!nestedObject) {
diff --git a/src/languages/IntlStore.ts b/src/languages/IntlStore.ts
index b4870c4fb813..345ccefb887a 100644
--- a/src/languages/IntlStore.ts
+++ b/src/languages/IntlStore.ts
@@ -24,7 +24,7 @@ import type zhHans from './zh-hans';
 // This function was added here to avoid circular dependencies
 function setAreTranslationsLoading(areTranslationsLoading: boolean) {
     // eslint-disable-next-line rulesdir/prefer-actions-set-data
-    Onyx.set(ONYXKEYS.RAM_ONLY_ARE_TRANSLATIONS_LOADING, areTranslationsLoading);
+    Onyx.set(ONYXKEYS.ARE_TRANSLATIONS_LOADING, areTranslationsLoading);
 }
 
 class IntlStore {
diff --git a/src/languages/de.ts b/src/languages/de.ts
index db35d9e82d2f..08ca9bf4beac 100644
--- a/src/languages/de.ts
+++ b/src/languages/de.ts
@@ -11,52 +11,189 @@
  */
 import {CONST as COMMON_CONST} from 'expensify-common';
 import startCase from 'lodash/startCase';
-import type {ValueOf} from 'type-fest';
 import type {OnboardingTask} from '@libs/actions/Welcome/OnboardingFlow';
 import StringUtils from '@libs/StringUtils';
 import dedent from '@libs/StringUtils/dedent';
 import CONST from '@src/CONST';
 import type {Country} from '@src/CONST';
 import type OriginalMessage from '@src/types/onyx/OriginalMessage';
-import type {OriginalMessageSettlementAccountLocked, PersonalRulesModifiedFields, PolicyRulesModifiedFields} from '@src/types/onyx/OriginalMessage';
+import type {OriginalMessageSettlementAccountLocked, PolicyRulesModifiedFields} from '@src/types/onyx/OriginalMessage';
+import ObjectUtils from '@src/types/utils/ObjectUtils';
 import type en from './en';
 import type {
+    AddBudgetParams,
+    AddedOrDeletedPolicyReportFieldParams,
+    AddOrDeletePolicyCustomUnitRateParams,
     ChangeFieldParams,
-    ConciergeBrokenCardConnectionParams,
     ConnectionNameParams,
+    CreatedReportForUnapprovedTransactionsParams,
     DelegateRoleParams,
     DeleteActionParams,
+    DeleteBudgetParams,
     DeleteConfirmationParams,
     EditActionParams,
     ExportAgainModalDescriptionParams,
     ExportIntegrationSelectedParams,
+    ImportPolicyCustomUnitRatesParams,
     IntacctMappingTitleParams,
     InvalidPropertyParams,
     InvalidValueParams,
     MarkReimbursedFromIntegrationParams,
     MissingPropertyParams,
     MovedFromPersonalSpaceParams,
+    MultifactorAuthenticationTranslationParams,
+    NextStepParams,
     NotAllowedExtensionParams,
     OptionalParam,
     PaidElsewhereParams,
     ParentNavigationSummaryParams,
     RemovedFromApprovalWorkflowParams,
+    RemovedPolicyCustomUnitSubRateParams,
     ReportArchiveReasonsClosedParams,
     ReportArchiveReasonsInvoiceReceiverPolicyDeletedParams,
     ReportArchiveReasonsMergedParams,
     ReportArchiveReasonsRemovedFromPolicyParams,
+    ReportFieldParams,
+    ReportPolicyNameParams,
+    RequestAmountParams,
+    RequiredFieldParams,
     ResolutionConstraintsParams,
+    ReviewParams,
+    RoleNamesParams,
+    RoomNameReservedErrorParams,
+    RoomRenamedToParams,
+    RoutedDueToDEWParams,
+    RulesEnableWorkflowsParams,
+    SecondaryLoginParams,
+    SetTheDistanceMerchantParams,
+    SetTheRequestParams,
+    SettledAfterAddedBankAccountParams,
+    SettleExpensifyCardParams,
+    SettlementAccountInfoParams,
+    SettlementAccountReconciliationParams,
+    SettlementDateParams,
     ShareParams,
+    SignerInfoMessageParams,
+    SignUpNewFaceCodeParams,
     SizeExceededParams,
+    SplitAmountParams,
+    SplitDateRangeParams,
+    SplitExpenseEditTitleParams,
+    SplitExpenseSubtitleParams,
+    StatementTitleParams,
     StepCounterParams,
+    StripePaidParams,
+    SubmitsToParams,
+    SubmittedToVacationDelegateParams,
+    SubmittedWithMemoParams,
+    SubscriptionCommitmentParams,
+    SubscriptionSettingsLearnMoreParams,
+    SubscriptionSettingsRenewsOnParams,
+    SubscriptionSettingsSaveUpToParams,
+    SubscriptionSettingsSummaryParams,
+    SubscriptionSizeParams,
     SyncStageNameConnectionsParams,
+    TaskCreatedActionParams,
+    TaxAmountParams,
+    TermsParams,
+    ThreadRequestReportNameParams,
+    ThreadSentMoneyReportNameParams,
+    ToggleImportTitleParams,
+    TotalAmountGreaterOrLessThanOriginalParams,
+    ToValidateLoginParams,
+    TransferParams,
+    TravelTypeParams,
+    TrialStartedTitleParams,
+    UnapproveWithIntegrationWarningParams,
     UnshareParams,
-    UnsupportedFormulaValueErrorParams,
+    UntilTimeParams,
+    UpdatedBudgetParams,
+    UpdatedCustomFieldParams,
+    UpdatedPolicyApprovalRuleParams,
+    UpdatedPolicyAuditRateParams,
+    UpdatedPolicyAutoHarvestingParams,
+    UpdatedPolicyBudgetNotificationParams,
+    UpdatedPolicyCategoriesParams,
+    UpdatedPolicyCategoryDescriptionHintTypeParams,
+    UpdatedPolicyCategoryExpenseLimitTypeParams,
+    UpdatedPolicyCategoryGLCodeParams,
+    UpdatedPolicyCategoryMaxAmountNoReceiptParams,
+    UpdatedPolicyCategoryMaxExpenseAmountParams,
+    UpdatedPolicyCategoryNameParams,
+    UpdatedPolicyCategoryParams,
+    UpdatedPolicyCurrencyParams,
+    UpdatedPolicyCustomUnitRateEnabledParams,
+    UpdatedPolicyCustomUnitRateParams,
+    UpdatedPolicyCustomUnitSubRateParams,
+    UpdatedPolicyCustomUnitTaxClaimablePercentageParams,
+    UpdatedPolicyCustomUnitTaxRateExternalIDParams,
+    UpdatedPolicyDefaultTitleParams,
+    UpdatedPolicyDescriptionParams,
+    UpdatedPolicyFieldWithNewAndOldValueParams,
+    UpdatedPolicyFieldWithValueParams,
+    UpdatedPolicyFrequencyParams,
+    UpdatedPolicyManualApprovalThresholdParams,
+    UpdatedPolicyOwnershipParams,
+    UpdatedPolicyPreventSelfApprovalParams,
+    UpdatedPolicyReimbursementChoiceParams,
+    UpdatedPolicyReimbursementEnabledParams,
+    UpdatedPolicyReimburserParams,
+    UpdatedPolicyReportFieldDefaultValueParams,
+    UpdatedPolicyTagFieldParams,
+    UpdatedPolicyTagListParams,
+    UpdatedPolicyTagListRequiredParams,
+    UpdatedPolicyTagNameParams,
+    UpdatedPolicyTagParams,
+    UpdatedPolicyTaxParams,
+    UpdatedPolicyTimeEnabledParams,
+    UpdatedPolicyTimeRateParams,
+    UpdatedTheDistanceMerchantParams,
+    UpdatedTheRequestParams,
+    UpdatePolicyCustomUnitDefaultCategoryParams,
+    UpdatePolicyCustomUnitParams,
+    UpdatePolicyCustomUnitTaxEnabledParams,
     UpdateRoleParams,
-    ViolationsIncreasedDistanceParams,
+    UpgradeSuccessMessageParams,
+    UsePlusButtonParams,
+    UserIsAlreadyMemberParams,
+    UserSplitParams,
+    VacationDelegateParams,
+    ViolationsCashExpenseWithNoReceiptParams,
+    ViolationsConversionSurchargeParams,
+    ViolationsCustomRulesParams,
+    ViolationsInvoiceMarkupParams,
+    ViolationsMaxAgeParams,
+    ViolationsMissingTagParams,
     ViolationsModifiedAmountParams,
+    ViolationsOverCategoryLimitParams,
+    ViolationsOverLimitParams,
+    ViolationsPerDayLimitParams,
+    ViolationsProhibitedExpenseParams,
+    ViolationsReceiptRequiredParams,
+    ViolationsRterParams,
+    ViolationsTagOutOfPolicyParams,
+    ViolationsTaxOutOfPolicyParams,
+    WaitingOnBankAccountParams,
+    WalletAgreementParams,
+    WalletProgramParams,
+    WelcomeEnterMagicCodeParams,
+    WelcomeToRoomParams,
+    WeSentYouMagicSignInLinkParams,
+    WorkEmailMergingBlockedParams,
+    WorkEmailResendCodeParams,
+    WorkflowSettingsParam,
     WorkspaceLockedPlanTypeParams,
+    WorkspaceMemberList,
+    WorkspaceMembersCountParams,
+    WorkspaceOwnerWillNeedToAddOrUpdatePaymentCardParams,
+    WorkspaceRouteParams,
+    WorkspaceShareNoteParams,
+    WorkspacesListRouteParams,
+    WorkspaceUpgradeNoteParams,
+    WorkspaceYouMayJoin,
     YourPlanPriceParams,
+    YourPlanPriceValueParams,
+    ZipCodeExampleFormatParams,
 } from './params';
 import type {TranslationDeepObject} from './types';
 
@@ -90,10 +227,8 @@ const translations: TranslationDeepObject<typeof en> = {
         optional: 'Optional',
         new: 'Neu',
         newFeature: 'Neue Funktion',
-        beta: 'Beta',
         search: 'Suche',
         reports: 'Berichte',
-        spend: 'Ausgaben',
         find: 'Finden',
         searchWithThreeDots: 'Suchen...',
         next: 'Weiter',
@@ -118,14 +253,6 @@ const translations: TranslationDeepObject<typeof en> = {
         workspaces: 'Workspaces',
         home: 'Startseite',
         inbox: 'Posteingang',
-        yourReviewIsRequired: 'Ihre Überprüfung ist erforderlich',
-        actionBadge: {
-            submit: 'Senden',
-            approve: 'Genehmigen',
-            pay: 'Bezahlen',
-            fix: 'Beheben',
-            task: 'Aufgabe',
-        },
         success: 'Erfolgreich',
         group: 'Gruppe',
         profile: 'Profil',
@@ -135,7 +262,7 @@ const translations: TranslationDeepObject<typeof en> = {
         wallet: 'Brieftasche',
         preferences: 'Einstellungen',
         view: 'Anzeigen',
-        review: (amount?: string) => `Prüfen${amount ? ` ${amount}` : ''}`,
+        review: (reviewParams?: ReviewParams) => `Prüfen${reviewParams?.amount ? ` ${reviewParams?.amount}` : ''}`,
         not: 'Nicht',
         signIn: 'Anmelden',
         signInWithGoogle: 'Mit Google anmelden',
@@ -146,7 +273,6 @@ const translations: TranslationDeepObject<typeof en> = {
         lastName: 'Nachname',
         scanning: 'Scannen',
         analyzing: 'Analysiere…',
-        thinking: 'Concierge denkt nach...',
         addCardTermsOfService: 'Expensify-Nutzungsbedingungen',
         perPerson: 'pro Person',
         phone: 'Telefon',
@@ -208,12 +334,10 @@ const translations: TranslationDeepObject<typeof en> = {
         admin: 'Admin',
         owner: 'Inhaber',
         dateFormat: 'YYYY-MM-DD',
-        calendarOpened: 'Kalender geöffnet',
         send: 'Senden',
         na: 'k. A.',
         noResultsFound: 'Keine Ergebnisse gefunden',
-        noResultsFoundMatching: (searchString: string) => `Keine Ergebnisse gefunden für „${searchString}”`,
-        suggestionsAvailableFor: (searchString: string) => (searchString ? `Vorschläge verfügbar für „${searchString}”.` : 'Vorschläge verfügbar.'),
+        noResultsFoundMatching: (searchString: string) => `Keine Ergebnisse gefunden für „${searchString}“`,
         recentDestinations: 'Letzte Ziele',
         timePrefix: 'Es ist',
         conjunctionFor: 'für',
@@ -224,7 +348,6 @@ const translations: TranslationDeepObject<typeof en> = {
         conjunctionTo: 'bis',
         genericErrorMessage: 'Ups ... etwas ist schiefgelaufen und Ihre Anfrage konnte nicht abgeschlossen werden. Bitte versuchen Sie es später noch einmal.',
         percentage: 'Prozentsatz',
-        progressBarLabel: 'Onboarding-Fortschritt',
         converted: 'Umgewandelt',
         error: {
             invalidAmount: 'Ungültiger Betrag',
@@ -263,7 +386,6 @@ const translations: TranslationDeepObject<typeof en> = {
         reset: 'Zurücksetzen',
         done: 'Fertig',
         more: 'Mehr',
-        other: 'Andere',
         debitCard: 'Debitkarte',
         bankAccount: 'Bankkonto',
         personalBankAccount: 'Persönliches Bankkonto',
@@ -289,7 +411,7 @@ const translations: TranslationDeepObject<typeof en> = {
         verify: 'Bestätigen',
         yesContinue: 'Ja, fortfahren',
         websiteExample: 'z.&nbsp;B. https://www.expensify.com',
-        zipCodeExampleFormat: (zipSampleFormat: string) => (zipSampleFormat ? `z. B. ${zipSampleFormat}` : ''),
+        zipCodeExampleFormat: ({zipSampleFormat}: ZipCodeExampleFormatParams) => (zipSampleFormat ? `z. B. ${zipSampleFormat}` : ''),
         description: 'Beschreibung',
         title: 'Titel',
         assignee: 'Zuständige Person',
@@ -300,8 +422,6 @@ const translations: TranslationDeepObject<typeof en> = {
         per: 'pro',
         mi: 'Meile',
         km: 'Kilometer',
-        milesAbbreviated: 'mi',
-        kilometersAbbreviated: 'km',
         copied: 'Kopiert!',
         someone: 'Jemand',
         total: 'Gesamt',
@@ -310,7 +430,6 @@ const translations: TranslationDeepObject<typeof en> = {
         letsStart: `Lass uns anfangen`,
         showMore: 'Mehr anzeigen',
         showLess: 'Weniger anzeigen',
-        plusMore: ({count}: {count: number}) => `+${count} weitere`,
         merchant: 'Händler',
         change: 'Ändern',
         category: 'Kategorie',
@@ -334,11 +453,8 @@ const translations: TranslationDeepObject<typeof en> = {
         selectCurrency: 'Wähle eine Währung',
         selectSymbolOrCurrency: 'Wähle ein Symbol oder eine Währung aus',
         card: 'Karte',
-        mcc: 'MCC',
-        categoryGLCode: 'Kategorie-GL-Code',
         whyDoWeAskForThis: 'Warum fragen wir danach?',
         required: 'Erforderlich',
-        automatic: 'Automatisch',
         showing: 'Wird angezeigt',
         of: 'von',
         default: 'Standard',
@@ -346,8 +462,6 @@ const translations: TranslationDeepObject<typeof en> = {
         member: 'Mitglied',
         auditor: 'Prüfer',
         role: 'Rolle',
-        roleCannotBeChanged: (workflowsLinkPage: string) =>
-            `Die Rolle kann nicht geändert werden, da dieses Mitglied ein <a href="${workflowsLinkPage}">zahler</a> in diesem Arbeitsbereich ist.`,
         currency: 'Währung',
         groupCurrency: 'Gruppenwährung',
         rate: 'Bewerten',
@@ -385,7 +499,6 @@ const translations: TranslationDeepObject<typeof en> = {
         reportID: 'Berichts-ID',
         longReportID: 'Langer Bericht-ID',
         withdrawalID: 'Auszahlungs-ID',
-        withdrawalStatus: 'Auszahlungsstatus',
         bankAccounts: 'Bankkonten',
         chooseFile: 'Datei auswählen',
         chooseFiles: 'Dateien auswählen',
@@ -419,21 +532,19 @@ const translations: TranslationDeepObject<typeof en> = {
         validate: 'Validieren',
         downloadAsPDF: 'Als PDF herunterladen',
         downloadAsCSV: 'Als CSV herunterladen',
-        print: 'Drucken',
         help: 'Hilfe',
-        collapsed: 'Eingeklappt',
-        expanded: 'Ausgeklappt',
         expenseReport: 'Spesenabrechnung',
+        expenseReports: 'Spesenabrechnungen',
         rateOutOfPolicy: 'Satz außerhalb der Richtlinie',
         leaveWorkspace: 'Arbeitsbereich verlassen',
         leaveWorkspaceConfirmation: 'Wenn du diesen Workspace verlässt, kannst du keine Ausgaben mehr dafür einreichen.',
         leaveWorkspaceConfirmationAuditor: 'Wenn du diesen Workspace verlässt, kannst du seine Berichte und Einstellungen nicht mehr anzeigen.',
         leaveWorkspaceConfirmationAdmin: 'Wenn du diesen Workspace verlässt, kannst du seine Einstellungen nicht mehr verwalten.',
-        leaveWorkspaceConfirmationApprover: (workspaceOwner: string) =>
+        leaveWorkspaceConfirmationApprover: ({workspaceOwner}: {workspaceOwner: string}) =>
             `Wenn du diesen Workspace verlässt, wirst du im Genehmigungsworkflow durch ${workspaceOwner}, den/die Workspace-Inhaber(in), ersetzt.`,
-        leaveWorkspaceConfirmationExporter: (workspaceOwner: string) =>
+        leaveWorkspaceConfirmationExporter: ({workspaceOwner}: {workspaceOwner: string}) =>
             `Wenn du diesen Workspace verlässt, wirst du als bevorzugte exportierende Person durch ${workspaceOwner}, die Workspace-Inhaber*in, ersetzt.`,
-        leaveWorkspaceConfirmationTechContact: (workspaceOwner: string) =>
+        leaveWorkspaceConfirmationTechContact: ({workspaceOwner}: {workspaceOwner: string}) =>
             `Wenn du diesen Workspace verlässt, wirst du als technischer Kontakt durch ${workspaceOwner}, den Workspace-Inhaber, ersetzt.`,
         leaveWorkspaceReimburser:
             'Du kannst diesen Workspace als Erstattungsverantwortliche·r nicht verlassen. Bitte lege unter „Workspaces > Zahlungen senden oder nachverfolgen“ eine·n neue·n Erstattungsverantwortliche·n fest und versuche es erneut.',
@@ -442,6 +553,9 @@ const translations: TranslationDeepObject<typeof en> = {
         comments: 'Kommentare',
         sharedIn: 'Geteilt in',
         unreported: 'Nicht gemeldet',
+        explore: 'Entdecken',
+        insights: 'Insights',
+        todo: 'To-do',
         invoice: 'Rechnung',
         expense: 'Ausgabe',
         chat: 'Chat',
@@ -452,15 +566,12 @@ const translations: TranslationDeepObject<typeof en> = {
         on: 'Ein',
         before: 'Vor',
         after: 'Nach',
-        range: 'Bereich',
         reschedule: 'Verschieben',
         general: 'Allgemein',
         workspacesTabTitle: 'Workspaces',
         headsUp: 'Achtung!',
         submitTo: 'Einreichen bei',
         forwardTo: 'Weiterleiten an',
-        approvalLimit: 'Genehmigungslimit',
-        overLimitForwardTo: 'Weiterleiten bei Überschreitung',
         merge: 'Zusammenführen',
         none: 'Keine',
         unstableInternetConnection: 'Instabile Internetverbindung. Bitte überprüfe dein Netzwerk und versuche es erneut.',
@@ -481,44 +592,19 @@ const translations: TranslationDeepObject<typeof en> = {
         exchangeRate: 'Wechselkurs',
         reimbursableTotal: 'Erstattungsfähiger Gesamtbetrag',
         nonReimbursableTotal: 'Nicht erstattungsfähige Gesamtsumme',
-        opensInNewTab: 'Wird in einem neuen Tab geöffnet',
         locked: 'Gesperrt',
         month: 'Monat',
         week: 'Woche',
         year: 'Jahr',
         quarter: 'Quartal',
-        vacationDelegate: 'Urlaubsvertretung',
-        expensifyLogo: 'Expensify-Logo',
-        concierge: {greeting: 'Hallo, wie kann ich helfen?', showHistory: 'Verlauf anzeigen'},
-        duplicateReport: 'Duplizierten Bericht',
-        approver: 'Genehmiger',
-        goToConcierge: 'Zu Concierge',
-        allSet: 'Alles erledigt!',
-        enterDigitLabel: ({digitIndex, totalDigits}: {digitIndex: number; totalDigits: number}) => `Ziffer ${digitIndex} von ${totalDigits} eingeben`,
-        copyOfReportName: (reportName: string) => `Kopie von ${reportName}`,
-        previousMonth: 'Vorheriger Monat',
-        nextMonth: 'Nächster Monat',
-        previousYear: 'Vorheriges Jahr',
-        nextYear: 'Nächstes Jahr',
-        avatar: 'Avatar',
-        editor: 'Editor',
-        restrictions: 'Beschränkungen',
-    },
-    socials: {
-        podcast: 'Folgen Sie uns auf Podcast',
-        twitter: 'Folgen Sie uns auf Twitter',
-        instagram: 'Folgen Sie uns auf Instagram',
-        facebook: 'Folgen Sie uns auf Facebook',
-        linkedin: 'Folgen Sie uns auf LinkedIn',
-    },
-    concierge: {
-        collapseReasoning: 'Begründung einklappen',
-        expandReasoning: 'Begründung erweitern',
-        enableNotifications: {prompt: 'Möchten Sie benachrichtigt werden, wenn Concierge antwortet?', cta: 'Benachrichtigen'},
     },
     supportalNoAccess: {
         title: 'Nicht so schnell',
-        descriptionWithCommand: (command?: string) =>
+        descriptionWithCommand: ({
+            command,
+        }: {
+            command?: string;
+        } = {}) =>
             `Sie sind nicht berechtigt, diese Aktion auszuführen, wenn der Support eingeloggt ist (Befehl: ${command ?? ''}). Wenn Sie der Meinung sind, dass Success in der Lage sein sollte, diese Aktion auszuführen, beginnen Sie bitte ein Gespräch in Slack.`,
     },
     lockedAccount: {
@@ -554,7 +640,7 @@ const translations: TranslationDeepObject<typeof en> = {
         chooseDocument: 'Datei auswählen',
         attachmentTooLarge: 'Anhang ist zu groß',
         sizeExceeded: 'Die Anhangsgröße überschreitet das Limit von 24 MB',
-        sizeExceededWithLimit: (maxUploadSizeInMB: number) => `Die Anhangsgröße überschreitet das Limit von ${maxUploadSizeInMB} MB`,
+        sizeExceededWithLimit: ({maxUploadSizeInMB}: SizeExceededParams) => `Die Anhangsgröße überschreitet das Limit von ${maxUploadSizeInMB} MB`,
         attachmentTooSmall: 'Anhang ist zu klein',
         sizeNotMet: 'Die Anhangsgröße muss größer als 240 Bytes sein',
         wrongFileType: 'Ungültiger Dateityp',
@@ -565,9 +651,9 @@ const translations: TranslationDeepObject<typeof en> = {
         attachmentImageTooLarge: 'Dieses Bild ist zu groß, um vor dem Hochladen eine Vorschau anzuzeigen.',
         imageDimensionsTooLarge: 'Die Bildabmessungen sind zu groß zum Verarbeiten. Bitte verwenden Sie ein kleineres Bild.',
         tooManyFiles: (fileLimit: number) => `Sie können jeweils nur bis zu ${fileLimit} Dateien hochladen.`,
-        sizeExceededWithValue: (maxUploadSizeInMB: number) => `Dateien überschreiten ${maxUploadSizeInMB} MB. Bitte versuche es erneut.`,
+        sizeExceededWithValue: ({maxUploadSizeInMB}: SizeExceededParams) => `Dateien überschreiten ${maxUploadSizeInMB} MB. Bitte versuche es erneut.`,
         someFilesCantBeUploaded: 'Einige Dateien können nicht hochgeladen werden',
-        sizeLimitExceeded: (maxUploadSizeInMB: number) => `Dateien dürfen nicht größer als ${maxUploadSizeInMB} MB sein. Größere Dateien werden nicht hochgeladen.`,
+        sizeLimitExceeded: ({maxUploadSizeInMB}: SizeExceededParams) => `Dateien dürfen nicht größer als ${maxUploadSizeInMB} MB sein. Größere Dateien werden nicht hochgeladen.`,
         maxFileLimitExceeded: 'Sie können bis zu 30 Belege auf einmal hochladen. Weitere darüber hinaus werden nicht hochgeladen.',
         unsupportedFileType: (fileType: string) => `${fileType}-Dateien werden nicht unterstützt. Es werden nur unterstützte Dateitypen hochgeladen.`,
         learnMoreAboutSupportedFiles: 'Erfahren Sie mehr über unterstützte Formate.',
@@ -607,55 +693,17 @@ const translations: TranslationDeepObject<typeof en> = {
         signIn: 'Bitte melde dich erneut an.',
     },
     multifactorAuthentication: {
-        reviewTransaction: {
-            reviewTransaction: 'Transaktion prüfen',
-            pleaseReview: 'Bitte überprüfe diese Transaktion',
-            requiresYourReview: 'Eine Expensify Card-Transaktion erfordert unten Ihre Überprüfung.',
-            transactionDetails: 'Transaktionsdetails',
-            deny: 'Ablehnen',
-            approve: 'Genehmigen',
-            denyTransaction: 'Transaktion ablehnen',
-            transactionDenied: 'Transaktion abgelehnt',
-            transactionApproved: 'Transaktion genehmigt!',
-            areYouSureToDeny: 'Bist du sicher? Die Transaktion wird abgelehnt, wenn du diesen Bildschirm schließt.',
-            youCanTryAgainAtMerchantOrReachOut:
-                'Du kannst es erneut beim Händler versuchen. Wenn du diese Transaktion nicht versucht hast, <concierge-link>wende dich an Concierge</concierge-link>, um möglichen Betrug zu melden.',
-            youNeedToTryAgainAtMerchant: 'Diese Transaktion wurde nicht verifiziert, daher haben wir sie abgelehnt. Bitte versuch es erneut direkt beim Händler.',
-            goBackToTheMerchant: 'Gehe zurück zur Händlerseite, um die Transaktion fortzusetzen.',
-            attemptedTransaction: 'Versuchte Transaktion',
-            transactionFailed: 'Transaktion fehlgeschlagen',
-            transactionCouldNotBeCompleted: 'Ihre Transaktion konnte nicht abgeschlossen werden. Bitte versuchen Sie es erneut beim Händler.',
-            transactionCouldNotBeCompletedReachOut:
-                'Ihre Transaktion konnte nicht abgeschlossen werden. Wenn Sie diese Transaktion nicht versucht haben, <concierge-link>wenden Sie sich an Concierge</concierge-link>, um möglichen Betrug zu melden.',
-            reviewFailed: 'Überprüfung fehlgeschlagen',
-            alreadyReviewedSubtitle:
-                'Sie haben diese Transaktion bereits überprüft. Bitte prüfen Sie Ihren <transaction-history-link>Transaktionsverlauf</transaction-history-link> oder kontaktieren Sie <concierge-link>Concierge</concierge-link>, um Probleme zu melden.',
-        },
         biometricsTest: {
             biometricsTest: 'Biometrie-Test',
             authenticationSuccessful: 'Authentifizierung erfolgreich',
-            successfullyAuthenticatedUsing: (authType?: string) => `Sie haben sich erfolgreich mit ${authType} authentifiziert.`,
-            troubleshootBiometricsStatus: ({status}: {status?: string}) => `Biometrische Daten (${status})`,
+            successfullyAuthenticatedUsing: ({authType}: MultifactorAuthenticationTranslationParams) => `Du hast dich erfolgreich mit ${authType} authentifiziert.`,
+            troubleshootBiometricsStatus: ({registered}: MultifactorAuthenticationTranslationParams) => `Biometrie (${registered ? 'Registriert' : 'Nicht registriert'})`,
             yourAttemptWasUnsuccessful: 'Dein Authentifizierungsversuch war nicht erfolgreich.',
             youCouldNotBeAuthenticated: 'Du konntest nicht authentifiziert werden',
             areYouSureToReject: 'Sind Sie sicher? Der Authentifizierungsversuch wird abgelehnt, wenn Sie diesen Bildschirm schließen.',
             rejectAuthentication: 'Authentifizierung ablehnen',
             test: 'Test',
             biometricsAuthentication: 'Biometrische Authentifizierung',
-            authType: {
-                unknown: 'Unbekannt',
-                none: 'Keine',
-                credentials: 'Anmeldedaten',
-                biometrics: 'Biometrie',
-                faceId: 'Face ID',
-                touchId: 'Touch ID',
-                opticId: 'Optic ID',
-                passkey: 'Passkey',
-            },
-            statusNeverRegistered: 'Nie registriert',
-            statusNotRegistered: 'Nicht registriert',
-            statusRegisteredThisDevice: 'Registriert',
-            statusRegisteredOtherDevice: () => ({one: 'Anderes Gerät registriert', other: 'Andere Geräte registriert'}),
         },
         pleaseEnableInSystemSettings: {
             start: 'Bitte aktiviere die Gesichts-/Fingerabdrucküberprüfung oder richte einen Gerätecode auf deinem Gerät ein',
@@ -668,42 +716,27 @@ const translations: TranslationDeepObject<typeof en> = {
         letsVerifyItsYou: 'Lass uns bestätigen, dass du es bist',
         nowLetsAuthenticateYou: 'Lassen Sie uns Sie jetzt authentifizieren …',
         letsAuthenticateYou: 'Lass uns dich authentifizieren …',
-        verifyYourself: {biometrics: 'Bestätige dich mit deinem Gesicht oder Fingerabdruck', passkeys: 'Bestätigen Sie sich mit einem Passkey'},
+        verifyYourself: {
+            biometrics: 'Bestätige dich mit deinem Gesicht oder Fingerabdruck',
+        },
         enableQuickVerification: {
             biometrics: 'Aktiviere eine schnelle, sichere Verifizierung mit deinem Gesicht oder Fingerabdruck. Keine Passwörter oder Codes erforderlich.',
-            passkeys: 'Aktivieren Sie eine schnelle, sichere Verifizierung mit einem Passkey. Keine Passwörter oder Codes erforderlich.',
         },
         revoke: {
-            title: 'Gesicht/Fingerabdruck & Zugangsschlüssel',
+            remove: 'Entfernen',
+            title: 'Gesicht/Fingerabdruck & Passkeys',
             explanation:
-                'Gesichts-/Fingerabdruck- oder Passkey-Verifizierung ist auf einem oder mehreren Geräten aktiviert. Beim Entziehen des Zugriffs ist für die nächste Verifizierung auf diesem Gerät ein magischer Code erforderlich.',
-            confirmationPrompt: 'Sind Sie sicher? Sie benötigen einen magischen Code für die nächste Verifizierung auf diesem Gerät.',
-            cta: 'Zugriff entziehen',
-            noDevices: 'Sie haben keine Geräte für Gesichts-/Fingerabdruck- oder Passkey-Verifizierung registriert. Wenn Sie welche registrieren, können Sie deren Zugriff hier widerrufen.',
+                'Gesichts-/Fingerabdruck- oder Passkey-Verifizierung ist auf einem oder mehreren Geräten aktiviert. Das Widerrufen des Zugriffs erfordert für die nächste Verifizierung auf jedem Gerät einen magischen Code.',
+            confirmationPrompt: 'Bist du sicher? Du brauchst einen magischen Code für die nächste Verifizierung auf jedem Gerät.',
+            cta: 'Zugriff widerrufen',
+            noDevices: 'Sie haben keine Geräte für die Überprüfung per Gesicht/Fingerabdruck oder Passkey registriert. Wenn Sie welche registrieren, können Sie den Zugriff hier widerrufen.',
             dismiss: 'Verstanden',
             error: 'Anfrage fehlgeschlagen. Versuche es später noch einmal.',
-            revoke: 'Widerrufen',
-            confirmationPromptAll: 'Sind Sie sicher? Sie benötigen einen Magic Code für die nächste Verifizierung auf jedem Gerät.',
-            ctaAll: 'Alle widerrufen',
-            thisDevice: 'Dieses Gerät',
-            otherDevices: (otherDeviceCount?: number) => {
-                const numberWords = ['Eins', 'Zwei', 'Drei', 'Vier', 'Fünf', 'Sechs', 'Sieben', 'Acht', 'Neun'];
-                const displayCount = otherDeviceCount !== undefined && otherDeviceCount >= 1 && otherDeviceCount <= 9 ? numberWords.at(otherDeviceCount - 1) : `${otherDeviceCount}`;
-                return `${displayCount} weitere ${otherDeviceCount === 1 ? 'Gerät' : 'Geräte'}`;
-            },
-            confirmationPromptThisDevice: 'Sind Sie sicher? Sie benötigen einen Magic-Code für die nächste Verifizierung auf diesem Gerät.',
-            confirmationPromptMultiple: 'Sind Sie sicher? Sie benötigen einen magischen Code für die nächste Verifizierung auf diesen Geräten.',
         },
         unsupportedDevice: {
             unsupportedDevice: 'Nicht unterstütztes Gerät',
-            pleaseDownloadMobileApp: `Diese Aktion wird auf deinem Gerät nicht unterstützt. Bitte lade die Expensify-App aus dem <a href="${CONST.APP_DOWNLOAD_LINKS.IOS}">App Store</a> oder dem <a href="${CONST.APP_DOWNLOAD_LINKS.ANDROID}">Google Play Store</a> herunter und versuche es erneut.`,
-            pleaseUseWebApp: `Diese Aktion wird auf deinem Gerät nicht unterstützt. Bitte verwende die <a href="${CONST.NEW_EXPENSIFY_URL}">Expensify-Webanwendung</a> und versuche es erneut.`,
+            pleaseDownloadMobileApp: `<centered-text><muted-text> Diese Aktion wird auf deinem Gerät nicht unterstützt. Bitte lade die Expensify-App aus dem <a href="${CONST.APP_DOWNLOAD_LINKS.IOS}">App Store</a> oder dem <a href="${CONST.APP_DOWNLOAD_LINKS.ANDROID}">Google Play Store</a> herunter und versuche es erneut.</muted-text></centered-text>`,
         },
-        verificationFailed: 'Überprüfung fehlgeschlagen',
-        setPin: {didNotShipCard: 'Wir haben Ihre Karte nicht versendet. Bitte versuchen Sie es erneut.'},
-        revealPin: {couldNotReveal: 'Wir konnten Ihre PIN nicht anzeigen. Bitte versuchen Sie es erneut.'},
-        changePin: {didNotChange: 'Wir haben Ihre PIN nicht geändert. Bitte versuchen Sie es erneut.'},
-        revealCardDetail: {couldNotReveal: 'Wir konnten Ihre Kartendaten nicht anzeigen. Bitte versuchen Sie es noch einmal.'},
     },
     validateCodeModal: {
         successfulSignInTitle: dedent(`
@@ -717,7 +750,7 @@ const translations: TranslationDeepObject<typeof en> = {
             auf dem er ursprünglich angefordert wurde
         `),
         doNotShare: dedent(`
-            Gib deinen Code an niemanden weiter.
+            Gib deinen Code an niemanden weiter.  
             Expensify wird niemals danach fragen!
         `),
         or: 'oder',
@@ -742,7 +775,11 @@ const translations: TranslationDeepObject<typeof en> = {
         nameEmailOrPhoneNumber: 'Name, E-Mail-Adresse oder Telefonnummer',
         findMember: 'Mitglied finden',
         searchForSomeone: 'Nach jemandem suchen',
-        userSelected: (username: string) => `${username} ausgewählt`,
+    },
+    customApprovalWorkflow: {
+        title: 'Benutzerdefinierter Genehmigungsworkflow',
+        description: 'Ihr Unternehmen verwendet in diesem Workspace einen benutzerdefinierten Genehmigungs-Workflow. Bitte führen Sie diese Aktion in Expensify Classic aus',
+        goToExpensifyClassic: 'Zu Expensify Classic wechseln',
     },
     emptyList: {
         [CONST.IOU.TYPE.CREATE]: {
@@ -764,8 +801,9 @@ const translations: TranslationDeepObject<typeof en> = {
         phrase2: 'Geld spricht. Und jetzt, da Chat und Zahlungen an einem Ort sind, ist es auch einfach.',
         phrase3: 'Deine Zahlungen kommen so schnell bei dir an, wie du deinen Standpunkt klarmachen kannst.',
         enterPassword: 'Bitte geben Sie Ihr Passwort ein',
-        welcomeNewFace: (login: string) => `${login}, es ist immer schön, ein neues Gesicht hier zu sehen!`,
-        welcomeEnterMagicCode: (login: string) => `Bitte gib den magischen Code ein, der an ${login} gesendet wurde. Er sollte innerhalb einer oder zwei Minuten ankommen.`,
+        welcomeNewFace: ({login}: SignUpNewFaceCodeParams) => `${login}, es ist immer schön, ein neues Gesicht hier zu sehen!`,
+        welcomeEnterMagicCode: ({login}: WelcomeEnterMagicCodeParams) =>
+            `Bitte gib den magischen Code ein, der an ${login} gesendet wurde. Er sollte innerhalb einer oder zwei Minuten ankommen.`,
     },
     login: {
         hero: {
@@ -793,9 +831,6 @@ const translations: TranslationDeepObject<typeof en> = {
         emoji: 'Emoji',
         collapse: 'Einklappen',
         expand: 'Erweitern',
-        askConciergeToUpdate: 'Versuche „Eine Ausgabe aktualisieren“…',
-        askConciergeToCorrect: 'Versuche es mit „Ausgabe korrigieren“ …',
-        askConciergeForHelp: 'Bitte Concierge AI um Hilfe ...',
     },
     reportActionContextMenu: {
         copyMessage: 'Nachricht kopieren',
@@ -859,9 +894,9 @@ const translations: TranslationDeepObject<typeof en> = {
         askMeAnything: 'Frag mich alles!',
         sayHello: 'Sag hallo!',
         yourSpace: 'Dein Bereich',
-        welcomeToRoom: (roomName: string) => `Willkommen in ${roomName}!`,
-        usePlusButton: (additionalText: string) => `Verwende die +‑Taste, um eine Ausgabe zu ${additionalText}.`,
-        askConcierge: 'Concierge kann Fragen beantworten, Ausgaben aktualisieren und mehr.',
+        welcomeToRoom: ({roomName}: WelcomeToRoomParams) => `Willkommen in ${roomName}!`,
+        usePlusButton: ({additionalText}: UsePlusButtonParams) => `Verwende die +‑Taste, um eine Ausgabe zu ${additionalText}.`,
+        askConcierge: 'Frag mich alles!',
         conciergeSupport: 'Dein persönlicher KI-Agent',
         create: 'erstellen',
         iouTypes: {
@@ -873,17 +908,12 @@ const translations: TranslationDeepObject<typeof en> = {
         },
     },
     adminOnlyCanPost: 'Nur Admins können Nachrichten in diesem Raum senden.',
-    readOnlyConversation: 'Diese Konversation ist schreibgeschützt.',
     reportAction: {
         asCopilot: 'als Copilot für',
-        assistedBy: (agentName: string) => `unterstützt von ${agentName}`,
-        humanSupportAgent: 'einem menschlichen Support-Mitarbeiter',
         harvestCreatedExpenseReport: (reportUrl: string, reportName: string) =>
             `hat diesen Bericht erstellt, um alle Ausgaben aus <a href="${reportUrl}">${reportName}</a> aufzunehmen, die nicht mit der von dir gewählten Häufigkeit eingereicht werden konnten`,
-        createdReportForUnapprovedTransactions: (reportUrl: string, reportName: string, reportID: string, isReportDeleted: boolean) =>
-            isReportDeleted
-                ? `hat diesen Bericht für alle zurückgehaltenen Ausgaben aus dem gelöschten Bericht #${reportID} erstellt`
-                : `hat diesen Bericht für alle zurückgehaltenen Ausgaben aus <a href="${reportUrl}">${reportName}</a> erstellt`,
+        createdReportForUnapprovedTransactions: ({reportUrl, reportName}: CreatedReportForUnapprovedTransactionsParams) =>
+            `erstellte diesen Bericht für alle zurückgehaltenen Ausgaben aus <a href="${reportUrl}">${reportName}</a>`,
     },
     mentionSuggestions: {
         hereAlternateText: 'Alle in dieser Unterhaltung benachrichtigen',
@@ -922,6 +952,7 @@ const translations: TranslationDeepObject<typeof en> = {
         buttonFind: 'Etwas finden ...',
         buttonMySettings: 'Meine Einstellungen',
         fabNewChat: 'Chat starten',
+        fabNewChatExplained: 'Aktionsmenü öffnen',
         fabScanReceiptExplained: 'Beleg scannen',
         chatPinned: 'Chat angeheftet',
         draftedMessage: 'Entwurfene Nachricht',
@@ -929,44 +960,41 @@ const translations: TranslationDeepObject<typeof en> = {
         listOfChats: 'Chatliste',
         saveTheWorld: 'Rette die Welt',
         tooltip: 'Starte hier!',
+        redirectToExpensifyClassicModal: {
+            title: 'Bald verfügbar',
+            description:
+                'Wir nehmen noch ein paar letzte Anpassungen an New Expensify vor, damit alles zu deiner speziellen Einrichtung passt. In der Zwischenzeit kannst du Expensify Classic verwenden.',
+        },
     },
     homePage: {
         forYou: 'Für dich',
         timeSensitiveSection: {
             title: 'Zeitkritisch',
-            addShippingAddress: {title: 'Wir benötigen deine Versandadresse', subtitle: 'Geben Sie eine Adresse an, um Ihre Expensify Karte zu erhalten.', cta: 'Adresse hinzufügen'},
-            addPaymentCard: {title: 'Fügen Sie eine Zahlungskarte hinzu, um Expensify weiter zu nutzen', subtitle: 'Konto > Abonnement', cta: 'Hinzufügen'},
-            activateCard: {title: 'Aktivieren Sie Ihre Expensify Karte', subtitle: 'Validieren Sie Ihre Karte und beginnen Sie mit dem Ausgeben.', cta: 'Aktivieren'},
-            reviewCardFraud: {
-                title: 'Möglichen Betrug mit Ihrer Expensify Karte überprüfen',
-                titleWithDetails: ({amount, merchant}: {amount: string; merchant: string}) => `Überprüfe mögliche betrügerische ${amount} bei ${merchant}`,
-                subtitle: 'Expensify Karte',
-                cta: 'Überprüfen',
+            cta: 'Antrag',
+            offer50off: {
+                title: 'Sparen Sie 50 % im ersten Jahr!',
+                subtitle: ({formattedTime}: {formattedTime: string}) => `${formattedTime} verbleibend`,
             },
-            ctaFix: 'Beheben',
-            fixCompanyCardConnection: {
-                title: ({feedName}: {feedName: string}) => (feedName ? `${feedName}-Firmenkartenverbindung reparieren` : 'Firmenkarte reparieren Verbindung der Firmenkarte reparieren'),
-                defaultSubtitle: 'Arbeitsbereich',
-                subtitle: ({policyName}: {policyName: string}) => `${policyName} > Unternehmenskarten`,
+            offer25off: {
+                title: 'Erhalte 25 % Rabatt auf dein erstes Jahr!',
+                subtitle: ({days}: {days: number}) => `${days} ${days === 1 ? 'Tag' : 'Tage'} verbleibend`,
             },
-            fixPolicyConnection: {
-                title: ({integrationName}: {integrationName: string}) => `${integrationName}-Verbindung reparieren`,
-                defaultSubtitle: 'Arbeitsbereich',
-                subtitle: ({policyName}: {policyName: string}) => `${policyName} > Buchhaltung`,
+            addShippingAddress: {
+                title: 'Wir benötigen deine Versandadresse',
+                subtitle: 'Gib eine Adresse an, um deine Expensify Card zu erhalten.',
+                cta: 'Adresse hinzufügen',
             },
-            fixPersonalCardConnection: {
-                title: ({cardName}: {cardName?: string}) => (cardName ? `Verbindung der persönlichen Karte ${cardName} reparieren` : 'Verbindung der persönlichen Karte reparieren'),
-                subtitle: 'Wallet',
+            activateCard: {
+                title: 'Aktiviere deine Expensify Card',
+                subtitle: 'Validieren Sie Ihre Karte und beginnen Sie mit dem Ausgeben.',
+                cta: 'Aktivieren',
             },
-            validateAccount: {title: 'Bestätigen Sie Ihr Konto', subtitle: 'Konto', cta: 'Bestätigen'},
-            fixFailedBilling: {title: 'Wir konnten Ihre hinterlegte Karte nicht belasten', subtitle: 'Abonnement'},
-            unlockBankAccount: {
-                workspaceTitle: 'Ihr Geschäftskonto wurde gesperrt',
-                personalTitle: 'Ihr Bankkonto wurde gesperrt',
-                workspaceSubtitle: ({policyName}: {policyName: string}) => policyName,
-                personalSubtitle: 'Geldbörse',
+            ctaFix: 'Beheben',
+            fixCompanyCardConnection: {
+                title: ({feedName}: {feedName: string}) => (feedName ? `${feedName}-Firmenkartenverbindung reparieren` : 'Firmenkarte reparieren Verbindung der Firmenkarte reparieren'),
+                subtitle: 'Workspace > Unternehmenskarten',
             },
-            enterSignerInfo: {title: 'Unterzeichnerdaten erforderlich', subtitle: ({bankAccountLastFour}: {bankAccountLastFour: string}) => `Bankkonto ${bankAccountLastFour}`},
+            fixAccountingConnection: {title: ({integrationName}: {integrationName: string}) => `${integrationName}-Verbindung reparieren`, subtitle: 'Arbeitsbereich > Buchhaltung'},
         },
         announcements: 'Ankündigungen',
         discoverSection: {
@@ -982,78 +1010,12 @@ const translations: TranslationDeepObject<typeof en> = {
             export: ({count}: {count: number}) => `${count} ${count === 1 ? 'Bericht' : 'Berichte'} exportieren`,
             begin: 'Begin',
             emptyStateMessages: {
-                thumbsUpStarsTitle: 'Sie sind fertig!',
-                thumbsUpStarsDescription: 'Daumen hoch für Sie, bleiben Sie gespannt auf weitere Aufgaben.',
-                smallRocketTitle: 'Alles erledigt',
-                smallRocketDescription: 'Anstehende To-dos werden hier angezeigt.',
-                cowboyHatTitle: 'Sie sind fertig!',
-                cowboyHatDescription: 'Alle Aufgaben sind erledigt, halten Sie Ausschau nach weiteren.',
-                trophy1Title: 'Nichts anzuzeigen',
-                trophy1Description: 'Geschafft! Halten Sie Ausschau nach weiteren Aufgaben.',
-                palmTreeTitle: 'Alles erledigt',
-                palmTreeDescription: 'Zeit zum Entspannen, aber bleiben Sie gespannt auf zukünftige Aufgaben.',
-                fishbowlBlueTitle: 'Sie sind fertig!',
-                fishbowlBlueDescription: 'Zukünftige Aufgaben werden hier angezeigt.',
-                targetTitle: 'Alles erledigt',
-                targetDescription: 'Weiter so, Sie bleiben auf Kurs. Schauen Sie später nach weiteren Aufgaben!',
-                chairTitle: 'Nichts anzuzeigen',
-                chairDescription: 'Entspannen Sie sich, wir listen anstehende Aufgaben hier auf.',
-                broomTitle: 'Sie sind fertig!',
-                broomDescription: 'Aufgaben sind erledigt, bleiben Sie aber gespannt auf weitere To-dos.',
-                houseTitle: 'Alles erledigt',
-                houseDescription: 'Hier ist Ihre Zentrale für anstehende Aufgaben.',
-                conciergeBotTitle: 'Nichts anzuzeigen',
-                conciergeBotDescription: 'Biep biep biep biep, schauen Sie später nach weiteren Aufgaben!',
-                checkboxTextTitle: 'Alles erledigt',
-                checkboxTextDescription: 'Haken Sie hier Ihre anstehenden Aufgaben ab.',
-                flashTitle: 'Sie sind fertig!',
-                flashDescription: 'Zukünftige Aufgaben werden hier blitzschnell angezeigt.',
-                sunglassesTitle: 'Nichts anzuzeigen',
-                sunglassesDescription: 'Zeit zum Entspannen, aber bleiben Sie gespannt auf das, was kommt!',
-                f1FlagsTitle: 'Alles erledigt',
-                f1FlagsDescription: 'Sie haben alle offenen Aufgaben abgeschlossen.',
-            },
-        },
-        upcomingTravel: 'Bevorstehende Reisen',
-        upcomingTravelSection: {
-            flightTo: ({destination}: {destination: string}) => `Flug nach ${destination}`,
-            trainTo: ({destination}: {destination: string}) => `Zug nach ${destination}`,
-            hotelIn: ({destination}: {destination: string}) => `Hotel in ${destination}`,
-            carRentalIn: ({destination}: {destination: string}) => `Mietwagen in ${destination}`,
-            inOneWeek: 'In 1 Woche',
-            inDays: () => ({one: 'In 1 Tag', other: (count: number) => `In ${count} Tagen`}),
-            today: 'Heute',
-        },
-        gettingStartedSection: {
-            title: 'Erste Schritte',
-            createWorkspace: 'Workspace erstellen',
-            connectAccounting: ({integrationName}: {integrationName: string}) => `Mit ${integrationName} verbinden`,
-            connectAccountingDefault: 'Mit Buchhaltung verbinden',
-            customizeCategories: 'Buchhaltungskategorien anpassen',
-            linkCompanyCards: 'Firmenkarten verknüpfen',
-            setupRules: 'Ausgabelimits einrichten',
-            inviteAccountant: 'Lade deine:n Steuerberater:in ein',
-        },
-        freeTrialSection: {
-            title: ({days}: {days: number}) => `Kostenlose Testversion: Noch ${days} ${days === 1 ? 'Tag' : 'Tage'}!`,
-            offer50Body: 'Sparen Sie 50 % im ersten Jahr',
-            offer25Body: 'Erhalten Sie 25 % Rabatt auf Ihr erstes Jahr',
-            addCardBody: 'Zahlungskarte hinzufügen',
-            ctaClaim: 'Anspruch',
-            ctaAdd: 'Karte hinzufügen',
-            timeRemaining: ({formattedTime}: {formattedTime: string}) => `Verbleibende Zeit: ${formattedTime}`,
-            timeRemainingDays: () => ({
-                one: 'Verbleibende Zeit: 1 Tag',
-                other: (pluralCount: number) => `Verbleibende Zeit: ${pluralCount} Tage`,
-            }),
-        },
-        yourSpend: {
-            title: 'Ihre Ausgaben',
-            awaitingApproval: 'Ausstehende Genehmigung',
-            repaidLast30Days: 'In den letzten 30 Tagen zurückgezahlt',
-            recentTransactions: ({lastFour}: {lastFour: string}) => `Aktuelle Transaktionen • ${lastFour}`,
+                nicelyDone: 'Gut gemacht',
+                keepAnEyeOut: 'Behalte im Blick, was als Nächstes kommt!',
+                allCaughtUp: 'Alles erledigt',
+                upcomingTodos: 'Anstehende To-dos werden hier angezeigt.',
+            },
         },
-        seeMore: ({count}: {count: number}) => `${count} weitere anzeigen`,
     },
     allSettingsScreen: {
         subscription: 'Abonnement',
@@ -1082,20 +1044,7 @@ const translations: TranslationDeepObject<typeof en> = {
         singleFieldMultipleColumns: (fieldName: string) => `Ups! Du hast ein einzelnes Feld („${fieldName}“) mehreren Spalten zugeordnet. Bitte überprüfe dies und versuche es erneut.`,
         emptyMappedField: (fieldName: string) => `Ups! Das Feld („${fieldName}“) enthält einen oder mehrere leere Werte. Bitte überprüfe es und versuche es erneut.`,
         importSuccessfulTitle: 'Import erfolgreich',
-        importCategoriesSuccessfulDescription: ({added, updated}: {added: number; updated: number}) => {
-            if (!added && !updated) {
-                return 'Es wurden keine Kategorien hinzugefügt oder aktualisiert.';
-            }
-            if (added && updated) {
-                return `${added} ${added === 1 ? 'Kategorie' : 'Kategorien'} hinzugefügt, ${updated} ${updated === 1 ? 'Kategorie' : 'Kategorien'} aktualisiert.`;
-            }
-            if (added) {
-                return added === 1 ? '1 Kategorie wurde hinzugefügt.' : `${added} Kategorien wurden hinzugefügt.`;
-            }
-            return updated === 1 ? '1 Kategorie wurde aktualisiert.' : `${updated} Kategorien wurden aktualisiert.`;
-        },
-        importCompanyCardTransactionsSuccessfulDescription: ({transactions}: {transactions: number}) =>
-            transactions > 1 ? `${transactions} Transaktionen wurden hinzugefügt.` : '1 Transaktion wurde hinzugefügt.',
+        importCategoriesSuccessfulDescription: ({categories}: {categories: number}) => (categories > 1 ? `${categories} Kategorien wurden hinzugefügt.` : '1 Kategorie wurde hinzugefügt.'),
         importMembersSuccessfulDescription: ({added, updated}: {added: number; updated: number}) => {
             if (!added && !updated) {
                 return 'Es wurden keine Mitglieder hinzugefügt oder aktualisiert.';
@@ -1127,7 +1076,6 @@ const translations: TranslationDeepObject<typeof en> = {
             other: (count: number) =>
                 `Bitte bestätige die folgenden Details für die ${count} neuen Workspace-Mitglieder, die im Rahmen dieses Uploads hinzugefügt werden. Bestehende Mitglieder erhalten keine Rollenaktualisierungen oder Einladungsnachrichten.`,
         }),
-        importCompanyCardTransactionsPendingMessage: 'Neue Karten und Transaktionen können etwas Zeit benötigen, bis sie erscheinen. Bitte haben Sie etwas Geduld.',
     },
     receipt: {
         upload: 'Beleg hochladen',
@@ -1160,9 +1108,7 @@ const translations: TranslationDeepObject<typeof en> = {
         deleteReceipt: 'Beleg löschen',
         deleteConfirmation: 'Sind Sie sicher, dass Sie diesen Beleg löschen möchten?',
         addReceipt: 'Beleg hinzufügen',
-        addAdditionalReceipt: 'Zusätzlichen Beleg hinzufügen',
         scanFailed: 'Der Beleg konnte nicht gescannt werden, da Händler, Datum oder Betrag fehlen.',
-        crop: 'Zuschneiden',
         addAReceipt: {
             phrase1: 'Beleg hinzufügen',
             phrase2: 'oder ziehe eine hierher und lege sie ab',
@@ -1182,7 +1128,6 @@ const translations: TranslationDeepObject<typeof en> = {
         noLongerHaveReportAccess: 'Sie haben keinen Zugriff mehr auf Ihr bisheriges Ziel für Schnellaktionen. Wählen Sie unten ein neues aus.',
         updateDestination: 'Ziel aktualisieren',
         createReport: 'Bericht erstellen',
-        createTimeExpense: 'Zeitaufwand erstellen',
     },
     iou: {
         amount: 'Betrag',
@@ -1202,18 +1147,18 @@ const translations: TranslationDeepObject<typeof en> = {
         split: 'Aufteilen',
         splitExpense: 'Ausgabe aufteilen',
         splitDates: 'Geteilte Daten',
-        splitDateRange: (startDate: string, endDate: string, count: number) => `${startDate} bis ${endDate} (${count} Tage)`,
-        splitExpenseSubtitle: (amount: string, merchant: string) => `${amount} von ${merchant}`,
+        splitDateRange: ({startDate, endDate, count}: SplitDateRangeParams) => `${startDate} bis ${endDate} (${count} Tage)`,
+        splitExpenseSubtitle: ({amount, merchant}: SplitExpenseSubtitleParams) => `${amount} von ${merchant}`,
         splitByPercentage: 'Nach Prozentsatz aufteilen',
         splitByDate: 'Nach Datum aufteilen',
         addSplit: 'Aufteilung hinzufügen',
         makeSplitsEven: 'Aufteilungen ausgleichen',
         editSplits: 'Aufteilungen bearbeiten',
-        totalAmountGreaterThanOriginal: (amount: string) => `Der Gesamtbetrag ist um ${amount} höher als die ursprüngliche Ausgabe.`,
-        totalAmountLessThanOriginal: (amount: string) => `Der Gesamtbetrag ist um ${amount} geringer als die ursprüngliche Ausgabe.`,
+        totalAmountGreaterThanOriginal: ({amount}: TotalAmountGreaterOrLessThanOriginalParams) => `Der Gesamtbetrag ist um ${amount} höher als die ursprüngliche Ausgabe.`,
+        totalAmountLessThanOriginal: ({amount}: TotalAmountGreaterOrLessThanOriginalParams) => `Der Gesamtbetrag ist um ${amount} geringer als die ursprüngliche Ausgabe.`,
         splitExpenseZeroAmount: 'Bitte gib einen gültigen Betrag ein, bevor du fortfährst.',
         splitExpenseOneMoreSplit: 'Keine Aufteilungen hinzugefügt. Füge mindestens eine hinzu, um zu speichern.',
-        splitExpenseEditTitle: (amount: string, merchant: string) => `${amount} für ${merchant} bearbeiten`,
+        splitExpenseEditTitle: ({amount, merchant}: SplitExpenseEditTitleParams) => `${amount} für ${merchant} bearbeiten`,
         removeSplit: 'Aufteilung entfernen',
         splitExpenseCannotBeEditedModalTitle: 'Diese Ausgabe kann nicht bearbeitet werden',
         splitExpenseCannotBeEditedModalDescription: 'Genehmigte oder bezahlte Ausgaben können nicht bearbeitet werden',
@@ -1244,12 +1189,9 @@ const translations: TranslationDeepObject<typeof en> = {
         deleteReceipt: 'Beleg löschen',
         findExpense: 'Ausgabe finden',
         deletedTransaction: (amount: string, merchant: string) => `hat eine Ausgabe gelöscht (${amount} für ${merchant})`,
-        movedFromReport: (reportName: string) => `hat eine Ausgabe aus ${reportName} verschoben`,
-        movedFromReportNoName: 'hat eine Ausgabe verschoben',
-        movedTransactionTo: (reportUrl: string, reportName: string) => `hat diese Ausgabe nach <a href="${reportUrl}">${reportName}</a> verschoben`,
-        movedTransactionToAnotherReport: 'hat diese Ausgabe in einen anderen Bericht verschoben',
-        movedTransactionFrom: (reportUrl: string, reportName: string) => `hat diese Ausgabe von <a href="${reportUrl}">${reportName}</a> verschoben`,
-        movedTransactionFromAnotherReport: 'diese Ausgabe aus einem anderen Bericht verschoben',
+        movedFromReport: (reportName: string) => `hat eine Ausgabe verschoben${reportName ? `von ${reportName}` : ''}`,
+        movedTransactionTo: (reportUrl: string, reportName?: string) => `hat diese Ausgabe verschoben${reportName ? `zu <a href="${reportUrl}">${reportName}</a>` : ''}`,
+        movedTransactionFrom: (reportUrl: string, reportName?: string) => `hat diese Ausgabe verschoben${reportName ? `von <a href="${reportUrl}">${reportName}</a>` : ''}`,
         unreportedTransaction: (reportUrl: string) => `hat diese Ausgabe in deinen <a href="${reportUrl}">persönlichen Bereich</a> verschoben`,
         movedAction: (shouldHideMovedReportUrl: boolean, movedReportUrl: string, newParentReportUrl: string, toPolicyName: string) => {
             if (shouldHideMovedReportUrl) {
@@ -1261,10 +1203,7 @@ const translations: TranslationDeepObject<typeof en> = {
         pendingMatch: 'Ausstehende Zuordnung',
         pendingMatchWithCreditCardDescription: 'Beleg wartet auf Abgleich mit Kartenumsatz. Als Barzahlung markieren, um abzubrechen.',
         markAsCash: 'Als Bar markieren',
-        pendingMatchSubmitTitle: 'Bericht einreichen',
-        pendingMatchSubmitDescription: 'Einige Ausgaben warten auf die Zuordnung mit einer Kreditkartentransaktion. Möchten Sie sie als Bar markieren?',
         routePending: 'Routing ausstehend ...',
-        automaticallyEnterExpenseDetails: 'Concierge füllt die Details für Sie aus.',
         receiptScanning: () => ({
             one: 'Beleg wird gescannt ...',
             other: 'Belege werden gescannt …',
@@ -1291,7 +1230,7 @@ const translations: TranslationDeepObject<typeof en> = {
         receiptStatusTitle: 'Scannen …',
         receiptStatusText: 'Nur du kannst diesen Beleg sehen, während er gescannt wird. Schau später noch einmal vorbei oder gib die Details jetzt ein.',
         receiptScanningFailed: 'Belegerkennung fehlgeschlagen. Bitte geben Sie die Details manuell ein.',
-        allTransactionsPendingNextStep: 'Alle Transaktionen sind ausstehend. Sie können diesen Bericht erst einreichen, wenn sie in ein paar Tagen verbucht wurden.',
+        transactionPendingDescription: 'Transaktion ausstehend. Die Buchung kann ein paar Tage dauern.',
         companyInfo: 'Unternehmensinfos',
         companyInfoDescription: 'Wir benötigen noch ein paar weitere Angaben, bevor du deine erste Rechnung senden kannst.',
         yourCompanyName: 'Ihr Firmenname',
@@ -1326,18 +1265,20 @@ const translations: TranslationDeepObject<typeof en> = {
         settledElsewhere: 'Anderswo bezahlt',
         individual: 'Einzelperson',
         business: 'Business',
-        settlePersonal: (formattedAmount?: string) => (formattedAmount ? `${formattedAmount} als Privatperson bezahlen` : `Mit Privatkonto bezahlen`),
-        settleWallet: (formattedAmount?: string) => (formattedAmount ? `${formattedAmount} mit Wallet bezahlen` : `Mit Wallet bezahlen`),
-        settlePayment: (formattedAmount: string) => `${formattedAmount} bezahlen`,
-        settleBusiness: (formattedAmount?: string) => (formattedAmount ? `${formattedAmount} als Unternehmen bezahlen` : `Mit Geschäftskonto bezahlen`),
-        payElsewhere: (formattedAmount?: string) => (formattedAmount ? `${formattedAmount} als bezahlt markieren` : `Als bezahlt markieren`),
-        confirmPaymentReceivedModalTitle: 'Zahlungseingang bestätigen',
-        receivedPayment: 'Zahlung erhalten',
-        receivedPaymentConfirmation: 'Bitte fahren Sie nur fort, wenn Sie die Zahlung bereits außerhalb von Expensify erhalten haben.',
-        confirmReceivedPayment: 'Ja, ich habe die Zahlung erhalten.',
+        settleExpensify: ({formattedAmount}: SettleExpensifyCardParams) => (formattedAmount ? `${formattedAmount} mit Expensify bezahlen` : `Mit Expensify bezahlen`),
+        settlePersonal: ({formattedAmount}: SettleExpensifyCardParams) => (formattedAmount ? `${formattedAmount} als Privatperson bezahlen` : `Mit Privatkonto bezahlen`),
+        settleWallet: ({formattedAmount}: SettleExpensifyCardParams) => (formattedAmount ? `${formattedAmount} mit Wallet bezahlen` : `Mit Wallet bezahlen`),
+        settlePayment: ({formattedAmount}: SettleExpensifyCardParams) => `${formattedAmount} bezahlen`,
+        settleBusiness: ({formattedAmount}: SettleExpensifyCardParams) => (formattedAmount ? `${formattedAmount} als Unternehmen bezahlen` : `Mit Geschäftskonto bezahlen`),
+        payElsewhere: ({formattedAmount}: SettleExpensifyCardParams) => (formattedAmount ? `${formattedAmount} als bezahlt markieren` : `Als bezahlt markieren`),
         settleInvoicePersonal: (amount?: string, last4Digits?: string) => (amount ? `${amount} mit persönlichem Konto ${last4Digits} bezahlt` : `Mit Privatkonto bezahlt`),
         settleInvoiceBusiness: (amount?: string, last4Digits?: string) => (amount ? `${amount} mit Geschäftskonto ${last4Digits} bezahlt` : `Mit Geschäftskonto bezahlt`),
-        payWithPolicy: (policyName: string, formattedAmount?: string) => (formattedAmount ? `Bezahle ${formattedAmount} über ${policyName}` : `Bezahlen über ${policyName}`),
+        payWithPolicy: ({
+            formattedAmount,
+            policyName,
+        }: SettleExpensifyCardParams & {
+            policyName: string;
+        }) => (formattedAmount ? `Bezahle ${formattedAmount} über ${policyName}` : `Bezahlen über ${policyName}`),
         businessBankAccount: (amount?: string, last4Digits?: string) => (amount ? `${amount} mit Bankkonto ${last4Digits} bezahlt` : `bezahlt mit Bankkonto ${last4Digits}`),
         automaticallyPaidWithBusinessBankAccount: (amount?: string, last4Digits?: string) =>
             `${amount ? `${amount} ` : ''} mit Bankkonto ${last4Digits} über <a href="${CONST.CONFIGURE_EXPENSE_REPORT_RULES_HELP_URL}">Workspace-Regeln</a> bezahlt`,
@@ -1346,16 +1287,16 @@ const translations: TranslationDeepObject<typeof en> = {
         nextStep: 'Nächste Schritte',
         finished: 'Fertig',
         flip: 'Flip',
-        sendInvoice: (amount: string) => `${amount}-Rechnung senden`,
+        sendInvoice: ({amount}: RequestAmountParams) => `${amount}-Rechnung senden`,
         expenseAmount: (formattedAmount: string, comment?: string) => `${formattedAmount}${comment ? `für ${comment}` : ''}`,
-        submitted: (memo?: string) => `eingereicht${memo ? `, mit dem Vermerk ${memo}` : ''}`,
+        submitted: ({memo}: SubmittedWithMemoParams) => `eingereicht${memo ? `, mit dem Vermerk ${memo}` : ''}`,
         automaticallySubmitted: `eingereicht über <a href="${CONST.SELECT_WORKFLOWS_HELP_URL}">Einreichungen verzögern</a>`,
         queuedToSubmitViaDEW: 'zur Einreichung über benutzerdefinierten Genehmigungsworkflow eingereiht',
         queuedToApproveViaDEW: 'Zur Genehmigung über benutzerdefinierten Genehmigungsworkflow eingereiht',
         trackedAmount: (formattedAmount: string, comment?: string) => `Verfolgen ${formattedAmount}${comment ? `für ${comment}` : ''}`,
-        splitAmount: (amount: string) => `${amount} aufteilen`,
-        didSplitAmount: (formattedAmount: string, comment?: string) => `aufteilen ${formattedAmount}${comment ? `für ${comment}` : ''}`,
-        yourSplit: (amount: string) => `Dein Anteil ${amount}`,
+        splitAmount: ({amount}: SplitAmountParams) => `${amount} aufteilen`,
+        didSplitAmount: (formattedAmount: string, comment: string) => `aufteilen ${formattedAmount}${comment ? `für ${comment}` : ''}`,
+        yourSplit: ({amount}: UserSplitParams) => `Dein Anteil ${amount}`,
         payerOwesAmount: (amount: number | string, payer: string, comment?: string) => `${payer} schuldet ${amount}${comment ? `für ${comment}` : ''}`,
         payerOwes: (payer: string) => `${payer} schuldet:`,
         payerPaidAmount: (amount: number | string, payer?: string) => `${payer ? `${payer} ` : ''}hat ${amount} bezahlt`,
@@ -1371,72 +1312,33 @@ const translations: TranslationDeepObject<typeof en> = {
         approvedMessage: `genehmigt`,
         unapproved: `nicht genehmigt`,
         automaticallyForwarded: `über Genehmigung durch <a href="${CONST.CONFIGURE_EXPENSE_REPORT_RULES_HELP_URL}">Workspace-Regeln</a>`,
-        forwarded: (memo?: string) => `genehmigt${memo ? `, mit dem Vermerk ${memo}` : ''}`,
-        rejectedThisReport: 'abgelehnt',
-        waitingOnBankAccount: (submitterDisplayName: string) => `hat die Zahlung gestartet, wartet aber darauf, dass ${submitterDisplayName} ein Bankkonto hinzufügt.`,
+        forwarded: `genehmigt`,
+        rejectedThisReport: 'hat diesen Bericht abgelehnt',
+        waitingOnBankAccount: ({submitterDisplayName}: WaitingOnBankAccountParams) => `hat die Zahlung gestartet, wartet aber darauf, dass ${submitterDisplayName} ein Bankkonto hinzufügt.`,
         adminCanceledRequest: 'hat die Zahlung storniert',
         canceledRequest: (amount: string, submitterDisplayName: string) =>
             `${amount} Zahlung storniert, weil ${submitterDisplayName} ihr Expensify Wallet nicht innerhalb von 30 Tagen aktiviert hat`,
-        settledAfterAddedBankAccount: (submitterDisplayName: string, amount: string) =>
+        settledAfterAddedBankAccount: ({submitterDisplayName, amount}: SettledAfterAddedBankAccountParams) =>
             `${submitterDisplayName} hat ein Bankkonto hinzugefügt. Die Zahlung über ${amount} wurde vorgenommen.`,
         paidElsewhere: ({payer, comment}: PaidElsewhereParams = {}) => `${payer ? `${payer} ` : ''}als bezahlt markiert${comment ? `und sagt „${comment}“` : ''}`,
         paidWithExpensify: (payer?: string) => `${payer ? `${payer} ` : ''}mit Wallet bezahlt`,
         automaticallyPaidWithExpensify: (payer?: string) =>
             `${payer ? `${payer} ` : ''}mit Expensify über <a href="${CONST.CONFIGURE_EXPENSE_REPORT_RULES_HELP_URL}">Workspace-Regeln</a> bezahlt`,
-        reimbursedThisReport: 'diesen Bericht erstattet',
-        paidThisBill: 'diese Rechnung bezahlt',
-        reimbursedOnBehalfOf: (actor: string) => `im Namen von ${actor}`,
-        reimbursedFromBankAccount: (debitBankAccount: string) => `vom Bankkonto mit der Endung ${debitBankAccount}`,
-        reimbursedSubmitterAddedBankAccount: (submitter: string) =>
-            `${submitter} hat ein Bankkonto hinzugefügt und den Bericht aus der Warteschleife genommen. Die Erstattung wurde eingeleitet`,
-        reimbursedWithFastACH: ({
-            isCurrentUser,
-            submitterLogin,
-            creditBankAccount,
-            expectedDate,
-        }: {
-            isCurrentUser: boolean;
-            submitterLogin: string;
-            creditBankAccount: string;
-            expectedDate: string;
-        }) =>
-            isCurrentUser
-                ? `. Das Geld ist auf dem Weg zu Ihrem ${creditBankAccount ? `Bankkonto mit der Endung ${creditBankAccount}` : 'Konto'}. Die Erstattung wird voraussichtlich bis zum ${expectedDate} abgeschlossen.`
-                : `. Das Geld ist auf dem Weg zum Bankkonto von ${submitterLogin}${creditBankAccount ? ` mit der Endung ${creditBankAccount}` : ''}. Die Erstattung wird voraussichtlich am ${expectedDate} abgeschlossen.`,
-        reimbursedWithCheck: ' per Scheck.',
-        reimbursedWithStripeConnect: ({
-            isCurrentUser,
-            submitterLogin,
-            creditBankAccount,
-            isCard,
-        }: {
-            isCurrentUser: boolean;
-            submitterLogin: string;
-            creditBankAccount: string;
-            isCard: boolean;
-        }) => {
-            const paymentMethod = isCard ? 'Karte' : 'Bankkonto';
-            return isCurrentUser
-                ? `. Das Geld ist auf dem Weg zu Ihrem ${creditBankAccount ? `Bankkonto mit der Endung ${creditBankAccount}` : 'Konto'} (bezahlt über ${paymentMethod}). Dies kann bis zu 10 Werktage dauern.`
-                : `. Das Geld ist auf dem Weg zum Bankkonto von ${submitterLogin}${creditBankAccount ? ` mit der Endung ${creditBankAccount}` : ''} (bezahlt über ${paymentMethod}). Dies kann bis zu 10 Werktage dauern.`;
-        },
-        reimbursedWithACH: ({creditBankAccount, expectedDate}: {creditBankAccount?: string; expectedDate?: string}) =>
-            ` mit Direkteinzahlung (ACH)${creditBankAccount ? ` auf das Bankkonto mit der Endziffer ${creditBankAccount}.` : '. '}${expectedDate ? `Die Rückerstattung wird voraussichtlich bis zum ${expectedDate} abgeschlossen sein.` : 'Dies dauert in der Regel 4–5 Werktage.'}`,
         noReimbursableExpenses: 'Dieser Bericht enthält einen ungültigen Betrag',
         pendingConversionMessage: 'Die Gesamtsumme wird aktualisiert, sobald du wieder online bist',
         changedTheExpense: 'hat die Ausgabe geändert',
-        setTheRequest: (valueName: string, newValueToDisplay: string) => `den Wert ${valueName} auf ${newValueToDisplay}`,
-        setTheDistanceMerchant: (translatedChangedField: string, newMerchant: string, newAmountToDisplay: string) =>
+        setTheRequest: ({valueName, newValueToDisplay}: SetTheRequestParams) => `den Wert ${valueName} auf ${newValueToDisplay}`,
+        setTheDistanceMerchant: ({translatedChangedField, newMerchant, newAmountToDisplay}: SetTheDistanceMerchantParams) =>
             `lege ${translatedChangedField} auf ${newMerchant} fest, wodurch der Betrag auf ${newAmountToDisplay} gesetzt wurde`,
         removedTheRequest: (valueName: string, oldValueToDisplay: string) => `der/die/das ${valueName} (zuvor ${oldValueToDisplay})`,
-        updatedTheRequest: (valueName: string, newValueToDisplay: string, oldValueToDisplay: string) => `die/den/das ${valueName} auf ${newValueToDisplay} (zuvor ${oldValueToDisplay})`,
-        updatedTheDistanceMerchant: (translatedChangedField: string, newMerchant: string, oldMerchant: string, newAmountToDisplay: string, oldAmountToDisplay: string) =>
+        updatedTheRequest: ({valueName, newValueToDisplay, oldValueToDisplay}: UpdatedTheRequestParams) => `die/den/das ${valueName} auf ${newValueToDisplay} (zuvor ${oldValueToDisplay})`,
+        updatedTheDistanceMerchant: ({translatedChangedField, newMerchant, oldMerchant, newAmountToDisplay, oldAmountToDisplay}: UpdatedTheDistanceMerchantParams) =>
             `hat ${translatedChangedField} in ${newMerchant} geändert (vorher ${oldMerchant}), wodurch der Betrag auf ${newAmountToDisplay} aktualisiert wurde (vorher ${oldAmountToDisplay})`,
         basedOnAI: 'basierend auf bisherigen Aktivitäten',
         basedOnMCC: ({rulesLink}: {rulesLink: string}) => (rulesLink ? `basierend auf den <a href="${rulesLink}">Workspace-Regeln</a>` : 'basierend auf dem Workspace-Regelwerk'),
-        threadExpenseReportName: (formattedAmount: string, comment?: string) => `${formattedAmount} ${comment ? `für ${comment}` : 'Ausgabe'}`,
+        threadExpenseReportName: ({formattedAmount, comment}: ThreadRequestReportNameParams) => `${formattedAmount} ${comment ? `für ${comment}` : 'Ausgabe'}`,
         invoiceReportName: ({linkedReportID}: OriginalMessage<typeof CONST.REPORT.ACTIONS.TYPE.REPORT_PREVIEW>) => `Rechnungsbericht Nr. ${linkedReportID}`,
-        threadPaySomeoneReportName: (formattedAmount: string, comment?: string) => `${formattedAmount} gesendet${comment ? `für ${comment}` : ''}`,
+        threadPaySomeoneReportName: ({formattedAmount, comment}: ThreadSentMoneyReportNameParams) => `${formattedAmount} gesendet${comment ? `für ${comment}` : ''}`,
         movedFromPersonalSpace: ({reportName, workspaceName}: MovedFromPersonalSpaceParams) =>
             `Ausgabe von persönlichem Bereich nach ${workspaceName ?? `Chat mit ${reportName}`} verschoben`,
         movedToPersonalSpace: 'Ausgabe in persönlichen Bereich verschoben',
@@ -1445,14 +1347,10 @@ const translations: TranslationDeepObject<typeof en> = {
             invalidTagLength: 'Der Tagname überschreitet 255 Zeichen. Bitte kürzen Sie ihn oder wählen Sie einen anderen Tag.',
             invalidAmount: 'Bitte gib vor dem Fortfahren einen gültigen Betrag ein',
             invalidDistance: 'Bitte gib eine gültige Entfernung ein, bevor du fortfährst',
-            invalidReadings: 'Bitte geben Sie sowohl Start- als auch Endstand ein, bevor Sie fortfahren',
+            invalidReadings: 'Bitte geben Sie sowohl Start- als auch Endstand ein',
             negativeDistanceNotAllowed: 'Endstand muss größer als Anfangsstand sein',
-            distanceAmountTooLarge: 'Der Gesamtbetrag ist zu hoch. Verringere die Entfernung oder reduziere den Satz.',
-            distanceAmountTooLargeReduceDistance: 'Der Gesamtbetrag ist zu hoch. Verringere die Entfernung.',
-            distanceAmountTooLargeReduceRate: 'Der Gesamtbetrag ist zu hoch. Reduziere den Satz.',
-            odometerReadingTooLarge: (formattedMax: string) => `Kilometerstände dürfen ${formattedMax} nicht überschreiten.`,
             invalidIntegerAmount: 'Bitte gib einen vollen Dollarbetrag ein, bevor du fortfährst',
-            invalidTaxAmount: (amount: string) => `Der maximale Steuerbetrag ist ${amount}`,
+            invalidTaxAmount: ({amount}: RequestAmountParams) => `Der maximale Steuerbetrag ist ${amount}`,
             invalidSplit: 'Die Summe der Aufteilungen muss dem Gesamtbetrag entsprechen',
             invalidSplitParticipants: 'Bitte gib für mindestens zwei Teilnehmende einen Betrag größer als null ein',
             invalidSplitYourself: 'Bitte gib für deine Aufteilung einen von null verschiedenen Betrag ein',
@@ -1466,8 +1364,6 @@ const translations: TranslationDeepObject<typeof en> = {
             receiptFailureMessage:
                 '<rbr>Beim Hochladen deiner Quittung ist ein Fehler aufgetreten. Bitte <a href="download">speichere die Quittung</a> und <a href="retry">versuche es später erneut</a>.</rbr>',
             receiptFailureMessageShort: 'Beim Hochladen Ihres Belegs ist ein Fehler aufgetreten.',
-            receiptUploadFailedMessage: 'Beleg-Upload fehlgeschlagen. Speichere den Beleg oder lösche die Ausgabe und verliere sie.',
-            saveReceipt: 'Beleg speichern',
             genericDeleteFailureMessage: 'Unerwarteter Fehler beim Löschen dieses Belegs. Bitte versuche es später erneut.',
             genericEditFailureMessage: 'Unerwarteter Fehler beim Bearbeiten dieser Ausgabe. Bitte versuche es später noch einmal.',
             genericSmartscanFailureMessage: 'Der Transaktion fehlen Felder',
@@ -1484,14 +1380,11 @@ const translations: TranslationDeepObject<typeof en> = {
             endDateSameAsStartDate: 'Das Enddatum darf nicht mit dem Startdatum übereinstimmen',
             manySplitsProvided: `Die maximale Anzahl zulässiger Aufteilungen beträgt ${CONST.IOU.SPLITS_LIMIT}.`,
             dateRangeExceedsMaxDays: `Der Datumsbereich darf ${CONST.IOU.SPLITS_LIMIT} Tage nicht überschreiten.`,
-            unableToSubmitReport: 'Bericht kann nicht eingereicht werden',
-            allTransactionsPendingDescription: 'Sie können diesen Bericht nicht einreichen, weil alle Transaktionen ausstehen. Es kann einige Tage dauern, bis sie gebucht werden.',
-            stitchOdometerImagesFailed: 'Kilometerzählerbilder konnten nicht zusammengeführt werden. Bitte versuchen Sie es später noch einmal.',
-            failedToSaveOdometerDraft: 'Dein Kilometerzähler-Entwurf konnte nicht gespeichert werden. Bitte versuche es erneut.',
         },
         dismissReceiptError: 'Fehler ausblenden',
         dismissReceiptErrorConfirmation: 'Achtung! Wenn du diesen Fehler schließt, wird deine hochgeladene Quittung vollständig entfernt. Bist du sicher?',
-        waitingOnEnabledWallet: (submitterDisplayName: string) => `hat mit dem Ausgleich begonnen. Die Zahlung ist ausgesetzt, bis ${submitterDisplayName} das Wallet aktiviert.`,
+        waitingOnEnabledWallet: ({submitterDisplayName}: WaitingOnBankAccountParams) =>
+            `hat mit dem Ausgleich begonnen. Die Zahlung ist ausgesetzt, bis ${submitterDisplayName} das Wallet aktiviert.`,
         enableWallet: 'Wallet aktivieren',
         hold: 'Warteschleife',
         unhold: 'Zurückhalten aufheben',
@@ -1503,20 +1396,16 @@ const translations: TranslationDeepObject<typeof en> = {
         heldExpense: 'hat diese Ausgabe zurückgehalten',
         unheldExpense: 'Zurückgehaltene Ausgabe freigegeben',
         moveUnreportedExpense: 'Nicht gemeldete Ausgabe verschieben',
-        addExistingExpense: 'Vorhandene Ausgabe hinzufügen',
-        selectExistingExpense: 'Wähle mindestens eine Ausgabe aus, um sie dem Bericht hinzuzufügen.',
-        emptyStateExistingExpenseTitle: 'Keine vorhandenen Ausgaben',
-        emptyStateExistingExpenseSubtitle: 'Es scheint, dass du keine vorhandenen Ausgaben hast. Erstelle unten eine neue.',
-        addExistingExpenseConfirm: 'Zu Bericht hinzufügen',
+        addUnreportedExpense: 'Nicht gemeldete Ausgabe hinzufügen',
+        selectUnreportedExpense: 'Wähle mindestens eine Ausgabe aus, um sie dem Bericht hinzuzufügen.',
+        emptyStateUnreportedExpenseTitle: 'Keine nicht gemeldeten Ausgaben',
+        emptyStateUnreportedExpenseSubtitle: 'Sie scheinen keine nicht eingereichten Ausgaben zu haben. Erstellen Sie unten eine.',
+        addUnreportedExpenseConfirm: 'Zu Bericht hinzufügen',
         newReport: 'Neuer Bericht',
         explainHold: () => ({
             one: 'Erkläre, warum du diese Ausgabe zurückhältst.',
             other: 'Erklären Sie, warum Sie diese Ausgaben zurückhalten.',
         }),
-        explainHoldApprover: () => ({
-            one: 'Erkläre, was du vor der Genehmigung dieser Ausgabe benötigst.',
-            other: 'Erkläre, was du vor der Genehmigung dieser Ausgaben benötigst.',
-        }),
         retracted: 'zurückgezogen',
         retract: 'Zurückziehen',
         reopened: 'wiedereröffnet',
@@ -1532,9 +1421,6 @@ const translations: TranslationDeepObject<typeof en> = {
         someDuplicatesArePaid: 'Einige dieser Duplikate wurden bereits genehmigt oder bezahlt.',
         reviewDuplicates: 'Duplikate prüfen',
         keepAll: 'Alle behalten',
-        keepSelected: 'Auswahl behalten',
-        noDuplicatesTitle: 'Alles erledigt!',
-        noDuplicatesDescription: 'Es gibt hier keine doppelten Transaktionen zur Überprüfung.',
         confirmApprove: 'Genehmigungsbetrag bestätigen',
         confirmApprovalAmount: 'Nur regelkonforme Ausgaben genehmigen oder den gesamten Bericht genehmigen.',
         confirmApprovalAllHoldAmount: () => ({
@@ -1568,7 +1454,7 @@ const translations: TranslationDeepObject<typeof en> = {
         unapprove: 'Genehmigung aufheben',
         unapproveReport: 'Bericht ablehnen',
         headsUp: 'Achtung!',
-        unapproveWithIntegrationWarning: (accountingIntegration: string) =>
+        unapproveWithIntegrationWarning: ({accountingIntegration}: UnapproveWithIntegrationWarningParams) =>
             `Dieser Bericht wurde bereits nach ${accountingIntegration} exportiert. Änderungen können zu Datenabweichungen führen. Möchtest du die Freigabe dieses Berichts wirklich aufheben?`,
         reimbursable: 'erstattungsfähig',
         nonReimbursable: 'nicht erstattungsfähig',
@@ -1577,7 +1463,6 @@ const translations: TranslationDeepObject<typeof en> = {
         bookingArchived: 'Diese Buchung ist archiviert',
         bookingArchivedDescription: 'Diese Buchung ist archiviert, weil das Reisedatum verstrichen ist. Füge bei Bedarf eine Ausgabe für den endgültigen Betrag hinzu.',
         attendees: 'Teilnehmende',
-        totalPerAttendee: 'Pro Teilnehmendem',
         whoIsYourAccountant: 'Wer ist Ihre Steuerberaterin bzw. Ihr Steuerberater?',
         paymentComplete: 'Zahlung abgeschlossen',
         time: 'Zeit',
@@ -1604,7 +1489,7 @@ const translations: TranslationDeepObject<typeof en> = {
         }),
         dates: 'Daten',
         rates: 'Sätze',
-        submitsTo: (name: string) => `Reicht bei ${name} ein`,
+        submitsTo: ({name}: SubmitsToParams) => `Reicht bei ${name} ein`,
         reject: {
             educationalTitle: 'Solltest du zurückhalten oder ablehnen?',
             educationalText: 'Wenn du noch nicht bereit bist, eine Ausgabe zu genehmigen oder zu bezahlen, kannst du sie zurückstellen oder ablehnen.',
@@ -1613,7 +1498,7 @@ const translations: TranslationDeepObject<typeof en> = {
             heldExpenseLeftBehindTitle: 'Zurückgehaltene Ausgaben werden ausgelassen, wenn du einen gesamten Bericht genehmigst.',
             rejectExpenseTitle: 'Lehne eine Ausgabe ab, die du nicht genehmigen oder bezahlen möchtest.',
             reasonPageTitle: 'Ausgabe ablehnen',
-            reasonPageDescription: 'Erkläre, warum du diese Ausgabe nicht genehmigen wirst.',
+            reasonPageDescription: 'Erkläre, warum du diese Ausgabe ablehnst.',
             rejectReason: 'Ablehnungsgrund',
             markAsResolved: 'Als gelöst markieren',
             rejectedStatus: 'Diese Ausgabe wurde abgelehnt. Wir warten darauf, dass du die Probleme behebst und als gelöst markierst, um das Einreichen zu ermöglichen.',
@@ -1622,26 +1507,13 @@ const translations: TranslationDeepObject<typeof en> = {
                 markedAsResolved: 'hat den Ablehnungsgrund als gelöst markiert',
             },
         },
-        rejectReport: {
-            title: 'Bericht ablehnen',
-            description: 'Erläutern Sie, warum Sie diesen Bericht nicht genehmigen werden:',
-            rejectReason: 'Ablehnungsgrund',
-            selectTarget: 'Wählen Sie das Mitglied aus, an das dieser Bericht zur Überprüfung zurückgewiesen werden soll:',
-            lastApprover: 'Letzte*r Genehmigende*r',
-            submitter: 'Einreicher',
-            rejectedReportMessage: 'Dieser Bericht wurde abgelehnt.',
-            rejectedNextStep: 'Dieser Bericht wurde abgelehnt. Wir warten darauf, dass Sie die Probleme beheben und ihn manuell erneut einreichen.',
-            selectMemberError: 'Wählen Sie ein Mitglied aus, an das dieser Bericht zurückgewiesen werden soll.',
-            couldNotReject: 'Der Bericht konnte nicht abgelehnt werden. Bitte versuchen Sie es erneut.',
-        },
-        moveExpenses: 'Zum Bericht verschieben',
+        moveExpenses: () => ({one: 'Ausgabe verschieben', other: 'Ausgaben verschieben'}),
         moveExpensesError: 'Sie können Pauschalspesen nicht in Berichte anderer Arbeitsbereiche verschieben, da die Pauschalsätze je nach Arbeitsbereich unterschiedlich sein können.',
         changeApprover: {
             title: 'Genehmigende Person ändern',
-            header: (workflowSettingLink: string) =>
+            header: ({workflowSettingLink}: WorkflowSettingsParam) =>
                 `Wähle eine Option, um die approvierende Person für diesen Bericht zu ändern. (Aktualisiere deine <a href="${workflowSettingLink}">Workspace-Einstellungen</a>, um dies dauerhaft für alle Berichte zu ändern.)`,
             changedApproverMessage: (managerID: number) => `Genehmigenden in <mention-user accountID="${managerID}"/> geändert`,
-            reassignedApproverMessage: (managerID: number) => `hat den Genehmigenden über eine Workflow-Aktualisierung neu zu <mention-user accountID="${managerID}"/> zugewiesen`,
             actions: {
                 addApprover: 'Genehmiger hinzufügen',
                 addApproverSubtitle: 'Füge dem bestehenden Workflow eine weitere genehmigende Person hinzu.',
@@ -1650,12 +1522,10 @@ const translations: TranslationDeepObject<typeof en> = {
             },
             addApprover: {
                 subtitle: 'Wählen Sie eine zusätzliche genehmigende Person für diesen Bericht, bevor wir ihn durch den restlichen Genehmigungsworkflow leiten.',
-                bulkSubtitle: 'Wähle eine zusätzliche genehmigende Person für diese Berichte aus, bevor wir sie durch den restlichen Genehmigungs-Workflow leiten.',
             },
-            bulkSubtitle: 'Wählen Sie eine Option, um den Genehmiger für diese Berichte zu ändern.',
         },
         chooseWorkspace: 'Wähle einen Arbeitsbereich',
-        routedDueToDEW: (to: string, reason?: string) => `Bericht weitergeleitet an ${to}${reason ? ` weil ${reason}` : ''}`,
+        routedDueToDEW: ({to}: RoutedDueToDEWParams) => `Report aufgrund des benutzerdefinierten Genehmigungsworkflows an ${to} weitergeleitet`,
         timeTracking: {
             hoursAt: (hours: number, rate: string) => `${hours} ${hours === 1 ? 'Stunde' : 'Stunden'} @ ${rate} / Stunde`,
             hrs: 'Std.',
@@ -1663,35 +1533,34 @@ const translations: TranslationDeepObject<typeof en> = {
             ratePreview: (rate: string) => `${rate} / Stunde`,
             amountTooLargeError: 'Der Gesamtbetrag ist zu hoch. Verringere die Stunden oder reduziere den Satz.',
         },
-        correctRateError: 'Beheben Sie den Kursfehler und versuchen Sie es erneut.',
-        AskToExplain: `. <a href="${CONST.CONCIERGE_EXPLAIN_LINK_PATH}">Erklären<sparkles-icon/></a>`,
-        duplicateNonDefaultWorkspacePerDiemError:
-            'Sie können Per-Diem-Ausgaben nicht über mehrere Workspaces hinweg duplizieren, da sich die Sätze zwischen den Workspaces unterscheiden können.',
-        rulesModifiedFields: {
-            reimbursable: (value: boolean) => (value ? 'hat die Ausgabe als „erstattungsfähig“ markiert' : 'hat die Ausgabe als „nicht erstattungsfähig“ markiert'),
-            billable: (value: boolean) => (value ? 'hat die Ausgabe als „verrechenbar“ markiert' : 'hat die Ausgabe als „nicht abrechenbar“ markiert'),
-            tax: (value: string, isFirst: boolean) => (isFirst ? `Steuersatz auf „${value}“ festlegen` : `Steuersatz auf „${value}“`),
-            reportName: (value: string) => `hat diese Ausgabe in den Bericht „${value}“ verschoben`,
-            common: (key: keyof PolicyRulesModifiedFields | keyof PersonalRulesModifiedFields, value: string, isFirst: boolean) => {
-                const field = translations.common[key].toLowerCase();
-                return isFirst ? `setze ${field} auf „${value}“` : `${field} zu „${value}“`;
-            },
-            formatPersonalRules: (fragments: string, route: string) => `${fragments} über <a href="${route}">Regeln für persönliche Ausgaben</a>`,
-            formatPolicyRules: (fragments: string, route: string) => `${fragments} über <a href="${route}">Workspace-Regeln</a>`,
-        },
-        failedToAutoSubmitViaDEW: (reason: string) => `Senden des Berichts über <a href="${CONST.SELECT_WORKFLOWS_HELP_URL}">Übermittlungen verzögern</a> fehlgeschlagen. ${reason}`,
-        failedToSubmitViaDEW: (reason: string) => `Der Bericht konnte nicht übermittelt werden. ${reason}`,
-        failedToAutoApproveViaDEW: (reason: string) => `Genehmigung über <a href="${CONST.CONFIGURE_EXPENSE_REPORT_RULES_HELP_URL}">Workspace-Regeln</a> fehlgeschlagen. ${reason}`,
-        failedToApproveViaDEW: (reason: string) => `Genehmigung fehlgeschlagen. ${reason}`,
-        cannotDuplicateDistanceExpense:
-            'Sie können Entfernungsausgaben nicht über mehrere Arbeitsbereiche hinweg duplizieren, da sich die Sätze zwischen den Arbeitsbereichen unterscheiden können.',
-        taxDisabledAlert: {
-            title: 'Steuer deaktiviert',
-            prompt: 'Aktivieren Sie die Steuerverfolgung im Workspace, um die Ausgabendetails zu bearbeiten oder die Steuer aus dieser Ausgabe zu löschen.',
-            confirmText: 'Steuer löschen',
-        },
-        bulkDuplicateLimit: `Sie können bis zu ${CONST.SEARCH.BULK_DUPLICATE_LIMIT} Ausgaben gleichzeitig duplizieren. Bitte wählen Sie weniger Ausgaben aus und versuchen Sie es erneut.`,
-        deleted: 'Gelöscht',
+        correctDistanceRateError: 'Behebe den Fehler beim Entfernungssatz und versuche es erneut.',
+        AskToExplain: `. <a href="${CONST.CONCIERGE_EXPLAIN_LINK_PATH}"><strong>Erklären</strong></a> &#x2728;`,
+        policyRulesModifiedFields: (policyRulesModifiedFields: PolicyRulesModifiedFields, policyRulesRoute: string, formatList: (list: string[]) => string) => {
+            const entries = ObjectUtils.typedEntries(policyRulesModifiedFields);
+            const fragments = entries.map(([key, value], i) => {
+                const isFirst = i === 0;
+                if (key === 'reimbursable') {
+                    return value ? 'hat die Ausgabe als „erstattungsfähig“ markiert' : 'hat die Ausgabe als „nicht erstattungsfähig“ markiert';
+                }
+                if (key === 'billable') {
+                    return value ? 'hat die Ausgabe als „verrechenbar“ markiert' : 'hat die Ausgabe als „nicht abrechenbar“ markiert';
+                }
+                if (key === 'tax') {
+                    const taxEntry = value as PolicyRulesModifiedFields['tax'];
+                    const taxRateName = taxEntry?.field_id_TAX.name ?? '';
+                    if (isFirst) {
+                        return `Steuersatz auf „${taxRateName}“ festlegen`;
+                    }
+                    return `Steuersatz auf „${taxRateName}“`;
+                }
+                const updatedValue = value as string | boolean;
+                if (isFirst) {
+                    return `setze ${translations.common[key].toLowerCase()} auf „${updatedValue}“`;
+                }
+                return `${translations.common[key].toLowerCase()} zu „${updatedValue}“`;
+            });
+            return `${formatList(fragments)} über <a href="${policyRulesRoute}">Workspace-Regeln</a>`;
+        },
     },
     transactionMerge: {
         listPage: {
@@ -1764,185 +1633,110 @@ const translations: TranslationDeepObject<typeof en> = {
     },
     nextStep: {
         message: {
-            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_TO_ADD_TRANSACTIONS]: (
-                actor: string,
-                actorType: ValueOf<typeof CONST.NEXT_STEP.ACTOR_TYPE>,
-                _eta?: string,
-                _etaType?: ValueOf<typeof CONST.NEXT_STEP.ETA_TYPE>,
-            ) => {
+            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_TO_ADD_TRANSACTIONS]: ({actor, actorType}: NextStepParams) => {
                 switch (actorType) {
                     case CONST.NEXT_STEP.ACTOR_TYPE.CURRENT_USER:
-                        return `Warte darauf, dass <strong>Sie</strong> Spesen hinzufügen.`;
+                        return `Warte darauf, dass <strong>du</strong> Auslagen hinzufügst.`;
                     case CONST.NEXT_STEP.ACTOR_TYPE.OTHER_USER:
-                        return `Warten darauf, dass <strong>${actor}</strong> Ausgaben hinzufügt.`;
+                        return `Warten auf <strong>${actor}</strong>, um Ausgaben hinzuzufügen.`;
                     case CONST.NEXT_STEP.ACTOR_TYPE.UNSPECIFIED_ADMIN:
-                        return `Warten auf eine:n Admin, der Ausgaben hinzufügt.`;
+                        return `Warte darauf, dass ein Admin Ausgaben hinzufügt.`;
                 }
             },
-            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_TO_SUBMIT]: (
-                actor: string,
-                actorType: ValueOf<typeof CONST.NEXT_STEP.ACTOR_TYPE>,
-                _eta?: string,
-                _etaType?: ValueOf<typeof CONST.NEXT_STEP.ETA_TYPE>,
-            ) => {
+            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_TO_SUBMIT]: ({actor, actorType}: NextStepParams) => {
                 switch (actorType) {
                     case CONST.NEXT_STEP.ACTOR_TYPE.CURRENT_USER:
-                        return `Wartet darauf, dass <strong>Sie</strong> Spesen einreichen.`;
+                        return `Warte darauf, dass <strong>du</strong> Ausgaben einreichst.`;
                     case CONST.NEXT_STEP.ACTOR_TYPE.OTHER_USER:
-                        return `Warten darauf, dass <strong>${actor}</strong> Ausgaben einreicht.`;
+                        return `Warten auf <strong>${actor}</strong>, um Spesen einzureichen.`;
                     case CONST.NEXT_STEP.ACTOR_TYPE.UNSPECIFIED_ADMIN:
-                        return `Warten darauf, dass ein Admin Spesen einreicht.`;
+                        return `Warten darauf, dass eine Verwaltungsperson Spesen einreicht.`;
                 }
             },
-            [CONST.NEXT_STEP.MESSAGE_KEY.NO_FURTHER_ACTION]: (
-                _actor: string,
-                _actorType: ValueOf<typeof CONST.NEXT_STEP.ACTOR_TYPE>,
-                _eta?: string,
-                _etaType?: ValueOf<typeof CONST.NEXT_STEP.ETA_TYPE>,
-            ) => `Kein weiterer Handlungsbedarf!`,
-            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_FOR_SUBMITTER_ACCOUNT]: (
-                actor: string,
-                actorType: ValueOf<typeof CONST.NEXT_STEP.ACTOR_TYPE>,
-                _eta?: string,
-                _etaType?: ValueOf<typeof CONST.NEXT_STEP.ETA_TYPE>,
-            ) => {
+            [CONST.NEXT_STEP.MESSAGE_KEY.NO_FURTHER_ACTION]: (_: NextStepParams) => `Keine weiteren Maßnahmen erforderlich!`,
+            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_FOR_SUBMITTER_ACCOUNT]: ({actor, actorType}: NextStepParams) => {
                 switch (actorType) {
                     case CONST.NEXT_STEP.ACTOR_TYPE.CURRENT_USER:
-                        return `Warten darauf, dass <strong>Sie</strong> ein Bankkonto hinzufügen.`;
+                        return `Warte darauf, dass <strong>du</strong> ein Bankkonto hinzufügst.`;
                     case CONST.NEXT_STEP.ACTOR_TYPE.OTHER_USER:
                         return `Warten darauf, dass <strong>${actor}</strong> ein Bankkonto hinzufügt.`;
                     case CONST.NEXT_STEP.ACTOR_TYPE.UNSPECIFIED_ADMIN:
-                        return `Warten Sie darauf, dass ein Admin ein Bankkonto hinzufügt.`;
+                        return `Warten auf eine:n Admin, um ein Bankkonto hinzuzufügen.`;
                 }
             },
-            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_FOR_AUTOMATIC_SUBMIT]: (
-                actor: string,
-                actorType: ValueOf<typeof CONST.NEXT_STEP.ACTOR_TYPE>,
-                eta?: string,
-                etaType?: ValueOf<typeof CONST.NEXT_STEP.ETA_TYPE>,
-            ) => {
+            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_FOR_AUTOMATIC_SUBMIT]: ({actor, actorType, eta, etaType}: NextStepParams) => {
                 let formattedETA = '';
                 if (eta) {
-                    formattedETA = etaType === CONST.NEXT_STEP.ETA_TYPE.DATE_TIME ? `am ${eta} eines jeden Monats` : ` ${eta}`;
+                    formattedETA = etaType === CONST.NEXT_STEP.ETA_TYPE.DATE_TIME ? `am ${eta}` : ` ${eta}`;
                 }
                 switch (actorType) {
                     case CONST.NEXT_STEP.ACTOR_TYPE.CURRENT_USER:
-                        return `Warten darauf, dass <strong>Ihre</strong> Ausgaben automatisch eingereicht werden${formattedETA}.`;
+                        return `Es wird darauf gewartet, dass <strong>deine</strong> Ausgaben automatisch eingereicht werden${formattedETA}.`;
                     case CONST.NEXT_STEP.ACTOR_TYPE.OTHER_USER:
-                        return `Es wird darauf gewartet, dass die Ausgaben von <strong>${actor}</strong> automatisch eingereicht werden${formattedETA}.`;
+                        return `Warte darauf, dass sich die Spesen von <strong>${actor}</strong> automatisch einreichen${formattedETA}.`;
                     case CONST.NEXT_STEP.ACTOR_TYPE.UNSPECIFIED_ADMIN:
-                        return `Es wird darauf gewartet, dass die Ausgaben eines Admins automatisch eingereicht werden${formattedETA}.`;
+                        return `Warten darauf, dass die Ausgaben eines Admins automatisch eingereicht werden${formattedETA}.`;
                 }
             },
-            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_TO_FIX_ISSUES]: (
-                actor: string,
-                actorType: ValueOf<typeof CONST.NEXT_STEP.ACTOR_TYPE>,
-                _eta?: string,
-                _etaType?: ValueOf<typeof CONST.NEXT_STEP.ETA_TYPE>,
-            ) => {
+            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_TO_FIX_ISSUES]: ({actor, actorType}: NextStepParams) => {
                 switch (actorType) {
                     case CONST.NEXT_STEP.ACTOR_TYPE.CURRENT_USER:
-                        return `Warten auf <strong>Sie</strong>, um die Probleme zu beheben.`;
+                        return `Warten auf <strong>dich</strong>, um die Probleme zu beheben.`;
                     case CONST.NEXT_STEP.ACTOR_TYPE.OTHER_USER:
-                        return `Warten darauf, dass <strong>${actor}</strong> die Probleme behebt.`;
+                        return `Warten auf <strong>${actor}</strong>, um die Probleme zu beheben.`;
                     case CONST.NEXT_STEP.ACTOR_TYPE.UNSPECIFIED_ADMIN:
                         return `Warten auf eine*n Admin, um die Probleme zu beheben.`;
                 }
             },
-            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_TO_APPROVE]: (
-                actor: string,
-                actorType: ValueOf<typeof CONST.NEXT_STEP.ACTOR_TYPE>,
-                _eta?: string,
-                _etaType?: ValueOf<typeof CONST.NEXT_STEP.ETA_TYPE>,
-            ) => {
+            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_TO_APPROVE]: ({actor, actorType}: NextStepParams) => {
                 switch (actorType) {
                     case CONST.NEXT_STEP.ACTOR_TYPE.CURRENT_USER:
-                        return `Es wird darauf gewartet, dass <strong>Sie</strong> Spesen genehmigen.`;
+                        return `Warte darauf, dass <strong>du</strong> Spesen freigibst.`;
                     case CONST.NEXT_STEP.ACTOR_TYPE.OTHER_USER:
                         return `Warten auf die Genehmigung der Ausgaben durch <strong>${actor}</strong>.`;
                     case CONST.NEXT_STEP.ACTOR_TYPE.UNSPECIFIED_ADMIN:
-                        return `Warten auf Genehmigung der Ausgaben durch eine Adminperson.`;
+                        return `Warten auf die Genehmigung der Ausgaben durch eine*n Admin.`;
                 }
             },
-            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_TO_EXPORT]: (
-                actor: string,
-                actorType: ValueOf<typeof CONST.NEXT_STEP.ACTOR_TYPE>,
-                _eta?: string,
-                _etaType?: ValueOf<typeof CONST.NEXT_STEP.ETA_TYPE>,
-            ) => {
+            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_TO_EXPORT]: ({actor, actorType}: NextStepParams) => {
                 switch (actorType) {
                     case CONST.NEXT_STEP.ACTOR_TYPE.CURRENT_USER:
-                        return `Warte darauf, dass <strong>Sie</strong> diesen Bericht exportieren.`;
+                        return `Warte darauf, dass <strong>du</strong> diesen Bericht exportierst.`;
                     case CONST.NEXT_STEP.ACTOR_TYPE.OTHER_USER:
-                        return `Warten darauf, dass <strong>${actor}</strong> diesen Bericht exportiert.`;
+                        return `Warten auf <strong>${actor}</strong>, um diesen Bericht zu exportieren.`;
                     case CONST.NEXT_STEP.ACTOR_TYPE.UNSPECIFIED_ADMIN:
-                        return `Warten auf eine Administratorin oder einen Administrator, um diesen Bericht zu exportieren.`;
+                        return `Es wird darauf gewartet, dass ein Admin diesen Bericht exportiert.`;
                 }
             },
-            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_TO_PAY]: (
-                actor: string,
-                actorType: ValueOf<typeof CONST.NEXT_STEP.ACTOR_TYPE>,
-                _eta?: string,
-                _etaType?: ValueOf<typeof CONST.NEXT_STEP.ETA_TYPE>,
-            ) => {
+            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_TO_PAY]: ({actor, actorType}: NextStepParams) => {
                 switch (actorType) {
                     case CONST.NEXT_STEP.ACTOR_TYPE.CURRENT_USER:
-                        return `Wartet darauf, dass <strong>Sie</strong> Spesen bezahlen.`;
+                        return `Wartet auf <strong>dich</strong>, um Spesen zu bezahlen.`;
                     case CONST.NEXT_STEP.ACTOR_TYPE.OTHER_USER:
-                        return `Warten auf <strong>${actor}</strong>, um Auslagen zu bezahlen.`;
+                        return `Warten auf die Zahlung der Spesen durch <strong>${actor}</strong>.`;
                     case CONST.NEXT_STEP.ACTOR_TYPE.UNSPECIFIED_ADMIN:
-                        return `Warten darauf, dass eine Adminperson Spesen bezahlt.`;
+                        return `Warte darauf, dass ein Admin Spesen bezahlt.`;
                 }
             },
-            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_FOR_POLICY_BANK_ACCOUNT]: (
-                actor: string,
-                actorType: ValueOf<typeof CONST.NEXT_STEP.ACTOR_TYPE>,
-                _eta?: string,
-                _etaType?: ValueOf<typeof CONST.NEXT_STEP.ETA_TYPE>,
-            ) => {
+            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_FOR_POLICY_BANK_ACCOUNT]: ({actor, actorType}: NextStepParams) => {
                 switch (actorType) {
                     case CONST.NEXT_STEP.ACTOR_TYPE.CURRENT_USER:
-                        return `Warten darauf, dass <strong>Sie</strong> die Einrichtung eines Geschäftskontos abschließen.`;
+                        return `Warten darauf, dass <strong>du</strong> das Einrichten eines Geschäftskontos abschließt.`;
                     case CONST.NEXT_STEP.ACTOR_TYPE.OTHER_USER:
-                        return `Warten darauf, dass <strong>${actor}</strong> die Einrichtung eines Geschäftskontos abschließt.`;
+                        return `Warte darauf, dass <strong>${actor}</strong> die Einrichtung eines Geschäftskontos abschließt.`;
                     case CONST.NEXT_STEP.ACTOR_TYPE.UNSPECIFIED_ADMIN:
-                        return `Warten auf eine Administration, um das Einrichten eines geschäftlichen Bankkontos abzuschließen.`;
+                        return `Warten, bis ein Admin das Geschäftskonto eingerichtet hat.`;
                 }
             },
-            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_FOR_PAYMENT]: (
-                _actor: string,
-                _actorType: ValueOf<typeof CONST.NEXT_STEP.ACTOR_TYPE>,
-                eta?: string,
-                etaType?: ValueOf<typeof CONST.NEXT_STEP.ETA_TYPE>,
-            ) => {
+            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_FOR_PAYMENT]: ({eta, etaType}: NextStepParams) => {
                 let formattedETA = '';
                 if (eta) {
                     formattedETA = etaType === CONST.NEXT_STEP.ETA_TYPE.DATE_TIME ? `bis ${eta}` : ` ${eta}`;
                 }
-                return `Warten, bis die Zahlung abgeschlossen ist${formattedETA}.`;
-            },
-            [CONST.NEXT_STEP.MESSAGE_KEY.SUBMITTING_TO_SELF]: (
-                _actor: string,
-                _actorType: ValueOf<typeof CONST.NEXT_STEP.ACTOR_TYPE>,
-                _eta?: string,
-                _etaType?: ValueOf<typeof CONST.NEXT_STEP.ETA_TYPE>,
-            ) =>
-                `Ups! Sie scheinen diesen Bericht bei <strong>sich selbst</strong> einzureichen. Die Genehmigung eigener Berichte ist in Ihrem Workspace <strong>verboten</strong>. Bitte reichen Sie diesen Bericht bei jemand anderem ein oder kontaktieren Sie Ihre Admin, um die Person zu ändern, an die Sie Berichte einreichen.`,
-            [CONST.NEXT_STEP.MESSAGE_KEY.REJECTED_REPORT]: (
-                actor: string,
-                actorType: ValueOf<typeof CONST.NEXT_STEP.ACTOR_TYPE>,
-                _eta?: string,
-                _etaType?: ValueOf<typeof CONST.NEXT_STEP.ETA_TYPE>,
-            ) => {
-                switch (actorType) {
-                    case CONST.NEXT_STEP.ACTOR_TYPE.CURRENT_USER:
-                        return `Dieser Bericht wurde abgelehnt. Es wird darauf gewartet, dass <strong>Sie</strong> die Probleme beheben und ihn manuell erneut einreichen.`;
-                    case CONST.NEXT_STEP.ACTOR_TYPE.OTHER_USER:
-                        return `Dieser Bericht wurde abgelehnt. Es wird darauf gewartet, dass <strong>${actor}</strong> die Probleme behebt und den Bericht manuell erneut einreicht.`;
-                    case CONST.NEXT_STEP.ACTOR_TYPE.UNSPECIFIED_ADMIN:
-                        return `Dieser Bericht wurde abgelehnt. Es wird darauf gewartet, dass ein Admin die Probleme behebt und ihn manuell erneut einreicht.`;
-                }
+                return `Warten auf Abschluss der Zahlung${formattedETA}.`;
             },
+            [CONST.NEXT_STEP.MESSAGE_KEY.SUBMITTING_TO_SELF]: (_: NextStepParams) =>
+                `Ups! Es sieht so aus, als würdest du diesen Bericht bei <strong>dir selbst</strong> einreichen. Das Genehmigen eigener Berichte ist in deinem Workspace <strong>verboten</strong>. Bitte reiche diesen Bericht bei jemand anderem ein oder kontaktiere deine Adminperson, um die Person zu ändern, an die du Berichte einreichst.`,
         },
         eta: {
             [CONST.NEXT_STEP.ETA_KEY.SHORTLY]: 'in Kürze',
@@ -1968,8 +1762,6 @@ const translations: TranslationDeepObject<typeof en> = {
         offline: 'Offline',
         syncing: 'Synchronisierung',
         profileAvatar: 'Profil-Avatar',
-        customInstructions: 'Benutzerdefinierte Anweisungen',
-        copilotIntoAccount: 'Copilot in Konto',
         publicSection: {
             title: 'Öffentlich',
             subtitle: 'Diese Angaben werden in deinem öffentlichen Profil angezeigt. Jede:r kann sie sehen.',
@@ -1978,16 +1770,12 @@ const translations: TranslationDeepObject<typeof en> = {
             title: 'Privat',
             subtitle: 'Diese Angaben werden für Reisen und Zahlungen verwendet. Sie werden niemals in deinem öffentlichen Profil angezeigt.',
         },
-        aiPromptSection: {
-            title: 'KI-Aufforderung',
-            subtitle: 'Eigene Anweisungen schreiben',
-            prompt: 'Aufforderung',
-            editPrompt: 'Eingabeaufforderung bearbeiten',
-            promptCannotBeEmpty: 'Eingabe darf nicht leer sein',
-            saved: 'Gespeichert',
-        },
     },
-    securityPage: {title: 'Sicherheit', subtitle: 'Schützen Sie Ihr Konto.', goToSecurity: 'Zur Sicherheitsseite zurückkehren'},
+    securityPage: {
+        title: 'Sicherheitsoptionen',
+        subtitle: 'Aktiviere die Zwei-Faktor-Authentifizierung, um dein Konto zu schützen.',
+        goToSecurity: 'Zur Sicherheitsseite zurückkehren',
+    },
     shareCodePage: {
         title: 'Ihr Code',
         subtitle: 'Lade Mitglieder zu Expensify ein, indem du deinen persönlichen QR-Code oder Empfehlungslink teilst.',
@@ -2025,7 +1813,6 @@ const translations: TranslationDeepObject<typeof en> = {
         },
         newContactMethod: 'Neue Kontaktmethode',
         goBackContactMethods: 'Zurück zu den Kontaktmethoden',
-        yourDefaultContactMethodRestrictedSwitch: 'Dies ist Ihre derzeitige standardmäßige Kontaktmethode. Ihr Unternehmen hat das Entfernen oder Ändern eingeschränkt.',
     },
     pronouns: {
         coCos: 'Co / Cos',
@@ -2085,6 +1872,8 @@ const translations: TranslationDeepObject<typeof en> = {
         },
         troubleshoot: {
             clearCacheAndRestart: 'Cache leeren und neu starten',
+            viewConsole: 'Debugkonsole anzeigen',
+            debugConsole: 'Debug-Konsole',
             description:
                 '<muted-text>Verwende die folgenden Tools, um Probleme mit Expensify zu beheben. Wenn du auf Probleme stößt, <concierge-link>melde bitte einen Fehler</concierge-link>.</muted-text>',
             confirmResetDescription: 'Alle nicht gesendeten Entwurfsnachrichten gehen verloren, aber alle anderen Daten sind sicher.',
@@ -2116,47 +1905,36 @@ const translations: TranslationDeepObject<typeof en> = {
             invalidateWithDelay: 'Mit Verzögerung ungültig machen',
             leftHandNavCache: 'Cache der linken Navigation',
             clearleftHandNavCache: 'Löschen',
+            recordTroubleshootData: 'Fehlerdiagnosedaten aufzeichnen',
             softKillTheApp: 'App sanft beenden',
             kill: 'Töten',
             sentryDebug: 'Sentry-Debug',
-            sentrySendDescription: 'Daten an Sentry senden',
             sentryDebugDescription: 'Sentry-Anfragen in der Konsole protokollieren',
             sentryHighlightedSpanOps: 'Hervorgehobene Spannen-Namen',
             sentryHighlightedSpanOpsPlaceholder: 'ui.interaktion.klick, navigation, ui.laden',
-            showBranchNameInTitle: 'Branch-Namen im Browser-Titel anzeigen',
+        },
+        debugConsole: {
+            saveLog: 'Protokoll speichern',
+            shareLog: 'Protokoll teilen',
+            enterCommand: 'Befehl eingeben',
+            execute: 'Ausführen',
+            noLogsAvailable: 'Keine Protokolle verfügbar',
+            logSizeTooLarge: (size: number) =>
+                `Protokollgröße überschreitet das Limit von ${size} MB. Bitte verwende „Protokoll speichern“, um die Protokolldatei stattdessen herunterzuladen.`,
+            logs: 'Protokolle',
+            viewConsole: 'Konsole anzeigen',
         },
         security: 'Sicherheit',
         signOut: 'Abmelden',
         restoreStashed: 'Gespeicherten Login wiederherstellen',
         signOutConfirmationText: 'Alle Offline-Änderungen gehen verloren, wenn du dich abmeldest.',
         versionLetter: 'v',
-        readTheTermsAndPrivacy: `Lesen Sie die <a href="${CONST.OLD_DOT_PUBLIC_URLS.TERMS_URL}">Nutzungsbedingungen</a> und die <a href="${CONST.OLD_DOT_PUBLIC_URLS.PRIVACY_URL}">Datenschutzerklärung</a>.`,
+        readTheTermsAndPrivacy: `<muted-text-micro>Lies die <a href="${CONST.OLD_DOT_PUBLIC_URLS.TERMS_URL}">Nutzungsbedingungen</a> und die <a href="${CONST.OLD_DOT_PUBLIC_URLS.PRIVACY_URL}">Datenschutzerklärung</a>.</muted-text-micro>`,
         help: 'Hilfe',
         whatIsNew: 'Was ist neu',
         accountSettings: 'Kontoeinstellungen',
         account: 'Konto',
         general: 'Allgemein',
-        helpPage: {
-            title: 'Hilfe und Support',
-            description: 'Wir sind rund um die Uhr für Sie da.',
-            helpSite: 'Hilfeseite',
-            helpSiteDescription: 'Artikel, Tutorials und mehr',
-            conciergeChat: 'Concierge',
-            conciergeChatDescription: 'Ihr persönlicher KI-Agent',
-            accountManager: 'Kontomanager',
-            yourAccountManager: 'Ihre Kundenbetreuung',
-            accountManagerDescription: 'Fragen stellen und Unterstützung erhalten',
-            partnerManager: 'Partnermanager',
-            yourPartnerManager: 'Ihre Partnermanagerin / Ihr Partnermanager',
-            partnerManagerDescription: 'Nutzen Sie Ihre Partnerschaft optimal und fördern Sie Empfehlungen',
-            guideDescription: 'Ihre Account Managerin / Ihr Account Manager',
-            approvedPartnerTeamTitle: 'Lernen Sie Ihr Approved!-Partnerventeam kennen',
-            approvedPartnerTeamDescription:
-                'Ein engagiertes Team, das sich darauf konzentriert, Ihrem Unternehmen beim Wachstum zu helfen, Kund:innen schneller einzuarbeiten und Ihnen jederzeit fachkundige Unterstützung zu bieten.',
-            accountExecutive: 'Account Executive',
-            accountExecutiveDescription: 'Kund:innen erfolgreich einrichten',
-            moreResources: 'Weitere Ressourcen',
-        },
     },
     closeAccountPage: {
         closeAccount: 'Konto schließen',
@@ -2229,12 +2007,10 @@ const translations: TranslationDeepObject<typeof en> = {
         lockAccount: 'Konto sperren',
         unlockAccount: 'Konto entsperren',
         compromisedDescription:
-            'Ist Ihnen etwas Ungewöhnliches mit Ihrem Konto aufgefallen? Wenn Sie es melden, wird Ihr Konto sofort gesperrt, neue Expensify Karte-Transaktionen werden blockiert und alle Kontenänderungen verhindert.',
-        domainAdminsDescription: 'Für Domain-Admins: Dadurch werden auch alle Aktivitäten der Expensify Karte und alle Administratoraktionen in Ihrer/Ihren Domain(s) pausiert.',
+            'Ist Ihnen etwas Ungewöhnliches an Ihrem Konto aufgefallen? Wenn Sie es melden, wird Ihr Konto sofort gesperrt, neue Expensify Card-Transaktionen werden blockiert und alle Kontenänderungen verhindert.',
+        domainAdminsDescription: 'Für Domain-Admin:innen: Dies pausiert außerdem alle Expensify Card-Aktivitäten und Admin-Aktionen in deiner/Ihrer Domain bzw. deinen/Ihren Domains.',
         areYouSure: 'Möchtest du dein Expensify-Konto wirklich sperren?',
         onceLocked: 'Sobald Ihr Konto gesperrt ist, wird es eingeschränkt, bis eine Entsperrungsanfrage gestellt und eine Sicherheitsprüfung durchgeführt wurde',
-        unlockTitle: 'Wir haben Ihre Anfrage erhalten',
-        unlockDescription: 'Wir überprüfen das Konto, um sicherzustellen, dass es sicher entsperrt werden kann, und melden uns bei Fragen über Concierge.',
     },
     failedToLockAccountPage: {
         failedToLockAccount: 'Konto konnte nicht gesperrt werden',
@@ -2247,13 +2023,6 @@ const translations: TranslationDeepObject<typeof en> = {
         chatToConciergeToUnlock: 'Chatte mit Concierge, um Sicherheitsbedenken zu klären und dein Konto zu entsperren.',
         chatWithConcierge: 'Mit Concierge chatten',
     },
-    deviceManagementPage: {
-        title: 'Geräteverwaltung',
-        description:
-            'Verwalten Sie alle Geräte, bei denen Sie sich mit Ihrem Expensify Konto angemeldet haben. <a href="https://help.expensify.com/articles/new-expensify/settings/Manage-Logged-in-Devices">Erfahren Sie mehr</a>.',
-        revoke: 'Widerrufen',
-        unknownDevice: 'Unbekanntes Gerät',
-    },
     twoFactorAuth: {
         headerTitle: 'Zwei-Faktor-Authentifizierung',
         twoFactorAuthEnabled: 'Zwei-Faktor-Authentifizierung aktiviert',
@@ -2265,17 +2034,17 @@ const translations: TranslationDeepObject<typeof en> = {
         disabled: 'Die Zwei-Faktor-Authentifizierung ist jetzt deaktiviert',
         noAuthenticatorApp: 'Sie benötigen keine Authentifizierungs-App mehr, um sich bei Expensify anzumelden.',
         stepCodes: 'Wiederherstellungscodes',
-        keepCodesSafe: 'Bewahren Sie diese Codes sicher auf!',
+        keepCodesSafe: 'Bewahre diese Wiederherstellungscodes sicher auf!',
         codesLoseAccess: dedent(`
-            Wenn Sie den Zugriff auf Ihre Authentifizierungs-App verlieren und diese Codes nicht haben, wird Ihr Konto gesperrt.<br><br>
-            <strong>Hinweis</strong>: Durch das Aktivieren der 2FA werden Sie aus allen anderen Sitzungen abgemeldet.
+            Wenn du den Zugriff auf deine Authentifizierungs-App verlierst und diese Codes nicht hast, verlierst du den Zugriff auf dein Konto.
+
+            Hinweis: Das Einrichten der Zwei-Faktor-Authentifizierung meldet dich von allen anderen aktiven Sitzungen ab.
         `),
         errorStepCodes: 'Bitte kopiere oder lade die Codes herunter, bevor du fortfährst',
         stepVerify: 'Bestätigen',
         scanCode: 'Scanne den QR-Code mit deinem',
         authenticatorApp: 'Authentifizierungs-App',
         addKey: 'Oder füge diesen geheimen Schlüssel zu deiner Authentifizierungs-App hinzu:',
-        secretKey: 'geheimer Schlüssel',
         enterCode: 'Gib dann den sechsstelligen Code ein, der von deiner Authentifizierungs-App generiert wurde.',
         stepSuccess: 'Fertig',
         enabled: 'Zwei-Faktor-Authentifizierung aktiviert',
@@ -2291,14 +2060,6 @@ const translations: TranslationDeepObject<typeof en> = {
         twoFactorAuthIsRequiredCompany: 'Ihr Unternehmen verlangt eine Zwei-Faktor-Authentifizierung.',
         twoFactorAuthCannotDisable: '2FA kann nicht deaktiviert werden',
         twoFactorAuthRequired: 'Die Zwei-Faktor-Authentifizierung (2FA) ist für Ihre Xero-Verbindung erforderlich und kann nicht deaktiviert werden.',
-        replaceDevice: 'Gerät ersetzen',
-        replaceDeviceTitle: 'Zwei-Faktor-Gerät ersetzen',
-        verifyOldDeviceTitle: 'Altes Gerät verifizieren',
-        verifyOldDeviceDescription: 'Geben Sie den sechsstelligen Code aus Ihrer aktuellen Authentifizierungs-App ein, um zu bestätigen, dass Sie Zugriff darauf haben.',
-        verifyNewDeviceTitle: 'Neues Gerät einrichten',
-        verifyNewDeviceDescription: 'Scannen Sie den QR-Code mit Ihrem neuen Gerät und geben Sie dann den Code ein, um die Einrichtung abzuschließen.',
-        downloadCodes: 'Codes herunterladen',
-        copyCodes: 'Codes kopieren',
     },
     recoveryCodeForm: {
         error: {
@@ -2386,39 +2147,6 @@ const translations: TranslationDeepObject<typeof en> = {
             password: 'Bitte gib dein Expensify-Passwort ein',
         },
     },
-    personalCard: {
-        addPersonalCard: 'Persönliche Karte hinzufügen',
-        addCompanyCard: 'Firmenkarte hinzufügen',
-        lookingForCompanyCards: 'Müssen Sie Firmenkarten hinzufügen?',
-        lookingForCompanyCardsDescription: 'Verbinden Sie Ihre eigenen Karten von über 10.000 Banken weltweit.',
-        personalCardAdded: 'Persönliche Karte hinzugefügt!',
-        personalCardAddedDescription: 'Herzlichen Glückwunsch! Wir beginnen nun mit dem Import von Transaktionen Ihrer Karte.',
-        isPersonalCard: 'Ist dies eine private Karte?',
-        thisIsPersonalCard: 'Dies ist eine private Karte',
-        thisIsCompanyCard: 'Dies ist eine Firmenkarte',
-        askAdmin: 'Fragen Sie Ihren Administrator',
-        warningDescription: ({isAdmin}: {isAdmin?: boolean}) =>
-            `Wenn ja, super! Aber wenn es eine <strong>Firmen</strong>karte ist, weisen Sie sie bitte ${isAdmin ? 'stattdessen über Ihren Workspace zu.' : 'bitten Sie Ihren Administrator, sie Ihnen stattdessen über den Workspace zuzuweisen.'}`,
-        bankConnectionError: 'Bankverbindungsproblem',
-        bankConnectionDescription: 'Bitte versuchen Sie, Ihre Karten erneut hinzuzufügen. Andernfalls können Sie',
-        connectWithPlaid: 'eine Verbindung über Plaid herstellen.',
-        brokenConnection: 'Ihre Kartenverbindung ist unterbrochen.',
-        conciergeBrokenConnection: ({cardName, connectionLink}: ConciergeBrokenCardConnectionParams) =>
-            connectionLink
-                ? `Die Verbindung Ihrer ${cardName}-Karte ist unterbrochen. <a href="${connectionLink}">Melden Sie sich bei Ihrer Bank an</a>, um die Karte zu reparieren.`
-                : `Die Verbindung Ihrer ${cardName}-Karte ist unterbrochen. Melden Sie sich bei Ihrer Bank an, um die Karte zu reparieren.`,
-        fixCard: 'Karte reparieren',
-        addAdditionalCards: 'Weitere Karten hinzufügen',
-        upgradeDescription: 'Müssen Sie weitere Karten hinzufügen? Erstellen Sie einen Workspace, um weitere persönliche Karten hinzuzufügen oder Firmenkarten dem gesamten Team zuzuweisen.',
-        onlyAvailableOnPlan: ({formattedPrice}: {formattedPrice: string}) =>
-            `<muted-text>Dies ist im Collect-Tarif verfügbar, der <strong>${formattedPrice}</strong> pro Mitglied und Monat kostet.</muted-text>`,
-        note: (subscriptionLink: string) =>
-            `<muted-text>Erstellen Sie einen Workspace, um auf diese Funktion zuzugreifen, oder <a href="${subscriptionLink}">erfahren Sie mehr</a> über unsere Tarife und Preise.</muted-text>`,
-        workspaceCreated: 'Workspace erstellt',
-        newWorkspace: 'Sie haben einen Workspace erstellt!',
-        successMessage: ({subscriptionLink}: {subscriptionLink: string}) =>
-            `<centered-text>Sie können jetzt weitere Karten hinzufügen. <a href="${subscriptionLink}">Zeigen Sie Ihr Abonnement an</a> für weitere Details.</centered-text>`,
-    },
     walletPage: {
         balance: 'Saldo',
         paymentMethodsTitle: 'Zahlungsmethoden',
@@ -2446,10 +2174,9 @@ const translations: TranslationDeepObject<typeof en> = {
         enableWallet: 'Wallet aktivieren',
         addBankAccountToSendAndReceive: 'Füge ein Bankkonto hinzu, um Zahlungen zu senden oder zu empfangen.',
         addDebitOrCreditCard: 'Debit- oder Kreditkarte hinzufügen',
-        cardInactive: 'Inaktiv',
-        assignedCards: 'Karten',
-        assignedCardsDescription: 'Transaktionen von zugewiesenen Karten werden automatisch synchronisiert.',
-        expensifyCard: 'Expensify Karte',
+        assignedCards: 'Zugewiesene Karten',
+        assignedCardsDescription: 'Transaktionen von diesen Karten werden automatisch synchronisiert.',
+        expensifyCard: 'Expensify Card',
         walletActivationPending: 'Wir überprüfen gerade Ihre Angaben. Bitte schauen Sie in ein paar Minuten noch einmal vorbei!',
         walletActivationFailed: 'Leider kann Ihre Wallet derzeit nicht aktiviert werden. Bitte chatten Sie mit Concierge, um weitere Unterstützung zu erhalten.',
         addYourBankAccount: 'Füge dein Bankkonto hinzu',
@@ -2472,31 +2199,27 @@ const translations: TranslationDeepObject<typeof en> = {
         unshareBankAccountDescription:
             'Alle unten aufgeführten Personen haben Zugriff auf dieses Bankkonto. Du kannst den Zugriff jederzeit entfernen. Wir werden dennoch alle laufenden Zahlungen abschließen.',
         unshareBankAccountWarning: ({admin}: {admin?: string | null}) => `${admin} wird den Zugriff auf dieses Geschäftskonto verlieren. Wir schließen dennoch alle laufenden Zahlungen ab.`,
-        reachOutForHelp: 'Sie wird mit der Expensify Karte verwendet. <concierge-link>Wenden Sie sich an Concierge</concierge-link>, wenn Sie sie nicht mehr teilen möchten.',
+        reachOutForHelp: 'Sie wird mit der Expensify Card verwendet. <concierge-link>Wende dich an Concierge</concierge-link>, wenn du sie nicht mehr teilen möchtest.',
         unshareErrorModalTitle: 'Bankkonto kann nicht freigegeben werden',
-        travelCVV: {
-            title: 'Reise-CVV',
-            subtitle: 'Verwenden Sie dies bei der Buchung von Reisen',
-            description: 'Verwende diese Karte für deine Expensify Travel-Buchungen. Sie wird beim Bezahlen als “Travel Card” angezeigt.',
-        },
         chaseAccountNumberDifferent: 'Warum ist meine Kontonummer anders?',
     },
     cardPage: {
-        expensifyCard: 'Expensify Karte',
+        expensifyCard: 'Expensify Card',
         expensifyTravelCard: 'Expensify Travel Card',
         availableSpend: 'Verbleibendes Limit',
         smartLimit: {
             name: 'Smartes Limit',
-            title: (formattedLimit: string) =>
+            title: ({formattedLimit}: ViolationsOverLimitParams) =>
                 `Sie können mit dieser Karte bis zu ${formattedLimit} ausgeben, und das Limit wird zurückgesetzt, sobald Ihre eingereichten Ausgaben genehmigt wurden.`,
         },
         fixedLimit: {
             name: 'Fester Grenzwert',
-            title: (formattedLimit: string) => `Sie können bis zu ${formattedLimit} mit dieser Karte ausgeben, danach wird sie deaktiviert.`,
+            title: ({formattedLimit}: ViolationsOverLimitParams) => `Sie können bis zu ${formattedLimit} mit dieser Karte ausgeben, danach wird sie deaktiviert.`,
         },
         monthlyLimit: {
             name: 'Monatliches Limit',
-            title: (formattedLimit: string) => `Sie können mit dieser Karte bis zu ${formattedLimit} pro Monat ausgeben. Das Limit wird am 1. Tag eines jeden Kalendermonats zurückgesetzt.`,
+            title: ({formattedLimit}: ViolationsOverLimitParams) =>
+                `Sie können mit dieser Karte bis zu ${formattedLimit} pro Monat ausgeben. Das Limit wird am 1. Tag eines jeden Kalendermonats zurückgesetzt.`,
         },
         virtualCardNumber: 'Virtuelle Kartennummer',
         travelCardCvv: 'Reisekarten-CVV',
@@ -2517,11 +2240,9 @@ const translations: TranslationDeepObject<typeof en> = {
             expiration: 'Ablauf',
             cvv: 'CVV',
             address: 'Adresse',
-            reveal: 'Anzeigen',
             revealDetails: 'Details anzeigen',
             revealCvv: 'CVV anzeigen',
             copyCardNumber: 'Kartennummer kopieren',
-            copyCvv: 'CVV kopieren',
             updateAddress: 'Adresse aktualisieren',
         },
         cardAddedToWallet: ({platform}: {platform: 'Google' | 'Apple'}) => `Zu ${platform} Wallet hinzugefügt`,
@@ -2529,6 +2250,8 @@ const translations: TranslationDeepObject<typeof en> = {
         validateCardTitle: 'Stellen wir sicher, dass du es bist',
         enterMagicCode: (contactMethod: string) =>
             `Bitte gib den magischen Code ein, der an ${contactMethod} gesendet wurde, um deine Kartendetails anzusehen. Er sollte innerhalb ein bis zwei Minuten ankommen.`,
+        missingPrivateDetails: ({missingDetailsLink}: {missingDetailsLink: string}) =>
+            `Bitte <a href="${missingDetailsLink}">füge deine persönlichen Daten hinzu</a> und versuche es dann erneut.`,
         unexpectedError: 'Beim Abrufen deiner Expensify-Kartendaten ist ein Fehler aufgetreten. Bitte versuche es erneut.',
         cardFraudAlert: {
             confirmButtonText: 'Ja, das tue ich',
@@ -2550,43 +2273,6 @@ const translations: TranslationDeepObject<typeof en> = {
 
 ${amount} für ${merchant} – ${date}`,
         },
-        setYourPin: 'Legen Sie Ihre PIN fest.',
-        confirmYourPin: 'Bestätigen Sie Ihre PIN.',
-        changeYourPin: 'Geben Sie eine neue PIN für Ihre Karte ein.',
-        confirmYourChangedPin: 'Bestätigen Sie Ihre neue PIN.',
-        pinMustBeFourDigits: 'Die PIN muss genau 4 Ziffern lang sein.',
-        invalidPin: 'Bitte wählen Sie eine sicherere PIN.',
-        pinMismatch: 'PINs stimmen nicht überein. Bitte versuchen Sie es erneut.',
-        revealPin: 'PIN anzeigen',
-        hidePin: 'PIN ausblenden',
-        pin: 'PIN',
-        changePin: 'PIN ändern',
-        pinChanged: 'PIN geändert!',
-        pinChangedHeader: 'PIN geändert',
-        pinChangedDescription: 'Sie können Ihre PIN jetzt verwenden.',
-        changePinAtATM: 'Ändern Sie Ihre PIN an jedem Geldautomaten',
-        changePinAtATMDescription: 'Dies ist in Ihrer Region erforderlich. <concierge-link>Kontaktieren Sie Concierge</concierge-link> falls Sie Fragen haben.',
-        freezeCard: 'Karte sperren',
-        unfreeze: 'Entsperren',
-        unfreezeCard: 'Karte entsperren',
-        askToUnfreeze: 'Entsperrung anfragen',
-        freezeDescription: 'Eine gesperrte Karte kann nicht für Käufe und Transaktionen verwendet werden. Du kannst sie jederzeit entsperren.',
-        unfreezeDescription:
-            'Durch das Entsperren dieser Karte werden Käufe und Transaktionen wieder zugelassen. Fahre nur fort, wenn du sicher bist, dass die Karte sicher verwendet werden kann.',
-        frozen: 'Gesperrt',
-        youFroze: ({date}: {date: string}) => `Du hast diese Karte am ${date} gesperrt.`,
-        frozenBy: ({person, date}: {person: string; date: string}) => `${person} hat diese Karte am ${date} gesperrt.`,
-        frozenByAdminPrefix: ({date}: {date: string}) => `Diese Karte wurde am ${date} gesperrt von `,
-        frozenByAdminNeedsUnfreezePrefix: 'Diese Karte wurde von ',
-        frozenByAdminNeedsUnfreezeSuffix: ' gesperrt. Bitte kontaktiere einen Admin, um sie zu entsperren.',
-        frozenByAdminNeedsUnfreeze: ({person}: {person: string}) => `Diese Karte wurde von ${person} gesperrt. Bitte kontaktiere einen Admin, um sie zu entsperren.`,
-        spendRules: 'Ausgaberichtlinien',
-        editSpendRules: 'Ausgaberegeln bearbeiten',
-        cardUnblocked: 'Karte entsperrt!',
-        cardUnblockedDescription: 'Möglicherweise werden Sie beim nächsten Einkauf aufgefordert, Ihre Karte in das Lesegerät einzustecken.',
-        pinBlocked: 'Ihre Karte wurde aufgrund falscher PIN-Eingaben gesperrt.',
-        unblock: 'Entsperren',
-        unblockCard: 'Karte entsperren',
     },
     workflowsPage: {
         workflowTitle: 'Ausgaben',
@@ -2598,14 +2284,9 @@ ${amount} für ${merchant} – ${date}`,
         addApprovalsTitle: 'Genehmigungen',
         accessibilityLabel: ({members, approvers}: {members: string; approvers: string}) => `Ausgaben von ${members} und die genehmigende Person ist ${approvers}`,
         addApprovalButton: 'Genehmigungsablauf hinzufügen',
-        editWorkflowAction: 'Bearbeiten',
-        addAgentAction: 'Agent hinzufügen',
-        findWorkflow: 'Workflow suchen',
         addApprovalTip: 'Dieser Standard-Workflow gilt für alle Mitglieder, sofern kein spezifischerer Workflow vorhanden ist.',
         approver: 'Genehmiger',
         addApprovalsDescription: 'Zusätzliche Genehmigung einholen, bevor eine Zahlung autorisiert wird.',
-        automateApprovalsWithAgentsTitle: 'Genehmigungen mit Agenten automatisieren',
-        automateApprovalsWithAgentsSubtitle: 'Fügen Sie die untenstehende Person zum Workflow hinzu, um Genehmigungen zu automatisieren.',
         makeOrTrackPaymentsTitle: 'Zahlungen',
         makeOrTrackPaymentsDescription:
             'Fügen Sie eine bevollmächtigte zahlende Person für in Expensify getätigte Zahlungen hinzu oder verfolgen Sie Zahlungen, die andernorts getätigt wurden.',
@@ -2651,15 +2332,7 @@ ${amount} für ${merchant} – ${date}`,
             title: 'Keine Mitglieder zum Anzeigen',
             expensesFromSubtitle: 'Alle Workspace-Mitglieder gehören bereits zu einem bestehenden Genehmigungsworkflow.',
             approverSubtitle: 'Alle Genehmigenden gehören zu einem bestehenden Workflow.',
-            bulkApproverSubtitle: 'Keine Genehmigenden entsprechen den Kriterien für die ausgewählten Berichte.',
         },
-        configureViaHR: ({provider}: {provider: string}) => `Über ${provider} konfigurieren.`,
-        hrApprovalWorkflowLockedPrompt: ({provider}: {provider: string}) =>
-            `Genehmigungen werden über deine ${provider}-Integration verwaltet. Um deinen Genehmigungsworkflow zu aktualisieren, gehe zu deinen ${provider}-Verbindungseinstellungen.`,
-        goToHRSettings: ({provider}: {provider: string}) => `Zu den ${provider}-Einstellungen gehen`,
-        approverFromProvider: ({provider}: {provider: string}) => `von ${provider}`,
-        finalApprover: 'Letzte*r Genehmigende*r',
-        manager: 'Manager',
     },
     workflowsDelayedSubmissionPage: {
         autoReportingFrequencyErrorMessage: 'Sendehäufigkeit konnte nicht geändert werden. Bitte versuche es erneut oder kontaktiere den Support.',
@@ -2679,9 +2352,6 @@ ${amount} für ${merchant} – ${date}`,
     workflowsExpensesFromPage: {
         title: 'Ausgaben ab',
         header: 'Wenn die folgenden Mitglieder Ausgaben einreichen:',
-        memberAlreadyInWorkflowTitle: 'Mitglied ist bereits in einem Workflow',
-        memberAlreadyInWorkflowPrompt: ({memberName, approverName}: {memberName: string; approverName: string}) =>
-            `${memberName} befindet sich bereits in einem Genehmigungs-Workflow, der an ${approverName} übermittelt wird. Wenn du das Mitglied hier hinzufügst, wird es in diesen Workflow verschoben.`,
     },
     workflowsApproverPage: {
         genericErrorMessage: 'Die genehmigende Person konnte nicht geändert werden. Bitte versuche es erneut oder kontaktiere den Support.',
@@ -2711,16 +2381,6 @@ ${amount} für ${merchant} – ${date}`,
         admins: 'Admins',
         payer: 'Zahler',
         paymentAccount: 'Zahlungskonto',
-        shareBankAccount: {
-            shareTitle: 'Bankkontozugriff teilen?',
-            shareDescription: ({admin}: {admin: string}) => `Sie müssen ${admin} den Bankkontozugriff gewähren, damit dieser als Zahler eingetragen werden kann.`,
-            validationTitle: 'Bankkonto wartet auf Validierung',
-            validationDescription: ({admin}: {admin: string}) =>
-                `Sie müssen <a href="#">dieses Bankkonto validieren</a>. Anschließend können Sie den Zugriff auf das Bankkonto mit ${admin} teilen, um ihn/sie als Zahler festzulegen.`,
-            errorTitle: 'Zahler kann nicht geändert werden',
-            errorDescription: ({admin, owner}: {admin: string; owner: string}) =>
-                `${admin} hat keinen Zugriff auf dieses Bankkonto, daher kann er nicht als Zahler festgelegt werden. <a href="#">Kontaktieren Sie ${owner}</a>, falls das Bankkonto freigegeben werden soll.`,
-        },
     },
     reportFraudPage: {
         title: 'Virtuelle Kartenbetrugsfälle melden',
@@ -2732,7 +2392,6 @@ ${amount} für ${merchant} – ${date}`,
     reportFraudConfirmationPage: {
         title: 'Kartenbetrug gemeldet',
         description: 'Wir haben Ihre bestehende Karte dauerhaft deaktiviert. Wenn Sie Ihre Kartendetails erneut aufrufen, steht Ihnen eine neue virtuelle Karte zur Verfügung.',
-        descriptionCardNotReplaced: 'Deine Karte wurde dauerhaft deaktiviert. Bitte kontaktiere einen Administrator, um eine neue Karte auszustellen.',
         buttonText: 'Verstanden, danke!',
     },
     activateCardPage: {
@@ -2742,7 +2401,7 @@ ${amount} für ${merchant} – ${date}`,
         error: {
             thatDidNotMatch: 'Das stimmt nicht mit den letzten 4 Ziffern Ihrer Karte überein. Bitte versuchen Sie es erneut.',
             throttled:
-                'Sie haben die letzten 4 Ziffern Ihrer Expensify Karte zu oft falsch eingegeben. Wenn Sie sicher sind, dass die Zahlen korrekt sind, wenden Sie sich bitte an Concierge, um das Problem zu lösen. Andernfalls versuchen Sie es später noch einmal.',
+                'Sie haben die letzten 4 Ziffern Ihrer Expensify Card zu oft falsch eingegeben. Wenn Sie sicher sind, dass die Nummern korrekt sind, wenden Sie sich bitte an Concierge, um das Problem zu lösen. Andernfalls versuchen Sie es später erneut.',
         },
     },
     getPhysicalCard: {
@@ -2767,7 +2426,7 @@ ${amount} für ${merchant} – ${date}`,
         shipCard: 'Karte versenden',
     },
     transferAmountPage: {
-        transfer: (amount: string) => `Überweisung${amount ? ` ${amount}` : ''}`,
+        transfer: ({amount}: TransferParams) => `Überweisung${amount ? ` ${amount}` : ''}`,
         instant: 'Sofort (Debitkarte)',
         instantSummary: (rate: string, minAmount: string) => `${rate}% Gebühr (mindestens ${minAmount})`,
         ach: '1–3 Werktage (Bankkonto)',
@@ -2794,46 +2453,14 @@ ${amount} für ${merchant} – ${date}`,
         defaultPaymentMethod: 'Standard',
         bankAccountLastFour: (lastFour: string) => `Bankkonto • ${lastFour}`,
     },
-    agentsPage: {
-        title: 'Agenten',
-        subtitle: 'Erstelle Agents, die deinen Workflow übernehmen. Spare dir die manuelle Arbeit und gewinne stundenweise Zeit im Alltag zurück.',
-        newAgent: 'Neue:r Agent:in',
-        emptyAgents: {title: 'Keine Agenten erstellt', subtitle: 'Hör auf, Dinge manuell zu erledigen. Weise stattdessen eine:n Agent:in an und spare dir eine Menge Zeit.'},
-        error: {
-            genericAdd: 'Beim Hinzufügen dieses Agenten ist ein Problem aufgetreten',
-            genericUpdate: 'Beim Aktualisieren dieses Agenten ist ein Problem aufgetreten',
-            updateName: 'Beim Aktualisieren des Namens dieser Vertretung ist ein Problem aufgetreten',
-            updatePrompt: 'Beim Aktualisieren der Anweisungen dieses Agenten ist ein Problem aufgetreten',
-            updateAvatar: 'Beim Aktualisieren des Avatars dieser Vertretung ist ein Problem aufgetreten',
-        },
-    },
-    addAgentPage: {
-        title: 'Neue Kontaktperson',
-        agentName: 'Name der Ansprechperson',
-        instructions: 'Eigene Anweisungen schreiben',
-        createAgent: 'Agent erstellen',
-        editAvatar: 'Profilbild wechseln',
-        defaultAgentName: (displayName: string) => `Agent*in von ${displayName}`,
-        defaultPrompt:
-            'Lehne Ausgaben ab, die für Glücksspiele, Kinobesuche oder andere offensichtlich nicht geschäftliche Zwecke sind.\n\nErinnere den:die Nutzer:in daran, immer ein Belegfoto beizufügen, auf dem das Trinkgeld klar erkennbar ist.\n\nGenehmige den Bericht, wenn er früheren Berichten derselben Person sehr ähnlich ist.\n\nLehne Berichte mit mehr als 500 $ an Reisekosten ab.',
-    },
-    editAgentPage: {
-        title: 'Agent bearbeiten',
-        agentName: 'Name der Agentin/des Agenten',
-        instructions: 'Eigene Anweisungen schreiben',
-        chatWithAgent: 'Mit Agent chatten',
-        copilotIntoAccount: 'Copilot ins Konto',
-        deleteAgent: 'Agent löschen',
-        deleteAgentTitle: 'Agent löschen?',
-        deleteAgentMessage: 'Sind Sie sicher, dass Sie diese Vermittlerin/diesen Vermittler löschen möchten? Diese Aktion kann nicht rückgängig gemacht werden.',
-    },
-    editAgentAvatarPage: {title: 'Avatar bearbeiten'},
-    editAgentNamePage: {title: 'Name der Agentin/des Agenten'},
-    editAgentPromptPage: {title: 'Eigene Anweisungen schreiben', error: {emptyPrompt: 'Bitte geben Sie Anweisungen für Ihre:n Agent:in ein.'}},
     expenseRulesPage: {
         title: 'Ausgabenregeln',
+        subtitle: 'Diese Regeln gelten für deine Ausgaben. Wenn du bei einem Workspace einreichst, können die Workspace-Regeln sie außer Kraft setzen.',
         findRule: 'Regel finden',
-        emptyRules: {title: 'Noch keine Regeln', subtitle: 'Füge eine Regel hinzu, um die Spesenabrechnung zu automatisieren.'},
+        emptyRules: {
+            title: 'Du hast noch keine Regeln erstellt',
+            subtitle: 'Füge eine Regel hinzu, um die Spesenabrechnung zu automatisieren.',
+        },
         changes: {
             billableUpdate: (value: boolean) => `Ausgabe ${value ? 'verrechenbar' : 'nicht abrechenbar'} aktualisieren`,
             categoryUpdate: (value: string) => `Kategorie auf „${value}“ aktualisieren`,
@@ -2874,7 +2501,6 @@ ${amount} für ${merchant} – ${date}`,
             deleteSinglePrompt: 'Sind Sie sicher, dass Sie diese Regel löschen möchten?',
             deleteMultiplePrompt: 'Möchtest du diese Regeln wirklich löschen?',
         },
-        subtitle: 'Diese Regeln gelten für deine Ausgaben.',
     },
     preferencesPage: {
         appSection: {
@@ -2902,12 +2528,11 @@ ${amount} für ${merchant} – ${date}`,
         },
     },
     reportDetailsPage: {
-        inWorkspace: (policyName: string) => `in ${policyName}`,
+        inWorkspace: ({policyName}: ReportPolicyNameParams) => `in ${policyName}`,
         generatingPDF: 'PDF erstellen',
         waitForPDF: 'Bitte warten, während wir das PDF erstellen.',
         errorPDF: 'Beim Versuch, Ihre PDF zu erstellen, ist ein Fehler aufgetreten',
         successPDF: 'Dein PDF wurde erstellt! Falls es nicht automatisch heruntergeladen wurde, verwende die Schaltfläche unten.',
-        goToRoom: 'Zum Raum gehen',
     },
     reportDescriptionPage: {
         roomDescription: 'Zimmerbeschreibung',
@@ -2917,7 +2542,7 @@ ${amount} für ${merchant} – ${date}`,
     groupChat: {
         lastMemberTitle: 'Achtung!',
         lastMemberWarning: 'Da du die letzte Person hier bist, wird dieser Chat für alle Mitglieder unzugänglich, wenn du gehst. Bist du sicher, dass du den Chat verlassen möchtest?',
-        defaultReportName: (displayName: string) => `Gruppenchat von ${displayName}`,
+        defaultReportName: ({displayName}: ReportArchiveReasonsClosedParams) => `Gruppenchat von ${displayName}`,
     },
     languagePage: {
         language: 'Sprache',
@@ -2936,26 +2561,19 @@ ${amount} für ${merchant} – ${date}`,
                 label: 'Geräteeinstellungen verwenden',
             },
         },
-        highContrastMode: 'Hoher Kontrast',
-        enableHighContrast: 'Hohen Kontrast aktivieren',
-        disableHighContrast: 'Hohen Kontrast deaktivieren',
         chooseThemeBelowOrSync: 'Wählen Sie unten ein Design aus oder synchronisieren Sie es mit den Einstellungen Ihres Geräts.',
     },
     termsOfUse: {
         terms: `<muted-text-xs>Durch das Einloggen stimmst du den <a href="${CONST.OLD_DOT_PUBLIC_URLS.TERMS_URL}">Nutzungsbedingungen</a> und der <a href="${CONST.OLD_DOT_PUBLIC_URLS.PRIVACY_URL}">Datenschutzerklärung</a> zu.</muted-text-xs>`,
-        license: `Die Geldübermittlung wird von ${CONST.WALLET.PROGRAM_ISSUERS.EXPENSIFY_PAYMENTS} (NMLS-ID:2017010) gemäß seinen <a href="${CONST.OLD_DOT_PUBLIC_URLS.LICENSES_URL}">Lizenzen</a> bereitgestellt.`,
+        license: `<muted-text-xs>Geldübermittlung wird bereitgestellt von ${CONST.WALLET.PROGRAM_ISSUERS.EXPENSIFY_PAYMENTS} (NMLS-ID:2017010) gemäß seinen <a href="${CONST.OLD_DOT_PUBLIC_URLS.LICENSES_URL}">Lizenzen</a>.</muted-text-xs>`,
     },
     validateCodeForm: {
         magicCodeNotReceived: 'Keinen magischen Code erhalten?',
-        avoidScamsMessage:
-            '<strong>Vermeiden Sie Betrug. Geben Sie Ihren Code nicht an andere weiter.</strong> Unser Team wird Sie niemals anrufen, per SMS kontaktieren oder Ihnen eine E-Mail senden, um diesen Code zu erfragen.',
         enterAuthenticatorCode: 'Bitte gib deinen Authentifizierungscode ein',
         enterRecoveryCode: 'Bitte gib deinen Wiederherstellungscode ein',
         requiredWhen2FAEnabled: 'Erforderlich, wenn 2FA aktiviert ist',
         requestNewCode: ({timeRemaining}: {timeRemaining: string}) => `Fordere einen neuen Code an in <a>${timeRemaining}</a>`,
         requestNewCodeAfterErrorOccurred: 'Neuen Code anfordern',
-        timeRemainingAnnouncement: ({timeRemaining}) => `Verbleibende Zeit: ${timeRemaining} ${timeRemaining === 1 ? 'Sekunde' : 'Sekunden'}`,
-        timeExpiredAnnouncement: 'Die Zeit ist abgelaufen',
         error: {
             pleaseFillMagicCode: 'Bitte gib deinen Magic Code ein',
             incorrectMagicCode: 'Falscher oder ungültiger Magic-Code. Bitte versuche es erneut oder fordere einen neuen Code an.',
@@ -2986,8 +2604,6 @@ ${amount} für ${merchant} – ${date}`,
         phoneOrEmail: 'Telefon oder E-Mail',
         error: {
             invalidFormatEmailLogin: 'Die eingegebene E-Mail-Adresse ist ungültig. Bitte korrigiere das Format und versuche es erneut.',
-            agentSignInBlocked:
-                'Agent-Konten können nicht direkt verwendet werden. Um ein Agent-Konto zu nutzen, melden Sie sich mit Ihrem eigenen Konto an und greifen Sie über Copilot darauf zu.',
         },
         cannotGetAccountDetails: 'Kontodetails konnten nicht abgerufen werden. Bitte melde dich erneut an.',
         loginForm: 'Anmeldeformular',
@@ -3005,38 +2621,27 @@ ${amount} für ${merchant} – ${date}`,
         },
         getStarted: 'Loslegen',
         whatsYourName: 'Wie heißt du?',
-        peopleYouMayKnow: 'Prüfen Sie, ob Ihr Team in Expensify ist',
-        workspaceYouMayJoin: (domain: string, email: string) =>
-            `Geben Sie den an ${email} gesendeten Code ein, um zu prüfen, ob jemand von ${domain} einen Arbeitsbereich hat, dem Sie beitreten können.`,
+        peopleYouMayKnow: 'Personen, die du vielleicht kennst, sind bereits hier! Bestätige deine E-Mail-Adresse, um dich ihnen anzuschließen.',
+        workspaceYouMayJoin: ({domain, email}: WorkspaceYouMayJoin) =>
+            `Jemand von ${domain} hat bereits einen Workspace erstellt. Bitte gib den magischen Code ein, der an ${email} gesendet wurde.`,
         joinAWorkspace: 'Einem Arbeitsbereich beitreten',
-        listOfWorkspaces: 'Hier ist die Liste der Arbeitsbereiche, denen Sie beitreten können.',
-        skipForNow: 'Vorerst überspringen',
-        workspaceMemberList: (employeeCount: number, policyOwner: string) => `${employeeCount} Mitglied${employeeCount > 1 ? 's' : ''} • ${policyOwner}`,
+        listOfWorkspaces: 'Hier ist die Liste der Arbeitsbereiche, denen du beitreten kannst. Keine Sorge, du kannst ihnen auch später jederzeit beitreten, wenn du möchtest.',
+        workspaceMemberList: ({employeeCount, policyOwner}: WorkspaceMemberList) => `${employeeCount} Mitglied${employeeCount > 1 ? 's' : ''} • ${policyOwner}`,
         whereYouWork: 'Wo arbeitest du?',
         errorSelection: 'Wähle eine Option, um fortzufahren',
         purpose: {
             title: 'Was möchtest du heute tun?',
             errorContinue: 'Bitte auf „Weiter“ drücken, um die Einrichtung abzuschließen',
             errorBackButton: 'Bitte beantworte die Einrichtungsfragen, um die App verwenden zu können',
-            [CONST.ONBOARDING_CHOICES.EMPLOYER]: 'Ausgaben bei meinem Arbeitgeber einreichen',
+            [CONST.ONBOARDING_CHOICES.EMPLOYER]: 'Von meinem Arbeitgeber zurückerstattet werden',
             [CONST.ONBOARDING_CHOICES.MANAGE_TEAM]: 'Verwalte die Ausgaben meines Teams',
-            [CONST.ONBOARDING_CHOICES.TRACK_BUSINESS]: 'Geschäftsausgaben nachverfolgen',
-            [CONST.ONBOARDING_CHOICES.TRACK_PERSONAL]: 'Meine persönlichen Ausgaben organisieren',
+            [CONST.ONBOARDING_CHOICES.PERSONAL_SPEND]: 'Ausgaben nachverfolgen und budgetieren',
+            [CONST.ONBOARDING_CHOICES.CHAT_SPLIT]: 'Chatten und Ausgaben mit Freunden aufteilen',
             [CONST.ONBOARDING_CHOICES.LOOKING_AROUND]: 'Etwas anderes',
         },
-        personalTrackGoal: {
-            title: 'Was möchten Sie verfolgen?',
-            [CONST.ONBOARDING_PERSONAL_TRACK_GOALS.INVESTMENT_TRACKING]: 'Kosten für eine Investitionsimmobilie',
-            [CONST.ONBOARDING_PERSONAL_TRACK_GOALS.HOUSEHOLD_TRACKING]: 'Haushaltsausgaben',
-            [CONST.ONBOARDING_PERSONAL_TRACK_GOALS.SIDEPROJECT_TRACKING]: 'Ausgaben für Nebenprojekte',
-            [CONST.ONBOARDING_PERSONAL_TRACK_GOALS.SOMETHING_ELSE]: 'Etwas anderes',
-            somethingElsePlaceholder: 'Was möchten Sie verfolgen?',
-        },
         employees: {
             title: 'Wie viele Mitarbeitende haben Sie?',
-            [CONST.ONBOARDING_COMPANY_SIZE.MICRO_SMALL]: '1–4 Mitarbeitende',
-            [CONST.ONBOARDING_COMPANY_SIZE.MICRO_MEDIUM]: '5–10 Mitarbeitende',
-            [CONST.ONBOARDING_COMPANY_SIZE.MICRO]: '1–10 Mitarbeitende',
+            [CONST.ONBOARDING_COMPANY_SIZE.MICRO]: '1–10 Beschäftigte',
             [CONST.ONBOARDING_COMPANY_SIZE.SMALL]: '11–50 Mitarbeitende',
             [CONST.ONBOARDING_COMPANY_SIZE.MEDIUM_SMALL]: '51–100 Mitarbeitende',
             [CONST.ONBOARDING_COMPANY_SIZE.MEDIUM]: '101–1.000 Mitarbeitende',
@@ -3066,19 +2671,16 @@ ${amount} für ${merchant} – ${date}`,
         },
         workEmailValidation: {
             title: 'Bestätige deine Arbeits-E-Mail-Adresse',
-            magicCodeSent: (workEmail: string | undefined) => `Bitte gib den magischen Code ein, der an ${workEmail} gesendet wurde. Er sollte in ein bis zwei Minuten ankommen.`,
+            magicCodeSent: ({workEmail}: WorkEmailResendCodeParams) => `Bitte gib den magischen Code ein, der an ${workEmail} gesendet wurde. Er sollte in ein bis zwei Minuten ankommen.`,
         },
         workEmailValidationError: {
             publicEmail: 'Bitte gib eine gültige geschäftliche E-Mail-Adresse von einer privaten Domain ein, z. B. mitch@company.com',
-            sameAsSignupEmail: 'Bitte geben Sie eine andere E-Mail-Adresse ein als die, mit der Sie sich registriert haben',
             offline: 'Wir konnten deine geschäftliche E-Mail nicht hinzufügen, da du offenbar offline bist',
         },
         mergeBlockScreen: {
             title: 'Arbeits-E-Mail konnte nicht hinzugefügt werden',
-            subtitle: (workEmail: string | undefined) =>
+            subtitle: ({workEmail}: WorkEmailMergingBlockedParams) =>
                 `Wir konnten ${workEmail} nicht hinzufügen. Bitte versuche es später in den Einstellungen erneut oder chatte mit Concierge, um Unterstützung zu erhalten.`,
-            workAccountClosedSubtitle:
-                'Das Arbeitskonto, das mit dieser E-Mail-Adresse verknüpft ist, wurde geschlossen. Bitte wenden Sie sich an Ihre Unternehmensadministratorin bzw. Ihren Unternehmensadministrator, um es zu reaktivieren, oder registrieren Sie sich mit einer anderen E-Mail-Adresse.',
         },
         tasks: {
             testDriveAdminTask: {
@@ -3109,7 +2711,7 @@ ${amount} für ${merchant} – ${date}`,
             },
             createTestDriveAdminWorkspaceTask: {
                 title: ({workspaceConfirmationLink}) => `[Erstelle](${workspaceConfirmationLink}) einen Workspace`,
-                description: 'Erstellen Sie einen Workspace und konfigurieren Sie die Einstellungen mit Hilfe Ihrer Account Executive!',
+                description: 'Erstelle einen Arbeitsbereich und konfiguriere die Einstellungen mit Hilfe deiner Einrichtungsexpertin/deines Einrichtungsexperten!',
             },
             createWorkspaceTask: {
                 title: ({workspaceSettingsLink}) => `[Workspace] erstellen (${workspaceSettingsLink})`,
@@ -3125,13 +2727,13 @@ ${amount} für ${merchant} – ${date}`,
                 title: ({workspaceCategoriesLink}) => `Richte [Kategorien](${workspaceCategoriesLink}) ein`,
                 description: ({workspaceCategoriesLink}) =>
                     dedent(`
-                        *Richten Sie Kategorien ein*, damit Ihr Team Ausgaben für eine einfache Berichterstattung verschlüsseln kann.
+                        *Richte Kategorien ein*, damit dein Team Ausgaben für eine einfache Auswertung zuordnen kann.
 
-                        1. Klicken Sie auf *Workspaces*.
-                        2. Wählen Sie Ihren Workspace aus.
-                        3. Klicken Sie auf *Categories*.
-                        4. Deaktivieren Sie alle Kategorien, die Sie nicht benötigen.
-                        5. Fügen Sie oben rechts Ihre eigenen Kategorien hinzu.
+                        1. Klicke auf *Workspaces*.
+                        2. Wähle deinen Workspace aus.
+                        3. Klicke auf *Categories*.
+                        4. Deaktiviere alle Kategorien, die du nicht benötigst.
+                        5. Füge oben rechts deine eigenen Kategorien hinzu.
 
                         [Zu den Workspace-Kategorieneinstellungen](${workspaceCategoriesLink}).
                     `),
@@ -3141,7 +2743,7 @@ ${amount} für ${merchant} – ${date}`,
                 description: dedent(`
                     *Reiche eine Ausgabe ein*, indem du einen Betrag eingibst oder einen Beleg einscannst.
 
-                    1. Klicke auf die Schaltfläche *+*.
+                    1. Klicke auf die Schaltfläche ${CONST.CUSTOM_EMOJIS.GLOBAL_CREATE}.
                     2. Wähle *Ausgabe erstellen*.
                     3. Gib einen Betrag ein oder scanne einen Beleg.
                     4. Füge die E-Mail-Adresse oder Telefonnummer deiner Führungskraft hinzu.
@@ -3155,7 +2757,7 @@ ${amount} für ${merchant} – ${date}`,
                 description: dedent(`
                     *Reiche eine Ausgabe ein*, indem du einen Betrag eingibst oder einen Beleg scannst.
 
-                    1. Klicke auf die Schaltfläche *+*.
+                    1. Klicke auf die Schaltfläche ${CONST.CUSTOM_EMOJIS.GLOBAL_CREATE}.
                     2. Wähle *Ausgabe erstellen*.
                     3. Gib einen Betrag ein oder scanne einen Beleg.
                     4. Bestätige die Details.
@@ -3169,7 +2771,7 @@ ${amount} für ${merchant} – ${date}`,
                 description: dedent(`
                     *Verfolge eine Ausgabe* in jeder Währung, egal ob du eine Quittung hast oder nicht.
 
-                    1. Klicke auf die Schaltfläche *+*.
+                    1. Klicke auf die Schaltfläche ${CONST.CUSTOM_EMOJIS.GLOBAL_CREATE}.
                     2. Wähle *Ausgabe erstellen*.
                     3. Gib einen Betrag ein oder scanne eine Quittung.
                     4. Wähle deinen *persönlichen* Bereich.
@@ -3191,8 +2793,13 @@ ${amount} für ${merchant} – ${date}`,
                         4. Suche nach ${integrationName}.
                         5. Klicke auf *Connect*.
 
-                        [Zur Buchhaltung](${workspaceAccountingLink}).
-                    `),
+${
+    integrationName && CONST.connectionsVideoPaths[integrationName]
+        ? `[Zum Bereich Buchhaltung](${workspaceAccountingLink}).
+
+                        ![Mit ${integrationName} verbinden](${CONST.CLOUDFRONT_URL}/${CONST.connectionsVideoPaths[integrationName]})`
+        : `[Zur Buchhaltung](${workspaceAccountingLink}).`
+}`),
             },
             connectCorporateCardTask: {
                 title: ({corporateCardLink}) => `[Geschäftskarten verbinden](${corporateCardLink})`,
@@ -3211,17 +2818,16 @@ ${amount} für ${merchant} – ${date}`,
                 title: ({workspaceMembersLink}) => `[your team](${workspaceMembersLink}) einladen`,
                 description: ({workspaceMembersLink}) =>
                     dedent(`
-                        *Lade dein Team* zu Expensify ein, damit alle noch heute mit der Spesenerfassung starten können.
+                        *Lade dein Team* zu Expensify ein, damit es noch heute mit der Spesenerfassung beginnen kann.
 
                         1. Klicke auf *Workspaces*.
                         2. Wähle deinen Workspace aus.
                         3. Klicke auf *Members* > *Invite member*.
                         4. Gib E-Mail-Adressen oder Telefonnummern ein.
-                        5. Füge eine individuelle Einladung hinzu, wenn du möchtest!
+                        5. Füge eine eigene Einladung hinzu, wenn du möchtest!
 
                         [Zu den Workspace-Mitgliedern](${workspaceMembersLink}).
-
-                    `),
+        `),
             },
             setupCategoriesAndTags: {
                 title: ({workspaceCategoriesLink, workspaceTagsLink}) => `Richte [Kategorien](${workspaceCategoriesLink}) und [Tags](${workspaceTagsLink}) ein`,
@@ -3235,14 +2841,14 @@ ${amount} für ${merchant} – ${date}`,
                 title: ({workspaceTagsLink}) => `Richte [Tags](${workspaceTagsLink}) ein`,
                 description: ({workspaceMoreFeaturesLink}) =>
                     dedent(`
-                        Verwende Tags, um zusätzliche Ausgabendetails wie Projekte, Kunden, Standorte und Abteilungen hinzuzufügen. Wenn du mehrere Tag-Ebenen benötigst, kannst du auf den Control-Tarif upgraden.
+                        Verwende Tags, um zusätzliche Spesendetails wie Projekte, Kunden, Standorte und Abteilungen hinzuzufügen. Wenn du mehrere Tag-Ebenen benötigst, kannst du auf den Control-Tarif upgraden.
 
                         1. Klicke auf *Workspaces*.
                         2. Wähle deinen Workspace aus.
-                        3. Klicke auf *Weitere Funktionen*.
+                        3. Klicke auf *More features*.
                         4. Aktiviere *Tags*.
                         5. Navigiere im Workspace-Editor zu *Tags*.
-                        6. Klicke auf *+ Tag hinzufügen*, um eigene Tags zu erstellen.
+                        6. Klicke auf *+ Add tag*, um eigene zu erstellen.
 
                         [Zu den zusätzlichen Funktionen](${workspaceMoreFeaturesLink}).
                     `),
@@ -3266,7 +2872,7 @@ ${amount} für ${merchant} – ${date}`,
                 description: dedent(`
                     *Starte einen Chat* mit jeder Person über ihre E‑Mail-Adresse oder Telefonnummer.
 
-                    1. Klicke auf die Schaltfläche *+*.
+                    1. Klicke auf die Schaltfläche ${CONST.CUSTOM_EMOJIS.GLOBAL_CREATE}.
                     2. Wähle *Chat starten*.
                     3. Gib eine E‑Mail-Adresse oder Telefonnummer ein.
 
@@ -3280,7 +2886,7 @@ ${amount} für ${merchant} – ${date}`,
                 description: dedent(`
                     *Spalte Ausgaben* mit einer oder mehreren Personen.
 
-                    1. Klicke auf die Schaltfläche *+*.
+                    1. Klicke auf die Schaltfläche ${CONST.CUSTOM_EMOJIS.GLOBAL_CREATE}.
                     2. Wähle *Chat starten*.
                     3. Gib E-Mail-Adressen oder Telefonnummern ein.
                     4. Klicke im Chat auf die graue *+*-Schaltfläche > *Ausgabe aufteilen*.
@@ -3304,7 +2910,7 @@ ${amount} für ${merchant} – ${date}`,
                 description: dedent(`
                     So erstellst du einen Bericht:
 
-                    1. Klicke auf die Schaltfläche *+*.
+                    1. Klicke auf die Schaltfläche ${CONST.CUSTOM_EMOJIS.GLOBAL_CREATE}.
                     2. Wähle *Bericht erstellen*.
                     3. Klicke auf *Ausgabe hinzufügen*.
                     4. Füge deine erste Ausgabe hinzu.
@@ -3326,16 +2932,19 @@ ${amount} für ${merchant} – ${date}`,
             onboardingManageTeamMessage: ({isOnboardingFlow = false}: {isOnboardingFlow?: boolean}) =>
                 isOnboardingFlow
                     ? dedent(`
-                        # Ihre kostenlose Testversion hat begonnen! Lassen Sie uns mit der Einrichtung starten.
-                        👋 Hallo, ich bin Ihre Expensify Account Executive. Ich habe bereits einen Arbeitsbereich erstellt, um die Belege und Ausgaben Ihres Teams zu verwalten. Um das Beste aus Ihrer 30-tägigen kostenlosen Testversion herauszuholen, folgen Sie einfach den verbleibenden Einrichtungsschritten unten!
+                        # Ihre kostenlose Testphase hat begonnen! Lassen Sie uns mit der Einrichtung starten.
+                        👋 Hallo, ich bin Ihre Expensify-Einrichtungsspezialist*in. Ich habe bereits einen Arbeitsbereich erstellt, um die Belege und Ausgaben Ihres Teams zu verwalten. Um Ihre 30-tägige kostenlose Testphase optimal zu nutzen, folgen Sie einfach den restlichen untenstehenden Einrichtungsschritten!
                     `)
                     : dedent(`
-                        # Ihre kostenlose Testversion hat begonnen! Lassen Sie uns mit der Einrichtung starten.
-                        👋 Hallo, ich bin Ihre Expensify-Ansprechperson. Jetzt, da Sie einen Workspace erstellt haben, nutzen Sie Ihre 30-tägige kostenlose Testversion optimal, indem Sie die folgenden Schritte ausführen!
+                        # Deine kostenlose Testversion hat begonnen! Lass uns alles einrichten.
+                        👋 Hallo, ich bin deine Expensify-Einrichtungsspezialist*in. Nachdem du jetzt einen Arbeitsbereich erstellt hast, nutze deine 30-tägige kostenlose Testversion optimal, indem du die folgenden Schritte befolgst!
                     `),
-            onboardingTrackWorkspaceMessage: 'Um das Beste aus Ihrer 30-tägigen kostenlosen Testversion zu machen, folgen Sie den verbleibenden Schritten unten:',
+            onboardingTrackWorkspaceMessage:
+                '# Lass uns alles einrichten\n👋 Hallo, ich bin deine Expensify-Einrichtungsspezialist*in. Ich habe bereits einen Workspace erstellt, um dir bei der Verwaltung deiner Belege und Ausgaben zu helfen. Um das Beste aus deiner 30-tägigen kostenlosen Testphase herauszuholen, folge einfach den verbleibenden Einrichtungsschritten unten!',
             onboardingChatSplitMessage: 'Rechnungen mit Freund*innen zu teilen ist so einfach wie das Senden einer Nachricht. So geht’s.',
             onboardingAdminMessage: 'Erfahre, wie du als Admin den Arbeitsbereich deines Teams verwaltest und deine eigenen Ausgaben einreichst.',
+            onboardingLookingAroundMessage:
+                'Expensify ist vor allem für die Verwaltung von Spesen, Reisen und Firmenkarten bekannt, aber wir können noch viel mehr. Sag mir, was dich interessiert, und ich helfe dir beim Einstieg.',
             onboardingTestDriveReceiverMessage: '*Du erhältst 3 Monate gratis! Leg unten los.*',
         },
         workspace: {
@@ -3346,7 +2955,7 @@ ${amount} für ${merchant} – ${date}`,
                 descriptionTwo: 'Ausgaben kategorisieren und taggen',
                 descriptionThree: 'Berichte erstellen und teilen',
             },
-            price: (price?: string) => `Teste es 30 Tage kostenlos und upgrade dann für nur <strong>${price ?? '5 $'}/Nutzer/Monat</strong>.`,
+            price: 'Teste es 30 Tage kostenlos und upgrade dann für nur <strong>5 $/Nutzer/Monat</strong>.',
             createWorkspace: 'Workspace erstellen',
         },
         confirmWorkspace: {
@@ -3358,8 +2967,6 @@ ${amount} für ${merchant} – ${date}`,
             title: 'Mitglieder einladen',
             subtitle: 'Füge dein Team hinzu oder lade deine Steuerberatung ein. Je mehr, desto besser!',
         },
-        workEmail2FAError: 'Dieser Login gehört zu einem bestehenden Konto mit aktivierter Zwei-Faktor-Authentifizierung (2FA).',
-        singleSignOnError: 'Diese Anmeldung ist ein bestehendes Konto mit aktiviertem SSO/SAML.',
     },
     featureTraining: {
         doNotShowAgain: 'Nicht mehr anzeigen',
@@ -3379,7 +2986,6 @@ ${amount} für ${merchant} – ${date}`,
         enterPhoneNumber: 'Wie lautet deine Telefonnummer?',
         personalDetails: 'Persönliche Angaben',
         privateDataMessage: 'Diese Angaben werden für Reisen und Zahlungen verwendet. Sie werden niemals in deinem öffentlichen Profil angezeigt.',
-        basicDetails: 'Grundlegende Angaben',
         legalName: 'Rechtlicher Name',
         legalFirstName: 'Rechtlicher Vorname',
         legalLastName: 'Rechtlicher Nachname',
@@ -3388,18 +2994,18 @@ ${amount} für ${merchant} – ${date}`,
             dateShouldBeBefore: (dateString: string) => `Datum muss vor dem ${dateString} liegen`,
             dateShouldBeAfter: (dateString: string) => `Datum muss nach ${dateString} liegen`,
             hasInvalidCharacter: 'Name darf nur lateinische Zeichen enthalten',
-            cannotIncludeCommaOrSemicolon: 'Name darf kein Komma oder Semikolon enthalten',
             incorrectZipFormat: (zipFormat?: string) => `Ungültiges Postleitzahlenformat${zipFormat ? `Zulässiges Format: ${zipFormat}` : ''}`,
             invalidPhoneNumber: `Bitte stelle sicher, dass die Telefonnummer gültig ist (z. B. ${CONST.EXAMPLE_PHONE_NUMBER})`,
         },
     },
     resendValidationForm: {
         linkHasBeenResent: 'Link wurde erneut gesendet',
-        weSentYouMagicSignInLink: (login: string, loginType: string) => `Ich habe einen magischen Anmeldelink an ${login} gesendet. Bitte überprüfe dein ${loginType}, um dich anzumelden.`,
+        weSentYouMagicSignInLink: ({login, loginType}: WeSentYouMagicSignInLinkParams) =>
+            `Ich habe einen magischen Anmeldelink an ${login} gesendet. Bitte überprüfe dein ${loginType}, um dich anzumelden.`,
         resendLink: 'Link erneut senden',
     },
     unlinkLoginForm: {
-        toValidateLogin: (primaryLogin: string, secondaryLogin: string) =>
+        toValidateLogin: ({primaryLogin, secondaryLogin}: ToValidateLoginParams) =>
             `Um ${secondaryLogin} zu bestätigen, sende den magischen Code bitte erneut aus den Kontoeinstellungen von ${primaryLogin}.`,
         noLongerHaveAccess: (primaryLogin: string) => `Wenn du keinen Zugriff mehr auf ${primaryLogin} hast, trenne bitte die Verknüpfung deiner Konten.`,
         unlink: 'Verknüpfung aufheben',
@@ -3458,12 +3064,14 @@ ${amount} für ${merchant} – ${date}`,
     },
     welcomeSignUpForm: {
         join: 'Beitreten',
-        marketingSMSConsent: 'Ich stimme zu, Marketing-SMS von Expensify zu erhalten',
     },
     detailsPage: {
         localTime: 'Ortszeit',
     },
-    newChatPage: {startGroup: 'Gruppe starten', addToGroup: 'Zur Gruppe hinzufügen', addUserToGroup: (username: string) => `${username} zur Gruppe hinzufügen`},
+    newChatPage: {
+        startGroup: 'Gruppe starten',
+        addToGroup: 'Zur Gruppe hinzufügen',
+    },
     yearPickerPage: {
         year: 'Jahr',
         selectYear: 'Bitte ein Jahr auswählen',
@@ -3506,18 +3114,17 @@ ${amount} für ${merchant} – ${date}`,
             custom: 'Benutzerdefiniert',
         },
         untilTomorrow: 'Bis morgen',
-        untilTime: (time: string) => `Bis ${time}`,
+        untilTime: ({time}: UntilTimeParams) => `Bis ${time}`,
         date: 'Datum',
         time: 'Zeit',
         clearAfter: 'Nach Ablauf löschen',
         whenClearStatus: 'Wann sollen wir deinen Status zurücksetzen?',
+        vacationDelegate: 'Urlaubsvertretung',
         setVacationDelegate: `Lege eine Vertretung für den Urlaub fest, die Berichte in deiner Abwesenheit in deinem Namen genehmigt.`,
-        cannotSetVacationDelegate: `Du kannst keinen Urlaubsvertreter festlegen, da du derzeit der Vertreter für die folgenden Mitglieder bist:`,
-        addVacationDelegate: 'Urlaubsvertretung hinzufügen',
         vacationDelegateError: 'Beim Aktualisieren Ihrer Vertretung im Urlaub ist ein Fehler aufgetreten.',
-        asVacationDelegate: (nameOrEmail: string) => `als Urlaubsvertretung von ${nameOrEmail}`,
-        toAsVacationDelegate: (submittedToName: string, vacationDelegateName: string) => `an ${submittedToName} als Urlaubsvertretung für ${vacationDelegateName}`,
-        vacationDelegateWarning: (nameOrEmail: string) =>
+        asVacationDelegate: ({nameOrEmail}: VacationDelegateParams) => `als Urlaubsvertretung von ${nameOrEmail}`,
+        toAsVacationDelegate: ({submittedToName, vacationDelegateName}: SubmittedToVacationDelegateParams) => `an ${submittedToName} als Urlaubsvertretung für ${vacationDelegateName}`,
+        vacationDelegateWarning: ({nameOrEmail}: VacationDelegateParams) =>
             `Sie weisen ${nameOrEmail} als Ihre Urlaubsvertretung zu. Diese Person ist noch nicht in all Ihren Arbeitsbereichen. Wenn Sie fortfahren, wird eine E-Mail an alle Admins Ihrer Arbeitsbereiche gesendet, damit sie hinzugefügt wird.`,
     },
     stepCounter: ({step, total, text}: StepCounterParams) => {
@@ -3547,35 +3154,24 @@ ${amount} für ${merchant} – ${date}`,
         desktopConnection:
             'Hinweis: Um eine Verbindung mit Chase, Wells Fargo, Capital One oder Bank of America herzustellen, klicke bitte hier, um diesen Vorgang in einem Browser abzuschließen.',
         yourDataIsSecure: 'Ihre Daten sind sicher',
-        toGetStarted: 'Fügen Sie ein Bankkonto hinzu, um Ausgaben zu erstatten, Expensify Karten auszugeben, Rechnungszahlungen zu erhalten und Rechnungen zentral zu bezahlen.',
+        toGetStarted:
+            'Füge ein Bankkonto hinzu, um Ausgaben zu erstatten, Expensify Cards auszustellen, Rechnungszahlungen einzuziehen und Rechnungen zentral von einem Ort aus zu bezahlen.',
         plaidBodyCopy: 'Geben Sie Ihren Mitarbeitenden eine einfachere Möglichkeit, Firmenausgaben zu bezahlen – und erstattet zu bekommen.',
         checkHelpLine: 'Ihre Bankleitzahl und Kontonummer finden Sie auf einem Scheck für dieses Konto.',
-        bankAccountPurposeTitle: 'Was möchten Sie mit Ihrem Bankkonto machen?',
-        getReimbursed: 'Erstattung erhalten',
-        getReimbursedDescription: 'Vom Arbeitgeber oder anderen',
-        makePayments: 'Zahlungen tätigen',
-        makePaymentsDescription: 'Spesen bezahlen oder Expensify Karten ausgeben',
         hasPhoneLoginError: (contactMethodRoute: string) =>
             `Um ein Bankkonto zu verknüpfen, bitte <a href="${contactMethodRoute}">füge eine E-Mail-Adresse als deine primäre Anmeldung hinzu</a> und versuche es erneut. Du kannst deine Telefonnummer als sekundäre Anmeldung hinzufügen.`,
         hasBeenThrottledError: 'Beim Hinzufügen Ihres Bankkontos ist ein Fehler aufgetreten. Bitte warten Sie ein paar Minuten und versuchen Sie es erneut.',
-        hasCurrencyError: (workspaceRoute: string) =>
+        hasCurrencyError: ({workspaceRoute}: WorkspaceRouteParams) =>
             `Ups! Es scheint, dass die Währung deines Arbeitsbereichs auf eine andere Währung als USD eingestellt ist. Um fortzufahren, gehe bitte zu <a href="${workspaceRoute}">deinen Arbeitsbereichseinstellungen</a>, stelle sie auf USD ein und versuche es erneut.`,
         bbaAdded: 'Geschäftsbankkonto hinzugefügt!',
         bbaAddedDescription: 'Es ist bereit, für Zahlungen verwendet zu werden.',
-        lockedBankAccount: 'Gesperrtes Bankkonto',
-        unlockBankAccount: 'Bankkonto entsperren',
-        youCantPayThis: `Du kannst diesen Bericht nicht bezahlen, weil du ein <a href="${CONST.UNLOCK_BANK_ACCOUNT_HELP_URL}">gesperrtes Bankkonto</a> hast. Tippe unten und der Concierge hilft dir bei den nächsten Schritten zur Entsperrung.`,
-        htmlUnlockMessage: (maskedAccountNumber: string) =>
-            `<h1>Expensify Business Bank Account ${maskedAccountNumber}</h1><p>Vielen Dank für Ihre Anfrage zur Entsperrung Ihres Bankkontos. Auszahlungsanfragen können aufgrund unzureichender Deckung oder weil das Bankkonto nicht für Lastschriften aktiviert wurde, abgelehnt werden. Wir werden Ihren Fall prüfen und uns bei Ihnen melden, falls wir weitere Informationen zur Lösung dieses Problems benötigen.</p>`,
-        textUnlockMessage: (maskedAccountNumber: string) =>
-            `Expensify Business Bank Account ${maskedAccountNumber}\nVielen Dank für Ihre Anfrage zur Entsperrung Ihres Bankkontos. Auszahlungsanfragen können aufgrund unzureichender Deckung oder weil das Bankkonto nicht für Lastschriften aktiviert wurde, abgelehnt werden. Wir werden Ihren Fall prüfen und uns bei Ihnen melden, falls wir weitere Informationen zur Lösung dieses Problems benötigen.`,
         error: {
             youNeedToSelectAnOption: 'Bitte wählen Sie eine Option, um fortzufahren',
             noBankAccountAvailable: 'Leider ist kein Bankkonto verfügbar',
             noBankAccountSelected: 'Bitte wähle ein Konto aus',
             taxID: 'Bitte geben Sie eine gültige Steueridentifikationsnummer ein',
             website: 'Bitte eine gültige Website eingeben',
-            zipCode: `Bitte gib eine gültige Postleitzahl im folgenden Format ein: ${COMMON_CONST.COUNTRY_ZIP_REGEX_DATA.US.samples}`,
+            zipCode: `Bitte gib eine gültige Postleitzahl im folgenden Format ein: ${CONST.COUNTRY_ZIP_REGEX_DATA.US.samples}`,
             phoneNumber: 'Bitte gib eine gültige Telefonnummer ein',
             email: 'Bitte gib eine gültige E-Mail-Adresse ein',
             companyName: 'Bitte gib einen gültigen Unternehmensnamen ein',
@@ -3603,7 +3199,7 @@ ${amount} für ${merchant} – ${date}`,
             fullName: 'Bitte gib einen gültigen vollständigen Namen ein',
             ownershipPercentage: 'Bitte gib eine gültige Prozentzahl ein',
             deletePaymentBankAccount:
-                'Dieses Bankkonto kann nicht gelöscht werden, da es für Zahlungen mit der Expensify Karte verwendet wird. Wenn Sie dieses Konto trotzdem löschen möchten, wenden Sie sich bitte an Concierge.',
+                'Dieses Bankkonto kann nicht gelöscht werden, da es für Expensify Card-Zahlungen verwendet wird. Wenn du dieses Konto trotzdem löschen möchtest, wende dich bitte an Concierge.',
             sameDepositAndWithdrawalAccount: 'Die Einzahlungs- und Auszahlungskonten sind identisch.',
         },
     },
@@ -3618,11 +3214,6 @@ ${amount} für ${merchant} – ${date}`,
         confirmationStepHeader: 'Überprüfe deine Angaben.',
         confirmationStepSubHeader: 'Prüfen Sie die untenstehenden Angaben sorgfältig und aktivieren Sie das Kontrollkästchen für die Bedingungen, um zu bestätigen.',
         toGetStarted: 'Fügen Sie ein persönliches Bankkonto hinzu, um Erstattungen zu erhalten, Rechnungen zu bezahlen oder die Expensify Wallet zu aktivieren.',
-        updatePersonalInfo: 'Bankkonto aktualisieren',
-        updatePersonalInfoFailure: 'Die Bankkontoinformationen konnten nicht aktualisiert werden. Bitte versuchen Sie es später erneut.',
-        updateSuccessTitle: 'Bankkonto aktualisiert!',
-        updateSuccessHeader: 'Bankkonto aktualisiert',
-        updateSuccessMessage: 'Glückwunsch, dein Bankkonto ist eingerichtet und bereit, Rückerstattungen zu empfangen.',
     },
     addPersonalBankAccountPage: {
         enterPassword: 'Expensify-Passwort eingeben',
@@ -3650,8 +3241,8 @@ ${amount} für ${merchant} – ${date}`,
     messages: {
         errorMessageInvalidPhone: `Bitte gib eine gültige Telefonnummer ohne Klammern oder Bindestriche ein. Wenn du außerhalb der USA bist, füge bitte deine Ländervorwahl hinzu (z. B. ${CONST.EXAMPLE_PHONE_NUMBER}).`,
         errorMessageInvalidEmail: 'Ungültige E-Mail',
-        userIsAlreadyMember: (login: string, name: string) => `${login} ist bereits Mitglied von ${name}`,
-        userIsAlreadyAnAdmin: (login: string, name: string) => `${login} ist bereits Administrator*in von ${name}`,
+        userIsAlreadyMember: ({login, name}: UserIsAlreadyMemberParams) => `${login} ist bereits Mitglied von ${name}`,
+        userIsAlreadyAnAdmin: ({login, name}: UserIsAlreadyMemberParams) => `${login} ist bereits Administrator*in von ${name}`,
     },
     onfidoStep: {
         acceptTerms: 'Indem Sie mit der Anfrage zur Aktivierung Ihres Expensify Wallets fortfahren, bestätigen Sie, dass Sie dies gelesen haben, verstehen und akzeptieren',
@@ -3697,7 +3288,7 @@ ${amount} für ${merchant} – ${date}`,
         haveReadAndAgreePlain: 'Ich habe die Informationen gelesen und bin damit einverstanden, elektronische Hinweise zu erhalten.',
         haveReadAndAgree: `Ich habe die <a href="${CONST.ELECTRONIC_DISCLOSURES_URL}">elektronischen Hinweise</a> gelesen und stimme zu, sie zu erhalten.`,
         agreeToThePlain: 'Ich stimme der Datenschutz- und Wallet-Vereinbarung zu.',
-        agreeToThe: (walletAgreementUrl: string) =>
+        agreeToThe: ({walletAgreementUrl}: WalletAgreementParams) =>
             `Ich stimme der <a href="${CONST.OLD_DOT_PUBLIC_URLS.PRIVACY_URL}">Datenschutzerklärung</a> und der <a href="${walletAgreementUrl}">Wallet-Vereinbarung</a> zu.`,
         enablePayments: 'Zahlungen aktivieren',
         monthlyFee: 'Monatliche Gebühr',
@@ -3709,7 +3300,7 @@ ${amount} für ${merchant} – ${date}`,
         checkTheBoxes: 'Bitte kreuzen Sie die Kästchen unten an.',
         agreeToTerms: 'Stimme den Bedingungen zu und du bist startklar!',
         shortTermsForm: {
-            expensifyPaymentsAccount: (walletProgram: string) => `Die Expensify-Wallet wird von ${walletProgram} herausgegeben.`,
+            expensifyPaymentsAccount: ({walletProgram}: WalletProgramParams) => `Die Expensify-Wallet wird von ${walletProgram} herausgegeben.`,
             perPurchase: 'Pro Einkauf',
             atmWithdrawal: 'Geldautomat-Abhebung',
             cashReload: 'Bargeldaufladung',
@@ -3723,7 +3314,7 @@ ${amount} für ${merchant} – ${date}`,
             generalInfo: `Allgemeine Informationen zu Prepaid-Konten finden Sie unter <a href="${CONST.CFPB_PREPAID_URL}">${CONST.TERMS.CFPB_PREPAID}</a>.`,
             conditionsDetails: `Details und Bedingungen zu allen Gebühren und Dienstleistungen finden Sie unter <a href="${CONST.FEES_URL}">${CONST.FEES_URL}</a> oder telefonisch unter +1 833-400-0904.`,
             electronicFundsWithdrawalInstant: 'Elektronische Abbuchung (sofort)',
-            electronicFundsInstantFeeMin: (amount: string) => `(Min. ${amount})`,
+            electronicFundsInstantFeeMin: ({amount}: TermsParams) => `(Min. ${amount})`,
         },
         longTermsForm: {
             listOfAllFees: 'Eine Liste aller Expensify-Wallet-Gebühren',
@@ -3743,7 +3334,7 @@ ${amount} für ${merchant} – ${date}`,
             electronicFundsInstantDetails: (percentage: string, amount: string) =>
                 'Für das Überweisen von Geld von deinem Expensify-Wallet auf deine verknüpfte Debitkarte über die Option „Sofortüberweisung“ fällt eine Gebühr an. Diese Überweisung wird in der Regel innerhalb weniger Minuten abgeschlossen.' +
                 `Die Gebühr beträgt ${percentage}% des Überweisungsbetrags (mit einer Mindestgebühr von ${amount}).`,
-            fdicInsuranceBancorp: (amount: string) =>
+            fdicInsuranceBancorp: ({amount}: TermsParams) =>
                 `Ihre Gelder sind für eine FDIC-Versicherung berechtigt. Ihre Gelder werden bei oder an ${CONST.WALLET.PROGRAM_ISSUERS.BANCORP_BANK}, ein durch die FDIC versichertes Institut, gehalten oder übertragen.` +
                 `Sobald sie dort sind, sind Ihre Gelder bis zu ${amount} durch die FDIC versichert, falls ${CONST.WALLET.PROGRAM_ISSUERS.BANCORP_BANK} ausfällt, sofern bestimmte Anforderungen an die Einlagensicherung erfüllt sind und Ihre Karte registriert ist. Einzelheiten finden Sie unter ${CONST.TERMS.FDIC_PREPAID}.`,
             contactExpensifyPayments: `Kontaktieren Sie ${CONST.WALLET.PROGRAM_ISSUERS.EXPENSIFY_PAYMENTS} telefonisch unter +1 833-400-0904, per E-Mail an ${CONST.EMAIL.CONCIERGE} oder melden Sie sich bei ${CONST.NEW_EXPENSIFY_URL} an.`,
@@ -3752,7 +3343,7 @@ ${amount} für ${merchant} – ${date}`,
             automated: 'Automatisiert',
             liveAgent: 'Live-Agent',
             instant: 'Sofort',
-            electronicFundsInstantFeeMin: (amount: string) => `Mind. ${amount}`,
+            electronicFundsInstantFeeMin: ({amount}: TermsParams) => `Mind. ${amount}`,
         },
     },
     activateStep: {
@@ -4039,10 +3630,6 @@ ${amount} für ${merchant} – ${date}`,
         youCanChange: 'Sie können die Währung Ihres Arbeitsbereichs in Ihren',
         findCountry: 'Land finden',
         selectCountry: 'Land auswählen',
-        error: {
-            connectToWorkspace: (workspaceRoute: string) =>
-                `Dieses Bankkonto muss mit einem Arbeitsbereich verknüpft werden. Gehen Sie zu <a href="${workspaceRoute}">Arbeitsbereiche</a>, wählen Sie Ihren Arbeitsbereich und navigieren Sie dann zu Workflows > Zahlungen > Bankkonto hinzufügen.`,
-        },
     },
     bankInfoStep: {
         whatAreYour: 'Wie lauten die Bankdaten Ihres Geschäftskontos?',
@@ -4086,7 +3673,7 @@ ${amount} für ${merchant} – ${date}`,
         pleaseUpload: 'Bitte laden Sie unten zusätzliche Unterlagen hoch, damit wir Ihre Identität als Geschäftsführer*in des Unternehmens verifizieren können.',
         enterSignerInfo: 'Unterzeichnerinformationen eingeben',
         thisStep: 'Dieser Schritt wurde abgeschlossen',
-        isConnecting: (bankAccountLastFour: string | undefined, currency: string | undefined) =>
+        isConnecting: ({bankAccountLastFour, currency}: SignerInfoMessageParams) =>
             `verknüpft ein ${currency}-Geschäftskonto mit der Endung ${bankAccountLastFour} mit Expensify, um Mitarbeitende in ${currency} zu bezahlen. Der nächste Schritt erfordert Unterzeichnungsinformationen von einer Führungsperson.`,
         error: {
             emailsMustBeDifferent: 'E-Mail-Adressen müssen unterschiedlich sein',
@@ -4098,7 +3685,7 @@ ${amount} für ${merchant} – ${date}`,
         regulationRequiresUs: 'Vorschriften verpflichten uns, die Identität jeder Person zu überprüfen, die mehr als 25 % des Unternehmens besitzt.',
         iAmAuthorized: 'Ich bin berechtigt, das Geschäftskonto für Geschäftsausgaben zu verwenden.',
         iCertify: 'Ich bestätige, dass die bereitgestellten Angaben wahr und korrekt sind.',
-        iAcceptTheTermsAndConditions: `Ich akzeptiere die <a href="https://www.corpay.com/cross-border/terms">Allgemeinen Geschäftsbedingungen</a>.`,
+        iAcceptTheTermsAndConditions: `Ich akzeptiere die <a href="https://cross-border.corpay.com/tc/">Allgemeinen Geschäftsbedingungen</a>.`,
         iAcceptTheTermsAndConditionsAccessibility: 'Ich akzeptiere die Geschäftsbedingungen.',
         accept: 'Akzeptieren und Bankkonto hinzufügen',
         iConsentToThePrivacyNotice: 'Ich stimme der <a href="https://payments.corpay.com/compliance">Datenschutzerklärung</a> zu.',
@@ -4130,38 +3717,6 @@ ${amount} für ${merchant} – ${date}`,
         weTake: 'Wir nehmen Ihre Sicherheit ernst. Bitte richten Sie jetzt 2FA ein, um Ihrem Konto eine zusätzliche Schutzebene hinzuzufügen.',
         secure: 'Schütze dein Konto',
     },
-    documentsStep: {
-        beforeYouGo: 'Bevor du fortfährst, benötigen wir einige Dokumente, um bestimmte Angaben zu überprüfen',
-        subheader: 'Verifizierung',
-        verificationFailed: 'Die Verifizierung ist fehlgeschlagen, daher benötigen wir zusätzliche Dokumente, um dich und dein Unternehmen zu überprüfen',
-        taxIDVerification: 'Steuer-ID-Verifizierung',
-        taxIDVerificationDescription: dedent(`
-        Bitte lade eine der folgenden Dateien hoch:
-        • IRS TIN/EIN-Zuweisungsschreiben
-        • IRS TIN/EIN-Antragsbestätigung (enthält normalerweise „Congratulations! The EIN has been successfully assigned“)
-        • IRS-Steuerbefreiungsschreiben mit Firmenname und EIN`),
-        nameChangeDocument: 'Dokument zur Namensänderung',
-        nameChangeDocumentDescription:
-            'Wenn sich der Name deines Unternehmens seit der Beantragung der TIN/EIN geändert hat, benötigen wir dieses Dokument zur Verifizierung der angegebenen Steuer-ID',
-        companyAddressVerification: 'Verifizierung der Unternehmensadresse',
-        companyAddressVerificationDescription: dedent(`
-        Bitte lade eine der folgenden Dateien hoch:
-        • Aktuelle Strom-, Wasser- oder Gasrechnung mit Firmenname und Adresse
-        • Kontoauszug mit Firmenname und Adresse
-        • Aktueller Miet- oder Leasingvertrag inkl. Unterschriftsseite mit Firmenname und aktueller Adresse
-        • Versicherungsnachweis mit Firmenname und Adresse
-        • TIN-Zuweisungsdokument mit Firmenname und Adresse`),
-        userAddressVerification: 'Adressverifizierung',
-        userAddressVerificationDescription: dedent(`
-        Bitte lade eine der folgenden Dateien hoch:
-        • Wählerregistrierungskarte
-        • Führerschein
-        • Kontoauszug
-        • Versorgungsrechnung`),
-        userDOBVerification: 'Geburtsdatumsverifizierung',
-        userDOBVerificationDescription: 'Bitte lade einen in den USA ausgestellten Ausweis hoch',
-        finishViaChat: 'Über Chat abschließen',
-    },
     reimbursementAccountLoadingAnimation: {
         oneMoment: 'Einen Moment',
         explanationLine: 'Wir überprüfen gerade Ihre Angaben. Sie können in Kürze mit den nächsten Schritten fortfahren.',
@@ -4301,15 +3856,15 @@ ${amount} für ${merchant} – ${date}`,
             flightSeatChanged: (airlineCode: string) => `Ihre Sitzplatzzuweisung auf Flug ${airlineCode} wurde geändert.`,
             flightSeatCancelled: (airlineCode: string) => `Ihre Sitzplatzzuweisung auf Flug ${airlineCode} wurde entfernt.`,
             paymentDeclined: 'Die Zahlung für Ihre Flugbuchung ist fehlgeschlagen. Bitte versuchen Sie es erneut.',
-            bookingCancelledByTraveler: (type: string, id = '') => `Sie haben Ihre ${type}-Reservierung ${id} storniert.`,
-            bookingCancelledByVendor: (type: string, id = '') => `Der Anbieter hat deine ${type}-Reservierung ${id} storniert.`,
-            bookingRebooked: (type: string, id = '') => `Ihre ${type}-Reservierung wurde erneut gebucht. Neue Bestätigungsnummer: ${id}.`,
-            bookingUpdated: (type: string) => `Ihre ${type}-Buchung wurde aktualisiert. Prüfen Sie die neuen Details in der Reiseroute.`,
+            bookingCancelledByTraveler: ({type, id = ''}: TravelTypeParams) => `Sie haben Ihre ${type}-Reservierung ${id} storniert.`,
+            bookingCancelledByVendor: ({type, id = ''}: TravelTypeParams) => `Der Anbieter hat deine ${type}-Reservierung ${id} storniert.`,
+            bookingRebooked: ({type, id = ''}: TravelTypeParams) => `Ihre ${type}-Reservierung wurde erneut gebucht. Neue Bestätigungsnummer: ${id}.`,
+            bookingUpdated: ({type}: TravelTypeParams) => `Ihre ${type}-Buchung wurde aktualisiert. Prüfen Sie die neuen Details in der Reiseroute.`,
             railTicketRefund: (origin: string, destination: string, startDate: string) =>
                 `Ihr Bahnticket für ${origin} → ${destination} am ${startDate} wurde erstattet. Eine Gutschrift wird verarbeitet.`,
             railTicketExchange: (origin: string, destination: string, startDate: string) => `Ihr Bahnticket für ${origin} → ${destination} am ${startDate} wurde umgetauscht.`,
             railTicketUpdate: (origin: string, destination: string, startDate: string) => `Dein Zugticket von ${origin} nach ${destination} am ${startDate} wurde aktualisiert.`,
-            defaultUpdate: (type: string) => `Ihre ${type}-Reservierung wurde aktualisiert.`,
+            defaultUpdate: ({type}: TravelTypeParams) => `Ihre ${type}-Reservierung wurde aktualisiert.`,
         },
         flightTo: 'Flug nach',
         trainTo: 'Zug nach',
@@ -4320,19 +3875,19 @@ ${amount} für ${merchant} – ${date}`,
     workspace: {
         common: {
             card: 'Karten',
-            expensifyCard: 'Expensify Karte',
+            expensifyCard: 'Expensify Card',
             companyCards: 'Firmenkarten',
             personalCards: 'Persönliche Karten',
             workflows: 'Workflows',
             workspace: 'Workspace',
             findWorkspace: 'Arbeitsbereich finden',
-            findRoom: 'Raum finden',
             edit: 'Arbeitsbereich bearbeiten',
             enabled: 'Aktiviert',
             disabled: 'Deaktiviert',
             everyone: 'Alle',
             delete: 'Arbeitsbereich löschen',
             settings: 'Einstellungen',
+            reimburse: 'Erstattungen',
             categories: 'Kategorien',
             tags: 'Tags',
             customField1: 'Benutzerdefiniertes Feld 1',
@@ -4340,7 +3895,6 @@ ${amount} für ${merchant} – ${date}`,
             customFieldHint: 'Füge benutzerdefinierte Codierung hinzu, die für alle Ausgaben dieses Mitglieds gilt.',
             reports: 'Berichte',
             reportFields: 'Berichtsfelder',
-            invoiceFields: 'Rechnungsfelder',
             reportTitle: 'Berichtstitel',
             reportField: 'Berichts­feld',
             taxes: 'Steuern',
@@ -4369,10 +3923,6 @@ ${amount} für ${merchant} – ${date}`,
             defaultNote: `Belege, die an ${CONST.EMAIL.RECEIPTS} gesendet werden, erscheinen in diesem Workspace.`,
             deleteConfirmation: 'Möchten Sie diesen Workspace wirklich löschen?',
             deleteWithCardsConfirmation: 'Möchtest du diesen Workspace wirklich löschen? Dadurch werden alle Kartenfeeds und zugewiesenen Karten entfernt.',
-            deleteOpenExpensifyCardsError: 'Ihr Unternehmen hat noch aktive Expensify Cards.',
-            outstandingBalanceWarning:
-                'Sie haben einen offenen Saldo, der beglichen werden muss, bevor Sie Ihren letzten Workspace löschen können. Bitte gehen Sie zu Ihren Abonnementeinstellungen, um die Zahlung abzuschließen.',
-            settleBalance: 'Zu Abo wechseln',
             unavailable: 'Nicht verfügbiger Arbeitsbereich',
             memberNotFound: 'Mitglied nicht gefunden. Um ein neues Mitglied zum Arbeitsbereich einzuladen, verwende bitte die Einladungsschaltfläche oben.',
             notAuthorized: `Du hast keinen Zugriff auf diese Seite. Wenn du versuchst, diesem Arbeitsbereich beizutreten, bitte einfach die/den Arbeitsbereichsinhaber·in, dich als Mitglied hinzuzufügen. Etwas anderes? Wende dich an ${CONST.EMAIL.CONCIERGE}.`,
@@ -4383,11 +3933,8 @@ ${amount} für ${merchant} – ${date}`,
             clearFilter: 'Filter zurücksetzen',
             workspaceName: 'Arbeitsbereichsname',
             workspaceOwner: 'Inhaber',
-            keepMeAsAdmin: 'Behalte mich als Administrator',
             workspaceType: 'Arbeitsbereichstyp',
             workspaceAvatar: 'Workspace-Avatar',
-            clientID: 'Kunden-ID',
-            clientIDInputHint: 'Geben Sie die eindeutige Kennung des Kunden ein',
             mustBeOnlineToViewMembers: 'Du musst online sein, um die Mitglieder dieses Arbeitsbereichs anzeigen zu können.',
             moreFeatures: 'Mehr Funktionen',
             requested: 'Angefordert',
@@ -4406,7 +3953,7 @@ ${amount} für ${merchant} – ${date}`,
             appliedOnExport: 'Nicht in Expensify importiert, beim Export angewendet',
             shareNote: {
                 header: 'Teile deinen Workspace mit anderen Mitgliedern',
-                content: (adminsRoomLink: string) =>
+                content: ({adminsRoomLink}: WorkspaceShareNoteParams) =>
                     `Teile diesen QR-Code oder kopiere den Link unten, damit Mitglieder ganz einfach Zugriff auf deinen Workspace anfordern können. Alle Anfragen zum Beitritt zum Workspace werden zur Überprüfung im Raum <a href="${adminsRoomLink}">${CONST.REPORT.WORKSPACE_CHAT_ROOMS.ADMINS}</a> angezeigt.`,
             },
             connectTo: ({connectionName}: ConnectionNameParams) => `Mit ${CONST.POLICY.CONNECTIONS.NAME_USER_FRIENDLY[connectionName]} verbinden`,
@@ -4421,20 +3968,12 @@ ${amount} für ${merchant} – ${date}`,
             memberAlternateText: 'Berichte einreichen und freigeben.',
             adminAlternateText: 'Berichte und Arbeitsbereichseinstellungen verwalten.',
             auditorAlternateText: 'Berichte anzeigen und kommentieren.',
-            roleName: (role?: string) => {
+            roleName: ({role}: OptionalParam<RoleNamesParams> = {}) => {
                 switch (role) {
                     case CONST.POLICY.ROLE.ADMIN:
-                        return 'Workspace-Administrator';
+                        return 'Admin';
                     case CONST.POLICY.ROLE.AUDITOR:
                         return 'Prüfer';
-                    case CONST.POLICY.ROLE.EDITOR:
-                        return 'Editor';
-                    case CONST.POLICY.ROLE.CARD_ADMIN:
-                        return 'Kartenadministrator';
-                    case CONST.POLICY.ROLE.PEOPLE_ADMIN:
-                        return 'Personalverwaltung';
-                    case CONST.POLICY.ROLE.PAYMENTS_ADMIN:
-                        return 'Zahlungsadministrator';
                     case CONST.POLICY.ROLE.USER:
                         return 'Mitglied';
                     default:
@@ -4464,22 +4003,7 @@ ${amount} für ${merchant} – ${date}`,
             budgetFrequency: {monthly: 'monatlich', yearly: 'jährlich'},
             budgetFrequencyUnit: {monthly: 'Monat', yearly: 'Jahr'},
             budgetTypeForNotificationMessage: {tag: 'Tag', category: 'Kategorie'},
-            deepDiveExpensifyCard: `<muted-text-label>Transaktionen der Expensify Karte werden automatisch in ein „Expensify Karte Verbindlichkeitskonto” exportiert, das mit <a href=”${CONST.DEEP_DIVE_EXPENSIFY_CARD}”>unserer Integration</a> erstellt wird.</muted-text-label>`,
-            travelInvoicing: 'Reiseabrechnungskosten exportieren als',
-            travelInvoicingVendor: 'Reiseanbieter',
-            travelInvoicingPayableAccount: 'Reiseverbindlichkeitskonto',
-            hr: 'Personalwesen',
-            rooms: 'Räume',
-            findDomain: 'Domain finden',
-            cardAdminAlternateText: 'Arbeitsbereichskarten verwalten.',
-            peopleAdminAlternateText: 'Mitglieder und Genehmigungsabläufe verwalten.',
-            paymentsAdminAlternateText: 'Workflow-Zahlungen verwalten.',
-            readOnlyActionTitle: 'Nicht so schnell …',
-            readOnlyActionPrompt: 'Ihre Arbeitsbereichsrolle kann diese Einstellungen anzeigen, aber nicht bearbeiten.',
-        },
-        createdForClient: {
-            title: 'Du hast einen Workspace für deinen Kunden erstellt!',
-            description: 'Großartige Neuigkeiten 🎉. Kontaktiere uns, wenn sie Hilfe bei der Einrichtung benötigen.',
+            deepDiveExpensifyCard: `<muted-text-label>Expensify Card-Transaktionen werden automatisch in ein „Expensify Card Liability Account“ exportiert, das mit <a href="${CONST.DEEP_DIVE_EXPENSIFY_CARD}">unserer Integration</a> erstellt wird.</muted-text-label>`,
         },
         receiptPartners: {
             uber: {
@@ -4544,7 +4068,7 @@ ${amount} für ${merchant} – ${date}`,
             exportDescription: 'Konfigurieren Sie, wie Expensify-Daten nach QuickBooks Desktop exportiert werden.',
             date: 'Exportdatum',
             exportInvoices: 'Rechnungen exportieren nach',
-            exportExpensifyCard: 'Expensify Karte-Transaktionen exportieren als',
+            exportExpensifyCard: 'Expensify Card-Transaktionen exportieren als',
             account: 'Konto',
             accountDescription: 'Wähle aus, wo Buchungssätze gebucht werden sollen.',
             accountsPayable: 'Verbindlichkeiten aus Lieferungen und Leistungen',
@@ -4666,7 +4190,7 @@ ${amount} für ${merchant} – ${date}`,
             exportDescription: 'Konfiguriere, wie Expensify-Daten nach QuickBooks Online exportiert werden.',
             date: 'Exportdatum',
             exportInvoices: 'Rechnungen exportieren nach',
-            exportExpensifyCard: 'Expensify Karte-Transaktionen exportieren als',
+            exportExpensifyCard: 'Expensify Card-Transaktionen exportieren als',
             exportDate: {
                 label: 'Exportdatum',
                 description: 'Verwenden Sie dieses Datum beim Exportieren von Berichten zu QuickBooks Online.',
@@ -4704,9 +4228,8 @@ ${amount} für ${merchant} – ${date}`,
             notConfigured: 'Nicht konfiguriert',
             bankAccountDescription: 'Wähle aus, von wo Schecks versendet werden sollen.',
             creditCardAccount: 'Kreditkartenkonto',
-            travelInvoicingDescription: 'Reisekosten werden als Kreditkartenbelastungen in das unten angegebene QuickBooks Online-Konto exportiert.',
             companyCardsLocationEnabledDescription:
-                'QuickBooks Online unterstützt keine Standorte beim Export von Kreditorenrechnungen, wenn Standorte als Tags importiert werden. Da in Ihrem Workspace Standorte als Tags importiert sind, ist diese Exportoption nicht verfügbar.',
+                'QuickBooks Online unterstützt keine Standorte beim Export von Kreditorenrechnungen. Da in deinem Workspace Standorte aktiviert sind, ist diese Exportoption nicht verfügbar.',
             outOfPocketTaxEnabledDescription:
                 'QuickBooks Online unterstützt keine Steuern beim Export von Journalbuchungen. Da in Ihrem Workspace Steuern aktiviert sind, ist diese Exportoption nicht verfügbar.',
             outOfPocketTaxEnabledError: 'Buchungssätze sind nicht verfügbar, wenn Steuern aktiviert sind. Bitte wähle eine andere Exportoption.',
@@ -4802,7 +4325,6 @@ ${amount} für ${merchant} – ${date}`,
             exportDeepDiveCompanyCard:
                 'Exportierte Ausgaben werden als Banktransaktionen auf das unten angegebene Xero-Bankkonto gebucht, und die Buchungsdaten entsprechen den Daten auf Ihrem Kontoauszug.',
             bankTransactions: 'Banktransaktionen',
-            travelInvoicingDescription: 'Reisekosten werden als Banktransaktionen auf das unten angegebene Xero-Konto exportiert.',
             xeroBankAccount: 'Xero-Bankkonto',
             xeroBankAccountDescription: 'Wählen Sie, wo Spesen als Banktransaktionen verbucht werden.',
             exportExpensesDescription: 'Berichte werden als Einkaufsrechnung mit dem unten ausgewählten Datum und Status exportiert.',
@@ -4897,7 +4419,6 @@ ${amount} für ${merchant} – ${date}`,
                     [CONST.SAGE_INTACCT_NON_REIMBURSABLE_EXPENSE_TYPE.VENDOR_BILL]: 'Lieferantenrechnungen',
                 },
             },
-            travelInvoicingDescription: 'Reisekosten werden als Kreditkartenbelastungen in das unten angegebene Sage Intacct-Konto exportiert.',
             creditCardAccount: 'Kreditkartenkonto',
             defaultVendor: 'Standardanbieter',
             defaultVendorDescription: (isReimbursable: boolean) =>
@@ -4930,68 +4451,6 @@ ${amount} für ${merchant} – ${date}`,
                 },
             },
         },
-        certinia: {
-            title: 'Certinia',
-            titleFFA: 'Certinia (FFA)',
-            autoSyncDescription: 'Expensify wird jeden Tag automatisch mit Certinia synchronisiert.',
-            syncReimbursedReportsDescription:
-                'Wenn diese Option aktiviert ist, wird jedes Mal, wenn eine zu zahlende Rechnung in FFA bezahlt wird, der zugehörige Expensify-Bericht automatisch als erstattet markiert.',
-            exportDescription: 'Konfigurieren Sie, wie Expensify-Daten nach Certinia exportiert werden.',
-            payableInvoices: 'Fällige Rechnungen',
-            exportStatus: {
-                label: 'Status der zu zahlenden Rechnung',
-                values: {
-                    [CONST.CERTINIA_EXPORT_STATUS.APPROVED]: 'Abschließen',
-                    [CONST.CERTINIA_EXPORT_STATUS.IN_PROGRESS]: 'In Bearbeitung',
-                    [CONST.CERTINIA_EXPORT_STATUS.SUBMITTED]: 'Übermittelt',
-                },
-            },
-            exportDate: {
-                label: 'Fälligkeitstag der Rechnung',
-                values: {
-                    [CONST.CERTINIA_EXPORT_DATE.LAST_EXPENSE]: 'Datum der letzten Ausgabe',
-                    [CONST.CERTINIA_EXPORT_DATE.REPORT_SUBMITTED]: 'Datum der Berichtseinreichung',
-                    [CONST.CERTINIA_EXPORT_DATE.REPORT_EXPORTED]: 'Exportdatum',
-                },
-            },
-            exportReimbursable: {
-                label: 'Erstattungsfähige Ausgaben exportieren als',
-                helperText: 'Als erstattungsfähig markierte Ausgaben werden als Verbindlichkeitsrechnungen auf den*die Mitarbeitende*n exportiert.',
-            },
-            exportNonReimbursable: {label: 'Nicht erstattungsfähige Ausgaben exportieren als'},
-            noVendorsFound: 'Keine Anbieter gefunden',
-            noVendorsFoundDescription: 'Bitte synchronisieren Sie die Verbindung erneut, nachdem Lieferanten in Certinia hinzugefügt wurden.',
-            prerequisites: {
-                title: 'Bevor Sie die Verbindung herstellen',
-                installBundle: 'Für FFA-Verbindungen',
-                installBundleDescription: ({href, version}: {href: string; version: string}) =>
-                    `Installieren Sie das Expensify-Paket in Salesforce, indem Sie auf diesen Link klicken: <a href="${href}">FFA Expensify-Paket installieren (Version ${version})</a>`,
-                installBundleConfirm: 'Ich habe das Paket installiert',
-                setupContacts: 'Benutzer und Kontakte einrichten',
-                setupContactsBullet1:
-                    'Erstellen Sie sowohl einen Benutzer als auch einen Kontakt für sich selbst in Certinia, falls diese noch nicht vorhanden sind, und stellen Sie sicher, dass die E‑Mail-Adresse mit Ihrer primären E‑Mail-Adresse in Expensify übereinstimmt.',
-                setupContactsBullet2:
-                    'Erstellen Sie Kontakte für alle Mitarbeitenden, die Spesenabrechnungen einreichen werden, sowie für alle Berichtsgenehmigenden. Stellen Sie sicher, dass die E‑Mail-Adresse jedes Kontakts mit der E‑Mail-Adresse des Expensify-Kontos der jeweiligen Mitarbeitenden übereinstimmt.',
-                setupContactsBullet3: 'Legen Sie die Berechtigungssteuerung für Ihre Benutzer für jeden Kontakt/Ressource fest.',
-                setupContactsConfirm: 'Ich habe den Benutzer und die Kontakte eingerichtet',
-                oauth: 'Über Salesforce anmelden',
-                oauthDescription: 'Um die Einrichtung abzuschließen, müssen Sie sich über Salesforce und Certinia anmelden.\n\nVerwenden Sie die Schaltfläche unten, um fortzufahren.',
-                connectButton: 'Mit Certinia verbinden',
-            },
-            import: {
-                chartOfAccounts: 'Kontenplan',
-                chartOfAccountsDescription: 'Der Kontenplan wird als Kategorien in Expensify importiert.',
-                dimensionMapping: ({n}: {n: number}) => `Dimension ${n}`,
-                dimensions: {dimension1: 'Dimension 1', dimension2: 'Dimension 2', dimension3: 'Dimension 3', dimension4: 'Dimension 4'},
-                doNotMap: 'Nicht zuordnen',
-                doNotMapSubtitle: 'Mitarbeiterressource standardmäßig verwenden',
-                mappingTypes: {
-                    [CONST.CERTINIA_MAPPING_VALUE.DEFAULT]: 'Nicht zuordnen',
-                    [CONST.CERTINIA_MAPPING_VALUE.TAG]: 'Als Tags importiert',
-                    [CONST.CERTINIA_MAPPING_VALUE.REPORT_FIELD]: 'Als Berichtsfelder importiert',
-                },
-            },
-        },
         netsuite: {
             subsidiary: 'Tochtergesellschaft',
             subsidiarySelectDescription: 'Wähle die Tochtergesellschaft in NetSuite aus, aus der du Daten importieren möchtest.',
@@ -5006,8 +4465,8 @@ ${amount} für ${merchant} – ${date}`,
             journalPostingPreference: {
                 label: 'Bevorzugte Verbuchung von Journalbuchungen',
                 values: {
-                    [CONST.NETSUITE_JOURNAL_POSTING_PREFERENCE.JOURNALS_POSTING_INDIVIDUAL_LINE]: 'Einzelner Eintrag für jede Ausgabe',
-                    [CONST.NETSUITE_JOURNAL_POSTING_PREFERENCE.JOURNALS_POSTING_TOTAL_LINE]: 'Einzelner, aufgegliederter Eintrag für jeden Bericht',
+                    [CONST.NETSUITE_JOURNAL_POSTING_PREFERENCE.JOURNALS_POSTING_INDIVIDUAL_LINE]: 'Einzelner, aufgeschlüsselter Eintrag für jeden Bericht',
+                    [CONST.NETSUITE_JOURNAL_POSTING_PREFERENCE.JOURNALS_POSTING_TOTAL_LINE]: 'Einzelner Eintrag für jede Ausgabe',
                 },
             },
             invoiceItem: {
@@ -5073,7 +4532,6 @@ ${amount} für ${merchant} – ${date}`,
 
                             Wenn du für jede Karte einen bestimmten Lieferanten festlegen möchtest, gehe zu *Einstellungen > Domains > Firmenkarten*.
                         `),
-                        travelDescription: 'Reisekosten werden als Journaleinträge in das unten angegebene NetSuite-Konto exportiert.',
                     },
                 },
                 expenseReportDestinationConfirmDescription:
@@ -5218,7 +4676,7 @@ ${amount} für ${merchant} – ${date}`,
                 importCustomFields: {
                     chooseOptionBelow: 'Wähle unten eine Option aus:',
                     label: (importedTypes: string[]) => `Importiert als ${importedTypes.join('und')}`,
-                    requiredFieldError: (fieldName: string) => `Bitte gib ${fieldName} ein`,
+                    requiredFieldError: ({fieldName}: RequiredFieldParams) => `Bitte gib ${fieldName} ein`,
                     customSegments: {
                         title: 'Benutzerdefinierte Segmente/Datensätze',
                         addText: 'Benutzerdefiniertes Segment/Datensatz hinzufügen',
@@ -5292,7 +4750,7 @@ _Für detailliertere Anweisungen [besuchen Sie unsere Hilfeseite](${CONST.NETSUI
                             customRecordMappingTitle: 'Wie soll dieser benutzerdefinierte Datensatz in Expensify angezeigt werden?',
                         },
                         errors: {
-                            uniqueFieldError: (fieldName: string) => `Ein benutzerdefiniertes Segment/Datensatz mit dieser ${fieldName?.toLowerCase()} existiert bereits`,
+                            uniqueFieldError: ({fieldName}: RequiredFieldParams) => `Ein benutzerdefiniertes Segment/Datensatz mit dieser ${fieldName?.toLowerCase()} existiert bereits`,
                         },
                     },
                     customLists: {
@@ -5359,7 +4817,7 @@ _Für ausführlichere Anweisungen [besuchen Sie unsere Hilfeseite](${CONST.NETSU
             employeeDefaultDescription: 'Die Standardabteilung der*des Mitarbeitenden wird auf ihre Ausgaben in Sage Intacct angewendet, sofern eine vorhanden ist.',
             displayedAsTagDescription: 'Die Abteilung kann für jede einzelne Ausgabe im Bericht eines Mitarbeitenden ausgewählt werden.',
             displayedAsReportFieldDescription: 'Die Abteilungsauswahl wird auf alle Ausgaben im Bericht einer*s Mitarbeitenden angewendet.',
-            toggleImportTitle: (mappingTitle: string) => `Wähle aus, wie Sage Intacct-<strong>${mappingTitle}</strong> in Expensify behandelt werden soll.`,
+            toggleImportTitle: ({mappingTitle}: ToggleImportTitleParams) => `Wähle aus, wie Sage Intacct-<strong>${mappingTitle}</strong> in Expensify behandelt werden soll.`,
             expenseTypes: 'Ausgabenarten',
             expenseTypesDescription: 'Ihre Sage Intacct-Spesenarten werden in Expensify als Kategorien importiert.',
             accountTypesDescription: 'Ihr Sage Intacct-Kontenplan wird in Expensify als Kategorien importiert.',
@@ -5399,14 +4857,10 @@ _Für ausführlichere Anweisungen [besuchen Sie unsere Hilfeseite](${CONST.NETSU
             free: 'Kostenlos',
             control: 'Steuerung',
             collect: 'Einziehen',
-            submit: 'Einreichen',
         },
         companyCards: {
             addCards: 'Karten hinzufügen',
             selectCards: 'Karten auswählen',
-            fromOtherWorkspaces: 'Aus anderen Workspaces',
-            addWorkEmail: 'Fügen Sie Ihre Arbeits-E-Mail hinzu',
-            addWorkEmailDescription: 'Bitte fügen Sie Ihre Arbeits-E-Mail hinzu, um vorhandene Feeds aus anderen Workspaces zu nutzen.',
             error: {
                 workspaceFeedsCouldNotBeLoadedTitle: 'Kartendaten konnten nicht geladen werden',
                 workspaceFeedsCouldNotBeLoadedMessage:
@@ -5418,11 +4872,6 @@ _Für ausführlichere Anweisungen [besuchen Sie unsere Hilfeseite](${CONST.NETSU
             },
             addNewCard: {
                 other: 'Sonstiges',
-                fileImport: 'Transaktionen aus Datei importieren',
-                createFileFeedHelpText: `<muted-text>Bitte folge dieser <a href="${CONST.COMPANY_CARDS_CREATE_FILE_FEED_HELP_URL}">Hilfsanleitung</a>, um die Ausgaben deiner Firmenkarte zu importieren!</muted-text>`,
-                companyCardLayoutName: 'Name des Firmenkarten-Layouts',
-                cardLayoutNameRequired: 'Der Name des Firmenkarten-Layouts ist erforderlich',
-                useAdvancedFields: 'Erweiterte Felder verwenden (nicht empfohlen)',
                 cardProviders: {
                     gl1025: 'American Express Corporate Cards',
                     cdf: 'Mastercard Firmenkarten',
@@ -5503,27 +4952,6 @@ _Für ausführlichere Anweisungen [besuchen Sie unsere Hilfeseite](${CONST.NETSU
                     confirmText: 'Problem melden',
                     cancelText: 'Überspringen',
                 },
-                csvColumns: {
-                    cardNumber: 'Kartennummer',
-                    postedDate: 'Datum',
-                    merchant: 'Händler',
-                    amount: 'Betrag',
-                    currency: 'Währung',
-                    ignore: 'Ignorieren',
-                    originalTransactionDate: 'Ursprüngliches Transaktionsdatum',
-                    originalAmount: 'Ursprünglicher Betrag',
-                    originalCurrency: 'Ursprüngliche Währung',
-                    comment: 'Kommentar',
-                    category: 'Kategorie',
-                    tag: 'Tag',
-                },
-                csvErrors: {
-                    requiredColumns: (missingColumns: string) => `Bitte weisen Sie jeder der folgenden Eigenschaften eine Spalte zu: ${missingColumns}.`,
-                    duplicateColumns: (duplicateColumn: string) =>
-                        `Ups! Du hast ein einzelnes Feld („${duplicateColumn}“) mehreren Spalten zugeordnet. Bitte überprüfe die Zuordnung und versuche es erneut.`,
-                },
-                fileImportDescription: 'Eine manuelle Option, falls Ihre Bank keinen Feed senden kann.',
-                duplicateFeedModal: {title: 'Karten-Feed bereits verbunden', prompt: 'Sie können denselben Kartenfeed nicht zweimal zu demselben Workspace hinzufügen.'},
             },
             statementCloseDate: {
                 [CONST.COMPANY_CARDS.STATEMENT_CLOSE_DATE.LAST_DAY_OF_MONTH]: 'Letzter Tag des Monats',
@@ -5575,14 +5003,12 @@ _Für ausführlichere Anweisungen [besuchen Sie unsere Hilfeseite](${CONST.NETSU
                 flipAmountSign: 'Betragsvorzeichen umkehren',
                 importButton: 'Transaktionen importieren',
             },
-            deletedCard: 'Gelöschte Karte',
-            assignNewCards: {title: 'Neue Karten zuweisen', description: 'Holen Sie die neuesten Karten zum Zuweisen von Ihrer Bank'},
         },
         expensifyCard: {
-            issueAndManageCards: 'Geben Sie Expensify Karten aus und verwalten Sie sie',
+            issueAndManageCards: 'Expensify Cards ausgeben und verwalten',
             getStartedIssuing: 'Beginne, indem du deine erste virtuelle oder physische Karte ausstellst.',
             verificationInProgress: 'Verifizierung läuft ...',
-            verifyingTheDetails: 'Wir überprüfen ein paar Details. Concierge informiert Sie, sobald Expensify Karten ausgegeben werden können.',
+            verifyingTheDetails: 'Wir überprüfen ein paar Angaben. Concierge informiert dich, sobald Expensify Cards ausgegeben werden können.',
             disclaimer:
                 'Die Expensify Visa® Commercial Card wird von der The Bancorp Bank, N.A., Mitglied der FDIC, gemäß einer Lizenz von Visa U.S.A. Inc. herausgegeben und kann nicht bei allen Händlern verwendet werden, die Visa-Karten akzeptieren. Apple® und das Apple-Logo® sind Marken von Apple Inc., eingetragen in den USA und anderen Ländern. App Store ist eine Dienstleistungsmarke von Apple Inc. Google Play und das Google-Play-Logo sind Marken von Google LLC.',
             euUkDisclaimer:
@@ -5594,8 +5020,8 @@ _Für ausführlichere Anweisungen [besuchen Sie unsere Hilfeseite](${CONST.NETSU
             lastFour: 'Letzte 4',
             limit: 'Limit',
             currentBalance: 'Aktueller Kontostand',
-            currentBalanceDescription: 'Der aktuelle Saldo ist die Summe aller verbuchten Expensify Karte-Transaktionen, die seit dem letzten Abrechnungsdatum erfolgt sind.',
-            balanceWillBeSettledOn: (settlementDate: string) => `Der Saldo wird am ${settlementDate} ausgeglichen.`,
+            currentBalanceDescription: 'Der aktuelle Saldo ist die Summe aller verbuchten Expensify-Card-Transaktionen, die seit dem letzten Abrechnungsdatum stattgefunden haben.',
+            balanceWillBeSettledOn: ({settlementDate}: SettlementDateParams) => `Der Saldo wird am ${settlementDate} ausgeglichen.`,
             settleBalance: 'Saldo ausgleichen',
             cardLimit: 'Kartenlimit',
             remainingLimit: 'Verbleibendes Limit',
@@ -5603,28 +5029,27 @@ _Für ausführlichere Anweisungen [besuchen Sie unsere Hilfeseite](${CONST.NETSU
             remainingLimitDescription:
                 'Wir berücksichtigen mehrere Faktoren, wenn wir Ihr verbleibendes Limit berechnen: Ihre Dauer als Kund*in, die geschäftsbezogenen Angaben, die Sie bei der Registrierung gemacht haben, sowie das verfügbare Guthaben auf Ihrem Geschäftskonto. Ihr verbleibendes Limit kann täglich schwanken.',
             earnedCashback: 'Cashback',
-            earnedCashbackDescription: 'Der Cashback-Saldo basiert auf den abgerechneten monatlichen Ausgaben mit der Expensify Karte in Ihrem Arbeitsbereich.',
+            earnedCashbackDescription: 'Der Cashback-Saldo basiert auf den abgerechneten monatlichen Ausgaben mit der Expensify Card in deinem Workspace.',
             issueNewCard: 'Neue Karte ausstellen',
             finishSetup: 'Einrichtung abschließen',
             chooseBankAccount: 'Bankkonto auswählen',
-            chooseExistingBank: 'Wählen Sie ein bestehendes Geschäftskonto aus, um den Saldo Ihrer Expensify Karte zu bezahlen, oder fügen Sie ein neues Bankkonto hinzu',
+            chooseExistingBank: 'Wähle ein bestehendes Geschäftskonto aus, um dein Expensify Card-Guthaben zu bezahlen, oder füge ein neues Bankkonto hinzu',
             accountEndingIn: 'Konto mit Endziffern',
             addNewBankAccount: 'Neues Bankkonto hinzufügen',
             settlementAccount: 'Verrechnungskonto',
-            settlementAccountDescription: 'Wählen Sie ein Konto aus, um den Saldo Ihrer Expensify Karte zu begleichen.',
-            settlementAccountInfo: (reconciliationAccountSettingsLink: string, accountNumber: string) =>
+            settlementAccountDescription: 'Wähle ein Konto aus, um deinen Expensify Card‑Saldo zu bezahlen.',
+            settlementAccountInfo: ({reconciliationAccountSettingsLink, accountNumber}: SettlementAccountInfoParams) =>
                 `Stelle sicher, dass dieses Konto mit deinem <a href="${reconciliationAccountSettingsLink}">Abstimmungskonto</a> (${accountNumber}) übereinstimmt, damit die kontinuierliche Abstimmung ordnungsgemäß funktioniert.`,
             settlementFrequency: 'Auszahlungsfrequenz',
-            settlementFrequencyDescription: 'Wählen Sie, wie oft Sie den Saldo Ihrer Expensify Karte begleichen.',
+            settlementFrequencyDescription: 'Wähle aus, wie oft du deinen Expensify Card‑Saldo bezahlst.',
             settlementFrequencyInfo:
                 'Wenn du zur monatlichen Abrechnung wechseln möchtest, musst du dein Bankkonto über Plaid verbinden und eine positive Kontohistorie der letzten 90 Tage haben.',
-            applyCashbackToBill: 'Cashback auf meine Expensify-Rechnung anwenden',
-            applyCashbackToBillDescription: 'Das Cashback von der Expensify-Karte wird zur Begleichung deiner Expensify-Rechnung verwendet.',
             frequency: {
                 daily: 'Täglich',
                 monthly: 'Monatlich',
             },
             cardDetails: 'Kartendaten',
+            cardPending: ({name}: {name: string}) => `Die Karte ist derzeit ausstehend und wird ausgestellt, sobald das Konto von ${name} verifiziert wurde.`,
             virtual: 'Virtuell',
             physical: 'Physisch',
             deactivate: 'Karte deaktivieren',
@@ -5641,28 +5066,24 @@ _Für ausführlichere Anweisungen [besuchen Sie unsere Hilfeseite](${CONST.NETSU
             changeCardMonthlyLimitTypeWarning: (limit: number | string) =>
                 `Wenn Sie den Limittyp dieser Karte auf Monatlich ändern, werden neue Transaktionen abgelehnt, da das monatliche Limit von ${limit} bereits erreicht wurde.`,
             addShippingDetails: 'Versanddetails hinzufügen',
-            issuedCard: (assignee: string) => `hat ${assignee} eine Expensify Karte ausgestellt! Die Karte wird in 2–3 Werktagen ankommen.`,
-            issuedCardNoShippingDetails: (assignee: string) => `hat ${assignee} eine Expensify Karte ausgestellt! Die Karte wird versendet, sobald die Versanddaten bestätigt sind.`,
-            issuedCardVirtual: (assignee: string, link: string) => `hat ${assignee} eine virtuelle Expensify Karte ausgestellt! Die ${link} kann sofort verwendet werden.`,
-            addedShippingDetails: (assignee: string) => `${assignee} hat Versanddetails hinzugefügt. Die Expensify Karte wird in 2–3 Werktagen ankommen.`,
-            replacedCard: (assignee: string) => `${assignee} hat ihre Expensify Karte ersetzt. Die neue Karte wird in 2–3 Werktagen ankommen.`,
-            replacedVirtualCard: (assignee: string, link: string) => `${assignee} hat ihre virtuelle Expensify Karte ersetzt! Der ${link} kann sofort verwendet werden.`,
+            issuedCard: (assignee: string) => `hat ${assignee} eine Expensify Card ausgestellt! Die Karte kommt in 2–3 Werktagen an.`,
+            issuedCardNoShippingDetails: (assignee: string) => `hat ${assignee} eine Expensify Card ausgestellt! Die Karte wird versendet, sobald die Versanddetails bestätigt sind.`,
+            issuedCardVirtual: (assignee: string, link: string) => `hat ${assignee} eine virtuelle Expensify Card ausgestellt! Die ${link} kann sofort verwendet werden.`,
+            addedShippingDetails: (assignee: string) => `${assignee} hat Versanddetails hinzugefügt. Die Expensify Card kommt in 2–3 Werktagen an.`,
+            replacedCard: (assignee: string) => `${assignee} hat ihre Expensify Card ersetzt. Die neue Karte wird in 2–3 Werktagen ankommen.`,
+            replacedVirtualCard: (assignee: string, link: string) => `${assignee} hat ihre virtuelle Expensify Card ersetzt! Die ${link} kann sofort verwendet werden.`,
             card: 'Karte',
             replacementCard: 'Ersatzkarte',
             verifyingHeader: 'Wird überprüft',
             bankAccountVerifiedHeader: 'Bankkonto verifiziert',
             verifyingBankAccount: 'Bankkonto wird verifiziert ...',
-            verifyingBankAccountDescription: 'Bitte warten Sie, während wir bestätigen, dass dieses Konto zur Ausgabe von Expensify Karten verwendet werden kann.',
+            verifyingBankAccountDescription: 'Bitte warten Sie, während wir bestätigen, dass dieses Konto zur Ausgabe von Expensify Cards verwendet werden kann.',
             bankAccountVerified: 'Bankkonto verifiziert!',
-            bankAccountVerifiedDescription: 'Sie können Ihren Workspace-Mitgliedern jetzt Expensify Karten ausstellen.',
+            bankAccountVerifiedDescription: 'Sie können jetzt Expensify Cards an die Mitglieder Ihres Arbeitsbereichs ausgeben.',
             oneMoreStep: 'Noch ein Schritt …',
             oneMoreStepDescription: 'Es sieht so aus, als müssten wir Ihr Bankkonto manuell verifizieren. Bitte gehen Sie zu Concierge, wo bereits Anweisungen auf Sie warten.',
             gotIt: 'Verstanden',
             goToConcierge: 'Zu Concierge gehen',
-            exportAsCSV: 'Als CSV exportieren',
-            csvColumnType: 'Typ',
-            csvColumnLimitType: 'Limittyp',
-            csvColumnLimit: 'Limit',
         },
         categories: {
             deleteCategories: 'Kategorien löschen',
@@ -5681,10 +5102,10 @@ _Für ausführlichere Anweisungen [besuchen Sie unsere Hilfeseite](${CONST.NETSU
             needCategoryForExportToIntegration: (connectionName: string) => `Alle Ausgaben müssen kategorisiert werden, um nach ${connectionName} exportiert zu werden.`,
             subtitle: 'Verschaffe dir einen besseren Überblick darüber, wofür Geld ausgegeben wird. Verwende unsere Standardkategorien oder füge eigene hinzu.',
             emptyCategories: {
-                title: 'Noch keine Kategorien',
+                title: 'Sie haben noch keine Kategorien erstellt',
                 subtitle: 'Füge eine Kategorie hinzu, um deine Ausgaben zu organisieren.',
-                subtitleWithAccounting: (accountingPageURL: string, canManage = true) =>
-                    `<muted-text><centered-text>Ihre Kategorien werden derzeit über eine Buchhaltungsverbindung importiert.${canManage ? ` Gehen Sie zu <a href="${accountingPageURL}">Buchhaltung</a>, um Änderungen vorzunehmen.` : ''}</centered-text></muted-text>`,
+                subtitleWithAccounting: (accountingPageURL: string) =>
+                    `<muted-text><centered-text>Ihre Kategorien werden derzeit über eine Buchhaltungsverbindung importiert. Gehen Sie zu <a href="${accountingPageURL}">Buchhaltung</a>, um Änderungen vorzunehmen.</centered-text></muted-text>`,
             },
             updateFailureMessage: 'Beim Aktualisieren der Kategorie ist ein Fehler aufgetreten, bitte versuche es erneut.',
             createFailureMessage: 'Beim Erstellen der Kategorie ist ein Fehler aufgetreten, bitte versuche es erneut.',
@@ -5739,9 +5160,6 @@ _Für ausführlichere Anweisungen [besuchen Sie unsere Hilfeseite](${CONST.NETSU
             travel: {
                 title: 'Reisen',
                 subtitle: 'Buchen, verwalten und abstimmen Sie all Ihre Geschäftsreisen.',
-                disableTravelTitle: 'Deaktivieren Sie zuerst die Reiseabrechnung',
-                disableTravelPrompt: 'Reiseabrechnung ist für diesen Workspace aktiviert. Schalten Sie sie aus, bevor Sie Reisen deaktivieren können.',
-                disableTravelButton: 'Zu den Reiseeinstellungen gehen',
                 getStarted: {
                     title: 'Los geht’s mit Expensify Travel',
                     subtitle: 'Wir brauchen nur noch ein paar weitere Informationen zu deinem Unternehmen, dann bist du startklar.',
@@ -5752,9 +5170,10 @@ _Für ausführlichere Anweisungen [besuchen Sie unsere Hilfeseite](${CONST.NETSU
                     subtitle: 'Wir prüfen derzeit deine Anfrage zur Aktivierung von Expensify Travel. Keine Sorge, wir sagen dir Bescheid, sobald alles bereit ist.',
                     ctaText: 'Anfrage gesendet',
                 },
-                bookOrManageYourTrip: {title: 'Reisebuchung', subtitle: 'Glückwunsch! Du kannst in diesem Arbeitsbereich jetzt Reisen buchen und verwalten.', ctaText: 'Reisen verwalten'},
-                settings: {
-                    autoAddTripName: {title: 'Reisenamen zu Ausgaben hinzufügen', subtitle: 'Reisenamen für in Expensify gebuchte Reisen automatisch zu Spesenbeschreibungen hinzufügen.'},
+                bookOrManageYourTrip: {
+                    title: 'Reise buchen oder verwalten',
+                    subtitle: 'Nutze Expensify Travel, um die besten Reiseangebote zu erhalten und all deine Geschäftsausgaben an einem einzigen Ort zu verwalten.',
+                    ctaText: 'Buchen oder verwalten',
                 },
                 travelInvoicing: {
                     travelBookingSection: {
@@ -5762,58 +5181,29 @@ _Für ausführlichere Anweisungen [besuchen Sie unsere Hilfeseite](${CONST.NETSU
                         subtitle: 'Glückwunsch! Du kannst jetzt in diesem Workspace Reisen buchen und verwalten.',
                         manageTravelLabel: 'Reisen verwalten',
                     },
-                    travelInvoicingSection: {
-                        title: 'Reiseabrechnung',
+                    centralInvoicingSection: {
+                        title: 'Zentrale Rechnungsstellung',
                         subtitle: 'Zentralisiere alle Reisekosten in einer monatlichen Rechnung, statt sie direkt beim Kauf zu bezahlen.',
                         learnHow: 'Mehr erfahren.',
                         subsections: {
                             currentTravelSpendLabel: 'Aktuelle Reisekosten',
-                            currentTravelSpendPaymentQueued: (amount: string) => `Die Zahlung über ${amount} ist in der Warteschlange und wird in Kürze bearbeitet.`,
                             currentTravelSpendCta: 'Saldo bezahlen',
                             currentTravelLimitLabel: 'Aktuelles Reisekontingent',
                             settlementAccountLabel: 'Verrechnungskonto',
                             settlementFrequencyLabel: 'Auszahlungsfrequenz',
                             settlementFrequencyDescription: 'Wie oft Expensify Ihr Geschäftskonto belastet, um aktuelle Expensify Travel-Transaktionen zu begleichen.',
-                            monthlySpendLimitLabel: 'Monatliches Ausgabelimit pro Mitglied',
-                            monthlySpendLimitDescription: 'Der maximale Betrag, den jedes Mitglied pro Monat für Reisen ausgeben kann.',
-                            reduceLimitTitle: 'Reise-Ausgabelimit reduzieren?',
-                            reduceLimitWarning:
-                                'Wenn Sie das Limit reduzieren, können Mitglieder, die diesen Betrag bereits überschritten haben, bis zum nächsten Monat keine neuen Reisebuchungen vornehmen.',
-                            provisioningError:
-                                'Wir konnten einige Mitglieder Ihres Workspace nicht für die Reiseabrechnung einrichten. Bitte versuchen Sie es später erneut oder wenden Sie sich für Unterstützung an Concierge.',
                         },
                     },
-                    disableModal: {
-                        title: 'Reiseabrechnung deaktivieren?',
-                        body: 'Bevorstehende Hotel- und Mietwagenreservierungen müssen möglicherweise mit einer anderen Zahlungsmethode erneut gebucht werden, um eine Stornierung zu vermeiden.',
-                        confirm: 'Ausschalten',
-                    },
-                    outstandingBalanceModal: {
-                        title: 'Reiseabrechnung kann nicht deaktiviert werden',
-                        body: 'Sie haben noch einen offenen Reisensaldo. Bitte begleichen Sie zuerst Ihren Saldo.',
-                        confirm: 'Verstanden',
-                    },
-                    payBalanceModal: {
-                        title: (amount: string) => `Saldo von ${amount} bezahlen?`,
-                        body: 'Die Zahlung wird in die Warteschlange gestellt und kurz darauf verarbeitet. Diese Aktion kann nach dem Start nicht mehr rückgängig gemacht werden.',
-                    },
-                    exportToPDF: 'Als PDF exportieren',
-                    exportToCSV: 'Als CSV exportieren',
-                    selectDateRangeError: 'Bitte wählen Sie einen Datumsbereich für den Export aus',
-                    invalidDateRangeError: 'Das Startdatum muss vor dem Enddatum liegen',
-                    enabled: 'Rechnungsstellung für Reisen aktiviert!',
-                    enabledDescription: 'Alle Reisekosten in diesem Workspace werden nun in einer monatlichen Rechnung zentralisiert.',
                 },
-                personalDetailsDescription: 'Um eine Reise zu buchen, gib bitte deinen amtlichen Namen genau so ein, wie er auf deinem amtlichen Ausweis steht.',
             },
             expensifyCard: {
-                title: 'Expensify Karte',
+                title: 'Expensify Card',
                 subtitle: 'Gewinne Einblicke und Kontrolle über Ausgaben.',
-                disableCardTitle: 'Expensify Karte deaktivieren',
-                disableCardPrompt: 'Sie können die Expensify Karte nicht deaktivieren, weil sie bereits verwendet wird. Wenden Sie sich an Concierge, um die nächsten Schritte zu erfahren.',
+                disableCardTitle: 'Expensify Card deaktivieren',
+                disableCardPrompt: 'Du kannst die Expensify Card nicht deaktivieren, weil sie bereits verwendet wird. Wende dich an Concierge, um die nächsten Schritte zu erfahren.',
                 disableCardButton: 'Mit Concierge chatten',
                 feed: {
-                    title: 'Holen Sie sich die Expensify Karte',
+                    title: 'Expensify Card bestellen',
                     subTitle: 'Optimieren Sie Ihre Geschäftsausgaben und sparen Sie bis zu 50 % bei Ihrer Expensify-Rechnung, plus:',
                     features: {
                         cashBack: 'Cashback auf jeden Einkauf in den USA',
@@ -5837,7 +5227,7 @@ _Für ausführlichere Anweisungen [besuchen Sie unsere Hilfeseite](${CONST.NETSU
                 },
                 bankConnectionError: 'Problem mit Bankverbindung',
                 connectWithPlaid: 'über Plaid verbinden',
-                connectWithExpensifyCard: 'probieren Sie die Expensify Karte aus.',
+                connectWithExpensifyCard: 'teste die Expensify Card.',
                 bankConnectionDescription: `Bitte versuchen Sie, Ihre Karten erneut hinzuzufügen. Andernfalls können Sie`,
                 disableCardTitle: 'Firmenkarten deaktivieren',
                 disableCardPrompt: 'Du kannst Firmenkarten nicht deaktivieren, da diese Funktion verwendet wird. Wende dich an den Concierge, um die nächsten Schritte zu erfahren.',
@@ -5858,10 +5248,7 @@ _Für ausführlichere Anweisungen [besuchen Sie unsere Hilfeseite](${CONST.NETSU
                 updateCard: 'Karte aktualisieren',
                 unassignCard: 'Karte zuweisen aufheben',
                 unassign: 'Zuweisung aufheben',
-                unassignCardDescription: 'Das Entfernen der Zuweisung dieser Karte wird alle nicht eingereichten Transaktionen löschen.',
-                removeCard: 'Karte entfernen',
-                remove: 'Entfernen',
-                removeCardDescription: 'Wenn Sie diese Karte entfernen, werden alle nicht eingereichten Transaktionen gelöscht.',
+                unassignCardDescription: 'Das Aufheben der Zuweisung dieser Karte entfernt alle Transaktionen in Entwurfsberichten aus dem Konto der Karteninhaber*in.',
                 assignCard: 'Karte zuweisen',
                 cardFeedName: 'Name des Kartenfeeds',
                 cardFeedNameDescription: 'Gib dem Kartenfeed einen eindeutigen Namen, damit du ihn von den anderen unterscheiden kannst.',
@@ -5893,9 +5280,9 @@ _Für ausführlichere Anweisungen [besuchen Sie unsere Hilfeseite](${CONST.NETSU
                 noAccountsFound: 'Keine Konten gefunden',
                 defaultCard: 'Standardkarte',
                 downgradeTitle: `Arbeitsbereich kann nicht herabgestuft werden`,
-                downgradeSubTitle: `Dieser Arbeitsbereich kann nicht herabgestuft werden, da mehrere Kartenfeeds verbunden sind (ohne Expensify Karten). Bitte <a href="#">lassen Sie nur einen Kartenfeed verbunden</a>, um fortzufahren.`,
+                downgradeSubTitle: `Dieser Workspace kann nicht herabgestuft werden, da mehrere Kartenfeeds verbunden sind (außer Expensify Cards). Bitte <a href="#">nur einen Kartenfeed behalten</a>, um fortzufahren.`,
                 noAccountsFoundDescription: (connection: string) => `Bitte fügen Sie das Konto in ${connection} hinzu und synchronisieren Sie die Verbindung erneut.`,
-                expensifyCardBannerTitle: 'Holen Sie sich die Expensify Karte',
+                expensifyCardBannerTitle: 'Expensify Card bestellen',
                 expensifyCardBannerSubtitle:
                     'Profitiere von Cashback auf jeden Einkauf in den USA, bis zu 50 % Rabatt auf deine Expensify-Rechnung, unbegrenzt viele virtuelle Karten und vieles mehr.',
                 expensifyCardBannerLearnMoreButton: 'Mehr erfahren',
@@ -5906,7 +5293,7 @@ _Für ausführlichere Anweisungen [besuchen Sie unsere Hilfeseite](${CONST.NETSU
                 title: 'Workflows',
                 subtitle: 'Konfigurieren Sie, wie Ausgaben genehmigt und bezahlt werden.',
                 disableApprovalPrompt:
-                    'Expensify Karten in diesem Workspace verwenden derzeit Genehmigungen, um ihre Smart Limits zu definieren. Bitte ändern Sie die Limittypen aller Expensify Karten mit Smart Limits, bevor Sie Genehmigungen deaktivieren.',
+                    'Expensify Cards in diesem Workspace verwenden derzeit Genehmigungen, um ihre Smart Limits zu definieren. Bitte passe die Limitarten aller Expensify Cards mit Smart Limits an, bevor du Genehmigungen deaktivierst.',
             },
             invoices: {
                 title: 'Rechnungen',
@@ -5951,8 +5338,8 @@ _Für ausführlichere Anweisungen [besuchen Sie unsere Hilfeseite](${CONST.NETSU
             workflowWarningModal: {
                 featureEnabledTitle: 'Nicht so schnell ...',
                 featureEnabledText:
-                    'Expensify Karten in diesem Workspace verwenden Genehmigungsworkflows, um ihre Smart Limits festzulegen.\n\nBitte ändern Sie die Limittypen aller Karten mit Smart Limits, bevor Sie Workflows deaktivieren.',
-                confirmText: 'Zu Expensify Karten',
+                    'Expensify Cards in diesem Workspace basieren auf Genehmigungs-Workflows, um ihre Smart Limits festzulegen.\n\nBitte ändern Sie die Limittypen aller Karten mit Smart Limits, bevor Sie Workflows deaktivieren.',
+                confirmText: 'Zu Expensify-Karten gehen',
             },
             rules: {
                 title: 'Regeln',
@@ -5963,7 +5350,6 @@ _Für ausführlichere Anweisungen [besuchen Sie unsere Hilfeseite](${CONST.NETSU
                 subtitle: 'Legen Sie einen abrechnungsfähigen Stundensatz für die Zeiterfassung fest.',
                 defaultHourlyRate: 'Standardstundensatz',
             },
-            hrWarningModal: {disconnectText: ({integration}: {integration: string}) => `Um HR zu deaktivieren, trennen Sie bitte zuerst ${integration} von diesem Workspace.`},
         },
         reports: {
             reportsCustomTitleExamples: 'Beispiele:',
@@ -5985,7 +5371,10 @@ _Für ausführlichere Anweisungen [besuchen Sie unsere Hilfeseite](${CONST.NETSU
             findReportField: 'Berichtsfeld suchen',
             deleteConfirmation: 'Sind Sie sicher, dass Sie dieses Berichts­feld löschen möchten?',
             deleteFieldsConfirmation: 'Möchten Sie diese Berichtsfelder wirklich löschen?',
-            emptyReportFields: {title: 'Noch keine Berichtsfelder', subtitle: 'Füge ein benutzerdefiniertes Feld (Text, Datum oder Dropdown) hinzu, das in Berichten erscheint.'},
+            emptyReportFields: {
+                title: 'Du hast noch keine Berichtsfelder erstellt',
+                subtitle: 'Füge ein benutzerdefiniertes Feld (Text, Datum oder Dropdown) hinzu, das in Berichten erscheint.',
+            },
             subtitle: 'Berichtsfelder gelten für alle Ausgaben und können hilfreich sein, wenn du nach zusätzlichen Informationen fragen möchtest.',
             disableReportFields: 'Berichtsfelder deaktivieren',
             disableReportFieldsConfirmation: 'Bist du sicher? Text- und Datumsfelder werden gelöscht und Listen werden deaktiviert.',
@@ -6009,7 +5398,10 @@ _Für ausführlichere Anweisungen [besuchen Sie unsere Hilfeseite](${CONST.NETSU
             disableValues: 'Werte deaktivieren',
             enableValue: 'Wert aktivieren',
             enableValues: 'Werte aktivieren',
-            emptyReportFieldsValues: {title: 'Noch keine Listeneinträge', subtitle: 'Füge benutzerdefinierte Werte hinzu, die in Berichten erscheinen.'},
+            emptyReportFieldsValues: {
+                title: 'Sie haben noch keine Listenwerte erstellt',
+                subtitle: 'Füge benutzerdefinierte Werte hinzu, die in Berichten erscheinen.',
+            },
             deleteValuePrompt: 'Sind Sie sicher, dass Sie diesen Listenwert löschen möchten?',
             deleteValuesPrompt: 'Bist du sicher, dass du diese Listenwerte löschen möchtest?',
             listValueRequiredError: 'Bitte gib einen Namen für den Listeneintrag ein',
@@ -6021,33 +5413,9 @@ _Für ausführlichere Anweisungen [besuchen Sie unsere Hilfeseite](${CONST.NETSU
             reportFieldNameRequiredError: 'Bitte gib einen Berichtsfeldnamen ein',
             reportFieldTypeRequiredError: 'Bitte wähle einen Berichtsfeldtyp aus',
             circularReferenceError: 'Dieses Feld kann nicht auf sich selbst verweisen. Bitte aktualisieren.',
-            unsupportedFormulaValueError: ({value}: UnsupportedFormulaValueErrorParams) => `Formelfeld ${value} nicht erkannt`,
             reportFieldInitialValueRequiredError: 'Bitte wähle einen Anfangswert für ein Berichtsfeld aus',
             genericFailureMessage: 'Beim Aktualisieren des Berichtfelds ist ein Fehler aufgetreten. Bitte versuche es erneut.',
         },
-        invoiceFields: {
-            subtitle: 'Rechnungsfelder können hilfreich sein, wenn du zusätzliche Informationen einfügen möchtest.',
-            importedFromAccountingSoftware: 'Die folgenden Rechnungsfelder werden importiert aus Ihrem',
-            disableInvoiceFields: 'Rechnungsfelder deaktivieren',
-            disableInvoiceFieldsConfirmation: 'Sind Sie sicher? Rechnungsfelder werden auf Rechnungen deaktiviert.',
-            delete: 'Rechnungsfeld löschen',
-            deleteConfirmation: 'Sind Sie sicher, dass Sie dieses Rechnungsfeld löschen möchten?',
-            findInvoiceField: 'Rechnungsfeld suchen',
-            nameInputSubtitle: 'Wähle einen Namen für das Rechnungsfeld.',
-            typeInputSubtitle: 'Wähle aus, welcher Rechnungsfeldtyp verwendet werden soll.',
-            initialValueInputSubtitle: 'Gib einen Startwert ein, der im Rechnungsfeld angezeigt werden soll.',
-            listValuesInputSubtitle: 'Diese Werte werden im Dropdown-Menü des Rechnungsfelds angezeigt. Aktivierte Werte können von Mitgliedern ausgewählt werden.',
-            listInputSubtitle: 'Diese Werte werden in der Rechnungsfeldliste angezeigt. Aktivierte Werte können von Mitgliedern ausgewählt werden.',
-            emptyInvoiceFieldsValues: {
-                title: 'Noch keine Listenwerte',
-                subtitle: 'Füge benutzerdefinierte Werte hinzu, die auf Rechnungen angezeigt werden.',
-            },
-            existingInvoiceFieldNameError: 'Ein Rechnungsfeld mit diesem Namen existiert bereits',
-            invoiceFieldNameRequiredError: 'Bitte gib einen Namen für das Rechnungsfeld ein',
-            invoiceFieldTypeRequiredError: 'Bitte wähle einen Rechnungsfeldtyp aus',
-            invoiceFieldInitialValueRequiredError: 'Bitte wähle einen Anfangswert für ein Rechnungsfeld aus',
-            addField: 'Feld hinzufügen',
-        },
         tags: {
             tagName: 'Tag-Name',
             requiresTag: 'Mitglieder müssen alle Ausgaben taggen',
@@ -6065,14 +5433,14 @@ _Für ausführlichere Anweisungen [besuchen Sie unsere Hilfeseite](${CONST.NETSU
             editTags: 'Tags bearbeiten',
             findTag: 'Tag finden',
             subtitle: 'Tags bieten detailliertere Möglichkeiten, Kosten zu klassifizieren.',
-            subtitleWithDependentTags: (importSpreadsheetLink: string, canReimport = true) =>
-                `<muted-text>Tags bieten detailliertere Möglichkeiten, Kosten zu klassifizieren. Sie verwenden <a href="${CONST.IMPORT_TAGS_EXPENSIFY_URL_DEPENDENT_TAGS}">abhängige Tags</a>.${canReimport ? ` Sie können <a href="${importSpreadsheetLink}">eine Tabelle erneut importieren</a>, um Ihre Tags zu aktualisieren.` : ''}</muted-text>`,
+            dependentMultiLevelTagsSubtitle: (importSpreadsheetLink: string) =>
+                `<muted-text>Sie verwenden <a href="${CONST.IMPORT_TAGS_EXPENSIFY_URL_DEPENDENT_TAGS}">abhängige Tags</a>. Sie können <a href="${importSpreadsheetLink}">eine Tabelle erneut importieren</a>, um Ihre Tags zu aktualisieren.</muted-text>`,
             emptyTags: {
-                title: 'Noch keine Tags',
+                title: 'Sie haben noch keine Tags erstellt',
                 subtitle: 'Füge ein Tag hinzu, um Projekte, Standorte, Abteilungen und mehr zu verfolgen.',
                 subtitleHTML: `<muted-text><centered-text>Fügen Sie Tags hinzu, um Projekte, Standorte, Abteilungen und mehr nachzuverfolgen. <a href="${CONST.IMPORT_TAGS_EXPENSIFY_URL}">Erfahren Sie mehr</a> über das Formatieren von Tag-Dateien für den Import.</centered-text></muted-text>`,
-                subtitleWithAccounting: (accountingPageURL: string, canManage = true) =>
-                    `<muted-text><centered-text>Ihre Tags werden derzeit über eine Buchhaltungsverbindung importiert.${canManage ? ` Gehen Sie zu <a href="${accountingPageURL}">Buchhaltung</a>, um Änderungen vorzunehmen.` : ''}</centered-text></muted-text>`,
+                subtitleWithAccounting: (accountingPageURL: string) =>
+                    `<muted-text><centered-text>Ihre Tags werden derzeit über eine Buchhaltungsverbindung importiert. Gehen Sie zu <a href="${accountingPageURL}">Buchhaltung</a>, um Änderungen vorzunehmen.</centered-text></muted-text>`,
             },
             deleteTag: 'Tag löschen',
             deleteTags: 'Tags löschen',
@@ -6158,7 +5526,7 @@ _Für ausführlichere Anweisungen [besuchen Sie unsere Hilfeseite](${CONST.NETSU
                 updateTaxClaimableFailureMessage: 'Der erstattungsfähige Anteil muss geringer sein als der Betrag des Kilometerpauschalsatzes',
             },
             deleteTaxConfirmation: 'Sind Sie sicher, dass Sie diese Steuer löschen möchten?',
-            deleteMultipleTaxConfirmation: (taxAmount: number) => `Möchtest du die Steuern in Höhe von ${taxAmount} wirklich löschen?`,
+            deleteMultipleTaxConfirmation: ({taxAmount}: TaxAmountParams) => `Möchtest du die Steuern in Höhe von ${taxAmount} wirklich löschen?`,
             actions: {
                 delete: 'Satz löschen',
                 deleteMultiple: 'Tarife löschen',
@@ -6186,47 +5554,10 @@ _Für ausführlichere Anweisungen [besuchen Sie unsere Hilfeseite](${CONST.NETSU
             reimbursementAccount: 'Erstattungskonto',
             welcomeNote: 'Bitte verwende meinen neuen Arbeitsbereich',
             delayedSubmission: 'verspätete Einreichung',
-            merchantRules: 'Händlerregeln',
-            merchantRulesCount: () => ({
-                one: '1 Händlerregel',
-                other: (count: number) => `${count} Händlerregeln`,
-            }),
             confirmTitle: ({newWorkspaceName, totalMembers}: {newWorkspaceName?: string; totalMembers?: number}) =>
                 `Sie sind dabei, ${newWorkspaceName ?? ''} mit ${totalMembers ?? 0} Mitgliedern aus dem ursprünglichen Workspace zu erstellen und zu teilen.`,
             error: 'Beim Duplizieren deines neuen Workspace ist ein Fehler aufgetreten. Bitte versuche es erneut.',
         },
-        copyPolicySettings: {
-            title: 'Einstellungen kopieren',
-            error: 'Beim Kopieren der Arbeitsbereichseinstellungen ist ein Fehler aufgetreten. Bitte versuche es erneut.',
-            selectWorkspaces: {
-                title: 'Arbeitsbereiche auswählen',
-                description: 'Wählen Sie die Arbeitsbereiche aus, in die Sie Einstellungen kopieren möchten, und wählen Sie dann die Einstellungen aus, die Sie kopieren möchten.',
-                searchPlaceholder: 'Workspaces durchsuchen',
-            },
-            selectSettings: {
-                title: 'Zu kopierende Funktionen auswählen',
-                description: 'Wählen Sie die Einstellungen aus, die in Ihren bestehenden Arbeitsbereichen überschrieben werden sollen.',
-                accountingMismatch: ({part}: {part: string}) =>
-                    `Sie können ${part} nur kopieren, wenn alle Arbeitsbereiche dasselbe Buchhaltungssystem und dieselbe Unternehmensverbindung verwenden.`,
-            },
-            confirmSettings: {
-                title: 'Stellen wir sicher, dass alles richtig aussieht.',
-                description: ({workspaceName}: {workspaceName: string}) =>
-                    `Wir kopieren die folgenden Einstellungen von <strong>${workspaceName}</strong> in die von Ihnen angegebenen Arbeitsbereiche`,
-            },
-            confirmWorkflows: {
-                continue: 'Ohne Mitglieder fortfahren',
-                description: 'Das Kopieren von Workflows ohne Mitglieder kopiert keine Genehmigungs-Workflows. Einreichungs- und Zahlungseinstellungen werden trotzdem kopiert.',
-            },
-            progress: {
-                copyInProgressTitle: 'Kopieren läuft ...',
-                copyInProgressDescription: 'Sie können entweder warten, bis der Vorgang abgeschlossen ist, oder Concierge kann Sie benachrichtigen, sobald er fertig ist.',
-                letMeKnowPrompt: 'Sagen Sie mir Bescheid, wenn es fertig ist',
-                conciergeNotificationTitle: 'Concierge wird Sie benachrichtigen',
-                conciergeNotificationDescription: 'Wenn der Vorgang abgeschlossen ist, sendet Concierge Ihnen eine Nachricht.',
-                copyCompleted: 'Ihre Workspace-Einstellungen wurden kopiert.',
-            },
-        },
         emptyWorkspace: {
             title: 'Du hast keine Arbeitsbereiche',
             subtitle: 'Belege erfassen, Auslagen erstatten, Reisen verwalten, Rechnungen versenden und mehr.',
@@ -6242,7 +5573,7 @@ _Für ausführlichere Anweisungen [besuchen Sie unsere Hilfeseite](${CONST.NETSU
         },
         new: {
             newWorkspace: 'Neuer Arbeitsbereich',
-            getTheExpensifyCardAndMore: 'Holen Sie sich die Expensify Karte und mehr',
+            getTheExpensifyCardAndMore: 'Hol dir die Expensify Card und mehr',
             confirmWorkspace: 'Workspace bestätigen',
             myGroupWorkspace: ({workspaceNumber}: {workspaceNumber?: number}) => `Mein Gruppen-Arbeitsbereich${workspaceNumber ? ` ${workspaceNumber}` : ''}`,
             workspaceName: (userName: string, workspaceNumber?: number) => `Workspace von ${userName}${workspaceNumber ? ` ${workspaceNumber}` : ''}`,
@@ -6285,12 +5616,12 @@ _Für ausführlichere Anweisungen [besuchen Sie unsere Hilfeseite](${CONST.NETSU
                 genericRemove: 'Beim Entfernen dieses Workspace-Mitglieds ist ein Problem aufgetreten',
             },
             addedWithPrimary: 'Einige Mitglieder wurden mit ihren primären Anmeldungen hinzugefügt.',
-            invitedBySecondaryLogin: (secondaryLogin: string) => `Hinzugefügt durch sekundären Login ${secondaryLogin}.`,
-            workspaceMembersCount: (count: number) => `Gesamtzahl der Workspace-Mitglieder: ${count}`,
+            invitedBySecondaryLogin: ({secondaryLogin}: SecondaryLoginParams) => `Hinzugefügt durch sekundären Login ${secondaryLogin}.`,
+            workspaceMembersCount: ({count}: WorkspaceMembersCountParams) => `Gesamtzahl der Workspace-Mitglieder: ${count}`,
             importMembers: 'Mitglieder importieren',
-            removeMemberPromptApprover: (approver: string, workspaceOwner: string) =>
+            removeMemberPromptApprover: ({approver, workspaceOwner}: {approver: string; workspaceOwner: string}) =>
                 `Wenn du ${approver} aus diesem Workspace entfernst, ersetzen wir diese Person im Freigabe-Workflow durch ${workspaceOwner}, den/die Workspace-Inhaber:in.`,
-            removeMemberPromptPendingApproval: (memberName: string) =>
+            removeMemberPromptPendingApproval: ({memberName}: {memberName: string}) =>
                 `${memberName} hat ausstehende Spesenabrechnungen zur Genehmigung. Bitte bitten Sie diese Person, sie zu genehmigen, oder übernehmen Sie die Kontrolle über ihre Abrechnungen, bevor Sie sie aus dem Workspace entfernen.`,
             removeMemberPromptReimburser: ({memberName}: {memberName: string}) =>
                 `Sie können ${memberName} nicht aus diesem Workspace entfernen. Bitte legen Sie unter Workflows > Zahlungen ausführen oder nachverfolgen eine*n neue*n Erstattungsverantwortliche*n fest und versuchen Sie es dann erneut.`,
@@ -6300,20 +5631,10 @@ _Für ausführlichere Anweisungen [besuchen Sie unsere Hilfeseite](${CONST.NETSU
                 `Wenn du ${memberName} aus diesem Workspace entfernst, ersetzen wir sie/ihn als technischen Kontakt durch ${workspaceOwner}, den/die Workspace-Inhaber:in.`,
             cannotRemoveUserDueToReport: ({memberName}: {memberName: string}) =>
                 `${memberName} hat einen ausstehenden Bericht in Bearbeitung, zu dem eine Aktion erforderlich ist. Bitte bitten Sie diese Person, die erforderliche Aktion abzuschließen, bevor Sie sie aus dem Workspace entfernen.`,
-            allMembers: 'Alle Mitglieder',
-            admins: 'Workspace-Administratoren',
-            cardAdmins: 'Kartenadministratoren',
-            approvers: 'Genehmigende',
-            auditors: 'Prüfer',
-            emptyRoleFilter: {title: 'Keine Mitglieder entsprechen diesem Filter', subtitle: 'Laden Sie ein Mitglied ein oder ändern Sie den Filter oben.'},
-            configureHRSync: (providerName: string) => `Synchronisierung mit ${providerName} einrichten.`,
-            syncWithHR: (providerName: string) => `Mit ${providerName} synchronisieren`,
-            makeCardAdmin: () => ({one: 'Als Karten-Admin festlegen', other: 'Zu Karten-Admins machen'}),
         },
         card: {
             getStartedIssuing: 'Beginne, indem du deine erste virtuelle oder physische Karte ausstellst.',
             issueCard: 'Karte ausstellen',
-            chooseRule: 'Wählen Sie eine Regel',
             issueNewCard: {
                 whoNeedsCard: 'Wer braucht eine Karte?',
                 inviteNewMember: 'Neues Mitglied einladen',
@@ -6355,27 +5676,21 @@ _Für ausführlichere Anweisungen [besuchen Sie unsere Hilfeseite](${CONST.NETSU
                 enterValidDate: 'Gib ein gültiges Datum ein',
                 expirationDate: 'Ablaufdatum',
                 limitAmount: 'Limitbetrag',
-                setCardRules: 'Kartenregeln festlegen',
-                addSpendRule: 'Ausgaberegel hinzufügen',
-                addExpirationDate: 'Ablaufdatum hinzufügen',
-                addExpirationDateDescription: 'Wenn kein bestimmtes Datum festgelegt ist, läuft die Karte basierend auf dem bestehenden Ablaufdatum der Karte ab',
+                setExpiryOptions: 'Ablaufoptionen festlegen',
+                setExpiryDate: 'Ablaufdatum festlegen',
+                setExpiryDateDescription: 'Die Karte läuft ab, wie auf der Karte angegeben',
                 amount: 'Betrag',
-                copyExisting: 'Vorhandene kopieren',
-                createNew: 'Neu erstellen',
-                spendRulesEmptyStateTitle: 'Keine Regeln zur Auswahl',
-                spendRulesEmptyStateSubtitle: 'Noch keine Regeln. Sie können eine auf dem vorherigen Bildschirm erstellen.',
             },
             deactivateCardModal: {
                 deactivate: 'Deaktivieren',
                 deactivateCard: 'Karte deaktivieren',
                 deactivateConfirmation: 'Wenn du diese Karte deaktivierst, werden alle zukünftigen Transaktionen abgelehnt und dies kann nicht rückgängig gemacht werden.',
             },
-            searchRules: 'Ausgaberegel finden',
         },
         accounting: {
             settings: 'Einstellungen',
             title: 'Verknüpfungen',
-            subtitle: 'Verbinden Sie Ihre Buchhaltungssoftware für eine automatische Synchronisierung.',
+            subtitle: 'Verbinde dein Buchhaltungssystem, um Transaktionen mit deinem Kontenrahmen zu kodieren, Zahlungen automatisch abzugleichen und deine Finanzen synchron zu halten.',
             qbo: 'QuickBooks Online',
             qbd: 'QuickBooks Desktop',
             xero: 'Xero',
@@ -6384,7 +5699,7 @@ _Für ausführlichere Anweisungen [besuchen Sie unsere Hilfeseite](${CONST.NETSU
             sap: 'SAP',
             oracle: 'Oracle',
             microsoftDynamics: 'Microsoft Dynamics',
-            talkYourOnboardingSpecialist: 'Chatten Sie mit Ihrer Kundenbetreuung.',
+            talkYourOnboardingSpecialist: 'Chatte mit deiner Einrichtungsexpertin/deinem Einrichtungsexperten.',
             talkYourAccountManager: 'Chatte mit deiner/deinem Account Manager/in.',
             talkToConcierge: 'Chatte mit Concierge.',
             needAnotherAccounting: 'Benötigen Sie eine weitere Buchhaltungssoftware?',
@@ -6459,8 +5774,6 @@ _Für ausführlichere Anweisungen [besuchen Sie unsere Hilfeseite](${CONST.NETSU
             connectPrompt: ({connectionName}: ConnectionNameParams) =>
                 `Sind Sie sicher, dass Sie ${CONST.POLICY.CONNECTIONS.NAME_USER_FRIENDLY[connectionName] ?? 'diese Buchhaltungsintegration'} verbinden möchten? Dadurch werden alle bestehenden Buchhaltungsverbindungen entfernt.`,
             enterCredentials: 'Gib deine Anmeldedaten ein',
-            reconnect: 'Erneut verbinden',
-            updateCredentials: 'Anmeldedaten aktualisieren',
             claimOffer: {
                 badgeText: 'Angebot verfügbar!',
                 xero: {
@@ -6603,26 +5916,6 @@ _Für ausführlichere Anweisungen [besuchen Sie unsere Hilfeseite](${CONST.NETSU
                             return 'Sage Intacct-Dimensionen werden importiert';
                         case 'intacctImportTitle':
                             return 'Sage Intacct-Daten importieren';
-                        case 'financialForceSyncTitle':
-                            return 'Certinia-Daten werden synchronisiert';
-                        case 'financialForceSyncStep':
-                            return 'Certinia-Verbindung wird synchronisiert';
-                        case 'financialForceSyncCategories':
-                            return 'Kategorien werden importiert';
-                        case 'financialForceSyncTags':
-                            return 'Tags werden importiert';
-                        case 'financialForceSyncVendors':
-                            return 'Lieferanten werden importiert';
-                        case 'financialForceSyncContacts':
-                            return 'Kontakte werden importiert';
-                        case 'financialForceSyncCompanies':
-                            return 'Unternehmen werden importiert';
-                        case 'financialForceSyncUsers':
-                            return 'Benutzer werden importiert';
-                        case 'financialForceSyncDimensions':
-                            return 'Dimensionen werden importiert';
-                        case 'financialForceMarkAsReimbursed':
-                            return 'Berichte werden als erstattet markiert';
                         default: {
                             return `Übersetzung fehlt für Stufe: ${stage}`;
                         }
@@ -6645,18 +5938,14 @@ _Für ausführlichere Anweisungen [besuchen Sie unsere Hilfeseite](${CONST.NETSU
             reconciliationAccount: 'Abstimkonto',
             continuousReconciliation: 'Laufende Abstimmung',
             saveHoursOnReconciliation:
-                'Sparen Sie in jedem Abrechnungszeitraum Stunden bei der Abstimmung, indem Expensify fortlaufend Kontoauszüge und Abrechnungen der Expensify Karte für Sie abstimmt.',
+                'Sparen Sie in jedem Abrechnungszeitraum Stunden bei der Abstimmung, indem Expensify fortlaufend Expensify Card‑Abrechnungen und -Ausgleichsbuchungen automatisch für Sie abstimmt.',
             enableContinuousReconciliation: (accountingAdvancedSettingsLink: string, connectionName: string) =>
                 `<muted-text-label>Um die kontinuierliche Abstimmung zu aktivieren, aktiviere bitte die <a href="${accountingAdvancedSettingsLink}">automatische Synchronisierung</a> für ${connectionName}.</muted-text-label>`,
             chooseReconciliationAccount: {
-                chooseBankAccount: 'Wählen Sie das Bankkonto aus, mit dem Ihre Zahlungen mit der Expensify Karte abgeglichen werden.',
-                settlementAccountReconciliation: (settlementAccountUrl: string, lastFourPAN: string) =>
-                    `Stellen Sie sicher, dass dieses Konto mit Ihrem <a href="${settlementAccountUrl}">Expensify Karte-Abrechnungskonto</a> (endend auf ${lastFourPAN}) übereinstimmt, damit die fortlaufende Abstimmung richtig funktioniert.`,
-                chooseTravelInvoicingBankAccount: 'Wählen Sie das Bankkonto aus, mit dem Ihre Zahlungen aus der Reiseabrechnung abgeglichen werden.',
-                travelInvoicingSettlementAccountReconciliation: (lastFourPAN: string) =>
-                    `Stellen Sie sicher, dass dieses Konto mit Ihrem Abrechnungskonto für Reiseabrechnungen (endet auf ${lastFourPAN}) übereinstimmt, damit die kontinuierliche Abstimmung ordnungsgemäß funktioniert.`,
+                chooseBankAccount: 'Wähle das Bankkonto aus, mit dem deine Expensify Card-Zahlungen abgeglichen werden.',
+                settlementAccountReconciliation: ({settlementAccountUrl, lastFourPAN}: SettlementAccountReconciliationParams) =>
+                    `Vergewissere dich, dass dieses Konto mit deinem <a href="${settlementAccountUrl}">Expensify Card-Abwicklungskonto</a> (endet auf ${lastFourPAN}) übereinstimmt, damit die kontinuierliche Abstimmung ordnungsgemäß funktioniert.`,
             },
-            syncTravelInvoicingSettlements: 'Reiseabrechnungs­abgleiche synchronisieren',
         },
         export: {
             notReadyHeading: 'Nicht bereit zum Export',
@@ -6737,13 +6026,7 @@ _Für ausführlichere Anweisungen [besuchen Sie unsere Hilfeseite](${CONST.NETSU
             errors: {
                 rateNameRequired: 'Ratenname ist erforderlich',
                 existingRateName: 'Ein Distanzsatz mit diesem Namen existiert bereits',
-                nameRequired: 'Name ist erforderlich',
-                startDateMustBeBeforeEndDate: 'Das Startdatum muss vor dem Enddatum liegen',
-                amountRequired: 'Betrag ist erforderlich',
             },
-            amountPerUnit: (unit: string) => `Betrag pro ${unit}`,
-            startDate: 'Startdatum',
-            endDate: 'Enddatum',
         },
         editor: {
             descriptionInputLabel: 'Beschreibung',
@@ -6788,7 +6071,7 @@ _Für ausführlichere Anweisungen [besuchen Sie unsere Hilfeseite](${CONST.NETSU
             updateToUSD: 'Auf USD aktualisieren',
             updateWorkspaceCurrency: 'Arbeitsbereichswährung aktualisieren',
             workspaceCurrencyNotSupported: 'Workspace-Währung wird nicht unterstützt',
-            yourWorkspace: `Dein Arbeitsbereich ist auf eine nicht unterstützte Währung eingestellt. Sieh dir die <a href="${CONST.ENABLE_GLOBAL_REIMBURSEMENT_HELP_URL}">Liste der unterstützten Währungen</a> an.`,
+            yourWorkspace: `Dein Arbeitsbereich ist auf eine nicht unterstützte Währung eingestellt. Sieh dir die <a href="${CONST.CONNECT_A_BUSINESS_BANK_ACCOUNT_HELP_URL}">Liste der unterstützten Währungen</a> an.`,
             chooseAnExisting: 'Wähle ein bestehendes Bankkonto zum Bezahlen von Ausgaben oder füge ein neues hinzu.',
         },
         changeOwner: {
@@ -6825,7 +6108,7 @@ Wenn du die Abrechnung für das gesamte Abonnement übernehmen willst, bitte sie
             hasFailedSettlementsTitle: 'Eigentumsübertragung nicht möglich',
             hasFailedSettlementsButtonText: 'Verstanden',
             hasFailedSettlementsText: (email: string) =>
-                `Sie können die Abrechnung nicht übernehmen, weil ${email} eine überfällige Expensify Karte-Abrechnung hat. Bitte bitten Sie diese Person, sich an concierge@expensify.com zu wenden, um das Problem zu lösen. Danach können Sie die Abrechnung für diesen Arbeitsbereich übernehmen.`,
+                `Sie können die Abrechnung nicht übernehmen, weil ${email} einen überfälligen Expensify Card-Ausgleich hat. Bitte bitten Sie diese Person, sich an concierge@expensify.com zu wenden, um das Problem zu lösen. Danach können Sie die Abrechnung für diesen Workspace übernehmen.`,
             failedToClearBalanceTitle: 'Kontostand konnte nicht ausgeglichen werden',
             failedToClearBalanceButtonText: 'OK',
             failedToClearBalanceText: 'Wir konnten den Saldo nicht ausgleichen. Bitte versuche es später noch einmal.',
@@ -6854,12 +6137,6 @@ Möchten Sie sie wirklich noch einmal exportieren?`,
                 onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
                     `<muted-text>Berichtsfelder sind nur im Control-Tarif verfügbar, ab <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `pro Mitglied und Monat.` : `pro aktivem Mitglied und Monat.`}</muted-text>`,
             },
-            invoiceFields: {
-                title: 'Rechnungsfelder',
-                description: `Mit Rechnungsfeldern kannst du zusätzliche Details auf Rechnungsebene in Rechnungen aufnehmen.`,
-                onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
-                    `<muted-text>Rechnungsfelder sind nur im Control-Tarif verfügbar, ab <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `pro Mitglied und Monat.` : `pro aktivem Mitglied und Monat.`}</muted-text>`,
-            },
             [CONST.POLICY.CONNECTIONS.NAME.NETSUITE]: {
                 title: 'NetSuite',
                 description: `Profitiere von automatischer Synchronisierung und reduziere manuelle Eingaben mit der Expensify + NetSuite-Integration. Gewinne detaillierte Finanzanalysen in Echtzeit mit nativer und benutzerdefinierter Segmentunterstützung, einschließlich Projekt- und Kundenzuordnung.`,
@@ -6878,12 +6155,6 @@ Möchten Sie sie wirklich noch einmal exportieren?`,
                 onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
                     `<muted-text>Unsere QuickBooks Desktop-Integration ist nur im Control-Tarif verfügbar, beginnend bei <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `pro Mitglied und Monat.` : `pro aktivem Mitglied und Monat.`}</muted-text>`,
             },
-            [CONST.POLICY.CONNECTIONS.NAME.CERTINIA]: {
-                title: 'Certinia',
-                description: `Profitiere von automatisierter Synchronisierung und reduziere manuelle Eingaben mit der Expensify + Certinia-Integration. Richte Spesenkodierungsdimensionen und die Steuersynchronisierung auf deine Certinia-Einrichtung aus, um eine klarere finanzielle Übersicht zu erhalten.`,
-                onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
-                    `<muted-text>Unsere Certinia-Integration ist nur im Control-Tarif verfügbar, beginnend bei <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `pro Mitglied und Monat.` : `pro aktivem Mitglied und Monat.`}</muted-text>`,
-            },
             [CONST.UPGRADE_FEATURE_INTRO_MAPPING.approvals.id]: {
                 title: 'Erweiterte Genehmigungen',
                 description: `Wenn du weitere Genehmigungsstufen hinzufügen möchtest – oder einfach sicherstellen willst, dass die höchsten Ausgaben noch einmal geprüft werden – bist du bei uns richtig. Erweiterte Genehmigungen helfen dir, auf jeder Ebene die passenden Kontrollen einzurichten, damit du die Ausgaben deines Teams im Griff behältst.`,
@@ -6961,7 +6232,7 @@ Fordern Sie Spesendetails wie Belege und Beschreibungen an, legen Sie Limits und
                 onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
                     `<muted-text>Entfernungsraten sind im Collect-Tarif verfügbar, beginnend bei <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `pro Mitglied und Monat.` : `pro aktivem Mitglied und Monat.`}</muted-text>`,
             },
-            controlPolicyRoles: {
+            auditor: {
                 title: 'Prüfer',
                 description: 'Prüfer erhalten schreibgeschützten Zugriff auf alle Berichte für vollständige Transparenz und Compliance-Überwachung.',
                 onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
@@ -6978,12 +6249,13 @@ Fordern Sie Spesendetails wie Belege und Beschreibungen an, legen Sie Limits und
                 perActiveMember: 'pro aktivem Mitglied und Monat.',
                 perMember: 'pro Mitglied und Monat.',
             },
-            note: (subscriptionLink: string) => `<muted-text><a href="${subscriptionLink}">Erfahren Sie mehr</a> über unsere Pläne und Preise.</muted-text>`,
+            note: ({subscriptionLink}: WorkspaceUpgradeNoteParams) =>
+                `<muted-text>Upgrade, um auf diese Funktion zuzugreifen, oder <a href="${subscriptionLink}">erfahre mehr</a> über unsere Tarife und Preise.</muted-text>`,
             upgradeToUnlock: 'Diese Funktion freischalten',
             completed: {
                 headline: `Du hast deinen Arbeitsbereich aktualisiert!`,
-                successMessage: (policyName: string, planName: string, subscriptionLink: string) =>
-                    `<centered-text>Du hast ${policyName} erfolgreich auf den ${planName}-Tarif hochgestuft! <a href="${subscriptionLink}">Abonnement ansehen</a> für mehr Details.</centered-text>`,
+                successMessage: ({policyName, subscriptionLink}: UpgradeSuccessMessageParams) =>
+                    `<centered-text>Du hast ${policyName} erfolgreich auf den Control-Tarif hochgestuft! <a href="${subscriptionLink}">Abonnement ansehen</a> für mehr Details.</centered-text>`,
                 categorizeMessage: `Du hast erfolgreich auf den Collect‑Tarif upgegradet. Jetzt kannst du deine Ausgaben kategorisieren!`,
                 travelMessage: `Du hast erfolgreich auf den Collect‑Tarif upgegradet. Jetzt kannst du mit dem Buchen und Verwalten von Reisen beginnen!`,
                 distanceRateMessage: `Du hast erfolgreich auf den Collect-Tarif upgegradet. Jetzt kannst du den Kilometersatz ändern!`,
@@ -7007,87 +6279,25 @@ Fordern Sie Spesendetails wie Belege und Beschreibungen an, legen Sie Limits und
                 upgradeWorkspaceWarningForRestrictedPolicyCreationPrompt:
                     'Ihr Unternehmen hat das Erstellen von Arbeitsbereichen eingeschränkt. Bitte wenden Sie sich an eine*n Admin, um Hilfe zu erhalten.',
             },
-            hr: {
-                title: 'HR-Integrationen',
-                description:
-                    'Verbinden Sie Ihren HR-Anbieter, um Mitarbeitende automatisch zu synchronisieren und Genehmigungsworkflows zu verwalten. Halten Sie Ihr Teamverzeichnis und Ihre Berichtsstruktur ohne manuellen Aufwand auf dem neuesten Stand.',
-                onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
-                    `<muted-text>HR-Integrationen sind nur im Control-Tarif verfügbar, ab <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `pro Mitglied und Monat.` : `pro aktivem Mitglied und Monat.`}</muted-text>`,
-            },
-            approvalSubmit: {
-                title: 'Genehmigungen',
-                description: 'Konfigurieren Sie zentral, an wen alle Mitglieder einreichen, indem Sie Genehmigungen aktivieren.',
-                onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
-                    `<muted-text>Genehmigungen sind in den Collect- und Control-Tarifen verfügbar, beginnend bei <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `pro Mitglied und Monat.` : `pro aktivem Mitglied und Monat.`}</muted-text>`,
-            },
-            companyCardSubmit: {
-                title: 'Firmenkarten',
-                description: `Bringe deine eigene Firmenkarte zu Expensify, um automatische Importe, automatische Kategorisierung, anpassbare Regeln und integrierte Abstimmung zu erhalten.`,
-                onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
-                    `<muted-text>Der Import von Firmenkreditkarten ist in den Collect- und Control-Tarifen verfügbar, beginnend bei <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `pro Mitglied und Monat.` : `pro aktivem Mitglied und Monat.`}</muted-text>`,
-            },
-            travelSubmit: {
-                title: 'Expensify Travel',
-                description: 'Buche weltweit vergünstigte Flüge, Hotels, Autos und Züge direkt in Expensify – mit Duty-of-Care-Berichten und integrierter Spesenverwaltung.',
-                onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
-                    `<muted-text>Expensify Travel ist in den Collect- und Control-Tarifen verfügbar, beginnend bei <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `pro Mitglied und Monat.` : `pro aktivem Mitglied und Monat.`}</muted-text>`,
-            },
-            roles: {
-                title: 'Rollen',
-                description: 'Weise verschiedenen Mitgliedern unterschiedliche Rollen zu, um Sichtbarkeit und Kontrolle bei Bedarf zu erhöhen oder zu verringern.',
-                onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
-                    `<muted-text>Rollen sind in den Collect- und Control-Tarifen verfügbar, beginnend ab <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `pro Mitglied und Monat.` : `pro aktivem Mitglied und Monat.`}</muted-text>`,
-            },
-            payments: {
-                title: 'Zahlungen',
-                description: 'Erstatte Mitarbeitenden direkt von deinem Geschäftskonto.',
-                onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
-                    `<muted-text>Zahlungen sind in den Collect- und Control-Tarifen verfügbar, ab <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `pro Mitglied und Monat.` : `pro aktivem Mitglied und Monat.`}</muted-text>`,
-            },
-            accounting: {
-                title: 'Buchhaltung',
-                description:
-                    'Synchronisiere Kategorien, Tags, Steuersätze und mehr aus deinem Buchhaltungssystem mit Expensify und exportiere Spesenberichte sowie Kartentransaktionen – ganz ohne Tippen (oder Tippfehler)!',
-                onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
-                    `<muted-text>Buchhaltung ist in den Tarifen Collect und Control verfügbar, ab <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `pro Mitglied und Monat.` : `pro aktivem Mitglied und Monat.`}</muted-text>`,
-            },
-            expensifyCard: {
-                title: 'Expensify Card',
-                description:
-                    'Gib Firmenkarten (einschließlich virtueller Karten) direkt von deinem eigenen Bankkonto aus, um in Echtzeit die Ausgaben zu kontrollieren – mit einer untrennbaren Verbindung und bis zu 2 % Cashback!',
-                onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
-                    `<muted-text>Die Expensify Card ist in den Collect- und Control-Tarifen verfügbar, ab <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `pro Mitglied und Monat.` : `pro aktivem Mitglied und Monat.`}</muted-text>`,
-                upgradeButton: 'Upgrade durchführen und aktivieren',
-            },
-            invoicing: {
-                title: 'Rechnungsstellung',
-                description:
-                    'Erstelle, versende und verfolge professionelle Rechnungen – alles in Expensify. Erhalte dein Geld schneller mit integrierten Zahlungen und vollständiger Transparenz in Echtzeit.',
-                onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
-                    `<muted-text>Die Rechnungsstellung ist in den Collect- und Control-Tarifen verfügbar, beginnend ab <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `pro Mitglied und Monat.` : `pro aktivem Mitglied und Monat.`}</muted-text>`,
-            },
         },
         downgrade: {
             commonFeatures: {
-                title: 'Herabstufen auf Collect',
-                note: 'Sie verlieren den Zugriff auf die folgenden Funktionen',
+                title: 'Zum Collect-Tarif wechseln',
+                note: 'Wenn du herabstufst, verlierst du den Zugriff auf diese und weitere Funktionen:',
                 benefits: {
-                    confirm: 'Sie müssen den „Plantyp“ jedes Arbeitsbereichs auf „Collect“ ändern, um den Collect-Tarif zu sichern.',
-                    benefit1: 'NetSuite, Sage Intacct, QuickBooks Desktop, Oracle, Microsoft Dynamics',
-                    benefit2: 'Workday, Certinia',
-                    benefit3: 'SSO/SAML',
-                    benefit4: 'Intelligente Spesenregeln, Tagegelder, Genehmigungen mit mehreren Ebenen, benutzerdefinierte Berichte und Budgetierung',
+                    note: 'Für einen vollständigen Vergleich unserer Tarife sehen Sie sich unsere',
+                    pricingPage: 'Preisseite',
+                    confirm: 'Bist du sicher, dass du ein Downgrade durchführen und deine Konfigurationen entfernen möchtest?',
+                    warning: 'Dies kann nicht rückgängig gemacht werden.',
+                    benefit1: 'Buchhaltungsverbindungen (außer QuickBooks Online und Xero)',
+                    benefit2: 'Intelligente Ausgabenregeln',
+                    benefit3: 'Genehmigungs-Workflows mit mehreren Ebenen',
+                    benefit4: 'Erweiterte Sicherheitskontrollen',
                     headsUp: 'Achtung!',
                     multiWorkspaceNote:
                         'Sie müssen alle Ihre Workspaces herabstufen, bevor Ihre erste monatliche Zahlung fällig ist, um ein Abonnement zum Collect-Tarif zu beginnen. Klicken Sie',
                     selectStep: '> Wähle jeden Workspace aus > ändere den Plantyp in',
-                    benefit1Label: 'ERP-Integrationen',
-                    benefit2Label: 'HR-Integrationen',
-                    benefit3Label: 'Sicherheit',
-                    benefit4Label: 'Erweitert',
-                    important: 'WICHTIG:',
                 },
-                noteAndMore: 'und mehr:',
             },
             completed: {
                 headline: 'Dein Workspace wurde herabgestuft',
@@ -7107,7 +6317,7 @@ Fordern Sie Spesendetails wie Belege und Beschreibungen an, legen Sie Limits und
         restrictedAction: {
             restricted: 'Eingeschränkt',
             actionsAreCurrentlyRestricted: (workspaceName: string) => `Aktionen im Workspace ${workspaceName} sind derzeit eingeschränkt`,
-            workspaceOwnerWillNeedToAddOrUpdatePaymentCard: (workspaceOwnerName: string) =>
+            workspaceOwnerWillNeedToAddOrUpdatePaymentCard: ({workspaceOwnerName}: WorkspaceOwnerWillNeedToAddOrUpdatePaymentCardParams) =>
                 `Der/die Workspace-Inhaber:in ${workspaceOwnerName} muss die hinterlegte Zahlungskarte hinzufügen oder aktualisieren, um neue Workspace-Aktivitäten freizuschalten.`,
             youWillNeedToAddOrUpdatePaymentCard: 'Du musst die hinterlegte Zahlungskarte hinzufügen oder aktualisieren, um neue Aktivitäten im Workspace freizuschalten.',
             addPaymentCardToUnlock: 'Füge eine Zahlungskarte hinzu, um das freizuschalten!',
@@ -7160,18 +6370,16 @@ Fordern Sie Spesendetails wie Belege und Beschreibungen an, legen Sie Limits und
                 eReceiptsHint: `eBelege werden automatisch erstellt [für die meisten Kreditkartentransaktionen in USD](${CONST.DEEP_DIVE_ERECEIPTS}).`,
                 attendeeTracking: 'Teilnehmernachverfolgung',
                 attendeeTrackingHint: 'Verfolge die Pro-Kopf-Kosten für jede Ausgabe.',
-                prohibitedDefaultDescription: 'Markieren Sie Belege mit diesen Positionen zur manuellen Überprüfung.',
+                prohibitedDefaultDescription:
+                    'Markiere alle Belege, auf denen Alkohol, Glücksspiel oder andere eingeschränkte Artikel erscheinen. Ausgaben mit Belegen, auf denen solche Positionen vorkommen, müssen manuell geprüft werden.',
                 prohibitedExpenses: 'Verbotene Ausgaben',
                 alcohol: 'Alkohol',
                 hotelIncidentals: 'Nebenkosten im Hotel',
                 gambling: 'Glücksspiel',
                 tobacco: 'Tabak',
                 adultEntertainment: 'Erwachsenenunterhaltung',
-                giftCard: 'Geschenkkartenkäufe',
-                handwrittenReceipt: 'Handschriftliche Belege',
                 requireCompanyCard: 'Firmenkarten für alle Käufe vorschreiben',
                 requireCompanyCardDescription: 'Kennzeichne alle Barausgaben, einschließlich Kilometer- und Tagegeldspesen.',
-                requireCompanyCardDisabledTooltip: 'Aktiviere Firmenkarten (unter Weitere Funktionen), um dies freizuschalten.',
             },
             expenseReportRules: {
                 title: 'Erweitert',
@@ -7180,8 +6388,8 @@ Fordern Sie Spesendetails wie Belege und Beschreibungen an, legen Sie Limits und
                 preventSelfApprovalsSubtitle: 'Verhindere, dass Workspace-Mitglieder ihre eigenen Spesenabrechnungen genehmigen.',
                 autoApproveCompliantReportsTitle: 'Konforme Berichte automatisch genehmigen',
                 autoApproveCompliantReportsSubtitle: 'Konfiguriere, welche Spesenabrechnungen für die automatische Genehmigung infrage kommen.',
-                autoApproveReportsUnderTitle: 'Berichte automatisch genehmigen, wenn alle Ausgaben unter',
-                autoApproveReportsUnderDescription: 'Vollständig konforme Spesenabrechnungen, bei denen alle Ausgaben unter diesem Betrag liegen, werden automatisch genehmigt.',
+                autoApproveReportsUnderTitle: 'Berichte automatisch genehmigen unter',
+                autoApproveReportsUnderDescription: 'Vollständig konforme Spesenabrechnungen unter diesem Betrag werden automatisch genehmigt.',
                 randomReportAuditTitle: 'Stichprobenprüfung von Berichten',
                 randomReportAuditDescription: 'Verlange, dass einige Berichte manuell genehmigt werden, selbst wenn sie für die automatische Genehmigung infrage kommen.',
                 autoPayApprovedReportsTitle: 'Genehmigte Berichte automatisch bezahlen',
@@ -7194,11 +6402,6 @@ Fordern Sie Spesendetails wie Belege und Beschreibungen an, legen Sie Limits und
                 enableFeatureSubtitle: (featureName: string, moreFeaturesLink?: string) =>
                     `Gehe zu [weitere Funktionen](${moreFeaturesLink}) und aktiviere ${featureName}, um diese Funktion freizuschalten.`,
             },
-            agentsPromoBanner: {
-                title: 'Sie sehen die benötigte Regel nicht? Fügen Sie eine:n Agent:in hinzu',
-                subtitle: 'Fügen Sie komplexe Regeln hinzu und reduzieren Sie manuelle Genehmigungen mit benutzerdefinierten Agenten.',
-                cta: 'Ausprobieren',
-            },
             merchantRules: {
                 title: 'Händler',
                 subtitle: 'Legen Sie Händlerregeln fest, damit Spesen korrekt codiert ankommen und weniger Nachbearbeitung erfordern.',
@@ -7226,10 +6429,9 @@ Fordern Sie Spesendetails wie Belege und Beschreibungen an, legen Sie Limits und
                 matchTypeContains: 'Enthält',
                 matchTypeExact: 'Exakte Übereinstimmung',
                 duplicateRuleTitle: 'Ähnliche Händlerregel existiert bereits',
-                duplicateRulePrompt: (merchantName: string) => `Ihre bestehende Regel für „${merchantName}“ hat Vorrang vor dieser. Trotzdem speichern?`,
+                duplicateRulePrompt: (merchantName: string) => `Möchtest du eine neue Regel für „${merchantName}“ speichern, obwohl bereits eine existierende Regel vorhanden ist?`,
                 saveAnyway: 'Trotzdem speichern',
                 applyToExistingUnsubmittedExpenses: 'Auf bestehende nicht eingereichte Ausgaben anwenden',
-                findRule: 'Händlerregel finden',
             },
             categoryRules: {
                 title: 'Kategorienregeln',
@@ -7267,131 +6469,12 @@ Fordern Sie Spesendetails wie Belege und Beschreibungen an, legen Sie Limits und
                     always: 'Immer detaillierte Belege verlangen',
                 },
                 defaultTaxRate: 'Standardsteuersatz',
-                enableWorkflows: (moreFeaturesLink: string) =>
+                enableWorkflows: ({moreFeaturesLink}: RulesEnableWorkflowsParams) =>
                     `Gehe zu [Weitere Funktionen](${moreFeaturesLink}) und aktiviere Workflows, füge dann Genehmigungen hinzu, um diese Funktion freizuschalten.`,
             },
             customRules: {
                 title: 'Spesenrichtlinie',
                 cardSubtitle: 'Hier ist die Spesenrichtlinie deines Teams hinterlegt, damit alle denselben Stand haben, was abgedeckt ist.',
-                policyDocument: 'Richtliniendokument',
-                policyText: 'Richtlinientext',
-            },
-            spendRules: {
-                title: 'Ausgaben',
-                subtitle: 'Genehmigen oder lehnen Sie Expensify Karte-Transaktionen in Echtzeit ab.',
-                defaultRuleDescription: 'Alle Karten',
-                block: 'Blockieren',
-                defaultRuleTitle: 'Kategorien: Erotikdienstleistungen, Geldautomaten, Glücksspiele, Geldüberweisungen',
-                builtInProtectionModal: {
-                    title: 'Expensify Karten bieten integrierten Schutz – jederzeit',
-                    description: `Expensify lehnt diese Belastungen immer ab:
-
-  • Erwachsenenservices
-  • Geldautomaten
-  • Glücksspiel
-  • Geldüberweisungen
-
-Fügen Sie weitere Ausgabelimits hinzu, um den Cashflow Ihres Unternehmens zu schützen.`,
-                },
-                addSpendRule: 'Ausgaberegel hinzufügen',
-                cardPageTitle: 'Karte',
-                cardsSectionTitle: 'Karten',
-                chooseCards: 'Karten auswählen',
-                saveRule: 'Regel speichern',
-                allow: 'Erlauben',
-                spendRuleSectionTitle: 'Ausgabenregel',
-                restrictionType: 'Beschränkungstyp',
-                restrictionTypeHelpAllow: 'Ausgaben werden genehmigt, wenn sie einem beliebigen Händler oder einer Kategorie entsprechen und einen Höchstbetrag nicht überschreiten.',
-                restrictionTypeHelpBlock: 'Buchungen werden abgelehnt, wenn sie mit einem Händler oder einer Kategorie übereinstimmen oder einen Höchstbetrag überschreiten.',
-                addMerchant: 'Händler hinzufügen',
-                merchantContains: 'Händler enthält',
-                merchantExactlyMatches: 'Händler stimmt exakt überein',
-                noBlockedMerchants: 'Keine blockierten Händler',
-                addMerchantToBlockSpend: 'Händler hinzufügen, um Ausgaben zu blockieren',
-                noAllowedMerchants: 'Keine erlaubten Händler',
-                addMerchantToAllowSpend: 'Fügen Sie einen Händler hinzu, um Ausgaben zu erlauben',
-                matchType: 'Übereinstimmungstyp',
-                matchTypeContains: 'Enthält',
-                matchTypeExact: 'Stimmt genau überein',
-                spendCategory: 'Ausgabenkategorie',
-                maxAmount: 'Maximalbetrag',
-                maxAmountHelp: 'Jede Belastung über diesem Betrag wird abgelehnt, unabhängig von Händler- und Ausgabenkategoriebeschränkungen.',
-                currencyMismatchTitle: 'Währungsinkonsistenz',
-                currencyMismatchPrompt: 'Um einen Höchstbetrag festzulegen, wählen Sie Karten aus, die in derselben Währung abgerechnet werden.',
-                reviewSelectedCards: 'Ausgewählte Karten prüfen',
-                summaryMoreCount: ({summary, count}: {summary: string; count: number}) => (count > 0 ? `${summary}, +${count} weitere` : summary),
-                confirmErrorApplyAtLeastOneSpendRuleToOneCard: 'Wenden Sie mindestens eine Ausgabenregel auf eine Karte an',
-                confirmErrorCardRequired: 'Feld „Karte“ ist erforderlich',
-                confirmErrorApplyAtLeastOneSpendRule: 'Wenden Sie mindestens eine Ausgabenregel an',
-                categories: 'Kategorien',
-                merchants: 'Händler',
-                noAvailableCards: 'Alle Karten haben bereits eine Regel',
-                noAvailableCardsSubtitle: 'Bearbeiten Sie eine vorhandene Kartenregel, um Änderungen vorzunehmen',
-                noCardsIssuedTitle: 'Keine Expensify Karten ausgestellt',
-                noCardsIssuedSubtitle: 'Geben Sie Expensify Karten aus, um Ausgabelimits festzulegen',
-                max: 'Max',
-                categoryOptions: {
-                    [CONST.SPEND_RULES.CATEGORIES.AIRLINES]: 'Fluggesellschaften',
-                    [CONST.SPEND_RULES.CATEGORIES.ALCOHOL_AND_BARS]: 'Alkohol und Bars',
-                    [CONST.SPEND_RULES.CATEGORIES.AMAZON_AND_BOOKSTORES]: 'Amazon und Buchhandlungen',
-                    [CONST.SPEND_RULES.CATEGORIES.AUTOMOTIVE]: 'Automobilindustrie',
-                    [CONST.SPEND_RULES.CATEGORIES.CAR_RENTALS]: 'Mietwagen',
-                    [CONST.SPEND_RULES.CATEGORIES.DINING]: 'Essen',
-                    [CONST.SPEND_RULES.CATEGORIES.FUEL_AND_GAS]: 'Kraftstoff und Gas',
-                    [CONST.SPEND_RULES.CATEGORIES.GOVERNMENT_AND_NON_PROFITS]: 'Regierung und gemeinnützige Organisationen',
-                    [CONST.SPEND_RULES.CATEGORIES.GROCERIES]: 'Lebensmittel',
-                    [CONST.SPEND_RULES.CATEGORIES.GYMS_AND_FITNESS]: 'Fitnessstudios und Fitness',
-                    [CONST.SPEND_RULES.CATEGORIES.HEALTHCARE]: 'Gesundheitswesen',
-                    [CONST.SPEND_RULES.CATEGORIES.HOTELS]: 'Hotels',
-                    [CONST.SPEND_RULES.CATEGORIES.INTERNET_AND_PHONE]: 'Internet und Telefon',
-                    [CONST.SPEND_RULES.CATEGORIES.OFFICE_SUPPLIES]: 'Bürobedarf',
-                    [CONST.SPEND_RULES.CATEGORIES.PARKING_AND_TOLLS]: 'Parken und Mautgebühren',
-                    [CONST.SPEND_RULES.CATEGORIES.PROFESSIONAL_SERVICES]: 'Professionelle Dienstleistungen',
-                    [CONST.SPEND_RULES.CATEGORIES.RETAIL]: 'Einzelhandel',
-                    [CONST.SPEND_RULES.CATEGORIES.SHIPPING_AND_DELIVERY]: 'Versand und Lieferung',
-                    [CONST.SPEND_RULES.CATEGORIES.SOFTWARE]: 'Software',
-                    [CONST.SPEND_RULES.CATEGORIES.TRANSIT_AND_RIDESHARE]: 'Öffentlicher Nahverkehr und Fahrgemeinschaften',
-                    [CONST.SPEND_RULES.CATEGORIES.TRAVEL_AGENCIES]: 'Reisebüros',
-                },
-                editRuleTitle: 'Regel bearbeiten',
-                deleteRule: 'Regel löschen',
-                deleteRuleConfirmation: 'Sind Sie sicher, dass Sie diese Regel löschen möchten?',
-                summaryMerchants: ({
-                    merchants,
-                    hiddenCount,
-                    shownCount,
-                    action,
-                }: {
-                    merchants: string;
-                    hiddenCount: number;
-                    shownCount: number;
-                    action: ValueOf<typeof CONST.SPEND_RULES.ACTION>;
-                }) =>
-                    `${action === CONST.SPEND_RULES.ACTION.BLOCK ? 'Blockiert' : 'Erlaubt'} ${shownCount > 1 ? 'Händler' : 'Händler'}: ${merchants}${hiddenCount > 0 ? `, +${hiddenCount} weitere` : ''}`,
-                summaryCategories: ({
-                    categories,
-                    hiddenCount,
-                    shownCount,
-                    action,
-                }: {
-                    categories: string;
-                    hiddenCount: number;
-                    shownCount: number;
-                    action: ValueOf<typeof CONST.SPEND_RULES.ACTION>;
-                }) =>
-                    `${action === CONST.SPEND_RULES.ACTION.BLOCK ? 'Blockiert' : 'Erlaubt'} ${shownCount > 1 ? 'Kategorien' : 'Kategorie'}: ${categories}${hiddenCount > 0 ? `, +${hiddenCount} weitere` : ''}`,
-            },
-            aiRules: {
-                title: 'KI-Regeln',
-                subtitle: 'Beschreiben Sie flexible Regeln, die ausgeführt werden, wenn Sie sie benötigen',
-                addRule: 'KI-Regel hinzufügen',
-                findRule: 'KI-Regel finden',
-                addRuleTitle: 'Regel hinzufügen',
-                editRuleTitle: 'Regel bearbeiten',
-                deleteRule: 'Regel löschen',
-                deleteRuleConfirmation: 'Sind Sie sicher, dass Sie diese Regel löschen möchten?',
-                describeRuleTitle: 'Beschreiben Sie Ihre Regel',
-                describeRuleSubtitle: 'Beschreiben Sie Ihre Regel und Concierge erstellt sie',
             },
         },
         planTypePage: {
@@ -7404,105 +6487,15 @@ Fügen Sie weitere Ausgabelimits hinzu, um den Cashflow Ihres Unternehmens zu sc
                     label: 'Steuerung',
                     description: 'Für Organisationen mit erweiterten Anforderungen.',
                 },
-                submit2026: {
-                    label: 'Einreichen',
-                    description: 'Für Mitarbeiter, die Ausgaben bei ihrem Arbeitgeber einreichen möchten.',
-                },
             },
-            description: 'Wählen Sie das passende Abo für Sie.',
-            subscriptionLink: 'Mehr erfahren',
+            description: 'Wähle ein passendes Abo für dich. Eine detaillierte Liste der Funktionen und Preise findest du in unserem',
+            subscriptionLink: 'Hilfeseite zu Plantypen und Preisen',
             lockedPlanDescription: ({count, annualSubscriptionEndDate}: WorkspaceLockedPlanTypeParams) => ({
                 one: `Sie haben sich bis zum Ende Ihres Jahresabonnements am ${annualSubscriptionEndDate} zu 1 aktivem Mitglied im Control-Tarif verpflichtet. Sie können ab dem ${annualSubscriptionEndDate} zu einem nutzungsbasierten Abonnement wechseln und in den Collect-Tarif herabstufen, indem Sie die automatische Verlängerung in`,
                 other: `Sie haben sich bis zum Ende Ihres Jahresabonnements am ${annualSubscriptionEndDate} zu ${count} aktiven Mitgliedern im Control-Tarif verpflichtet. Ab dem ${annualSubscriptionEndDate} können Sie durch Deaktivieren der automatischen Verlängerung in ein nutzungsabhängiges Abonnement wechseln und auf den Collect-Tarif herabstufen in`,
             }),
             subscriptions: 'Abonnements',
         },
-        hr: {
-            title: 'Personalwesen',
-            connections: 'Verbindungen',
-            connectionsSubtitle:
-                'Verbinden Sie sich mit Ihrem HR-System, um Mitarbeiterdaten zu synchronisieren, Erstattungen automatisch den richtigen Personen zuzuordnen und die Ausgaben Ihres Teams ohne manuellen Aufwand korrekt zu halten.',
-            subtitle: 'HR-Tools verbinden und Mitarbeitergenehmigungen synchron halten.',
-            connect: 'Verbinden',
-            syncNow: 'Jetzt synchronisieren',
-            disconnect: 'Trennen',
-            disconnectTitle: (providerName: string) => `${providerName} trennen`,
-            disconnectPrompt: (providerName: string) => `Möchten Sie ${providerName} wirklich trennen?`,
-            alreadyConnectedTitle: 'Es kann keine Verbindung zu mehreren HR-Plattformen hergestellt werden',
-            alreadyConnectedPrompt: 'Sie müssen Ihre aktuelle HR-Plattform trennen, bevor Sie eine andere verbinden.',
-            lastSync: (relativeDate: string) => `Zuletzt synchronisiert ${relativeDate}`,
-            syncError: (providerName: string) => `Verbindung zu ${providerName} nicht möglich`,
-            connectionDescription: (providerName: string) => `Verbinden Sie ${providerName}, um Mitarbeitergenehmigungen mit Ihrem Workspace zu synchronisieren.`,
-            approvalMode: 'Genehmigungsmodus',
-            providerApprovalMode: (providerName: string) => `${providerName}-Genehmigungsmodus`,
-            finalApprover: 'Endgültige:r Genehmiger:in',
-            providerFinalApprover: (providerName: string) => `${providerName} Endgenehmigende*r`,
-            notSet: 'Nicht festgelegt',
-            approvalModeDescription: (providerName: string) => `Mitglieder und Manager sind für die Synchronisation mit ${providerName} eingerichtet.`,
-            approvalModeWarningTitle: 'Genehmigungsmodus ändern?',
-            approvalModeWarningPrompt: (providerName: string, helpSiteURL: string) =>
-                `Möchten Sie den Genehmigungsmodus für diesen Workspace wirklich ändern? Erfahren Sie mehr über die verschiedenen ${providerName}-aktivierten Workflow-Modi auf unserer <a href="${helpSiteURL}">Hilfeseite</a>.`,
-            approvalModeWarningConfirm: 'Genehmigungsmodus ändern',
-            approvalModes: {
-                basic: {label: 'Einfache Genehmigung', description: 'Alle Benutzer reichen zur Bearbeitung und Genehmigung bei einer einzigen Person ein.'},
-                manager: {
-                    label: 'Manager-Genehmigung',
-                    description: (providerName: string) => `Mitarbeitende reichen Berichte bei ihrer in ${providerName} hinterlegten direkten Führungskraft ein.`,
-                },
-                custom: {label: 'Benutzerdefinierte Genehmigung', description: 'Ich richte Genehmigungs-Workflows in Expensify manuell ein.'},
-            },
-            syncStageName: ({stage}: SyncStageNameConnectionsParams) => {
-                switch (stage) {
-                    case 'gustoSyncTitle':
-                        return 'Gusto-Mitarbeitende werden synchronisiert';
-                    case 'gustoSyncLoadData':
-                        return 'Daten werden von Gusto geladen';
-                    case 'gustoSyncProvisioning':
-                        return 'Mitarbeiterbereitstellung in Richtlinie';
-                    case 'zenefitsSyncTitle':
-                        return 'TriNet-Mitarbeitende werden synchronisiert';
-                    case 'zenefitsSyncLoadData':
-                        return 'Lade Daten von TriNet';
-                    case 'zenefitsSyncProvisioning':
-                        return 'Mitarbeiterbereitstellung in Richtlinie';
-                    case 'jobDone':
-                        return 'Warten auf das Laden der importierten Daten';
-                    default: {
-                        return `Übersetzung fehlt für Stufe: ${stage}`;
-                    }
-                }
-            },
-            syncResults: {
-                title: (provider: string) => `${provider}-Synchronisierung abgeschlossen`,
-                successTitle: (provider: string) => `Ihre ${provider}-Verbindung wurde erfolgreich synchronisiert!`,
-                added: 'Hinzugefügt',
-                removed: 'Entfernt',
-                skipped: 'Übersprungen',
-                employeeCount: () => ({
-                    one: '1 Mitarbeiter',
-                    other: (count: number) => `${count} Mitarbeitende`,
-                }),
-            },
-            gusto: {
-                title: 'Gusto',
-            },
-            zenefits: {
-                title: 'TriNet',
-            },
-            syncingModalTitle: 'Ihre Verbindung wird synchronisiert',
-            syncingModalDescription: 'Die erste Verbindung kann einige Zeit dauern. Sie werden über alle Fehler benachrichtigt.',
-            syncing: 'Mitarbeitende werden synchronisiert',
-            mergeHR: {
-                completeSetup: 'Einrichtung abschließen',
-                setupIncomplete: (setupLink: string | undefined) =>
-                    `<muted-text-label>Verbunden. ${setupLink ? `<a href="${setupLink}">Einrichtung abschließen</a>` : 'Einrichtung abschließen'} zum Importieren von Mitarbeitenden.</muted-text-label>`,
-                groups: {title: 'Gruppen', description: 'Wählen Sie die Mitarbeitergruppen aus, die Sie mit diesem Workspace synchronisieren möchten'},
-            },
-        },
-        emptyDomain: {
-            title: 'Stärken Sie Ihre Sicherheit mit Domains',
-            subtitle: 'Verlangen Sie, dass Mitglieder in Ihrer Domain sich per Single Sign-On anmelden, schränken Sie das Erstellen von Arbeitsbereichen ein und mehr.',
-        },
     },
     getAssistancePage: {
         title: 'Hilfe erhalten',
@@ -7530,7 +6523,6 @@ Fügen Sie weitere Ausgabelimits hinzu, um den Cashflow Ihres Unternehmens zu sc
             symbols: 'Symbole',
             flags: 'Markierungen',
         },
-        emojiNotSelected: 'Emoji nicht ausgewählt',
     },
     newRoomPage: {
         newRoom: 'Neuer Raum',
@@ -7543,7 +6535,7 @@ Fügen Sie weitere Ausgabelimits hinzu, um den Cashflow Ihres Unternehmens zu sc
         public_announceDescription: 'Jede Person kann diesen Raum finden',
         createRoom: 'Raum erstellen',
         roomAlreadyExistsError: 'Ein Raum mit diesem Namen existiert bereits',
-        roomNameReservedError: (reservedName: string) => `${reservedName} ist ein Standardraum in allen Arbeitsbereichen. Bitte wähle einen anderen Namen.`,
+        roomNameReservedError: ({reservedName}: RoomNameReservedErrorParams) => `${reservedName} ist ein Standardraum in allen Arbeitsbereichen. Bitte wähle einen anderen Namen.`,
         roomNameInvalidError: 'Raumnamen dürfen nur Kleinbuchstaben, Zahlen und Bindestriche enthalten',
         pleaseEnterRoomName: 'Bitte gib einen Raumnamen ein',
         pleaseSelectWorkspace: 'Bitte wähle einen Workspace aus',
@@ -7551,7 +6543,7 @@ Fügen Sie weitere Ausgabelimits hinzu, um den Cashflow Ihres Unternehmens zu sc
             const actor = actorName ? `${actorName} ` : '';
             return isExpenseReport ? `${actor}umbenannt in „${newName}“ (zuvor „${oldName}“)` : `${actor}hat diesen Raum in „${newName}“ umbenannt (zuvor „${oldName}“)`;
         },
-        roomRenamedTo: (newName: string) => `Raum in ${newName} umbenannt`,
+        roomRenamedTo: ({newName}: RoomRenamedToParams) => `Raum in ${newName} umbenannt`,
         social: 'sozial',
         selectAWorkspace: 'Arbeitsbereich auswählen',
         growlMessageOnRenameError: 'Arbeitsbereichsraum kann nicht umbenannt werden. Bitte überprüfe deine Verbindung und versuche es erneut.',
@@ -7593,14 +6585,14 @@ Fügen Sie weitere Ausgabelimits hinzu, um den Cashflow Ihres Unternehmens zu sc
             `${approverName} (${approverEmail}) als Genehmiger:in für das Feld ${field} „${name}“ hinzugefügt`,
         deleteApprovalRule: (approverEmail: string, approverName: string, field: string, name: string) =>
             `${approverName} (${approverEmail}) als Genehmiger:in für das Feld ${field} „${name}“ entfernt`,
-        updateApprovalRule: (field: string, name: string, newApproverEmail: string, newApproverName: string | undefined, oldApproverEmail: string, oldApproverName: string | undefined) => {
+        updateApprovalRule: ({field, name, newApproverEmail, newApproverName, oldApproverEmail, oldApproverName}: UpdatedPolicyApprovalRuleParams) => {
             const formatApprover = (displayName?: string, email?: string) => (displayName ? `${displayName} (${email})` : email);
             return `Genehmigende Person für ${field} „${name}“ auf ${formatApprover(newApproverName, newApproverEmail)} geändert (zuvor ${formatApprover(oldApproverName, oldApproverEmail)})`;
         },
-        addCategory: (categoryName: string) => `Kategorie „${categoryName}“ hinzugefügt`,
-        deleteCategory: (categoryName: string) => `hat die Kategorie „${categoryName}“ entfernt`,
-        updateCategory: (categoryName: string, oldValue: boolean) => `${oldValue ? 'deaktiviert' : 'aktiviert'} die Kategorie „${categoryName}“`,
-        updateCategoryPayrollCode: (categoryName: string, newValue?: string, oldValue?: string) => {
+        addCategory: ({categoryName}: UpdatedPolicyCategoryParams) => `Kategorie „${categoryName}“ hinzugefügt`,
+        deleteCategory: ({categoryName}: UpdatedPolicyCategoryParams) => `hat die Kategorie „${categoryName}“ entfernt`,
+        updateCategory: ({oldValue, categoryName}: UpdatedPolicyCategoryParams) => `${oldValue ? 'deaktiviert' : 'aktiviert'} die Kategorie „${categoryName}“`,
+        updateCategoryPayrollCode: ({oldValue, categoryName, newValue}: UpdatedPolicyCategoryGLCodeParams) => {
             if (!oldValue) {
                 return `die Lohnabrechnungscode-Nummer „${newValue}“ zur Kategorie „${categoryName}“ hinzugefügt`;
             }
@@ -7609,7 +6601,7 @@ Fügen Sie weitere Ausgabelimits hinzu, um den Cashflow Ihres Unternehmens zu sc
             }
             return `hat den Lohnabrechnungscode der Kategorie „${categoryName}“ in „${newValue}“ geändert (zuvor „${oldValue}“)`;
         },
-        updateCategoryGLCode: (categoryName: string, newValue?: string, oldValue?: string) => {
+        updateCategoryGLCode: ({oldValue, categoryName, newValue}: UpdatedPolicyCategoryGLCodeParams) => {
             if (!oldValue) {
                 return `hat den Hauptbuchcode „${newValue}” zur Kategorie „${categoryName}” hinzugefügt`;
             }
@@ -7618,10 +6610,10 @@ Fügen Sie weitere Ausgabelimits hinzu, um den Cashflow Ihres Unternehmens zu sc
             }
             return `hat den SKR-Code der Kategorie „${categoryName}“ in „${newValue}“ geändert (zuvor „${oldValue}“)`;
         },
-        updateAreCommentsRequired: (categoryName: string, oldValue: boolean) => {
+        updateAreCommentsRequired: ({oldValue, categoryName}: UpdatedPolicyCategoryParams) => {
             return `die Beschreibung der Kategorie „${categoryName}“ zu ${!oldValue ? 'erforderlich' : 'nicht erforderlich'} geändert (zuvor ${!oldValue ? 'nicht erforderlich' : 'erforderlich'})`;
         },
-        updateCategoryMaxExpenseAmount: (categoryName: string, newAmount?: string, oldAmount?: string) => {
+        updateCategoryMaxExpenseAmount: ({categoryName, oldAmount, newAmount}: UpdatedPolicyCategoryMaxExpenseAmountParams) => {
             if (newAmount && !oldAmount) {
                 return `hat einen maximalen Betrag von ${newAmount} zur Kategorie „${categoryName}“ hinzugefügt`;
             }
@@ -7630,26 +6622,26 @@ Fügen Sie weitere Ausgabelimits hinzu, um den Cashflow Ihres Unternehmens zu sc
             }
             return `hat den Maximalbetrag der Kategorie „${categoryName}“ auf ${newAmount} geändert (zuvor ${oldAmount})`;
         },
-        updateCategoryExpenseLimitType: (categoryName: string, newValue: string, oldValue?: string) => {
+        updateCategoryExpenseLimitType: ({categoryName, oldValue, newValue}: UpdatedPolicyCategoryExpenseLimitTypeParams) => {
             if (!oldValue) {
                 return `hat den Grenztyp ${newValue} zur Kategorie „${categoryName}“ hinzugefügt`;
             }
             return `hat den Limittyp der Kategorie „${categoryName}“ in ${newValue} geändert (zuvor ${oldValue})`;
         },
-        updateCategoryMaxAmountNoReceipt: (categoryName: string, newValue: string, oldValue?: string) => {
+        updateCategoryMaxAmountNoReceipt: ({categoryName, oldValue, newValue}: UpdatedPolicyCategoryMaxAmountNoReceiptParams) => {
             if (!oldValue) {
                 return `hat die Kategorie „${categoryName}“ aktualisiert, indem Belege auf ${newValue} geändert wurden`;
             }
             return `hat die Kategorie „${categoryName}“ zu ${newValue} geändert (zuvor ${oldValue})`;
         },
-        updateCategoryMaxAmountNoItemizedReceipt: (categoryName: string, oldValue: string | undefined, newValue: string) => {
+        updateCategoryMaxAmountNoItemizedReceipt: ({categoryName, oldValue, newValue}: UpdatedPolicyCategoryMaxAmountNoReceiptParams) => {
             if (!oldValue) {
                 return `hat die Kategorie „${categoryName}“ aktualisiert, indem Einzelpostenbelege in ${newValue} geändert wurden`;
             }
             return `hat die Positionenbelege der Kategorie „${categoryName}“ auf ${newValue} geändert (zuvor ${oldValue})`;
         },
-        setCategoryName: (oldName: string, newName: string) => `hat die Kategorie „${oldName}“ in „${newName}“ umbenannt`,
-        updatedDescriptionHint: (categoryName: string, newValue?: string, oldValue?: string) => {
+        setCategoryName: ({oldName, newName}: UpdatedPolicyCategoryNameParams) => `hat die Kategorie „${oldName}“ in „${newName}“ umbenannt`,
+        updatedDescriptionHint: ({categoryName, oldValue, newValue}: UpdatedPolicyCategoryDescriptionHintTypeParams) => {
             if (!newValue) {
                 return `hat den Beschreibungshinweis „${oldValue}“ aus der Kategorie „${categoryName}“ entfernt`;
             }
@@ -7657,43 +6649,44 @@ Fügen Sie weitere Ausgabelimits hinzu, um den Cashflow Ihres Unternehmens zu sc
                 ? `hat den Beschreibungshinweis „${newValue}“ zur Kategorie „${categoryName}“ hinzugefügt`
                 : `hat den Hinweis zur Beschreibung der Kategorie „${categoryName}“ in „${newValue}“ geändert (zuvor „${oldValue}“)`;
         },
-        updateTagListName: (oldName: string, newName: string) => `hat den Schlagwortlistennamen in „${newName}“ geändert (zuvor „${oldName}“)`,
-        addTag: (tagListName: string, tagName?: string) => `den Tag „${tagName}“ zur Liste „${tagListName}“ hinzugefügt`,
-        updateTagName: (tagListName: string, newName: string, oldName: string) =>
+        updateTagListName: ({oldName, newName}: UpdatedPolicyCategoryNameParams) => `hat den Schlagwortlistennamen in „${newName}“ geändert (zuvor „${oldName}“)`,
+        addTag: ({tagListName, tagName}: UpdatedPolicyTagParams) => `den Tag „${tagName}“ zur Liste „${tagListName}“ hinzugefügt`,
+        updateTagName: ({tagListName, newName, oldName}: UpdatedPolicyTagNameParams) =>
             `hat die Tag-Liste „${tagListName}“ aktualisiert, indem der Tag „${oldName}“ in „${newName}“ geändert wurde`,
-        updateTagEnabled: (tagListName: string, tagName?: string, enabled?: boolean) => `${enabled ? 'aktiviert' : 'deaktiviert'} das Tag „${tagName}“ in der Liste „${tagListName}“`,
-        deleteTag: (tagListName: string, tagName?: string) => `hat das Tag „${tagName}“ aus der Liste „${tagListName}“ entfernt`,
-        deleteMultipleTags: (count?: string, tagListName?: string) => `„${count}“ Tags aus der Liste „${tagListName}“ entfernt`,
-        updateTag: (tagListName: string, newValue: string, tagName: string, updatedField: string, oldValue?: string) => {
+        updateTagEnabled: ({tagListName, tagName, enabled}: UpdatedPolicyTagParams) => `${enabled ? 'aktiviert' : 'deaktiviert'} das Tag „${tagName}“ in der Liste „${tagListName}“`,
+        deleteTag: ({tagListName, tagName}: UpdatedPolicyTagParams) => `hat das Tag „${tagName}“ aus der Liste „${tagListName}“ entfernt`,
+        deleteMultipleTags: ({count, tagListName}: UpdatedPolicyTagParams) => `„${count}“ Tags aus der Liste „${tagListName}“ entfernt`,
+        updateTag: ({tagListName, newValue, tagName, updatedField, oldValue}: UpdatedPolicyTagFieldParams) => {
             if (oldValue) {
                 return `hat das Tag „${tagName}“ in der Liste „${tagListName}“ aktualisiert, indem das Feld ${updatedField} auf „${newValue}“ geändert wurde (zuvor „${oldValue}“)`;
             }
             return `hat das Tag „${tagName}“ in der Liste „${tagListName}“ aktualisiert, indem ein(e) ${updatedField} mit dem Wert „${newValue}“ hinzugefügt wurde`;
         },
-        updateCustomUnit: (customUnitName: string, newValue: string, oldValue: string, updatedField: string) =>
+        updateCustomUnit: ({customUnitName, newValue, oldValue, updatedField}: UpdatePolicyCustomUnitParams) =>
             `hat ${updatedField} der benutzerdefinierten Einheit ${customUnitName} von „${oldValue}“ auf „${newValue}“ geändert`,
-        updateCustomUnitTaxEnabled: (newValue: boolean) => `${newValue ? 'aktiviert' : 'deaktiviert'} Steuerverfolgung bei Entfernungsraten`,
-        addCustomUnitRate: (customUnitName: string, rateName: string) => `${customUnitName}-Satz „${rateName}“ hinzugefügt`,
-        updatedCustomUnitRate: (customUnitName: string, customUnitRateName: string, updatedField: string, newValue: string, oldValue: string) =>
+        updateCustomUnitTaxEnabled: ({newValue}: UpdatePolicyCustomUnitTaxEnabledParams) => `${newValue ? 'aktiviert' : 'deaktiviert'} Steuerverfolgung bei Entfernungsraten`,
+        addCustomUnitRate: ({customUnitName, rateName}: AddOrDeletePolicyCustomUnitRateParams) => `hat einen neuen ${customUnitName}-Satz „${rateName}“ hinzugefügt`,
+        updatedCustomUnitRate: ({customUnitName, customUnitRateName, newValue, oldValue, updatedField}: UpdatedPolicyCustomUnitRateParams) =>
             `hat den Satz des/der ${customUnitName} ${updatedField} „${customUnitRateName}“ auf „${newValue}“ geändert (zuvor „${oldValue}“)`,
-        updatedCustomUnitTaxRateExternalID: (customUnitRateName: string, newValue: string, newTaxPercentage: string, oldTaxPercentage?: string, oldValue?: string) => {
+        updatedCustomUnitTaxRateExternalID: ({customUnitRateName, newValue, newTaxPercentage, oldTaxPercentage, oldValue}: UpdatedPolicyCustomUnitTaxRateExternalIDParams) => {
             if (oldTaxPercentage && oldValue) {
                 return `hat den Steuersatz für den Kilometersatz „${customUnitRateName}“ auf „${newValue} (${newTaxPercentage})“ geändert (zuvor „${oldValue} (${oldTaxPercentage})“)`;
             }
             return `die Steuerquote „${newValue} (${newTaxPercentage})“ zum Entfernungssatz „${customUnitRateName}“ hinzugefügt`;
         },
-        updatedCustomUnitTaxClaimablePercentage: (customUnitRateName: string, newValue: number, oldValue?: number) => {
+        updatedCustomUnitTaxClaimablePercentage: ({customUnitRateName, newValue, oldValue}: UpdatedPolicyCustomUnitTaxClaimablePercentageParams) => {
             if (oldValue) {
                 return `hat den erstattungsfähigen Steueranteil im Distanzsatz „${customUnitRateName}“ auf „${newValue}“ geändert (zuvor „${oldValue}“)`;
             }
             return `eine steuerlich rückforderbare Komponente von „${newValue}“ zum Distanzsatz „${customUnitRateName}“ hinzugefügt`;
         },
-        updatedCustomUnitRateName: (customUnitName: string, oldValue: string, newValue: string) => `hat den ${customUnitName}-Satz „${oldValue}“ in „${newValue}“ umbenannt`,
-        updatedCustomUnitRateEnabled: (customUnitName: string, customUnitRateName: string, newValue: boolean) => {
+        updatedCustomUnitRateEnabled: ({customUnitName, customUnitRateName, newValue}: UpdatedPolicyCustomUnitRateEnabledParams) => {
             return `${newValue ? 'aktiviert' : 'deaktiviert'} den ${customUnitName}-Satz „${customUnitRateName}“`;
         },
-        deleteCustomUnitRate: (customUnitName: string, rateName: string) => `hat den „${customUnitName}“-Satz „${rateName}“ entfernt`,
-        updateReportFieldDefaultValue: (defaultValue?: string, fieldName?: string) => `Standardwert des Berichts­feldes „${fieldName}“ auf „${defaultValue}“ festlegen`,
+        deleteCustomUnitRate: ({customUnitName, rateName}: AddOrDeletePolicyCustomUnitRateParams) => `hat den „${customUnitName}“-Satz „${rateName}“ entfernt`,
+        addedReportField: ({fieldType, fieldName}: AddedOrDeletedPolicyReportFieldParams) => `${fieldType}-Berichtsfenster „${fieldName}“ hinzugefügt`,
+        updateReportFieldDefaultValue: ({defaultValue, fieldName}: UpdatedPolicyReportFieldDefaultValueParams) =>
+            `Standardwert des Berichts­feldes „${fieldName}“ auf „${defaultValue}“ festlegen`,
         addedReportFieldOption: (fieldName: string, optionName: string) => `die Option „${optionName}“ zum Berichtsfeld „${fieldName}“ hinzugefügt`,
         removedReportFieldOption: (fieldName: string, optionName: string) => `hat die Option „${optionName}“ aus dem Berichtsfeld „${fieldName}“ entfernt`,
         updateReportFieldOptionDisabled: (fieldName: string, optionName: string, optionEnabled: boolean) =>
@@ -7705,20 +6698,22 @@ Fügen Sie weitere Ausgabelimits hinzu, um den Cashflow Ihres Unternehmens zu sc
             return `${allEnabled ? 'aktiviert' : 'deaktiviert'} die Option „${optionName}“ für das Berichtsfeld „${fieldName}“, wodurch alle Optionen ${allEnabled ? 'aktiviert' : 'deaktiviert'}`;
         },
         deleteReportField: ({fieldType, fieldName}: {fieldType: string; fieldName?: string}) => `${fieldType}-Berichts-Feld „${fieldName}“ entfernt`,
-        preventSelfApproval: (oldValue: string, newValue: string) =>
+        preventSelfApproval: ({oldValue, newValue}: UpdatedPolicyPreventSelfApprovalParams) =>
             `aktualisierte „Selbstgenehmigung verhindern“ auf „${newValue === 'true' ? 'Aktiviert' : 'Deaktiviert'}“ (zuvor „${oldValue === 'true' ? 'Aktiviert' : 'Deaktiviert'}“)`,
-        updateMonthlyOffset: (oldValue: string, newValue: string) => {
+        updateMonthlyOffset: ({oldValue, newValue}: UpdatedPolicyFieldWithNewAndOldValueParams) => {
             if (!oldValue) {
                 return `monatliches Berichtsabgabedatum auf „${newValue}“ festlegen`;
             }
             return `hat das Einreichungsdatum des Monatsberichts auf „${newValue}“ aktualisiert (zuvor „${oldValue}“)`;
         },
-        updateDefaultBillable: (oldValue: string, newValue: string) => `„Spesen an Kunden weiterberechnen“ wurde auf „${newValue}“ aktualisiert (zuvor „${oldValue}“)`,
-        changedCustomReportNameFormula: (oldValue: string, newValue: string) => `hat die Formel für den benutzerdefinierten Berichtsnamen in „${newValue}“ geändert (zuvor „${oldValue}“)`,
+        updateDefaultBillable: ({oldValue, newValue}: UpdatedPolicyFieldWithNewAndOldValueParams) =>
+            `„Spesen an Kunden weiterberechnen“ wurde auf „${newValue}“ aktualisiert (zuvor „${oldValue}“)`,
+        changedCustomReportNameFormula: ({newValue, oldValue}: UpdatedPolicyFieldWithNewAndOldValueParams) =>
+            `hat die Formel für den benutzerdefinierten Berichtsnamen in „${newValue}“ geändert (zuvor „${oldValue}“)`,
         renamedWorkspaceNameAction: (oldName: string, newName: string) => `hat den Namen dieses Workspaces zu „${newName}“ geändert (zuvor „${oldName}“)`,
-        updateDefaultReimbursable: (oldValue: string, newValue: string) => `„Standard für Barausgaben“ auf „${newValue}“ aktualisiert (zuvor „${oldValue}“)`,
-        updateDefaultTitleEnforced: (value: boolean) => `„Standard-Berichtstitel erzwingen“ aktiviert ${value ? 'an' : 'aus'}`,
-        updateWorkspaceDescription: (newDescription: string, oldDescription: string) =>
+        updateDefaultReimbursable: ({oldValue, newValue}: UpdatedPolicyFieldWithNewAndOldValueParams) => `„Standard für Barausgaben“ auf „${newValue}“ aktualisiert (zuvor „${oldValue}“)`,
+        updateDefaultTitleEnforced: ({value}: UpdatedPolicyFieldWithValueParams) => `„Standard-Berichtstitel erzwingen“ aktiviert ${value ? 'an' : 'aus'}`,
+        updateWorkspaceDescription: ({newDescription, oldDescription}: UpdatedPolicyDescriptionParams) =>
             !oldDescription
                 ? `setze die Beschreibung dieses Arbeitsbereichs auf „${newDescription}“`
                 : `hat die Beschreibung dieses Arbeitsbereichs auf „${newDescription}“ aktualisiert (zuvor „${oldDescription}“)`,
@@ -7738,15 +6733,17 @@ Fügen Sie weitere Ausgabelimits hinzu, um den Cashflow Ihres Unternehmens zu sc
         },
         demotedFromWorkspace: (policyName: string, oldRole: string) =>
             `hat Ihre Rolle in ${policyName} von ${oldRole} zu Nutzer geändert. Sie wurden aus allen Einreicher-Spesen-Chats entfernt, außer aus Ihrem eigenen.`,
-        updatedWorkspaceCurrencyAction: (oldCurrency: string, newCurrency: string) => `Standardwährung auf ${newCurrency} aktualisiert (zuvor ${oldCurrency})`,
-        updatedWorkspaceFrequencyAction: (oldFrequency: string, newFrequency: string) => `die automatische Berichtshäufigkeit auf „${newFrequency}“ aktualisiert (zuvor „${oldFrequency}“)`,
+        updatedWorkspaceCurrencyAction: ({oldCurrency, newCurrency}: UpdatedPolicyCurrencyParams) => `Standardwährung auf ${newCurrency} aktualisiert (zuvor ${oldCurrency})`,
+        updatedWorkspaceFrequencyAction: ({oldFrequency, newFrequency}: UpdatedPolicyFrequencyParams) =>
+            `die automatische Berichtshäufigkeit auf „${newFrequency}“ aktualisiert (zuvor „${oldFrequency}“)`,
         updateApprovalMode: ({newValue, oldValue}: ChangeFieldParams) => `hat den Genehmigungsmodus auf „${newValue}“ aktualisiert (zuvor „${oldValue}“)`,
         upgradedWorkspace: 'hat diesen Workspace auf den Control-Tarif hochgestuft',
         forcedCorporateUpgrade: `Dieser Workspace wurde auf den Control-Tarif hochgestuft. Klicken Sie <a href="${CONST.COLLECT_UPGRADE_HELP_URL}">hier</a> für weitere Informationen.`,
         downgradedWorkspace: 'hat diesen Workspace auf den Collect-Tarif heruntergestuft',
-        updatedAuditRate: (oldAuditRate: number, newAuditRate: number) =>
+        updatedAuditRate: ({oldAuditRate, newAuditRate}: UpdatedPolicyAuditRateParams) =>
             `hat die Rate der Berichte, die zufällig zur manuellen Genehmigung zugewiesen werden, auf ${Math.round(newAuditRate * 100)}% geändert (zuvor ${Math.round(oldAuditRate * 100)}%)`,
-        updatedManualApprovalThreshold: (oldLimit: string, newLimit: string) => `hat das manuelle Genehmigungslimit für alle Ausgaben auf ${newLimit} geändert (zuvor ${oldLimit})`,
+        updatedManualApprovalThreshold: ({oldLimit, newLimit}: UpdatedPolicyManualApprovalThresholdParams) =>
+            `hat das manuelle Genehmigungslimit für alle Ausgaben auf ${newLimit} geändert (zuvor ${oldLimit})`,
         updatedFeatureEnabled: ({enabled, featureName}: {enabled: boolean; featureName: string}) => {
             switch (featureName) {
                 case 'categories':
@@ -7754,25 +6751,23 @@ Fügen Sie weitere Ausgabelimits hinzu, um den Cashflow Ihres Unternehmens zu sc
                 case 'tags':
                     return `${enabled ? 'aktiviert' : 'deaktiviert'} Tags`;
                 case 'workflows':
-                    return `${enabled ? 'aktiviert' : 'deaktiviert'}-Workflows`;
+                    return `${enabled ? 'aktiviert' : 'deaktiviert'} Workflows`;
                 case 'distance rates':
                     return `${enabled ? 'aktiviert' : 'deaktiviert'} Entfernungssätze`;
                 case 'accounting':
                     return `${enabled ? 'aktiviert' : 'deaktiviert'} Buchhaltung`;
                 case 'Expensify Cards':
-                    return `${enabled ? 'aktiviert' : 'deaktiviert'} Expensify Karten`;
-                case 'travel invoicing':
-                    return `${enabled ? 'aktiviert' : 'deaktiviert'} Reiserechnungsstellung`;
+                    return `${enabled ? 'aktiviert' : 'deaktiviert'} Expensify Cards`;
                 case 'company cards':
                     return `${enabled ? 'aktiviert' : 'deaktiviert'} Firmenkarten`;
                 case 'invoicing':
-                    return `${enabled ? 'aktiviert' : 'deaktiviert'} Rechnungsstellung`;
+                    return `${enabled ? 'aktiviert' : 'deaktiviert'}-Rechnungsstellung`;
                 case 'per diem':
                     return `${enabled ? 'aktiviert' : 'deaktiviert'} Tagegeld`;
                 case 'receipt partners':
                     return `${enabled ? 'aktiviert' : 'deaktiviert'} Belegpartner`;
                 case 'rules':
-                    return `${enabled ? 'aktiviert' : 'deaktiviert'}-Regeln`;
+                    return `${enabled ? 'aktiviert' : 'deaktiviert'} Regeln`;
                 case 'tax tracking':
                     return `${enabled ? 'aktiviert' : 'deaktiviert'} Steuerverfolgung`;
                 default:
@@ -7845,17 +6840,14 @@ Fügen Sie weitere Ausgabelimits hinzu, um den Cashflow Ihres Unternehmens zu sc
             oldValue ? `hat den Firmennamen der Rechnung in „${newValue}“ geändert (zuvor „${oldValue}“)` : `setze den Rechnungsfirmennamen auf „${newValue}“`,
         changedInvoiceCompanyWebsite: ({newValue, oldValue}: {newValue: string; oldValue?: string}) =>
             oldValue ? `hat die Unternehmenswebsite der Rechnung in „${newValue}“ geändert (zuvor „${oldValue}“)` : `Rechnungsunternehmens-Website auf „${newValue}“ festlegen`,
-        changedReimburser: (newReimburser: string, previousReimburser?: string) =>
+        changedReimburser: ({newReimburser, previousReimburser}: UpdatedPolicyReimburserParams) =>
             previousReimburser
                 ? `hat die/den autorisierte:n Zahler:in in „${newReimburser}“ geändert (zuvor „${previousReimburser}“)`
                 : `den/die autorisierte/n Zahler/in in „${newReimburser}“ geändert`,
-        updateReimbursementEnabled: (enabled: boolean) => `${enabled ? 'aktiviert' : 'deaktiviert'} Rückerstattungen`,
-        updateCustomTaxName: (oldName: string, newName: string) => `benutzerdefinierten Steuernamen in „${newName}" geändert (zuvor „${oldName}")`,
-        updateCurrencyDefaultTax: (oldName: string, newName: string) => `Standard-Steuerbetrag der Workspace-Währung auf „${newName}" geändert (zuvor „${oldName}")`,
-        updateForeignCurrencyDefaultTax: (oldName: string, newName: string) => `den Standardsteuersatz für Fremdwährungen in „${newName}" geändert (zuvor „${oldName}")`,
-        addTax: (taxName: string) => `die Steuer „${taxName}" hinzugefügt`,
-        deleteTax: (taxName: string) => `hat die Steuer „${taxName}“ entfernt`,
-        updateTax: (oldValue?: string | boolean | number, taxName?: string, updatedField?: string, newValue?: string | boolean | number) => {
+        updateReimbursementEnabled: ({enabled}: UpdatedPolicyReimbursementEnabledParams) => `${enabled ? 'aktiviert' : 'deaktiviert'} Rückerstattungen`,
+        addTax: ({taxName}: UpdatedPolicyTaxParams) => `hat die Steuer „${taxName}“ hinzugefügt`,
+        deleteTax: ({taxName}: UpdatedPolicyTaxParams) => `hat die Steuer „${taxName}“ entfernt`,
+        updateTax: ({oldValue, taxName, updatedField, newValue}: UpdatedPolicyTaxParams) => {
             if (!updatedField) {
                 return '';
             }
@@ -7877,30 +6869,28 @@ Fügen Sie weitere Ausgabelimits hinzu, um den Cashflow Ihres Unternehmens zu sc
                 }
             }
         },
-        setReceiptRequiredAmount: (newValue: string) => `Belegpflichtigen Betrag auf „${newValue}“ festlegen`,
-        changedReceiptRequiredAmount: (oldValue: string, newValue: string) => `Belegpflichtbetrag auf „${newValue}“ geändert (zuvor „${oldValue}“)`,
-        removedReceiptRequiredAmount: (oldValue: string) => `Belegpflichtigen Betrag entfernt (zuvor „${oldValue}”)`,
-        setItemizedReceiptRequiredAmount: (newValue: string) => `Betrag für Pflicht zur Einzelauflistung auf „${newValue}” festgelegt`,
-        changedItemizedReceiptRequiredAmount: (oldValue: string, newValue: string) => `erforderlichen Betrag des aufgeschlüsselten Belegs auf „${newValue}” geändert (zuvor „${oldValue}”)`,
-        removedItemizedReceiptRequiredAmount: (oldValue: string) => `Betrag für obligatorische Einzelpostenbelege entfernt (zuvor „${oldValue}”)`,
-        setMaxExpenseAmount: (newValue: string) => `maximalen Ausgabenbetrag auf „${newValue}“ festlegen`,
-        changedMaxExpenseAmount: (oldValue: string, newValue: string) => `hat den maximalen Ausgabenbetrag auf „${newValue}“ geändert (zuvor „${oldValue}“)`,
-        removedMaxExpenseAmount: (oldValue: string) => `maximale Ausgabenhöhe entfernt (zuvor „${oldValue}“)`,
-        setMaxExpenseAge: (newValue: string) => `maximales Ausgabenalter auf „${newValue}“ Tage festlegen`,
-        changedMaxExpenseAge: (oldValue: string, newValue: string) => `maximales Ausgabenalter auf „${newValue}“ Tage geändert (zuvor „${oldValue}“)`,
-        updateCategories: (count: number) => `${count} Kategorien aktualisiert`,
-        updateTagList: (tagListName: string) => `Tags in der Liste „${tagListName}“ aktualisiert`,
-        updateTagListRequired: (tagListsName: string, isRequired: boolean) => `Tag-Liste „${tagListsName}“ in ${isRequired ? 'erforderlich' : 'nicht erforderlich'} geändert`,
+        setReceiptRequiredAmount: ({newValue}: UpdatedPolicyFieldWithNewAndOldValueParams) => `Belegpflichtigen Betrag auf „${newValue}“ festlegen`,
+        changedReceiptRequiredAmount: ({oldValue, newValue}: UpdatedPolicyFieldWithNewAndOldValueParams) => `Belegpflichtbetrag auf „${newValue}“ geändert (zuvor „${oldValue}“)`,
+        removedReceiptRequiredAmount: ({oldValue}: UpdatedPolicyFieldWithNewAndOldValueParams) => `Belegpflichtigen Betrag entfernt (zuvor „${oldValue}“)`,
+        setMaxExpenseAmount: ({newValue}: UpdatedPolicyFieldWithNewAndOldValueParams) => `maximalen Ausgabenbetrag auf „${newValue}“ festlegen`,
+        changedMaxExpenseAmount: ({oldValue, newValue}: UpdatedPolicyFieldWithNewAndOldValueParams) => `hat den maximalen Ausgabenbetrag auf „${newValue}“ geändert (zuvor „${oldValue}“)`,
+        removedMaxExpenseAmount: ({oldValue}: UpdatedPolicyFieldWithNewAndOldValueParams) => `maximale Ausgabenhöhe entfernt (zuvor „${oldValue}“)`,
+        setMaxExpenseAge: ({newValue}: UpdatedPolicyFieldWithNewAndOldValueParams) => `maximales Ausgabenalter auf „${newValue}“ Tage festlegen`,
+        changedMaxExpenseAge: ({oldValue, newValue}: UpdatedPolicyFieldWithNewAndOldValueParams) => `maximales Ausgabenalter auf „${newValue}“ Tage geändert (zuvor „${oldValue}“)`,
+        updateCategories: ({count}: UpdatedPolicyCategoriesParams) => `${count} Kategorien aktualisiert`,
+        updateTagList: ({tagListName}: UpdatedPolicyTagListParams) => `Tags in der Liste „${tagListName}“ aktualisiert`,
+        updateTagListRequired: ({tagListsName, isRequired}: UpdatedPolicyTagListRequiredParams) =>
+            `Tag-Liste „${tagListsName}“ in ${isRequired ? 'erforderlich' : 'nicht erforderlich'} geändert`,
         importTags: 'Tags aus einer Tabelle importiert',
         deletedAllTags: 'alle Tags gelöscht',
-        updateCustomUnitDefaultCategory: (customUnitName: string, newValue?: string, oldValue?: string) =>
+        updateCustomUnitDefaultCategory: ({customUnitName, newValue, oldValue}: UpdatePolicyCustomUnitDefaultCategoryParams) =>
             `hat die Standardkategorie für ${customUnitName} in „${newValue}“ geändert ${oldValue ? `(zuvor „${oldValue}“)` : ''}`,
-        importCustomUnitRates: (customUnitName: string) => `importierte Preise für benutzerdefinierte Einheit „${customUnitName}“`,
-        updateCustomUnitSubRate: (customUnitName: string, customUnitRateName: string, customUnitSubRateName: string, oldValue: string, newValue: string, updatedField: string) =>
+        importCustomUnitRates: ({customUnitName}: ImportPolicyCustomUnitRatesParams) => `importierte Preise für benutzerdefinierte Einheit „${customUnitName}“`,
+        updateCustomUnitSubRate: ({customUnitName, customUnitRateName, customUnitSubRateName, oldValue, newValue, updatedField}: UpdatedPolicyCustomUnitSubRateParams) =>
             `hat Tarif „${customUnitName}“ mit Satz „${customUnitRateName}“ und Untersatz „${customUnitSubRateName}“ ${updatedField} auf „${newValue}“ geändert (zuvor „${oldValue}“)`,
-        removedCustomUnitSubRate: (customUnitName: string, customUnitRateName: string, removedSubRateName: string) =>
+        removedCustomUnitSubRate: ({customUnitName, customUnitRateName, removedSubRateName}: RemovedPolicyCustomUnitSubRateParams) =>
             `entfernte „${customUnitName}“-Rate „${customUnitRateName}“ Unterrate „${removedSubRateName}“`,
-        addBudget: (frequency: string, entityName: string, entityType: string, shared?: string, individual?: string, notificationThreshold?: number) => {
+        addBudget: ({frequency, entityName, entityType, shared, individual, notificationThreshold}: AddBudgetParams) => {
             const thresholdSuffix = typeof notificationThreshold === 'number' ? `mit Benachrichtigungsschwelle von „${notificationThreshold}%“` : '';
             if (typeof shared !== 'undefined' && typeof individual !== 'undefined') {
                 return `${frequency} individuelles Budget „${individual}“ und ${frequency} gemeinsames Budget „${shared}“${thresholdSuffix} zum/zur ${entityType} „${entityName}“ hinzugefügt`;
@@ -7910,18 +6900,18 @@ Fügen Sie weitere Ausgabelimits hinzu, um den Cashflow Ihres Unternehmens zu sc
             }
             return `${frequency} gemeinsames Budget „${shared}“${thresholdSuffix} zum ${entityType} „${entityName}“ hinzugefügt`;
         },
-        updateBudget: (
-            entityType: string,
-            entityName: string,
-            oldFrequency?: string,
-            newFrequency?: string,
-            oldIndividual?: string,
-            newIndividual?: string,
-            oldShared?: string,
-            newShared?: string,
-            oldNotificationThreshold?: number,
-            newNotificationThreshold?: number,
-        ) => {
+        updateBudget: ({
+            entityType,
+            entityName,
+            oldFrequency,
+            newFrequency,
+            oldIndividual,
+            newIndividual,
+            oldShared,
+            newShared,
+            oldNotificationThreshold,
+            newNotificationThreshold,
+        }: UpdatedBudgetParams) => {
             const frequencyChanged = !!(newFrequency && oldFrequency !== newFrequency);
             const sharedChanged = !!(newShared && oldShared !== newShared);
             const individualChanged = !!(newIndividual && oldIndividual !== newIndividual);
@@ -7956,7 +6946,7 @@ Fügen Sie weitere Ausgabelimits hinzu, um den Cashflow Ihres Unternehmens zu sc
             }
             return `Budget für ${entityType} „${entityName}“ aktualisiert: ${changesList.join('; ')}`;
         },
-        deleteBudget: (entityType: string, entityName: string, frequency?: string, individual?: string, shared?: string, notificationThreshold?: number) => {
+        deleteBudget: ({entityType, entityName, frequency, individual, shared, notificationThreshold}: DeleteBudgetParams) => {
             const thresholdSuffix = typeof notificationThreshold === 'number' ? `mit Benachrichtigungsschwelle von „${notificationThreshold}%“` : '';
             if (shared && individual) {
                 return `hat ${frequency} gemeinsames Budget von „${shared}“ und individuelles Budget von „${individual}“${thresholdSuffix} aus dem/der ${entityType} „${entityName}“ entfernt`;
@@ -7969,124 +6959,50 @@ Fügen Sie weitere Ausgabelimits hinzu, um den Cashflow Ihres Unternehmens zu sc
             }
             return `Budget aus dem ${entityType} „${entityName}“ entfernt`;
         },
-        updatedTimeEnabled: (enabled?: boolean) => {
+        updatedTimeEnabled: ({enabled}: UpdatedPolicyTimeEnabledParams) => {
             return `${enabled ? 'aktiviert' : 'deaktiviert'} Zeiterfassung`;
         },
-        updatedTimeRate: (newRate?: string, oldRate?: string) => {
+        updatedTimeRate: ({newRate, oldRate}: UpdatedPolicyTimeRateParams) => {
             return `Stundensatz auf „${newRate}“ geändert (zuvor „${oldRate}“)`;
         },
         addedProhibitedExpense: ({prohibitedExpense}: {prohibitedExpense: string}) => `„${prohibitedExpense}“ zu verbotenen Ausgaben hinzugefügt`,
         removedProhibitedExpense: ({prohibitedExpense}: {prohibitedExpense: string}) => `„${prohibitedExpense}“ aus verbotenen Ausgaben entfernt`,
-        updatedReimbursementChoice: (newReimbursementChoice: string, oldReimbursementChoice: string) =>
+        updatedReimbursementChoice: ({newReimbursementChoice, oldReimbursementChoice}: UpdatedPolicyReimbursementChoiceParams) =>
             `Erstattungmethode zu „${newReimbursementChoice}“ geändert (vorher „${oldReimbursementChoice}“)`,
         setAutoJoin: ({enabled}: {enabled: boolean}) => `${enabled ? 'aktiviert' : 'deaktiviert'} Vorabgenehmigung von Arbeitsbereich-Beitrittsanfragen`,
-        updatedDefaultTitle: (newDefaultTitle: string, oldDefaultTitle: string) => `benutzerdefinierte Berichtstitelformel in „${newDefaultTitle}“ geändert (zuvor „${oldDefaultTitle}“)`,
-        updatedOwnership: (oldOwnerEmail: string, oldOwnerName: string, policyName: string) => `hat die Inhaberschaft von ${policyName} von ${oldOwnerName} (${oldOwnerEmail}) übernommen`,
-        updatedAutoHarvesting: (enabled: boolean) => `${enabled ? 'aktiviert' : 'deaktiviert'} geplante Einreichung`,
-        updatedIndividualBudgetNotification: (
-            budgetAmount: string,
-            budgetFrequency: string,
-            budgetName: string,
-            budgetTypeForNotificationMessage: string,
-            thresholdPercentage: number,
-            totalSpend: number,
-            unsubmittedSpend: number,
-            awaitingApprovalSpend: number,
-            approvedReimbursedClosedSpend: number,
-            summaryLink?: string,
-            userEmail?: string,
-        ) =>
+        updatedDefaultTitle: ({newDefaultTitle, oldDefaultTitle}: UpdatedPolicyDefaultTitleParams) =>
+            `benutzerdefinierte Berichtstitelformel in „${newDefaultTitle}“ geändert (zuvor „${oldDefaultTitle}“)`,
+        updatedOwnership: ({oldOwnerEmail, oldOwnerName, policyName}: UpdatedPolicyOwnershipParams) =>
+            `hat die Inhaberschaft von ${policyName} von ${oldOwnerName} (${oldOwnerEmail}) übernommen`,
+        updatedAutoHarvesting: ({enabled}: UpdatedPolicyAutoHarvestingParams) => `${enabled ? 'aktiviert' : 'deaktiviert'} geplante Einreichung`,
+        updatedIndividualBudgetNotification: ({
+            budgetAmount,
+            budgetFrequency,
+            budgetName,
+            budgetTypeForNotificationMessage,
+            summaryLink,
+            thresholdPercentage,
+            totalSpend,
+            unsubmittedSpend,
+            userEmail,
+            awaitingApprovalSpend,
+            approvedReimbursedClosedSpend,
+        }: UpdatedPolicyBudgetNotificationParams) =>
             `Achtung! Dieser Workspace hat ein ${budgetFrequency}-Budget von „${budgetAmount}“ für den/die/das ${budgetTypeForNotificationMessage} „${budgetName}“. ${userEmail} liegt derzeit bei ${approvedReimbursedClosedSpend}, was über ${thresholdPercentage}% des Budgets liegt. Außerdem warten ${awaitingApprovalSpend} noch auf Genehmigung und ${unsubmittedSpend} wurden noch nicht eingereicht, für insgesamt ${totalSpend}.${summaryLink ? `<a href="${summaryLink}">Hier ist ein Bericht</a> mit all diesen Ausgaben für Ihre Unterlagen!` : ''}`,
-        updatedSharedBudgetNotification: (
-            budgetAmount: string,
-            budgetFrequency: string,
-            budgetName: string,
-            budgetTypeForNotificationMessage: string,
-            summaryLink: string | undefined,
-            thresholdPercentage: number,
-            totalSpend: number,
-            unsubmittedSpend: number,
-            awaitingApprovalSpend: number,
-            approvedReimbursedClosedSpend: number,
-        ) =>
+        updatedSharedBudgetNotification: ({
+            budgetAmount,
+            budgetFrequency,
+            budgetName,
+            budgetTypeForNotificationMessage,
+            summaryLink,
+            thresholdPercentage,
+            totalSpend,
+            unsubmittedSpend,
+            awaitingApprovalSpend,
+            approvedReimbursedClosedSpend,
+        }: UpdatedPolicyBudgetNotificationParams) =>
             `Achtung! Dieser Workspace hat ein ${budgetFrequency}-Budget von „${budgetAmount}“ für den ${budgetTypeForNotificationMessage} „${budgetName}“. Du liegst derzeit bei ${approvedReimbursedClosedSpend}, was über ${thresholdPercentage}% des Budgets liegt. Außerdem warten ${awaitingApprovalSpend} auf Genehmigung und ${unsubmittedSpend} wurden noch nicht eingereicht, für insgesamt ${totalSpend}. ${summaryLink ? `<a href="${summaryLink}">Hier ist ein Bericht</a> mit all diesen Ausgaben für Ihre Unterlagen!` : ''}`,
-        removedMaxExpenseAge: (oldValue: string) => `maximales Spesenalter entfernt (zuvor „${oldValue}“ Tage)`,
-        addedCardFeed: (feedName: string) => `Kartenfeed „${feedName}“ hinzugefügt`,
-        removedCardFeed: (feedName: string) => `Kartenfeed „${feedName}“ entfernt`,
-        renamedCardFeed: (newName: string, oldName: string) => `Kartenfeed in „${newName}“ umbenannt (zuvor „${oldName}“)`,
-        assignedCompanyCard: (email: string, feedName: string, cardLastFour: string) =>
-            `hat ${email} ${feedName ? `„${feedName}" ` : ''}Firmenkreditkarte mit der Endziffer ${cardLastFour} zugewiesen`,
-        unassignedCompanyCard: (email: string, feedName: string, cardLastFour: string) =>
-            `nicht zugewiesene ${feedName ? `„${feedName}" ` : ''}Firmenkarte ${email}, endet auf ${cardLastFour}`,
-        updatedCardFeedLiability: (feedName: string, enabled: boolean) =>
-            `${enabled ? 'aktiviert' : 'deaktiviert'} Karteninhaber:innen können Kartentransaktionen für Kartenfeed „${feedName}“ löschen`,
-        updatedCardFeedStatementPeriod: (feedName: string, newValue?: string, previousValue?: string) =>
-            `Kartenfeed-Tag für das Abrechnungsperiodenende von „${feedName}“ geändert${newValue ? ` in „${newValue}“` : ''}${previousValue ? ` (zuvor „${previousValue}“)` : ''}`,
-        addedReportField: (fieldType: string, fieldName?: string, defaultValue?: string) =>
-            `${fieldType}-Berichtsfeld „${fieldName}“${defaultValue ? ` mit Standardwert „${defaultValue}“` : ''} hinzugefügt`,
-        updatedMccGroupCategory: ({mccGroupName, oldCategory, newCategory}: {mccGroupName: string; oldCategory: string; newCategory: string}) =>
-            `hat die Standardausgabenkategorie für „${mccGroupName}“ in „${newCategory}“ geändert (zuvor „${oldCategory}“)`,
-        updatedRequireCompanyCards: ({enabled}: {enabled: boolean}) => `${enabled ? 'aktiviert' : 'deaktiviert'} die Anforderung für Firmenkartenkäufe`,
-        expensifyCardRule: {
-            actionVerb: {block: 'blockiert', allow: 'erlaubt'},
-            amountOperator: {over: 'über', under: 'unter'},
-            amountFilter: ({operator, amount}: {operator: string; amount: string}) => `Beträge ${operator} ${amount}`,
-            theCard: 'die Karte',
-            multipleCards: ({count}: {count: number}) => ({
-                one: '1 Karte',
-                other: `${count} Karten`,
-            }),
-            addRule: ({verb, filters, cards}: {verb: string; filters: string; cards: string}) => {
-                let text = verb;
-                if (filters !== '') {
-                    text += ` ${filters}`;
-                }
-                text += ` auf ${cards}`;
-                return text;
-            },
-            removeRule: ({cards}: {cards: string}) => `Ausgaberegel von ${cards} entfernt`,
-            restrictionVerb: {block: 'Block', allow: 'nur zulassen'},
-            update: {
-                modeChange: ({fromAction, toAction, cards}: {fromAction: string; toAction: string; cards: string}) => `Ausgaberegel von ${fromAction} zu ${toAction} auf ${cards} geändert`,
-                appliedToAdditionalCards: ({count}: {count: number}) => ({
-                    one: 'Ausgaberegel auf 1 weitere Karte angewendet',
-                    other: `Ausgaberegel auf ${count} weitere Karten angewendet`,
-                }),
-                phraseVerb: {added: 'hinzugefügt', removed: 'entfernt', changed: 'geändert', set: 'festlegen', applied: 'Angewendet'},
-                bodyMerchant: ({adjective, value}: {adjective: string; value: string}) => (adjective !== '' ? `${adjective} Händler: „${value}“` : `Händler: „${value}“`),
-                bodyMerchantChange: ({adjective, oldValue, newValue}: {adjective: string; oldValue: string; newValue: string}) =>
-                    adjective !== '' ? `${adjective} Händler von „${oldValue}“ in „${newValue}“ geändert` : `Händler von „${oldValue}“ zu „${newValue}“`,
-                bodySpendCategory: ({adjective, value}: {adjective: string; value: string}) =>
-                    adjective !== '' ? `${adjective} Ausgabenkategorie „${value}“` : `Ausgabenkategorie „${value}“`,
-                bodySpendCategoryChange: ({adjective, oldValue, newValue}: {adjective: string; oldValue: string; newValue: string}) =>
-                    adjective !== '' ? `Ausgabenkategorie (${adjective}) von „${oldValue}“ in „${newValue}“ geändert` : `Ausgabenkategorie von „${oldValue}“ zu „${newValue}“`,
-                bodyMaxAmount: 'Höchstbetrag',
-                bodyMaxAmountSet: ({value}: {value: string}) => `Maximalbetrag bis ${value}`,
-                bodyMaxAmountChange: ({oldValue, newValue}: {oldValue: string; newValue: string}) => `Maximalbetrag von ${oldValue} auf ${newValue}`,
-                bodyAppliedToAdditionalCards: ({count}: {count: number}) => ({
-                    one: 'Ausgabenregel für 1 zusätzliche Karte',
-                    other: `Ausgabenregel für ${count} zusätzliche Karten`,
-                }),
-                bodyRemovedFromCards: ({cards}: {cards: string}) => `Ausgaberegel von ${cards}`,
-                composeOnCards: ({content, cards}: {content: string; cards: string}) => `${content} auf ${cards}`,
-                composeFromCards: ({content, cards}: {content: string; cards: string}) => `${content} von ${cards}`,
-            },
-        },
-        addCustomUnitRateWithAmount: (rateName: string, rateValue: string) => `„${rateName}“-Satz von ${rateValue} hinzugefügt`,
-        addCustomUnitRateWithAmountAndStartDate: (rateName: string, rateValue: string, startDate: string) => `„${rateName}“-Satz von ${rateValue} hinzugefügt, gültig ab ${startDate}`,
-        addCustomUnitRateWithAmountAndEndDate: (rateName: string, rateValue: string, endDate: string) => `„${rateName}“-Satz von ${rateValue} hinzugefügt, gültig bis ${endDate}`,
-        addCustomUnitRateWithAmountAndDates: (rateName: string, rateValue: string, startDate: string, endDate: string) =>
-            `hat den Tarif „${rateName}“ mit ${rateValue} hinzugefügt, gültig vom ${startDate} bis ${endDate}`,
-        updatedCustomUnitRateStartDate: (rateName: string, newDate: string, oldDate?: string) =>
-            oldDate ? `Startdatum des Tarifs „${rateName}“ auf ${newDate} aktualisiert (zuvor ${oldDate})` : `Startdatum des Tarifs „${rateName}“ auf ${newDate} festlegen`,
-        updatedCustomUnitRateEndDate: (rateName: string, newDate: string, oldDate?: string) =>
-            oldDate ? `Enddatum des Tarifs „${rateName}“ auf ${newDate} aktualisiert (zuvor ${oldDate})` : `Enddatum des Tarifs „${rateName}“ auf ${newDate} setzen`,
-        updatedCustomUnitRateStartAndEndDate: (rateName: string, newStartDate: string, newEndDate: string, oldStartDate?: string, oldEndDate?: string) =>
-            oldStartDate && oldEndDate
-                ? `Start- und Enddatum des Tarifs „${rateName}“ auf ${newStartDate} - ${newEndDate} aktualisiert (zuvor ${oldStartDate} - ${oldEndDate})`
-                : `Start- und Enddatum des Tarifs „${rateName}“ auf ${newStartDate} – ${newEndDate} festlegen`,
-        removedCustomUnitRateStartDate: (rateName: string, oldDate: string) => `Startdatum aus Tarif „${rateName}“ entfernt (zuvor ${oldDate})`,
-        removedCustomUnitRateEndDate: (rateName: string, oldDate: string) => `Enddatum aus dem Tarif „${rateName}“ entfernt (zuvor ${oldDate})`,
+        removedMaxExpenseAge: ({oldValue}: UpdatedPolicyFieldWithNewAndOldValueParams) => `maximales Spesenalter entfernt (zuvor „${oldValue}“ Tage)`,
     },
     roomMembersPage: {
         memberNotFound: 'Mitglied nicht gefunden.',
@@ -8118,7 +7034,7 @@ Fügen Sie weitere Ausgabelimits hinzu, um den Cashflow Ihres Unternehmens zu sc
         completed: 'Abgeschlossen',
         action: 'Abschließen',
         messages: {
-            created: (title: string) => `Aufgabe für ${title}`,
+            created: ({title}: TaskCreatedActionParams) => `Aufgabe für ${title}`,
             completed: 'als erledigt markiert',
             canceled: 'gelöschte Aufgabe',
             reopened: 'als unvollständig markiert',
@@ -8132,7 +7048,7 @@ Fügen Sie weitere Ausgabelimits hinzu, um den Cashflow Ihres Unternehmens zu sc
         deleteConfirmation: 'Sind Sie sicher, dass Sie diese Aufgabe löschen möchten?',
     },
     statementPage: {
-        title: (year: number | string, monthName: string) => `Abrechnung ${monthName} ${year}`,
+        title: ({year, monthName}: StatementTitleParams) => `Abrechnung ${monthName} ${year}`,
     },
     keyboardShortcutsPage: {
         title: 'Tastenkürzel',
@@ -8145,8 +7061,6 @@ Fügen Sie weitere Ausgabelimits hinzu, um den Cashflow Ihres Unternehmens zu sc
             newChat: 'Neuer Chat-Bildschirm',
             copy: 'Kommentar kopieren',
             openDebug: 'Testeinstellungen öffnen',
-            expenseReportSearch: 'Spesenberichte suchen',
-            goToWorkspace: 'Zum Workspace des aktuellen Berichts gehen',
         },
     },
     guides: {
@@ -8156,8 +7070,6 @@ Fügen Sie weitere Ausgabelimits hinzu, um den Cashflow Ihres Unternehmens zu sc
     search: {
         resultsAreLimited: 'Suchergebnisse sind begrenzt.',
         viewResults: 'Ergebnisse anzeigen',
-        applyFilters: 'Filter anwenden',
-        appliedFilters: 'Angewandte filter',
         resetFilters: 'Filter zurücksetzen',
         searchResults: {
             emptyResults: {
@@ -8165,24 +7077,27 @@ Fügen Sie weitere Ausgabelimits hinzu, um den Cashflow Ihres Unternehmens zu sc
                 subtitle: `Versuche, deine Suchkriterien anzupassen oder etwas mit der +‑Schaltfläche zu erstellen.`,
             },
             emptyExpenseResults: {
-                title: 'Noch keine Ausgaben',
+                title: 'Du hast noch keine Ausgaben erstellt',
                 subtitle: 'Erstelle eine Ausgabe oder mache eine Probefahrt mit Expensify, um mehr zu erfahren.',
                 subtitleWithOnlyCreateButton: 'Verwende die grüne Schaltfläche unten, um eine Ausgabe zu erstellen.',
             },
             emptyReportResults: {
-                title: 'Noch keine Berichte',
+                title: 'Du hast noch keine Berichte erstellt',
                 subtitle: 'Erstelle einen Bericht oder mache eine Probefahrt mit Expensify, um mehr zu erfahren.',
                 subtitleWithOnlyCreateButton: 'Verwende die grüne Schaltfläche unten, um einen Bericht zu erstellen.',
             },
             emptyInvoiceResults: {
-                title: 'Noch keine Rechnungen',
+                title: dedent(`
+                    Sie haben noch keine Rechnungen erstellt
+                `),
                 subtitle: 'Sende eine Rechnung oder mache eine Probefahrt mit Expensify, um mehr zu erfahren.',
                 subtitleWithOnlyCreateButton: 'Verwende die grüne Schaltfläche unten, um eine Rechnung zu senden.',
-                subtitleCannotSend: 'Du benötigst einen Arbeitsbereich mit aktiviertem Invoices, um Rechnungen zu senden.',
-                subtitleCannotSendWithTestDrive:
-                    'Du benötigst einen Arbeitsbereich mit aktiviertem Invoices, um Rechnungen zu senden. Mache eine Probefahrt mit Expensify, um mehr zu erfahren.',
             },
-            emptyTripResults: {title: 'Noch keine Reisen', subtitle: 'Beginne, indem du unten deine erste Reise buchst.', buttonText: 'Reise buchen'},
+            emptyTripResults: {
+                title: 'Keine Reisen zum Anzeigen',
+                subtitle: 'Beginne, indem du unten deine erste Reise buchst.',
+                buttonText: 'Reise buchen',
+            },
             emptySubmitResults: {
                 title: 'Keine Ausgaben zum Einreichen',
                 subtitle: 'Alles erledigt. Dreh eine Ehrenrunde!',
@@ -8210,31 +7125,30 @@ Fügen Sie weitere Ausgabelimits hinzu, um den Cashflow Ihres Unternehmens zu sc
             },
         },
         columns: 'Spalten',
-        editColumns: 'Spalten bearbeiten',
         resetColumns: 'Spalten zurücksetzen',
         groupColumns: 'Spalten gruppieren',
         expenseColumns: 'Spalten für Ausgaben',
-        saveView: 'Ansicht speichern',
+        statements: 'Abrechnungen',
+        unapprovedCash: 'Nicht genehmigtes Bargeld',
+        unapprovedCard: 'Nicht genehmigte Karte',
+        reconciliation: 'Abstimmung',
+        topSpenders: 'Top-Ausgaben',
+        saveSearch: 'Suche speichern',
         deleteSavedSearch: 'Gespeicherte Suche löschen',
         deleteSavedSearchConfirm: 'Möchtest du diese Suche wirklich löschen?',
         searchName: 'Namen suchen',
         savedSearchesMenuItemTitle: 'Gespeichert',
-        urlCopied: 'URL kopiert',
+        topCategories: 'Top-Kategorien',
+        topMerchants: 'Top-Händler',
         groupedExpenses: 'gruppierte Ausgaben',
         bulkActions: {
-            editMultiple: 'Mehrere bearbeiten',
-            editMultipleTitle: 'Mehrere Ausgaben bearbeiten',
-            editMultipleDescription: 'Änderungen werden für alle ausgewählten Ausgaben übernommen und überschreiben alle zuvor festgelegten Werte.',
             approve: 'Genehmigen',
             pay: 'Bezahlen',
             delete: 'Löschen',
             hold: 'Warteschleife',
             unhold: 'Zurückhalten aufheben',
             reject: 'Ablehnen',
-            duplicateExpense: ({count}: {count: number}) => `${count === 1 ? 'Ausgabe' : 'Ausgaben'} duplizieren`,
             noOptionsAvailable: 'Für die ausgewählte Ausgabengruppe sind keine Optionen verfügbar.',
-            undelete: 'Wiederherstellen',
-            duplicateReport: ({count}: {count: number}) => `Duplikat ${count === 1 ? 'Bericht' : 'Berichte'}`,
         },
         filtersHeader: 'Filter',
         filters: {
@@ -8242,14 +7156,11 @@ Fügen Sie weitere Ausgabelimits hinzu, um den Cashflow Ihres Unternehmens zu sc
                 before: (date?: string) => `Vor ${date ?? ''}`,
                 after: (date?: string) => `Nach ${date ?? ''}`,
                 on: (date?: string) => `Am ${date ?? ''}`,
-                customDate: 'Benutzerdefiniertes Datum',
-                customRange: 'Benutzerdefinierter Bereich',
                 presets: {
                     [CONST.SEARCH.DATE_PRESETS.NEVER]: 'Nie',
                     [CONST.SEARCH.DATE_PRESETS.LAST_MONTH]: 'Letzter Monat',
                     [CONST.SEARCH.DATE_PRESETS.THIS_MONTH]: 'Diesen Monat',
                     [CONST.SEARCH.DATE_PRESETS.YEAR_TO_DATE]: 'Laufendes Jahr',
-                    [CONST.SEARCH.DATE_PRESETS.LAST_12_MONTHS]: 'Letzte 12 Monate',
                     [CONST.SEARCH.DATE_PRESETS.LAST_STATEMENT]: 'Letzter Auszug',
                 },
             },
@@ -8261,15 +7172,10 @@ Fügen Sie weitere Ausgabelimits hinzu, um den Cashflow Ihres Unternehmens zu sc
             currency: 'Währung',
             completed: 'Abgeschlossen',
             amount: {
-                lessThan: (amount?: string) => `Weniger als ${amount ?? ''}`,
-                greaterThan: (amount?: string) => `Größer als ${amount ?? ''}`,
-                between: (greaterThan?: string, lessThan?: string) => {
-                    if (greaterThan && lessThan) {
-                        return `Zwischen ${greaterThan} und ${lessThan}`;
-                    }
-                    return 'Zwischen';
-                },
-                equalTo: (amount?: string) => `Gleich ${amount ?? ''}`,
+                lessThan: ({amount}: OptionalParam<RequestAmountParams> = {}) => `Weniger als ${amount ?? ''}`,
+                greaterThan: ({amount}: OptionalParam<RequestAmountParams> = {}) => `Größer als ${amount ?? ''}`,
+                between: (greaterThan: string, lessThan: string) => `Zwischen ${greaterThan} und ${lessThan}`,
+                equalTo: ({amount}: OptionalParam<RequestAmountParams> = {}) => `Gleich ${amount ?? ''}`,
             },
             card: {
                 expensify: 'Expensify',
@@ -8279,9 +7185,8 @@ Fügen Sie weitere Ausgabelimits hinzu, um den Cashflow Ihres Unternehmens zu sc
                 cardFeedName: ({cardFeedBankName, cardFeedLabel}: {cardFeedBankName: string; cardFeedLabel?: string}) =>
                     `Alle ${cardFeedBankName}${cardFeedLabel ? ` - ${cardFeedLabel}` : ''}`,
                 cardFeedNameCSV: ({cardFeedLabel}: {cardFeedLabel?: string}) => `Alle importierten CSV-Karten${cardFeedLabel ? ` - ${cardFeedLabel}` : ''}`,
-                travelInvoicing: 'Reiseabrechnung',
             },
-            reportField: (name: string, value: string) => `${name} ist ${value}`,
+            reportField: ({name, value}: OptionalParam<ReportFieldParams>) => `${name} ist ${value}`,
             current: 'Aktuell',
             past: 'Vergangenes',
             submitted: 'Eingereicht',
@@ -8293,10 +7198,6 @@ Fügen Sie weitere Ausgabelimits hinzu, um den Cashflow Ihres Unternehmens zu sc
             billable: 'Abrechenbar',
             reimbursable: 'Erstattungsfähig',
             purchaseCurrency: 'Kaufwährung',
-            sortOrder: {
-                [CONST.SEARCH.SORT_ORDER.ASC]: 'Aufsteigend',
-                [CONST.SEARCH.SORT_ORDER.DESC]: 'Absteigend',
-            },
             groupBy: {
                 [CONST.SEARCH.GROUP_BY.FROM]: 'Von',
                 [CONST.SEARCH.GROUP_BY.CARD]: 'Karte',
@@ -8311,9 +7212,8 @@ Fügen Sie weitere Ausgabelimits hinzu, um den Cashflow Ihres Unternehmens zu sc
             },
             feed: 'Feed',
             withdrawalType: {
-                [CONST.SEARCH.WITHDRAWAL_TYPE.EXPENSIFY_CARD]: 'Expensify Karte',
-                [CONST.SEARCH.WITHDRAWAL_TYPE.REIMBURSEMENT]: 'Erstattung',
-                [CONST.SEARCH.WITHDRAWAL_TYPE.CENTRAL_TRAVEL_INVOICING]: 'Reiseabrechnung',
+                [CONST.SEARCH.WITHDRAWAL_TYPE.EXPENSIFY_CARD]: 'Expensify Card',
+                [CONST.SEARCH.WITHDRAWAL_TYPE.REIMBURSEMENT]: 'Rückerstattung',
             },
             is: 'Ist',
             action: {
@@ -8323,20 +7223,13 @@ Fügen Sie weitere Ausgabelimits hinzu, um den Cashflow Ihres Unternehmens zu sc
                 [CONST.SEARCH.ACTION_FILTERS.EXPORT]: 'Export',
             },
         },
-        display: {
-            label: 'Anzeige',
-            sortBy: 'Sortieren nach',
-            sortOrder: 'Sortierreihenfolge',
-            groupBy: 'Gruppieren nach',
-            limitResults: 'Ergebnisse einschränken',
-        },
         has: 'Hat',
+        groupBy: 'Gruppieren nach',
         view: {
             label: 'Anzeigen',
             table: 'Tabelle',
             bar: 'Leiste',
             line: 'Linie',
-            pie: 'Kreisdiagramm',
         },
         chartTitles: {
             [CONST.SEARCH.GROUP_BY.FROM]: 'Von',
@@ -8361,22 +7254,9 @@ Fügen Sie weitere Ausgabelimits hinzu, um den Cashflow Ihres Unternehmens zu sc
         withdrawalType: 'Auszahlungsart',
         recentSearches: 'Letzte Suchen',
         recentChats: 'Neueste Chats',
-        serverResults: 'Suchergebnisse',
         searchIn: 'Suchen in',
-        askConcierge: (message: string) => `Frage Concierge „${message}“`,
-        searchPlaceholder: 'Nach etwas suchen...',
+        searchPlaceholder: 'Nach etwas suchen',
         suggestions: 'Vorschläge',
-        suggestionsAvailable: (
-            {
-                count,
-            }: {
-                count: number;
-            },
-            query = '',
-        ) => ({
-            one: `Vorschläge verfügbar${query ? ` für ${query}` : ''}. ${count} Ergebnis.`,
-            other: (resultCount: number) => `Vorschläge verfügbar${query ? ` für ${query}` : ''}. ${resultCount} Ergebnisse.`,
-        }),
         exportSearchResults: {
             title: 'Export erstellen',
             description: 'Wow, das sind aber viele Elemente! Wir bündeln sie, und Concierge schickt dir in Kürze eine Datei.',
@@ -8385,29 +7265,6 @@ Fügen Sie weitere Ausgabelimits hinzu, um den Cashflow Ihres Unternehmens zu sc
         exportAll: {
             selectAllMatchingItems: 'Alle passenden Einträge auswählen',
             allMatchingItemsSelected: 'Alle passenden Elemente ausgewählt',
-            selectAllOnThisPage: 'Alle auf dieser Seite auswählen',
-        },
-        errors: {
-            pleaseSelectDatesForBothFromAndTo: 'Bitte wähle Daten für Von und Bis',
-        },
-        spendOverTime: 'Ausgaben im Zeitverlauf',
-        tabs: {
-            expenseReports: 'Spesenabrechnungen',
-            reports: 'Berichte',
-            expenses: 'Ausgaben',
-            submit: 'Entwürfe',
-            approve: 'Genehmigung erforderlich',
-            pay: 'Zahlungsbereit',
-            accounting: 'Buchhaltung',
-            export: 'Export ausstehend',
-            unapprovedCash: 'Kassenabgrenzungen',
-            unapprovedCard: 'Kartenabgrenzungen',
-            statements: 'Kartenabrechnungen',
-            reconciliation: 'Bankabstimmung',
-            insights: 'Einblicke',
-            topSpenders: 'Höchste Ausgaben',
-            topCategories: 'Topkategorien',
-            topMerchants: 'Top-Händler',
         },
     },
     genericErrorPage: {
@@ -8464,6 +7321,7 @@ Fügen Sie weitere Ausgabelimits hinzu, um den Cashflow Ihres Unternehmens zu sc
             emptyReportConfirmationTitle: 'Sie haben bereits einen leeren Bericht',
             emptyReportConfirmationPrompt: ({workspaceName}: {workspaceName: string}) =>
                 `Möchtest du wirklich einen weiteren Bericht in ${workspaceName} erstellen? Du kannst auf deine leeren Berichte zugreifen in`,
+            emptyReportConfirmationPromptLink: 'Berichte',
             emptyReportConfirmationDontShowAgain: 'Nicht mehr anzeigen',
             genericWorkspaceName: 'dieser Workspace',
         },
@@ -8501,7 +7359,6 @@ Fügen Sie weitere Ausgabelimits hinzu, um den Cashflow Ihres Unternehmens zu sc
                     reimburseableLink: 'Auslagen',
                     nonReimbursableLink: 'Firmenkarten-Ausgaben',
                     pending: (label: string) => `hat begonnen, diesen Bericht nach ${label} zu exportieren...`,
-                    travelCardLink: 'Reisespesen mit Firmenkarte',
                 },
                 integrationsMessage: (errorMessage: string, label: string, linkText?: string, linkURL?: string) =>
                     `Fehler beim Exportieren dieses Berichts nach ${label} („${errorMessage}${linkText ? `<a href="${linkURL}">${linkText}</a>` : ''}“)`,
@@ -8510,8 +7367,7 @@ Fügen Sie weitere Ausgabelimits hinzu, um den Cashflow Ihres Unternehmens zu sc
                 markedReimbursed: (amount: string, currency: string) => `hat ${currency}${amount} anderweitig bezahlt`,
                 markedReimbursedFromIntegration: ({amount, currency}: MarkReimbursedFromIntegrationParams) => `${currency}${amount} über Integration bezahlt`,
                 outdatedBankAccount: `Konnte die Zahlung aufgrund eines Problems mit dem Bankkonto des Zahlenden nicht verarbeiten`,
-                reimbursementACHBounceDefault: `Zahlung konnte wegen einer falschen Bankleitzahl/Kontonummer oder eines geschlossenen Kontos nicht verarbeitet werden`,
-                reimbursementACHBounceWithReason: ({returnReason}: {returnReason: string}) => `Die Zahlung konnte nicht verarbeitet werden: ${returnReason}`,
+                reimbursementACHBounce: `Zahlung konnte aufgrund eines Problems mit dem Bankkonto nicht verarbeitet werden`,
                 reimbursementACHCancelled: `hat die Zahlung storniert`,
                 reimbursementAccountChanged: `Die Zahlung konnte nicht verarbeitet werden, da der Zahlungspflichtige das Bankkonto gewechselt hat`,
                 reimbursementDelayed: `hat die Zahlung verarbeitet, aber sie verzögert sich um weitere 1–2 Werktage`,
@@ -8519,22 +7375,17 @@ Fügen Sie weitere Ausgabelimits hinzu, um den Cashflow Ihres Unternehmens zu sc
                 selectedForRandomAuditMarkdown: `zufällig zur Überprüfung [ausgewählt](https://help.expensify.com/articles/expensify-classic/reports/Set-a-random-report-audit-schedule)`,
                 share: ({to}: ShareParams) => `Mitglied ${to} eingeladen`,
                 unshare: ({to}: UnshareParams) => `Mitglied ${to} entfernt`,
-                stripePaid: (amount: string, currency: string) => `bezahlt: ${currency}${amount}`,
+                stripePaid: ({amount, currency}: StripePaidParams) => `bezahlt: ${currency}${amount}`,
                 takeControl: `Kontrolle übernommen`,
                 integrationSyncFailed: (label: string, errorMessage: string, workspaceAccountingLink?: string) =>
                     `Beim Synchronisieren mit ${label}${errorMessage ? ` ("${errorMessage}")` : ''} ist ein Problem aufgetreten. Bitte behebe das Problem in den <a href="${workspaceAccountingLink}">Workspace-Einstellungen</a>.`,
-                integrationSyncFailedRecurrence: ({count}: {count: number}) => `(${count} Mal wiederholt.)`,
                 companyCardConnectionBroken: ({feedName, workspaceCompanyCardRoute}: {feedName: string; workspaceCompanyCardRoute: string}) =>
                     `Die Verbindung für ${feedName} ist unterbrochen. Um Kartenimporte wiederherzustellen, <a href='${workspaceCompanyCardRoute}'>melden Sie sich bei Ihrer Bank an</a>.`,
                 plaidBalanceFailure: ({maskedAccountNumber, walletRoute}: {maskedAccountNumber: string; walletRoute: string}) =>
-                    `Die Plaid-Verbindung zu Ihrem Geschäftskonto ist unterbrochen. Bitte <a href='${walletRoute}'>verbinden Sie Ihr Bankkonto ${maskedAccountNumber} erneut</a>, damit Sie Ihre Expensify Karten weiterhin verwenden können.`,
-                addEmployee: (email: string, role: string, didJoinPolicy?: boolean) => {
-                    const translatedRole = String(translations.workspace.common.roleName(role)).toLowerCase();
-                    const article = role === CONST.POLICY.ROLE.AUDITOR ? 'an' : 'ein';
-                    return didJoinPolicy ? `${email} ist über den Workspace-Einladungslink beigetreten` : `${email} als ${article} ${translatedRole} hinzugefügt`;
-                },
+                    `Die Plaid-Verbindung zu Ihrem Geschäftskonto ist unterbrochen. Bitte <a href='${walletRoute}'>verbinden Sie Ihr Bankkonto ${maskedAccountNumber} erneut</a>, damit Sie Ihre Expensify Cards weiterhin nutzen können.`,
+                addEmployee: (email: string, role: string) => `${email} als ${role === 'member' ? 'a' : 'an'} ${role} hinzugefügt`,
                 updateRole: ({email, currentRole, newRole}: UpdateRoleParams) => `hat die Rolle von ${email} in ${newRole} geändert (zuvor ${currentRole})`,
-                updatedCustomField1: (email: string, newValue: string, previousValue: string) => {
+                updatedCustomField1: ({email, previousValue, newValue}: UpdatedCustomFieldParams) => {
                     if (!newValue) {
                         return `Benutzerdefiniertes Feld 1 von ${email} entfernt (zuvor „${previousValue}“)`;
                     }
@@ -8542,7 +7393,7 @@ Fügen Sie weitere Ausgabelimits hinzu, um den Cashflow Ihres Unternehmens zu sc
                         ? `„${newValue}“ zu benutzerdefiniertem Feld 1 von ${email} hinzugefügt`
                         : `benutzerdefiniertes Feld 1 von ${email} auf „${newValue}“ geändert (zuvor „${previousValue}“)`;
                 },
-                updatedCustomField2: (email: string, newValue: string, previousValue: string) => {
+                updatedCustomField2: ({email, previousValue, newValue}: UpdatedCustomFieldParams) => {
                     if (!newValue) {
                         return `benutzerdefiniertes Feld 2 von ${email} entfernt (vorher „${previousValue}“)`;
                     }
@@ -8556,12 +7407,8 @@ Fügen Sie weitere Ausgabelimits hinzu, um den Cashflow Ihres Unternehmens zu sc
                 addedConnection: ({connectionName}: ConnectionNameParams) => `verbunden mit ${CONST.POLICY.CONNECTIONS.NAME_USER_FRIENDLY[connectionName]}`,
                 leftTheChat: 'hat den Chat verlassen',
                 settlementAccountLocked: ({maskedBankAccountNumber}: OriginalMessageSettlementAccountLocked, linkURL: string) =>
-                    `Das Geschäftskonto ${maskedBankAccountNumber} wurde aufgrund eines Problems mit entweder der Erstattung oder dem Ausgleich der Expensify Karte automatisch gesperrt. Bitte beheben Sie das Problem in Ihren <a href="${linkURL}">Workspace-Einstellungen</a>.`,
+                    `Das Geschäftskonto ${maskedBankAccountNumber} wurde aufgrund eines Problems mit der Erstattung oder der Expensify Card-Abrechnung automatisch gesperrt. Bitte behebe das Problem in deinen <a href="${linkURL}">Workspace-Einstellungen</a>.`,
                 leftTheChatWithName: (nameOrEmail: string) => `${nameOrEmail ? `${nameOrEmail}: ` : ''} hat den Chat verlassen`,
-                actionableCard3DSTransactionApproval: (amount: string, merchant: string | undefined) => {
-                    const amountAndMerchantText = [amount, merchant].filter((s) => !!s?.length).join(' ');
-                    return `Öffne die Expensify Mobile-App, um deine${amountAndMerchantText ? ` ${amountAndMerchantText}-` : ' '}Transaktion zu prüfen`;
-                },
             },
             error: {
                 invalidCredentials: 'Ungültige Anmeldedaten, bitte überprüfen Sie die Konfiguration Ihrer Verbindung.',
@@ -8571,23 +7418,6 @@ Fügen Sie weitere Ausgabelimits hinzu, um den Cashflow Ihres Unternehmens zu sc
     chronos: {
         oooEventSummaryFullDay: (summary: string, dayCount: number, date: string) => `${summary} für ${dayCount} ${dayCount === 1 ? 'Tag' : 'Tage'} bis ${date}`,
         oooEventSummaryPartialDay: (summary: string, timePeriod: string, date: string) => `${summary} von ${timePeriod} am ${date}`,
-        startTimer: 'Timer starten',
-        stopTimer: (duration: string) => `Timer stoppen (${duration})`,
-        scheduleOOO: 'Abwesenheit planen',
-        scheduleOOOTitle: 'Abwesenheit planen',
-        date: 'Datum',
-        time: 'Zeit (24-Stunden-Format)',
-        durationAmount: 'Dauer',
-        durationUnit: 'Einheit',
-        reason: 'Grund',
-        workingPercentage: 'Arbeitsprozentsatz',
-        dateRequired: 'Datum ist erforderlich.',
-        invalidTimeFormat: 'Bitte geben Sie eine gültige Uhrzeit im 24‑Stunden-Format ein (z. B. 14:30).',
-        enterANumber: 'Bitte geben Sie eine Zahl ein.',
-        hour: 'Stunden',
-        day: 'Tage',
-        week: 'Wochen',
-        month: 'Monate',
     },
     footer: {
         features: 'Funktionen',
@@ -8630,24 +7460,8 @@ Fügen Sie weitere Ausgabelimits hinzu, um den Cashflow Ihres Unternehmens zu sc
         workspaceName: 'Arbeitsbereichsname',
         chatUserDisplayNames: 'Anzeigenamen von Chatmitgliedern',
         scrollToNewestMessages: 'Zu neuesten Nachrichten scrollen',
-        scrollToActionBadgeTarget: 'Zur Aktion scrollen, die Aufmerksamkeit erfordert',
         preStyledText: 'Vorgestylter Text',
         viewAttachment: 'Anhang anzeigen',
-        contextMenuAvailable: 'Kontextmenü verfügbar. Drücken Sie Shift+F10, um es zu öffnen.',
-        contextMenuAvailableMacOS: 'Kontextmenü verfügbar. Drücken Sie VO-Shift-M, um es zu öffnen.',
-        contextMenuAvailableNative: 'Kontextmenü verfügbar. Doppeltippen und halten, um es zu öffnen.',
-        selectAllFeatures: 'Alle Funktionen auswählen',
-        selectAllTransactions: 'Alle Transaktionen auswählen',
-        selectAllItems: 'Alle Einträge auswählen',
-        openActionsMenu: 'Aktionsmenü öffnen',
-        selectAllCategories: 'Alle Kategorien auswählen',
-        selectAllDistanceRates: 'Alle Entfernungssätze auswählen',
-        selectAllTags: 'Alle Tags auswählen',
-        selectAllTaxes: 'Alle Steuern auswählen',
-        selectAllPerDiemRates: 'Alle Pauschalspesen-Sätze auswählen',
-        selectAllMembers: 'Alle Mitglieder auswählen',
-        selectAllValues: 'Alle Werte auswählen',
-        selectAllRules: 'Alle Regeln auswählen',
     },
     parentReportAction: {
         deletedReport: 'Gelöschter Bericht',
@@ -8666,7 +7480,6 @@ Fügen Sie weitere Ausgabelimits hinzu, um den Cashflow Ihres Unternehmens zu sc
         parentNavigationSummary: ({reportName, workspaceName}: ParentNavigationSummaryParams) => `Von ${reportName}${workspaceName ? `in ${workspaceName}` : ''}`,
     },
     qrCodes: {
-        qrCode: 'QR-Code',
         copy: 'URL kopieren',
         copied: 'Kopiert!',
     },
@@ -8713,11 +7526,6 @@ Fügen Sie weitere Ausgabelimits hinzu, um den Cashflow Ihres Unternehmens zu sc
             'Schließ dich Expensify.org an, um Ungerechtigkeit auf der ganzen Welt zu beseitigen. Die aktuelle „Teachers Unite“-Kampagne unterstützt Lehrkräfte überall, indem sie die Kosten für grundlegende Schulmaterialien teilt.',
         iKnowATeacher: 'Ich kenne eine Lehrkraft',
         iAmATeacher: 'Ich bin Lehrer',
-        personalKarma: {
-            title: 'Persönliches Karma aktivieren',
-            description: 'Spende 1 $ an Expensify.org für je 500 $, die du jeden Monat ausgibst',
-            stopDonationsPrompt: 'Bist du sicher, dass du nicht mehr an Expensify.org spenden möchtest?',
-        },
         getInTouch: 'Ausgezeichnet! Bitte teile ihre Kontaktdaten, damit wir sie erreichen können.',
         introSchoolPrincipal: 'Einführung für Ihre Schulleitung',
         schoolPrincipalVerifyExpense:
@@ -8740,11 +7548,6 @@ Fügen Sie weitere Ausgabelimits hinzu, um den Cashflow Ihres Unternehmens zu sc
         notActivated: 'Nicht aktiviert',
         outOfPocket: 'Erstattungsfähig',
         companySpend: 'Nicht erstattungsfähig',
-        personalCard: 'Private Karte',
-        companyCard: 'Firmenkarte',
-        expensifyCard: 'Expensify Karte',
-        travelInvoicing: 'Reiseabrechnung',
-        travelCard: 'Reisekarte',
     },
     distance: {
         addStop: 'Stopp hinzufügen',
@@ -8768,18 +7571,14 @@ Fügen Sie weitere Ausgabelimits hinzu, um den Cashflow Ihres Unternehmens zu sc
             endReading: 'Lesen beenden',
             saveForLater: 'Für später speichern',
             totalDistance: 'Gesamtdistanz',
-            startMessageWeb: 'Füge ein Foto deines Kilometerzählers vom <strong>Beginn</strong> deiner Fahrt hinzu. Ziehe eine Datei hierher oder wähle eine zum Hochladen aus.',
-            endMessageWeb: 'Fügen Sie ein Foto Ihres Kilometerzählers vom <strong>Ende</strong> Ihrer Fahrt hinzu. Ziehen Sie eine Datei hierher oder wählen Sie eine zum Hochladen aus.',
             startTitle: 'Foto des Kilometerzähler-Starts',
             endTitle: 'Kilometerzähler-Endfoto',
-            deleteOdometerPhoto: 'Kilometerzähler-Foto löschen',
-            deleteOdometerPhotoConfirmation: 'Möchtest du dieses Kilometerzählerfoto wirklich löschen?',
-            cameraAccessRequired: 'Für das Aufnehmen von Bildern ist der Kamerazugriff erforderlich.',
-            snapPhotoStart: '<muted-text-label>Machen Sie zu <strong>Beginn</strong> Ihrer Fahrt ein Foto von Ihrem Kilometerzähler.</muted-text-label>',
-            snapPhotoEnd: '<muted-text-label>Machen Sie ein Foto von Ihrem Kilometerzähler am <strong>Ende</strong> Ihrer Fahrt.</muted-text-label>',
+            startMessageWeb: 'Füge ein Foto deines Kilometerzählers vom <strong>Beginn</strong> deiner Fahrt hinzu. Ziehe eine Datei hierher oder wähle eine zum Hochladen aus.',
+            endMessageWeb: 'Fügen Sie ein Foto Ihres Kilometerzählers vom <strong>Ende</strong> Ihrer Fahrt hinzu. Ziehen Sie eine Datei hierher oder wählen Sie eine zum Hochladen aus.',
         },
     },
     gps: {
+        disclaimer: 'Verwende GPS, um aus deiner Fahrt eine Ausgabe zu erstellen. Tippe unten auf „Start“, um die Aufzeichnung zu beginnen.',
         error: {
             failedToStart: 'Standortverfolgung konnte nicht gestartet werden.',
             failedToGetPermissions: 'Erforderliche Standortberechtigungen konnten nicht abgerufen werden.',
@@ -8788,9 +7587,13 @@ Fügen Sie weitere Ausgabelimits hinzu, um den Cashflow Ihres Unternehmens zu sc
         stopped: 'Angehalten',
         start: 'Start',
         stop: 'Stopp',
-        save: 'Speichern',
-        resume: 'Fortsetzen',
         discard: 'Verwerfen',
+        stopGpsTrackingModal: {
+            title: 'GPS-Tracking stoppen',
+            prompt: 'Bist du sicher? Dadurch wird deine aktuelle Sitzung beendet.',
+            cancel: 'Tracking fortsetzen',
+            confirm: 'GPS-Tracking stoppen',
+        },
         discardDistanceTrackingModal: {
             title: 'Entfernungsverfolgung verwerfen',
             prompt: 'Bist du sicher? Dadurch wird dein aktueller Ablauf verworfen und das kann nicht rückgängig gemacht werden.',
@@ -8838,18 +7641,12 @@ Fügen Sie weitere Ausgabelimits hinzu, um den Cashflow Ihres Unternehmens zu sc
             prompt: 'Sind Sie sicher, dass Sie die GPS-Verfolgung beenden und zu Expensify Classic wechseln möchten?',
             confirm: 'Anhalten und wechseln',
         },
-        switchAccountWarningTripInProgress: {
-            title: 'GPS-Tracking läuft',
-            prompt: 'Sind Sie sicher, dass Sie die GPS-Verfolgung beenden und das Konto wechseln möchten?',
-            confirm: 'Anhalten und wechseln',
-        },
         locationServicesRequiredModal: {
             title: 'Standortzugriff erforderlich',
             confirm: 'Einstellungen öffnen',
             prompt: 'Bitte erlaube den Standortzugriff in den Einstellungen deines Geräts, um die GPS‑Streckenverfolgung zu starten.',
         },
-        gpsFloatingPillText: 'GPS-Verfolgung läuft...',
-        liveActivity: {subtitle: 'Entfernungserfassung', button: 'Fortschritt anzeigen', lockScreenBadgeText: 'Entfernung', lockScreenTrackingText: 'Verfolge …'},
+        fabGpsTripExplained: 'Zum GPS-Bildschirm wechseln (Schnellaktion)',
     },
     reportCardLostOrDamaged: {
         screenTitle: 'Zeugnis verloren oder beschädigt',
@@ -8876,13 +7673,11 @@ Fügen Sie weitere Ausgabelimits hinzu, um den Cashflow Ihres Unternehmens zu sc
         [CONST.REFERRAL_PROGRAM.CONTENT_TYPES.START_CHAT]: {
             buttonText: 'Beginne einen Chat, <success><strong>empfiehl eine:n Freund:in</strong></success>.',
             header: 'Chat starten, Freund empfehlen',
-            closeAccessibilityLabel: 'Schließen, einen Chat starten, einen Freund empfehlen, Banner',
             body: 'Möchtest du, dass deine Freund*innen Expensify auch nutzen? Starte einfach einen Chat mit ihnen, und wir kümmern uns um den Rest.',
         },
         [CONST.REFERRAL_PROGRAM.CONTENT_TYPES.SUBMIT_EXPENSE]: {
             buttonText: 'Reiche eine Ausgabe ein, <success><strong>wirb dein Team</strong></success>.',
             header: 'Reiche eine Ausgabe ein, wirb dein Team an',
-            closeAccessibilityLabel: 'Schließen, eine Ausgabe einreichen, dein Team einladen, Banner',
             body: 'Möchtest du, dass dein Team Expensify auch nutzt? Reiche ihnen einfach eine Ausgabe ein und wir kümmern uns um den Rest.',
         },
         [CONST.REFERRAL_PROGRAM.CONTENT_TYPES.REFER_FRIEND]: {
@@ -8898,27 +7693,26 @@ Fügen Sie weitere Ausgabelimits hinzu, um den Cashflow Ihres Unternehmens zu sc
     },
     systemChatFooterMessage: {
         [CONST.INTRO_CHOICES.MANAGE_TEAM]: ({adminReportName, href}: {adminReportName: string; href: string}) =>
-            `Chatten Sie mit Ihrer Kundenbetreuung in <a href="${href}">${adminReportName}</a>, um Hilfe zu erhalten`,
-        default: `Schreiben Sie eine Nachricht an <concierge-link>${CONST.CONCIERGE_CHAT_NAME}</concierge-link> für Hilfe bei der Einrichtung`,
+            `Chatte mit deiner Setup-Fachperson in <a href="${href}">${adminReportName}</a>, um Hilfe zu erhalten`,
+        default: `Sende eine Nachricht an <concierge-link>${CONST.CONCIERGE_CHAT_NAME}</concierge-link>, um Hilfe bei der Einrichtung zu erhalten`,
     },
     violations: {
         allTagLevelsRequired: 'Alle Tags erforderlich',
         autoReportedRejectedExpense: 'Diese Ausgabe wurde abgelehnt.',
         billableExpense: 'Abrechenbar nicht mehr gültig',
-        cashExpenseWithNoReceipt: (formattedLimit?: string) => `Beleg erforderlich${formattedLimit ? `über ${formattedLimit}` : ''}`,
+        cashExpenseWithNoReceipt: ({formattedLimit}: ViolationsCashExpenseWithNoReceiptParams = {}) => `Beleg erforderlich${formattedLimit ? `über ${formattedLimit}` : ''}`,
         categoryOutOfPolicy: 'Kategorie nicht mehr gültig',
-        conversionSurcharge: (surcharge: number) => `${surcharge}% Umrechnungszuschlag angewendet`,
+        conversionSurcharge: ({surcharge}: ViolationsConversionSurchargeParams) => `${surcharge}% Umrechnungszuschlag angewendet`,
         customUnitOutOfPolicy: 'Satz für diesen Workspace ungültig',
         duplicatedTransaction: 'Möglicherweise dupliziert',
         fieldRequired: 'Berichtsfelder sind erforderlich',
         futureDate: 'Zukünftiges Datum nicht erlaubt',
-        inactiveVendor: 'Anbieter nicht mehr gültig',
-        invoiceMarkup: (invoiceMarkup: number) => `Um ${invoiceMarkup}% erhöht`,
-        maxAge: (maxAge: number) => `Datum ist älter als ${maxAge} Tage`,
+        invoiceMarkup: ({invoiceMarkup}: ViolationsInvoiceMarkupParams) => `Um ${invoiceMarkup}% erhöht`,
+        maxAge: ({maxAge}: ViolationsMaxAgeParams) => `Datum ist älter als ${maxAge} Tage`,
         missingCategory: 'Fehlende Kategorie',
         missingComment: 'Beschreibung für die ausgewählte Kategorie erforderlich',
         missingAttendees: 'Für diese Kategorie sind mehrere Teilnehmende erforderlich',
-        missingTag: (tagName?: string) => `Fehlend ${tagName ?? 'Tag'}`,
+        missingTag: ({tagName}: ViolationsMissingTagParams = {}) => `Fehlend ${tagName ?? 'Tag'}`,
         modifiedAmount: ({type, displayPercentVariance}: ViolationsModifiedAmountParams) => {
             switch (type) {
                 case 'distance':
@@ -8933,17 +7727,15 @@ Fügen Sie weitere Ausgabelimits hinzu, um den Cashflow Ihres Unternehmens zu sc
             }
         },
         modifiedDate: 'Datum weicht vom gescannten Beleg ab',
-        increasedDistance: ({formattedRouteDistance}: ViolationsIncreasedDistanceParams) =>
-            formattedRouteDistance ? `Die Entfernung übersteigt die berechnete Route von ${formattedRouteDistance}` : 'Entfernung übersteigt die berechnete Route',
         nonExpensiworksExpense: 'Nicht-Expensiworks-Ausgabe',
-        overAutoApprovalLimit: (formattedLimit: string) => `Ausgabe überschreitet das Auto-Genehmigungslimit von ${formattedLimit}`,
-        overCategoryLimit: (formattedLimit: string) => `Betrag über dem Kategorie-Limit von ${formattedLimit}/Person`,
-        overLimit: (formattedLimit: string) => `Betrag über dem Limit von ${formattedLimit}/Person`,
-        overTripLimit: (formattedLimit: string) => `Betrag über dem Limit von ${formattedLimit}/Reise`,
-        overLimitAttendee: (formattedLimit: string) => `Betrag über dem Limit von ${formattedLimit}/Person`,
-        perDayLimit: (formattedLimit: string) => `Betrag über dem täglichen Kategorienlimit von ${formattedLimit}/Person`,
+        overAutoApprovalLimit: ({formattedLimit}: ViolationsOverLimitParams) => `Ausgabe überschreitet das Auto-Genehmigungslimit von ${formattedLimit}`,
+        overCategoryLimit: ({formattedLimit}: ViolationsOverCategoryLimitParams) => `Betrag über dem Kategorie-Limit von ${formattedLimit}/Person`,
+        overLimit: ({formattedLimit}: ViolationsOverLimitParams) => `Betrag über dem Limit von ${formattedLimit}/Person`,
+        overTripLimit: ({formattedLimit}: ViolationsOverLimitParams) => `Betrag über dem Limit von ${formattedLimit}/Reise`,
+        overLimitAttendee: ({formattedLimit}: ViolationsOverLimitParams) => `Betrag über dem Limit von ${formattedLimit}/Person`,
+        perDayLimit: ({formattedLimit}: ViolationsPerDayLimitParams) => `Betrag über dem täglichen Kategorienlimit von ${formattedLimit}/Person`,
         receiptNotSmartScanned: 'Beleg- und Ausgabendetails manuell hinzugefügt.',
-        receiptRequired: (formattedLimit?: string, category?: string) => {
+        receiptRequired: ({formattedLimit, category}: ViolationsReceiptRequiredParams) => {
             if (formattedLimit && category) {
                 return `Beleg erforderlich bei Überschreitung der Kategoriegrenze von ${formattedLimit}`;
             }
@@ -8955,8 +7747,8 @@ Fügen Sie weitere Ausgabelimits hinzu, um den Cashflow Ihres Unternehmens zu sc
             }
             return 'Beleg erforderlich';
         },
-        itemizedReceiptRequired: (formattedLimit?: string) => `Einzelpostenbeleg erforderlich${formattedLimit ? `über ${formattedLimit}` : ''}`,
-        prohibitedExpense: (prohibitedExpenseTypes: string | string[]) => {
+        itemizedReceiptRequired: ({formattedLimit}: {formattedLimit?: string}) => `Einzelpostenbeleg erforderlich${formattedLimit ? `über ${formattedLimit}` : ''}`,
+        prohibitedExpense: ({prohibitedExpenseTypes}: ViolationsProhibitedExpenseParams) => {
             const preMessage = 'Unzulässige Ausgabe:';
             const getProhibitedExpenseTypeText = (prohibitedExpenseType: string) => {
                 switch (prohibitedExpenseType) {
@@ -8970,10 +7762,6 @@ Fügen Sie weitere Ausgabelimits hinzu, um den Cashflow Ihres Unternehmens zu sc
                         return `Erwachsenenunterhaltung`;
                     case 'hotelIncidentals':
                         return `Nebenkosten im Hotel`;
-                    case 'giftCard':
-                        return `Geschenkkartenkäufe`;
-                    case 'handwrittenReceipt':
-                        return `handschriftliche Belege`;
                     default:
                         return `${prohibitedExpenseType}`;
                 }
@@ -8989,37 +7777,19 @@ Fügen Sie weitere Ausgabelimits hinzu, um den Cashflow Ihres Unternehmens zu sc
             }
             return `${preMessage} ${types.map(getProhibitedExpenseTypeText).join(', ')}`;
         },
-        customRules: (message: string) => message,
+        customRules: ({message}: ViolationsCustomRulesParams) => message,
         reviewRequired: 'Überprüfung erforderlich',
-        rter: (
-            brokenBankConnection: boolean,
-            isAdmin: boolean,
-            isTransactionOlderThan7Days: boolean,
-            member?: string,
-            rterType?: ValueOf<typeof CONST.RTER_VIOLATION_TYPES>,
-            companyCardPageURL?: string,
-            connectionLink?: string,
-            isPersonalCard?: boolean,
-            isMarkAsCash?: boolean,
-        ) => {
+        rter: ({brokenBankConnection, isAdmin, isTransactionOlderThan7Days, member, rterType, companyCardPageURL}: ViolationsRterParams) => {
             if (rterType === CONST.RTER_VIOLATION_TYPES.BROKEN_CARD_CONNECTION_530) {
-                return 'Beleg kann wegen unterbrochener Bankverbindung nicht automatisch zugeordnet werden.';
-            }
-            if (isPersonalCard && (rterType === CONST.RTER_VIOLATION_TYPES.BROKEN_CARD_CONNECTION || brokenBankConnection)) {
-                if (!connectionLink) {
-                    return 'Beleg kann wegen unterbrochener Bankverbindung nicht automatisch zugeordnet werden.';
-                }
-                return isMarkAsCash
-                    ? `Beleg kann wegen einer unterbrochenen Kartenverbindung nicht automatisch zugeordnet werden. Markiere ihn als Barzahlung, um ihn zu ignorieren, oder <a href="${connectionLink}">repariere die Karte</a>, um den Beleg zuzuordnen.`
-                    : `Quittung kann aufgrund einer unterbrochenen Kartenverbindung nicht automatisch zugeordnet werden. <a href="${connectionLink}">Karte reparieren</a>, um die Quittung zuzuordnen.`;
+                return 'Beleg kann wegen unterbrochener Bankverbindung nicht automatisch zugeordnet werden';
             }
             if (brokenBankConnection || rterType === CONST.RTER_VIOLATION_TYPES.BROKEN_CARD_CONNECTION) {
                 return isAdmin
-                    ? `Bankverbindung unterbrochen. <a href="${companyCardPageURL}">Erneut verbinden, um Beleg zuzuordnen</a>`
-                    : 'Bankverbindung unterbrochen. Bitte eine:n Admin bitten, die Verbindung wiederherzustellen, um den Beleg abzugleichen.';
+                    ? `Bankverbindung unterbrochen. <a href="${companyCardPageURL}">Erneut verbinden, um Beleg abzugleichen</a>`
+                    : 'Bankverbindung unterbrochen. Bitte eine:n Admin darum bitten, sie neu zu verbinden, um den Beleg abzugleichen.';
             }
             if (!isTransactionOlderThan7Days) {
-                return isAdmin ? `Bitte ${member} darum, es als Barzahlung zu markieren, oder warte 7 Tage und versuche es dann erneut` : 'Wartet auf Abgleich mit Kartentransaktion.';
+                return isAdmin ? `Bitte ${member} darum, als Barzahlung zu markieren, oder warte 7 Tage und versuche es dann erneut` : 'Warten auf Abgleich mit Kartentransaktion.';
             }
             return '';
         },
@@ -9028,21 +7798,12 @@ Fügen Sie weitere Ausgabelimits hinzu, um den Cashflow Ihres Unternehmens zu sc
             `<muted-text-label>Beleg ausstehend wegen unterbrochener Bankverbindung. Bitte in <a href="${workspaceCompanyCardRoute}">Firmenkarten</a> beheben.</muted-text-label>`,
         memberBrokenConnectionError: 'Beleg ausstehend aufgrund einer unterbrochenen Bankverbindung. Bitte wende dich an eine Workspace-Admin, um das Problem zu beheben.',
         markAsCashToIgnore: 'Als Barzahlung markieren, um sie zu ignorieren und Zahlung anzufordern.',
-        smartscanFailed: ({canEdit = true, missingFields = []}: {canEdit?: boolean; missingFields?: string[]}) => {
-            if (missingFields.length > 0) {
-                const fieldNames: Record<string, string> = {merchant: 'Händler', date: 'Datum', amount: 'Betrag'};
-                const translated = missingFields.map((f) => fieldNames[f] ?? f);
-                const fieldList = translated.join(translated.length > 2 ? ', ' : ' und ');
-                const verb = translated.length === 1 ? 'fehlt' : 'fehlen';
-                return `Beleg-Scan fehlgeschlagen — ${fieldList} ${verb}.${canEdit ? ' Details manuell eingeben.' : ''}`;
-            }
-            return `Beleg-Scan fehlgeschlagen.${canEdit ? 'Details manuell eingeben.' : ''}`;
-        },
+        smartscanFailed: ({canEdit = true}) => `Beleg-Scan fehlgeschlagen.${canEdit ? 'Details manuell eingeben.' : ''}`,
         receiptGeneratedWithAI: 'Mögliche KI-generierte Quittung',
-        someTagLevelsRequired: (tagName?: string) => `Fehlende ${tagName ?? 'Tag'}`,
-        tagOutOfPolicy: (tagName?: string) => `${tagName ?? 'Tag'} nicht mehr gültig`,
+        someTagLevelsRequired: ({tagName}: ViolationsTagOutOfPolicyParams = {}) => `Fehlende ${tagName ?? 'Tag'}`,
+        tagOutOfPolicy: ({tagName}: ViolationsTagOutOfPolicyParams = {}) => `${tagName ?? 'Tag'} nicht mehr gültig`,
         taxAmountChanged: 'Steuerbetrag wurde geändert',
-        taxOutOfPolicy: (taxName?: string) => `${taxName ?? 'Steuer'} nicht mehr gültig`,
+        taxOutOfPolicy: ({taxName}: ViolationsTaxOutOfPolicyParams = {}) => `${taxName ?? 'Steuer'} nicht mehr gültig`,
         taxRateChanged: 'Steuersatz wurde geändert',
         taxRequired: 'Fehlender Steuersatz',
         none: 'Keine',
@@ -9062,7 +7823,7 @@ Fügen Sie weitere Ausgabelimits hinzu, um den Cashflow Ihres Unternehmens zu sc
         noRoute: 'Bitte wähle eine gültige Adresse aus',
     },
     reportViolations: {
-        [CONST.REPORT_VIOLATIONS.FIELD_REQUIRED]: (fieldName: string) => `${fieldName} ist erforderlich`,
+        [CONST.REPORT_VIOLATIONS.FIELD_REQUIRED]: ({fieldName}: RequiredFieldParams) => `${fieldName} ist erforderlich`,
         reportContainsExpensesWithViolations: 'Der Bericht enthält Ausgaben mit Verstößen.',
     },
     violationDismissal: {
@@ -9119,7 +7880,6 @@ Fügen Sie weitere Ausgabelimits hinzu, um den Cashflow Ihres Unternehmens zu sc
         bookACallTextBottom:
             'Wir würden uns freuen, mit Ihnen zu telefonieren, um die Gründe besser zu verstehen. Sie können einen Anruf mit einer*m unserer leitenden Produktmanager*innen buchen, um Ihre Bedürfnisse zu besprechen.',
         takeMeToExpensifyClassic: 'Bring mich zu Expensify Classic',
-        goBackJustOnce: 'Nur dieses Mal zurück',
     },
     listBoundary: {
         errorMessage: 'Beim Laden weiterer Nachrichten ist ein Fehler aufgetreten',
@@ -9194,7 +7954,7 @@ Fügen Sie weitere Ausgabelimits hinzu, um den Cashflow Ihres Unternehmens zu sc
                 subtitle: 'Als nächsten Schritt <a href="#">schließe deine Einrichtungs-Checkliste ab</a>, damit dein Team mit der Spesenerfassung beginnen kann.',
             },
             trialStarted: {
-                title: (numOfDays: number) => `Testversion: Noch ${numOfDays} ${numOfDays === 1 ? 'Tag' : 'Tage'} übrig!`,
+                title: ({numOfDays}: TrialStartedTitleParams) => `Testversion: Noch ${numOfDays} ${numOfDays === 1 ? 'Tag' : 'Tage'} übrig!`,
                 subtitle: 'Füge eine Zahlungskarte hinzu, um alle deine Lieblingsfunktionen weiterhin nutzen zu können.',
             },
             trialEnded: {
@@ -9233,15 +7993,15 @@ Fügen Sie weitere Ausgabelimits hinzu, um den Cashflow Ihres Unternehmens zu sc
             title: 'Ihr Tarif',
             exploreAllPlans: 'Alle Tarife anzeigen',
             customPricing: 'Individuelle Preise',
-            asLowAs: (price: string) => `schon ab ${price} pro aktivem Mitglied/Monat`,
-            pricePerMemberMonth: (price: string) => `${price} pro Mitglied/Monat`,
-            pricePerMemberPerMonth: (price: string) => `${price} pro Mitglied und Monat`,
+            asLowAs: ({price}: YourPlanPriceValueParams) => `schon ab ${price} pro aktivem Mitglied/Monat`,
+            pricePerMemberMonth: ({price}: YourPlanPriceValueParams) => `${price} pro Mitglied/Monat`,
+            pricePerMemberPerMonth: ({price}: YourPlanPriceValueParams) => `${price} pro Mitglied und Monat`,
             perMemberMonth: 'pro Mitglied/Monat',
             collect: {
                 title: 'Einziehen',
                 description: 'Der Kleinunternehmens-Tarif, der dir Spesen, Reisen und Chat bietet.',
-                priceAnnual: ({lower, upper}: YourPlanPriceParams) => `Von ${lower}/aktivem Mitglied mit der Expensify Karte, ${upper}/aktivem Mitglied ohne die Expensify Karte.`,
-                pricePayPerUse: ({lower, upper}: YourPlanPriceParams) => `Von ${lower}/aktivem Mitglied mit der Expensify Karte, ${upper}/aktivem Mitglied ohne die Expensify Karte.`,
+                priceAnnual: ({lower, upper}: YourPlanPriceParams) => `Von ${lower}/aktivem Mitglied mit der Expensify Card, ${upper}/aktivem Mitglied ohne die Expensify Card.`,
+                pricePayPerUse: ({lower, upper}: YourPlanPriceParams) => `Von ${lower}/aktivem Mitglied mit der Expensify Card, ${upper}/aktivem Mitglied ohne die Expensify Card.`,
                 benefit1: 'Belegerfassung',
                 benefit2: 'Erstattungen',
                 benefit3: 'Firmenkartenverwaltung',
@@ -9254,8 +8014,8 @@ Fügen Sie weitere Ausgabelimits hinzu, um den Cashflow Ihres Unternehmens zu sc
             control: {
                 title: 'Steuerung',
                 description: 'Spesen, Reisen und Chat für größere Unternehmen.',
-                priceAnnual: ({lower, upper}: YourPlanPriceParams) => `Von ${lower}/aktivem Mitglied mit der Expensify Karte, ${upper}/aktivem Mitglied ohne die Expensify Karte.`,
-                pricePayPerUse: ({lower, upper}: YourPlanPriceParams) => `Von ${lower}/aktivem Mitglied mit der Expensify Karte, ${upper}/aktivem Mitglied ohne die Expensify Karte.`,
+                priceAnnual: ({lower, upper}: YourPlanPriceParams) => `Von ${lower}/aktivem Mitglied mit der Expensify Card, ${upper}/aktivem Mitglied ohne die Expensify Card.`,
+                pricePayPerUse: ({lower, upper}: YourPlanPriceParams) => `Von ${lower}/aktivem Mitglied mit der Expensify Card, ${upper}/aktivem Mitglied ohne die Expensify Card.`,
                 benefit1: 'Alles im Collect-Tarif',
                 benefit2: 'Genehmigungs-Workflows mit mehreren Ebenen',
                 benefit3: 'Benutzerdefinierte Ausgabenregeln',
@@ -9269,8 +8029,8 @@ Fügen Sie weitere Ausgabelimits hinzu, um den Cashflow Ihres Unternehmens zu sc
             downgrade: 'Downgrade auf Collect',
             upgrade: 'Upgrade auf Control',
             addMembers: 'Mitglieder hinzufügen',
-            saveWithExpensifyTitle: 'Sparen mit der Expensify Karte',
-            saveWithExpensifyDescription: 'Verwenden Sie unseren Einsparungsrechner, um zu sehen, wie das Cashback der Expensify Karte Ihre Expensify Rechnung reduzieren kann.',
+            saveWithExpensifyTitle: 'Sparen mit der Expensify Card',
+            saveWithExpensifyDescription: 'Nutze unseren Sparrechner, um zu sehen, wie das Cashback der Expensify Card deine Expensify-Rechnung senken kann.',
             saveWithExpensifyButton: 'Mehr erfahren',
         },
         compareModal: {
@@ -9280,7 +8040,6 @@ Fügen Sie weitere Ausgabelimits hinzu, um den Cashflow Ihres Unternehmens zu sc
         details: {
             title: 'Abonnementdetails',
             annual: 'Jahresabonnement',
-            creditBalance: 'Guthaben',
             taxExempt: 'Steuerbefreiungsstatus beantragen',
             taxExemptEnabled: 'Steuerbefreit',
             taxExemptStatus: 'Steuerbefreiungsstatus',
@@ -9298,10 +8057,10 @@ Fügen Sie weitere Ausgabelimits hinzu, um den Cashflow Ihres Unternehmens zu sc
             note: 'Hinweis: Ein aktives Mitglied ist jede Person, die Ausgabedaten, die mit dem Workspace Ihres Unternehmens verknüpft sind, erstellt, bearbeitet, eingereicht, genehmigt, erstattet oder exportiert hat.',
             confirmDetails: 'Bestätige die Details deines neuen Jahresabos:',
             subscriptionSize: 'Abonnementgröße',
-            activeMembers: (size: number) => `${size} aktive Mitglieder/Monat`,
+            activeMembers: ({size}: SubscriptionSizeParams) => `${size} aktive Mitglieder/Monat`,
             subscriptionRenews: 'Abonnement verlängert sich',
             youCantDowngrade: 'Sie können Ihr Jahresabonnement während der Laufzeit nicht herabstufen.',
-            youAlreadyCommitted: (size: number, date: string) =>
+            youAlreadyCommitted: ({size, date}: SubscriptionCommitmentParams) =>
                 `Sie haben sich bereits bis ${date} zu einem jährlichen Abonnement mit ${size} aktiven Mitgliedern pro Monat verpflichtet. Sie können am ${date} zu einem nutzungsbasierten Abonnement wechseln, indem Sie die automatische Verlängerung deaktivieren.`,
             error: {
                 size: 'Bitte gib eine gültige Abonnementgröße ein',
@@ -9314,50 +8073,37 @@ Fügen Sie weitere Ausgabelimits hinzu, um den Cashflow Ihres Unternehmens zu sc
             security: 'Expensify ist PCI-DSS-konform, verwendet eine Verschlüsselung auf Bankniveau und setzt redundante Infrastruktur ein, um Ihre Daten zu schützen.',
             learnMoreAboutSecurity: 'Erfahren Sie mehr über unsere Sicherheit.',
         },
-        expensifyCode: {
-            title: 'Expensify-Code',
-            discountCode: 'Rabattcode',
-            enterCode: 'Geben Sie einen Expensify-Code ein, um ihn auf Ihr Abonnement anzuwenden.',
-            discountMessage: (promoDiscount: string, validBillingCycles: string) =>
-                `Du erhältst ${promoDiscount}% Rabatt auf deine nächsten ${validBillingCycles ? `${validBillingCycles} ` : ''}Abrechnungen.`,
-            apply: 'Anwenden',
-            error: {
-                invalid: 'Dieser Code ist ungültig',
-            },
-        },
         subscriptionSettings: {
             title: 'Abonnementeinstellungen',
-            summary: (subscriptionType: string, subscriptionSize: string, expensifyCode: string, autoRenew: string, autoIncrease: string) =>
-                `Abonnementstyp: ${subscriptionType}, Abonnementgröße: ${subscriptionSize}${expensifyCode ? `, Expensify-Code: ${expensifyCode}` : ''}, Automatische Verlängerung: ${autoRenew}, Automatische jährliche Sitzplatzerhöhung: ${autoIncrease}`,
+            summary: ({subscriptionType, subscriptionSize, autoRenew, autoIncrease}: SubscriptionSettingsSummaryParams) =>
+                `Abonnementstyp: ${subscriptionType}, Abonnementgröße: ${subscriptionSize}, Automatische Verlängerung: ${autoRenew}, Automatische jährliche Sitzplatzerhöhung: ${autoIncrease}`,
             none: 'keine',
             on: 'an',
             off: 'aus',
             annual: 'Jährlich',
             autoRenew: 'Automatisch verlängern',
             autoIncrease: 'Jährliche Plätze automatisch erhöhen',
-            saveUpTo: (amountWithCurrency: string) => `Spare bis zu ${amountWithCurrency}/Monat pro aktivem Mitglied`,
+            saveUpTo: ({amountWithCurrency}: SubscriptionSettingsSaveUpToParams) => `Spare bis zu ${amountWithCurrency}/Monat pro aktivem Mitglied`,
             automaticallyIncrease:
                 'Erhöhe deine jährlichen Plätze automatisch, um aktive Mitglieder zu berücksichtigen, die deine Abonnementgröße überschreiten. Hinweis: Dadurch wird das Enddatum deines Jahresabonnements verlängert.',
             disableAutoRenew: 'Automatische Verlängerung deaktivieren',
             helpUsImprove: 'Hilf uns, Expensify zu verbessern',
             whatsMainReason: 'Was ist der Hauptgrund, warum du die automatische Verlängerung deaktivierst?',
-            renewsOn: (date: string) => `Verlängert sich am ${date}.`,
-            pricingConfiguration: 'Die Preise hängen von der Konfiguration ab. Wählen Sie für den niedrigsten Preis ein Jahresabonnement und nutzen Sie die Expensify Karte.',
-            learnMore: (hasAdminsRoom: boolean) =>
+            renewsOn: ({date}: SubscriptionSettingsRenewsOnParams) => `Verlängert sich am ${date}.`,
+            pricingConfiguration: 'Die Preise hängen von der Konfiguration ab. Wählen Sie für den niedrigsten Preis ein Jahresabonnement und holen Sie sich die Expensify Card.',
+            learnMore: ({hasAdminsRoom}: SubscriptionSettingsLearnMoreParams) =>
                 `<muted-text>Erfahre mehr auf unserer <a href="${CONST.PRICING}">Preisseite</a> oder chatte mit unserem Team in deinem ${hasAdminsRoom ? `<a href="adminsRoom">#admins-Raum.</a>` : '#admins-Raum.'}</muted-text>`,
             estimatedPrice: 'Geschätzter Preis',
-            changesBasedOn: 'Dies ändert sich basierend auf Ihrer Nutzung der Expensify Karte und den untenstehenden Abooptionen.',
-            collectBillingDescription: 'Collect-Arbeitsbereiche werden monatlich pro Mitglied ohne jährliche Verpflichtung abgerechnet.',
-            pricing: 'Preise',
+            changesBasedOn: 'Dies ändert sich basierend auf deiner Expensify Card-Nutzung und den untenstehenden Abo-Optionen.',
         },
-        cancelSubscription: {
-            title: 'Abonnement kündigen',
-            subtitle: 'Was ist der Hauptgrund, warum du dein Abonnement kündigst?',
+        requestEarlyCancellation: {
+            title: 'Frühzeitige Kündigung anfordern',
+            subtitle: 'Was ist der Hauptgrund, warum du eine vorzeitige Kündigung beantragst?',
             subscriptionCanceled: {
                 title: 'Abonnement gekündigt',
                 subtitle: 'Dein Jahresabonnement wurde gekündigt.',
                 info: 'Wenn du deine(n) Arbeitsbereich(e) weiterhin nutzungsbasiert bezahlen möchtest, bist du startklar.',
-                preventFutureActivity: (workspacesListRoute: string) =>
+                preventFutureActivity: ({workspacesListRoute}: WorkspacesListRouteParams) =>
                     `Wenn du zukünftige Aktivitäten und Gebühren verhindern möchtest, musst du deinen <a href="${workspacesListRoute}">Workspace bzw. deine Workspaces löschen</a>. Bitte beachte, dass dir beim Löschen deines Workspace bzw. deiner Workspaces alle ausstehenden Aktivitäten in Rechnung gestellt werden, die im aktuellen Kalendermonat angefallen sind.`,
             },
             requestSubmitted: {
@@ -9365,7 +8111,7 @@ Fügen Sie weitere Ausgabelimits hinzu, um den Cashflow Ihres Unternehmens zu sc
                 subtitle:
                     'Danke, dass du uns mitgeteilt hast, dass du dein Abonnement kündigen möchtest. Wir prüfen deine Anfrage und melden uns in Kürze über deinen Chat mit <concierge-link>Concierge</concierge-link>.',
             },
-            acknowledgement: `Mit dem Antrag auf Kündigung erkenne ich an und stimme zu, dass Expensify gemäß den Expensify-<a href=${CONST.OLD_DOT_PUBLIC_URLS.TERMS_URL}>Nutzungsbedingungen</a> oder einer sonstigen anwendbaren Servicevereinbarung zwischen mir und Expensify nicht verpflichtet ist, einem solchen Antrag stattzugeben, und dass Expensify das alleinige Ermessen in Bezug auf die Genehmigung eines solchen Antrags behält.`,
+            acknowledgement: `Mit dem Antrag auf vorzeitige Kündigung erkenne ich an und stimme zu, dass Expensify gemäß den Expensify-<a href=${CONST.OLD_DOT_PUBLIC_URLS.TERMS_URL}>Nutzungsbedingungen</a> oder einer sonstigen anwendbaren Servicevereinbarung zwischen mir und Expensify nicht verpflichtet ist, einem solchen Antrag stattzugeben, und dass Expensify das alleinige Ermessen in Bezug auf die Genehmigung eines solchen Antrags behält.`,
         },
     },
     feedbackSurvey: {
@@ -9384,14 +8130,11 @@ Fügen Sie weitere Ausgabelimits hinzu, um den Cashflow Ihres Unternehmens zu sc
     },
     delegate: {
         switchAccount: 'Konten wechseln:',
-        switch: 'Wechseln',
-        copilot: 'Copilot',
         copilotDelegatedAccess: 'Copilot: Delegierter Zugriff',
         copilotDelegatedAccessDescription: 'Anderen Mitgliedern erlauben, auf dein Konto zuzugreifen.',
-        learnMoreAboutDelegatedAccess: 'Mehr über delegierten Zugriff erfahren',
         addCopilot: 'Copilot hinzufügen',
         membersCanAccessYourAccount: 'Diese Mitglieder haben Zugriff auf Ihr Konto:',
-        youCanAccessTheseAccounts: 'Du kannst auf diese Konten zugreifen:',
+        youCanAccessTheseAccounts: 'Du kannst auf diese Konten über den Kontowechsel zugreifen:',
         role: ({role}: OptionalParam<DelegateRoleParams> = {}) => {
             switch (role) {
                 case CONST.DELEGATE_ROLE.ALL:
@@ -9510,7 +8253,6 @@ Fügen Sie weitere Ausgabelimits hinzu, um den Cashflow Ihres Unternehmens zu sc
             theresWasAProblemDuringAWorkspaceConnectionSync: 'Während der Synchronisierung der Workspace-Verbindung ist ein Problem aufgetreten',
             theresAProblemWithYourWallet: 'Es gibt ein Problem mit deinem Wallet',
             theresAProblemWithYourWalletTerms: 'Es gibt ein Problem mit deinen Wallet-Bedingungen',
-            aBankAccountIsLocked: 'Ein Bankkonto ist gesperrt',
         },
     },
     emptySearchView: {
@@ -9531,10 +8273,15 @@ Fügen Sie weitere Ausgabelimits hinzu, um den Cashflow Ihres Unternehmens zu sc
         conciergeLHNGBR: '<tooltip>Beginne <strong>hier!</strong></tooltip>',
         saveSearchTooltip: '<tooltip><strong>Benenne deine gespeicherten Suchen um</strong> – hier!</tooltip>',
         accountSwitcher: '<tooltip>Greifen Sie hier auf Ihre <strong>Copilot-Konten</strong> zu</tooltip>',
+        scanTestTooltip: {
+            main: '<tooltip><strong>Scanne unseren Testbeleg</strong>, um zu sehen, wie es funktioniert!</tooltip>',
+            manager: '<tooltip>Wähle unseren <strong>Testmanager</strong>, um es auszuprobieren!</tooltip>',
+            confirmation: '<tooltip>Jetzt <strong>reiche deine Ausgabe ein</strong> und sieh zu, wie die Magie passiert!</tooltip>',
+            tryItOut: 'Probiere es aus',
+        },
         outstandingFilter: '<tooltip>Nach Ausgaben filtern,\ndie <strong>genehmigt werden müssen</strong></tooltip>',
         scanTestDriveTooltip: '<tooltip>Sende diese Quittung, um\n<strong>die Probefahrt abzuschließen!</strong></tooltip>',
         gpsTooltip: '<tooltip>GPS-Tracking läuft! Wenn du fertig bist, stoppe die Aufzeichnung unten.</tooltip>',
-        hasFilterNegation: '<tooltip>Suchen Sie nach Ausgaben ohne Belege mit <strong>-has:receipt</strong>.</tooltip>',
     },
     discardChangesConfirmation: {
         title: 'Änderungen verwerfen?',
@@ -9550,7 +8297,7 @@ Fügen Sie weitere Ausgabelimits hinzu, um den Cashflow Ihres Unternehmens zu sc
         confirmation: {
             title: 'Anruf bestätigen',
             description: 'Stell sicher, dass die Details unten für dich gut aussehen. Sobald du den Anruf bestätigst, senden wir dir eine Einladung mit weiteren Informationen.',
-            setupSpecialist: 'Ihre Account Managerin / Ihr Account Manager',
+            setupSpecialist: 'Ihre*e*r Einrichtungsspezialist*in',
             meetingLength: 'Meetingdauer',
             dateTime: 'Datum & Uhrzeit',
             minutes: '30 Minuten',
@@ -9598,20 +8345,6 @@ Hier ist ein *Testbeleg*, um dir zu zeigen, wie es funktioniert:`,
         exportInProgress: 'Export wird ausgeführt',
         conciergeWillSend: 'Concierge wird dir die Datei in Kürze senden.',
     },
-    exportDownload: {
-        preparingTitle: 'Preparing download...',
-        preparingBody: 'You can either wait for the download to finish or Concierge can send it to you via chat.',
-        sendFromConcierge: "Send me the file when it's ready",
-        conciergeTitle: 'You bet!',
-        conciergeBody: 'Concierge will send you a message when the file is ready.',
-        goToConcierge: 'Go to Concierge',
-        dismiss: 'Dismiss',
-        readyTitle: 'Your file is ready!',
-        readyBody: "If it didn't automatically download, use the button below.",
-        downloadFile: 'Download file',
-        failedTitle: 'Export failed',
-        close: 'Close',
-    },
     domain: {
         notVerified: 'Nicht verifiziert',
         retry: 'Wiederholen',
@@ -9655,8 +8388,6 @@ Hier ist ein *Testbeleg*, um dir zu zeigen, wie es funktioniert:`,
             disableSamlRequired: 'Deaktivierung von SAML erforderlich',
             oktaWarningPrompt: 'Bist du sicher? Dadurch wird auch Okta SCIM deaktiviert.',
             requireWithEmptyMetadataError: 'Bitte fügen Sie unten die Metadaten des Identitätsanbieters hinzu, um dies zu aktivieren',
-            pleaseDisableTwoFactorAuth: (twoFactorAuthSettingsUrl: string) =>
-                `<muted-text>Bitte deaktiviere <a href="${twoFactorAuthSettingsUrl}">Zwei-Faktor-Authentifizierung erzwingen</a>, um die SAML-Anmeldung zu aktivieren.</muted-text>`,
         },
         samlConfigurationDetails: {
             title: 'SAML-Konfigurationsdetails',
@@ -9706,6 +8437,7 @@ Hier ist ein *Testbeleg*, um dir zu zeigen, wie es funktioniert:`,
             primaryContact: 'Hauptansprechperson',
             addPrimaryContact: 'Hauptkontakt hinzufügen',
             setPrimaryContactError: 'Primären Kontakt konnte nicht festgelegt werden. Bitte versuche es später erneut.',
+            settings: 'Einstellungen',
             consolidatedDomainBilling: 'Konsolidierte Domain-Abrechnung',
             consolidatedDomainBillingDescription: (domainName: string) =>
                 `<comment><muted-text-label>Wenn diese Option aktiviert ist, bezahlt die primäre Kontaktperson alle Workspaces, die Mitgliedern von <strong>${domainName}</strong> gehören, und erhält alle Abrechnungsbelege.</muted-text-label></comment>`,
@@ -9722,107 +8454,25 @@ Hier ist ein *Testbeleg*, um dir zu zeigen, wie es funktioniert:`,
             resetDomain: 'Domain zurücksetzen',
             resetDomainExplanation: ({domainName}: {domainName?: string}) => `Bitte gib zur Bestätigung des Zurücksetzens der Domain <strong>${domainName}</strong> ein.`,
             enterDomainName: 'Gib hier deinen Domainnamen ein',
-            resetDomainInfo: `Diese Aktion ist <strong>dauerhaft</strong> und die folgenden Daten werden gelöscht: <br/> <bullet-list><bullet-item>Firmenkartenzugänge und alle nicht eingereichten Ausgaben dieser Karten</bullet-item><bullet-item>SAML- und Gruppeneinstellungen</bullet-item><bullet-item>Reisedaten und Zugang zu Expensify Travel</bullet-item></bullet-list> Alle Konten, Arbeitsbereiche, Berichte, Ausgaben und anderen Daten bleiben erhalten. <br/><br/>Hinweis: Sie können diese Domain aus Ihrer Domainliste entfernen, indem Sie die zugehörige E-Mail-Adresse aus Ihren <a href="#">Kontaktmethoden</a> löschen.`,
+            resetDomainInfo: `Diese Aktion ist <strong>dauerhaft</strong> und die folgenden Daten werden gelöscht: <br/> <ul><li>Firmenkartenzugänge und alle nicht eingereichten Ausgaben dieser Karten</li> <li>SAML- und Gruppeneinstellungen</li> </ul> Alle Konten, Workspaces, Berichte, Ausgaben und andere Daten bleiben erhalten. <br/><br/>Hinweis: Sie können diese Domain aus Ihrer Domainliste entfernen, indem Sie die zugehörige E-Mail aus Ihren <a href="#">Kontaktmethoden</a> entfernen.`,
         },
         domainMembers: 'Domänenmitglieder',
         members: {
             title: 'Mitglieder',
             findMember: 'Mitglied finden',
             addMember: 'Mitglied hinzufügen',
-            allMembers: 'Alle Mitglieder',
             email: 'E-Mail-Adresse',
-            closeAccount: () => ({
-                one: 'Konto schließen',
-                other: 'Konten schließen',
-            }),
+            closeAccount: 'Konto schließen',
             closeAccountPrompt: 'Bist du sicher? Diese Aktion ist dauerhaft.',
-            forceCloseAccount: () => ({one: 'Konto zwangsweise schließen', other: 'Konten zwangsweise schließen'}),
-            safeCloseAccount: () => ({
-                one: 'Konto sicher schließen',
-                other: 'Konten sicher schließen',
-            }),
-            closeAccountInfo: () => ({
-                one: 'Wir empfehlen, das Konto sicher zu schließen, um das Schließen zu überspringen, falls Folgendes vorliegt: <bullet-list><bullet-item>Ausstehende Genehmigungen</bullet-item><bullet-item>Aktive Erstattungen</bullet-item><bullet-item>Keine alternativen Anmeldemethoden</bullet-item></bullet-list>Andernfalls können Sie die oben genannten Sicherheitsvorkehrungen ignorieren und das ausgewählte Konto zwangsweise schließen.',
-                other: 'Wir empfehlen, die Konten sicher zu schließen, um das Schließen zu überspringen, falls Folgendes vorliegt: <bullet-list><bullet-item>Ausstehende Genehmigungen</bullet-item><bullet-item>Aktive Erstattungen</bullet-item><bullet-item>Keine alternativen Anmeldemethoden</bullet-item></bullet-list>Andernfalls können Sie die oben genannten Sicherheitsvorkehrungen ignorieren und die ausgewählten Konten zwangsweise schließen.',
-            }),
+            forceCloseAccount: 'Konto zwangsweise schließen',
+            safeCloseAccount: 'Konto sicher schließen',
+            closeAccountInfo:
+                'Wir empfehlen, das Konto sicher zu schließen, um das Schließen zu überspringen, falls Folgendes vorliegt: <ul><li>Ausstehende Genehmigungen</li><li>Aktive Erstattungen</li><li>Keine alternativen Anmeldemethoden</li></ul>Andernfalls können Sie die oben genannten Sicherheitsvorkehrungen ignorieren und das ausgewählte Konto zwangsweise schließen.',
             error: {
                 removeMember: 'Dieser Benutzer kann nicht entfernt werden. Bitte versuche es erneut.',
                 addMember: 'Dieses Mitglied kann nicht hinzugefügt werden. Bitte versuche es erneut.',
-                vacationDelegate: 'Dieser Benutzer kann nicht als Urlaubsvertretung festgelegt werden. Bitte versuche es erneut.',
-                moveMember: 'Dieses Mitglied kann nicht verschoben werden. Bitte versuchen Sie es erneut.',
-                moveMemberNotPolicyAdmin:
-                    'Das Mitglied kann nicht in die Domänengruppe verschoben werden. Sie müssen Richtlinienadministrator für die bevorzugte Richtlinie sein, die für die Domänengruppe festgelegt ist, in die Sie diesen Benutzer verschieben möchten.',
-            },
-            reportSuspiciousActivityPrompt: (email: string) =>
-                `Bist du sicher? Dadurch wird das Konto von <strong>${email}</strong> gesperrt. <br /><br /> Unser Team wird das Konto anschließend überprüfen und unbefugten Zugriff entfernen. Um den Zugriff wiederherzustellen, muss die Person mit Concierge zusammenarbeiten.`,
-            reportSuspiciousActivityConfirmationPrompt: 'Wir überprüfen das Konto, um sicherzustellen, dass es sicher entsperrt werden kann, und melden uns bei Fragen über Concierge.',
-            cannotSetVacationDelegateForMember: (email: string) => `Du kannst keine Urlaubsvertretung für ${email} festlegen, weil sie derzeit die Vertretung für folgende Mitglieder sind:`,
-            emptyMembers: {title: 'Keine Mitglieder in dieser Gruppe', subtitle: 'Fügen Sie ein Mitglied hinzu oder versuchen Sie, den Filter oben zu ändern.'},
-            moveToGroup: 'In Gruppe verschieben',
-            chooseWhereToMove: ({count}: {count: number}) => `Wählen Sie aus, wohin Sie ${count} ${count === 1 ? 'Mitglied' : 'Mitglieder'} verschieben möchten.`,
-            domainGroup: 'Domain-Gruppe',
-            chooseWhereToMoveName: ({name}: {name: string}) => `Wähle aus, wohin ${name} verschoben werden soll.`,
-            membersFeatureList: {
-                subtitle: ({domainName}: {domainName: string}) =>
-                    `<muted-text>Bestätigen Sie Ihre Domain, um mehr Kontrolle über <strong>${domainName}</strong>-Mitglieder in Expensify zu erhalten.</muted-text>`,
-                controlPolicyCreation: 'Arbeitsbereichserstellung einschränken',
-                enableSamlSso: 'SAML-SSO aktivieren',
-                enforce2FA: '2FA erzwingen',
             },
         },
-        common: {
-            settings: 'Einstellungen',
-            forceTwoFactorAuth: 'Zwei-Faktor-Authentifizierung erzwingen',
-            forceTwoFactorAuthSAMLEnabledDescription: (samlPageUrl: string) =>
-                `<muted-text>Bitte deaktiviere <a href="${samlPageUrl}">SAML</a>, um die Zwei-Faktor-Authentifizierung zu erzwingen.</muted-text>`,
-            forceTwoFactorAuthDescription: `<muted-text>Zwei-Faktor-Authentifizierung für alle Mitglieder dieser Domain verlangen. Domänenmitglieder werden beim Anmelden aufgefordert, die Zwei-Faktor-Authentifizierung für ihr Konto einzurichten.</muted-text>`,
-            forceTwoFactorAuthError: 'Die Erzwingung der Zwei-Faktor-Authentifizierung konnte nicht geändert werden. Bitte versuche es später erneut.',
-            resetTwoFactorAuth: 'Zwei-Faktor-Authentifizierung zurücksetzen',
-            error: 'Diese Änderung konnte nicht gespeichert werden. Bitte versuche es erneut.',
-        },
-        groups: {
-            title: 'Gruppen',
-            memberCount: () => ({one: '1 Mitglied', other: (count: number) => `${count} Mitglieder`}),
-            defaultGroup: 'Standardgruppe für neue Mitglieder',
-            defaultGroupPrompt: (currentName: string, newName: string) =>
-                `Möchtest du ${newName} wirklich zur Standardgruppe machen? Neue Mitglieder werden zu dieser Gruppe anstelle der bisherigen Standardgruppe (${currentName}) eingeladen. `,
-            makeDefault: 'Als Standard festlegen',
-            neverMind: 'Vergiss es',
-            createGroupError: 'Diese Gruppe konnte nicht erstellt werden. Bitte versuche es erneut.',
-            permissions: 'Gruppenberechtigungen',
-            createNewGroupButton: 'Neue Gruppe',
-            createGroupSubmitButton: 'Gruppe erstellen',
-            expensifyCardPreferredWorkspace: 'Bevorzugter Workspace für Expensify Card',
-            expensifyCardPreferredWorkspaceDescription:
-                'Alle Expensify Card-Transaktionen werden im bevorzugten Expensify Card-Arbeitsbereich anstelle des bevorzugten Arbeitsbereichs erstellt. Durch Aktivieren dieser Funktion wird die Einstellung des bevorzugten Arbeitsbereichs nur für Expensify Card-Transaktionen überschrieben.',
-            strictlyEnforceWorkspaceRules: 'Workspace-Regeln strikt durchsetzen',
-            strictlyEnforceWorkspaceRulesDescription: 'Alle Workspace-Regeln müssen erfüllt sein, bevor ein Bericht eingereicht wird. Manuelle Ausnahmen sind nicht zulässig.',
-            restrictExpenseWorkspaceCreation: 'Erstellen/Entfernen von Ausgaben-Workspaces einschränken',
-            restrictExpenseWorkspaceCreationDescription:
-                'Verhindert, dass Mitglieder einen Ausgaben-Workspace erstellen oder sich selbst aus einem Ausgaben-Workspace entfernen können. Dies ist nützlich, um zu verhindern, dass Personen Expensify verwenden, um Berichte für die Nutzung außerhalb deiner Domain einzureichen, wenn es mit einer strikten Workspace-Durchsetzung kombiniert wird.',
-            deleteGroup: 'Gruppe löschen',
-            deleteGroupDangerConfirmationModal: 'Gruppe löschen',
-            deleteGroupDangerConfirmationModalDescription: (defaultGroupName: string) =>
-                `Bist du sicher? Dadurch werden alle Mitglieder der Standardgruppe (${defaultGroupName}) neu zugewiesen und dies kann nicht rückgängig gemacht werden.`,
-            deleteGroupError: 'Diese Gruppe konnte nicht gelöscht werden. Bitte versuche es erneut.',
-            preferredWorkspace: 'Bevorzugter Arbeitsbereich',
-            preferredWorkspaceDescription: (enabled: boolean) => `Alle neuen Berichte und Ausgaben werden im ${enabled ? 'ausgewählten bevorzugten' : 'diesem'} Arbeitsbereich erstellt.`,
-            preferredWorkspaceSelectDescription: 'Alle neuen Ausgaben und Berichte werden in diesem Arbeitsbereich erstellt.',
-            noWorkspacesMessage: 'Es gibt keine Arbeitsbereiche in dieser Domain. Ein Arbeitsbereich ist erforderlich, um diese Einschränkung zu aktivieren.',
-            restrictDefaultLoginSelection: 'Standard-Login-Auswahl einschränken',
-            restrictDefaultLoginSelectionDescription:
-                'Verhindert, dass Mitglieder ihre Login-E-Mail-Adresse außerhalb der Unternehmensdomäne ändern, um Richtlinienbeschränkungen zu umgehen.',
-            expensifyCardPreferredWorkspaceDisabledMessage:
-                'Um diese Einstellung zu aktivieren, aktiviere zuerst einen bevorzugten Workspace und richte Expensify Cards in deiner Domain ein.',
-            findGroup: 'Gruppe suchen',
-        },
-    },
-    proactiveAppReview: {
-        title: 'Gefällt dir das neue Expensify?',
-        description: 'Lass es uns wissen, damit wir dir helfen können, deine Abrechnungserfahrung noch besser zu machen.',
-        positiveButton: 'Ja!',
-        negativeButton: 'Nicht wirklich',
-    },
-    monthPickerPage: {month: 'Monat', selectMonth: 'Bitte wählen Sie einen Monat aus'},
+    },
 };
 export default translations;
diff --git a/src/languages/es.ts b/src/languages/es.ts
index c54584768a54..1d01c26234e9 100644
--- a/src/languages/es.ts
+++ b/src/languages/es.ts
@@ -1,22 +1,13 @@
-/**
- *   _____                      __         __
- *  / ___/__ ___  ___ _______ _/ /____ ___/ /
- * / (_ / -_) _ \/ -_) __/ _ \`/ __/ -_) _  /
- * \___/\__/_//_/\__/_/  \_,_/\__/\__/\_,_/
- *
- * This file was automatically generated. Please consider these alternatives before manually editing it:
- *
- * - Improve the prompts in prompts/translation, or
- * - Improve context annotations in src/languages/en.ts
- */
 import {CONST as COMMON_CONST} from 'expensify-common';
 import dedent from '@libs/StringUtils/dedent';
 import CONST from '@src/CONST';
-import type {OriginalMessageSettlementAccountLocked, PersonalRulesModifiedFields, PolicyRulesModifiedFields} from '@src/types/onyx/OriginalMessage';
+import type {OriginalMessageSettlementAccountLocked, PolicyRulesModifiedFields} from '@src/types/onyx/OriginalMessage';
+import ObjectUtils from '@src/types/utils/ObjectUtils';
 import type en from './en';
-import type {ConciergeBrokenCardConnectionParams, PaidElsewhereParams, UnsupportedFormulaValueErrorParams} from './params';
+import type {CreatedReportForUnapprovedTransactionsParams, PaidElsewhereParams, RoutedDueToDEWParams, SplitDateRangeParams, UpdatedPolicyTagParams, ViolationsRterParams} from './params';
 import type {TranslationDeepObject} from './types';
 
+/* eslint-disable max-len */
 const translations: TranslationDeepObject<typeof en> = {
     common: {
         count: 'Contar',
@@ -40,11 +31,9 @@ const translations: TranslationDeepObject<typeof en> = {
         optional: 'Opcional',
         new: 'Nuevo',
         newFeature: 'Nueva función',
-        beta: 'Beta',
         center: 'Centrar',
         search: 'Buscar',
         reports: 'Informes',
-        spend: 'Gastos',
         find: 'Encontrar',
         searchWithThreeDots: 'Buscar...',
         select: 'Seleccionar',
@@ -53,10 +42,6 @@ const translations: TranslationDeepObject<typeof en> = {
         next: 'Siguiente',
         create: 'Crear',
         previous: 'Anterior',
-        previousMonth: 'Mes anterior',
-        nextMonth: 'Próximo mes',
-        previousYear: 'Año anterior',
-        nextYear: 'Próximo año',
         goBack: 'Volver',
         add: 'Añadir',
         resend: 'Reenviar',
@@ -72,14 +57,6 @@ const translations: TranslationDeepObject<typeof en> = {
         twoFactorCode: 'Autenticación de dos factores',
         workspaces: 'Espacios de trabajo',
         inbox: 'Recibidos',
-        yourReviewIsRequired: 'Se requiere tu revisión',
-        actionBadge: {
-            submit: 'Enviar',
-            approve: 'Aprobar',
-            pay: 'Pagar',
-            fix: 'Corregir',
-            task: 'Tarea',
-        },
         home: 'Inicio',
         group: 'Grupo',
         profile: 'Perfil',
@@ -89,7 +66,7 @@ const translations: TranslationDeepObject<typeof en> = {
         wallet: 'Billetera',
         preferences: 'Preferencias',
         view: 'Ver',
-        review: (amount) => `Revisar${amount ? ` ${amount}` : ''}`,
+        review: (reviewParams) => `Revisar${reviewParams?.amount ? ` ${reviewParams?.amount}` : ''}`,
         not: 'No',
         privacyPolicy: 'la Política de Privacidad de Expensify',
         addCardTermsOfService: 'Términos de Servicio',
@@ -103,7 +80,6 @@ const translations: TranslationDeepObject<typeof en> = {
         lastName: 'Apellidos',
         scanning: 'Escaneando',
         analyzing: 'Analizando...',
-        thinking: 'Concierge está pensando...',
         phone: 'Teléfono',
         phoneNumber: 'Número de teléfono',
         phoneNumberPlaceholder: '(xxx) xxx-xxxx',
@@ -132,7 +108,6 @@ const translations: TranslationDeepObject<typeof en> = {
         members: 'Miembros',
         invite: 'Invitar',
         here: 'aquí',
-        avatar: 'Avatar',
         date: 'Fecha',
         dob: 'Fecha de nacimiento',
         currentYear: 'Año actual',
@@ -163,12 +138,10 @@ const translations: TranslationDeepObject<typeof en> = {
         admin: 'Administrador',
         owner: 'Dueño',
         dateFormat: 'AAAA-MM-DD',
-        calendarOpened: 'calendario abierto',
         send: 'Enviar',
         na: 'N/A',
         noResultsFound: 'No se han encontrado resultados',
         noResultsFoundMatching: (searchString: string) => `No se encontraron resultados que coincidan con "${searchString}"`,
-        suggestionsAvailableFor: (searchString: string) => (searchString ? `Sugerencias disponibles para "${searchString}".` : 'Sugerencias disponibles.'),
         recentDestinations: 'Destinos recientes',
         timePrefix: 'Son las',
         conjunctionFor: 'para',
@@ -179,7 +152,6 @@ const translations: TranslationDeepObject<typeof en> = {
         conjunctionTo: 'a',
         genericErrorMessage: 'Ups... algo no ha ido bien y la acción no se ha podido completar. Por favor, inténtalo más tarde.',
         percentage: 'Porcentaje',
-        progressBarLabel: 'Progreso de incorporación',
         converted: 'Convertido',
         error: {
             invalidAmount: 'Importe no válido',
@@ -219,7 +191,6 @@ const translations: TranslationDeepObject<typeof en> = {
         reset: 'Restablecer',
         done: 'Listo',
         more: 'Más',
-        other: 'Otro',
         debitCard: 'Tarjeta de débito',
         bankAccount: 'Cuenta bancaria',
         personalBankAccount: 'Cuenta bancaria personal',
@@ -245,7 +216,7 @@ const translations: TranslationDeepObject<typeof en> = {
         verify: 'Verifique',
         yesContinue: 'Sí, continuar',
         websiteExample: 'p. ej. https://www.expensify.com',
-        zipCodeExampleFormat: (zipSampleFormat: string) => (zipSampleFormat ? `p. ej. ${zipSampleFormat}` : ''),
+        zipCodeExampleFormat: ({zipSampleFormat}) => (zipSampleFormat ? `p. ej. ${zipSampleFormat}` : ''),
         description: 'Descripción',
         title: 'Título',
         assignee: 'Asignado a',
@@ -256,8 +227,6 @@ const translations: TranslationDeepObject<typeof en> = {
         per: 'por',
         mi: 'milla',
         km: 'kilómetro',
-        milesAbbreviated: 'mi',
-        kilometersAbbreviated: 'km',
         copied: '¡Copiado!',
         someone: 'Alguien',
         total: 'Total',
@@ -266,7 +235,6 @@ const translations: TranslationDeepObject<typeof en> = {
         letsStart: 'Empecemos',
         showMore: 'Mostrar más',
         showLess: 'Mostrar menos',
-        plusMore: ({count}: {count: number}) => `+${count} más`,
         merchant: 'Comerciante',
         change: 'Cambio',
         category: 'Categoría',
@@ -290,11 +258,8 @@ const translations: TranslationDeepObject<typeof en> = {
         selectCurrency: 'Selecciona una moneda',
         selectSymbolOrCurrency: 'Selecciona un símbolo o moneda',
         card: 'Tarjeta',
-        mcc: 'MCC',
-        categoryGLCode: 'Código de Libro Mayor de categoría',
         whyDoWeAskForThis: '¿Por qué pedimos esto?',
         required: 'Obligatorio',
-        automatic: 'Automático',
         showing: 'Mostrando',
         of: 'de',
         default: 'Predeterminado',
@@ -303,7 +268,6 @@ const translations: TranslationDeepObject<typeof en> = {
         success: 'Éxito',
         auditor: 'Auditor',
         role: 'Role',
-        roleCannotBeChanged: (workflowsLinkPage: string) => `El rol no se puede cambiar porque este miembro es un <a href="${workflowsLinkPage}">pagador</a> en este espacio de trabajo.`,
         currency: 'Divisa',
         groupCurrency: 'Moneda del grupo',
         rate: 'Tarifa',
@@ -341,7 +305,6 @@ const translations: TranslationDeepObject<typeof en> = {
         reportID: 'ID del informe',
         longReportID: 'ID de informe largo',
         withdrawalID: 'ID de retiro',
-        withdrawalStatus: 'Estado de retiro',
         bankAccounts: 'Cuentas bancarias',
         chooseFile: 'Elegir archivo',
         chooseFiles: 'Elegir archivos',
@@ -373,21 +336,19 @@ const translations: TranslationDeepObject<typeof en> = {
         validate: 'Validar',
         downloadAsPDF: 'Descargar como PDF',
         downloadAsCSV: 'Descargar como CSV',
-        print: 'Imprimir',
         help: 'Ayuda',
-        collapsed: 'Contraído',
-        expanded: 'Expandido',
         expenseReport: 'Informe de Gastos',
+        expenseReports: 'Informes de Gastos',
         rateOutOfPolicy: 'Tasa fuera de póliza',
         leaveWorkspace: 'Salir del espacio de trabajo',
         leaveWorkspaceConfirmation: 'Si sales de este espacio de trabajo, no podrás enviar gastos en él.',
         leaveWorkspaceConfirmationAuditor: 'Si sales de este espacio de trabajo, no podrás ver sus informes y configuraciones.',
         leaveWorkspaceConfirmationAdmin: 'Si sales de este espacio de trabajo, no podrás gestionar su configuración.',
-        leaveWorkspaceConfirmationApprover: (workspaceOwner: string) =>
+        leaveWorkspaceConfirmationApprover: ({workspaceOwner}: {workspaceOwner: string}) =>
             `Si sales de este espacio de trabajo, serás reemplazado en el flujo de aprobación por ${workspaceOwner}, el propietario del espacio de trabajo.`,
-        leaveWorkspaceConfirmationExporter: (workspaceOwner: string) =>
+        leaveWorkspaceConfirmationExporter: ({workspaceOwner}: {workspaceOwner: string}) =>
             `Si sales de este espacio de trabajo, serás reemplazado como el exportador preferido por ${workspaceOwner}, el propietario del espacio de trabajo.`,
-        leaveWorkspaceConfirmationTechContact: (workspaceOwner: string) =>
+        leaveWorkspaceConfirmationTechContact: ({workspaceOwner}: {workspaceOwner: string}) =>
             `Si dejas este espacio de trabajo, serás reemplazado como el contacto técnico por ${workspaceOwner}, el propietario del espacio de trabajo.`,
         leaveWorkspaceReimburser:
             'No puedes salir de este espacio de trabajo como reembolsador. Por favor, establece un nuevo reembolsador en Espacios de trabajo > Realizar o rastrear pagos y luego inténtalo de nuevo.',
@@ -396,6 +357,9 @@ const translations: TranslationDeepObject<typeof en> = {
         comments: 'Comentarios',
         sharedIn: 'Compartido en',
         unreported: 'No reportado',
+        explore: 'Explorar',
+        insights: 'Información',
+        todo: 'Tereas',
         invoice: 'Factura',
         expense: 'Gasto',
         chat: 'Chat',
@@ -406,15 +370,12 @@ const translations: TranslationDeepObject<typeof en> = {
         on: 'El',
         before: 'Antes',
         after: 'Después',
-        range: 'Rango',
         reschedule: 'Reprogramar',
         general: 'General',
         workspacesTabTitle: 'Espacios',
         headsUp: '¡Atención!',
         submitTo: 'Enviar a',
         forwardTo: 'Reenviar a',
-        approvalLimit: 'Límite de aprobación',
-        overLimitForwardTo: 'Reenviar si excede el límite',
         merge: 'Fusionar',
         none: 'Ninguno',
         unstableInternetConnection: 'Conexión a internet inestable. Por favor, revisa tu red e inténtalo de nuevo.',
@@ -432,48 +393,18 @@ const translations: TranslationDeepObject<typeof en> = {
         duplicate: 'Duplicar',
         duplicated: 'Duplicado',
         duplicateExpense: 'Duplicar gasto',
-        duplicateReport: 'Duplicar informe',
-        copyOfReportName: (reportName: string) => `Copia de ${reportName}`,
         exchangeRate: 'Tipo de cambio',
         reimbursableTotal: 'Total reembolsable',
         nonReimbursableTotal: 'Total no reembolsable',
-        opensInNewTab: 'Se abre en una nueva pestaña',
         locked: 'Bloqueado',
         month: 'Monat',
         week: 'Semana',
         year: 'Año',
         quarter: 'Trimestre',
-        concierge: {
-            greeting: 'Hola, ¿en qué puedo ayudarte?',
-            showHistory: 'Mostrar historial',
-        },
-        vacationDelegate: 'Delegado de vacaciones',
-        expensifyLogo: 'Logo de Expensify',
-        approver: 'Aprobador',
-        goToConcierge: 'Ir a Concierge',
-        allSet: '¡Todo listo!',
-        enterDigitLabel: ({digitIndex, totalDigits}: {digitIndex: number; totalDigits: number}) => `introducir dígito ${digitIndex} de ${totalDigits}`,
-        editor: 'Editor',
-        restrictions: 'Restricciones',
-    },
-    socials: {
-        podcast: 'Síguenos en Podcast',
-        twitter: 'Síguenos en Twitter',
-        instagram: 'Síguenos en Instagram',
-        facebook: 'Síguenos en Facebook',
-        linkedin: 'Síguenos en LinkedIn',
-    },
-    concierge: {
-        collapseReasoning: 'Contraer razonamiento',
-        expandReasoning: 'Expandir razonamiento',
-        enableNotifications: {
-            prompt: '¿Quieres que te avisemos cuando Concierge responda?',
-            cta: 'Notificar',
-        },
     },
     supportalNoAccess: {
         title: 'No tan rápido',
-        descriptionWithCommand: (command) =>
+        descriptionWithCommand: ({command} = {}) =>
             `No estás autorizado para realizar esta acción cuando el soporte ha iniciado sesión (comando: ${command ?? ''}). Si crees que Success debería poder realizar esta acción, inicia una conversación en Slack.`,
     },
     lockedAccount: {
@@ -513,7 +444,7 @@ const translations: TranslationDeepObject<typeof en> = {
         chooseDocument: 'Elegir un archivo',
         attachmentTooLarge: 'Archivo adjunto demasiado grande',
         sizeExceeded: 'El archivo adjunto supera el límite de 24 MB.',
-        sizeExceededWithLimit: (maxUploadSizeInMB) => `El archivo adjunto supera el límite de ${maxUploadSizeInMB} MB.`,
+        sizeExceededWithLimit: ({maxUploadSizeInMB}) => `El archivo adjunto supera el límite de ${maxUploadSizeInMB} MB.`,
         attachmentTooSmall: 'Archivo adjunto demasiado pequeño',
         sizeNotMet: 'El archivo adjunto debe ser más grande que 240 bytes.',
         wrongFileType: 'Tipo de archivo inválido',
@@ -524,9 +455,9 @@ const translations: TranslationDeepObject<typeof en> = {
         attachmentImageTooLarge: 'Esta imagen es demasiado grande para obtener una vista previa antes de subirla.',
         imageDimensionsTooLarge: 'Las dimensiones de la imagen son demasiado grandes para procesar. Por favor, usa una imagen más pequeña.',
         tooManyFiles: (fileLimit: number) => `Solamente puedes suber ${fileLimit} archivos a la vez.`,
-        sizeExceededWithValue: (maxUploadSizeInMB) => `El archivo supera los ${maxUploadSizeInMB} MB. Por favor, vuelve a intentarlo.`,
+        sizeExceededWithValue: ({maxUploadSizeInMB}) => `El archivo supera los ${maxUploadSizeInMB} MB. Por favor, vuelve a intentarlo.`,
         someFilesCantBeUploaded: 'Algunos archivos no se pueden subir',
-        sizeLimitExceeded: (maxUploadSizeInMB) => `Los archivos deben ser menores a ${maxUploadSizeInMB} MB. Los archivos más grandes no se subirán.`,
+        sizeLimitExceeded: ({maxUploadSizeInMB}) => `Los archivos deben ser menores a ${maxUploadSizeInMB} MB. Los archivos más grandes no se subirán.`,
         maxFileLimitExceeded: 'Puedes subir hasta 30 recibos a la vez. Los extras no se subirán.',
         unsupportedFileType: (fileType) => `${fileType} archivos no son compatibles. Solo se subirán los archivos compatibles.`,
         learnMoreAboutSupportedFiles: 'Obtén más información sobre los formatos compatibles.',
@@ -562,61 +493,22 @@ const translations: TranslationDeepObject<typeof en> = {
         signIn: 'Por favor, inicia sesión de nuevo.',
     },
     multifactorAuthentication: {
-        reviewTransaction: {
-            reviewTransaction: 'Revisar transacción',
-            pleaseReview: 'Por favor revisa esta transacción',
-            requiresYourReview: 'Una transacción con la tarjeta Expensify requiere tu revisión a continuación.',
-            transactionDetails: 'Detalles de la transacción',
-            attemptedTransaction: 'Intento de transacción',
-            deny: 'Rechazar',
-            approve: 'Aprobar',
-            denyTransaction: 'Rechazar transacción',
-            transactionDenied: 'Transacción rechazada',
-            transactionApproved: '¡Transacción aprobada!',
-            areYouSureToDeny: '¿Estás seguro? La transacción será rechazada si cierras esta pantalla.',
-            youCanTryAgainAtMerchantOrReachOut: 'Puedes intentarlo de nuevo en el comercio. Si no realizaste esta transacción, comunícate con Concierge para reportar un posible fraude.',
-            youNeedToTryAgainAtMerchant: 'Esta transacción no fue verificada, por lo que la hemos rechazado. Necesitarás intentarlo de nuevo en el comercio.',
-            goBackToTheMerchant: 'Regresa al sitio del comercio para continuar la transacción.',
-            transactionFailed: 'Transacción fallida',
-            transactionCouldNotBeCompleted: 'Su transacción no pudo ser completada. Por favor, inténtelo de nuevo en el comercio.',
-            transactionCouldNotBeCompletedReachOut:
-                'Su transacción no pudo ser completada. Si usted no intentó esta transacción, <concierge-link>póngase en contacto con el Concierge</concierge-link> para reportar un posible fraude.',
-            reviewFailed: 'Revisión fallida',
-            alreadyReviewedSubtitle:
-                'Ya ha revisado esta transacción. Por favor, revise su <transaction-history-link>historial de transacciones</transaction-history-link> o contacte a <concierge-link>Concierge</concierge-link> para reportar cualquier problema.',
-        },
         unsupportedDevice: {
             unsupportedDevice: 'Dispositivo no compatible',
-            pleaseDownloadMobileApp: `Esta acción no está soportada en tu dispositivo. Por favor descarga la aplicación de Expensify desde la <a href="${CONST.APP_DOWNLOAD_LINKS.IOS}">App Store</a> o <a href="${CONST.APP_DOWNLOAD_LINKS.ANDROID}">Google Play Store</a> e inténtalo de nuevo.`,
-            pleaseUseWebApp: `Esta acción no está soportada en tu dispositivo. Por favor usa la <a href="${CONST.NEW_EXPENSIFY_URL}">aplicación web de Expensify</a> e inténtalo de nuevo.`,
+            pleaseDownloadMobileApp: `<centered-text><muted-text> Esta acción no está soportada en tu dispositivo. Por favor descarga la aplicación de Expensify desde la <a href="${CONST.APP_DOWNLOAD_LINKS.IOS}">App Store</a> o <a href="${CONST.APP_DOWNLOAD_LINKS.ANDROID}">Google Play Store</a> e inténtalo de nuevo.</muted-text></centered-text>`,
         },
         biometricsTest: {
             biometricsTest: 'Prueba de biometría',
             authenticationSuccessful: 'Autenticación exitosa',
-            successfullyAuthenticatedUsing: (authType) => `Te has autenticado exitosamente con ${authType}.`,
-            troubleshootBiometricsStatus: ({status}) => `Biometría (${status})`,
-            statusNeverRegistered: 'Nunca registrado',
-            statusNotRegistered: 'No registrado',
-            statusRegisteredThisDevice: 'Registrado',
-            statusRegisteredOtherDevice: () => ({one: 'Otro dispositivo registrado', other: 'Otros dispositivos registrados'}),
+            successfullyAuthenticatedUsing: ({authType}) => `Te has autenticado exitosamente con ${authType}.`,
+            troubleshootBiometricsStatus: ({registered}) => `Biometría (${registered ? 'Registrada' : 'No registrada'})`,
             yourAttemptWasUnsuccessful: 'Tu intento de autenticación fue fallido.',
             youCouldNotBeAuthenticated: 'No se pudo autenticar',
             areYouSureToReject: '¿Estás seguro? El intento de autenticación será rechazado si cierras esta pantalla.',
             rejectAuthentication: 'Rechazar autenticación',
             test: 'Prueba',
             biometricsAuthentication: 'Autenticación biométrica',
-            authType: {
-                unknown: 'Desconocido',
-                none: 'Ninguno',
-                credentials: 'Credenciales',
-                biometrics: 'Biometría',
-                faceId: 'Face ID',
-                touchId: 'Touch ID',
-                opticId: 'Optic ID',
-                passkey: 'Passkey',
-            },
         },
-        verificationFailed: 'Verificación fallida',
         pleaseEnableInSystemSettings: {
             start: 'Por favor, activa la verificación de rostro/huella digital o establece un código de acceso en tus ',
             link: 'ajustes del sistema',
@@ -628,43 +520,24 @@ const translations: TranslationDeepObject<typeof en> = {
         letsVerifyItsYou: 'Verifiquemos que eres tú',
         nowLetsAuthenticateYou: 'Vamos a validarte...',
         letsAuthenticateYou: 'Validando...',
-        verifyYourself: {biometrics: 'Verifícate con tu rostro o huella dactilar', passkeys: 'Verifícate con una passkey'},
+        verifyYourself: {
+            biometrics: 'Verifícate con tu rostro o huella dactilar',
+        },
         enableQuickVerification: {
             biometrics: 'Activa la verificación rápida y segura usando tu rostro o huella dactilar. No se requieren contraseñas ni códigos.',
-            passkeys: 'Habilita una verificación rápida y segura usando una passkey. No se requieren contraseñas ni códigos.',
         },
         revoke: {
-            revoke: 'Revocar',
+            remove: 'Eliminar',
             title: 'Reconocimiento facial/huella digital y claves de acceso',
             explanation:
-                'La verificación mediante reconocimiento facial, huella digital o clave de acceso está habilitada en uno o más dispositivos. Revocar el acceso requerirá un código mágico para la próxima verificación en ese dispositivo.',
-            confirmationPrompt: '¿Estás seguro? Necesitarás un código mágico para la próxima verificación en ese dispositivo.',
-            confirmationPromptThisDevice: '¿Estás seguro? Necesitarás un código mágico para la próxima verificación en este dispositivo.',
-            confirmationPromptMultiple: '¿Estás seguro? Necesitarás un código mágico para la próxima verificación en esos dispositivos.',
-            confirmationPromptAll: '¿Estás seguro? Necesitarás un código mágico para la próxima verificación en cualquier dispositivo.',
+                'La verificación mediante reconocimiento facial, huella digital o clave de acceso está habilitada en uno o más dispositivos. Revocar el acceso requerirá un código mágico para la próxima verificación en cualquier dispositivo.',
+            confirmationPrompt: '¿Estás seguro? Necesitarás un código mágico para la próxima verificación en cualquier dispositivo.',
             cta: 'Revocar acceso',
-            ctaAll: 'Revocar todo',
             noDevices:
                 'No tienes ningún dispositivo registrado para la verificación mediante reconocimiento facial, huella digital o clave de acceso. Si registras alguno, podrás revocar ese acceso aquí.',
             dismiss: 'Entendido',
             error: 'La solicitud ha fallado. Inténtalo de nuevo más tarde.',
-            thisDevice: 'Este dispositivo',
-            otherDevices: (otherDeviceCount?: number) => {
-                const numberWords = ['Un', 'Dos', 'Tres', 'Cuatro', 'Cinco', 'Seis', 'Siete', 'Ocho', 'Nueve'];
-                const displayCount = otherDeviceCount !== undefined && otherDeviceCount >= 1 && otherDeviceCount <= 9 ? numberWords.at(otherDeviceCount - 1) : `${otherDeviceCount}`;
-                return `${displayCount} ${otherDeviceCount === 1 ? 'otro dispositivo' : 'otros dispositivos'}`;
-            },
-        },
-        setPin: {
-            didNotShipCard: 'No enviamos tu tarjeta. Por favor, inténtalo de nuevo.',
-        },
-        revealPin: {
-            couldNotReveal: 'No pudimos revelar tu PIN. Por favor, inténtalo de nuevo.',
-        },
-        changePin: {
-            didNotChange: 'No pudimos cambiar tu PIN. Por favor, inténtalo de nuevo.',
         },
-        revealCardDetail: {couldNotReveal: 'No hemos podido mostrar los datos de tu tarjeta. Por favor, inténtalo de nuevo.'},
     },
     validateCodeModal: {
         successfulSignInTitle: 'Abracadabra,\n¡sesión iniciada!',
@@ -689,7 +562,11 @@ const translations: TranslationDeepObject<typeof en> = {
         nameEmailOrPhoneNumber: 'Nombre, correo electrónico o número de teléfono',
         findMember: 'Encuentra un miembro',
         searchForSomeone: 'Busca a alguien',
-        userSelected: (username: string) => `${username} seleccionado`,
+    },
+    customApprovalWorkflow: {
+        title: 'Flujo de aprobación personalizado',
+        description: 'Tu empresa tiene un flujo de aprobación personalizado en este espacio de trabajo. Por favor, realiza esta acción en Expensify Classic',
+        goToExpensifyClassic: 'Cambiar a Expensify Classic',
     },
     emptyList: {
         [CONST.IOU.TYPE.CREATE]: {
@@ -711,8 +588,8 @@ const translations: TranslationDeepObject<typeof en> = {
         phrase2: 'El dinero habla. Y ahora que chat y pagos están en un mismo lugar, es también fácil.',
         phrase3: 'Tus pagos llegan tan rápido como tus mensajes.',
         enterPassword: 'Por favor, introduce tu contraseña',
-        welcomeNewFace: (login) => `${login}, siempre es genial ver una cara nueva por aquí!`,
-        welcomeEnterMagicCode: (login) => `Por favor, introduce el código mágico enviado a ${login}. Debería llegar en un par de minutos.`,
+        welcomeNewFace: ({login}) => `${login}, siempre es genial ver una cara nueva por aquí!`,
+        welcomeEnterMagicCode: ({login}) => `Por favor, introduce el código mágico enviado a ${login}. Debería llegar en un par de minutos.`,
     },
     login: {
         hero: {
@@ -734,9 +611,6 @@ const translations: TranslationDeepObject<typeof en> = {
         addAttachment: 'Añadir archivo adjunto',
         writeSomething: 'Escribe algo...',
         blockedFromConcierge: 'Comunicación no permitida',
-        askConciergeToUpdate: 'Prueba "Actualizar un gasto"...',
-        askConciergeToCorrect: 'Prueba "Corregir un gasto"...',
-        askConciergeForHelp: 'Pide ayuda a Concierge AI...',
         fileUploadFailed: 'Subida fallida. El archivo no es compatible.',
         localTime: (user, time) => `Son las ${time} para ${user}`,
         edited: '(editado)',
@@ -807,9 +681,9 @@ const translations: TranslationDeepObject<typeof en> = {
         askMeAnything: '¡Pregúntame lo que quieras!',
         sayHello: '¡Saluda!',
         yourSpace: 'Tu espacio',
-        welcomeToRoom: (roomName) => `¡Bienvenido a ${roomName}!`,
-        usePlusButton: (additionalText) => ` Usa el botón + para ${additionalText} un gasto`,
-        askConcierge: 'Concierge puede responder preguntas, actualizar gastos y mucho más.',
+        welcomeToRoom: ({roomName}) => `¡Bienvenido a ${roomName}!`,
+        usePlusButton: ({additionalText}) => ` Usa el botón + para ${additionalText} un gasto`,
+        askConcierge: ' ¡Pregúntame lo que quieras!',
         conciergeSupport: 'Tu agente personal de IA',
         create: 'crear',
         iouTypes: {
@@ -821,17 +695,12 @@ const translations: TranslationDeepObject<typeof en> = {
         },
     },
     adminOnlyCanPost: 'Solo los administradores pueden enviar mensajes en esta sala.',
-    readOnlyConversation: 'Esta conversación es de solo lectura.',
     reportAction: {
         asCopilot: 'como copiloto de',
-        assistedBy: (agentName: string) => `asistido por ${agentName}`,
-        humanSupportAgent: 'un agente de soporte humano',
         harvestCreatedExpenseReport: (reportUrl, reportName) =>
             `creó este informe para contener todos los gastos de <a href="${reportUrl}">${reportName}</a> que no se pudieron enviar con la frecuencia que elegiste`,
-        createdReportForUnapprovedTransactions: (reportUrl, reportName, reportID, isReportDeleted) =>
-            isReportDeleted
-                ? `creó este informe para cualquier gasto retenido del informe eliminado #${reportID}`
-                : `creó este informe para cualquier gasto retenido de <a href="${reportUrl}">${reportName}</a>`,
+        createdReportForUnapprovedTransactions: ({reportUrl, reportName}: CreatedReportForUnapprovedTransactionsParams) =>
+            `creó este informe para cualquier gasto retenido de <a href="${reportUrl}">${reportName}</a>`,
     },
     mentionSuggestions: {
         hereAlternateText: 'Notificar a todos en esta conversación',
@@ -867,6 +736,7 @@ const translations: TranslationDeepObject<typeof en> = {
         buttonFind: 'Encuentre algo...',
         buttonMySettings: 'Mi configuración',
         fabNewChat: 'Iniciar chat',
+        fabNewChatExplained: 'Abrir menú de acciones',
         fabScanReceiptExplained: 'Escanear recibo',
         chatPinned: 'Chat fijado',
         draftedMessage: 'Mensaje borrador',
@@ -874,82 +744,43 @@ const translations: TranslationDeepObject<typeof en> = {
         listOfChats: 'lista de chats',
         saveTheWorld: 'Salvar el mundo',
         tooltip: '¡Comienza aquí!',
+        redirectToExpensifyClassicModal: {
+            title: 'Próximamente',
+            description: 'Estamos ajustando algunos detalles de New Expensify para adaptarla a tu configuración específica. Mientras tanto, dirígete a Expensify Classic.',
+        },
     },
     homePage: {
         forYou: 'Para ti',
         timeSensitiveSection: {
             title: 'Requiere atención inmediata',
+            cta: 'Reclamar',
             ctaFix: 'Corrige',
+            offer50off: {
+                title: '¡Obtén 50% de descuento en tu primer año!',
+                subtitle: ({formattedTime}: {formattedTime: string}) => `${formattedTime} restantes`,
+            },
+            offer25off: {
+                title: '¡Obtén 25% de descuento en tu primer año!',
+                subtitle: ({days}: {days: number}) => `${days} ${days === 1 ? 'día' : 'días'} restantes`,
+            },
             fixCompanyCardConnection: {
                 title: ({feedName}: {feedName: string}) => (feedName ? `Reconectar la tarjeta corporativa de ${feedName}` : 'Reconectar la tarjeta corporativa'),
-                defaultSubtitle: 'Espacio de trabajo',
-                subtitle: ({policyName}: {policyName: string}) => policyName,
+                subtitle: 'Espacio de trabajo > Tarjetas de empresa',
             },
-            fixPersonalCardConnection: {
-                title: ({cardName}: {cardName?: string}) => (cardName ? `Arreglar la conexión de la tarjeta personal de ${cardName}` : 'Arreglar la conexión de la tarjeta personal'),
-                subtitle: 'Billetera',
-            },
-            fixPolicyConnection: {
+            fixAccountingConnection: {
                 title: ({integrationName}: {integrationName: string}) => `Reconectar con ${integrationName}`,
-                defaultSubtitle: 'Espacio de trabajo',
-                subtitle: ({policyName}: {policyName: string}) => policyName,
+                subtitle: 'Espacio de trabajo > Contabilidad',
             },
             addShippingAddress: {
                 title: 'Necesitamos tu dirección de envío',
                 subtitle: 'Proporciona una dirección para recibir tu Tarjeta Expensify.',
                 cta: 'Añade dirección',
             },
-            addPaymentCard: {
-                title: 'Añade una tarjeta de pago para seguir usando Expensify',
-                subtitle: 'Cuenta > Suscripción',
-                cta: 'Añadir',
-            },
             activateCard: {
                 title: 'Activa tu Tarjeta Expensify',
                 subtitle: 'Valida tu tarjeta y empieza a gastar.',
                 cta: 'Activa',
             },
-            reviewCardFraud: {
-                title: 'Revisa un posible fraude en tu tarjeta Expensify',
-                titleWithDetails: ({amount, merchant}: {amount: string; merchant: string}) => `Revisa ${amount} en posible fraude en ${merchant}`,
-                subtitle: 'Tarjeta Expensify',
-                cta: 'Revisar',
-            },
-            validateAccount: {
-                title: 'Valida tu cuenta',
-                subtitle: 'Cuenta',
-                cta: 'Validar',
-            },
-            fixFailedBilling: {
-                title: 'No pudimos cobrar a la tarjeta registrada.',
-                subtitle: 'Suscripción',
-            },
-            unlockBankAccount: {
-                workspaceTitle: 'Tu cuenta bancaria empresarial ha sido bloqueada',
-                personalTitle: 'Tu cuenta bancaria ha sido bloqueada',
-                workspaceSubtitle: ({policyName}: {policyName: string}) => policyName,
-                personalSubtitle: 'Billetera',
-            },
-            enterSignerInfo: {title: 'Se necesita la información del firmante', subtitle: ({bankAccountLastFour}: {bankAccountLastFour: string}) => `Cuenta bancaria ${bankAccountLastFour}`},
-        },
-        freeTrialSection: {
-            title: ({days}: {days: number}) => `Prueba gratuita: ${days} ${days === 1 ? 'día' : 'días'} restantes!`,
-            offer50Body: '¡Obtén 50% de descuento en tu primer año',
-            offer25Body: '¡Obtén 25% de descuento en tu primer año',
-            addCardBody: 'Añadir una tarjeta de pago',
-            ctaClaim: 'Reclamar',
-            ctaAdd: 'Añadir tarjeta',
-            timeRemaining: ({formattedTime}: {formattedTime: string}) => `Tiempo restante: ${formattedTime}`,
-            timeRemainingDays: () => ({
-                one: 'Tiempo restante: 1 día',
-                other: (pluralCount: number) => `Tiempo restante: ${pluralCount} días`,
-            }),
-        },
-        yourSpend: {
-            title: 'Tu gasto',
-            awaitingApproval: 'Pendiente de aprobación',
-            repaidLast30Days: 'Reembolsado en los últimos 30 días',
-            recentTransactions: ({lastFour}: {lastFour: string}) => `Transacciones recientes • ${lastFour}`,
         },
         announcements: 'Anuncios',
         discoverSection: {
@@ -965,62 +796,12 @@ const translations: TranslationDeepObject<typeof en> = {
             export: ({count}: {count: number}) => `Exportar ${count} ${count === 1 ? 'informe' : 'informes'}`,
             begin: 'Comenzar',
             emptyStateMessages: {
-                thumbsUpStarsTitle: '¡Has terminado!',
-                thumbsUpStarsDescription: 'Pulgar arriba, mantente atento a más tareas.',
-                smallRocketTitle: 'Todo al día',
-                smallRocketDescription: 'Las próximas tareas se lanzarán aquí.',
-                cowboyHatTitle: '¡Has terminado!',
-                cowboyHatDescription: 'Todas las tareas están domadas, mantente atento a más.',
-                trophy1Title: 'Nada que mostrar',
-                trophy1Description: '¡Lo lograste! Mantente atento a más tareas.',
-                palmTreeTitle: 'Todo al día',
-                palmTreeDescription: 'Hora de relajarse, pero mantente atento a futuras tareas.',
-                fishbowlBlueTitle: '¡Has terminado!',
-                fishbowlBlueDescription: 'Aquí mostraremos las futuras tareas.',
-                targetTitle: 'Todo al día',
-                targetDescription: 'Justo en el blanco. ¡Vuelve a revisar para más tareas!',
-                chairTitle: 'Nada que mostrar',
-                chairDescription: 'Relájate, listaremos las próximas tareas aquí.',
-                broomTitle: '¡Has terminado!',
-                broomDescription: 'Las tareas están limpias, pero mantente atento a más tareas.',
-                houseTitle: 'Todo al día',
-                houseDescription: 'Esta es tu base para las próximas tareas.',
-                conciergeBotTitle: 'Nada que mostrar',
-                conciergeBotDescription: '¡Bip bup bip bup, vuelve a revisar para más tareas!',
-                checkboxTextTitle: 'Todo al día',
-                checkboxTextDescription: 'Marca tus próximas tareas aquí.',
-                flashTitle: '¡Has terminado!',
-                flashDescription: 'Aquí mostraremos tus futuras tareas.',
-                sunglassesTitle: 'Nada que mostrar',
-                sunglassesDescription: '¡Hora de relajarse, pero mantente atento a lo que viene!',
-                f1FlagsTitle: 'Todo al día',
-                f1FlagsDescription: 'Has completado todas las tareas pendientes.',
-            },
-        },
-        gettingStartedSection: {
-            title: 'Primeros pasos',
-            createWorkspace: 'Crear un espacio de trabajo',
-            connectAccounting: ({integrationName}: {integrationName: string}) => `Conectar con ${integrationName}`,
-            connectAccountingDefault: 'Conectar a contabilidad',
-            customizeCategories: 'Personalizar categorías contables',
-            inviteAccountant: 'Invita a tu contador',
-            linkCompanyCards: 'Vincular tarjetas corporativas',
-            setupRules: 'Configurar reglas de gasto',
-        },
-        upcomingTravel: 'Próximos viajes',
-        upcomingTravelSection: {
-            flightTo: ({destination}: {destination: string}) => `Vuelo a ${destination}`,
-            trainTo: ({destination}: {destination: string}) => `Tren a ${destination}`,
-            hotelIn: ({destination}: {destination: string}) => `Hotel en ${destination}`,
-            carRentalIn: ({destination}: {destination: string}) => `Alquiler de coche en ${destination}`,
-            inOneWeek: 'En 1 semana',
-            inDays: () => ({
-                one: 'En 1 día',
-                other: (count: number) => `En ${count} días`,
-            }),
-            today: 'Hoy',
+                nicelyDone: '¡Muy bien hecho!',
+                keepAnEyeOut: '¡Mantente atento a lo que viene a continuación!',
+                allCaughtUp: 'Ya estás al día',
+                upcomingTodos: 'Las tareas pendientes aparecerán aquí.',
+            },
         },
-        seeMore: ({count}: {count: number}) => `Ver ${count} más`,
     },
     allSettingsScreen: {
         subscription: 'Suscripcion',
@@ -1050,38 +831,27 @@ const translations: TranslationDeepObject<typeof en> = {
         emptyMappedField: (fieldName) => `¡Vaya! El campo ("${fieldName}") contiene uno o más valores vacíos. Por favor, revísalo e inténtalo de nuevo.`,
         importFailedTitle: 'Fallo en la importación',
         importFailedDescription: 'Por favor, asegúrate de que todos los campos estén llenos correctamente e inténtalo de nuevo. Si el problema persiste, por favor contacta a Concierge.',
-        importCategoriesSuccessfulDescription: ({added, updated}: {added: number; updated: number}) => {
-            if (!added && !updated) {
-                return 'No se han añadido ni actualizado categorías.';
-            }
-            if (added && updated) {
-                return `Se añadieron ${added} categoría${added === 1 ? '' : 's'} y se actualizaron ${updated} categoría${updated === 1 ? '' : 's'}.`;
-            }
-            if (added) {
-                return added === 1 ? 'Se añadió 1 categoría.' : `Se añadieron ${added} categorías.`;
-            }
-            return updated === 1 ? 'Se actualizó 1 categoría.' : `Se actualizaron ${updated} categorías.`;
-        },
+        importCategoriesSuccessfulDescription: ({categories}) => (categories > 1 ? `Se han agregado ${categories} categorías.` : 'Se ha agregado 1 categoría.'),
         importMembersSuccessfulDescription: ({added, updated}) => {
             if (!added && !updated) {
                 return 'No se han añadido ni actualizado miembros.';
             }
+
             if (added && updated) {
                 const getPluralSuffix = (count: number) => (count > 1 ? 's' : '');
                 return `${added} miembro${getPluralSuffix(added)} añadido${getPluralSuffix(added)}, ${updated} miembro${getPluralSuffix(updated)} actualizado${getPluralSuffix(updated)}.`;
             }
+
             if (updated) {
                 return updated > 1 ? `${updated} miembros han sido actualizados.` : '1 miembro ha sido actualizado.';
             }
+
             return added > 1 ? `Se han agregado ${added} miembros` : 'Se ha agregado 1 miembro.';
         },
         importTagsSuccessfulDescription: ({tags}) => (tags > 1 ? `Se han agregado ${tags} etiquetas.` : 'Se ha agregado 1 etiqueta.'),
         importMultiLevelTagsSuccessfulDescription: 'Etiquetas de nivel múltiple han sido agregadas.',
         importPerDiemRatesSuccessfulDescription: ({rates}) => (rates > 1 ? `Se han añadido ${rates} tasas de per diem.` : 'Se ha añadido 1 tasa de per diem.'),
         importTransactionsSuccessfulDescription: ({transactions}) => (transactions > 1 ? `Se han importado ${transactions} transacciones.` : 'Se ha importado 1 transacción.'),
-        importCompanyCardTransactionsSuccessfulDescription: ({transactions}: {transactions: number}) =>
-            transactions > 1 ? `Se han importado ${transactions} transacciones.` : 'Se ha importado 1 transacción.',
-        importCompanyCardTransactionsPendingMessage: 'Las nuevas tarjetas y transacciones pueden tardar un poco en aparecer.',
         importSuccessfulTitle: 'Importar categorías',
         importDescription: 'Elige qué campos mapear desde tu hoja de cálculo haciendo clic en el menú desplegable junto a cada columna importada a continuación.',
         sizeNotMet: 'El archivo adjunto debe ser más grande que 0 bytes.',
@@ -1126,9 +896,7 @@ const translations: TranslationDeepObject<typeof en> = {
         deleteReceipt: 'Eliminar recibo',
         deleteConfirmation: '¿Estás seguro de que quieres borrar este recibo?',
         addReceipt: 'Añadir recibo',
-        addAdditionalReceipt: 'Añadir recibo adicional',
-        scanFailed: 'El recibo no pudo ser escaneado, ya que falta el comerciante, la fecha o el importe.',
-        crop: 'Recortar',
+        scanFailed: 'El recibo no pudo ser escaneado, ya que falta el comerciante, la fecha o el monto.',
         addAReceipt: {
             phrase1: 'Añade un recibo',
             phrase2: 'o arrastra y suelta uno aquí',
@@ -1148,7 +916,6 @@ const translations: TranslationDeepObject<typeof en> = {
         noLongerHaveReportAccess: 'Ya no tienes acceso al destino previo de esta acción rápida. Escoge uno nuevo a continuación.',
         updateDestination: 'Actualiza el destino',
         createReport: 'Crear informe',
-        createTimeExpense: 'Crear gasto de tiempo',
     },
     iou: {
         amount: 'Importe',
@@ -1164,18 +931,18 @@ const translations: TranslationDeepObject<typeof en> = {
         split: 'Dividir',
         splitExpense: 'Dividir gasto',
         splitDates: 'Fechas de división',
-        splitDateRange: (startDate, endDate, count) => `${startDate} al ${endDate} (${count} días)`,
-        splitExpenseSubtitle: (amount, merchant) => `${amount} de ${merchant}`,
+        splitDateRange: ({startDate, endDate, count}: SplitDateRangeParams) => `${startDate} al ${endDate} (${count} días)`,
+        splitExpenseSubtitle: ({amount, merchant}) => `${amount} de ${merchant}`,
         splitByPercentage: 'Dividir por porcentaje',
         splitByDate: 'Dividir por fecha',
         addSplit: 'Añadir división',
         makeSplitsEven: 'Igualar divisiones',
         editSplits: 'Editar divisiones',
-        totalAmountGreaterThanOriginal: (amount) => `El importe total es ${amount} mayor que el gasto original.`,
-        totalAmountLessThanOriginal: (amount) => `El importe total es ${amount} menor que el gasto original.`,
+        totalAmountGreaterThanOriginal: ({amount}) => `El importe total es ${amount} mayor que el gasto original.`,
+        totalAmountLessThanOriginal: ({amount}) => `El importe total es ${amount} menor que el gasto original.`,
         splitExpenseZeroAmount: 'Por favor, introduce un importe válido antes de continuar.',
         splitExpenseOneMoreSplit: 'No se han añadido divisiones. Añade al menos una para guardar.',
-        splitExpenseEditTitle: (amount, merchant) => `Editar ${amount} para ${merchant}`,
+        splitExpenseEditTitle: ({amount, merchant}) => `Editar ${amount} para ${merchant}`,
         removeSplit: 'Eliminar división',
         splitExpenseCannotBeEditedModalTitle: 'Este gasto no se puede editar',
         splitExpenseCannotBeEditedModalDescription: 'Los gastos aprobados o pagados no se pueden editar',
@@ -1208,17 +975,12 @@ const translations: TranslationDeepObject<typeof en> = {
         pendingMatchWithCreditCard: 'Recibo pendiente de adjuntar con la transacción de la tarjeta',
         pendingMatchWithCreditCardDescription: 'Recibo pendiente de adjuntar con la transacción de la tarjeta. Márcalo como efectivo para cancelar.',
         markAsCash: 'Marcar como efectivo',
-        pendingMatchSubmitTitle: 'Enviar informe',
-        pendingMatchSubmitDescription: 'Algunos gastos están pendientes de coincidencia con una transacción de tarjeta de crédito. ¿Deseas marcarlos como efectivo?',
         routePending: 'Ruta pendiente...',
         findExpense: 'Buscar gasto',
         deletedTransaction: (amount, merchant) => `eliminó un gasto (${amount} para ${merchant})`,
-        movedFromReport: (reportName) => `movió un gasto desde ${reportName}`,
-        movedFromReportNoName: 'movió un gasto',
-        movedTransactionTo: (reportUrl, reportName) => `movió este gasto a <a href="${reportUrl}">${reportName}</a>`,
-        movedTransactionToAnotherReport: 'movió este gasto a otro informe',
-        movedTransactionFrom: (reportUrl, reportName) => `movió este gasto desde <a href="${reportUrl}">${reportName}</a>`,
-        movedTransactionFromAnotherReport: 'movió este gasto desde otro informe',
+        movedFromReport: (reportName) => `movió un gasto${reportName ? ` desde ${reportName}` : ''}`,
+        movedTransactionTo: (reportUrl, reportName) => `movió este gasto${reportName ? ` a <a href="${reportUrl}">${reportName}</a>` : ''}`,
+        movedTransactionFrom: (reportUrl, reportName) => `movió este gasto${reportName ? ` desde <a href="${reportUrl}">${reportName}</a>` : ''}`,
         unreportedTransaction: (reportUrl) => `movió este gasto a tu <a href="${reportUrl}">espacio personal</a>`,
         movedAction: (shouldHideMovedReportUrl, movedReportUrl, newParentReportUrl, toPolicyName) => {
             if (shouldHideMovedReportUrl) {
@@ -1231,7 +993,6 @@ const translations: TranslationDeepObject<typeof en> = {
             other: 'Problemas encontrados',
         }),
         fieldPending: 'Pendiente...',
-        automaticallyEnterExpenseDetails: 'Concierge completará los detalles por ti.',
         receiptScanning: () => ({
             one: 'Escaneando recibo...',
             other: 'Escaneando recibos...',
@@ -1253,7 +1014,7 @@ const translations: TranslationDeepObject<typeof en> = {
         receiptStatusTitle: 'Escaneando…',
         receiptStatusText: 'Solo tú puedes ver este recibo cuando se está escaneando. Vuelve más tarde o introduce los detalles ahora.',
         receiptScanningFailed: 'El escaneo de recibo ha fallado. Introduce los detalles manualmente.',
-        allTransactionsPendingNextStep: 'Todas las transacciones están pendientes. No puedes enviar este informe hasta que se registren dentro de unos días.',
+        transactionPendingDescription: 'Transacción pendiente. Puede tardar unos días en contabilizarse.',
         companyInfo: 'Información de la empresa',
         companyInfoDescription: 'Necesitamos algunos detalles más antes de que pueda enviar su primera factura.',
         yourCompanyName: 'Nombre de su empresa',
@@ -1285,22 +1046,18 @@ const translations: TranslationDeepObject<typeof en> = {
         }),
         settledExpensify: 'Pagado',
         done: 'Listo',
-        deleted: 'Eliminado',
         settledElsewhere: 'Pagado de otra forma',
         individual: 'Individual',
         business: 'Empresa',
-        settlePersonal: (formattedAmount) => (formattedAmount ? `Pago ${formattedAmount} como individuo` : `Pago con cuenta personal`),
-        settleWallet: (formattedAmount) => (formattedAmount ? `Pagar ${formattedAmount} con billetera` : `con billetera`),
-        settlePayment: (formattedAmount) => `Pagar ${formattedAmount}`,
-        settleBusiness: (formattedAmount) => (formattedAmount ? `Pagar ${formattedAmount} como negocio` : `Pago con cuenta empresarial`),
-        payElsewhere: (formattedAmount) => (formattedAmount ? `Marcar ${formattedAmount} como pagado` : `Marcar como pagado`),
-        confirmPaymentReceivedModalTitle: 'Confirmar el pago recibido',
-        receivedPayment: 'Pago recibido',
-        receivedPaymentConfirmation: 'Por favor, continúa solo si ya has recibido el pago fuera de Expensify.',
-        confirmReceivedPayment: 'Sí, he recibido el pago.',
+        settleExpensify: ({formattedAmount}) => (formattedAmount ? `Pagar ${formattedAmount} con Expensify` : `Pagar con Expensify`),
+        settlePersonal: ({formattedAmount}) => (formattedAmount ? `Pago ${formattedAmount} como individuo` : `Pago con cuenta personal`),
+        settleWallet: ({formattedAmount}) => (formattedAmount ? `Pagar ${formattedAmount} con billetera` : `con billetera`),
+        settlePayment: ({formattedAmount}) => `Pagar ${formattedAmount}`,
+        settleBusiness: ({formattedAmount}) => (formattedAmount ? `Pagar ${formattedAmount} como negocio` : `Pago con cuenta empresarial`),
+        payElsewhere: ({formattedAmount}) => (formattedAmount ? `Marcar ${formattedAmount} como pagado` : `Marcar como pagado`),
         settleInvoicePersonal: (amount, last4Digits) => (amount ? `pagado ${amount} con cuenta personal ${last4Digits}` : `Pagado con cuenta personal`),
         settleInvoiceBusiness: (amount, last4Digits) => (amount ? `pagado ${amount} con cuenta de empresa ${last4Digits}` : `Pagado con cuenta de empresa`),
-        payWithPolicy: (policyName, formattedAmount) => (formattedAmount ? `Pay ${formattedAmount} via ${policyName}` : `Pay via ${policyName}`),
+        payWithPolicy: ({formattedAmount, policyName}) => (formattedAmount ? `Pay ${formattedAmount} via ${policyName}` : `Pay via ${policyName}`),
         businessBankAccount: (amount, last4Digits) => (amount ? `pagó ${amount} con la cuenta bancaria ${last4Digits}.` : `pagó con la cuenta bancaria ${last4Digits}`),
         automaticallyPaidWithBusinessBankAccount: (amount, last4Digits) =>
             `pagado ${amount ? `${amount} ` : ''}con la cuenta bancaria terminada en ${last4Digits} vía <a href="${CONST.CONFIGURE_EXPENSE_REPORT_RULES_HELP_URL}">reglas del espacio de trabajo</a>`,
@@ -1309,21 +1066,16 @@ const translations: TranslationDeepObject<typeof en> = {
         nextStep: 'Pasos siguientes',
         finished: 'Finalizado',
         flip: 'Cambiar',
-        sendInvoice: (amount) => `Enviar factura de ${amount}`,
+        sendInvoice: ({amount}) => `Enviar factura de ${amount}`,
         expenseAmount: (formattedAmount, comment) => `${formattedAmount}${comment ? ` para ${comment}` : ''}`,
-        submitted: (memo) => `enviado${memo ? `, dijo ${memo}` : ''}`,
+        submitted: ({memo}) => `enviado${memo ? `, dijo ${memo}` : ''}`,
         automaticallySubmitted: `envió mediante <a href="${CONST.SELECT_WORKFLOWS_HELP_URL}">retrasar envíos</a>`,
         queuedToSubmitViaDEW: 'en cola para enviar a través del flujo de aprobación personalizado',
-        failedToAutoSubmitViaDEW: (reason: string) => `no ha podido enviar este informe mediante <a href="${CONST.SELECT_WORKFLOWS_HELP_URL}">retrasar envíos</a>. ${reason}`,
-        failedToSubmitViaDEW: (reason: string) => `no ha podido enviar este informe. ${reason}`,
-        failedToAutoApproveViaDEW: (reason: string) =>
-            `no ha podido aprobar mediante <a href="${CONST.CONFIGURE_EXPENSE_REPORT_RULES_HELP_URL}">reglas del espacio de trabajo</a>. ${reason}`,
-        failedToApproveViaDEW: (reason: string) => `no ha podido aprobar. ${reason}`,
         queuedToApproveViaDEW: 'en cola para aprobar a través del flujo de aprobación personalizado',
         trackedAmount: (formattedAmount, comment) => `realizó un seguimiento de ${formattedAmount}${comment ? ` para ${comment}` : ''}`,
-        splitAmount: (amount) => `dividir ${amount}`,
+        splitAmount: ({amount}) => `dividir ${amount}`,
         didSplitAmount: (formattedAmount, comment) => `dividió ${formattedAmount}${comment ? ` para ${comment}` : ''}`,
-        yourSplit: (amount) => `Tu parte ${amount}`,
+        yourSplit: ({amount}) => `Tu parte ${amount}`,
         payerOwesAmount: (amount, payer, comment) => `${payer} debe ${amount}${comment ? ` para ${comment}` : ''}`,
         payerOwes: (payer) => `${payer} debe: `,
         payerPaidAmount: (amount, payer) => `${payer ? `${payer} ` : ''}pagó ${amount}`,
@@ -1339,72 +1091,34 @@ const translations: TranslationDeepObject<typeof en> = {
         approvedMessage: `aprobado`,
         unapproved: `no aprobado`,
         automaticallyForwarded: `aprobó mediante <a href="${CONST.CONFIGURE_EXPENSE_REPORT_RULES_HELP_URL}">reglas del espacio de trabajo</a>`,
-        forwarded: (memo) => `aprobó${memo ? `, dijo ${memo}` : ''}`,
-        rejectedThisReport: 'rechazó',
-        waitingOnBankAccount: (submitterDisplayName) => `inició el pago, pero está esperando a que ${submitterDisplayName} añada una cuenta bancaria.`,
+        forwarded: `aprobó`,
+        rejectedThisReport: 'rechazó este informe',
+        waitingOnBankAccount: ({submitterDisplayName}) => `inició el pago, pero está esperando a que ${submitterDisplayName} añada una cuenta bancaria.`,
         adminCanceledRequest: 'canceló el pago',
         canceledRequest: (amount, submitterDisplayName) => `canceló el pago  ${amount}, porque ${submitterDisplayName} no habilitó tu Billetera Expensify en un plazo de 30 días.`,
-        settledAfterAddedBankAccount: (submitterDisplayName, amount) => `${submitterDisplayName} añadió una cuenta bancaria. El pago de ${amount} se ha realizado.`,
+        settledAfterAddedBankAccount: ({submitterDisplayName, amount}) => `${submitterDisplayName} añadió una cuenta bancaria. El pago de ${amount} se ha realizado.`,
         paidElsewhere: ({payer, comment}: PaidElsewhereParams = {}) => `${payer ? `${payer} ` : ''}marcó como pagado${comment ? `, diciendo "${comment}"` : ''}`,
         paidWithExpensify: (payer) => `${payer ? `${payer} ` : ''}pagó con la billetera`,
         automaticallyPaidWithExpensify: (payer) =>
             `${payer ? `${payer} ` : ''}pagó con Expensify via <a href="${CONST.CONFIGURE_EXPENSE_REPORT_RULES_HELP_URL}">reglas del espacio de trabajo</a>`,
-        reimbursedThisReport: 'reembolsó este informe',
-        paidThisBill: 'pagó esta factura',
-        reimbursedOnBehalfOf: (actor: string) => `en nombre de ${actor}`,
-        reimbursedFromBankAccount: (debitBankAccount: string) => `desde la cuenta bancaria terminada en ${debitBankAccount}`,
-        reimbursedSubmitterAddedBankAccount: (submitter: string) => `${submitter} añadió una cuenta bancaria, quitando el informe de espera. El reembolso se ha iniciado`,
-        reimbursedWithFastACH: ({
-            isCurrentUser,
-            submitterLogin,
-            creditBankAccount,
-            expectedDate,
-        }: {
-            isCurrentUser: boolean;
-            submitterLogin: string;
-            creditBankAccount: string;
-            expectedDate: string;
-        }) =>
-            isCurrentUser
-                ? `. El dinero está en camino a tu${creditBankAccount ? ` cuenta bancaria terminada en ${creditBankAccount}` : ' cuenta'}. Se estima que el reembolso se completará el ${expectedDate}.`
-                : `. El dinero está en camino a la cuenta bancaria de ${submitterLogin}${creditBankAccount ? ` terminada en ${creditBankAccount}` : ''}. Se estima que el reembolso se completará el ${expectedDate}.`,
-        reimbursedWithCheck: ' mediante cheque.',
-        reimbursedWithStripeConnect: ({
-            isCurrentUser,
-            submitterLogin,
-            creditBankAccount,
-            isCard,
-        }: {
-            isCurrentUser: boolean;
-            submitterLogin: string;
-            creditBankAccount: string;
-            isCard: boolean;
-        }) => {
-            const paymentMethod = isCard ? 'tarjeta' : 'cuenta bancaria';
-            return isCurrentUser
-                ? `. El dinero está en camino a tu${creditBankAccount ? ` cuenta bancaria terminada en ${creditBankAccount}` : ' cuenta'} (pagado mediante ${paymentMethod}). Esto puede tardar hasta 10 días hábiles.`
-                : `. El dinero está en camino a la cuenta bancaria de ${submitterLogin}${creditBankAccount ? ` terminada en ${creditBankAccount}` : ''} (pagado mediante ${paymentMethod}). Esto puede tardar hasta 10 días hábiles.`;
-        },
-        reimbursedWithACH: ({creditBankAccount, expectedDate}: {creditBankAccount?: string; expectedDate?: string}) =>
-            ` con depósito directo (ACH)${creditBankAccount ? ` a la cuenta bancaria terminada en ${creditBankAccount}. ` : '. '}${expectedDate ? `Se estima que el reembolso se completará para el ${expectedDate}.` : 'Esto generalmente toma de 4 a 5 días hábiles.'}`,
         noReimbursableExpenses: 'El importe de este informe no es válido',
         pendingConversionMessage: 'El total se actualizará cuando estés online',
         changedTheExpense: 'cambió el gasto',
-        setTheRequest: (valueName, newValueToDisplay) =>
+        setTheRequest: ({valueName, newValueToDisplay}) =>
             `${valueName === 'comerciante' || valueName === 'importe' || valueName === 'gasto' ? 'el' : 'la'} ${valueName} a ${newValueToDisplay}`,
-        setTheDistanceMerchant: (translatedChangedField, newMerchant, newAmountToDisplay) =>
+        setTheDistanceMerchant: ({translatedChangedField, newMerchant, newAmountToDisplay}) =>
             `estableció la ${translatedChangedField} a ${newMerchant}, lo que estableció el importe a ${newAmountToDisplay}`,
         removedTheRequest: (valueName, oldValueToDisplay) =>
             `${valueName === 'comerciante' || valueName === 'importe' || valueName === 'gasto' ? 'el' : 'la'} ${valueName} (previamente ${oldValueToDisplay})`,
-        updatedTheRequest: (valueName, newValueToDisplay, oldValueToDisplay) =>
+        updatedTheRequest: ({valueName, newValueToDisplay, oldValueToDisplay}) =>
             `${valueName === 'comerciante' || valueName === 'importe' || valueName === 'gasto' ? 'el' : 'la'} ${valueName} a ${newValueToDisplay} (previamente ${oldValueToDisplay})`,
-        updatedTheDistanceMerchant: (translatedChangedField, newMerchant, oldMerchant, newAmountToDisplay, oldAmountToDisplay) =>
+        updatedTheDistanceMerchant: ({translatedChangedField, newMerchant, oldMerchant, newAmountToDisplay, oldAmountToDisplay}) =>
             `cambió la ${translatedChangedField} a ${newMerchant} (previamente ${oldMerchant}), lo que cambió el importe a ${newAmountToDisplay} (previamente ${oldAmountToDisplay})`,
         basedOnAI: 'basado en actividad pasada',
         basedOnMCC: ({rulesLink}: {rulesLink: string}) => (rulesLink ? `basado en <a href="${rulesLink}">reglas del espacio de trabajo</a>` : 'basado en regla del espacio de trabajo'),
-        threadExpenseReportName: (formattedAmount, comment) => `${comment ? `${formattedAmount} para ${comment}` : `Gasto de ${formattedAmount}`}`,
+        threadExpenseReportName: ({formattedAmount, comment}) => `${comment ? `${formattedAmount} para ${comment}` : `Gasto de ${formattedAmount}`}`,
         invoiceReportName: ({linkedReportID}) => `Informe de facturación #${linkedReportID}`,
-        threadPaySomeoneReportName: (formattedAmount, comment) => `${formattedAmount} enviado${comment ? ` para ${comment}` : ''}`,
+        threadPaySomeoneReportName: ({formattedAmount, comment}) => `${formattedAmount} enviado${comment ? ` para ${comment}` : ''}`,
         movedFromPersonalSpace: ({workspaceName, reportName}) => `movió el gasto desde su espacio personal a ${workspaceName ?? `un chat con ${reportName}`}`,
         movedToPersonalSpace: 'movió el gasto a su espacio personal',
         error: {
@@ -1412,21 +1126,13 @@ const translations: TranslationDeepObject<typeof en> = {
             invalidTagLength: 'La longitud de la etiqueta escogida excede el máximo permitido (255). Por favor, escoge otra etiqueta o acorta la etiqueta primero.',
             invalidAmount: 'Por favor, ingresa un importe válido antes de continuar',
             invalidDistance: 'Por favor, ingresa una distancia válida antes de continuar',
-            invalidReadings: 'Por favor ingrese ambas lecturas de inicio y fin para continuar',
+            invalidReadings: 'Por favor ingrese ambas lecturas de inicio y fin',
             negativeDistanceNotAllowed: 'La lectura final debe ser mayor que la lectura inicial',
-            distanceAmountTooLarge: 'El importe total es demasiado alto. Reduce la distancia o disminuye la tarifa.',
-            distanceAmountTooLargeReduceDistance: 'El importe total es demasiado alto. Reduce la distancia.',
-            distanceAmountTooLargeReduceRate: 'El importe total es demasiado alto. Disminuye la tarifa.',
-            odometerReadingTooLarge: (formattedMax: string) => `Las lecturas del odómetro no pueden superar ${formattedMax}.`,
-            unableToSubmitReport: 'No se puede enviar el informe',
-            allTransactionsPendingDescription: 'No puedes enviar este informe porque todas las transacciones están pendientes. Pueden tardar unos días en procesarse.',
-            stitchOdometerImagesFailed: 'No se pudieron combinar las imágenes del odómetro. Por favor, inténtalo de nuevo más tarde.',
-            failedToSaveOdometerDraft: 'No se pudo guardar el borrador del odómetro. Por favor, inténtalo de nuevo.',
-            invalidIntegerAmount: 'Por favor, introduce un importe entero en dólares antes de continuar',
-            invalidTaxAmount: (amount) => `El importe máximo del impuesto es ${amount}`,
+            invalidIntegerAmount: 'Por favor, introduce una cantidad entera en dólares antes de continuar',
+            invalidTaxAmount: ({amount}) => `El importe máximo del impuesto es ${amount}`,
             invalidSplit: 'La suma de las partes debe ser igual al importe total',
             invalidSplitParticipants: 'Introduce un importe superior a cero para al menos dos participantes',
-            invalidSplitYourself: 'Por favor, introduce un importe distinto de cero para tu parte',
+            invalidSplitYourself: 'Por favor, introduce una cantidad diferente de cero para tu parte',
             noParticipantSelected: 'Por favor, selecciona un participante',
             other: 'Error inesperado. Por favor, inténtalo más tarde.',
             genericHoldExpenseFailureMessage: 'Error inesperado al retener el gasto. Por favor, inténtalo de nuevo más tarde.',
@@ -1436,8 +1142,6 @@ const translations: TranslationDeepObject<typeof en> = {
             receiptDeleteFailureError: 'Error inesperado al borrar este recibo. Por favor, vuelve a intentarlo más tarde.',
             receiptFailureMessage: '<rbr>Hubo un error al cargar tu recibo. Por favor, <a href="download">guarda el recibo</a> e <a href="retry">inténtalo de nuevo</a> más tarde.</rbr>',
             receiptFailureMessageShort: 'Hubo un error al cargar tu recibo.',
-            receiptUploadFailedMessage: 'Error al subir el recibo. Guarda el recibo, o elimina el gasto y piérdelo.',
-            saveReceipt: 'Guardar recibo',
             genericDeleteFailureMessage: 'Error inesperado al eliminar este gasto. Por favor, inténtalo más tarde.',
             genericEditFailureMessage: 'Error inesperado al editar este gasto. Por favor, inténtalo más tarde.',
             genericSmartscanFailureMessage: 'La transacción tiene campos vacíos',
@@ -1452,12 +1156,12 @@ const translations: TranslationDeepObject<typeof en> = {
             invalidRate: 'Tasa no válida para este espacio de trabajo. Por favor, selecciona una tasa disponible en el espacio de trabajo.',
             endDateBeforeStartDate: 'La fecha de finalización no puede ser anterior a la fecha de inicio',
             endDateSameAsStartDate: 'La fecha de finalización no puede ser la misma que la fecha de inicio',
-            manySplitsProvided: `El número máximo de divisiones permitidas es ${CONST.IOU.SPLITS_LIMIT}.`,
+            manySplitsProvided: `La cantidad máxima de divisiones permitidas es ${CONST.IOU.SPLITS_LIMIT}.`,
             dateRangeExceedsMaxDays: `El rango de fechas no puede exceder los ${CONST.IOU.SPLITS_LIMIT} días.`,
         },
         dismissReceiptError: 'Descartar error',
         dismissReceiptErrorConfirmation: '¡Atención! Descartar este error eliminará completamente tu recibo cargado. ¿Estás seguro?',
-        waitingOnEnabledWallet: (submitterDisplayName) => `inició el pago, pero no se procesará hasta que ${submitterDisplayName} active su billetera`,
+        waitingOnEnabledWallet: ({submitterDisplayName}) => `inició el pago, pero no se procesará hasta que ${submitterDisplayName} active su billetera`,
         enableWallet: 'Habilitar billetera',
         holdExpense: () => ({
             one: 'Retener gasto',
@@ -1465,11 +1169,11 @@ const translations: TranslationDeepObject<typeof en> = {
         }),
         unholdExpense: 'Desbloquear gasto',
         moveUnreportedExpense: 'Mover gasto no reportado',
-        addExistingExpense: 'Añadir gasto existente',
-        selectExistingExpense: 'Selecciona al menos un gasto para agregar al informe.',
-        emptyStateExistingExpenseTitle: 'No hay gastos existentes',
-        emptyStateExistingExpenseSubtitle: 'Parece que no tienes gastos existentes. Puedes crear uno a continuación.',
-        addExistingExpenseConfirm: 'Añadir al informe',
+        addUnreportedExpense: 'Añadir gasto no reportado',
+        selectUnreportedExpense: 'Selecciona al menos un gasto para agregar al informe.',
+        emptyStateUnreportedExpenseTitle: 'No hay gastos no reportados',
+        emptyStateUnreportedExpenseSubtitle: 'Parece que no tienes gastos no reportados. Puedes crear uno a continuación.',
+        addUnreportedExpenseConfirm: 'Añadir al informe',
         heldExpense: 'retuvo este gasto',
         unheldExpense: 'desbloqueó este gasto',
         newReport: 'Nuevo informe',
@@ -1477,10 +1181,6 @@ const translations: TranslationDeepObject<typeof en> = {
             one: 'Explica la razón para retener esta solicitud.',
             other: 'Explica la razón para retener estas solicitudes.',
         }),
-        explainHoldApprover: () => ({
-            one: 'Explica qué necesitas antes de aprobar este gasto.',
-            other: 'Explica qué necesitas antes de aprobar estos gastos.',
-        }),
         retract: 'Retractar',
         reopened: 'reabrir',
         reopenReport: 'Reabrir informe',
@@ -1496,9 +1196,6 @@ const translations: TranslationDeepObject<typeof en> = {
         someDuplicatesArePaid: 'Algunos de estos duplicados ya han sido aprobados o pagados.',
         reviewDuplicates: 'Revisar duplicados',
         keepAll: 'Mantener todos',
-        keepSelected: 'Mantener seleccionado',
-        noDuplicatesTitle: '¡Todo listo!',
-        noDuplicatesDescription: 'No hay transacciones duplicadas para revisar aquí.',
         confirmApprove: 'Confirmar importe a aprobar',
         confirmApprovalAmount: 'Aprueba sólo los gastos conformes, o aprueba todo el informe.',
         confirmApprovalAllHoldAmount: () => ({
@@ -1534,16 +1231,15 @@ const translations: TranslationDeepObject<typeof en> = {
         unapprove: 'Desaprobar',
         unapproveReport: 'Anular la aprobación del informe',
         headsUp: 'Atención!',
-        unapproveWithIntegrationWarning: (accountingIntegration) =>
+        unapproveWithIntegrationWarning: ({accountingIntegration}) =>
             `Este informe ya se ha exportado a ${accountingIntegration}. Modificarlo puede provocar discrepancias en los datos. ¿Estás seguro de que deseas cancelar la aprobación de este informe?`,
         reimbursable: 'reembolsable',
         nonReimbursable: 'no reembolsable',
         bookingPending: 'Esta reserva está pendiente',
         bookingPendingDescription: 'Esta reserva está pendiente porque aún no se ha pagado.',
         bookingArchived: 'Esta reserva está archivada',
-        bookingArchivedDescription: 'Esta reserva está archivada porque la fecha del viaje ha pasado. Agregue un gasto por el importe final si es necesario.',
+        bookingArchivedDescription: 'Esta reserva está archivada porque la fecha del viaje ha pasado. Agregue un gasto por el monto final si es necesario.',
         attendees: 'Asistentes',
-        totalPerAttendee: 'Por asistente',
         whoIsYourAccountant: '¿Quién es tu contador?',
         paymentComplete: 'Pago completo',
         time: 'Tiempo',
@@ -1570,7 +1266,7 @@ const translations: TranslationDeepObject<typeof en> = {
         }),
         dates: 'Fechas',
         rates: 'Tasas',
-        submitsTo: (name) => `Se envía a ${name}`,
+        submitsTo: ({name}) => `Se envía a ${name}`,
         reject: {
             educationalTitle: '¿Debes retener o rechazar?',
             educationalText: 'Si no estás listo para aprobar o pagar un gasto, puedes retenerlo o rechazarlo.',
@@ -1579,7 +1275,7 @@ const translations: TranslationDeepObject<typeof en> = {
             heldExpenseLeftBehindTitle: 'Los gastos retenidos se dejan atrás cuando apruebas un informe completo.',
             rejectExpenseTitle: 'Rechaza un gasto que no tengos intención de aprobar o pagar.',
             reasonPageTitle: 'Rechazar gasto',
-            reasonPageDescription: 'Explica por qué no aprobarás este gasto.',
+            reasonPageDescription: 'Explica por qué estás rechazando este gasto.',
             rejectReason: 'Motivo del rechazo',
             markAsResolved: 'Marcar como resuelto',
             rejectedStatus: 'Este gasto fue rechazado. Estamos esperando que soluciones los problemas y lo marques como resuelto para poder enviarlo.',
@@ -1588,26 +1284,14 @@ const translations: TranslationDeepObject<typeof en> = {
                 markedAsResolved: 'marcó el motivo del rechazo como resuelto',
             },
         },
-        rejectReport: {
-            title: 'Rechazar informe',
-            description: 'Explica por qué rechazas este informe:',
-            rejectReason: 'Motivo del rechazo',
-            selectTarget: 'Elige al miembro al que devolver este informe para su revisión:',
-            lastApprover: 'Último aprobador',
-            submitter: 'Remitente',
-            rejectedReportMessage: 'Este informe fue rechazado.',
-            rejectedNextStep: 'Este informe fue rechazado. Esperando a que corrijas los problemas y lo vuelvas a enviar manualmente.',
-            selectMemberError: 'Selecciona un miembro al que devolver este informe.',
-            couldNotReject: 'No se pudo rechazar el informe. Por favor, inténtalo de nuevo.',
-        },
-        moveExpenses: 'Mover a informe',
+
+        moveExpenses: () => ({one: 'Mover gasto', other: 'Mover gastos'}),
         moveExpensesError: 'No puedes mover gastos per diem a informes de otros espacios de trabajo, porque las tarifas de dietas pueden diferir entre espacios de trabajo.',
         changeApprover: {
             title: 'Cambiar aprobador',
-            header: (workflowSettingLink) =>
+            header: ({workflowSettingLink}) =>
                 `Elige una opción para cambiar el aprobador de este informe. (Actualiza la <a href="${workflowSettingLink}">configuración del espacio de trabajo</a> para cambiarlo de forma permanente en todos los informes.)`,
             changedApproverMessage: (managerID) => `cambió el aprobador a <mention-user accountID="${managerID}"/>`,
-            reassignedApproverMessage: (managerID) => `reasignó el aprobador a <mention-user accountID="${managerID}"/> mediante una actualización de flujo de trabajo`,
             actions: {
                 addApprover: 'Añadir aprobador',
                 addApproverSubtitle: 'Añade un aprobador adicional al flujo de trabajo existente.',
@@ -1616,12 +1300,10 @@ const translations: TranslationDeepObject<typeof en> = {
             },
             addApprover: {
                 subtitle: 'Elige un aprobador adicional para este informe antes de que lo enviemos por el resto del flujo de aprobación.',
-                bulkSubtitle: 'Elige un aprobador adicional para estos informes antes de que los enviemos por el resto del flujo de aprobación.',
             },
-            bulkSubtitle: 'Elige una opción para cambiar el aprobador de estos informes.',
         },
         chooseWorkspace: 'Elige un espacio de trabajo',
-        routedDueToDEW: (to: string, reason?: string) => `informe enviado a ${to}${reason ? ` porque ${reason}` : ''}`,
+        routedDueToDEW: ({to}: RoutedDueToDEWParams) => `informe enviado a ${to} debido a un flujo de aprobación personalizado`,
         timeTracking: {
             hoursAt: (hours: number, rate: string) => `${hours} ${hours === 1 ? 'hora' : 'horas'} a ${rate} / hora`,
             hrs: 'h',
@@ -1629,27 +1311,40 @@ const translations: TranslationDeepObject<typeof en> = {
             ratePreview: (rate: string) => `${rate} / hora`,
             amountTooLargeError: 'El importe total es demasiado alto. Reduce las horas o disminuye la tasa.',
         },
-        correctRateError: 'Corrige el error de la tasa y vuelve a intentarlo.',
-        AskToExplain: `. <a href="${CONST.CONCIERGE_EXPLAIN_LINK_PATH}">Explicar<sparkles-icon/></a>`,
-        rulesModifiedFields: {
-            reimbursable: (value: boolean) => (value ? 'marcó el gasto como "reembolsable"' : 'marcó el gasto como "no reembolsable"'),
-            billable: (value: boolean) => (value ? 'marcó el gasto como "facturable"' : 'marcó el gasto como "no facturable"'),
-            tax: (value: string, isFirst: boolean) => (isFirst ? `estableció la tasa de impuesto a "${value}"` : `tasa de impuesto a "${value}"`),
-            reportName: (value: string) => `movió este gasto al informe "${value}"`,
-            common: (key: keyof PolicyRulesModifiedFields | keyof PersonalRulesModifiedFields, value: string, isFirst: boolean) => {
-                const field = translations.common[key].toLowerCase();
-                return isFirst ? `estableció el ${field} a "${value}"` : `${field} a "${value}"`;
-            },
-            formatPersonalRules: (fragments: string, route: string) => `${fragments} vía <a href="${route}">reglas de gastos personales</a>`,
-            formatPolicyRules: (fragments: string, route: string) => `${fragments} vía <a href="${route}">reglas del espacio de trabajo</a>`,
-        },
-        duplicateNonDefaultWorkspacePerDiemError: 'No puedes duplicar gastos de viáticos entre espacios de trabajo porque las tarifas pueden variar entre ellos.',
-        cannotDuplicateDistanceExpense: 'No puedes duplicar gastos de distancia entre espacios de trabajo porque las tasas pueden diferir entre espacios de trabajo.',
-        bulkDuplicateLimit: `Solo puedes duplicar hasta ${CONST.SEARCH.BULK_DUPLICATE_LIMIT} gastos a la vez. Por favor, selecciona menos gastos e inténtalo de nuevo.`,
-        taxDisabledAlert: {
-            title: 'Impuesto deshabilitado',
-            prompt: 'Habilita el seguimiento de impuestos en el espacio de trabajo para editar los detalles del gasto o eliminar el impuesto de este gasto.',
-            confirmText: 'Eliminar impuesto',
+        correctDistanceRateError: 'Corrige el error de la tasa de distancia y vuelve a intentarlo.',
+        AskToExplain: `. <a href="${CONST.CONCIERGE_EXPLAIN_LINK_PATH}"><strong>Explicar</strong></a> &#x2728;`,
+        policyRulesModifiedFields: (policyRulesModifiedFields: PolicyRulesModifiedFields, policyRulesRoute: string, formatList: (list: string[]) => string) => {
+            const entries = ObjectUtils.typedEntries(policyRulesModifiedFields);
+
+            const fragments = entries.map(([key, value], i) => {
+                const isFirst = i === 0;
+
+                if (key === 'reimbursable') {
+                    return value ? 'marcó el gasto como "reembolsable"' : 'marcó el gasto como "no reembolsable"';
+                }
+
+                if (key === 'billable') {
+                    return value ? 'marcó el gasto como "facturable"' : 'marcó el gasto como "no facturable"';
+                }
+
+                if (key === 'tax') {
+                    const taxEntry = value as PolicyRulesModifiedFields['tax'];
+                    const taxRateName = taxEntry?.field_id_TAX.name ?? '';
+                    if (isFirst) {
+                        return `estableció la tasa de impuesto a "${taxRateName}"`;
+                    }
+                    return `tasa de impuesto a "${taxRateName}"`;
+                }
+
+                const updatedValue = value as string | boolean;
+                if (isFirst) {
+                    return `estableció el ${translations.common[key].toLowerCase()} a "${updatedValue}"`;
+                }
+
+                return `${translations.common[key].toLowerCase()} a "${updatedValue}"`;
+            });
+
+            return `${formatList(fragments)} a través de <a href="${policyRulesRoute}">reglas del espacio de trabajo</a>`;
         },
     },
     transactionMerge: {
@@ -1719,7 +1414,8 @@ const translations: TranslationDeepObject<typeof en> = {
     },
     nextStep: {
         message: {
-            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_TO_ADD_TRANSACTIONS]: (actor, actorType, _eta, _etaType) => {
+            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_TO_ADD_TRANSACTIONS]: ({actor, actorType}) => {
+                // eslint-disable-next-line default-case
                 switch (actorType) {
                     case CONST.NEXT_STEP.ACTOR_TYPE.CURRENT_USER:
                         return `Esperando a que <strong>tú</strong> añadas gastos.`;
@@ -1729,7 +1425,8 @@ const translations: TranslationDeepObject<typeof en> = {
                         return `Esperando a que un administrador añada gastos.`;
                 }
             },
-            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_TO_SUBMIT]: (actor, actorType, _eta, _etaType) => {
+            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_TO_SUBMIT]: ({actor, actorType}) => {
+                // eslint-disable-next-line default-case
                 switch (actorType) {
                     case CONST.NEXT_STEP.ACTOR_TYPE.CURRENT_USER:
                         return `Esperando a que <strong>tú</strong> envíes los gastos.`;
@@ -1739,8 +1436,10 @@ const translations: TranslationDeepObject<typeof en> = {
                         return `Esperando a que un administrador envíe los gastos.`;
                 }
             },
-            [CONST.NEXT_STEP.MESSAGE_KEY.NO_FURTHER_ACTION]: (_actor, _actorType, _eta, _etaType) => `¡No se requiere ninguna acción adicional!`,
-            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_FOR_SUBMITTER_ACCOUNT]: (actor, actorType, _eta, _etaType) => {
+            // eslint-disable-next-line @typescript-eslint/no-unused-vars
+            [CONST.NEXT_STEP.MESSAGE_KEY.NO_FURTHER_ACTION]: (_) => `¡No se requiere ninguna acción adicional!`,
+            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_FOR_SUBMITTER_ACCOUNT]: ({actor, actorType}) => {
+                // eslint-disable-next-line default-case
                 switch (actorType) {
                     case CONST.NEXT_STEP.ACTOR_TYPE.CURRENT_USER:
                         return `Esperando a que <strong>tú</strong> añadas una cuenta bancaria.`;
@@ -1750,11 +1449,13 @@ const translations: TranslationDeepObject<typeof en> = {
                         return `Esperando a que un administrador añada una cuenta bancaria.`;
                 }
             },
-            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_FOR_AUTOMATIC_SUBMIT]: (actor, actorType, eta, etaType) => {
+            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_FOR_AUTOMATIC_SUBMIT]: ({actor, actorType, eta, etaType}) => {
                 let formattedETA = '';
                 if (eta) {
-                    formattedETA = etaType === CONST.NEXT_STEP.ETA_TYPE.DATE_TIME ? ` el ${eta} de cada mes` : ` ${eta}`;
+                    formattedETA = etaType === CONST.NEXT_STEP.ETA_TYPE.DATE_TIME ? ` el ${eta}` : ` ${eta}`;
                 }
+
+                // eslint-disable-next-line default-case
                 switch (actorType) {
                     case CONST.NEXT_STEP.ACTOR_TYPE.CURRENT_USER:
                         return `Esperando a que tus gastos se envíen automáticamente${formattedETA}.`;
@@ -1764,7 +1465,8 @@ const translations: TranslationDeepObject<typeof en> = {
                         return `Esperando a que los gastos de un administrador se envíen automáticamente${formattedETA}.`;
                 }
             },
-            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_TO_FIX_ISSUES]: (actor, actorType, _eta, _etaType) => {
+            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_TO_FIX_ISSUES]: ({actor, actorType}) => {
+                // eslint-disable-next-line default-case
                 switch (actorType) {
                     case CONST.NEXT_STEP.ACTOR_TYPE.CURRENT_USER:
                         return `Esperando a que <strong>tú</strong> soluciones ellos problemas.`;
@@ -1774,7 +1476,8 @@ const translations: TranslationDeepObject<typeof en> = {
                         return `Esperando a que un administrador solucione ellos problemas.`;
                 }
             },
-            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_TO_APPROVE]: (actor, actorType, _eta, _etaType) => {
+            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_TO_APPROVE]: ({actor, actorType}) => {
+                // eslint-disable-next-line default-case
                 switch (actorType) {
                     case CONST.NEXT_STEP.ACTOR_TYPE.CURRENT_USER:
                         return `Esperando a que <strong>tú</strong> apruebes los gastos.`;
@@ -1784,7 +1487,8 @@ const translations: TranslationDeepObject<typeof en> = {
                         return `Esperando a que un administrador apruebe los gastos.`;
                 }
             },
-            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_TO_EXPORT]: (actor, actorType, _eta, _etaType) => {
+            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_TO_EXPORT]: ({actor, actorType}) => {
+                // eslint-disable-next-line default-case
                 switch (actorType) {
                     case CONST.NEXT_STEP.ACTOR_TYPE.CURRENT_USER:
                         return `Esperando a que <strong>tú</strong> exportes este informe.`;
@@ -1794,7 +1498,8 @@ const translations: TranslationDeepObject<typeof en> = {
                         return `Esperando a que un administrador exporte este informe.`;
                 }
             },
-            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_TO_PAY]: (actor, actorType, _eta, _etaType) => {
+            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_TO_PAY]: ({actor, actorType}) => {
+                // eslint-disable-next-line default-case
                 switch (actorType) {
                     case CONST.NEXT_STEP.ACTOR_TYPE.CURRENT_USER:
                         return `Esperando a que <strong>tú</strong> pagues los gastos.`;
@@ -1804,7 +1509,8 @@ const translations: TranslationDeepObject<typeof en> = {
                         return `Esperando a que un administrador pague los gastos.`;
                 }
             },
-            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_FOR_POLICY_BANK_ACCOUNT]: (actor, actorType, _eta, _etaType) => {
+            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_FOR_POLICY_BANK_ACCOUNT]: ({actor, actorType}) => {
+                // eslint-disable-next-line default-case
                 switch (actorType) {
                     case CONST.NEXT_STEP.ACTOR_TYPE.CURRENT_USER:
                         return `Esperando a que <strong>tú</strong> termines de configurar una cuenta bancaria de empresa.`;
@@ -1814,25 +1520,17 @@ const translations: TranslationDeepObject<typeof en> = {
                         return `Esperando a que un administrador termine de configurar una cuenta bancaria de empresa.`;
                 }
             },
-            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_FOR_PAYMENT]: (_actor, _actorType, eta, etaType) => {
+            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_FOR_PAYMENT]: ({eta, etaType}) => {
                 let formattedETA = '';
                 if (eta) {
                     formattedETA = etaType === CONST.NEXT_STEP.ETA_TYPE.DATE_TIME ? ` para el ${eta}` : ` ${eta}`;
                 }
+
                 return `Esperando a que se complete el pago${formattedETA}.`;
             },
-            [CONST.NEXT_STEP.MESSAGE_KEY.SUBMITTING_TO_SELF]: (_actor, _actorType, _eta, _etaType) =>
+            // eslint-disable-next-line @typescript-eslint/no-unused-vars
+            [CONST.NEXT_STEP.MESSAGE_KEY.SUBMITTING_TO_SELF]: (_) =>
                 `¡Ups! Parece que estás enviando el informe a <strong>ti mismo</strong>. Aprobar tus propios informes está <strong>prohibido</strong> por tu espacio de trabajo. Por favor, envía este informe a otra persona o contacta a tu administrador para cambiar la persona a la que lo envías.`,
-            [CONST.NEXT_STEP.MESSAGE_KEY.REJECTED_REPORT]: (actor, actorType) => {
-                switch (actorType) {
-                    case CONST.NEXT_STEP.ACTOR_TYPE.CURRENT_USER:
-                        return `Este informe fue rechazado. Esperando a que <strong>tú</strong> corrijas los problemas y lo vuelvas a enviar manualmente.`;
-                    case CONST.NEXT_STEP.ACTOR_TYPE.OTHER_USER:
-                        return `Este informe fue rechazado. Esperando a que <strong>${actor}</strong> corrija los problemas y lo vuelva a enviar manualmente.`;
-                    case CONST.NEXT_STEP.ACTOR_TYPE.UNSPECIFIED_ADMIN:
-                        return `Este informe fue rechazado. Esperando a que un administrador corrija los problemas y lo vuelva a enviar manualmente.`;
-                }
-            },
         },
         eta: {
             [CONST.NEXT_STEP.ETA_KEY.SHORTLY]: 'en breve',
@@ -1844,6 +1542,7 @@ const translations: TranslationDeepObject<typeof en> = {
             [CONST.NEXT_STEP.ETA_KEY.END_OF_TRIP]: 'al final de tu viaje',
         },
     },
+
     profilePage: {
         profile: 'Perfil',
         preferredPronouns: 'Pronombres preferidos',
@@ -1858,8 +1557,6 @@ const translations: TranslationDeepObject<typeof en> = {
         offline: 'Desconectado',
         syncing: 'Sincronizando',
         profileAvatar: 'Perfil avatar',
-        customInstructions: 'Instrucciones personalizadas',
-        copilotIntoAccount: 'Copilot a la cuenta',
         publicSection: {
             title: 'Público',
             subtitle: 'Estos detalles se muestran en tu perfil público, a disposición de los demás.',
@@ -1868,16 +1565,12 @@ const translations: TranslationDeepObject<typeof en> = {
             title: 'Privado',
             subtitle: 'Estos detalles se utilizan para viajes y pagos. Nunca se mostrarán en tu perfil público.',
         },
-        aiPromptSection: {
-            title: 'Indicaciones de IA',
-            subtitle: 'Escribe instrucciones personalizadas',
-            prompt: 'Indicador',
-            editPrompt: 'Editar mensaje',
-            promptCannotBeEmpty: 'El campo de indicaciones no puede estar vacío',
-            saved: 'Guardado',
-        },
     },
-    securityPage: {title: 'Seguridad', subtitle: 'Mantén tu cuenta segura.', goToSecurity: 'Volver a la página de seguridad'},
+    securityPage: {
+        title: 'Opciones de seguridad',
+        subtitle: 'Activa la autenticación de dos factores para mantener tu cuenta segura.',
+        goToSecurity: 'Volver a la página de seguridad',
+    },
     shareCodePage: {
         title: 'Tu código',
         subtitle: 'Invita a miembros a Expensify compartiendo tu código QR personal o enlace de invitación.',
@@ -1899,7 +1592,6 @@ const translations: TranslationDeepObject<typeof en> = {
         setAsDefault: 'Establecer como predeterminado',
         yourDefaultContactMethod:
             'Este es tu método de contacto predeterminado. Antes de poder eliminarlo, tendrás que elegir otro método de contacto y haz clic en "Establecer como predeterminado".',
-        yourDefaultContactMethodRestrictedSwitch: 'Este es tu método de contacto predeterminado actual. Tu empresa ha restringido su eliminación o modificación.',
         removeContactMethod: 'Eliminar método de contacto',
         removeAreYouSure: '¿Estás seguro de que quieres eliminar este método de contacto? Esta acción no se puede deshacer.',
         failedNewContact: 'Se ha producido un error al añadir este método de contacto.',
@@ -1975,6 +1667,8 @@ const translations: TranslationDeepObject<typeof en> = {
         },
         troubleshoot: {
             clearCacheAndRestart: 'Borrar caché y reiniciar',
+            viewConsole: 'Ver la consola de depuración',
+            debugConsole: 'Consola de depuración',
             description:
                 '<muted-text>Utilice las herramientas que aparecen a continuación para solucionar los problemas de Expensify. Si tiene algún problema, por favor <concierge-link>envíe un informe de error</concierge-link>.</muted-text>',
             confirmResetDescription: 'Todos los borradores no enviados se perderán, pero el resto de tus datos estarán a salvo.',
@@ -2006,42 +1700,31 @@ const translations: TranslationDeepObject<typeof en> = {
             invalidateWithDelay: 'Invalidar con retraso',
             leftHandNavCache: 'Caché del menú de navegación izquierdo',
             clearleftHandNavCache: 'borrar',
+            recordTroubleshootData: 'Registrar datos de resolución de problemas',
             softKillTheApp: 'Desactivar la aplicación',
             kill: 'Matar',
             sentryDebug: 'Depuración de Sentry',
-            sentrySendDescription: 'Enviar datos a Sentry',
             sentryDebugDescription: 'Registrar las solicitudes de Sentry en la consola',
             sentryHighlightedSpanOps: 'Nombres de spans resaltados',
             sentryHighlightedSpanOpsPlaceholder: 'ui.interaction.click, navigation, ui.load',
-            showBranchNameInTitle: 'Mostrar nombre de rama en el título del navegador',
+        },
+        debugConsole: {
+            saveLog: 'Guardar registro',
+            shareLog: 'Compartir registro',
+            enterCommand: 'Introducir comando',
+            execute: 'Ejecutar',
+            noLogsAvailable: 'No hay registros disponibles',
+            logSizeTooLarge: (size) => `El tamaño del registro excede el límite de ${size} MB. Utilice "Guardar registro" para descargar el archivo de registro.`,
+            logs: 'Logs',
+            viewConsole: 'Ver consola',
         },
         security: 'Seguridad',
         restoreStashed: 'Restablecer login guardado',
         signOut: 'Desconectar',
         signOutConfirmationText: 'Si cierras sesión perderás los cambios hechos mientras estabas desconectado',
         versionLetter: 'v',
-        readTheTermsAndPrivacy: `Leer los <a href="${CONST.OLD_DOT_PUBLIC_URLS.TERMS_URL}">Términos de Servicio</a> y <a href="${CONST.OLD_DOT_PUBLIC_URLS.PRIVACY_URL}">Privacidad</a>.`,
+        readTheTermsAndPrivacy: `<muted-text-micro>Leer los <a href="${CONST.OLD_DOT_PUBLIC_URLS.TERMS_URL}">Términos de Servicio</a> y <a href="${CONST.OLD_DOT_PUBLIC_URLS.PRIVACY_URL}">Privacidad</a>.</muted-text-micro>`,
         help: 'Ayuda',
-        helpPage: {
-            title: 'Ayuda y soporte',
-            description: 'Estamos aquí para ayudarte en todo momento.',
-            helpSite: 'Centro de ayuda',
-            helpSiteDescription: 'Artículos, tutoriales y más',
-            conciergeChat: 'Concierge',
-            conciergeChatDescription: 'Tu asistente personal de IA',
-            accountManager: 'Gestor de cuenta',
-            yourAccountManager: 'Tu gestor de cuenta',
-            accountManagerDescription: 'Haz preguntas y obtén ayuda al cliente',
-            partnerManager: 'Gestor de socios',
-            yourPartnerManager: 'Tu gestor de partners',
-            partnerManagerDescription: 'Maximiza tu colaboración y genera referencias',
-            guideDescription: 'Tu ejecutivo de cuenta',
-            approvedPartnerTeamTitle: 'Conoce a tu equipo de partners de Approved!',
-            approvedPartnerTeamDescription: 'Un equipo dedicado centrado en ayudar a que tu firma crezca, incorporar clientes más rápido y obtener soporte experto siempre que lo necesites.',
-            accountExecutive: 'Ejecutivo de cuentas',
-            accountExecutiveDescription: 'Configura a los clientes correctamente',
-            moreResources: 'Más recursos',
-        },
         whatIsNew: 'Qué hay de nuevo',
         accountSettings: 'Configuración de la cuenta',
         account: 'Cuenta',
@@ -2117,8 +1800,6 @@ const translations: TranslationDeepObject<typeof en> = {
         reportSuspiciousActivity: 'Informar de actividad sospechosa',
         lockAccount: 'Bloquear cuenta',
         unlockAccount: 'Desbloquear cuenta',
-        unlockTitle: 'Hemos recibido tu solicitud',
-        unlockDescription: 'Revisaremos la cuenta para verificar que sea seguro desbloquearla y nos comunicaremos a través de Concierge si tenemos alguna pregunta.',
         compromisedDescription:
             '¿Notas algo extraño en tu cuenta? Informarlo bloqueará tu cuenta de inmediato, detendrá nuevas transacciones con la Tarjeta Expensify y evitará cualquier cambio en la cuenta.',
         domainAdminsDescription: 'Para administradores de dominio: Esto también detiene toda la actividad de la Tarjeta Expensify y las acciones administrativas en tus dominios.',
@@ -2136,13 +1817,6 @@ const translations: TranslationDeepObject<typeof en> = {
         chatToConciergeToUnlock: 'Chatea con Concierge para resolver los problemas de seguridad y desbloquear tu cuenta.',
         chatWithConcierge: 'Chatear con Concierge',
     },
-    deviceManagementPage: {
-        title: 'Gestión de dispositivos',
-        description:
-            'Gestiona todos los dispositivos en los que has iniciado sesión con tu cuenta de Expensify. <a href="https://help.expensify.com/articles/new-expensify/settings/Manage-Logged-in-Devices">Más información</a>.',
-        revoke: 'Revocar',
-        unknownDevice: 'Dispositivo Desconocido',
-    },
     twoFactorAuth: {
         headerTitle: 'Autenticación de dos factores',
         twoFactorAuthEnabled: 'Autenticación de dos factores habilitada',
@@ -2154,17 +1828,14 @@ const translations: TranslationDeepObject<typeof en> = {
         disabled: 'La autenticación de dos factores está ahora deshabilitada',
         noAuthenticatorApp: 'Ya no necesitarás una aplicación de autenticación para iniciar sesión en Expensify.',
         stepCodes: 'Códigos de recuperación',
-        keepCodesSafe: '¡Guarda estos códigos en un lugar seguro!',
-        codesLoseAccess: dedent(`
-            Si pierdes el acceso a tu aplicación de autenticación y no tienes estos códigos, quedarás bloqueado fuera de tu cuenta.<br><br>
-            <strong>Nota</strong>: Al habilitar la autenticación de dos factores, se cerrará tu sesión en todas las demás sesiones.
-        `),
+        keepCodesSafe: '¡Guarda los códigos de recuperación en un lugar seguro!',
+        codesLoseAccess:
+            'Si pierdes el acceso a tu aplicación de autenticación y no tienes estos códigos, perderás el acceso a tu cuenta. \n\nNota: Configurar la autenticación de dos factores cerrará la sesión de todas las demás sesiones activas.',
         errorStepCodes: 'Copia o descarga los códigos antes de continuar',
         stepVerify: 'Verificar',
         scanCode: 'Escanea el código QR usando tu',
         authenticatorApp: 'aplicación de autenticación',
         addKey: 'O añade esta clave secreta a tu aplicación de autenticación:',
-        secretKey: 'clave secreta',
         enterCode: 'Luego introduce el código de seis dígitos generado por tu aplicación de autenticación.',
         stepSuccess: 'Finalizado',
         enabled: 'La autenticación de dos factores habilitada',
@@ -2180,14 +1851,6 @@ const translations: TranslationDeepObject<typeof en> = {
         twoFactorAuthIsRequiredCompany: 'Tu empresa requiere el uso de autenticación de dos factores. Por favor, habilítala para seguir usando Expensify.',
         twoFactorAuthCannotDisable: 'No se puede desactivar la autenticación de dos factores (2FA)',
         twoFactorAuthRequired: 'La autenticación de dos factores (2FA) es obligatoria para tu conexión a Xero y no se puede desactivar.',
-        replaceDevice: 'Reemplazar dispositivo',
-        replaceDeviceTitle: 'Reemplazar dispositivo de autenticación de dos factores',
-        verifyOldDeviceTitle: 'Verificar dispositivo anterior',
-        verifyOldDeviceDescription: 'Introduce el código de seis dígitos de tu aplicación de autenticación actual para confirmar que tienes acceso a ella.',
-        verifyNewDeviceTitle: 'Configurar nuevo dispositivo',
-        verifyNewDeviceDescription: 'Escanea el código QR con tu nuevo dispositivo y luego introduce el código para completar la configuración.',
-        downloadCodes: 'Descargar códigos',
-        copyCodes: 'Copiar códigos',
     },
     recoveryCodeForm: {
         error: {
@@ -2275,39 +1938,6 @@ const translations: TranslationDeepObject<typeof en> = {
             password: 'Por favor, introduce tu contraseña de Expensify',
         },
     },
-    personalCard: {
-        addPersonalCard: 'Añadir tarjeta personal',
-        addCompanyCard: 'Añadir tarjeta de empresa',
-        lookingForCompanyCards: '¿Necesitas añadir tarjetas de empresa?',
-        lookingForCompanyCardsDescription: 'Añade tus propias tarjetas de más de 10.000 bancos de todo el mundo.',
-        personalCardAdded: '¡Tarjeta personal añadida!',
-        personalCardAddedDescription: '¡Felicidades! Empezaremos a importar transacciones desde tu tarjeta',
-        isPersonalCard: '¿Es una tarjeta personal?',
-        thisIsPersonalCard: 'Esta es una tarjeta personal',
-        thisIsCompanyCard: 'Esta es una tarjeta de empresa',
-        askAdmin: 'Pregunta a tu administrador',
-        warningDescription: ({isAdmin}: {isAdmin?: boolean}) =>
-            `Si es así, ¡genial! Pero si es una tarjeta de <strong>empresa</strong>, ${isAdmin ? 'asígnala desde tu espacio de trabajo.' : 'pide a tu administrador que te la asigne desde el espacio de trabajo.'}`,
-        bankConnectionError: 'Problema de conexión bancaria',
-        bankConnectionDescription: 'Intenta añadir tus tarjetas de nuevo. De lo contrario, puedes',
-        connectWithPlaid: 'conectar a través de Plaid.',
-        brokenConnection: 'Hay un problema con la conexión de tu tarjeta.',
-        fixCard: 'Arreglar conexión de la tarjeta',
-        conciergeBrokenConnection: ({cardName, connectionLink}: ConciergeBrokenCardConnectionParams) =>
-            connectionLink
-                ? `La conexión de tu tarjeta ${cardName} se ha interrumpido. <a href="${connectionLink}">Inicia sesión en tu banco</a> para arreglarla.`
-                : `La conexión de tu tarjeta ${cardName} se ha interrumpido. Inicia sesión en tu banco para arreglarla.`,
-        addAdditionalCards: 'Añadir más tarjetas',
-        upgradeDescription: '¿Necesitas añadir más tarjetas? Crea un espacio de trabajo para añadir tarjetas personales o asignar tarjetas de empresa a todo el equipo.',
-        onlyAvailableOnPlan: ({formattedPrice}: {formattedPrice: string}) =>
-            `<muted-text>Disponible en el plan Collect, que cuesta <strong>${formattedPrice}</strong> por miembro al mes.</muted-text>`,
-        note: (subscriptionLink) =>
-            `<muted-text>Crea un espacio de trabajo para acceder a esta función, o <a href="${subscriptionLink}">más información</a> sobre nuestros planes y precios.</muted-text>`,
-        workspaceCreated: 'Espacio de trabajo creado',
-        newWorkspace: '¡Has creado un espacio de trabajo!',
-        successMessage: ({subscriptionLink}: {subscriptionLink: string}) =>
-            `<centered-text>Ya puedes añadir más tarjetas. <a href="${subscriptionLink}">Ver tu suscripción</a> para más detalles.</centered-text>`,
-    },
     walletPage: {
         balance: 'Saldo',
         paymentMethodsTitle: 'Métodos de pago',
@@ -2335,9 +1965,8 @@ const translations: TranslationDeepObject<typeof en> = {
         enableWallet: 'Habilitar billetera',
         addBankAccountToSendAndReceive: 'Añade una cuenta bancaria para hacer o recibir pagos.',
         addDebitOrCreditCard: 'Añadir tarjeta de débito o crédito',
-        cardInactive: 'Inactiva',
-        assignedCards: 'Tarjetas',
-        assignedCardsDescription: 'Las transacciones de las tarjetas asignadas se sincronizan automáticamente.',
+        assignedCards: 'Tarjetas asignadas',
+        assignedCardsDescription: 'Las transacciones de estas tarjetas se sincronizan automáticamente.',
         expensifyCard: 'Tarjeta Expensify',
         walletActivationPending: 'Estamos revisando tu información. Por favor, vuelve en unos minutos.',
         walletActivationFailed: 'Lamentablemente, no podemos activar tu billetera en este momento. Chatea con Concierge para obtener más ayuda.',
@@ -2363,11 +1992,6 @@ const translations: TranslationDeepObject<typeof en> = {
         unshareBankAccountWarning: ({admin}: {admin?: string | null}) => `${admin} perderá el acceso a esta cuenta bancaria comercial. Seguiremos completando los pagos en proceso.`,
         reachOutForHelp: 'Se está usando con la tarjeta Expensify. <concierge-link>Contacte con Concierge</concierge-link> si necesita dejar de compartirla.',
         unshareErrorModalTitle: 'No se puede dejar de compartir la cuenta bancaria',
-        travelCVV: {
-            title: 'CVV de viaje',
-            subtitle: 'Úsalo al reservar viajes',
-            description: 'Usa esta tarjeta para tus reservas de Expensify Travel. Aparecerá como “Travel Card” al pagar.',
-        },
         chaseAccountNumberDifferent: '¿Por qué es diferente el número de mi cuenta?',
     },
     cardPage: {
@@ -2376,15 +2000,15 @@ const translations: TranslationDeepObject<typeof en> = {
         availableSpend: 'Límite restante',
         smartLimit: {
             name: 'Límite inteligente',
-            title: (formattedLimit) => `Puedes gastar hasta ${formattedLimit} en esta tarjeta al mes. El límite se restablecerá el primer día del mes.`,
+            title: ({formattedLimit}) => `Puedes gastar hasta ${formattedLimit} en esta tarjeta al mes. El límite se restablecerá el primer día del mes.`,
         },
         fixedLimit: {
             name: 'Límite fijo',
-            title: (formattedLimit) => `Puedes gastar hasta ${formattedLimit} en esta tarjeta, luego se desactivará.`,
+            title: ({formattedLimit}) => `Puedes gastar hasta ${formattedLimit} en esta tarjeta, luego se desactivará.`,
         },
         monthlyLimit: {
             name: 'Límite mensual',
-            title: (formattedLimit) => `Puedes gastar hasta ${formattedLimit} en esta tarjeta y el límite se restablecerá a medida que se aprueben tus gastos.`,
+            title: ({formattedLimit}) => `Puedes gastar hasta ${formattedLimit} en esta tarjeta y el límite se restablecerá a medida que se aprueben tus gastos.`,
         },
         virtualCardNumber: 'Número de la tarjeta virtual',
         travelCardCvv: 'CVV de la tarjeta de viaje',
@@ -2393,8 +2017,6 @@ const translations: TranslationDeepObject<typeof en> = {
         getPhysicalCard: 'Obtener tarjeta física',
         reportFraud: 'Reportar fraude con la tarjeta virtual',
         reportTravelFraud: 'Reportar fraude con la tarjeta de viaje',
-        spendRules: 'Reglas de gasto',
-        editSpendRules: 'Editar reglas de gasto',
         reviewTransaction: 'Revisar transacción',
         suspiciousBannerTitle: 'Transacción sospechosa',
         suspiciousBannerDescription: 'Hemos detectado una transacción sospechosa en la tarjeta. Haz click abajo para revisarla.',
@@ -2407,17 +2029,16 @@ const translations: TranslationDeepObject<typeof en> = {
             expiration: 'Expiración',
             cvv: 'CVV',
             address: 'Dirección',
-            reveal: 'Revelar',
             revealDetails: 'Revelar detalles',
             revealCvv: 'Revelar CVV',
             copyCardNumber: 'Copiar número de la tarjeta',
-            copyCvv: 'Copiar CVV',
             updateAddress: 'Actualizar dirección',
         },
         cardAddedToWallet: ({platform}) => `Añadida a ${platform} Wallet`,
         cardDetailsLoadingFailure: 'Se ha producido un error al cargar los datos de la tarjeta. Comprueba tu conexión a Internet e inténtalo de nuevo.',
         validateCardTitle: 'Asegurémonos de que eres tú',
         enterMagicCode: (contactMethod) => `Introduzca el código mágico enviado a ${contactMethod} para ver los datos de su tarjeta. Debería llegar en un par de minutos.`,
+        missingPrivateDetails: ({missingDetailsLink}: {missingDetailsLink: string}) => `Por favor, <a href="${missingDetailsLink}">agrega tus datos personales</a> y vuelve a intentarlo.`,
         unexpectedError: 'Se produjo un error al intentar obtener los detalles de tu tarjeta Expensify. Vuelve a intentarlo.',
         cardFraudAlert: {
             confirmButtonText: 'Sí, lo hago',
@@ -2428,40 +2049,6 @@ const translations: TranslationDeepObject<typeof en> = {
 
 ${amount} para ${merchant} - ${date}`,
         },
-        setYourPin: 'Establece tu PIN.',
-        confirmYourPin: 'Confirma tu PIN.',
-        changeYourPin: 'Introduce un nuevo PIN para tu tarjeta.',
-        confirmYourChangedPin: 'Confirma tu nuevo PIN.',
-        pinMustBeFourDigits: 'El PIN debe tener exactamente 4 dígitos.',
-        invalidPin: 'Por favor, elige un PIN más seguro.',
-        pinMismatch: 'Los PINs no coinciden. Por favor, inténtalo de nuevo.',
-        revealPin: 'Mostrar PIN',
-        hidePin: 'Ocultar PIN',
-        pin: 'PIN',
-        changePin: 'Cambiar PIN',
-        pinChanged: '¡PIN cambiado!',
-        pinChangedHeader: 'PIN cambiado',
-        pinChangedDescription: 'Ya puedes usar tu nuevo PIN.',
-        cardUnblocked: '¡Tarjeta desbloqueada!',
-        cardUnblockedDescription: 'Es posible que se te pida insertar tu tarjeta en el lector la próxima vez que realices una compra.',
-        pinBlocked: 'Tu tarjeta fue bloqueada por introducir el PIN incorrectamente varias veces.',
-        unblock: 'Desbloquear',
-        unblockCard: 'Desbloquear tarjeta',
-        changePinAtATM: 'Cambia tu PIN en cualquier cajero automático',
-        changePinAtATMDescription: 'Esto es obligatorio en tu región. <concierge-link>Contacta a Concierge</concierge-link> si tienes alguna pregunta.',
-        freezeCard: 'Congelar tarjeta',
-        unfreeze: 'Descongelar',
-        unfreezeCard: 'Descongelar tarjeta',
-        askToUnfreeze: 'Solicitar descongelación',
-        freezeDescription: 'Una tarjeta congelada no se puede usar para compras ni transacciones. Puedes descongelarla en cualquier momento.',
-        unfreezeDescription: 'Al descongelar esta tarjeta se volverán a permitir compras y transacciones. Continúa solo si estás seguro de que la tarjeta es segura para usar.',
-        frozen: 'Congelada',
-        youFroze: ({date}: {date: string}) => `Congelaste esta tarjeta el ${date}.`,
-        frozenBy: ({person, date}: {person: string; date: string}) => `${person} congeló esta tarjeta el ${date}.`,
-        frozenByAdminPrefix: ({date}: {date: string}) => `Esta tarjeta fue congelada el ${date} por `,
-        frozenByAdminNeedsUnfreezePrefix: 'Esta tarjeta fue congelada por ',
-        frozenByAdminNeedsUnfreezeSuffix: '. Ponte en contacto con un administrador para descongelarla.',
-        frozenByAdminNeedsUnfreeze: ({person}: {person: string}) => `Esta tarjeta fue congelada por ${person}. Ponte en contacto con un administrador para descongelarla.`,
     },
     workflowsPage: {
         workflowTitle: 'Gasto',
@@ -2473,21 +2060,9 @@ ${amount} para ${merchant} - ${date}`,
         addApprovalsTitle: 'Aprobaciones',
         accessibilityLabel: ({members, approvers}: {members: string; approvers: string}) => `gastos de ${members}, y el aprobador es ${approvers}`,
         addApprovalButton: 'Añadir flujo de aprobación',
-        editWorkflowAction: 'Editar',
-        addAgentAction: 'Añadir agente',
-        findWorkflow: 'Buscar flujo de trabajo',
         addApprovalTip: 'Este flujo de trabajo por defecto se aplica a todos los miembros, a menos que exista un flujo de trabajo más específico.',
         approver: 'Aprobador',
         addApprovalsDescription: 'Requiere una aprobación adicional antes de autorizar un pago.',
-        automateApprovalsWithAgentsTitle: 'Automatiza las aprobaciones con agentes',
-        automateApprovalsWithAgentsSubtitle: 'Añade el agente de abajo al flujo de trabajo para automatizar las aprobaciones.',
-        configureViaHR: ({provider}: {provider: string}) => `Configurar mediante ${provider}.`,
-        hrApprovalWorkflowLockedPrompt: ({provider}: {provider: string}) =>
-            `Las aprobaciones se gestionan mediante tu integración de ${provider}. Para actualizar tu flujo de aprobación, ve a la configuración de conexión de ${provider}.`,
-        goToHRSettings: ({provider}: {provider: string}) => `Ir a la configuración de ${provider}`,
-        approverFromProvider: ({provider}: {provider: string}) => `de ${provider}`,
-        finalApprover: 'Aprobador final',
-        manager: 'Responsable',
         makeOrTrackPaymentsTitle: 'Realizar o seguir pagos',
         makeOrTrackPaymentsDescription: 'Añade un pagador autorizado para los pagos realizados en Expensify o realiza un seguimiento de los pagos realizados en otro lugar.',
         customApprovalWorkflowEnabled:
@@ -2513,6 +2088,7 @@ ${amount} para ${merchant} - ${date}`,
                 two: 'º',
                 few: 'º',
                 other: 'º',
+                /* eslint-disable @typescript-eslint/naming-convention */
                 '1': 'Primero',
                 '2': 'Segundo',
                 '3': 'Tercero',
@@ -2523,6 +2099,7 @@ ${amount} para ${merchant} - ${date}`,
                 '8': 'Octavo',
                 '9': 'Noveno',
                 '10': 'Décimo',
+                /* eslint-enable @typescript-eslint/naming-convention */
             },
         },
         approverInMultipleWorkflows: 'Este miembro ya pertenece a otro flujo de aprobación. Cualquier actualización aquí se reflejará allí también.',
@@ -2532,7 +2109,6 @@ ${amount} para ${merchant} - ${date}`,
             title: 'No hay miembros para mostrar',
             expensesFromSubtitle: 'Todos los miembros del espacio de trabajo ya pertenecen a un flujo de aprobación existente.',
             approverSubtitle: 'Todos los aprobadores pertenecen a un flujo de trabajo existente.',
-            bulkApproverSubtitle: 'Ningún aprobador coincide con los criterios de los informes seleccionados.',
         },
     },
     workflowsDelayedSubmissionPage: {
@@ -2553,9 +2129,6 @@ ${amount} para ${merchant} - ${date}`,
     workflowsExpensesFromPage: {
         title: 'Gastos de',
         header: 'Cuando los siguientes miembros presenten gastos:',
-        memberAlreadyInWorkflowTitle: 'Miembro ya está en un flujo de trabajo',
-        memberAlreadyInWorkflowPrompt: ({memberName, approverName}: {memberName: string; approverName: string}) =>
-            `${memberName} ya está en un flujo de trabajo de aprobación que envía a ${approverName}. Agregarlo aquí lo moverá a este flujo de trabajo.`,
     },
     workflowsApproverPage: {
         genericErrorMessage: 'El aprobador no pudo ser cambiado. Por favor, inténtelo de nuevo o contacte al soporte.',
@@ -2585,16 +2158,6 @@ ${amount} para ${merchant} - ${date}`,
         admins: 'Administradores',
         payer: 'Pagador',
         paymentAccount: 'Cuenta de pago',
-        shareBankAccount: {
-            shareTitle: '¿Compartir acceso a la cuenta bancaria?',
-            shareDescription: ({admin}: {admin: string}) => `Necesitarás compartir el acceso a la cuenta bancaria con ${admin} para que sea el pagador.`,
-            validationTitle: 'Cuenta bancaria en espera de validación',
-            validationDescription: ({admin}: {admin: string}) =>
-                `Necesitas <a href="#">validar esta cuenta bancaria</a>. Una vez hecho esto, puedes compartir el acceso a la cuenta bancaria con ${admin} para que sea el pagador.`,
-            errorTitle: 'No se puede cambiar el pagador',
-            errorDescription: ({admin, owner}: {admin: string; owner: string}) =>
-                `${admin} no tiene acceso a esta cuenta bancaria, por lo que no puede asignarle el pago. <a href="#">Chatea con ${owner}</a> si la cuenta bancaria debe compartirse.`,
-        },
     },
     reportFraudPage: {
         title: 'Reportar fraude con la tarjeta virtual',
@@ -2606,7 +2169,6 @@ ${amount} para ${merchant} - ${date}`,
     reportFraudConfirmationPage: {
         title: 'Fraude con tarjeta reportado',
         description: 'Hemos desactivado permanentemente tu tarjeta existente. Cuando vuelvas a ver los detalles de tu tarjeta, tendrás una nueva tarjeta virtual disponible.',
-        descriptionCardNotReplaced: 'Tu tarjeta fue desactivada permanentemente. Por favor, contacta a un administrador para emitir una nueva tarjeta.',
         buttonText: 'Entendido, ¡gracias!',
     },
     activateCardPage: {
@@ -2641,7 +2203,7 @@ ${amount} para ${merchant} - ${date}`,
         shipCard: 'Enviar tarjeta',
     },
     transferAmountPage: {
-        transfer: (amount) => `Transferir${amount ? ` ${amount}` : ''}`,
+        transfer: ({amount}) => `Transferir${amount ? ` ${amount}` : ''}`,
         instant: 'Instante',
         instantSummary: (rate, minAmount) => `Tarifa del ${rate}% (${minAmount} mínimo)`,
         ach: '1-3 días laborales',
@@ -2668,50 +2230,14 @@ ${amount} para ${merchant} - ${date}`,
         defaultPaymentMethod: 'Predeterminado',
         bankAccountLastFour: (lastFour) => `Cuenta bancaria • ${lastFour}`,
     },
-    agentsPage: {
-        title: 'Agentes',
-        subtitle: 'Automatiza tareas con agentes personalizados.',
-        newAgent: 'Nuevo agente',
-        emptyAgents: {
-            title: 'No se han creado agentes.',
-            subtitle: 'Deja de hacer las cosas manualmente. En su lugar, instruye a un agente y ahorra mucho tiempo.',
-        },
-        error: {
-            genericAdd: 'Hubo un problema al agregar este agente',
-            genericUpdate: 'Hubo un problema al actualizar este agente',
-            updateName: 'Hubo un problema al actualizar el nombre de este agente',
-            updatePrompt: 'Hubo un problema al actualizar las instrucciones de este agente',
-            updateAvatar: 'Hubo un problema al actualizar el avatar de este agente',
-        },
-    },
-    addAgentPage: {
-        title: 'Nuevo agente',
-        agentName: 'Nombre del agente',
-        instructions: 'Escribe instrucciones personalizadas',
-        createAgent: 'Crear agente',
-        editAvatar: 'Cambiar avatar',
-        defaultAgentName: (displayName: string) => `Agente de ${displayName}`,
-        defaultPrompt:
-            'Rechazar gastos por juegos de azar, películas u otras razones claramente no comerciales.\n\nRecordar al usuario que siempre incluya una imagen del recibo que muestre claramente la propina.\n\nAprobar el informe si es muy similar a informes anteriores del mismo usuario.\n\nRechazar informes con más de $500 en gastos de viaje.',
-    },
-    editAgentPage: {
-        title: 'Editar agente',
-        agentName: 'Nombre del agente',
-        instructions: 'Escribir instrucciones personalizadas',
-        chatWithAgent: 'Chatear con el agente',
-        copilotIntoAccount: 'Copilot en la cuenta',
-        deleteAgent: 'Eliminar agente',
-        deleteAgentTitle: '¿Eliminar agente?',
-        deleteAgentMessage: '¿Seguro que quieres eliminar a este agente? Esta acción no se puede deshacer.',
-    },
-    editAgentAvatarPage: {title: 'Editar avatar'},
-    editAgentNamePage: {title: 'Nombre del agente'},
-    editAgentPromptPage: {title: 'Escribir instrucciones personalizadas', error: {emptyPrompt: 'Por favor, introduce instrucciones para tu agente.'}},
     expenseRulesPage: {
         title: 'Reglas de gastos',
-        subtitle: 'Estas reglas se aplicarán a tus gastos.',
+        subtitle: 'Estas reglas se aplicarán a tus gastos. Si los envías a un espacio de trabajo, las reglas del espacio de trabajo pueden anularlas.',
         findRule: 'Encontrar regla',
-        emptyRules: {title: 'Aún no hay reglas', subtitle: 'Añade una regla para automatizar los informes de gastos.'},
+        emptyRules: {
+            title: 'Aún no has creado ninguna regla',
+            subtitle: 'Añade una regla para automatizar los informes de gastos.',
+        },
         changes: {
             billableUpdate: (value: boolean) => `Actualiza el gasto a ${value ? 'facturable' : 'no facturable'}`,
             categoryUpdate: (value: string) => `Actualiza la categoría a "${value}"`,
@@ -2780,8 +2306,7 @@ ${amount} para ${merchant} - ${date}`,
         },
     },
     reportDetailsPage: {
-        goToRoom: 'Ir a la sala',
-        inWorkspace: (policyName) => `en ${policyName}`,
+        inWorkspace: ({policyName}) => `en ${policyName}`,
         generatingPDF: 'Generar PDF',
         waitForPDF: 'Por favor, espera mientras creamos el PDF.',
         errorPDF: 'Ocurrió un error al crear el PDF',
@@ -2795,7 +2320,7 @@ ${amount} para ${merchant} - ${date}`,
     groupChat: {
         lastMemberTitle: '¡Atención!',
         lastMemberWarning: 'Ya que eres la última persona aquí, si te vas, este chat quedará inaccesible para todos los miembros. ¿Estás seguro de que quieres salir del chat?',
-        defaultReportName: (displayName) => `Chat de grupo de ${displayName}`,
+        defaultReportName: ({displayName}) => `Chat de grupo de ${displayName}`,
     },
     languagePage: {
         language: 'Idioma',
@@ -2814,26 +2339,19 @@ ${amount} para ${merchant} - ${date}`,
                 label: 'Utiliza los ajustes del dispositivo',
             },
         },
-        highContrastMode: 'Modo de alto contraste',
-        enableHighContrast: 'Activar alto contraste',
-        disableHighContrast: 'Desactivar alto contraste',
         chooseThemeBelowOrSync: 'Elige un tema a continuación o sincronízalo con los ajustes de tu dispositivo.',
     },
     termsOfUse: {
         terms: `<muted-text-xs>Al iniciar sesión, estás accediendo a los <a href="${CONST.OLD_DOT_PUBLIC_URLS.TERMS_URL}">Términos de Servicio</a> y <a href="${CONST.OLD_DOT_PUBLIC_URLS.PRIVACY_URL}">Privacidad</a>.</muted-text-xs>`,
-        license: `El envío de dinero es brindado por ${CONST.WALLET.PROGRAM_ISSUERS.EXPENSIFY_PAYMENTS} (NMLS ID:2017010) de conformidad con sus <a href="${CONST.OLD_DOT_PUBLIC_URLS.LICENSES_URL}">licencias</a>.`,
+        license: `<muted-text-xs>El envío de dinero es brindado por ${CONST.WALLET.PROGRAM_ISSUERS.EXPENSIFY_PAYMENTS} (NMLS ID:2017010) de conformidad con sus <a href="${CONST.OLD_DOT_PUBLIC_URLS.LICENSES_URL}">licencias</a>.</muted-text-xs>`,
     },
     validateCodeForm: {
         magicCodeNotReceived: '¿No recibiste un código mágico?',
-        avoidScamsMessage:
-            '<strong>Evita las estafas. No compartas tu código con nadie.</strong> Nuestro equipo nunca te llamará, enviará mensajes de texto ni correos electrónicos para solicitarte este código.',
         enterAuthenticatorCode: 'Por favor, introduce el código de autenticador',
         enterRecoveryCode: 'Por favor, introduce tu código de recuperación',
         requiredWhen2FAEnabled: 'Obligatorio cuando A2F está habilitado',
         requestNewCode: ({timeRemaining}) => `Pedir un código nuevo en <a>${timeRemaining}</a>`,
         requestNewCodeAfterErrorOccurred: 'Solicitar un nuevo código',
-        timeRemainingAnnouncement: ({timeRemaining}) => `Tiempo restante: ${timeRemaining} ${timeRemaining === 1 ? 'segundo' : 'segundos'}`,
-        timeExpiredAnnouncement: 'El tiempo ha expirado',
         error: {
             pleaseFillMagicCode: 'Por favor, introduce el código mágico.',
             incorrectMagicCode: 'Código mágico incorrecto o no válido. Inténtalo de nuevo o solicita otro código.',
@@ -2864,8 +2382,6 @@ ${amount} para ${merchant} - ${date}`,
         phoneOrEmail: 'Número de teléfono o correo electrónico',
         error: {
             invalidFormatEmailLogin: 'El correo electrónico introducido no es válido. Corrígelo e inténtalo de nuevo.',
-            agentSignInBlocked:
-                'No se puede iniciar sesión directamente en las cuentas de agente. Para usar un agente, inicia sesión con tu propia cuenta y accede a él a través de Copilot.',
         },
         cannotGetAccountDetails: 'No se pudieron cargar los detalles de tu cuenta. Por favor, intenta iniciar sesión de nuevo.',
         loginForm: 'Formulario de inicio de sesión',
@@ -2882,37 +2398,25 @@ ${amount} para ${merchant} - ${date}`,
         },
         getStarted: 'Comenzar',
         whatsYourName: '¿Cómo te llamas?',
-        peopleYouMayKnow: 'Comprueba si tu equipo está en Expensify',
-        workspaceMemberList: (employeeCount, policyOwner) => `${employeeCount} miembro${employeeCount > 1 ? 's' : ''} • ${policyOwner}`,
-        workspaceYouMayJoin: (domain: string, email: string) =>
-            `Introduce el código enviado a ${email} para comprobar si alguien de ${domain} tiene un espacio de trabajo al que puedas unirte.`,
+        peopleYouMayKnow: 'Las personas que tal vez conozcas ya están aquí. Verifica tu correo electrónico para unirte a ellos.',
+        workspaceMemberList: ({employeeCount, policyOwner}) => `${employeeCount} miembro${employeeCount > 1 ? 's' : ''} • ${policyOwner}`,
+        workspaceYouMayJoin: ({domain, email}) => `Alguien de ${domain} ya ha creado un espacio de trabajo. Por favor, introduce el código mágico enviado a ${email}.`,
         joinAWorkspace: 'Unirse a un espacio de trabajo',
-        listOfWorkspaces: 'Aquí tienes la lista de espacios de trabajo a los que puedes unirte.',
-        skipForNow: 'Omitir por ahora',
+        listOfWorkspaces: 'Aquí está la lista de espacios de trabajo a los que puedes unirte. No te preocupes, siempre puedes unirte a ellos más tarde si lo prefieres.',
         whereYouWork: '¿Dónde trabajas?',
         errorSelection: 'Selecciona una opción para continuar',
         purpose: {
             title: '¿Qué quieres hacer hoy?',
             errorContinue: 'Por favor, haz click en continuar para configurar tu cuenta',
             errorBackButton: 'Por favor, finaliza las preguntas de configuración para empezar a utilizar la aplicación',
-            [CONST.ONBOARDING_CHOICES.EMPLOYER]: 'Enviar gastos a mi empleador',
+            [CONST.ONBOARDING_CHOICES.EMPLOYER]: 'Cobrar de mi empresa',
             [CONST.ONBOARDING_CHOICES.MANAGE_TEAM]: 'Gestionar los gastos de mi equipo',
-            [CONST.ONBOARDING_CHOICES.TRACK_BUSINESS]: 'Controlar gastos de mi negocio',
-            [CONST.ONBOARDING_CHOICES.TRACK_PERSONAL]: 'Organizar mis gastos personales',
+            [CONST.ONBOARDING_CHOICES.PERSONAL_SPEND]: 'Controlar y presupuestar gastos',
+            [CONST.ONBOARDING_CHOICES.CHAT_SPLIT]: 'Chatea y divide gastos con tus amigos',
             [CONST.ONBOARDING_CHOICES.LOOKING_AROUND]: 'Algo más',
         },
-        personalTrackGoal: {
-            title: '¿Qué estás buscando organizar?',
-            [CONST.ONBOARDING_PERSONAL_TRACK_GOALS.INVESTMENT_TRACKING]: 'Costes de una propiedad de inversión',
-            [CONST.ONBOARDING_PERSONAL_TRACK_GOALS.HOUSEHOLD_TRACKING]: 'Gastos del hogar',
-            [CONST.ONBOARDING_PERSONAL_TRACK_GOALS.SIDEPROJECT_TRACKING]: 'Gastos de proyectos secundarios',
-            [CONST.ONBOARDING_PERSONAL_TRACK_GOALS.SOMETHING_ELSE]: 'Otra cosa',
-            somethingElsePlaceholder: '¿Qué estás organizando?',
-        },
         employees: {
             title: '¿Cuántos empleados tienes?',
-            [CONST.ONBOARDING_COMPANY_SIZE.MICRO_SMALL]: '1-4 empleados',
-            [CONST.ONBOARDING_COMPANY_SIZE.MICRO_MEDIUM]: '5-10 empleados',
             [CONST.ONBOARDING_COMPANY_SIZE.MICRO]: '1-10 empleados',
             [CONST.ONBOARDING_COMPANY_SIZE.SMALL]: '11-50 empleados',
             [CONST.ONBOARDING_COMPANY_SIZE.MEDIUM_SMALL]: '51-100 empleados',
@@ -2943,18 +2447,15 @@ ${amount} para ${merchant} - ${date}`,
         },
         workEmailValidation: {
             title: 'Verifica tu correo electrónico de trabajo',
-            magicCodeSent: (workEmail) => `Por favor, introduce el código mágico enviado a ${workEmail}. Debería llegar en uno o dos minutos.`,
+            magicCodeSent: ({workEmail}) => `Por favor, introduce el código mágico enviado a ${workEmail}. Debería llegar en uno o dos minutos.`,
         },
         workEmailValidationError: {
             publicEmail: 'Por favor, introduce un correo electrónico laboral válido de un dominio privado, por ejemplo: mitch@company.com',
-            sameAsSignupEmail: 'Por favor, introduce un correo electrónico diferente al que utilizaste para registrarte',
             offline: 'No pudimos añadir tu correo electrónico laboral porque parece que estás sin conexión.',
         },
         mergeBlockScreen: {
             title: 'No se pudo añadir el correo electrónico de trabajo',
-            subtitle: (workEmail) => `No pudimos añadir ${workEmail}. Por favor, inténtalo de nuevo más tarde en Configuración o chatea con Concierge para obtener ayuda.`,
-            workAccountClosedSubtitle:
-                'La cuenta de trabajo asociada a este correo electrónico está cerrada. Ponte en contacto con el administrador de tu empresa para reactivarla o regístrate con un correo electrónico diferente.',
+            subtitle: ({workEmail}) => `No pudimos añadir ${workEmail}. Por favor, inténtalo de nuevo más tarde en Configuración o chatea con Concierge para obtener ayuda.`,
         },
         tasks: {
             testDriveAdminTask: {
@@ -2986,7 +2487,7 @@ ${amount} para ${merchant} - ${date}`,
             },
             createTestDriveAdminWorkspaceTask: {
                 title: ({workspaceConfirmationLink}) => `[Crea](${workspaceConfirmationLink}) un espacio de trabajo`,
-                description: '¡Crea un espacio de trabajo y configura los ajustes con la ayuda de tu ejecutivo de cuenta!',
+                description: 'Crea un espacio de trabajo y configura los ajustes con la ayuda de tu especialista asignado.',
             },
             createWorkspaceTask: {
                 title: ({workspaceSettingsLink}) => `Crea un [espacio de trabajo](${workspaceSettingsLink})`,
@@ -3018,11 +2519,11 @@ ${amount} para ${merchant} - ${date}`,
             combinedTrackSubmitExpenseTask: {
                 title: 'Envía un gasto',
                 description: dedent(`
-                    *Envía un gasto* introduciendo un importe o escaneando un recibo.
+                    *Envía un gasto* introduciendo una cantidad o escaneando un recibo.
 
-                    1. Haz clic en el botón *+*.
+                    1. Haz clic en el botón ${CONST.CUSTOM_EMOJIS.GLOBAL_CREATE}.
                     2. Elige *Crear gasto*.
-                    3. Introduce un importe o escanea un recibo.
+                    3. Introduce una cantidad o escanea un recibo.
                     4. Añade el correo o teléfono de tu jefe.
                     5. Haz clic en *Crear*.
 
@@ -3032,11 +2533,11 @@ ${amount} para ${merchant} - ${date}`,
             adminSubmitExpenseTask: {
                 title: 'Envía un gasto',
                 description: dedent(`
-                    *Envía un gasto* introduciendo un importe o escaneando un recibo.
+                    *Envía un gasto* introduciendo una cantidad o escaneando un recibo.
 
-                    1. Haz clic en el botón *+*.
+                    1. Haz clic en el botón ${CONST.CUSTOM_EMOJIS.GLOBAL_CREATE}.
                     2. Elige *Crear gasto*.
-                    3. Introduce un importe o escanea un recibo.
+                    3. Introduce una cantidad o escanea un recibo.
                     4. Confirma los detalles.
                     5. Haz clic en *Crear*.
 
@@ -3048,9 +2549,9 @@ ${amount} para ${merchant} - ${date}`,
                 description: dedent(`
                     *Organiza un gasto* en cualquier moneda, tengas recibo o no.
 
-                    1. Haz clic en el botón *+*.
+                    1. Haz clic en el botón ${CONST.CUSTOM_EMOJIS.GLOBAL_CREATE}.
                     2. Elige *Crear gasto*.
-                    3. Introduce un importe o escanea un recibo.
+                    3. Introduce una cantidad o escanea un recibo.
                     4. Elige tu espacio *personal*.
                     5. Haz clic en *Crear*.
 
@@ -3060,6 +2561,7 @@ ${amount} para ${merchant} - ${date}`,
             addAccountingIntegrationTask: {
                 title: ({integrationName, workspaceAccountingLink}) =>
                     `Conéctate${integrationName === CONST.ONBOARDING_ACCOUNTING_MAPPING.other ? '' : ' a'} [${integrationName === CONST.ONBOARDING_ACCOUNTING_MAPPING.other ? 'tu' : ''} ${integrationName}](${workspaceAccountingLink})`,
+
                 description: ({integrationName, workspaceAccountingLink}) =>
                     dedent(`
                         Conéctate ${integrationName === CONST.ONBOARDING_ACCOUNTING_MAPPING.other ? 'tu' : 'a'} ${integrationName} para la clasificación y sincronización automática de gastos, lo que facilita el cierre de fin de mes.
@@ -3070,8 +2572,13 @@ ${amount} para ${merchant} - ${date}`,
                         4. Busca ${integrationName}.
                         5. Haz clic en *Conectar*.
 
-                        [Ir a contabilidad](${workspaceAccountingLink}).
-                    `),
+                        ${
+                            integrationName && CONST.connectionsVideoPaths[integrationName]
+                                ? `[Ir a contabilidad](${workspaceAccountingLink}).
+
+                        ![Conéctate a ${integrationName}](${CONST.CLOUDFRONT_URL}/${CONST.connectionsVideoPaths[integrationName]})`
+                                : `[Ir a contabilidad](${workspaceAccountingLink}).`
+                        }`),
             },
             connectCorporateCardTask: {
                 title: ({corporateCardLink}) => `Conecta [tu tarjeta corporativa](${corporateCardLink})`,
@@ -3149,7 +2656,7 @@ ${amount} para ${merchant} - ${date}`,
                 description: dedent(`
                     *Inicia un chat* con cualquier persona usando su correo o número.
 
-                    1. Haz clic en el botón *+*.
+                    1. Haz clic en el botón ${CONST.CUSTOM_EMOJIS.GLOBAL_CREATE}.
                     2. Elige *Iniciar chat*.
                     3. Introduce un correo o teléfono.
 
@@ -3163,7 +2670,7 @@ ${amount} para ${merchant} - ${date}`,
                 description: dedent(`
                     *Divide gastos* con una o más personas.
 
-                    1. Haz clic en el botón *+*.
+                    1. Haz clic en el botón ${CONST.CUSTOM_EMOJIS.GLOBAL_CREATE}.
                     2. Elige *Iniciar chat*.
                     3. Introduce correos o teléfonos.
                     4. Haz clic en el botón gris *+* en el chat > *Dividir gasto*.
@@ -3188,7 +2695,7 @@ ${amount} para ${merchant} - ${date}`,
                 description: dedent(`
                     Así es como puedes crear un informe:
 
-                    1. Haz clic en el botón *+*.
+                    1. Haz clic en el botón ${CONST.CUSTOM_EMOJIS.GLOBAL_CREATE}.
                     2. Elige *Crear informe*.
                     3. Haz clic en *Añadir gasto*.
                     4. Añade tu primer gasto.
@@ -3211,15 +2718,18 @@ ${amount} para ${merchant} - ${date}`,
                 isOnboardingFlow
                     ? dedent(`
                         # ¡Tu prueba gratuita ha comenzado! Vamos a configurarte.
-                        👋 Hola, soy tu ejecutivo de cuenta de Expensify. Ya he creado un espacio de trabajo para ayudarte a gestionar los recibos y gastos de tu equipo. Para aprovechar al máximo tu prueba gratuita de 30 días, solo sigue los pasos de configuración restantes a continuación.
+                        👋 Hola, soy tu **especialista asignado** de configuración de Expensify. Ya he creado un espacio de trabajo para ayudarte a gestionar los recibos y gastos de tu equipo. Para aprovechar al máximo tu prueba gratuita de 30 días, ¡solo sigue los pasos de configuración restantes que aparecen a continuación!
                     `)
                     : dedent(`
                         # ¡Tu prueba gratuita ha comenzado! Vamos a configurarte.
-                        👋 Hola, soy tu ejecutivo de cuenta de Expensify. Ahora que has creado un espacio de trabajo, aprovecha al máximo tus 30 días de prueba gratuita siguiendo los pasos a continuación.
+                        👋 Hola, soy tu **especialista asignado** de configuración de Expensify. Ahora que ya has creado un espacio de trabajo, aprovecha al máximo tu prueba gratuita de 30 días siguiendo los pasos que aparecen a continuación.
                     `),
-            onboardingTrackWorkspaceMessage: 'Para aprovechar al máximo tu prueba gratuita de 30 días, sigue los pasos restantes que aparecen a continuación:',
+            onboardingTrackWorkspaceMessage:
+                '# Vamos a configurarte\n👋 Hola, soy tu **especialista asignado** de configuración de Expensify. Ya he creado un espacio de trabajo para ayudarte a gestionar tus recibos y gastos. Para aprovechar al máximo tu prueba gratuita de 30 días, ¡solo sigue los pasos de configuración restantes que aparecen a continuación!',
             onboardingChatSplitMessage: 'Dividir cuentas con amigos es tan fácil como enviar un mensaje. Así se hace.',
             onboardingAdminMessage: 'Aprende a gestionar el espacio de tu equipo como administrador y enviar tus propios gastos.',
+            onboardingLookingAroundMessage:
+                'Expensify es conocido por gastos, viajes y gestión de tarjetas corporativas, pero hacemos mucho más. Dime qué te interesa y te ayudaré a empezar.',
             onboardingTestDriveReceiverMessage: '*¡Tienes 3 meses gratis! Empieza abajo.*',
         },
         workspace: {
@@ -3230,7 +2740,7 @@ ${amount} para ${merchant} - ${date}`,
                 descriptionTwo: 'Clasifica y etiqueta gastos',
                 descriptionThree: 'Crea y comparte informes',
             },
-            price: (price?: string) => `Pruébalo gratis durante 30 días y luego mejora por solo <strong>${price ?? '$5'}/usuario/mes</strong>.`,
+            price: 'Pruébalo gratis durante 30 días y luego mejora por solo <strong>$5/usuario/mes</strong>.',
             createWorkspace: 'Crear espacio de trabajo',
         },
         confirmWorkspace: {
@@ -3241,8 +2751,6 @@ ${amount} para ${merchant} - ${date}`,
             title: 'Invita a miembros',
             subtitle: 'Añade a tu equipo o invita a tu contador. ¡Cuantos más, mejor!',
         },
-        workEmail2FAError: 'Este inicio de sesión corresponde a una cuenta existente con la autenticación de dos factores (2FA) habilitada.',
-        singleSignOnError: 'Este inicio de sesión es una cuenta existente con SSO/SAML habilitado.',
     },
     featureTraining: {
         doNotShowAgain: 'No muestres esto otra vez',
@@ -3262,7 +2770,6 @@ ${amount} para ${merchant} - ${date}`,
         enterPhoneNumber: '¿Cuál es tu número de teléfono?',
         personalDetails: 'Datos personales',
         privateDataMessage: 'Estos detalles se utilizan para viajes y pagos. Nunca se mostrarán en tu perfil público.',
-        basicDetails: 'Datos básicos',
         legalName: 'Nombre completo',
         legalFirstName: 'Nombre legal',
         legalLastName: 'Apellidos legales',
@@ -3272,17 +2779,16 @@ ${amount} para ${merchant} - ${date}`,
             dateShouldBeAfter: (dateString) => `La fecha debe ser posterior a ${dateString}`,
             incorrectZipFormat: (zipFormat) => `Formato de código postal incorrecto.${zipFormat ? ` Formato aceptable: ${zipFormat}` : ''}`,
             hasInvalidCharacter: 'El nombre sólo puede incluir caracteres latinos',
-            cannotIncludeCommaOrSemicolon: 'El nombre no puede contener una coma o un punto y coma',
             invalidPhoneNumber: `Asegúrese de que el número de teléfono sean válidos (p. ej. ${CONST.EXAMPLE_PHONE_NUMBER})`,
         },
     },
     resendValidationForm: {
         linkHasBeenResent: 'El enlace se ha reenviado',
-        weSentYouMagicSignInLink: (login, loginType) => `Te he enviado un hiperenlace mágico para iniciar sesión a ${login}. Por favor, revisa tu ${loginType}`,
+        weSentYouMagicSignInLink: ({login, loginType}) => `Te he enviado un hiperenlace mágico para iniciar sesión a ${login}. Por favor, revisa tu ${loginType}`,
         resendLink: 'Reenviar enlace',
     },
     unlinkLoginForm: {
-        toValidateLogin: (primaryLogin, secondaryLogin) => `Para validar ${secondaryLogin}, reenvía el código mágico desde la Configuración de la cuenta de ${primaryLogin}.`,
+        toValidateLogin: ({primaryLogin, secondaryLogin}) => `Para validar ${secondaryLogin}, reenvía el código mágico desde la Configuración de la cuenta de ${primaryLogin}.`,
         noLongerHaveAccess: (primaryLogin) => `Si ya no tienes acceso a ${primaryLogin} por favor, desvincula las cuentas.`,
         unlink: 'Desvincular',
         linkSent: '¡Enlace enviado!',
@@ -3303,16 +2809,20 @@ ${amount} para ${merchant} - ${date}`,
             if (!timeData) {
                 return 'Por favor, espera un momento antes de intentarlo de nuevo.';
             }
+
             const timeParts = [];
             if (timeData.days) {
                 timeParts.push(`${timeData.days} ${timeData.days === 1 ? 'día' : 'días'}`);
             }
+
             if (timeData.hours) {
                 timeParts.push(`${timeData.hours} ${timeData.hours === 1 ? 'hora' : 'horas'}`);
             }
+
             if (timeData.minutes) {
                 timeParts.push(`${timeData.minutes} ${timeData.minutes === 1 ? 'minuto' : 'minutos'}`);
             }
+
             let timeText = '';
             if (timeParts.length === 1) {
                 timeText = timeParts.at(0) ?? '';
@@ -3321,12 +2831,12 @@ ${amount} para ${merchant} - ${date}`,
             } else if (timeParts.length === 3) {
                 timeText = `${timeParts.at(0)}, ${timeParts.at(1)}, y ${timeParts.at(2)}`;
             }
+
             return `¡Un momento! Debes esperar ${timeText} antes de intentar validar tu número nuevamente.`;
         },
     },
     welcomeSignUpForm: {
         join: 'Unirse',
-        marketingSMSConsent: 'Acepto recibir mensajes de texto de marketing de Expensify',
     },
     detailsPage: {
         localTime: 'Hora local',
@@ -3334,16 +2844,11 @@ ${amount} para ${merchant} - ${date}`,
     newChatPage: {
         startGroup: 'Crear grupo',
         addToGroup: 'Añadir al grupo',
-        addUserToGroup: (username: string) => `Añadir ${username} al grupo`,
     },
     yearPickerPage: {
         year: 'Año',
         selectYear: 'Por favor, selecciona un año',
     },
-    monthPickerPage: {
-        month: 'Mes',
-        selectMonth: 'Por favor, selecciona un mes',
-    },
     focusModeUpdateModal: {
         title: '¡Bienvenido al modo #concentración!',
         prompt: (priorityModePageUrl) =>
@@ -3382,36 +2887,41 @@ ${amount} para ${merchant} - ${date}`,
             custom: 'Personalizado',
         },
         untilTomorrow: 'Hasta mañana',
-        untilTime: (time) => {
+        untilTime: ({time}) => {
+            // Check for HH:MM AM/PM format and starts with '01:'
             if (CONST.REGEX.TIME_STARTS_01.test(time)) {
                 return `Hasta la ${time}`;
             }
+            // Check for any HH:MM AM/PM format not starting with '01:'
             if (CONST.REGEX.TIME_FORMAT.test(time)) {
                 return `Hasta las ${time}`;
             }
+            // Check for date-time format like "06-29 11:30 AM"
             if (CONST.REGEX.DATE_TIME_FORMAT.test(time)) {
                 return `Hasta el día ${time}`;
             }
+            // Default case
             return `Hasta ${time}`;
         },
         date: 'Fecha',
         time: 'Hora',
         clearAfter: 'Borrar después',
         whenClearStatus: '¿Cuándo deberíamos borrar tu estado?',
+        vacationDelegate: 'Delegado de vacaciones',
         setVacationDelegate: 'Configura un delegado de vacaciones para aprobar informes en tu nombre mientras estás fuera de la oficina.',
-        cannotSetVacationDelegate: `No puedes establecer un delegado de vacaciones porque actualmente eres el delegado de los siguientes miembros:`,
-        addVacationDelegate: 'Agregar delegado de vacaciones',
         vacationDelegateError: 'Hubo un error al actualizar tu delegado de vacaciones.',
-        asVacationDelegate: (managerName) => `como delegado de vacaciones de ${managerName}`,
-        toAsVacationDelegate: (submittedToName, vacationDelegateName) => `a ${submittedToName} como delegado de vacaciones de ${vacationDelegateName}`,
-        vacationDelegateWarning: (nameOrEmail) =>
+        asVacationDelegate: ({nameOrEmail: managerName}) => `como delegado de vacaciones de ${managerName}`,
+        toAsVacationDelegate: ({submittedToName, vacationDelegateName}) => `a ${submittedToName} como delegado de vacaciones de ${vacationDelegateName}`,
+        vacationDelegateWarning: ({nameOrEmail}) =>
             `Está asignando a ${nameOrEmail} como su delegado de vacaciones. Aún no está en todos sus espacios de trabajo. Si decide continuar, se enviará un correo electrónico a todos los administradores de sus espacios de trabajo para agregarlo.`,
     },
     stepCounter: ({step, total, text}) => {
         let result = `Paso ${step}`;
+
         if (total) {
             result = `${result} de ${total}`;
         }
+
         if (text) {
             result = `${result}: ${text}`;
         }
@@ -3436,32 +2946,20 @@ ${amount} para ${merchant} - ${date}`,
         toGetStarted: 'Conecta una cuenta bancaria para reembolsar gastos, emitir Tarjetas Expensify, y cobrar y pagar facturas todo desde un mismo lugar.',
         plaidBodyCopy: 'Ofrezca a sus empleados una forma más sencilla de pagar - y recuperar - los gastos de la empresa.',
         checkHelpLine: 'Tus números de ruta y de cuenta se pueden encontrar en un cheque de la cuenta bancaria.',
-        bankAccountPurposeTitle: '¿Qué quieres hacer con tu cuenta bancaria?',
-        getReimbursed: 'Recibir un reembolso',
-        getReimbursedDescription: 'Por tu empleador u otras personas',
-        makePayments: 'Hacer pagos',
-        makePaymentsDescription: 'Pagar gastos o emitir Tarjetas Expensify',
         hasPhoneLoginError: (contactMethodRoute) =>
             `Para añadir una cuenta bancaria verificada, <a href="${contactMethodRoute}">asegúrate de que tu nombre de usuario principal sea un correo electrónico válido</a> y vuelve a intentarlo. Puedes añadir tu número de teléfono como nombre de usuario secundario.`,
         hasBeenThrottledError: 'Se ha producido un error al intentar añadir tu cuenta bancaria. Por favor, espera unos minutos e inténtalo de nuevo.',
-        hasCurrencyError: (workspaceRoute) =>
+        hasCurrencyError: ({workspaceRoute}) =>
             `¡Ups! Parece que la moneda de tu espacio de trabajo no está configurada en USD. Para continuar, ve a <a href="${workspaceRoute}">la configuración del área de trabajo</a>, configúrala en USD e inténtalo nuevamente.`,
         bbaAdded: '¡Cuenta bancaria empresarial agregada!',
         bbaAddedDescription: 'Está lista para ser utilizada en pagos.',
-        lockedBankAccount: 'Cuenta bancaria bloqueada',
-        unlockBankAccount: 'Desbloquear cuenta bancaria',
-        youCantPayThis: `No puedes pagar este informe porque tienes una <a href="${CONST.UNLOCK_BANK_ACCOUNT_HELP_URL}">cuenta bancaria bloqueada</a>. Haz clic abajo y Concierge te ayudará con los próximos pasos para desbloquearla.`,
-        htmlUnlockMessage: (maskedAccountNumber: string) =>
-            `<h1>Cuenta Bancaria de Expensify ${maskedAccountNumber}</h1><p>Gracias por enviar una solicitud para desbloquear tu cuenta bancaria. Las solicitudes de retiro pueden ser rechazadas por fondos insuficientes o si la cuenta bancaria no ha sido habilitada para débito directo. Revisaremos tu caso y nos comunicaremos contigo si necesitamos algo más para resolver el problema.</p>`,
-        textUnlockMessage: (maskedAccountNumber: string) =>
-            `Cuenta Bancaria de Expensify ${maskedAccountNumber}\nGracias por enviar una solicitud para desbloquear tu cuenta bancaria. Las solicitudes de retiro pueden ser rechazadas por fondos insuficientes o si la cuenta bancaria no ha sido habilitada para débito directo. Revisaremos tu caso y nos comunicaremos contigo si necesitamos algo más para resolver el problema.`,
         error: {
             youNeedToSelectAnOption: 'Debes seleccionar una opción para continuar',
             noBankAccountAvailable: 'Lo sentimos, no hay ninguna cuenta bancaria disponible',
             noBankAccountSelected: 'Por favor, elige una cuenta bancaria',
             taxID: 'Por favor, introduce un número de identificación fiscal válido',
             website: 'Por favor, introduce un sitio web válido',
-            zipCode: `Formato de código postal incorrecto. Formato aceptable: ${COMMON_CONST.COUNTRY_ZIP_REGEX_DATA.US.samples}.`,
+            zipCode: `Formato de código postal incorrecto. Formato aceptable: ${CONST.COUNTRY_ZIP_REGEX_DATA.US.samples}.`,
             phoneNumber: 'Por favor, introduce un teléfono válido',
             email: 'Por favor, introduce una dirección de correo electrónico válida',
             companyName: 'Por favor, introduce un nombre comercial legal válido',
@@ -3477,7 +2975,7 @@ ${amount} para ${merchant} - ${date}`,
             routingAndAccountNumberCannotBeSame: 'Los números de ruta y de cuenta no pueden ser iguales',
             companyType: 'Por favor, selecciona un tipo de compañía válido',
             tooManyAttempts:
-                'Debido al gran número de intentos de inicio de sesión, esta opción ha sido desactivada temporalmente durante 24 horas. Por favor, inténtalo de nuevo más tarde.',
+                'Debido a la gran cantidad de intentos de inicio de sesión, esta opción ha sido desactivada temporalmente durante 24 horas. Por favor, inténtalo de nuevo más tarde.',
             address: 'Por favor, introduce una dirección válida',
             dob: 'Por favor, selecciona una fecha de nacimiento válida',
             age: 'Debe ser mayor de 18 años',
@@ -3504,11 +3002,6 @@ ${amount} para ${merchant} - ${date}`,
         confirmationStepHeader: 'Verifica tu información.',
         confirmationStepSubHeader: 'Verifica dos veces los detalles a continuación y marca la casilla de términos para confirmar.',
         toGetStarted: 'Agrega una cuenta bancaria personal para recibir reembolsos, pagar facturas o habilitar la Cartera de Expensify.',
-        updatePersonalInfo: 'Actualizar cuenta bancaria',
-        updatePersonalInfoFailure: 'No se pudo actualizar la información de la cuenta bancaria. Por favor, inténtalo de nuevo más tarde.',
-        updateSuccessTitle: '¡Cuenta bancaria actualizada!',
-        updateSuccessHeader: 'Cuenta bancaria actualizada',
-        updateSuccessMessage: 'Enhorabuena, tu cuenta bancaria está configurada y lista para recibir reembolsos.',
     },
     addPersonalBankAccountPage: {
         enterPassword: 'Escribe tu contraseña de Expensify',
@@ -3536,8 +3029,8 @@ ${amount} para ${merchant} - ${date}`,
     messages: {
         errorMessageInvalidPhone: `Por favor, introduce un número de teléfono válido sin paréntesis o guiones. Si reside fuera de Estados Unidos, por favor incluye el prefijo internacional (p. ej. ${CONST.EXAMPLE_PHONE_NUMBER}).`,
         errorMessageInvalidEmail: 'Correo electrónico inválido',
-        userIsAlreadyMember: (login, name) => `${login} ya es miembro de ${name}`,
-        userIsAlreadyAnAdmin: (login, name) => `${login} ya es administrador de ${name}`,
+        userIsAlreadyMember: ({login, name}) => `${login} ya es miembro de ${name}`,
+        userIsAlreadyAnAdmin: ({login, name}) => `${login} ya es administrador de ${name}`,
     },
     onfidoStep: {
         acceptTerms: 'Al continuar con la solicitud para activar tu Billetera Expensify, confirma que ha leído, comprende y acepta ',
@@ -3583,7 +3076,7 @@ ${amount} para ${merchant} - ${date}`,
         haveReadAndAgreePlain: 'He leído y acepto recibir divulgaciones electrónicas.',
         haveReadAndAgree: `He leído y acepto recibir <a href="${CONST.ELECTRONIC_DISCLOSURES_URL}">divulgaciones electrónicas</a>.`,
         agreeToThePlain: 'Estoy de acuerdo con el Privacidad y Acuerdo de la billetera.',
-        agreeToThe: (walletAgreementUrl) =>
+        agreeToThe: ({walletAgreementUrl}) =>
             `Estoy de acuerdo con el <a href="${CONST.OLD_DOT_PUBLIC_URLS.PRIVACY_URL}">Privacidad</a> y <a href="${walletAgreementUrl}">Acuerdo de la billetera</a>.`,
         enablePayments: 'Habilitar pagos',
         monthlyFee: 'Cuota mensual',
@@ -3595,7 +3088,7 @@ ${amount} para ${merchant} - ${date}`,
         checkTheBoxes: 'Por favor, marca las siguientes casillas.',
         agreeToTerms: 'Debes aceptar los términos y condiciones para continuar.',
         shortTermsForm: {
-            expensifyPaymentsAccount: (walletProgram) => `La Billetera Expensify es emitida por ${walletProgram}.`,
+            expensifyPaymentsAccount: ({walletProgram}) => `La Billetera Expensify es emitida por ${walletProgram}.`,
             perPurchase: 'Por compra',
             atmWithdrawal: 'Retiro en cajeros automáticos',
             cashReload: 'Recarga de efectivo',
@@ -3609,7 +3102,7 @@ ${amount} para ${merchant} - ${date}`,
             generalInfo: `Para obtener información general sobre cuentas de prepago, visite <a href="${CONST.CFPB_PREPAID_URL}">${CONST.TERMS.CFPB_PREPAID}</a>.`,
             conditionsDetails: `Encuentra detalles y condiciones para todas las tarifas y servicios visitando <a href="${CONST.FEES_URL}">${CONST.FEES_URL}</a> o llamando al +1 833-400-0904.`,
             electronicFundsWithdrawalInstant: 'Retiro electrónico de fondos (instantáneo)',
-            electronicFundsInstantFeeMin: (amount) => `(mínimo ${amount})`,
+            electronicFundsInstantFeeMin: ({amount}) => `(mínimo ${amount})`,
         },
         longTermsForm: {
             listOfAllFees: 'Una lista de todas las tarifas de la Billetera Expensify',
@@ -3630,7 +3123,7 @@ ${amount} para ${merchant} - ${date}`,
                 dedent(`
                     Hay una tarifa para transferir fondos desde tu Billetera Expensify a la tarjeta de débito vinculada utilizando la opción de transferencia instantánea. Esta transferencia generalmente se completa dentro de varios minutos. La tarifa es el ${percentage}% del importe de la transferencia (con una tarifa mínima de ${amount}).
                 `),
-            fdicInsuranceBancorp: (amount) =>
+            fdicInsuranceBancorp: ({amount}) =>
                 `Tus fondos pueden acogerse al seguro de la FDIC. Tus fondos se mantendrán o serán transferidos a ${CONST.WALLET.PROGRAM_ISSUERS.BANCORP_BANK}, una institución asegurada por la FDIC.` +
                 ` Una vez allí, tus fondos están asegurados hasta ${amount} por la FDIC en caso de que ${CONST.WALLET.PROGRAM_ISSUERS.BANCORP_BANK} quiebre, ` +
                 `si se cumplen los requisitos específicos del seguro de depósitos y tu tarjeta está registrada. Ver ${CONST.TERMS.FDIC_PREPAID} para más detalles.`,
@@ -3640,7 +3133,7 @@ ${amount} para ${merchant} - ${date}`,
             automated: 'Automatizado',
             liveAgent: 'Agente en vivo',
             instant: 'Instantáneo',
-            electronicFundsInstantFeeMin: (amount) => `Mínimo ${amount}`,
+            electronicFundsInstantFeeMin: ({amount}) => `Mínimo ${amount}`,
         },
     },
     activateStep: {
@@ -3765,7 +3258,7 @@ ${amount} para ${merchant} - ${date}`,
         whereWasTheBusinessIncorporated: '¿Dónde se constituyó la empresa?',
         whatTypeOfBusinessIsIt: '¿Qué tipo de empresa es?',
         whatsTheBusinessAnnualPayment: '¿Cuál es el volumen anual de pagos de la empresa?',
-        whatsYourExpectedAverageReimbursements: '¿Cuál es el importe medio esperado de reembolso?',
+        whatsYourExpectedAverageReimbursements: '¿Cuál es el monto promedio esperado de reembolso?',
         registrationNumber: 'Número de registro',
         taxIDEIN: (country) => {
             switch (country) {
@@ -3789,20 +3282,20 @@ ${amount} para ${merchant} - ${date}`,
         businessCategory: 'Categoría de la empresa',
         annualPaymentVolume: 'Volumen anual de pagos',
         annualPaymentVolumeInCurrency: (currencyCode) => `Volumen anual de pagos en ${currencyCode}`,
-        averageReimbursementAmount: 'Importe medio de reembolso',
-        averageReimbursementAmountInCurrency: (currencyCode) => `Importe medio de reembolso en ${currencyCode}`,
+        averageReimbursementAmount: 'Monto promedio de reembolso',
+        averageReimbursementAmountInCurrency: (currencyCode) => `Monto promedio de reembolso en ${currencyCode}`,
         selectIncorporationType: 'Seleccione tipo de constitución',
         selectBusinessCategory: 'Seleccione categoría de la empresa',
         selectAnnualPaymentVolume: 'Seleccione volumen anual de pagos',
         selectIncorporationCountry: 'Seleccione país de constitución',
         selectIncorporationState: 'Seleccione estado de constitución',
-        selectAverageReimbursement: 'Selecciona el importe medio de reembolso',
+        selectAverageReimbursement: 'Selecciona el monto promedio de reembolso',
         selectBusinessType: 'Seleccionar tipo de negocio',
         findIncorporationType: 'Buscar tipo de constitución',
         findBusinessCategory: 'Buscar categoría de la empresa',
         findAnnualPaymentVolume: 'Buscar volumen anual de pagos',
         findIncorporationState: 'Buscar estado de constitución',
-        findAverageReimbursement: 'Encuentra el importe medio de reembolso',
+        findAverageReimbursement: 'Encuentra el monto promedio de reembolso',
         findBusinessType: 'Buscar tipo de negocio',
         error: {
             registrationNumber: 'Por favor, proporciona un número de registro válido',
@@ -3925,10 +3418,6 @@ ${amount} para ${merchant} - ${date}`,
         youCanChange: 'Puede cambiar la moneda de su espacio de trabajo en su',
         findCountry: 'Encontrar país',
         selectCountry: 'Seleccione su país',
-        error: {
-            connectToWorkspace: (workspaceRoute: string) =>
-                `Esta cuenta bancaria debe vincularse a un espacio de trabajo. Ve a <a href="${workspaceRoute}">Espacios de trabajo</a>, selecciona tu espacio de trabajo y luego navega a Flujos de trabajo > Pagos > Añadir cuenta bancaria.`,
-        },
     },
     bankInfoStep: {
         whatAreYour: '¿Cuáles son los detalles de tu cuenta bancaria comercial?',
@@ -3969,7 +3458,7 @@ ${amount} para ${merchant} - ${date}`,
         pleaseUpload: 'Sube documentación adicional a continuación para ayudarnos a verificar tu identidad como director de la empresa.',
         enterSignerInfo: 'Ingrese la información del firmante',
         thisStep: 'Este paso ha sido completado',
-        isConnecting: (bankAccountLastFour, currency) =>
+        isConnecting: ({bankAccountLastFour, currency}) =>
             `está conectando una cuenta bancaria comercial en ${currency} que termina en ${bankAccountLastFour} a Expensify para pagar a los empleados en ${currency}. El siguiente paso requiere la información del firmante de un director.`,
         error: {
             emailsMustBeDifferent: 'Los correos electrónicos deben ser diferentes',
@@ -3981,7 +3470,7 @@ ${amount} para ${merchant} - ${date}`,
         regulationRequiresUs: 'La normativa requiere que verifiquemos la identidad de cualquier individuo que posea más del 25% del negocio.',
         iAmAuthorized: 'Estoy autorizado para usar la cuenta bancaria para gastos del negocio.',
         iCertify: 'Certifico que la información proporcionada es verdadera y correcta.',
-        iAcceptTheTermsAndConditions: `Acepto los <a href="https://www.corpay.com/cross-border/terms">términos y condiciones</a>.`,
+        iAcceptTheTermsAndConditions: `Acepto los <a href="https://cross-border.corpay.com/tc/">términos y condiciones</a>.`,
         iAcceptTheTermsAndConditionsAccessibility: 'Acepto los términos y condiciones.',
         accept: 'Agregar y aceptar cuenta bancaria',
         iConsentToThePrivacyNotice: 'Doy mi consentimiento para el <a href="https://payments.corpay.com/compliance">aviso de privacidad</a>.',
@@ -4013,37 +3502,6 @@ ${amount} para ${merchant} - ${date}`,
         weTake: 'Nos tomamos su seguridad en serio. Por favor, configure 2FA ahora para agregar una capa adicional de protección a su cuenta.',
         secure: 'Asegure su cuenta',
     },
-    documentsStep: {
-        beforeYouGo: 'Antes de continuar, necesitamos algunos documentos para verificar cierta información',
-        subheader: 'Verificación',
-        verificationFailed: 'La verificación falló, por lo que necesitaremos documentos adicionales para verificarte a ti y a tu empresa',
-        taxIDVerification: 'Verificación del ID fiscal',
-        taxIDVerificationDescription: dedent(`
-        Por favor, sube uno de los siguientes archivos:
-        • Carta de asignación de TIN/EIN del IRS
-        • Confirmación de solicitud de TIN/EIN del IRS (normalmente indica "Congratulations! The EIN has been successfully assigned")
-        • Carta de exención fiscal del IRS que incluya el nombre de la empresa y el EIN`),
-        nameChangeDocument: 'Documento de cambio de nombre',
-        nameChangeDocumentDescription: 'Si el nombre de tu empresa cambió desde que solicitaste el TIN/EIN, necesitamos este documento para verificar el número de ID fiscal proporcionado',
-        companyAddressVerification: 'Verificación de la dirección de la empresa',
-        companyAddressVerificationDescription: dedent(`
-        Por favor, sube uno de los siguientes archivos:
-        • Factura reciente de servicios públicos con nombre y dirección de la empresa
-        • Estado de cuenta bancario con nombre y dirección de la empresa
-        • Contrato de arrendamiento vigente con página de firmas que muestre el nombre y la dirección actual de la empresa
-        • Estado de seguro con nombre y dirección de la empresa
-        • Documento de asignación de TIN con nombre y dirección de la empresa`),
-        userAddressVerification: 'Verificación de dirección',
-        userAddressVerificationDescription: dedent(`
-        Por favor, sube uno de los siguientes archivos:
-        • Tarjeta de registro de votante
-        • Licencia de conducir
-        • Estado de cuenta bancario
-        • Factura de servicios públicos`),
-        userDOBVerification: 'Verificación de fecha de nacimiento',
-        userDOBVerificationDescription: 'Por favor, sube una identificación emitida en EE. UU.',
-        finishViaChat: 'Finalizar por chat',
-    },
     reimbursementAccountLoadingAnimation: {
         oneMoment: 'Un momento',
         explanationLine: 'Estamos verificando tu información y podrás continuar con los siguientes pasos en unos momentos.',
@@ -4178,14 +3636,14 @@ ${amount} para ${merchant} - ${date}`,
             flightSeatChanged: (airlineCode) => `Tu asignación de asiento en el vuelo ${airlineCode} ha sido modificada.`,
             flightSeatCancelled: (airlineCode) => `Tu asignación de asiento en el vuelo ${airlineCode} fue eliminada.`,
             paymentDeclined: 'El pago de tu reserva aérea ha fallado. Por favor, inténtalo de nuevo.',
-            bookingCancelledByTraveler: (type, id = '') => `Cancelaste tu reserva de ${type} ${id}.`,
-            bookingCancelledByVendor: (type, id = '') => `El proveedor canceló tu reserva de ${type} ${id}.`,
-            bookingRebooked: (type, id = '') => `Tu reserva de ${type} fue reprogramada. Nuevo número de confirmación: ${id}.`,
-            bookingUpdated: (type) => `Tu reserva de ${type} fue actualizada. Revisa los nuevos detalles en el itinerario.`,
+            bookingCancelledByTraveler: ({type, id = ''}) => `Cancelaste tu reserva de ${type} ${id}.`,
+            bookingCancelledByVendor: ({type, id = ''}) => `El proveedor canceló tu reserva de ${type} ${id}.`,
+            bookingRebooked: ({type, id = ''}) => `Tu reserva de ${type} fue reprogramada. Nuevo número de confirmación: ${id}.`,
+            bookingUpdated: ({type}) => `Tu reserva de ${type} fue actualizada. Revisa los nuevos detalles en el itinerario.`,
             railTicketRefund: (origin, destination, startDate) => `Tu billete de tren de ${origin} a ${destination} para el ${startDate} ha sido reembolsado. Se procesará un crédito.`,
             railTicketExchange: (origin, destination, startDate) => `Tu billete de tren de ${origin} a ${destination} para el ${startDate} ha sido cambiado.`,
             railTicketUpdate: (origin, destination, startDate) => `Tu billete de tren de ${origin} a ${destination} para el ${startDate} ha sido actualizado.`,
-            defaultUpdate: (type) => `Tu reserva de ${type} fue actualizada.`,
+            defaultUpdate: ({type}) => `Tu reserva de ${type} fue actualizada.`,
         },
         flightTo: 'Vuelo a',
         trainTo: 'Tren a',
@@ -4193,12 +3651,6 @@ ${amount} para ${merchant} - ${date}`,
         nightIn: 'noche en',
         nightsIn: 'noches en',
     },
-    proactiveAppReview: {
-        title: '¿Te gusta New Expensify?',
-        description: 'Dínoslo para que podamos ayudarte a mejorar tu experiencia de gestión de gastos.',
-        positiveButton: '¡Sí!',
-        negativeButton: 'No mucho',
-    },
     workspace: {
         common: {
             card: 'Tarjetas',
@@ -4208,13 +3660,13 @@ ${amount} para ${merchant} - ${date}`,
             workflows: 'Flujos de trabajo',
             workspace: 'Espacio de trabajo',
             findWorkspace: 'Encontrar espacio de trabajo',
-            findRoom: 'Encontrar sala',
             edit: 'Editar espacio de trabajo',
             enabled: 'Activada',
             disabled: 'Desactivada',
             everyone: 'Todos',
             delete: 'Eliminar espacio de trabajo',
             settings: 'Configuración',
+            reimburse: 'Reembolsos',
             categories: 'Categorías',
             tags: 'Etiquetas',
             customField1: 'Campo personalizado 1',
@@ -4222,7 +3674,6 @@ ${amount} para ${merchant} - ${date}`,
             customFieldHint: 'Añade una codificación personalizada que se aplique a todos los gastos de este miembro.',
             reports: 'Informes',
             reportFields: 'Campos de informe',
-            invoiceFields: 'Campos de factura',
             reportTitle: 'El título del informe.',
             taxes: 'Impuestos',
             bills: 'Pagar facturas',
@@ -4230,9 +3681,7 @@ ${amount} para ${merchant} - ${date}`,
             perDiem: 'Per diem',
             travel: 'Viajes',
             members: 'Miembros',
-            rooms: 'Salas',
             accounting: 'Contabilidad',
-            hr: 'HR',
             receiptPartners: 'Socios de recibos',
             rules: 'Reglas',
             plan: 'Plan',
@@ -4252,15 +3701,9 @@ ${amount} para ${merchant} - ${date}`,
             defaultNote: `Los recibos enviados a ${CONST.EMAIL.RECEIPTS} aparecerán en este espacio de trabajo.`,
             deleteConfirmation: '¿Estás seguro de que quieres eliminar este espacio de trabajo?',
             deleteWithCardsConfirmation: '¿Estás seguro de que quieres eliminar este espacio de trabajo? Se eliminarán todos los datos de las tarjetas y las tarjetas asignadas.',
-            deleteOpenExpensifyCardsError: 'Su empresa todavía tiene tarjetas Expensify activas.',
-            outstandingBalanceWarning:
-                'Tienes un saldo pendiente que debe liquidarse antes de eliminar tu último espacio de trabajo. Por favor, ve a la configuración de tu suscripción para resolver el pago.',
-            settleBalance: 'Ir a Suscripción',
             unavailable: 'Espacio de trabajo no disponible',
             memberNotFound: 'Miembro no encontrado. Para invitar a un nuevo miembro al espacio de trabajo, por favor, utiliza el botón invitar que está arriba.',
             notAuthorized: `No tienes acceso a esta página. Si estás intentando unirte a este espacio de trabajo, pide al dueño del espacio de trabajo que te añada como miembro. ¿Necesitas algo más? Comunícate con ${CONST.EMAIL.CONCIERGE}`,
-            readOnlyActionTitle: 'No tan rápido...',
-            readOnlyActionPrompt: 'Tu rol en el espacio de trabajo puede ver estos ajustes, pero no puede editarlos.',
             goToWorkspace: 'Ir al espacio de trabajo',
             duplicateWorkspace: 'Duplicar espacio de trabajo',
             duplicateWorkspacePrefix: 'Duplicar',
@@ -4268,11 +3711,8 @@ ${amount} para ${merchant} - ${date}`,
             clearFilter: 'Borrar filtro',
             workspaceName: 'Nombre del espacio de trabajo',
             workspaceOwner: 'Dueño',
-            keepMeAsAdmin: 'Mantenerme como administrador',
             workspaceType: 'Tipo de espacio de trabajo',
             workspaceAvatar: 'Espacio de trabajo avatar',
-            clientID: 'ID del cliente',
-            clientIDInputHint: 'Ingresa el identificador único del cliente',
             mustBeOnlineToViewMembers: 'Debes estar en línea para poder ver los miembros de este espacio de trabajo.',
             moreFeatures: 'Más características',
             requested: 'Solicitado',
@@ -4291,7 +3731,7 @@ ${amount} para ${merchant} - ${date}`,
             appliedOnExport: 'No se importa en Expensify, se aplica en la exportación',
             shareNote: {
                 header: 'Comparte tu espacio de trabajo con otros miembros',
-                content: (adminsRoomLink) =>
+                content: ({adminsRoomLink}) =>
                     `Comparte este código QR o copia el enlace de abajo para facilitar que los miembros soliciten acceso a tu espacio de trabajo. Todas las solicitudes para unirse al espacio de trabajo aparecerán en la sala <a href="${adminsRoomLink}">${CONST.REPORT.WORKSPACE_CHAT_ROOMS.ADMINS}</a> para tu revisión.`,
             },
             connectTo: ({connectionName}) => `Conéctate a ${CONST.POLICY.CONNECTIONS.NAME_USER_FRIENDLY[connectionName]}`,
@@ -4312,20 +3752,12 @@ ${amount} para ${merchant} - ${date}`,
                 [CONST.POLICY.REIMBURSEMENT_CHOICES.REIMBURSEMENT_NO]: 'Ninguno',
                 [CONST.POLICY.REIMBURSEMENT_CHOICES.REIMBURSEMENT_MANUAL]: 'Indirecto',
             },
-            roleName: (role?: string) => {
+            roleName: ({role} = {}) => {
                 switch (role) {
                     case CONST.POLICY.ROLE.ADMIN:
-                        return 'Administrador del espacio de trabajo';
+                        return 'Administrador';
                     case CONST.POLICY.ROLE.AUDITOR:
                         return 'Auditor';
-                    case CONST.POLICY.ROLE.EDITOR:
-                        return 'Editor';
-                    case CONST.POLICY.ROLE.CARD_ADMIN:
-                        return 'Administrador de tarjeta';
-                    case CONST.POLICY.ROLE.PEOPLE_ADMIN:
-                        return 'Administrador de personas';
-                    case CONST.POLICY.ROLE.PAYMENTS_ADMIN:
-                        return 'Administrador de pagos';
                     case CONST.POLICY.ROLE.USER:
                         return 'Miembro';
                     default:
@@ -4360,17 +3792,6 @@ ${amount} para ${merchant} - ${date}`,
             viewTransactions: 'Ver transacciones',
             policyExpenseChatName: (displayName) => `${displayName}'s gastos`,
             deepDiveExpensifyCard: `<muted-text-label>Las transacciones de la Tarjeta Expensify se exportan automáticamente a una "Cuenta de Responsabilidad de la Tarjeta Expensify" creada con <a href="${CONST.DEEP_DIVE_EXPENSIFY_CARD}">nuestra integración</a>.</muted-text-label>`,
-            travelInvoicing: 'Exportar gastos de facturación de viajes como',
-            travelInvoicingVendor: 'Proveedor de viajes',
-            travelInvoicingPayableAccount: 'Cuenta por pagar de viajes',
-            findDomain: 'Buscar dominio',
-            cardAdminAlternateText: 'Gestiona tarjetas del espacio de trabajo.',
-            peopleAdminAlternateText: 'Gestiona miembros y flujos de aprobación.',
-            paymentsAdminAlternateText: 'Gestiona los pagos del flujo de trabajo.',
-        },
-        createdForClient: {
-            title: '¡Has creado un espacio de trabajo para tu cliente!',
-            description: 'Excelentes noticias 🎉. Contáctanos si necesitan ayuda con la configuración.',
         },
         receiptPartners: {
             uber: {
@@ -4406,7 +3827,7 @@ ${amount} para ${merchant} - ${date}`,
         },
         perDiem: {
             subtitle: `<muted-text>Establece las tasas per diem para controlar los gastos diarios de los empleados. <a href="${CONST.DEEP_DIVE_PER_DIEM}">Más información</a>.</muted-text>`,
-            amount: 'Importe',
+            amount: 'Cantidad',
             deleteRates: () => ({
                 one: 'Eliminar tasa',
                 other: 'Eliminar tasas',
@@ -4436,7 +3857,7 @@ ${amount} para ${merchant} - ${date}`,
             exportExpensifyCard: 'Exportar las transacciones de la tarjeta Expensify como',
             account: 'Cuenta',
             accountDescription: 'Elige dónde contabilizar los asientos contables.',
-            accountsPayable: 'Cuentas por Pagar',
+            accountsPayable: 'Cuentas por pagar',
             accountsPayableDescription: 'Elige dónde crear las facturas de proveedores.',
             bankAccount: 'Cuenta bancaria',
             notConfigured: 'No configurado',
@@ -4472,16 +3893,19 @@ ${amount} para ${merchant} - ${date}`,
                 [CONST.QUICKBOOKS_DESKTOP_REIMBURSABLE_ACCOUNT_TYPE.VENDOR_BILL]: 'Factura del proveedor',
                 [CONST.QUICKBOOKS_DESKTOP_REIMBURSABLE_ACCOUNT_TYPE.JOURNAL_ENTRY]: 'Asiento contable',
                 [CONST.QUICKBOOKS_DESKTOP_REIMBURSABLE_ACCOUNT_TYPE.CHECK]: 'Cheque',
+
                 [`${CONST.QUICKBOOKS_DESKTOP_NON_REIMBURSABLE_EXPORT_ACCOUNT_TYPE.CHECK}Description`]:
                     'Crearemos un cheque desglosado para cada informe de Expensify y lo enviaremos desde la cuenta bancaria a continuación.',
                 [`${CONST.QUICKBOOKS_DESKTOP_NON_REIMBURSABLE_EXPORT_ACCOUNT_TYPE.CREDIT_CARD}Description`]:
                     "Automáticamente relacionaremos el nombre del comerciante de la transacción con tarjeta de crédito con cualquier proveedor correspondiente en QuickBooks. Si no existen proveedores, crearemos un proveedor asociado 'Credit Card Misc.'.",
                 [`${CONST.QUICKBOOKS_DESKTOP_REIMBURSABLE_ACCOUNT_TYPE.VENDOR_BILL}Description`]:
                     'Crearemos una factura de proveedor desglosada para cada informe de Expensify con la fecha del último gasto, y la añadiremos a la cuenta a continuación. Si este periodo está cerrado, lo contabilizaremos el 1º del siguiente periodo abierto.',
+
                 [`${CONST.QUICKBOOKS_DESKTOP_NON_REIMBURSABLE_EXPORT_ACCOUNT_TYPE.CREDIT_CARD}AccountDescription`]: 'Elige dónde exportar las transacciones con tarjeta de crédito.',
                 [`${CONST.QUICKBOOKS_DESKTOP_REIMBURSABLE_ACCOUNT_TYPE.VENDOR_BILL}AccountDescription`]:
                     'Selecciona el proveedor que se aplicará a todas las transacciones con tarjeta de crédito.',
                 [`${CONST.QUICKBOOKS_DESKTOP_REIMBURSABLE_ACCOUNT_TYPE.CHECK}AccountDescription`]: 'Elige desde dónde enviar los cheques.',
+
                 [`${CONST.QUICKBOOKS_DESKTOP_REIMBURSABLE_ACCOUNT_TYPE.VENDOR_BILL}Error`]:
                     'Las facturas de proveedores no están disponibles cuando las ubicaciones están habilitadas. Por favor, selecciona otra opción de exportación.',
                 [`${CONST.QUICKBOOKS_DESKTOP_REIMBURSABLE_ACCOUNT_TYPE.CHECK}Error`]:
@@ -4574,23 +3998,22 @@ ${amount} para ${merchant} - ${date}`,
                     },
                 },
             },
-            receivable: 'Cuentas por cobrar',
-            archive: 'Archivo de cuentas por cobrar',
+            receivable: 'Cuentas por cobrar', // This is an account name that will come directly from QBO, so I don't know why we need a translation for it. It should take whatever the name of the account is in QBO. Leaving this note for CS.
+            archive: 'Archivo de cuentas por cobrar', // This is an account name that will come directly from QBO, so I don't know why we need a translation for it. It should take whatever the name of the account is in QBO. Leaving this note for CS.
             exportInvoicesDescription: 'Usa esta cuenta al exportar facturas a QuickBooks Online.',
             exportCompanyCardsDescription: 'Establece cómo se exportan las compras con tarjeta de empresa a QuickBooks Online.',
             account: 'Cuenta',
             accountDescription: 'Elige dónde contabilizar los asientos contables.',
             vendor: 'Proveedor',
             defaultVendorDescription: 'Establece un proveedor predeterminado que se aplicará a todas las transacciones con tarjeta de crédito al momento de exportarlas.',
-            accountsPayable: 'Cuentas por Pagar',
+            accountsPayable: 'Cuentas por pagar',
             accountsPayableDescription: 'Elige dónde crear las facturas de proveedores.',
             bankAccount: 'Cuenta bancaria',
             notConfigured: 'No configurado',
             bankAccountDescription: 'Elige desde dónde enviar los cheques.',
             creditCardAccount: 'Cuenta de la tarjeta de crédito',
-            travelInvoicingDescription: 'Los gastos de viaje se exportarán como cargos de tarjeta de crédito a la cuenta de QuickBooks Online especificada a continuación.',
             companyCardsLocationEnabledDescription:
-                'QuickBooks Online no admite ubicaciones en las exportaciones de facturas de proveedor cuando las ubicaciones se importan como etiquetas. Como tienes ubicaciones importadas como etiquetas en tu espacio de trabajo, esta opción de exportación no está disponible.',
+                'QuickBooks Online no permite lugares en las exportaciones de facturas de proveedores. Como tienes activadas los lugares en tu espacio de trabajo, esta opción de exportación no está disponible.',
             exportOutOfPocketExpensesDescription: 'Establezca cómo se exportan los gastos de bolsillo a QuickBooks Online.',
             exportCheckDescription: 'Crearemos un cheque desglosado para cada informe de Expensify y lo enviaremos desde la cuenta bancaria a continuación.',
             exportJournalEntryDescription: 'Crearemos una entrada contable desglosada para cada informe de Expensify y lo contabilizaremos en la cuenta a continuación.',
@@ -4599,6 +4022,7 @@ ${amount} para ${merchant} - ${date}`,
             outOfPocketTaxEnabledDescription:
                 'QuickBooks Online no permite impuestos en las exportaciones de entradas a los asientos contables. Como tienes los impuestos activados en tu espacio de trabajo, esta opción de exportación no está disponible.',
             outOfPocketTaxEnabledError: 'La anotacion en el diario no está disponible cuando los impuestos están activados. Por favor, selecciona otra opción de exportación diferente.',
+
             advancedConfig: {
                 autoSyncDescription: 'Expensify se sincronizará automáticamente con QuickBooks Online todos los días.',
                 inviteEmployees: 'Invitar empleados',
@@ -4618,15 +4042,18 @@ ${amount} para ${merchant} - ${date}`,
                 [CONST.QUICKBOOKS_REIMBURSABLE_ACCOUNT_TYPE.VENDOR_BILL]: 'Factura del proveedor',
                 [CONST.QUICKBOOKS_REIMBURSABLE_ACCOUNT_TYPE.JOURNAL_ENTRY]: 'Asiento contable',
                 [CONST.QUICKBOOKS_REIMBURSABLE_ACCOUNT_TYPE.CHECK]: 'Cheque',
+
                 [`${CONST.QUICKBOOKS_NON_REIMBURSABLE_EXPORT_ACCOUNT_TYPE.DEBIT_CARD}Description`]:
                     "Automáticamente relacionaremos el nombre del comerciante de la transacción con tarjeta de débito con cualquier proveedor correspondiente en QuickBooks. Si no existen proveedores, crearemos un proveedor asociado 'Debit Card Misc.'.",
                 [`${CONST.QUICKBOOKS_NON_REIMBURSABLE_EXPORT_ACCOUNT_TYPE.CREDIT_CARD}Description`]:
                     "Automáticamente relacionaremos el nombre del comerciante de la transacción con tarjeta de crédito con cualquier proveedor correspondiente en QuickBooks. Si no existen proveedores, crearemos un proveedor asociado 'Credit Card Misc.'.",
                 [`${CONST.QUICKBOOKS_REIMBURSABLE_ACCOUNT_TYPE.VENDOR_BILL}Description`]:
                     'Crearemos una factura de proveedor desglosada para cada informe de Expensify con la fecha del último gasto, y la añadiremos a la cuenta a continuación. Si este periodo está cerrado, lo contabilizaremos en el día 1 del siguiente periodo abierto.',
+
                 [`${CONST.QUICKBOOKS_NON_REIMBURSABLE_EXPORT_ACCOUNT_TYPE.DEBIT_CARD}AccountDescription`]: 'Elige dónde exportar las transacciones con tarjeta de débito.',
                 [`${CONST.QUICKBOOKS_NON_REIMBURSABLE_EXPORT_ACCOUNT_TYPE.CREDIT_CARD}AccountDescription`]: 'Elige dónde exportar las transacciones con tarjeta de crédito.',
                 [`${CONST.QUICKBOOKS_REIMBURSABLE_ACCOUNT_TYPE.VENDOR_BILL}AccountDescription`]: 'Selecciona el proveedor que se aplicará a todas las transacciones con tarjeta de crédito.',
+
                 [`${CONST.QUICKBOOKS_REIMBURSABLE_ACCOUNT_TYPE.VENDOR_BILL}Error`]:
                     'Las facturas de proveedores no están disponibles cuando las ubicaciones están habilitadas. Por favor, selecciona otra opción de exportación diferente.',
                 [`${CONST.QUICKBOOKS_REIMBURSABLE_ACCOUNT_TYPE.CHECK}Error`]:
@@ -4690,7 +4117,6 @@ ${amount} para ${merchant} - ${date}`,
             exportDeepDiveCompanyCard:
                 'Cada gasto exportado se contabiliza como una transacción bancaria en la cuenta bancaria de Xero que selecciones a continuación. Las fechas de las transacciones coincidirán con las fechas de el extracto bancario.',
             bankTransactions: 'Transacciones bancarias',
-            travelInvoicingDescription: 'Los gastos de viaje se exportarán como transacciones bancarias a la cuenta de Xero especificada a continuación.',
             xeroBankAccount: 'Cuenta bancaria de Xero',
             xeroBankAccountDescription: 'Elige dónde se contabilizarán los gastos como transacciones bancarias.',
             exportExpensesDescription: 'Los informes se exportarán como una factura de compra utilizando la fecha y el estado que seleccione a continuación',
@@ -4750,6 +4176,7 @@ ${amount} para ${merchant} - ${date}`,
                 },
             },
         },
+
         sageIntacct: {
             preferredExporter: 'Exportador preferido',
             taxSolution: 'Solución fiscal',
@@ -4786,7 +4213,6 @@ ${amount} para ${merchant} - ${date}`,
                     [CONST.SAGE_INTACCT_NON_REIMBURSABLE_EXPENSE_TYPE.VENDOR_BILL]: 'Facturas de proveedores',
                 },
             },
-            travelInvoicingDescription: 'Los gastos de viaje se exportarán como cargos de tarjeta de crédito a la cuenta de Sage Intacct especificada a continuación.',
             creditCardAccount: 'Cuenta de tarjeta de crédito',
             defaultVendor: 'Proveedor por defecto',
             defaultVendorDescription: (isReimbursable) =>
@@ -4819,68 +4245,6 @@ ${amount} para ${merchant} - ${date}`,
                 },
             },
         },
-        certinia: {
-            title: 'Certinia',
-            titleFFA: 'Certinia (FFA)',
-            autoSyncDescription: 'Expensify se sincronizará automáticamente con Certinia cada día.',
-            syncReimbursedReportsDescription:
-                'Con esta opción habilitada, cada vez que se pague una factura por pagar en FFA, el informe de Expensify relacionado se marcará automáticamente como reembolsado.',
-            exportDescription: 'Configura cómo se exportan los datos de Expensify a Certinia.',
-            payableInvoices: 'Facturas por pagar',
-            exportStatus: {
-                label: 'Estado de factura por pagar',
-                values: {
-                    [CONST.CERTINIA_EXPORT_STATUS.APPROVED]: 'Completar',
-                    [CONST.CERTINIA_EXPORT_STATUS.IN_PROGRESS]: 'En curso',
-                    [CONST.CERTINIA_EXPORT_STATUS.SUBMITTED]: 'Enviado',
-                },
-            },
-            exportDate: {
-                label: 'Fecha de factura pagadera',
-                values: {
-                    [CONST.CERTINIA_EXPORT_DATE.LAST_EXPENSE]: 'Fecha del último gasto',
-                    [CONST.CERTINIA_EXPORT_DATE.REPORT_SUBMITTED]: 'Fecha de envío del informe',
-                    [CONST.CERTINIA_EXPORT_DATE.REPORT_EXPORTED]: 'Fecha de exportación',
-                },
-            },
-            exportReimbursable: {
-                label: 'Exportar gastos reembolsables como',
-                helperText: 'Los gastos marcados como reembolsables se exportarán como facturas por pagar a nombre de la persona empleada.',
-            },
-            exportNonReimbursable: {label: 'Exportar gastos no reembolsables como'},
-            noVendorsFound: 'No se encontraron proveedores',
-            noVendorsFoundDescription: 'Vuelve a sincronizar la conexión después de añadir los proveedores en Certinia.',
-            prerequisites: {
-                title: 'Antes de conectarte',
-                installBundle: 'Para conexiones FFA',
-                installBundleDescription: ({href, version}: {href: string; version: string}) =>
-                    `Instala el paquete de Expensify en Salesforce haciendo clic en este enlace: <a href="${href}">Instalar FFA Expensify Bundle (Versión ${version})</a>`,
-                installBundleConfirm: 'He instalado el paquete',
-                setupContacts: 'Configura usuario y contactos',
-                setupContactsBullet1:
-                    'Crea tanto un usuario como un contacto para ti si aún no existen en Certinia, asegurándote de que el correo electrónico coincida con tu correo principal en Expensify.',
-                setupContactsBullet2:
-                    'Crea contactos para cada empleado que vaya a enviar informes de gastos y para cada aprobador de informes. Asegúrate de que la dirección de correo electrónico de cada contacto corresponda con la dirección de correo electrónico de la cuenta de Expensify del empleado.',
-                setupContactsBullet3: 'Configura controles de permisos para tu usuario para cada contacto/recurso.',
-                setupContactsConfirm: 'He configurado el usuario y los contactos',
-                oauth: 'Inicia sesión con Salesforce',
-                oauthDescription: 'Para terminar la configuración, tendrás que iniciar sesión a través de Salesforce y Certinia.\n\nUsa el botón de abajo para continuar.',
-                connectButton: 'Conectar con Certinia',
-            },
-            import: {
-                chartOfAccounts: 'Plan de cuentas',
-                chartOfAccountsDescription: 'El plan de cuentas se importa en Expensify como categorías.',
-                dimensionMapping: ({n}: {n: number}) => `Dimensión ${n}`,
-                dimensions: {dimension1: 'Dimensión 1', dimension2: 'Dimensión 2', dimension3: 'Dimensión 3', dimension4: 'Dimensión 4'},
-                doNotMap: 'No asignar',
-                doNotMapSubtitle: 'Usar recurso de empleado por defecto',
-                mappingTypes: {
-                    [CONST.CERTINIA_MAPPING_VALUE.DEFAULT]: 'No asignar',
-                    [CONST.CERTINIA_MAPPING_VALUE.TAG]: 'Importado como etiquetas',
-                    [CONST.CERTINIA_MAPPING_VALUE.REPORT_FIELD]: 'Importado como campos de informe',
-                },
-            },
-        },
         netsuite: {
             subsidiary: 'Subsidiaria',
             subsidiarySelectDescription: 'Elige la subsidiaria de NetSuite de la que deseas importar datos.',
@@ -4895,8 +4259,8 @@ ${amount} para ${merchant} - ${date}`,
             journalPostingPreference: {
                 label: 'Preferencia de registro de asientos contables',
                 values: {
-                    [CONST.NETSUITE_JOURNAL_POSTING_PREFERENCE.JOURNALS_POSTING_INDIVIDUAL_LINE]: 'Entrada única para cada gasto individual',
-                    [CONST.NETSUITE_JOURNAL_POSTING_PREFERENCE.JOURNALS_POSTING_TOTAL_LINE]: 'Entrada única y detallada para cada informe',
+                    [CONST.NETSUITE_JOURNAL_POSTING_PREFERENCE.JOURNALS_POSTING_INDIVIDUAL_LINE]: 'Entrada única y detallada para cada informe',
+                    [CONST.NETSUITE_JOURNAL_POSTING_PREFERENCE.JOURNALS_POSTING_TOTAL_LINE]: 'Entrada única para cada gasto individual',
                 },
             },
             invoiceItem: {
@@ -4962,7 +4326,6 @@ ${amount} para ${merchant} - ${date}`,
 
                             Si deseas establecer un proveedor específico para cada tarjeta, ve a *Configuraciones > Dominios > Tarjetas de Empresa*.
                         `),
-                        travelDescription: 'Los gastos de viaje se exportarán como asientos contables a la cuenta de NetSuite especificada a continuación.',
                     },
                 },
                 expenseReportDestinationConfirmDescription:
@@ -5106,7 +4469,7 @@ ${amount} para ${merchant} - ${date}`,
                 importCustomFields: {
                     chooseOptionBelow: 'Elija una de las opciones siguientes:',
                     label: (importedTypes) => `Importados como ${importedTypes.join(' y ')}`,
-                    requiredFieldError: (fieldName) => `Por favor, introduzca el ${fieldName}`,
+                    requiredFieldError: ({fieldName}) => `Por favor, introduzca el ${fieldName}`,
                     customSegments: {
                         title: 'Segmentos/registros personalizados',
                         addText: 'Añadir segmento/registro personalizado',
@@ -5147,7 +4510,7 @@ ${amount} para ${merchant} - ${date}`,
                             customRecordMappingTitle: '¿Cómo debería mostrarse este registro de segmento personalizado en Expensify?',
                         },
                         errors: {
-                            uniqueFieldError: (fieldName) => `Ya existe un segmento/registro personalizado con este ${fieldName?.toLowerCase()}`,
+                            uniqueFieldError: ({fieldName}) => `Ya existe un segmento/registro personalizado con este ${fieldName?.toLowerCase()}`,
                         },
                     },
                     customLists: {
@@ -5208,7 +4571,7 @@ ${amount} para ${merchant} - ${date}`,
             employeeDefaultDescription: 'El departamento por defecto del empleado se aplicará a sus gastos en Sage Intacct si existe.',
             displayedAsTagDescription: 'Se podrá seleccionar el departamento para cada gasto individual en el informe de un empleado.',
             displayedAsReportFieldDescription: 'La selección de departamento se aplicará a todos los gastos que figuren en el informe de un empleado.',
-            toggleImportTitle: (mappingTitle) => `Elija cómo gestionar Sage Intacct <strong>${mappingTitle}</strong> en Expensify.`,
+            toggleImportTitle: ({mappingTitle}) => `Elija cómo gestionar Sage Intacct <strong>${mappingTitle}</strong> en Expensify.`,
             expenseTypes: 'Tipos de gastos',
             expenseTypesDescription: 'Los tipos de gastos de Sage Intacct se importan a Expensify como categorías.',
             accountTypesDescription: 'Su plan de cuentas de Sage Intacct se importará a Expensify como categorías.',
@@ -5248,14 +4611,10 @@ ${amount} para ${merchant} - ${date}`,
             free: 'Gratis',
             control: 'Controlar',
             collect: 'Recopilar',
-            submit: 'Enviar',
         },
         companyCards: {
             addCards: 'Añadir tarjetas',
             selectCards: 'Seleccionar tarjetas',
-            fromOtherWorkspaces: 'De otros espacios de trabajo',
-            addWorkEmail: 'Añade tu correo electrónico de trabajo',
-            addWorkEmailDescription: 'Por favor, añade tu correo de trabajo para poder usar los feeds existentes de otros espacios de trabajo.',
             error: {
                 workspaceFeedsCouldNotBeLoadedTitle: 'Error al cargar las fuentes de tarjetas del espacio de trabajo',
                 workspaceFeedsCouldNotBeLoadedMessage:
@@ -5266,12 +4625,6 @@ ${amount} para ${merchant} - ${date}`,
             },
             addNewCard: {
                 other: 'Otros',
-                fileImport: 'Importar transacciones desde un archivo',
-                fileImportDescription: 'Una opción manual si tu banco no puede enviar un feed.',
-                createFileFeedHelpText: `<muted-text>Siga este <a href="${CONST.COMPANY_CARDS_CREATE_FILE_FEED_HELP_URL}">guía de ayuda</a> para importar las transacciones de su tarjeta de empresa!</muted-text>`,
-                companyCardLayoutName: 'Nombre del layout de la tarjeta de empresa',
-                cardLayoutNameRequired: 'El nombre del layout de la tarjeta de empresa es requerido',
-                useAdvancedFields: 'Usar campos avanzados (no recomendado)',
                 cardProviders: {
                     gl1025: 'Tarjetas de empresa American Express',
                     cdf: 'Tarjetas comerciales Mastercard',
@@ -5334,25 +4687,6 @@ ${amount} para ${merchant} - ${date}`,
                     confirmText: 'Informar problema',
                     cancelText: 'Saltar',
                 },
-                csvColumns: {
-                    cardNumber: 'Número de la tarjeta',
-                    postedDate: 'Fecha',
-                    merchant: 'Comercio',
-                    amount: 'Importe',
-                    currency: 'Moneda',
-                    ignore: 'Ignorar',
-                    originalTransactionDate: 'Fecha original de la transacción',
-                    originalAmount: 'Importe original',
-                    originalCurrency: 'Moneda original',
-                    comment: 'Comentario',
-                    category: 'Categoría',
-                    tag: 'Etiqueta',
-                },
-                csvErrors: {
-                    requiredColumns: (missingColumns: string) => `Por favor, asigna una columna a cada uno de los atributos: ${missingColumns}.`,
-                    duplicateColumns: (duplicateColumn: string) => `¡Ups! Has asignado un solo campo ("${duplicateColumn}") a múltiples columnas. Por favor, revisa y vuelve a intentarlo.`,
-                },
-                duplicateFeedModal: {title: 'Feed de tarjeta ya conectado', prompt: 'No puedes añadir el mismo flujo de tarjeta al mismo espacio de trabajo dos veces.'},
             },
             statementCloseDate: {
                 [CONST.COMPANY_CARDS.STATEMENT_CLOSE_DATE.LAST_DAY_OF_MONTH]: 'Último día del mes',
@@ -5401,14 +4735,9 @@ ${amount} para ${merchant} - ${date}`,
                 cardDisplayName: 'Nombre de la tarjeta',
                 currency: 'Moneda',
                 transactionsAreReimbursable: 'Las transacciones son reembolsables',
-                flipAmountSign: 'Invertir el signo del importe',
+                flipAmountSign: 'Invertir el signo del monto',
                 importButton: 'Importar transacciones',
             },
-            deletedCard: 'Tarjeta eliminada',
-            assignNewCards: {
-                title: 'Asignar nuevas tarjetas',
-                description: 'Obtén las últimas tarjetas para asignar desde tu banco',
-            },
         },
         expensifyCard: {
             issueAndManageCards: 'Emitir y gestionar Tarjetas Expensify',
@@ -5420,10 +4749,6 @@ ${amount} para ${merchant} - ${date}`,
             euUkDisclaimer:
                 'Las tarjetas proporcionadas a residentes del EEE son emitidas por Transact Payments Malta Limited, y las proporcionadas a residentes del Reino Unido son emitidas por Transact Payments Limited con licencia de Visa Europe Limited. Transact Payments Malta Limited está debidamente autorizada y regulada por la Autoridad de Servicios Financieros de Malta como Institución Financiera, de conformidad con la Ley de Instituciones Financieras de 1994. Número de registro: C 91879. Transact Payments Limited está autorizada y regulada por la Comisión de Servicios Financieros de Gibraltar.',
             issueCard: 'Emitir tarjeta',
-            exportAsCSV: 'Exportar como CSV',
-            csvColumnType: 'Tipo',
-            csvColumnLimitType: 'Tipo de límite',
-            csvColumnLimit: 'Límite',
             findCard: 'Encontrar tarjeta',
             newCard: 'Nueva tarjeta',
             name: 'Nombre',
@@ -5432,7 +4757,7 @@ ${amount} para ${merchant} - ${date}`,
             currentBalance: 'Saldo actual',
             currentBalanceDescription:
                 'El saldo actual es la suma de todas las transacciones contabilizadas con la Tarjeta Expensify que se han producido desde la última fecha de liquidación.',
-            balanceWillBeSettledOn: (settlementDate) => `El saldo se liquidará el ${settlementDate}.`,
+            balanceWillBeSettledOn: ({settlementDate}) => `El saldo se liquidará el ${settlementDate}.`,
             settleBalance: 'Liquidar saldo',
             cardLimit: 'Límite de la tarjeta',
             remainingLimit: 'Límite restante',
@@ -5449,19 +4774,18 @@ ${amount} para ${merchant} - ${date}`,
             addNewBankAccount: 'Añadir nueva cuenta bancaria',
             settlementAccount: 'Cuenta de liquidación',
             settlementAccountDescription: 'Elige una cuenta para pagar el saldo de tu Tarjeta Expensify.',
-            settlementAccountInfo: (reconciliationAccountSettingsLink, accountNumber) =>
+            settlementAccountInfo: ({reconciliationAccountSettingsLink, accountNumber}) =>
                 `Asegúrate de que esta cuenta coincide con tu <a href="${reconciliationAccountSettingsLink}">Cuenta de conciliación</a> (${accountNumber}) para que Reconciliación Continua funcione correctamente.`,
             settlementFrequency: 'Frecuencia de liquidación',
             settlementFrequencyDescription: 'Elige con qué frecuencia pagarás el saldo de tu Tarjeta Expensify',
             settlementFrequencyInfo:
                 'Si deseas cambiar a la liquidación mensual, deberás conectar tu cuenta bancaria a través de Plaid y tener un historial de saldo positivo en los últimos 90 días.',
-            applyCashbackToBill: 'Aplicar reembolso a mi factura de Expensify',
-            applyCashbackToBillDescription: 'El reembolso de la Tarjeta Expensify se utilizará para el pago de tu factura de Expensify.',
             frequency: {
                 daily: 'Cada día',
                 monthly: 'Mensual',
             },
             cardDetails: 'Datos de la tarjeta',
+            cardPending: ({name}: {name: string}) => `La tarjeta está pendiente y se emitirá una vez que la cuenta de ${name} haya sido validada.`,
             virtual: 'Virtual',
             physical: 'Física',
             deactivate: 'Desactivar tarjeta',
@@ -5513,10 +4837,10 @@ ${amount} para ${merchant} - ${date}`,
             needCategoryForExportToIntegration: (connectionName) => `Todos los gastos deben estar categorizados para poder exportar a ${connectionName}.`,
             subtitle: 'Obtén una visión general de dónde te gastas el dinero. Utiliza las categorías predeterminadas o añade las tuyas propias.',
             emptyCategories: {
-                title: 'Todavía no hay categorías',
+                title: 'No has creado ninguna categoría',
                 subtitle: 'Añade una categoría para organizar tu gasto.',
-                subtitleWithAccounting: (accountingPageURL, canManage = true) =>
-                    `<muted-text><centered-text>Tus categorías se están importando actualmente desde una conexión de contabilidad.${canManage ? ` Dirígete a <a href="${accountingPageURL}">contabilidad</a> para hacer cualquier cambio.` : ''}</centered-text></muted-text>`,
+                subtitleWithAccounting: (accountingPageURL) =>
+                    `<muted-text><centered-text>Tus categorías se están importando actualmente desde una conexión de contabilidad. Dirígete a <a href="${accountingPageURL}">contabilidad</a> para hacer cualquier cambio.</centered-text></muted-text>`,
             },
             updateFailureMessage: 'Se ha producido un error al intentar eliminar la categoría. Por favor, inténtalo más tarde.',
             createFailureMessage: 'Se ha producido un error al intentar crear la categoría. Por favor, inténtalo más tarde.',
@@ -5571,9 +4895,6 @@ ${amount} para ${merchant} - ${date}`,
             travel: {
                 title: 'Viajes',
                 subtitle: 'Reserva, gestiona y concilia todos tus viajes de negocios.',
-                disableTravelTitle: 'Desactiva primero la facturación de viajes',
-                disableTravelPrompt: 'La facturación de viajes está habilitada para este espacio de trabajo. Desactívala antes de poder deshabilitar Viajes.',
-                disableTravelButton: 'Ve a la configuración de Viajes',
                 getStarted: {
                     title: 'Comienza con Expensify Travel',
                     subtitle: 'Solo necesitamos algunos datos más sobre tu empresa y estarás listo para despegar.',
@@ -5585,15 +4906,9 @@ ${amount} para ${merchant} - ${date}`,
                     ctaText: 'Solicitud enviada',
                 },
                 bookOrManageYourTrip: {
-                    title: 'Reserva de viajes',
-                    subtitle: '¡Felicidades! Ya puedes reservar y gestionar viajes en este espacio de trabajo.',
-                    ctaText: 'Gestionar viajes',
-                },
-                settings: {
-                    autoAddTripName: {
-                        title: 'Añadir nombres de viajes a los gastos',
-                        subtitle: 'Añade automáticamente los nombres de viajes a las descripciones de los gastos reservados en Expensify.',
-                    },
+                    title: 'Reserva o gestiona tu viaje',
+                    subtitle: 'Usa Expensify Travel para obtener las mejores ofertas de viaje y gestionar todos tus gastos de empresa en un solo lugar.',
+                    ctaText: 'Reservar o gestionar',
                 },
                 travelInvoicing: {
                     travelBookingSection: {
@@ -5601,49 +4916,21 @@ ${amount} para ${merchant} - ${date}`,
                         subtitle: '¡Felicidades! Todo está listo para reservar y gestionar viajes en este espacio de trabajo.',
                         manageTravelLabel: 'Gestionar viajes',
                     },
-                    travelInvoicingSection: {
-                        title: 'Facturación de viajes',
+                    centralInvoicingSection: {
+                        title: 'Facturación centralizada',
                         subtitle: 'Centraliza todos los gastos de viaje en una factura mensual en lugar de pagar en el momento de la compra.',
                         learnHow: 'Aprende cómo.',
                         subsections: {
                             currentTravelSpendLabel: 'Gasto actual en viajes',
-                            currentTravelSpendPaymentQueued: (amount: string) => `El pago de ${amount} está en cola y se procesará pronto.`,
                             currentTravelSpendCta: 'Pagar saldo',
                             currentTravelLimitLabel: 'Límite actual de viajes',
                             settlementAccountLabel: 'Cuenta de liquidación',
                             settlementFrequencyLabel: 'Frecuencia de liquidación',
                             settlementFrequencyDescription:
                                 'Con qué frecuencia Expensify retirará fondos de la cuenta bancaria de tu empresa para liquidar transacciones recientes de Expensify Travel.',
-                            monthlySpendLimitLabel: 'Límite de gasto mensual por miembro',
-                            monthlySpendLimitDescription: 'El importe máximo que cada miembro puede gastar en viajes por mes.',
-                            reduceLimitTitle: '¿Reducir el límite de gasto en viajes?',
-                            reduceLimitWarning: 'Si reduces el límite, los miembros que ya hayan gastado más de este importe no podrán hacer nuevas reservas de viaje hasta el próximo mes.',
-                            provisioningError:
-                                'No hemos podido aprovisionar a algunos de los miembros de tu espacio de trabajo para la facturación de viajes. Inténtalo de nuevo más tarde o ponte en contacto con Concierge para obtener ayuda.',
                         },
                     },
-                    disableModal: {
-                        title: '¿Desactivar la facturación de viajes?',
-                        body: 'Es posible que las próximas reservas de hotel y alquiler de coches deban volver a reservarse con un método de pago diferente para evitar su cancelación.',
-                        confirm: 'Desactivar',
-                    },
-                    outstandingBalanceModal: {
-                        title: 'No se puede desactivar la facturación de viajes',
-                        body: 'Aún tienes un saldo pendiente de viajes. Por favor, paga tu saldo primero.',
-                        confirm: 'Entendido',
-                    },
-                    payBalanceModal: {
-                        title: (amount: string) => `¿Pagar el saldo de ${amount}?`,
-                        body: 'El pago se pondrá en cola y se procesará poco después. Esta acción no se puede deshacer una vez iniciada.',
-                    },
-                    exportToPDF: 'Exportar a PDF',
-                    exportToCSV: 'Exportar a CSV',
-                    selectDateRangeError: 'Por favor, selecciona un rango de fechas para exportar',
-                    invalidDateRangeError: 'La fecha de inicio debe ser anterior a la fecha de fin',
-                    enabled: '¡Facturación de viajes habilitada!',
-                    enabledDescription: 'Todos los gastos de viaje en este espacio de trabajo ahora se centralizarán en una factura mensual.',
                 },
-                personalDetailsDescription: 'Para poder reservar el viaje, por favor ingrese su nombre legal tal como aparece en su identificación oficial emitida por el gobierno.',
             },
             expensifyCard: {
                 title: 'Tarjeta Expensify',
@@ -5697,10 +4984,7 @@ ${amount} para ${merchant} - ${date}`,
                 updateCard: 'Actualizar tarjeta',
                 unassignCard: 'Desasignar tarjeta',
                 unassign: 'Desasignar',
-                unassignCardDescription: 'Desasignar esta tarjeta eliminará todas las transacciones no enviadas.',
-                removeCard: 'Eliminar tarjeta',
-                remove: 'Eliminar',
-                removeCardDescription: 'Eliminar esta tarjeta eliminará todas las transacciones no enviadas.',
+                unassignCardDescription: 'Desasignar esta tarjeta eliminará todas las transacciones en informes en borrador de la cuenta del titular.',
                 assignCard: 'Asignar tarjeta',
                 cardFeedName: 'Nombre del feed de tarjeta',
                 cardFeedNameDescription: 'Dale al feed de tarjeta un nombre único para que puedas distinguirlo de los demás.',
@@ -5788,7 +5072,6 @@ ${amount} para ${merchant} - ${date}`,
                 description: '¿Está seguro de que desea desconectar esta integración?',
                 confirmText: 'Entendido',
             },
-            hrWarningModal: {disconnectText: ({integration}: {integration: string}) => `Para deshabilitar RR. HH., primero desconecta ${integration} de este espacio de trabajo.`},
             workflowWarningModal: {
                 featureEnabledTitle: 'No tan rápido...',
                 featureEnabledText:
@@ -5825,7 +5108,10 @@ ${amount} para ${merchant} - ${date}`,
             findReportField: 'Encontrar campo del informe',
             deleteConfirmation: '¿Está seguro de que desea eliminar este campo del informe?',
             deleteFieldsConfirmation: '¿Está seguro de que desea eliminar estos campos del informe?',
-            emptyReportFields: {title: 'Aún no hay campos de informe', subtitle: 'Añade un campo personalizado (texto, fecha o desplegable) que aparezca en los informes.'},
+            emptyReportFields: {
+                title: 'No has creado ningún campo de informe',
+                subtitle: 'Añade un campo personalizado (texto, fecha o desplegable) que aparezca en los informes.',
+            },
             subtitle: 'Los campos de informe se aplican a todos los gastos y pueden ser útiles cuando quieras solicitar información adicional.',
             disableReportFields: 'Desactivar campos de informe',
             disableReportFieldsConfirmation: 'Estás seguro? Se eliminarán los campos de texto y fecha y se desactivarán las listas.',
@@ -5849,7 +5135,10 @@ ${amount} para ${merchant} - ${date}`,
             disableValues: 'Desactivar valores',
             enableValue: 'Habilitar valor',
             enableValues: 'Habilitar valores',
-            emptyReportFieldsValues: {title: 'Aún no hay valores en la lista', subtitle: 'Añade valores personalizados para que aparezcan en los informes.'},
+            emptyReportFieldsValues: {
+                title: 'No has creado ningún valor en la lista',
+                subtitle: 'Añade valores personalizados para que aparezcan en los informes.',
+            },
             deleteValuePrompt: '¿Estás seguro de que quieres eliminar este valor de la lista?',
             deleteValuesPrompt: '¿Estás seguro de que quieres eliminar estos valores de la lista?',
             listValueRequiredError: 'Ingresa un nombre para el valor de la lista',
@@ -5861,33 +5150,9 @@ ${amount} para ${merchant} - ${date}`,
             reportFieldNameRequiredError: 'Ingresa un nombre de campo de informe',
             reportFieldTypeRequiredError: 'Elige un tipo de campo de informe',
             circularReferenceError: 'Este campo no puede hacer referencia a sí mismo. Por favor, actualizar.',
-            unsupportedFormulaValueError: ({value}: UnsupportedFormulaValueErrorParams) => `El campo de fórmula ${value} no se reconoce`,
             reportFieldInitialValueRequiredError: 'Elige un valor inicial de campo de informe',
             genericFailureMessage: 'Se ha producido un error al actualizar el campo de informe. Por favor, inténtalo de nuevo.',
         },
-        invoiceFields: {
-            subtitle: 'Los campos de factura pueden ayudarte cuando quieras incluir información adicional.',
-            importedFromAccountingSoftware: 'Campos de factura importados desde',
-            disableInvoiceFields: 'Desactivar campos de factura',
-            disableInvoiceFieldsConfirmation: '¿Estás seguro? Los campos de factura se desactivarán en las facturas.',
-            delete: 'Eliminar campo de factura',
-            deleteConfirmation: '¿Seguro que deseas eliminar este campo de factura?',
-            findInvoiceField: 'Buscar campo de factura',
-            nameInputSubtitle: 'Elige un nombre para el campo de factura.',
-            typeInputSubtitle: 'Elige qué tipo de campo de factura usar.',
-            initialValueInputSubtitle: 'Ingresa un valor inicial para mostrar en el campo de factura.',
-            listValuesInputSubtitle: 'Estos valores aparecerán en el menú desplegable del campo de factura. Los miembros pueden seleccionar los valores activados.',
-            listInputSubtitle: 'Estos valores aparecerán en la lista del campo de factura. Los miembros pueden seleccionar los valores activados.',
-            emptyInvoiceFieldsValues: {
-                title: 'Aún no hay valores de lista',
-                subtitle: 'Agrega valores personalizados para que aparezcan en las facturas.',
-            },
-            existingInvoiceFieldNameError: 'Ya existe un campo de factura con este nombre',
-            invoiceFieldNameRequiredError: 'Ingresa un nombre para el campo de factura',
-            invoiceFieldTypeRequiredError: 'Elige un tipo de campo de factura',
-            invoiceFieldInitialValueRequiredError: 'Elige un valor inicial para el campo de factura',
-            addField: 'Añadir campo',
-        },
         tags: {
             tagName: 'Nombre de etiqueta',
             requiresTag: 'Los miembros deben etiquetar todos los gastos',
@@ -5905,14 +5170,14 @@ ${amount} para ${merchant} - ${date}`,
             editTags: 'Editar etiquetas',
             findTag: 'Encontrar etiquetas',
             subtitle: 'Las etiquetas añaden formas más detalladas de clasificar los costos.',
-            subtitleWithDependentTags: (importSpreadsheetLink, canReimport = true) =>
-                `<muted-text>Las etiquetas añaden formas más detalladas de clasificar los costos. Estás usando <a href="${CONST.IMPORT_TAGS_EXPENSIFY_URL_DEPENDENT_TAGS}">etiquetas dependientes</a>.${canReimport ? ` Puedes <a href="${importSpreadsheetLink}">reimportar una hoja de cálculo</a> para actualizar tus etiquetas.` : ''}</muted-text>`,
+            dependentMultiLevelTagsSubtitle: (importSpreadsheetLink) =>
+                `<muted-text>Estás usando <a href="${CONST.IMPORT_TAGS_EXPENSIFY_URL_DEPENDENT_TAGS}">etiquetas dependientes</a>. Puedes <a href="${importSpreadsheetLink}">reimportar una hoja de cálculo</a> para actualizar tus etiquetas.</muted-text>`,
             emptyTags: {
-                title: 'Aún no hay etiquetas',
+                title: 'No has creado ninguna etiqueta',
                 subtitle: 'Añade una etiqueta para realizar el seguimiento de proyectos, ubicaciones, departamentos y otros.',
                 subtitleHTML: `<muted-text><centered-text>Importa una hoja de cálculo para añadir etiquetas y organizar proyectos, ubicaciones, departamentos y más. <a href="${CONST.IMPORT_TAGS_EXPENSIFY_URL}">Obtén más información</a> sobre cómo dar formato a los archivos de etiquetas.</centered-text></muted-text>`,
-                subtitleWithAccounting: (accountingPageURL, canManage = true) =>
-                    `<muted-text><centered-text>Tus etiquetas se están importando actualmente desde una conexión de contabilidad.${canManage ? ` Dirígete a <a href="${accountingPageURL}">contabilidad</a> para hacer cualquier cambio.` : ''}</centered-text></muted-text>`,
+                subtitleWithAccounting: (accountingPageURL) =>
+                    `<muted-text><centered-text>Tus etiquetas se están importando actualmente desde una conexión de contabilidad. Dirígete a <a href="${accountingPageURL}">contabilidad</a> para hacer cualquier cambio.</centered-text></muted-text>`,
             },
             deleteTag: 'Eliminar etiqueta',
             deleteTags: 'Eliminar etiquetas',
@@ -5995,10 +5260,10 @@ ${amount} para ${merchant} - ${date}`,
                 deleteFailureMessage: 'Se ha producido un error al intentar eliminar la tasa de impuesto. Por favor, inténtalo más tarde.',
                 updateFailureMessage: 'Se ha producido un error al intentar modificar la tasa de impuesto. Por favor, inténtalo más tarde.',
                 createFailureMessage: 'Se ha producido un error al intentar crear la tasa de impuesto. Por favor, inténtalo más tarde.',
-                updateTaxClaimableFailureMessage: 'La porción recuperable debe ser menor al importe por distancia',
+                updateTaxClaimableFailureMessage: 'La porción recuperable debe ser menor al monto del importe por distancia',
             },
             deleteTaxConfirmation: '¿Estás seguro de que quieres eliminar este impuesto?',
-            deleteMultipleTaxConfirmation: (taxAmount) => `¿Estás seguro de que quieres eliminar ${taxAmount} impuestos?`,
+            deleteMultipleTaxConfirmation: ({taxAmount}) => `¿Estás seguro de que quieres eliminar ${taxAmount} impuestos?`,
             actions: {
                 delete: 'Eliminar tasa',
                 deleteMultiple: 'Eliminar tasas',
@@ -6026,50 +5291,13 @@ ${amount} para ${merchant} - ${date}`,
             reimbursementAccount: 'cuenta de reembolso',
             delayedSubmission: 'presentación retrasada',
             welcomeNote: 'Por favor, comience a utilizar mi nuevo espacio de trabajo.',
-            merchantRules: 'Reglas de comerciante',
-            merchantRulesCount: () => ({
-                one: '1 regla de comerciante',
-                other: (count: number) => `${count} reglas de comerciante`,
-            }),
             confirmTitle: ({newWorkspaceName, totalMembers}) =>
                 `Estás a punto de crear y compartir ${newWorkspaceName ?? ''} con ${totalMembers ?? 0} miembros del espacio de trabajo original.`,
             error: 'Se produjo un error al duplicar tu nuevo espacio de trabajo. Inténtalo de nuevo.',
         },
-        copyPolicySettings: {
-            title: 'Copiar configuración',
-            error: 'Se produjo un error al copiar la configuración del espacio de trabajo. Por favor, inténtalo de nuevo.',
-            selectWorkspaces: {
-                title: 'Selecciona espacios de trabajo',
-                description: 'Elige los espacios de trabajo a los que quieres copiar la configuración y luego selecciona los ajustes que quieras copiar.',
-                searchPlaceholder: 'Buscar espacios de trabajo',
-            },
-            selectSettings: {
-                title: 'Selecciona las funciones que quieres copiar',
-                description: 'Selecciona los ajustes que se sobrescribirán en tus espacios de trabajo existentes.',
-                accountingMismatch: ({part}: {part: string}) =>
-                    `Solo puedes copiar ${part} si todos los espacios de trabajo usan el mismo sistema de contabilidad y la misma conexión de empresa.`,
-            },
-            confirmSettings: {
-                title: 'Vamos a asegurarnos de que todo se vea bien.',
-                description: ({workspaceName}: {workspaceName: string}) =>
-                    `Copiaríamos los siguientes ajustes de <strong>${workspaceName}</strong> a los espacios de trabajo que has especificado`,
-            },
-            confirmWorkflows: {
-                continue: 'Continuar sin miembros',
-                description: 'Copiar flujos de trabajo sin miembros no copiará los flujos de aprobación. La configuración de envío y pago sí se copiará.',
-            },
-            progress: {
-                copyInProgressTitle: 'Copia en curso...',
-                copyInProgressDescription: 'Puedes esperar a que el proceso termine o Concierge puede avisarte cuando esté listo.',
-                letMeKnowPrompt: 'Avísame cuando esté listo',
-                conciergeNotificationTitle: 'Concierge te avisará',
-                conciergeNotificationDescription: 'Cuando el proceso se complete, Concierge te enviará un mensaje.',
-                copyCompleted: 'Se han copiado la configuración de tu espacio de trabajo.',
-            },
-        },
         emptyWorkspace: {
-            title: 'Aún no hay espacios de trabajo',
-            subtitle: 'Crea un espacio de trabajo para gestionar tus gastos, reembolsos y tarjetas de empresa.',
+            title: 'No tienes espacios de trabajo',
+            subtitle: 'Organiza recibos, reembolsa gastos, gestiona viajes, envía facturas y mucho más.',
             createAWorkspaceCTA: 'Comenzar',
             features: {
                 trackAndCollect: 'Organiza recibos',
@@ -6124,19 +5352,10 @@ ${amount} para ${merchant} - ${date}`,
                 genericRemove: 'Ha ocurrido un problema al eliminar al miembro del espacio de trabajo',
             },
             addedWithPrimary: 'Se agregaron algunos miembros con sus nombres de usuario principales.',
-            invitedBySecondaryLogin: (secondaryLogin) => `Agregado por nombre de usuario secundario ${secondaryLogin}.`,
-            workspaceMembersCount: (count) => `Total de miembros del espacio de trabajo: ${count}`,
-            allMembers: 'Todos los miembros',
-            admins: 'Administradores del espacio de trabajo',
-            cardAdmins: 'Administradores de tarjetas',
-            approvers: 'Aprobadores',
-            auditors: 'Auditores',
-            emptyRoleFilter: {
-                title: 'Ningún miembro coincide con este filtro',
-                subtitle: 'Invita a un miembro o cambia el filtro anterior.',
-            },
+            invitedBySecondaryLogin: ({secondaryLogin}) => `Agregado por nombre de usuario secundario ${secondaryLogin}.`,
+            workspaceMembersCount: ({count}) => `Total de miembros del espacio de trabajo: ${count}`,
             importMembers: 'Importar miembros',
-            removeMemberPromptApprover: (approver: string, workspaceOwner: string) =>
+            removeMemberPromptApprover: ({approver, workspaceOwner}: {approver: string; workspaceOwner: string}) =>
                 `Si eliminas a ${approver} de este espacio de trabajo, lo reemplazaremos en el flujo de aprobación por ${workspaceOwner}, el propietario del espacio de trabajo.`,
             removeMemberPromptReimburser: ({memberName}: {memberName: string}) =>
                 `No puedes eliminar a ${memberName} de este espacio de trabajo. Por favor, establece un nuevo reembolsador en Flujos de trabajo > Realizar o rastrear pagos y vuelve a intentarlo.`,
@@ -6144,18 +5363,15 @@ ${amount} para ${merchant} - ${date}`,
                 `Si eliminas a ${memberName} de este espacio de trabajo, lo reemplazaremos como el exportador preferido por ${workspaceOwner}, el propietario del espacio de trabajo.`,
             removeMemberPromptTechContact: ({memberName, workspaceOwner}: {memberName: string; workspaceOwner: string}) =>
                 `Si eliminas a ${memberName} de este espacio de trabajo, lo reemplazaremos como contacto técnico por ${workspaceOwner}, el propietario del espacio de trabajo.`,
-            removeMemberPromptPendingApproval: (memberName: string) =>
+            removeMemberPromptPendingApproval: ({memberName}: {memberName: string}) =>
                 `${memberName} tiene gastos pendientes por aprobar. Por favor, pídeles que aprueben o tomen el control de sus informes antes de eliminarlos del espacio de trabajo.`,
             cannotRemoveUserDueToReport: ({memberName}: {memberName: string}) =>
                 `${memberName} tiene un informe en proceso pendiente de acción. Pídele que complete la acción requerida antes de eliminarlo del espacio de trabajo.`,
-            configureHRSync: (providerName: string) => `Configura la sincronización de ${providerName}.`,
-            syncWithHR: (providerName: string) => `Sincronizar con ${providerName}`,
-            makeCardAdmin: () => ({one: 'Hacer administrador de tarjeta', other: 'Hacer administradores de tarjetas'}),
         },
         accounting: {
             settings: 'configuración',
             title: 'Conexiones',
-            subtitle: 'Conecta tu software de contabilidad para una sincronización automática.',
+            subtitle: 'Conecta a tu sistema de contabilidad para codificar transacciones con tu plan de cuentas, auto-cotejar pagos, y mantener tus finanzas sincronizadas.',
             qbo: 'QuickBooks Online',
             qbd: 'QuickBooks Desktop',
             xero: 'Xero',
@@ -6164,7 +5380,7 @@ ${amount} para ${merchant} - ${date}`,
             sap: 'SAP',
             oracle: 'Oracle',
             microsoftDynamics: 'Microsoft Dynamics',
-            talkYourOnboardingSpecialist: 'Chatea con tu ejecutivo de cuenta.',
+            talkYourOnboardingSpecialist: 'Chatea con tu especialista asignado.',
             talkYourAccountManager: 'Chatea con tu gestor de cuenta.',
             talkToConcierge: 'Chatear con Concierge.',
             needAnotherAccounting: '¿Necesitas otro software de contabilidad? ',
@@ -6237,10 +5453,10 @@ ${amount} para ${merchant} - ${date}`,
                 return `¿Estás seguro de que quieres desconectar ${integrationName}?`;
             },
             connectPrompt: ({connectionName}) =>
-                `¿Estás seguro de que quieres conectar a ${CONST.POLICY.CONNECTIONS.NAME_USER_FRIENDLY[connectionName] ?? 'esta integración contable'}? Esto eliminará cualquier conexión contable existente.`,
+                `¿Estás seguro de que quieres conectar a ${
+                    CONST.POLICY.CONNECTIONS.NAME_USER_FRIENDLY[connectionName] ?? 'esta integración contable'
+                }? Esto eliminará cualquier conexión contable existente.`,
             enterCredentials: 'Ingresa tus credenciales',
-            reconnect: 'Reconectar',
-            updateCredentials: 'Actualizar credenciales',
             claimOffer: {
                 badgeText: '¡Oferta disponible!',
                 xero: {
@@ -6384,27 +5600,8 @@ ${amount} para ${merchant} - ${date}`,
                             return 'Importando dimensiones';
                         case 'intacctImportTitle':
                             return 'Importando datos desde Sage Intacct';
-                        case 'financialForceSyncTitle':
-                            return 'Sincronizando datos de Certinia';
-                        case 'financialForceSyncStep':
-                            return 'Sincronizando la conexión de Certinia';
-                        case 'financialForceSyncCategories':
-                            return 'Importando categorías';
-                        case 'financialForceSyncTags':
-                            return 'Importando etiquetas';
-                        case 'financialForceSyncVendors':
-                            return 'Importando proveedores';
-                        case 'financialForceSyncContacts':
-                            return 'Importando contactos';
-                        case 'financialForceSyncCompanies':
-                            return 'Importando empresas';
-                        case 'financialForceSyncUsers':
-                            return 'Importando usuarios';
-                        case 'financialForceSyncDimensions':
-                            return 'Importando dimensiones';
-                        case 'financialForceMarkAsReimbursed':
-                            return 'Marcando informes como reembolsados';
                         default: {
+                            // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
                             return `Translation missing for stage: ${stage}`;
                         }
                     }
@@ -6431,18 +5628,12 @@ ${amount} para ${merchant} - ${date}`,
                 `<muted-text-label>Para activar la Conciliación Continua, activa la <a href="${accountingAdvancedSettingsLink}">auto-sync</a> para ${connectionName}.</muted-text-label>`,
             chooseReconciliationAccount: {
                 chooseBankAccount: 'Elige la cuenta bancaria con la que se conciliarán los pagos de tu Tarjeta Expensify.',
-                settlementAccountReconciliation: (settlementAccountUrl, lastFourPAN) =>
+                settlementAccountReconciliation: ({settlementAccountUrl, lastFourPAN}) =>
                     `Asegúrate de que esta cuenta coincide con <a href="${settlementAccountUrl}">la cuenta de liquidación de tu Tarjeta Expensify</a> (que termina en ${lastFourPAN}) para que la conciliación continua funcione correctamente.`,
-                chooseTravelInvoicingBankAccount: 'Elige la cuenta bancaria con la que se reconciliarán los pagos de tus facturas de viaje.',
-                travelInvoicingSettlementAccountReconciliation: (lastFourPAN: string) =>
-                    `Asegúrate de que esta cuenta coincida con tu cuenta de liquidación de facturas de viaje (que termina en ${lastFourPAN}) para que la conciliación continua funcione correctamente.`,
             },
-            syncTravelInvoicingSettlements: 'Sincronizar liquidaciones de facturación de viajes',
         },
         card: {
             issueCard: 'Emitir tarjeta',
-            chooseRule: 'Elige una regla',
-            searchRules: 'Buscar regla de gasto',
             getStartedIssuing: 'Empieza emitiendo tu primera tarjeta virtual o física.',
             issueNewCard: {
                 whoNeedsCard: '¿Quién necesita una tarjeta?',
@@ -6455,12 +5646,12 @@ ${amount} para ${merchant} - ${date}`,
                 virtualCardDescription: 'Instantáneo y flexible',
                 chooseLimitType: 'Elegir un tipo de límite',
                 smartLimit: 'Límite inteligente',
-                smartLimitDescription: 'Gasta hasta un determinado importe antes de requerir aprobación',
+                smartLimitDescription: 'Gasta hasta una determinada cantidad antes de requerir aprobación',
                 monthly: 'Mensual',
-                monthlyDescription: 'Gasta hasta un determinado importe al mes',
-                fixedAmount: 'Importe fijo',
-                fixedAmountDescription: 'Gasta hasta un determinado importe una vez',
-                cardLimitError: 'Por favor, introduce un importe menor a $21,474,836',
+                monthlyDescription: 'Gasta hasta una determinada cantidad al mes',
+                fixedAmount: 'Cantidad fija',
+                fixedAmountDescription: 'Gasta hasta una determinada cantidad una vez',
+                cardLimitError: 'Por favor, introduce un monto menor a $21,474,836',
                 setLimit: 'Establecer un límite',
                 giveItName: 'Dale un nombre',
                 giveItNameInstruction: 'Hazlo lo suficientemente único para distinguirla de otras tarjetas. ¡Los casos de uso específicos son aún mejores!',
@@ -6484,16 +5675,11 @@ ${amount} para ${merchant} - ${date}`,
                 combineWithExpiration: 'Combina con opciones de vencimiento para un control de gasto adicional',
                 enterValidDate: 'Ingresa una fecha válida',
                 expirationDate: 'Fecha de vencimiento',
-                limitAmount: 'Importe del límite',
-                setCardRules: 'Configurar reglas de la tarjeta',
-                addSpendRule: 'Añadir regla de gasto',
-                addExpirationDate: 'Añade la fecha de vencimiento',
-                addExpirationDateDescription: 'Si no se establece una fecha específica, la tarjeta caducará según la fecha de vencimiento existente en la tarjeta.',
-                amount: 'Importe',
-                copyExisting: 'Copiar existente',
-                createNew: 'Crear nuevo',
-                spendRulesEmptyStateTitle: 'No hay reglas para elegir',
-                spendRulesEmptyStateSubtitle: 'Todavía no hay reglas. Puedes crear una desde la pantalla anterior.',
+                limitAmount: 'Monto del límite',
+                setExpiryOptions: 'Establecer opciones de vencimiento',
+                setExpiryDate: 'Establecer fecha de vencimiento',
+                setExpiryDateDescription: 'La tarjeta expirará según se indica en la tarjeta',
+                amount: 'Monto',
             },
             deactivateCardModal: {
                 deactivate: 'Desactivar',
@@ -6501,88 +5687,7 @@ ${amount} para ${merchant} - ${date}`,
                 deactivateConfirmation: 'Al desactivar esta tarjeta, se rechazarán todas las transacciones futuras y no se podrá deshacer.',
             },
         },
-        hr: {
-            title: 'HR',
-            connections: 'Conexiones',
-            connectionsSubtitle:
-                'Conéctate a tu sistema de RR. HH. para sincronizar los datos de empleados, emparejar automáticamente los reembolsos con las personas correctas y mantener los gastos de tu equipo precisos sin trabajo manual.',
-            subtitle: 'Conecta herramientas de HR y mantén sincronizadas las aprobaciones de empleados.',
-            connect: 'Conectar',
-            syncNow: 'Sincronizar ahora',
-            disconnect: 'Desconectar',
-            disconnectTitle: (providerName: string) => `Desconectar ${providerName}`,
-            disconnectPrompt: (providerName: string) => `¿Seguro que quieres desconectar ${providerName}?`,
-            alreadyConnectedTitle: 'No se puede conectar a varias plataformas de RR. HH.',
-            alreadyConnectedPrompt: 'Debes desconectar tu plataforma de RR. HH. actual antes de conectar otra.',
-            lastSync: (relativeDate: string) => `Última sincronización ${relativeDate}`,
-            syncError: (providerName: string) => `No se puede conectar con ${providerName}`,
-            connectionDescription: (providerName: string) => `Conecta ${providerName} para mantener sincronizadas las aprobaciones de empleados con tu espacio de trabajo.`,
-            approvalMode: 'Modo de aprobación',
-            providerApprovalMode: (providerName: string) => `Modo de aprobación de ${providerName}`,
-            finalApprover: 'Aprobador final',
-            providerFinalApprover: (providerName: string) => `Aprobador final de ${providerName}`,
-            notSet: 'No configurado',
-            approvalModeDescription: (providerName: string) => `Los miembros y gerentes están configurados para sincronizarse con ${providerName}.`,
-            approvalModeWarningTitle: '¿Cambiar modo de aprobación?',
-            approvalModeWarningPrompt: (providerName: string, helpSiteURL: string) =>
-                `¿Seguro que quieres cambiar el modo de aprobación de este espacio de trabajo? Obtén más información sobre los diferentes modos de flujo de trabajo con ${providerName} en nuestro <a href="${helpSiteURL}">sitio de ayuda</a>.`,
-            approvalModeWarningConfirm: 'Cambiar modo de aprobación',
-            approvalModes: {
-                basic: {label: 'Aprobación básica', description: 'Todos los usuarios envían a una sola persona para su procesamiento y aprobación.'},
-                manager: {
-                    label: 'Aprobación del gerente',
-                    description: (providerName: string) => `Los empleados envían informes a su gerente directo configurado en ${providerName}.`,
-                },
-                custom: {label: 'Aprobación personalizada', description: 'Configuraré manualmente los flujos de aprobación en Expensify.'},
-            },
-            syncStageName: ({stage}) => {
-                switch (stage) {
-                    case 'gustoSyncTitle':
-                        return 'Sincronizar empleados de Gusto';
-                    case 'gustoSyncLoadData':
-                        return 'Cargando datos desde Gusto';
-                    case 'gustoSyncProvisioning':
-                        return 'Aprovisionar empleados en la política';
-                    case 'zenefitsSyncTitle':
-                        return 'Sincronización de empleados de TriNet';
-                    case 'zenefitsSyncLoadData':
-                        return 'Cargando datos desde TriNet';
-                    case 'zenefitsSyncProvisioning':
-                        return 'Aprovisionar empleados en la política';
-                    case 'jobDone':
-                        return 'Esperando a que se carguen los datos importados';
-                    default: {
-                        return `Falta la traducción para la etapa: ${stage}`;
-                    }
-                }
-            },
-            syncResults: {
-                title: (provider: string) => `Sincronización de ${provider} completada`,
-                successTitle: (provider: string) => `¡Se sincronizó correctamente tu conexión de ${provider}!`,
-                added: 'Añadido',
-                removed: 'Eliminado',
-                skipped: 'Omitido',
-                employeeCount: () => ({
-                    one: '1 empleado',
-                    other: (count: number) => `${count} empleados`,
-                }),
-            },
-            gusto: {
-                title: 'Gusto',
-            },
-            zenefits: {
-                title: 'TriNet',
-            },
-            syncingModalTitle: 'Tu conexión se está sincronizando',
-            syncingModalDescription: 'La primera conexión puede tardar un poco. Se te notificará de cualquier error.',
-            syncing: 'Sincronizando empleados',
-            mergeHR: {
-                completeSetup: 'Completar configuración',
-                setupIncomplete: (setupLink: string | undefined) =>
-                    `<muted-text-label>Conectado. ${setupLink ? `<a href="${setupLink}">Completa la configuración</a>` : 'Completar configuración'} para importar empleados.</muted-text-label>`,
-                groups: {title: 'Grupos', description: 'Elige los grupos de empleados que te gustaría sincronizar con este espacio de trabajo'},
-            },
-        },
+
         export: {
             notReadyHeading: 'No está listo para exportar',
             notReadyDescription:
@@ -6661,13 +5766,7 @@ ${amount} para ${merchant} - ${date}`,
             errors: {
                 rateNameRequired: 'El nombre de la tasa es obligatorio',
                 existingRateName: 'Ya existe una tasa de distancia con este nombre',
-                nameRequired: 'El nombre es obligatorio',
-                startDateMustBeBeforeEndDate: 'La fecha de inicio debe ser anterior a la fecha de fin',
-                amountRequired: 'El importe es obligatorio',
             },
-            amountPerUnit: (unit: string) => `Importe por ${unit}`,
-            startDate: 'Fecha de inicio',
-            endDate: 'Fecha de fin',
         },
         editor: {
             nameInputLabel: 'Nombre',
@@ -6710,7 +5809,7 @@ ${amount} para ${merchant} - ${date}`,
             updateToUSD: 'Actualizar a USD',
             updateWorkspaceCurrency: 'Actualizar la moneda del espacio de trabajo',
             workspaceCurrencyNotSupported: 'Moneda del espacio de trabajo no soportada',
-            yourWorkspace: `Tu espacio de trabajo está configurado en una moneda no soportada. Consulta la <a href="${CONST.ENABLE_GLOBAL_REIMBURSEMENT_HELP_URL}">lista de monedas soportadas</a>.`,
+            yourWorkspace: `Tu espacio de trabajo está configurado en una moneda no soportada. Consulta la <a href="${CONST.CONNECT_A_BUSINESS_BANK_ACCOUNT_HELP_URL}">lista de monedas soportadas</a>.`,
             chooseAnExisting: 'Elige una cuenta bancaria existente para pagar gastos o añade una nueva.',
         },
         changeOwner: {
@@ -6728,7 +5827,7 @@ ${amount} para ${merchant} - ${date}`,
             ownerOwesAmountTitle: 'Saldo pendiente',
             ownerOwesAmountButtonText: 'Transferir saldo',
             ownerOwesAmountText: (email, amount) =>
-                `La cuenta propietaria de este espacio de trabajo (${email}) tiene un saldo pendiente de un mes anterior.\n\n¿Desea transferir este importe (${amount}) para hacerse cargo de la facturación de este espacio de trabajo? tu tarjeta de pago se cargará inmediatamente.`,
+                `La cuenta propietaria de este espacio de trabajo (${email}) tiene un saldo pendiente de un mes anterior.\n\n¿Desea transferir este monto (${amount}) para hacerse cargo de la facturación de este espacio de trabajo? tu tarjeta de pago se cargará inmediatamente.`,
             subscriptionTitle: 'Asumir la suscripción anual',
             subscriptionButtonText: 'Transferir suscripción',
             subscriptionText: (usersCount, finalCount) =>
@@ -6749,6 +5848,7 @@ ${amount} para ${merchant} - ${date}`,
             errorTitle: '¡Ups! No tan rapido...',
             errorDescription: `<muted-text><centered-text>Hubo un problema al transferir la propiedad de este espacio de trabajo. Inténtalo de nuevo, o <concierge-link>contacta con Concierge</concierge-link> por ayuda.</centered-text></muted-text>`,
         },
+
         exportAgainModal: {
             title: '¡Cuidado!',
             description: ({reportName, connectionName}) =>
@@ -6766,13 +5866,9 @@ ${amount} para ${merchant} - ${date}`,
                     label: 'Controlar',
                     description: 'Para organizaciones con requisitos avanzados.',
                 },
-                submit2026: {
-                    label: 'Enviar',
-                    description: 'Para empleados que buscan enviar gastos a su empleador.',
-                },
             },
-            description: 'Elige el plan adecuado para ti.',
-            subscriptionLink: 'Más información',
+            description: 'Elige el plan adecuado para ti. Para ver una lista detallada de funciones y precios, consulta nuestra',
+            subscriptionLink: 'página de ayuda sobre tipos de planes y precios',
             lockedPlanDescription: ({count, annualSubscriptionEndDate}) => ({
                 one: `Tienes un compromiso anual de 1 miembro activo en el plan Controlar hasta el ${annualSubscriptionEndDate}. Puedes cambiar a una suscripción de pago por uso y desmejorar al plan Recopilar a partir del ${annualSubscriptionEndDate} desactivando la renovación automática en`,
                 other: `Tienes un compromiso anual de ${count} miembros activos en el plan Controlar hasta el ${annualSubscriptionEndDate}. Puedes cambiar a una suscripción de pago por uso y desmejorar al plan Recopilar a partir del ${annualSubscriptionEndDate} desactivando la renovación automática en`,
@@ -6786,12 +5882,6 @@ ${amount} para ${merchant} - ${date}`,
                 onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}) =>
                     `<muted-text>Los campos de informe sólo están disponibles en el plan Controlar, a partir de <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `por miembro al mes.` : `por miembro activo al mes.`}</muted-text>`,
             },
-            invoiceFields: {
-                title: 'Campos de factura',
-                description: `Los campos de factura te permiten incluir detalles adicionales a nivel de factura.`,
-                onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}) =>
-                    `<muted-text>Los campos de factura sólo están disponibles en el plan Controlar, a partir de <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `por miembro al mes.` : `por miembro activo al mes.`}</muted-text>`,
-            },
             [CONST.POLICY.CONNECTIONS.NAME.NETSUITE]: {
                 title: 'NetSuite',
                 description: `Disfruta de la sincronización automática y reduce las entradas manuales con la integración Expensify + NetSuite. Obtén información financiera en profundidad y en tiempo real con la compatibilidad nativa y personalizada con segmentos, incluida la asignación de proyectos y clientes.`,
@@ -6810,24 +5900,12 @@ ${amount} para ${merchant} - ${date}`,
                 onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}) =>
                     `<muted-text>Nuestra integración con QuickBooks Desktop solo está disponible en el plan Controlar, que comienza en <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `por miembro al mes.` : `por miembro activo al mes.`}</muted-text>`,
             },
-            [CONST.POLICY.CONNECTIONS.NAME.CERTINIA]: {
-                title: 'Certinia',
-                description: `Disfruta de la sincronización automatizada y reduce las entradas manuales con la integración Expensify + Certinia. Alinea dimensiones de codificación de gastos y la sincronización de impuestos con tu configuración de Certinia para una visibilidad financiera más clara.`,
-                onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}) =>
-                    `<muted-text>Nuestra integración con Certinia solo está disponible en el plan Controlar, a partir de <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `por miembro al mes.` : `por miembro activo al mes.`}</muted-text>`,
-            },
             [CONST.UPGRADE_FEATURE_INTRO_MAPPING.approvals.id]: {
                 title: 'Aprobaciones anticipadas',
                 description: `Si quieres añadir más niveles de aprobación, o simplemente asegurarte de que los gastos más importantes reciben otro vistazo, no hay problema. Las aprobaciones avanzadas ayudan a realizar las comprobaciones adecuadas a cada nivel para mantener los gastos de tu equipo bajo control.`,
                 onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}) =>
                     `<muted-text>Las aprobaciones avanzadas sólo están disponibles en el plan Controlar, con precios desde <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `por miembro al mes.` : `por miembro activo al mes.`}</muted-text>`,
             },
-            approvalSubmit: {
-                title: 'Aprobaciones',
-                description: 'Configura de forma centralizada a quién envían todos los miembros sus gastos al activar las aprobaciones.',
-                onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}) =>
-                    `<muted-text>Las aprobaciones están disponibles en los planes Recopilar y Controlar, a partir de <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `por miembro al mes.` : `por miembro activo al mes.`}</muted-text>`,
-            },
             categories: {
                 title: 'Categorías',
                 description: 'Las categorías te permiten rastrear y organizar gastos. Usa nuestras categorías predeterminadas o añade las tuyas propias.',
@@ -6858,12 +5936,6 @@ ${amount} para ${merchant} - ${date}`,
                 onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}) =>
                     `<muted-text>Esto solo está disponible en el plan Control, a partir de <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `por miembro al mes.` : `por miembro activo al mes.`}</muted-text>`,
             },
-            companyCardSubmit: {
-                title: 'Tarjetas de empresa',
-                description: 'Trae tu propia tarjeta de empresa a Expensify para obtener importación automática, categorización automática, reglas personalizables y conciliación integrada.',
-                onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}) =>
-                    `<muted-text>La importación de tarjetas de empresa está disponible en los planes Recopilar y Controlar, a partir de <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `por miembro al mes.` : `por miembro activo al mes.`}</muted-text>`,
-            },
             rules: {
                 title: 'Reglas',
                 description: `Las reglas se ejecutan en segundo plano y mantienen tus gastos bajo control para que no tengas que preocuparte por los detalles pequeños.\n\nExige detalles de los gastos, como recibos y descripciones, establece límites y valores predeterminados, y automatiza las aprobaciones y los pagos, todo en un mismo lugar.`,
@@ -6877,13 +5949,6 @@ ${amount} para ${merchant} - ${date}`,
                 onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}) =>
                     `<muted-text>Las dietas per diem solo están disponibles en el plan Control, a partir de <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `por miembro al mes.` : `por miembro activo al mes.`}</muted-text>`,
             },
-            hr: {
-                title: 'Integraciones de HR',
-                description:
-                    'Conecta tu proveedor de HR para sincronizar automáticamente empleados y gestionar los flujos de aprobación. Mantén actualizados el equipo y la estructura de informes sin trabajo manual.',
-                onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}) =>
-                    `<muted-text>Las integraciones de HR solo están disponibles en el plan Control, a partir de <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `por miembro al mes.` : `por miembro activo al mes.`}</muted-text>`,
-            },
             travel: {
                 title: 'Viajes',
                 description:
@@ -6891,12 +5956,6 @@ ${amount} para ${merchant} - ${date}`,
                 onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}) =>
                     `<muted-text>Los viajes están disponibles en el plan Recopilar, a partir de <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `por miembro al mes.` : `por miembro activo al mes.`}</muted-text>`,
             },
-            travelSubmit: {
-                title: 'Expensify Travel',
-                description: 'Reserva vuelos, hoteles, coches y trenes con descuento en todo el mundo desde Expensify, con informes de duty of care y gestión de gastos integrada.',
-                onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}) =>
-                    `<muted-text>Expensify Travel está disponible en los planes Recopilar y Controlar, a partir de <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `por miembro al mes.` : `por miembro activo al mes.`}</muted-text>`,
-            },
             reports: {
                 title: 'Informes',
                 description: 'Los informes te permiten agrupar gastos para un seguimiento y organización más fáciles.',
@@ -6916,7 +5975,7 @@ ${amount} para ${merchant} - ${date}`,
                 onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}) =>
                     `<muted-text>Las tasas de distancia están disponibles en el plan Recopilar, a partir de <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `por miembro al mes.` : `por miembro activo al mes.`}</muted-text>`,
             },
-            controlPolicyRoles: {
+            auditor: {
                 title: 'Auditor',
                 description: 'Los auditores tienen acceso de lectura a todos los informes para una visibilidad completa y la supervisión del cumplimiento.',
                 onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
@@ -6929,40 +5988,7 @@ ${amount} para ${merchant} - ${date}`,
                 onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}) =>
                     `<muted-text>Los múltiples niveles de aprobación solo están disponibles en el plan Controlar, a partir de <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `por miembro al mes.` : `por miembro activo al mes.`}</muted-text>`,
             },
-            roles: {
-                title: 'Roles',
-                description: 'Asigna diferentes roles a diferentes miembros para aumentar o disminuir la visibilidad y el control según corresponda.',
-                onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}) =>
-                    `<muted-text>Los roles están disponibles en los planes Recopilar y Controlar, a partir de <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `por miembro al mes.` : `por miembro activo al mes.`}</muted-text>`,
-            },
-            payments: {
-                title: 'Pagos',
-                description: 'Reembolsa a los empleados directamente desde la cuenta bancaria de tu empresa.',
-                onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}) =>
-                    `<muted-text>Los pagos están disponibles en los planes Recopilar y Controlar, a partir de <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `por miembro al mes.` : `por miembro activo al mes.`}</muted-text>`,
-            },
-            accounting: {
-                title: 'Contabilidad',
-                description:
-                    'Sincroniza categorías, etiquetas, tasas de impuestos y más desde tu sistema contable a Expensify, además de exportar informes de gastos y transacciones de tarjetas, ¡sin necesidad de escribir (ni errores tipográficos)!',
-                onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}) =>
-                    `<muted-text>La contabilidad está disponible en los planes Recopilar y Controlar, a partir de <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `por miembro al mes.` : `por miembro activo al mes.`}</muted-text>`,
-            },
-            expensifyCard: {
-                title: 'Tarjeta Expensify',
-                description:
-                    'Emite tarjetas de empresa (incluidas tarjetas virtuales) directamente desde tu propia cuenta bancaria para obtener control de gastos en tiempo real con una conexión irrompible, ¡y hasta un 2% de reembolso!',
-                onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}) =>
-                    `<muted-text>La Tarjeta Expensify está disponible en los planes Recopilar y Controlar, a partir de <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `por miembro al mes.` : `por miembro activo al mes.`}</muted-text>`,
-                upgradeButton: 'Actualizar y activar',
-            },
-            invoicing: {
-                title: 'Facturación',
-                description: 'Crea, envía y rastrea facturas profesionales, todo dentro de Expensify. Recibe pagos más rápido con pagos integrados y visibilidad en tiempo real.',
-                onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}) =>
-                    `<muted-text>La facturación está disponible en los planes Recopilar y Controlar, a partir de <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `por miembro al mes.` : `por miembro activo al mes.`}</muted-text>`,
-            },
-            note: (subscriptionLink: string) => `<muted-text><a href="${subscriptionLink}">Obtén más información</a> sobre nuestros planes y precios.</muted-text>`,
+            note: ({subscriptionLink}) => `<muted-text>Mejore para acceder a esta función, o <a href="${subscriptionLink}">más información</a> sobre nuestros planes y precios.</muted-text>`,
             pricing: {
                 perActiveMember: 'por miembro activo al mes.',
                 perMember: 'por miembro al mes.',
@@ -6972,8 +5998,8 @@ ${amount} para ${merchant} - ${date}`,
                 headline: 'Has mejorado tu espacio de trabajo.',
                 categorizeMessage: `Has actualizado con éxito al plan Recopilar. ¡Ahora puedes categorizar tus gastos!`,
                 travelMessage: 'Has actualizado con éxito al plan Recopilar. ¡Ahora puedes comenzar a reservar y gestionar viajes!',
-                successMessage: (policyName, planName, subscriptionLink) =>
-                    `<centered-text>Has actualizado con éxito ${policyName} al plan ${planName}. <a href="${subscriptionLink}">Ver su suscripción</a> para obtener más información.</centered-text>`,
+                successMessage: ({policyName, subscriptionLink}) =>
+                    `<centered-text>Has actualizado con éxito ${policyName} al plan Controlar. <a href="${subscriptionLink}">Ver su suscripción</a> para obtener más información.</centered-text>`,
                 distanceRateMessage: 'Has actualizado correctamente al plan Recopilar. ¡Ahora puedes cambiar la tasa de distancia!',
                 gotIt: 'Entendido, gracias.',
                 createdWorkspace: '¡Has creado un espacio de trabajo!',
@@ -6998,20 +6024,17 @@ ${amount} para ${merchant} - ${date}`,
         },
         downgrade: {
             commonFeatures: {
-                title: 'Reducir a Controlar',
-                note: 'Perderás acceso a las siguientes funciones ',
-                noteAndMore: 'y más:',
+                title: 'Desmejorar al plan Recopilar',
+                note: 'Si desmejoras, perderás acceso a estas funciones y más:',
                 benefits: {
-                    important: '¡IMPORTANTE!',
-                    confirm: 'Necesitarás cambiar el "Tipo de plan" de cada espacio de trabajo a "Controlar" para asegurar la tarifa Controlar.',
-                    benefit1Label: 'Integraciones con ERP',
-                    benefit1: 'NetSuite, Sage Intacct, QuickBooks Desktop, Oracle, Microsoft Dynamics',
-                    benefit2Label: 'Integraciones con RR. HH.',
-                    benefit2: 'Workday, Certinia',
-                    benefit3Label: 'Seguridad',
-                    benefit3: 'SSO/SAML',
-                    benefit4Label: 'Avanzado',
-                    benefit4: 'Reglas inteligentes de gastos, dietas, aprobaciones multinivel, informes personalizados y presupuestos',
+                    note: 'Para una comparación completa de nuestros planes, consulta nuestra',
+                    pricingPage: 'página de precios',
+                    confirm: '¿Estás seguro de que deseas desmejorar y eliminar tus configuraciones?',
+                    warning: 'Esto no se puede deshacer.',
+                    benefit1: 'Conexiones de contabilidad (excepto QuickBooks Online y Xero)',
+                    benefit2: 'Reglas inteligentes de gastos',
+                    benefit3: 'Flujos de aprobación de varios niveles',
+                    benefit4: 'Controles de seguridad mejorados',
                     headsUp: '¡Atención!',
                     multiWorkspaceNote:
                         'Tendrás que bajar de categoría todos tus espacios de trabajo antes de tu primer pago mensual para comenzar una suscripción con la tasa del plan Recopilar. Haz clic en',
@@ -7036,7 +6059,7 @@ ${amount} para ${merchant} - ${date}`,
         restrictedAction: {
             restricted: 'Restringido',
             actionsAreCurrentlyRestricted: (workspaceName) => `Las acciones en el espacio de trabajo ${workspaceName} están actualmente restringidas`,
-            workspaceOwnerWillNeedToAddOrUpdatePaymentCard: (workspaceOwnerName) =>
+            workspaceOwnerWillNeedToAddOrUpdatePaymentCard: ({workspaceOwnerName}) =>
                 `El propietario del espacio de trabajo, ${workspaceOwnerName} tendrá que añadir o actualizar la tarjeta de pago registrada para desbloquear nueva actividad en el espacio de trabajo.`,
             youWillNeedToAddOrUpdatePaymentCard: 'Debes añadir o actualizar la tarjeta de pago registrada para desbloquear nueva actividad en el espacio de trabajo.',
             addPaymentCardToUnlock: 'Añade una tarjeta para desbloquearlo!',
@@ -7052,12 +6075,12 @@ ${amount} para ${merchant} - ${date}`,
                 title: 'Gastos',
                 subtitle: (categoriesPageLink, tagsPageLink) =>
                     `<muted-text>Establece controles y valores predeterminados para gastos individuales. También puedes crear reglas para <a href="${categoriesPageLink}">categorías</a> y <a href="${tagsPageLink}">etiquetas</a>.</muted-text>`,
-                receiptRequiredAmount: 'Importe requerido para los recibos',
+                receiptRequiredAmount: 'Cantidad requerida para los recibos',
                 receiptRequiredAmountDescription: 'Exige recibos cuando los gastos superen este importe, a menos que lo anule una regla de categoría.',
-                receiptRequiredAmountError: ({amount}: {amount: string}) => `El importe no puede ser mayor que el importe requerido para recibos detallados (${amount})`,
-                itemizedReceiptRequiredAmount: 'Importe requerido para recibos detallados',
+                receiptRequiredAmountError: ({amount}: {amount: string}) => `La cantidad no puede ser mayor que la cantidad requerida para recibos detallados (${amount})`,
+                itemizedReceiptRequiredAmount: 'Cantidad requerida para recibos detallados',
                 itemizedReceiptRequiredAmountDescription: 'Exige recibos detallados cuando los gastos superen este importe, a menos que lo anule una regla de categoría.',
-                itemizedReceiptRequiredAmountError: ({amount}: {amount: string}) => `El importe no puede ser menor que el importe requerido para recibos normales (${amount})`,
+                itemizedReceiptRequiredAmountError: ({amount}: {amount: string}) => `La cantidad no puede ser menor que la cantidad requerida para recibos regulares (${amount})`,
                 maxExpenseAmount: 'Importe máximo del gasto',
                 maxExpenseAmountDescription: 'Marca los gastos que superen este importe, a menos que una regla de categoría lo anule.',
                 maxAge: 'Antigüedad máxima',
@@ -7089,18 +6112,16 @@ ${amount} para ${merchant} - ${date}`,
                 eReceiptsHint: `Los recibos electrónicos se crean automáticamente [para la mayoría de las transacciones en USD](${CONST.DEEP_DIVE_ERECEIPTS}).`,
                 attendeeTracking: 'Seguimiento de asistentes',
                 attendeeTrackingHint: 'Haz un seguimiento del coste por persona para cada gasto.',
-                prohibitedDefaultDescription: 'Marque los recibos con estos conceptos para revisión manual',
+                prohibitedDefaultDescription:
+                    'Marque cualquier recibo donde aparezcan alcohol, apuestas u otros artículos restringidos. Los gastos con recibos que incluyan estos conceptos requerirán una revisión manual.',
                 prohibitedExpenses: 'Gastos prohibidos',
                 alcohol: 'Alcohol',
                 hotelIncidentals: 'Gastos adicionales de hotel',
                 gambling: 'Juegos de apuestas',
                 tobacco: 'Tabaco',
                 adultEntertainment: 'Entretenimiento para adultos',
-                giftCard: 'Compras de tarjetas regalo',
-                handwrittenReceipt: 'Recibos escritos a mano',
                 requireCompanyCard: 'Requerir que todas las compras se hagan con la tarjeta de empresa',
                 requireCompanyCardDescription: 'Marca todo gasto en efectivo, incluyendo kilometraje y gastos per diem.',
-                requireCompanyCardDisabledTooltip: 'Habilita las tarjetas de empresa (bajo Más características) para desbloquearlo.',
             },
             expenseReportRules: {
                 title: 'Avanzado',
@@ -7109,29 +6130,23 @@ ${amount} para ${merchant} - ${date}`,
                 preventSelfApprovalsSubtitle: 'Evita que los miembros del espacio de trabajo aprueben sus propios informes de gastos.',
                 autoApproveCompliantReportsTitle: 'Aprobación automática de informes conformes',
                 autoApproveCompliantReportsSubtitle: 'Configura qué informes de gastos pueden aprobarse de forma automática.',
-                autoApproveReportsUnderTitle: 'Aprobar automáticamente informes con todos los gastos por debajo de',
-                autoApproveReportsUnderDescription: 'Los informes de gastos totalmente conformes en los que todos los gastos estén por debajo de este importe se aprobarán automáticamente.',
+                autoApproveReportsUnderTitle: 'Aprobar automáticamente informes por debajo de',
+                autoApproveReportsUnderDescription: 'Los informes de gastos totalmente conformes por debajo de esta cantidad se aprobarán automáticamente.',
                 randomReportAuditTitle: 'Auditoría aleatoria de informes',
                 randomReportAuditDescription: 'Requiere que algunos informes sean aprobados manualmente, incluso si son elegibles para la aprobación automática.',
                 autoPayApprovedReportsTitle: 'Pago automático de informes aprobados',
                 autoPayApprovedReportsSubtitle: 'Configura qué informes de gastos pueden pagarse de forma automática.',
-                autoPayApprovedReportsLimitError: (currency) => `Por favor, introduce un importe menor a ${currency ?? ''}20,000`,
+                autoPayApprovedReportsLimitError: (currency) => `Por favor, introduce un monto menor a ${currency ?? ''}20,000`,
                 autoPayApprovedReportsLockedSubtitle: 'Ve a más funciones y habilita flujos de trabajo, luego agrega pagos para desbloquear esta función.',
                 autoPayReportsUnderTitle: 'Pagar automáticamente informes por debajo de',
-                autoPayReportsUnderDescription: 'Los informes de gastos totalmente conformes por debajo de este importe se pagarán automáticamente.',
+                autoPayReportsUnderDescription: 'Los informes de gastos totalmente conformes por debajo de esta cantidad se pagarán automáticamente.',
                 unlockFeatureEnableWorkflowsSubtitle: (featureName) => `Añade ${featureName} para desbloquear esta función.`,
                 enableFeatureSubtitle: (featureName, moreFeaturesLink) => `Ir a [más características](${moreFeaturesLink}) y habilita ${featureName} para desbloquear esta función.`,
             },
-            agentsPromoBanner: {
-                title: '¿No ves la regla que necesitas? Añade un agente',
-                subtitle: 'Añade reglas complejas y reduce las aprobaciones manuales con agentes personalizados.',
-                cta: 'Pruébalo',
-            },
             merchantRules: {
                 title: 'Comerciante',
                 subtitle: 'Configura las reglas de comerciante para que los gastos lleguen correctamente codificados y requieran menos limpieza.',
                 addRule: 'Añadir regla de comerciante',
-                findRule: 'Buscar regla de comerciante',
                 addRuleTitle: 'Añadir regla',
                 editRuleTitle: 'Editar regla',
                 expensesWith: 'Para gastos con:',
@@ -7155,7 +6170,7 @@ ${amount} para ${merchant} - ${date}`,
                 matchTypeContains: 'Contiene',
                 matchTypeExact: 'Coincide exactamente',
                 duplicateRuleTitle: 'Ya existe una regla de comerciante similar',
-                duplicateRulePrompt: (merchantName: string) => `La regla existente para "${merchantName}" tendrá prioridad sobre esta. ¿Desea guardarla de todos modos?`,
+                duplicateRulePrompt: (merchantName: string) => `¿Quieres guardar una nueva regla para "${merchantName}" aunque ya tengas una existente?`,
                 saveAnyway: 'Guardar de todos modos',
                 applyToExistingUnsubmittedExpenses: 'Aplicar a gastos existentes no enviados',
             },
@@ -7195,109 +6210,13 @@ ${amount} para ${merchant} - ${date}`,
                     always: 'Requerir recibos detallados siempre',
                 },
                 defaultTaxRate: 'Tasa de impuesto predeterminada',
-                enableWorkflows: (moreFeaturesLink) =>
+                enableWorkflows: ({moreFeaturesLink}) =>
                     `Ve a [Más características](${moreFeaturesLink}) y habilita los flujos de trabajo, luego añade aprobaciones para desbloquear esta función.`,
             },
             customRules: {
                 title: 'Reglas personalizadas',
                 cardSubtitle: 'Aquí es donde se definen las reglas de tu equipo, para que todos sepan lo que esta cubierto.',
-                policyDocument: 'Documento de política',
-                policyText: 'Texto de política',
             },
-            spendRules: {
-                title: 'Gastos',
-                subtitle: 'Aprueba o rechaza transacciones de la tarjeta Expensify en tiempo real.',
-                defaultRuleDescription: 'Todas las tarjetas',
-                block: 'Bloquear',
-                defaultRuleTitle: 'Categorías: Servicios para adultos, cajeros automáticos, juegos de azar, transferencias de dinero',
-                builtInProtectionModal: {
-                    title: 'Las tarjetas Expensify ofrecen protección integrada, siempre',
-                    description: `Expensify siempre rechaza estos cargos:\n\n  • Servicios para adultos\n  • Cajeros automáticos\n  • Juegos de azar\n  • Transferencias de dinero\n\nAgregue más reglas de gasto para proteger el flujo de caja de la empresa.`,
-                },
-                addSpendRule: 'Añadir regla de gastos',
-                editRuleTitle: 'Editar regla',
-                cardPageTitle: 'Tarjeta',
-                cardsSectionTitle: 'Tarjetas',
-                chooseCards: 'Elegir tarjetas',
-                saveRule: 'Guardar regla',
-                deleteRule: 'Eliminar regla',
-                deleteRuleConfirmation: '¿Estás seguro de que quieres eliminar esta regla?',
-                allow: 'Permitir',
-                spendRuleSectionTitle: 'Regla de gastos',
-                restrictionType: 'Tipo de restricción',
-                restrictionTypeHelpAllow: 'Los cargos se aprueban si coinciden con cualquier comerciante o categoría, y no superan un importe máximo.',
-                restrictionTypeHelpBlock: 'Los cargos se rechazan si coinciden con cualquier comerciante o categoría, o superan un importe máximo.',
-                addMerchant: 'Añadir comerciante',
-                merchantContains: 'El comerciante contiene',
-                merchantExactlyMatches: 'El comerciante coincide exactamente',
-                noBlockedMerchants: 'No hay comerciantes bloqueados',
-                addMerchantToBlockSpend: 'Añade un comerciante para bloquear gastos',
-                noAllowedMerchants: 'No hay comerciantes permitidos',
-                addMerchantToAllowSpend: 'Añade un comerciante para permitir gastos',
-                matchType: 'Tipo de coincidencia',
-                matchTypeContains: 'Contiene',
-                matchTypeExact: 'Coincide exactamente',
-                spendCategory: 'Categoría de gasto',
-                maxAmount: 'Importe máximo',
-                maxAmountHelp: 'Cualquier cargo por encima de este importe se rechazará, independientemente de las restricciones de comerciante y categoría de gasto.',
-                currencyMismatchTitle: 'Moneda no coincide',
-                currencyMismatchPrompt: 'Para establecer un importe máximo, selecciona tarjetas que se liquiden en la misma moneda.',
-                reviewSelectedCards: 'Revisar tarjetas seleccionadas',
-                summaryMoreCount: ({summary, count}) => (count > 0 ? `${summary}, +${count} más` : summary),
-                summaryMerchants: ({merchants, hiddenCount, shownCount, action}) =>
-                    `${action === CONST.SPEND_RULES.ACTION.BLOCK ? 'Bloqueados' : 'Permitidos'} ${shownCount > 1 ? 'comerciantes' : 'comerciante'}: ${merchants}${hiddenCount > 0 ? `, +${hiddenCount} más` : ''}`,
-                summaryCategories: ({categories, hiddenCount, shownCount, action}) =>
-                    `${action === CONST.SPEND_RULES.ACTION.BLOCK ? 'Bloqueados' : 'Permitidos'} ${shownCount > 1 ? 'categorías' : 'categoría'}: ${categories}${hiddenCount > 0 ? `, +${hiddenCount} más` : ''}`,
-                confirmErrorApplyAtLeastOneSpendRuleToOneCard: 'Aplica al menos una regla de gasto a una tarjeta',
-                confirmErrorCardRequired: 'La tarjeta es un campo obligatorio',
-                confirmErrorApplyAtLeastOneSpendRule: 'Aplica al menos una regla de gasto',
-                categories: 'Categorías',
-                merchants: 'Comerciantes',
-                noAvailableCards: 'No hay tarjetas activas en este feed',
-                noAvailableCardsSubtitle: 'Edita una regla de tarjeta existente para hacer cambios',
-                noCardsIssuedTitle: 'No se han emitido Tarjetas Expensify',
-                noCardsIssuedSubtitle: 'Emite Tarjetas Expensify para crear reglas de gasto',
-                max: 'Máx.',
-                categoryOptions: {
-                    [CONST.SPEND_RULES.CATEGORIES.AIRLINES]: 'Aerolíneas',
-                    [CONST.SPEND_RULES.CATEGORIES.ALCOHOL_AND_BARS]: 'Bares y restaurantes',
-                    [CONST.SPEND_RULES.CATEGORIES.AMAZON_AND_BOOKSTORES]: 'Amazon y librerías',
-                    [CONST.SPEND_RULES.CATEGORIES.AUTOMOTIVE]: 'Automotriz',
-                    [CONST.SPEND_RULES.CATEGORIES.CAR_RENTALS]: 'Alquiler de coches',
-                    [CONST.SPEND_RULES.CATEGORIES.DINING]: 'Comida y bebida',
-                    [CONST.SPEND_RULES.CATEGORIES.FUEL_AND_GAS]: 'Combustible y gasolina',
-                    [CONST.SPEND_RULES.CATEGORIES.GOVERNMENT_AND_NON_PROFITS]: 'Gobierno y organizaciones sin ánimo de lucro',
-                    [CONST.SPEND_RULES.CATEGORIES.GROCERIES]: 'Supermercados',
-                    [CONST.SPEND_RULES.CATEGORIES.GYMS_AND_FITNESS]: 'Gimnasios y fitness',
-                    [CONST.SPEND_RULES.CATEGORIES.HEALTHCARE]: 'Salud',
-                    [CONST.SPEND_RULES.CATEGORIES.HOTELS]: 'Hoteles',
-                    [CONST.SPEND_RULES.CATEGORIES.INTERNET_AND_PHONE]: 'Internet y teléfono',
-                    [CONST.SPEND_RULES.CATEGORIES.OFFICE_SUPPLIES]: 'Oficina',
-                    [CONST.SPEND_RULES.CATEGORIES.PARKING_AND_TOLLS]: 'Parking y peajes',
-                    [CONST.SPEND_RULES.CATEGORIES.PROFESSIONAL_SERVICES]: 'Servicios profesionales',
-                    [CONST.SPEND_RULES.CATEGORIES.RETAIL]: 'Tiendas',
-                    [CONST.SPEND_RULES.CATEGORIES.SHIPPING_AND_DELIVERY]: 'Envío y entrega',
-                    [CONST.SPEND_RULES.CATEGORIES.SOFTWARE]: 'Software',
-                    [CONST.SPEND_RULES.CATEGORIES.TRANSIT_AND_RIDESHARE]: 'Transporte y transporte compartido',
-                    [CONST.SPEND_RULES.CATEGORIES.TRAVEL_AGENCIES]: 'Agencias de viajes',
-                },
-            },
-            aiRules: {
-                title: 'Reglas de IA',
-                subtitle: 'Describe reglas flexibles que se ejecutan cuando las necesitas',
-                addRule: 'Añadir regla de IA',
-                findRule: 'Buscar regla de IA',
-                addRuleTitle: 'Añadir regla',
-                describeRuleTitle: 'Describe tu regla',
-                describeRuleSubtitle: 'Describe tu regla y Concierge la creará',
-                editRuleTitle: 'Editar regla',
-                deleteRule: 'Eliminar regla',
-                deleteRuleConfirmation: '¿Seguro que quieres eliminar esta regla?',
-            },
-        },
-        emptyDomain: {
-            title: 'Mejora tu seguridad con dominios',
-            subtitle: 'Exige que los miembros de tu dominio inicien sesión mediante inicio de sesión único, restrinjan la creación de espacios de trabajo y más.',
         },
     },
     getAssistancePage: {
@@ -7313,7 +6232,6 @@ ${amount} para ${merchant} - ${date}`,
         onboardingHelp: 'Ayuda de incorporación',
     },
     emojiPicker: {
-        emojiNotSelected: 'Emoji no seleccionado',
         skinTonePickerLabel: 'Elige el tono de piel por defecto',
         headers: {
             frequentlyUsed: 'Usado frecuentemente',
@@ -7336,10 +6254,11 @@ ${amount} para ${merchant} - ${date}`,
         restrictedDescription: 'Sólo las personas en tu espacio de trabajo pueden encontrar esta sala',
         privateDescription: 'Sólo las personas que están invitadas a esta sala pueden encontrarla',
         publicDescription: 'Cualquier persona puede unirse a esta sala',
+        // eslint-disable-next-line @typescript-eslint/naming-convention
         public_announceDescription: 'Cualquier persona puede unirse a esta sala',
         createRoom: 'Crea una sala de chat',
         roomAlreadyExistsError: 'Ya existe una sala con este nombre',
-        roomNameReservedError: (reservedName) => `${reservedName} es el nombre una sala por defecto de todos los espacios de trabajo. Por favor, elige otro nombre.`,
+        roomNameReservedError: ({reservedName}) => `${reservedName} es el nombre una sala por defecto de todos los espacios de trabajo. Por favor, elige otro nombre.`,
         roomNameInvalidError: 'Los nombres de las salas solo pueden contener minúsculas, números y guiones',
         pleaseEnterRoomName: 'Por favor, escribe el nombre de una sala',
         pleaseSelectWorkspace: 'Por favor, selecciona un espacio de trabajo',
@@ -7347,14 +6266,15 @@ ${amount} para ${merchant} - ${date}`,
             const actor = actorName ? `${actorName} ` : '';
             return isExpenseReport ? `${actor}cambió el nombre a "${newName}" (previamente "${oldName}")` : `${actor}cambió el nombre de la sala a "${newName}" (previamente "${oldName}")`;
         },
-        roomRenamedTo: (newName) => `Sala renombrada a ${newName}`,
+        roomRenamedTo: ({newName}) => `Sala renombrada a ${newName}`,
         social: 'social',
         selectAWorkspace: 'Seleccionar un espacio de trabajo',
         growlMessageOnRenameError: 'No se ha podido cambiar el nombre del espacio de trabajo. Por favor, comprueba tu conexión e inténtalo de nuevo.',
         visibilityOptions: {
-            restricted: 'Espacio de trabajo',
+            restricted: 'Espacio de trabajo', // the translation for "restricted" visibility is actually workspace. This is so we can display restricted visibility rooms as "workspace" without having to change what's stored.
             private: 'Privada',
             public: 'Público',
+            // eslint-disable-next-line @typescript-eslint/naming-convention
             public_announce: 'Anuncio Público',
         },
     },
@@ -7387,22 +6307,24 @@ ${amount} para ${merchant} - ${date}`,
             previousAddress ? `cambió la dirección de la empresa a "${newAddress}" (anteriormente "${previousAddress}")` : `estableció la dirección de la empresa en "${newAddress}"`,
         addApprovalRule: (approverEmail, approverName, field, name) => `añadió a ${approverName} (${approverEmail}) como aprobador para la ${field} "${name}"`,
         deleteApprovalRule: (approverEmail, approverName, field, name) => `eliminó a ${approverName} (${approverEmail}) como aprobador para la ${field} "${name}"`,
-        updateApprovalRule: (field, name, newApproverEmail, newApproverName, oldApproverEmail, oldApproverName) => {
+        updateApprovalRule: ({field, name, newApproverEmail, newApproverName, oldApproverEmail, oldApproverName}) => {
             const formatApprover = (displayName?: string, email?: string) => (displayName ? `${displayName} (${email})` : email);
+
             return `cambió el aprobador para la ${field} "${name}" a ${formatApprover(newApproverName, newApproverEmail)} (previamente ${formatApprover(oldApproverName, oldApproverEmail)})`;
         },
-        addCategory: (categoryName) => `añadió la categoría "${categoryName}""`,
-        deleteCategory: (categoryName) => `eliminó la categoría "${categoryName}"`,
-        updateCategory: (categoryName, oldValue) => `${oldValue ? 'deshabilitó' : 'habilitó'} la categoría "${categoryName}"`,
-        updatedDescriptionHint: (categoryName, newValue, oldValue) => {
+        addCategory: ({categoryName}) => `añadió la categoría "${categoryName}""`,
+        deleteCategory: ({categoryName}) => `eliminó la categoría "${categoryName}"`,
+        updateCategory: ({oldValue, categoryName}) => `${oldValue ? 'deshabilitó' : 'habilitó'} la categoría "${categoryName}"`,
+        updatedDescriptionHint: ({categoryName, oldValue, newValue}) => {
             if (!newValue) {
                 return `eliminó la sugerencia de descripción "${oldValue}" de la categoría "${categoryName}"`;
             }
+
             return !oldValue
                 ? `añadió la sugerencia de descripción "${newValue}" a la categoría "${categoryName}"`
                 : `cambió la sugerencia de descripción de la categoría "${categoryName}" a “${newValue}” (anteriormente “${oldValue}”)`;
         },
-        updateCategoryPayrollCode: (categoryName, newValue, oldValue) => {
+        updateCategoryPayrollCode: ({oldValue, categoryName, newValue}) => {
             if (!oldValue) {
                 return `añadió el código de nómina "${newValue}" a la categoría "${categoryName}"`;
             }
@@ -7411,7 +6333,7 @@ ${amount} para ${merchant} - ${date}`,
             }
             return `cambió el código de nómina de la categoría "${categoryName}" a “${newValue}” (previamente “${oldValue}”)`;
         },
-        updateCategoryGLCode: (categoryName, newValue, oldValue) => {
+        updateCategoryGLCode: ({oldValue, categoryName, newValue}) => {
             if (!oldValue) {
                 return `añadió el código GL "${newValue}" a la categoría "${categoryName}"`;
             }
@@ -7420,10 +6342,10 @@ ${amount} para ${merchant} - ${date}`,
             }
             return `cambió el código GL de la categoría “${categoryName}” a “${newValue}” (previamente “${oldValue}”)`;
         },
-        updateAreCommentsRequired: (categoryName, oldValue) => {
+        updateAreCommentsRequired: ({oldValue, categoryName}) => {
             return `cambió la descripción de la categoría "${categoryName}" a ${!oldValue ? 'requerida' : 'no requerida'} (previamente ${!oldValue ? 'no requerida' : 'requerida'})`;
         },
-        updateCategoryMaxExpenseAmount: (categoryName, newAmount, oldAmount) => {
+        updateCategoryMaxExpenseAmount: ({categoryName, oldAmount, newAmount}) => {
             if (newAmount && !oldAmount) {
                 return `añadió un importe máximo de ${newAmount} a la categoría "${categoryName}"`;
             }
@@ -7432,74 +6354,72 @@ ${amount} para ${merchant} - ${date}`,
             }
             return `cambió el importe máximo de la categoría "${categoryName}" a ${newAmount} (previamente ${oldAmount})`;
         },
-        updateCategoryExpenseLimitType: (categoryName, newValue, oldValue) => {
+        updateCategoryExpenseLimitType: ({categoryName, oldValue, newValue}) => {
             if (!oldValue) {
                 return `añadió un tipo de límite de ${newValue} a la categoría "${categoryName}"`;
             }
             return `actualizó la categoría "${categoryName}" cambiando el Tipo de Límite a ${newValue} (previamente "${oldValue}")`;
         },
-        updateCategoryMaxAmountNoReceipt: (categoryName, newValue, oldValue) => {
+        updateCategoryMaxAmountNoReceipt: ({categoryName, oldValue, newValue}) => {
             if (!oldValue) {
                 return `actualizó la categoría "${categoryName}" cambiando Recibos a ${newValue}`;
             }
             return `cambió la categoría "${categoryName}" a ${newValue} (previamente ${oldValue})`;
         },
-        updateCategoryMaxAmountNoItemizedReceipt: (categoryName, oldValue, newValue) => {
+        updateCategoryMaxAmountNoItemizedReceipt: ({categoryName, oldValue, newValue}) => {
             if (!oldValue) {
                 return `actualizó la categoría "${categoryName}" cambiando Recibos detallados a ${newValue}`;
             }
             return `cambió los Recibos detallados de la categoría "${categoryName}" a ${newValue} (previamente ${oldValue})`;
         },
-        setCategoryName: (oldName, newName) => `renombró la categoría "${oldName}" a "${newName}"`,
-        updateCategories: (count) => `actualizó ${count} categorías`,
-        updateTagListName: (oldName, newName) => `cambió el nombre de la lista de etiquetas a "${newName}" (previamente "${oldName}")`,
-        updateTagList: (tagListName) => `actualizó las etiquetas de la lista "${tagListName}"`,
-        updateTagListRequired: (tagListsName, isRequired) => `cambió la lista de etiquetas "${tagListsName}" a ${isRequired ? 'requerida' : 'no requerida'}`,
+        setCategoryName: ({oldName, newName}) => `renombró la categoría "${oldName}" a "${newName}"`,
+        updateCategories: ({count}) => `actualizó ${count} categorías`,
+        updateTagListName: ({oldName, newName}) => `cambió el nombre de la lista de etiquetas a "${newName}" (previamente "${oldName}")`,
+        updateTagList: ({tagListName}) => `actualizó las etiquetas de la lista "${tagListName}"`,
+        updateTagListRequired: ({tagListsName, isRequired}) => `cambió la lista de etiquetas "${tagListsName}" a ${isRequired ? 'requerida' : 'no requerida'}`,
         importTags: 'importó etiquetas desde una hoja de cálculo',
         deletedAllTags: 'eliminó todas las etiquetas',
-        addTag: (tagListName, tagName) => `añadió la etiqueta "${tagName}" a la lista "${tagListName}"`,
-        updateTagName: (tagListName, newName, oldName) => `actualizó la lista de etiquetas "${tagListName}" cambiando la etiqueta "${oldName}" a "${newName}"`,
-        updateTagEnabled: (tagListName, tagName, enabled) => `${enabled ? 'habilitó' : 'deshabilitó'} la etiqueta "${tagName}" en la lista "${tagListName}"`,
-        deleteTag: (tagListName, tagName) => `eliminó la etiqueta "${tagName}" de la lista "${tagListName}"`,
-        deleteMultipleTags: (count, tagListName) => `eliminó "${count}" etiquetas de la lista "${tagListName}"`,
-        updateTag: (tagListName, newValue, tagName, updatedField, oldValue) => {
+        addTag: ({tagListName, tagName}) => `añadió la etiqueta "${tagName}" a la lista "${tagListName}"`,
+        updateTagName: ({tagListName, newName, oldName}) => `actualizó la lista de etiquetas "${tagListName}" cambiando la etiqueta "${oldName}" a "${newName}"`,
+        updateTagEnabled: ({tagListName, tagName, enabled}: UpdatedPolicyTagParams) => `${enabled ? 'habilitó' : 'deshabilitó'} la etiqueta "${tagName}" en la lista "${tagListName}"`,
+        deleteTag: ({tagListName, tagName}: UpdatedPolicyTagParams) => `eliminó la etiqueta "${tagName}" de la lista "${tagListName}"`,
+        deleteMultipleTags: ({count, tagListName}) => `eliminó "${count}" etiquetas de la lista "${tagListName}"`,
+        updateTag: ({tagListName, newValue, tagName, updatedField, oldValue}) => {
             if (oldValue) {
                 return `actualizó la etiqueta "${tagName}" en la lista "${tagListName}" cambiando el ${updatedField} a "${newValue}" (previamente "${oldValue}")`;
             }
             return `actualizó la etiqueta "${tagName}" en la lista "${tagListName}" añadiendo un ${updatedField} de "${newValue}"`;
         },
-        updateCustomUnit: (customUnitName, newValue, oldValue, updatedField) => `cambió el ${customUnitName} ${updatedField} a "${newValue}" (previamente "${oldValue}")`,
-        updateCustomUnitTaxEnabled: (newValue) => `${newValue ? 'habilitó' : 'deshabilitó'} el seguimiento de impuestos en tasas de distancia`,
-        updateCustomUnitDefaultCategory: (customUnitName, newValue, oldValue) =>
+        updateCustomUnit: ({customUnitName, newValue, oldValue, updatedField}) => `cambió el ${customUnitName} ${updatedField} a "${newValue}" (previamente "${oldValue}")`,
+        updateCustomUnitTaxEnabled: ({newValue}) => `${newValue ? 'habilitó' : 'deshabilitó'} el seguimiento de impuestos en tasas de distancia`,
+        updateCustomUnitDefaultCategory: ({customUnitName, newValue, oldValue}) =>
             `cambió la categoría predeterminada de ${customUnitName} a "${newValue}" ${oldValue ? `(anteriormente "${oldValue}")` : ''}`,
-        importCustomUnitRates: (customUnitName) => `importó tasas para la unidad personalizada "${customUnitName}"`,
-        addCustomUnitRate: (customUnitName: string, rateName: string) => `añadió la tasa de ${customUnitName} «${rateName}»`,
-        deleteCustomUnitRate: (customUnitName, rateName) => `eliminó la tasa "${rateName}" de "${customUnitName}"`,
-        updateCustomUnitSubRate: (customUnitName, customUnitRateName, customUnitSubRateName, oldValue, newValue, updatedField) =>
+        importCustomUnitRates: ({customUnitName}) => `importó tasas para la unidad personalizada "${customUnitName}"`,
+        addCustomUnitRate: ({customUnitName, rateName}) => `añadió una nueva tasa de "${rateName}" para "${customUnitName}"`,
+        deleteCustomUnitRate: ({customUnitName, rateName}) => `eliminó la tasa "${rateName}" de "${customUnitName}"`,
+        updateCustomUnitSubRate: ({customUnitName, customUnitRateName, customUnitSubRateName, oldValue, newValue, updatedField}) =>
             `cambió la sub-tasa "${customUnitSubRateName}" de la tasa "${customUnitRateName}" de "${customUnitName}" ${updatedField} a "${newValue}" (anteriormente "${oldValue}")`,
-        removedCustomUnitSubRate: (customUnitName, customUnitRateName, removedSubRateName) =>
+        removedCustomUnitSubRate: ({customUnitName, customUnitRateName, removedSubRateName}) =>
             `eliminó la sub-tasa "${removedSubRateName}" de la tasa "${customUnitRateName}" de "${customUnitName}"`,
-        addedReportField: (fieldType, fieldName, defaultValue) =>
-            `añadió el campo de informe ${fieldType} "${fieldName}"${defaultValue ? ` con el valor predeterminado "${defaultValue}"` : ''}`,
-        updatedCustomUnitRate: (customUnitName, customUnitRateName, updatedField, newValue, oldValue) =>
+        addedReportField: ({fieldType, fieldName}) => `añadió el campo de informe ${fieldType} "${fieldName}"`,
+        updatedCustomUnitRate: ({customUnitName, customUnitRateName, newValue, oldValue, updatedField}) =>
             `cambió la tasa de ${customUnitName} ${updatedField} "${customUnitRateName}" a "${newValue}" (previamente "${oldValue}")`,
-        updatedCustomUnitTaxRateExternalID: (customUnitRateName, newValue, newTaxPercentage, oldTaxPercentage, oldValue) => {
+        updatedCustomUnitTaxRateExternalID: ({customUnitRateName, newValue, newTaxPercentage, oldTaxPercentage, oldValue}) => {
             if (oldTaxPercentage && oldValue) {
                 return `cambió la tasa de impuesto en la tasa por distancia "${customUnitRateName}" a "${newValue} (${newTaxPercentage})" (previamente "${oldValue} (${oldTaxPercentage})")`;
             }
             return `añadió la tasa de impuesto "${newValue} (${newTaxPercentage})" a la tasa de distancia "${customUnitRateName}"`;
         },
-        updatedCustomUnitTaxClaimablePercentage: (customUnitRateName, newValue, oldValue) => {
+        updatedCustomUnitTaxClaimablePercentage: ({customUnitRateName, newValue, oldValue}) => {
             if (oldValue) {
                 return `cambió la parte recuperable de impuestos en la tasa por distancia "${customUnitRateName}" a "${newValue}" (previamente "${oldValue}")`;
             }
             return `añadió una parte recuperable de impuestos de "${newValue}" a la tasa por distancia "${customUnitRateName}`;
         },
-        updatedCustomUnitRateName: (customUnitName: string, oldValue: string, newValue: string) => `cambió el nombre de la tasa de ${customUnitName} de "${oldValue}" a "${newValue}"`,
-        updatedCustomUnitRateEnabled: (customUnitName, customUnitRateName, newValue) => {
+        updatedCustomUnitRateEnabled: ({customUnitName, customUnitRateName, newValue}) => {
             return `${newValue ? 'habilitó' : 'deshabilitó'} la tasa de ${customUnitName} "${customUnitRateName}"`;
         },
-        updateReportFieldDefaultValue: (defaultValue, fieldName) => `estableció el valor predeterminado del campo de informe "${fieldName}" en "${defaultValue}"`,
+        updateReportFieldDefaultValue: ({defaultValue, fieldName}) => `estableció el valor predeterminado del campo de informe "${fieldName}" en "${defaultValue}"`,
         addedReportFieldOption: (fieldName, optionName) => `añadió la opción "${optionName}" al campo de informe "${fieldName}"`,
         removedReportFieldOption: (fieldName, optionName) => `eliminó la opción "${optionName}" del campo de informe "${fieldName}"`,
         updateReportFieldOptionDisabled: (fieldName, optionName, optionEnabled) =>
@@ -7508,90 +6428,35 @@ ${amount} para ${merchant} - ${date}`,
             if (toggledOptionsCount && toggledOptionsCount > 1) {
                 return `${allEnabled ? 'habilitó' : 'deshabilitó'} todas las opciones para el campo de informe "${fieldName}"`;
             }
-            return `${allEnabled ? 'habilitó' : 'deshabilitó'} la opción "${optionName}" para el campo de informe "${fieldName}", haciendo que todas las opciones queden ${allEnabled ? 'habilitadas' : 'deshabilitadas'}`;
+            return `${allEnabled ? 'habilitó' : 'deshabilitó'} la opción "${optionName}" para el campo de informe "${fieldName}", haciendo que todas las opciones queden ${
+                allEnabled ? 'habilitadas' : 'deshabilitadas'
+            }`;
         },
         deleteReportField: ({fieldType, fieldName}: {fieldType: string; fieldName?: string}) => `eliminó el campo de informe ${fieldType} "${fieldName}"`,
-        addedCardFeed: (feedName: string) => `añadió la fuente de tarjetas "${feedName}"`,
-        removedCardFeed: (feedName: string) => `eliminó la fuente de tarjetas "${feedName}"`,
-        renamedCardFeed: (newName: string, oldName: string) => `renombró la fuente de tarjetas a "${newName}" (previamente "${oldName}")`,
-        assignedCompanyCard: (email: string, feedName: string, cardLastFour: string) =>
-            `asignó la tarjeta de empresa ${feedName ? `"${feedName}" ` : ''}que termina en ${cardLastFour} a ${email}`,
-        unassignedCompanyCard: (email: string, feedName: string, cardLastFour: string) =>
-            `desasignó la tarjeta de empresa ${feedName ? `"${feedName}" ` : ''}que termina en ${cardLastFour} de ${email}`,
-        updatedCardFeedLiability: (feedName: string, enabled: boolean) =>
-            `${enabled ? 'habilitó' : 'deshabilitó'} que los titulares de tarjetas eliminen transacciones de la fuente de tarjetas "${feedName}"`,
-        updatedCardFeedStatementPeriod: (feedName: string, newValue?: string, previousValue?: string) =>
-            `cambió el día de cierre del período de estado de cuenta de la fuente de tarjetas "${feedName}"${newValue ? ` a "${newValue}"` : ''}${previousValue ? ` (previamente "${previousValue}")` : ''}`,
-        expensifyCardRule: {
-            actionVerb: {block: 'bloqueado', allow: 'permitido'},
-            amountOperator: {over: 'más de', under: 'debajo'},
-            amountFilter: ({operator, amount}: {operator: string; amount: string}) => `cantidades ${operator} ${amount}`,
-            theCard: 'la tarjeta',
-            multipleCards: ({count}: {count: number}) => ({
-                one: '1 tarjeta',
-                other: `${count} tarjetas`,
-            }),
-            addRule: ({verb, filters, cards}: {verb: string; filters: string; cards: string}) => {
-                let text = verb;
-                if (filters !== '') {
-                    text += ` ${filters}`;
-                }
-                text += ` en ${cards}`;
-                return text;
-            },
-            removeRule: ({cards}: {cards: string}) => `eliminó la regla de gasto de ${cards}`,
-            restrictionVerb: {block: 'bloquear', allow: 'permitir solo'},
-            update: {
-                modeChange: ({fromAction, toAction, cards}: {fromAction: string; toAction: string; cards: string}) => `cambió la regla de gasto de ${fromAction} a ${toAction} en ${cards}`,
-                appliedToAdditionalCards: ({count}: {count: number}) => ({
-                    one: 'aplicó la regla de gasto a 1 tarjeta adicional',
-                    other: `aplicó la regla de gasto a ${count} tarjetas adicionales`,
-                }),
-                phraseVerb: {added: 'añadido', removed: 'eliminado', changed: 'cambió', set: 'establecer', applied: 'aplicado'},
-                bodyMerchant: ({adjective, value}: {adjective: string; value: string}) => (adjective !== '' ? `${adjective} comercio «${value}»` : `comercio «${value}»`),
-                bodyMerchantChange: ({adjective, oldValue, newValue}: {adjective: string; oldValue: string; newValue: string}) =>
-                    adjective !== '' ? `${adjective} del comerciante de '${oldValue}' a '${newValue}'` : `comercio de '${oldValue}' a '${newValue}'`,
-                bodySpendCategory: ({adjective, value}: {adjective: string; value: string}) =>
-                    adjective !== '' ? `Categoría de gasto ${adjective} «${value}»` : `categoría de gasto «${value}»`,
-                bodySpendCategoryChange: ({adjective, oldValue, newValue}: {adjective: string; oldValue: string; newValue: string}) =>
-                    adjective !== '' ? `Categoría de gasto ${adjective} de '${oldValue}' a '${newValue}'` : `categoría de gasto de '${oldValue}' a '${newValue}'`,
-                bodyMaxAmount: 'importe máximo',
-                bodyMaxAmountSet: ({value}: {value: string}) => `importe máximo hasta ${value}`,
-                bodyMaxAmountChange: ({oldValue, newValue}: {oldValue: string; newValue: string}) => `importe máximo de ${oldValue} a ${newValue}`,
-                bodyAppliedToAdditionalCards: ({count}: {count: number}) => ({
-                    one: 'regla de gasto para 1 tarjeta adicional',
-                    other: `regla de gasto para ${count} tarjetas adicionales`,
-                }),
-                bodyRemovedFromCards: ({cards}: {cards: string}) => `regla de gasto de ${cards}`,
-                composeOnCards: ({content, cards}: {content: string; cards: string}) => `${content} en ${cards}`,
-                composeFromCards: ({content, cards}: {content: string; cards: string}) => `${content} de ${cards}`,
-            },
-        },
-        preventSelfApproval: (oldValue, newValue) =>
+        preventSelfApproval: ({oldValue, newValue}) =>
             `actualizó "Evitar la autoaprobación" a "${newValue === 'true' ? 'Habilitada' : 'Deshabilitada'}" (previamente "${oldValue === 'true' ? 'Habilitada' : 'Deshabilitada'}")`,
-        setReceiptRequiredAmount: (newValue) => `estableció el importe requerido del recibo en "${newValue}"`,
-        changedReceiptRequiredAmount: (oldValue, newValue) => `cambió el importe requerido del recibo a "${newValue}" (antes "${oldValue}")`,
-        removedReceiptRequiredAmount: (oldValue) => `eliminó el importe requerido del recibo (antes "${oldValue}")`,
-        setItemizedReceiptRequiredAmount: (newValue) => `estableció el importe requerido del recibo detallado en "${newValue}"`,
-        changedItemizedReceiptRequiredAmount: (oldValue, newValue) => `cambió el importe requerido del recibo detallado a "${newValue}" (antes "${oldValue}")`,
-        removedItemizedReceiptRequiredAmount: (oldValue) => `eliminó el importe requerido del recibo detallado (antes "${oldValue}")`,
-        setMaxExpenseAmount: (newValue) => `estableció el importe máximo del gasto en "${newValue}"`,
-        changedMaxExpenseAmount: (oldValue, newValue) => `cambió el importe máximo del gasto a "${newValue}" (antes "${oldValue}")`,
-        removedMaxExpenseAmount: (oldValue) => `eliminó el importe máximo del gasto (antes "${oldValue}")`,
-        setMaxExpenseAge: (newValue) => `estableció la antigüedad máxima del gasto en "${newValue}" días`,
-        changedMaxExpenseAge: (oldValue, newValue) => `cambió la antigüedad máxima del gasto a "${newValue}" días (antes "${oldValue}")`,
-        removedMaxExpenseAge: (oldValue) => `eliminó la antigüedad máxima del gasto (anteriormente "${oldValue}" días)`,
-        updateDefaultBillable: (oldValue, newValue) => `actualizó "Volver a facturar gastos a clientes" a "${newValue}" (previamente "${oldValue}")`,
-        updateDefaultReimbursable: (oldValue, newValue) => `actualizó "Valor predeterminado para gastos en efectivo" a "${newValue}" (previamente "${oldValue}")`,
-        updateMonthlyOffset: (oldValue, newValue) => {
+        setReceiptRequiredAmount: ({newValue}) => `estableció el importe requerido del recibo en "${newValue}"`,
+        changedReceiptRequiredAmount: ({oldValue, newValue}) => `cambió el importe requerido del recibo a "${newValue}" (antes "${oldValue}")`,
+        removedReceiptRequiredAmount: ({oldValue}) => `eliminó el importe requerido del recibo (antes "${oldValue}")`,
+
+        setMaxExpenseAmount: ({newValue}) => `estableció el importe máximo del gasto en "${newValue}"`,
+        changedMaxExpenseAmount: ({oldValue, newValue}) => `cambió el importe máximo del gasto a "${newValue}" (antes "${oldValue}")`,
+        removedMaxExpenseAmount: ({oldValue}) => `eliminó el importe máximo del gasto (antes "${oldValue}")`,
+
+        setMaxExpenseAge: ({newValue}) => `estableció la antigüedad máxima del gasto en "${newValue}" días`,
+        changedMaxExpenseAge: ({oldValue, newValue}) => `cambió la antigüedad máxima del gasto a "${newValue}" días (antes "${oldValue}")`,
+        removedMaxExpenseAge: ({oldValue}) => `eliminó la antigüedad máxima del gasto (anteriormente "${oldValue}" días)`,
+        updateDefaultBillable: ({oldValue, newValue}) => `actualizó "Volver a facturar gastos a clientes" a "${newValue}" (previamente "${oldValue}")`,
+        updateDefaultReimbursable: ({oldValue, newValue}) => `actualizó "Valor predeterminado para gastos en efectivo" a "${newValue}" (previamente "${oldValue}")`,
+        updateMonthlyOffset: ({oldValue, newValue}) => {
             if (!oldValue) {
                 return `establecer la fecha de envío del informe mensual a "${newValue}"`;
             }
             return `actualizar la fecha de envío del informe mensual a "${newValue}" (previamente "${oldValue}")`;
         },
-        updateDefaultTitleEnforced: (value) => `cambió "Requerir título predeterminado de informe" a ${value ? 'activado' : 'desactivado'}`,
-        changedCustomReportNameFormula: (oldValue, newValue) => `cambió la fórmula personalizado del nombre del informe a "${newValue}" (anteriormente "${oldValue}")`,
-        updateWorkspaceDescription: (newDescription, oldDescription) =>
+        updateDefaultTitleEnforced: ({value}) => `cambió "Requerir título predeterminado de informe" a ${value ? 'activado' : 'desactivado'}`,
+        changedCustomReportNameFormula: ({newValue, oldValue}) => `cambió la fórmula personalizado del nombre del informe a "${newValue}" (anteriormente "${oldValue}")`,
+        updateWorkspaceDescription: ({newDescription, oldDescription}) =>
             !oldDescription
                 ? `estableció la descripción de este espacio de trabajo como "${newDescription}"`
                 : `actualizó la descripción de este espacio de trabajo a "${newDescription}" (previamente "${oldDescription}")`,
@@ -7611,19 +6476,19 @@ ${amount} para ${merchant} - ${date}`,
             };
         },
         demotedFromWorkspace: (policyName, oldRole) => `cambió tu rol en ${policyName} de ${oldRole} a miembro. Te eliminamos de todos los chats de gastos, excepto el suyo.`,
-        updatedWorkspaceCurrencyAction: (oldCurrency, newCurrency) => `actualizó la moneda predeterminada a ${newCurrency} (previamente ${oldCurrency})`,
-        updatedWorkspaceFrequencyAction: (oldFrequency, newFrequency) => `actualizó la frecuencia de generación automática de informes a "${newFrequency}" (previamente "${oldFrequency}")`,
+        updatedWorkspaceCurrencyAction: ({oldCurrency, newCurrency}) => `actualizó la moneda predeterminada a ${newCurrency} (previamente ${oldCurrency})`,
+        updatedWorkspaceFrequencyAction: ({oldFrequency, newFrequency}) => `actualizó la frecuencia de generación automática de informes a "${newFrequency}" (previamente "${oldFrequency}")`,
         updateApprovalMode: ({newValue, oldValue}) => `actualizó el modo de aprobación a "${newValue}" (previamente "${oldValue}")`,
         upgradedWorkspace: 'mejoró este espacio de trabajo al plan Controlar',
         forcedCorporateUpgrade: `Este espacio de trabajo ha sido actualizado al plan Control. Haz clic <a href="${CONST.COLLECT_UPGRADE_HELP_URL}">aquí</a> para obtener más información.`,
         downgradedWorkspace: 'bajó de categoría este espacio de trabajo al plan Recopilar',
-        updatedAuditRate: (oldAuditRate, newAuditRate) =>
+        updatedAuditRate: ({oldAuditRate, newAuditRate}) =>
             `cambió la tasa de informes enviados aleatoriamente para aprobación manual a ${Math.round(newAuditRate * 100)}% (previamente ${Math.round(oldAuditRate * 100)}%)`,
-        changedReimburser: (newReimburser, previousReimburser) =>
+        changedReimburser: ({newReimburser, previousReimburser}) =>
             previousReimburser ? `cambió el pagador autorizado a "${newReimburser}" (previamente "${previousReimburser}")` : `cambió el pagador autorizado a "${newReimburser}"`,
-        updateReimbursementEnabled: (enabled) => `${enabled ? 'habilitó' : 'deshabilitó'} los reembolsos`,
-        updatedManualApprovalThreshold: (oldLimit, newLimit) => `cambió el límite de aprobación manual para todos los gastos a ${newLimit} (previamente ${oldLimit})`,
-        addBudget: (frequency, entityName, entityType, shared, individual, notificationThreshold) => {
+        updateReimbursementEnabled: ({enabled}) => `${enabled ? 'habilitó' : 'deshabilitó'} los reembolsos`,
+        updatedManualApprovalThreshold: ({oldLimit, newLimit}) => `cambió el límite de aprobación manual para todos los gastos a ${newLimit} (previamente ${oldLimit})`,
+        addBudget: ({frequency, entityName, entityType, shared, individual, notificationThreshold}) => {
             const thresholdSuffix = typeof notificationThreshold === 'number' ? ` con umbral de notificación de "${notificationThreshold}%"` : '';
             let entityLabel = entityType;
             if (entityType === 'category') {
@@ -7639,27 +6504,33 @@ ${amount} para ${merchant} - ${date}`,
             }
             return `añadió presupuesto ${frequency} compartido de "${shared}"${thresholdSuffix} a ${entityLabel} "${entityName}"`;
         },
-        updateBudget: (entityType, entityName, oldFrequency, newFrequency, oldIndividual, newIndividual, oldShared, newShared, oldNotificationThreshold, newNotificationThreshold) => {
+        updateBudget: ({entityType, entityName, oldFrequency, newFrequency, oldIndividual, newIndividual, oldShared, newShared, oldNotificationThreshold, newNotificationThreshold}) => {
             const frequencyChanged = !!(newFrequency && oldFrequency !== newFrequency);
             const sharedChanged = !!(newShared && oldShared !== newShared);
             const individualChanged = !!(newIndividual && oldIndividual !== newIndividual);
             const thresholdChanged = typeof newNotificationThreshold === 'number' && oldNotificationThreshold !== newNotificationThreshold;
             const changesList: string[] = [];
+
             if (frequencyChanged) {
                 changesList.push(`cambió la frecuencia del presupuesto a "${newFrequency}" (antes "${oldFrequency}")`);
             }
+
             if (sharedChanged) {
                 changesList.push(`cambió el presupuesto compartido total del espacio de trabajo a "${newShared}" (antes "${oldShared}")`);
             }
+
             if (individualChanged) {
                 changesList.push(`cambió el presupuesto individual a "${newIndividual}" (antes "${oldIndividual}")`);
             }
+
             if (thresholdChanged) {
                 changesList.push(`cambió el umbral de notificación a "${newNotificationThreshold}%" (antes "${oldNotificationThreshold}%")`);
             }
+
             if (!frequencyChanged && !sharedChanged && !individualChanged && !thresholdChanged) {
                 return `actualizó el presupuesto para ${entityType} "${entityName}"`;
             }
+
             if (changesList.length === 1) {
                 let entityLabel = entityType;
                 if (entityType === 'category') {
@@ -7678,6 +6549,7 @@ ${amount} para ${merchant} - ${date}`,
                 }
                 return `cambió el umbral de notificación para ${entityLabel} "${entityName}" a "${newNotificationThreshold}%" (antes "${oldNotificationThreshold}%")`;
             }
+
             let entityLabel = entityType;
             if (entityType === 'category') {
                 entityLabel = 'la categoría';
@@ -7686,7 +6558,7 @@ ${amount} para ${merchant} - ${date}`,
             }
             return `actualizó el presupuesto para ${entityLabel} "${entityName}": ${changesList.join('; ')}`;
         },
-        deleteBudget: (entityType, entityName, frequency, individual, shared, notificationThreshold) => {
+        deleteBudget: ({entityType, entityName, frequency, individual, shared, notificationThreshold}) => {
             const thresholdSuffix = typeof notificationThreshold === 'number' ? ` con umbral de notificación de "${notificationThreshold}%"` : '';
             let entityLabel = entityType;
             if (entityType === 'category') {
@@ -7705,31 +6577,31 @@ ${amount} para ${merchant} - ${date}`,
             }
             return `eliminó el presupuesto de ${entityLabel} "${entityName}"`;
         },
-        updatedTimeEnabled: (enabled) => `${enabled ? 'habilitó' : 'deshabilitó'} el seguimiento de tiempo`,
-        updatedTimeRate: (newRate, oldRate) => `cambió la tarifa por hora a "${newRate}" (anteriormente "${oldRate}")`,
+        updatedTimeEnabled: ({enabled}) => `${enabled ? 'habilitó' : 'deshabilitó'} el seguimiento de tiempo`,
+        updatedTimeRate: ({newRate, oldRate}) => `cambió la tarifa por hora a "${newRate}" (anteriormente "${oldRate}")`,
         addedProhibitedExpense: ({prohibitedExpense}) => `añadió "${prohibitedExpense}" a los gastos prohibidos`,
         removedProhibitedExpense: ({prohibitedExpense}) => `eliminó "${prohibitedExpense}" de los gastos prohibidos`,
-        updatedReimbursementChoice: (newReimbursementChoice, oldReimbursementChoice) =>
+        updatedReimbursementChoice: ({newReimbursementChoice, oldReimbursementChoice}) =>
             `cambió el método de reembolso a "${newReimbursementChoice}" (previamente "${oldReimbursementChoice}")`,
-        setAutoJoin: (enabled) => `${enabled ? 'habilitó' : 'deshabilitó'} la aprobación previa de solicitudes para unirse al espacio de trabajo`,
-        updatedDefaultTitle: (newDefaultTitle, oldDefaultTitle) => `cambió la fórmula personalizada del nombre del informe a "${newDefaultTitle}" (previamente "${oldDefaultTitle}")`,
-        updatedOwnership: (oldOwnerEmail, oldOwnerName, policyName) => `asumió la propiedad del espacio de trabajo ${policyName} de ${oldOwnerName} (${oldOwnerEmail})`,
-        updatedAutoHarvesting: (enabled) => `${enabled ? 'habilitó' : 'deshabilitó'} el envío programado`,
-        updatedIndividualBudgetNotification: (
+        setAutoJoin: ({enabled}) => `${enabled ? 'habilitó' : 'deshabilitó'} la aprobación previa de solicitudes para unirse al espacio de trabajo`,
+        updatedDefaultTitle: ({newDefaultTitle, oldDefaultTitle}) => `cambió la fórmula personalizada del nombre del informe a "${newDefaultTitle}" (previamente "${oldDefaultTitle}")`,
+        updatedOwnership: ({oldOwnerEmail, oldOwnerName, policyName}) => `asumió la propiedad del espacio de trabajo ${policyName} de ${oldOwnerName} (${oldOwnerEmail})`,
+        updatedAutoHarvesting: ({enabled}) => `${enabled ? 'habilitó' : 'deshabilitó'} el envío programado`,
+        updatedIndividualBudgetNotification: ({
             budgetAmount,
             budgetFrequency,
             budgetName,
             budgetTypeForNotificationMessage,
+            summaryLink,
             thresholdPercentage,
             totalSpend,
             unsubmittedSpend,
+            userEmail,
             awaitingApprovalSpend,
             approvedReimbursedClosedSpend,
-            summaryLink?,
-            userEmail?,
-        ) =>
+        }) =>
             `¡Atención! Este espacio de trabajo tiene un presupuesto ${budgetFrequency} ${budgetTypeForNotificationMessage} de "${budgetAmount}" para la categoría "${budgetName}". ${userEmail} está actualmente en ${approvedReimbursedClosedSpend}, lo que supera el ${thresholdPercentage}% del presupuesto. También hay ${awaitingApprovalSpend} en espera de aprobación y ${unsubmittedSpend} que aún no se ha enviado, para un total de ${totalSpend}.${summaryLink ? ` <a href="${summaryLink}">Aquí hay un informe</a> con todos esos gastos para tus registros.` : ''}`,
-        updatedSharedBudgetNotification: (
+        updatedSharedBudgetNotification: ({
             budgetAmount,
             budgetFrequency,
             budgetName,
@@ -7740,7 +6612,7 @@ ${amount} para ${merchant} - ${date}`,
             unsubmittedSpend,
             awaitingApprovalSpend,
             approvedReimbursedClosedSpend,
-        ) =>
+        }) =>
             `¡Atención! Este espacio de trabajo tiene un presupuesto ${budgetFrequency} ${budgetTypeForNotificationMessage} de "${budgetAmount}" para la categoría "${budgetName}". Actualmente estás en ${approvedReimbursedClosedSpend}, lo que supera el ${thresholdPercentage}% del presupuesto. También hay ${awaitingApprovalSpend} en espera de aprobación y ${unsubmittedSpend} que aún no se ha enviado, para un total de ${totalSpend}.${summaryLink ? ` <a href="${summaryLink}">Aquí hay un informe</a> con todos esos gastos para tus registros.` : ''}`,
         updatedFeatureEnabled: ({enabled, featureName}) => {
             switch (featureName) {
@@ -7756,8 +6628,6 @@ ${amount} para ${merchant} - ${date}`,
                     return `${enabled ? 'activó' : 'desactivó'} la contabilidad`;
                 case 'Expensify Cards':
                     return `${enabled ? 'activó' : 'desactivó'} las tarjetas Expensify`;
-                case 'travel invoicing':
-                    return `${enabled ? 'activó' : 'desactivó'} la facturación de viajes`;
                 case 'company cards':
                     return `${enabled ? 'activó' : 'desactivó'} las tarjetas de empresa`;
                 case 'invoicing':
@@ -7775,14 +6645,11 @@ ${amount} para ${merchant} - ${date}`,
             }
         },
         updatedAttendeeTracking: ({enabled}: {enabled: boolean}) => `${enabled ? 'habilitó' : 'deshabilitó'} el seguimiento de asistentes`,
-        updatedRequireCompanyCards: ({enabled}: {enabled: boolean}) => `${enabled ? 'habilitó' : 'deshabilitó'} el requisito de compras con tarjeta de la empresa`,
         updatedAutoPayApprovedReports: ({enabled}: {enabled: boolean}) => `${enabled ? 'habilitó' : 'deshabilitó'} el autopago de informes aprobados`,
         setAutoPayApprovedReportsLimit: ({newLimit}: {newLimit: string}) => `estableció el umbral de autopago de informes aprobados en "${newLimit}"`,
         updatedAutoPayApprovedReportsLimit: ({oldLimit, newLimit}: {oldLimit: string; newLimit: string}) =>
             `cambió el umbral de autopago de informes aprobados a "${newLimit}" (previamente "${oldLimit}")`,
         removedAutoPayApprovedReportsLimit: 'eliminó el umbral de autopago de informes aprobados',
-        updatedMccGroupCategory: ({mccGroupName, oldCategory, newCategory}: {mccGroupName: string; oldCategory: string; newCategory: string}) =>
-            `cambió la categoría de gasto predeterminada para "${mccGroupName}" a "${newCategory}" (previamente "${oldCategory}")`,
         changedDefaultApprover: ({newApprover, previousApprover}: {newApprover: string; previousApprover?: string}) =>
             previousApprover ? `cambió el aprobador predeterminado a ${newApprover} (anteriormente ${previousApprover})` : `cambió el aprobador predeterminado a ${newApprover}`,
         changedSubmitsToApprover: ({
@@ -7837,18 +6704,15 @@ ${amount} para ${merchant} - ${date}`,
             previousForwardsTo
                 ? `cambió el flujo de aprobación para ${approver} para dejar de reenviar informes aprobados (anteriormente reenviados a ${previousForwardsTo})`
                 : `cambió el flujo de aprobación para ${approver} para dejar de reenviar informes aprobados`,
-        updateCustomTaxName: (oldName, newName) => `cambió el nombre del impuesto personalizado a "${newName}" (antes "${oldName}")`,
-        updateCurrencyDefaultTax: (oldName, newName) => `cambió la tasa impositiva predeterminada de la moneda del espacio de trabajo a "${newName}" (anteriormente "${oldName}")`,
-        updateForeignCurrencyDefaultTax: (oldName, newName) => `cambió la tasa impositiva predeterminada de la moneda extranjera a "${newName}" (anteriormente "${oldName}")`,
         changedInvoiceCompanyName: ({newValue, oldValue}: {newValue: string; oldValue?: string}) =>
             oldValue ? `cambió el nombre de la empresa de la factura a "${newValue}" (previamente "${oldValue}")` : `estableció el nombre de la empresa de la factura como "${newValue}"`,
         changedInvoiceCompanyWebsite: ({newValue, oldValue}: {newValue: string; oldValue?: string}) =>
             oldValue
                 ? `cambió el sitio web de la empresa de la factura a "${newValue}" (previamente "${oldValue}")`
                 : `estableció el sitio web de la empresa de la factura como "${newValue}"`,
-        addTax: (taxName) => `añadió el impuesto "${taxName}"`,
-        deleteTax: (taxName) => `eliminó el impuesto "${taxName}"`,
-        updateTax: (oldValue, taxName, updatedField, newValue) => {
+        addTax: ({taxName}) => `añadió el impuesto "${taxName}"`,
+        deleteTax: ({taxName}) => `eliminó el impuesto "${taxName}"`,
+        updateTax: ({oldValue, taxName, updatedField, newValue}) => {
             if (!updatedField) {
                 return '';
             }
@@ -7870,23 +6734,6 @@ ${amount} para ${merchant} - ${date}`,
                 }
             }
         },
-        addCustomUnitRateWithAmount: (rateName: string, rateValue: string) => `añadió la tasa «${rateName}» de ${rateValue}`,
-        addCustomUnitRateWithAmountAndStartDate: (rateName: string, rateValue: string, startDate: string) => `añadió la tasa "${rateName}" de ${rateValue}, válida desde ${startDate}`,
-        addCustomUnitRateWithAmountAndEndDate: (rateName: string, rateValue: string, endDate: string) => `añadió la tasa "${rateName}" de ${rateValue}, válida hasta ${endDate}`,
-        addCustomUnitRateWithAmountAndDates: (rateName: string, rateValue: string, startDate: string, endDate: string) =>
-            `añadió la tasa "${rateName}" de ${rateValue}, válida del ${startDate} al ${endDate}`,
-        updatedCustomUnitRateStartDate: (rateName: string, newDate: string, oldDate?: string) =>
-            oldDate ? `actualizó la fecha de inicio de la tasa "${rateName}" a ${newDate} (previamente ${oldDate})` : `establecer la fecha de inicio de la tasa "${rateName}" a ${newDate}`,
-        updatedCustomUnitRateEndDate: (rateName: string, newDate: string, oldDate?: string) =>
-            oldDate
-                ? `actualizó la fecha de finalización de la tasa "${rateName}" a ${newDate} (previamente ${oldDate})`
-                : `establecer la fecha de finalización de la tasa "${rateName}" en ${newDate}`,
-        updatedCustomUnitRateStartAndEndDate: (rateName: string, newStartDate: string, newEndDate: string, oldStartDate?: string, oldEndDate?: string) =>
-            oldStartDate && oldEndDate
-                ? `actualizó la fecha de inicio y fin de la tasa "${rateName}" a ${newStartDate} - ${newEndDate} (previamente ${oldStartDate} - ${oldEndDate})`
-                : `establece la fecha de inicio y fin de la tasa "${rateName}" a ${newStartDate} - ${newEndDate}`,
-        removedCustomUnitRateStartDate: (rateName: string, oldDate: string) => `se eliminó la fecha de inicio de la tasa "${rateName}" (previamente ${oldDate})`,
-        removedCustomUnitRateEndDate: (rateName: string, oldDate: string) => `eliminó la fecha de finalización de la tasa «${rateName}» (previamente ${oldDate})`,
     },
     roomMembersPage: {
         memberNotFound: 'Miembro no encontrado.',
@@ -7918,7 +6765,7 @@ ${amount} para ${merchant} - ${date}`,
         completed: 'Completada',
         action: 'Completar',
         messages: {
-            created: (title) => `tarea para ${title}`,
+            created: ({title}) => `tarea para ${title}`,
             completed: 'marcada como completa',
             canceled: 'tarea eliminada',
             reopened: 'marcada como incompleta',
@@ -7932,7 +6779,7 @@ ${amount} para ${merchant} - ${date}`,
         deleteConfirmation: '¿Estás seguro de que quieres eliminar esta tarea?',
     },
     statementPage: {
-        title: (year, monthName) => `Estado de cuenta de ${monthName} ${year}`,
+        title: ({year, monthName}) => `Estado de cuenta de ${monthName} ${year}`,
     },
     keyboardShortcutsPage: {
         title: 'Atajos de teclado',
@@ -7945,8 +6792,6 @@ ${amount} para ${merchant} - ${date}`,
             newChat: 'Nueva pantalla de chat',
             copy: 'Copiar comentario',
             openDebug: 'Abrir el diálogo de preferencias de pruebas',
-            expenseReportSearch: 'Buscar informes de gastos',
-            goToWorkspace: 'Ir al espacio de trabajo del informe actual',
         },
     },
     guides: {
@@ -7954,28 +6799,8 @@ ${amount} para ${merchant} - ${date}`,
         screenShareRequest: 'Expensify te está invitando a compartir la pantalla',
     },
     search: {
-        tabs: {
-            expenseReports: 'Informes de gastos',
-            reports: 'Informes',
-            expenses: 'Gastos',
-            submit: 'Borradores',
-            approve: 'Necesita aprobación',
-            pay: 'Listo para pagar',
-            accounting: 'Contabilidad',
-            export: 'Pendiente de exportación',
-            unapprovedCash: 'Acumulaciones de efectivo',
-            unapprovedCard: 'Acumulaciones de tarjeta',
-            statements: 'Extractos de tarjeta',
-            reconciliation: 'Conciliación bancaria',
-            insights: 'Información',
-            topSpenders: 'Mayores gastadores',
-            topCategories: 'Categorías principales',
-            topMerchants: 'Principales comerciantes',
-        },
         resultsAreLimited: 'Los resultados de búsqueda están limitados.',
         viewResults: 'Ver resultados',
-        applyFilters: 'Aplicar filtros',
-        appliedFilters: 'Filtros aplicados',
         resetFilters: 'Restablecer filtros',
         searchResults: {
             emptyResults: {
@@ -7983,23 +6808,25 @@ ${amount} para ${merchant} - ${date}`,
                 subtitle: `Intenta ajustar tus criterios de búsqueda o crear algo con el botón +.`,
             },
             emptyExpenseResults: {
-                title: 'Aún no hay gastos',
+                title: 'Aún no has creado ningún gasto',
                 subtitle: 'Crea un gasto o haz una prueba por Expensify para aprender más.',
                 subtitleWithOnlyCreateButton: 'Usa el botón verde de abajo para crear un gasto.',
             },
             emptyReportResults: {
-                title: 'Aún no hay informes',
+                title: 'Aún no has creado ningún informe',
                 subtitle: 'Crea un informe o haz una prueba de Expensify para aprender más.',
                 subtitleWithOnlyCreateButton: 'Usa el botón verde de abajo para crear un informe.',
             },
             emptyInvoiceResults: {
-                title: 'Aún no hay facturas',
+                title: 'Aún no has creado \nninguna factura',
                 subtitle: 'Envía una factura o haz una prueba por Expensify para aprender más.',
                 subtitleWithOnlyCreateButton: 'Usa el botón verde de abajo para enviar una factura.',
-                subtitleCannotSend: 'Necesitas un espacio de trabajo con Invoices habilitado para enviar facturas.',
-                subtitleCannotSendWithTestDrive: 'Necesitas un espacio de trabajo con Invoices habilitado para enviar facturas. Haz una prueba por Expensify para aprender más.',
             },
-            emptyTripResults: {title: 'Aún no hay viajes', subtitle: 'Reserva tu primer viaje a continuación.', buttonText: 'Reserva un viaje'},
+            emptyTripResults: {
+                title: 'No tienes viajes',
+                subtitle: 'Reserva tu primer viaje a continuación.',
+                buttonText: 'Reserva un viaje',
+            },
             emptySubmitResults: {
                 title: 'No hay gastos para enviar',
                 subtitle: 'Todo despejado. ¡Date una vuelta de victoria!',
@@ -8027,40 +6854,30 @@ ${amount} para ${merchant} - ${date}`,
             },
         },
         columns: 'Columnas',
-        editColumns: 'Editar columnas',
         resetColumns: 'Restablecer columnas',
         groupColumns: 'Columnas de grupo',
         expenseColumns: 'Columnas de gastos',
-        display: {
-            label: 'Mostrar',
-            sortBy: 'Ordenar por',
-            sortOrder: 'Orden de clasificación',
-            groupBy: 'Agrupar por',
-            limitResults: 'Limitar resultados',
-        },
-        has: 'Tiene',
-        view: {label: 'Ver', table: 'Tabla', bar: 'Barra', line: 'Línea', pie: 'Circular'},
-        saveView: 'Guardar vista',
+        statements: 'Extractos',
+        unapprovedCash: 'Efectivo no aprobado',
+        unapprovedCard: 'Tarjeta no aprobada',
+        reconciliation: 'Conciliación',
+        topSpenders: 'Mayores gastadores',
+        view: {label: 'Ver', table: 'Tabla', bar: 'Barra', line: 'Línea'},
+        saveSearch: 'Guardar búsqueda',
         savedSearchesMenuItemTitle: 'Guardadas',
-        urlCopied: 'URL copiada',
-        spendOverTime: 'Evolución de gastos',
+        topCategories: 'Categorías principales',
+        topMerchants: 'Principales comerciantes',
         searchName: 'Nombre de la búsqueda',
         deleteSavedSearch: 'Eliminar búsqueda guardada',
         deleteSavedSearchConfirm: '¿Estás seguro de que quieres eliminar esta búsqueda?',
         groupedExpenses: 'gastos agrupados',
         bulkActions: {
-            editMultiple: 'Editar múltiples',
-            editMultipleTitle: 'Editar múltiples gastos',
-            editMultipleDescription: 'Los cambios se aplicarán a todos los gastos seleccionados y sustituirán cualquier valor establecido previamente.',
             approve: 'Aprobar',
             pay: 'Pagar',
             delete: 'Eliminar',
             hold: 'Retener',
             unhold: 'Desbloquear',
             reject: 'Rechazar',
-            duplicateExpense: ({count}: {count: number}) => `Duplicar ${count === 1 ? 'gasto' : 'gastos'}`,
-            duplicateReport: ({count}: {count: number}) => `Duplicar ${count === 1 ? 'informe' : 'informes'}`,
-            undelete: 'Restaurar',
             noOptionsAvailable: 'No hay opciones disponibles para el grupo de gastos seleccionado.',
         },
         filtersHeader: 'Filtros',
@@ -8069,14 +6886,11 @@ ${amount} para ${merchant} - ${date}`,
                 before: (date) => `Antes de ${date ?? ''}`,
                 after: (date) => `Después de ${date ?? ''}`,
                 on: (date) => `En ${date ?? ''}`,
-                customDate: 'Fecha personalizada',
-                customRange: 'Rango personalizado',
                 presets: {
                     [CONST.SEARCH.DATE_PRESETS.NEVER]: 'Nunca',
                     [CONST.SEARCH.DATE_PRESETS.LAST_MONTH]: 'El mes pasado',
                     [CONST.SEARCH.DATE_PRESETS.THIS_MONTH]: 'Este mes',
                     [CONST.SEARCH.DATE_PRESETS.YEAR_TO_DATE]: 'Año hasta la fecha',
-                    [CONST.SEARCH.DATE_PRESETS.LAST_12_MONTHS]: 'Últimos 12 meses',
                     [CONST.SEARCH.DATE_PRESETS.LAST_STATEMENT]: 'Último extracto',
                 },
             },
@@ -8089,7 +6903,6 @@ ${amount} para ${merchant} - ${date}`,
             completed: 'Completadas',
             card: {
                 expensify: 'Expensify',
-                travelInvoicing: 'Facturación de viajes',
                 individualCards: 'Tarjetas individuales',
                 closedCards: 'Tarjetas cerradas',
                 cardFeeds: 'Flujos de tarjetas',
@@ -8097,15 +6910,10 @@ ${amount} para ${merchant} - ${date}`,
                 cardFeedNameCSV: ({cardFeedLabel}) => `Todas las Tarjetas Importadas desde CSV${cardFeedLabel ? ` - ${cardFeedLabel}` : ''}`,
             },
             amount: {
-                lessThan: (amount) => `Menos de ${amount ?? ''}`,
-                greaterThan: (amount) => `Más que ${amount ?? ''}`,
-                between: (greaterThan, lessThan) => {
-                    if (greaterThan && lessThan) {
-                        return `Entre ${greaterThan} y ${lessThan}`;
-                    }
-                    return 'Entre';
-                },
-                equalTo: (amount) => `Igual a ${amount ?? ''}`,
+                lessThan: ({amount} = {}) => `Menos de ${amount ?? ''}`,
+                greaterThan: ({amount} = {}) => `Más que ${amount ?? ''}`,
+                between: (greaterThan, lessThan) => `Entre ${greaterThan} y ${lessThan}`,
+                equalTo: ({amount} = {}) => `Igual a ${amount ?? ''}`,
             },
             current: 'Actual',
             past: 'Anterior',
@@ -8118,10 +6926,6 @@ ${amount} para ${merchant} - ${date}`,
             billable: 'Facturable',
             reimbursable: 'Reembolsable',
             purchaseCurrency: 'Moneda de compra',
-            sortOrder: {
-                [CONST.SEARCH.SORT_ORDER.ASC]: 'Ascendente',
-                [CONST.SEARCH.SORT_ORDER.DESC]: 'Descendente',
-            },
             groupBy: {
                 [CONST.SEARCH.GROUP_BY.FROM]: 'De',
                 [CONST.SEARCH.GROUP_BY.CARD]: 'Tarjeta',
@@ -8136,9 +6940,8 @@ ${amount} para ${merchant} - ${date}`,
             },
             feed: 'Feed',
             withdrawalType: {
-                [CONST.SEARCH.WITHDRAWAL_TYPE.EXPENSIFY_CARD]: 'Tarjeta Expensify',
+                [CONST.SEARCH.WITHDRAWAL_TYPE.EXPENSIFY_CARD]: 'Expensify Card',
                 [CONST.SEARCH.WITHDRAWAL_TYPE.REIMBURSEMENT]: 'Reembolso',
-                [CONST.SEARCH.WITHDRAWAL_TYPE.CENTRAL_TRAVEL_INVOICING]: 'Facturación de viajes',
             },
             is: 'Es',
             action: {
@@ -8147,8 +6950,10 @@ ${amount} para ${merchant} - ${date}`,
                 [CONST.SEARCH.ACTION_FILTERS.PAY]: 'Pagar',
                 [CONST.SEARCH.ACTION_FILTERS.EXPORT]: 'Exportar',
             },
-            reportField: (name, value) => `${name} es ${value}`,
+            reportField: ({name, value}) => `${name} es ${value}`,
         },
+        has: 'Tiene',
+        groupBy: 'Agrupar por',
         chartTitles: {
             [CONST.SEARCH.GROUP_BY.FROM]: 'De',
             [CONST.SEARCH.GROUP_BY.CARD]: 'Tarjetas',
@@ -8172,22 +6977,9 @@ ${amount} para ${merchant} - ${date}`,
         withdrawalType: 'Tipo de retiro',
         recentSearches: 'Búsquedas recientes',
         recentChats: 'Chats recientes',
-        serverResults: 'Resultados de búsqueda',
         searchIn: 'Buscar en',
-        askConcierge: (message: string) => `Pregunta a Concierge “${message}”`,
-        searchPlaceholder: 'Busca algo...',
+        searchPlaceholder: 'Busca algo',
         suggestions: 'Sugerencias',
-        suggestionsAvailable: (
-            {
-                count,
-            }: {
-                count: number;
-            },
-            query = '',
-        ) => ({
-            one: `Sugerencias disponibles${query ? ` para ${query}` : ''}. ${count} resultado.`,
-            other: (resultCount: number) => `Sugerencias disponibles${query ? ` para ${query}` : ''}. ${resultCount} resultados.`,
-        }),
         exportSearchResults: {
             title: 'Crear exportación',
             description: '¡Wow, esos son muchos elementos! Los agruparemos y Concierge te enviará un archivo en breve.',
@@ -8196,10 +6988,6 @@ ${amount} para ${merchant} - ${date}`,
         exportAll: {
             selectAllMatchingItems: 'Seleccionar todos los elementos coincidentes',
             allMatchingItemsSelected: 'Todos los elementos coincidentes seleccionados',
-            selectAllOnThisPage: 'Seleccionar todo en esta página',
-        },
-        errors: {
-            pleaseSelectDatesForBothFromAndTo: 'Por favor, selecciona fechas para Desde y Hasta',
         },
     },
     genericErrorPage: {
@@ -8256,6 +7044,7 @@ ${amount} para ${merchant} - ${date}`,
             emptyReportConfirmationTitle: 'Ya tienes un informe vacío',
             emptyReportConfirmationPrompt: ({workspaceName}: {workspaceName: string}) =>
                 `¿Estás seguro de que quieres crear otro informe en ${workspaceName}? Puedes acceder a tus informes vacíos en`,
+            emptyReportConfirmationPromptLink: 'Informes',
             emptyReportConfirmationDontShowAgain: 'No me muestres esto otra vez',
             genericWorkspaceName: 'este espacio de trabajo',
         },
@@ -8279,6 +7068,7 @@ ${amount} para ${merchant} - ${date}`,
                 exportedToCSV: `exportado a CSV`,
                 exportedToIntegration: {
                     automatic: (label) => {
+                        // The label will always be in English, so we need to translate it
                         const labelTranslations: Record<string, string> = {
                             [CONST.REPORT.EXPORT_OPTION_LABELS.EXPENSE_LEVEL_EXPORT]: translations.export.expenseLevelExport,
                             [CONST.REPORT.EXPORT_OPTION_LABELS.REPORT_LEVEL_EXPORT]: translations.export.reportLevelExport,
@@ -8292,7 +7082,6 @@ ${amount} para ${merchant} - ${date}`,
                     automaticActionThree: 'y creó un registro con éxito para',
                     reimburseableLink: 'Exportar gastos por cuenta propia como',
                     nonReimbursableLink: 'gastos de la tarjeta de empresa',
-                    travelCardLink: 'gastos de la tarjeta de viaje',
                     pending: (label) => `comenzó a exportar este informe a ${label}...`,
                 },
                 integrationsMessage: (errorMessage, label, linkText, linkURL) =>
@@ -8302,8 +7091,7 @@ ${amount} para ${merchant} - ${date}`,
                 markedReimbursed: (amount, currency) => `pagó ${currency}${amount} en otro lugar`,
                 markedReimbursedFromIntegration: ({amount, currency}) => `pagó ${currency}${amount} mediante integración`,
                 outdatedBankAccount: `no se pudo procesar el pago debido a un problema con la cuenta bancaria del pagador`,
-                reimbursementACHBounceDefault: `no se pudo procesar el pago debido a un número de ruta/cuenta incorrecto o una cuenta cerrada`,
-                reimbursementACHBounceWithReason: ({returnReason}: {returnReason: string}) => `no se pudo procesar el pago: ${returnReason}`,
+                reimbursementACHBounce: `no se pudo procesar el pago debido a un problema con la cuenta bancaria`,
                 reimbursementACHCancelled: `canceled the payment`,
                 reimbursementAccountChanged: `no se pudo procesar el pago porque el pagador cambió de cuenta bancaria`,
                 reimbursementDelayed: `procesó el pago pero se retrasó entre 1 y 2 días hábiles más`,
@@ -8311,37 +7099,30 @@ ${amount} para ${merchant} - ${date}`,
                 selectedForRandomAuditMarkdown: `[seleccionado al azar](https://help.expensify.com/articles/expensify-classic/reports/Set-a-random-report-audit-schedule) para revisión`,
                 share: ({to}) => `miembro invitado ${to}`,
                 unshare: ({to}) => `miembro eliminado ${to}`,
-                stripePaid: (amount, currency) => `pagado ${currency}${amount}`,
+                stripePaid: ({amount, currency}) => `pagado ${currency}${amount}`,
                 takeControl: `tomó el control`,
-                actionableCard3DSTransactionApproval: (amount: string, merchant: string | undefined) => {
-                    const amountAndMerchantText = [amount, merchant].filter((s) => !!s?.length).join(' ');
-                    return `Abra la aplicación móvil de Expensify para revisar su transacción de${amountAndMerchantText ? ` ${amountAndMerchantText}` : ''}`;
-                },
                 integrationSyncFailed: (label, errorMessage, workspaceAccountingLink) =>
                     `hubo un problema al sincronizar con ${label}${errorMessage ? ` ("${errorMessage}")` : ''}. Por favor, soluciona el problema en la <a href="${workspaceAccountingLink}">configuración del espacio de trabajo</a>.`,
-                integrationSyncFailedRecurrence: ({count}: {count: number}) => `(Repetido ${count} veces.)`,
                 companyCardConnectionBroken: ({feedName, workspaceCompanyCardRoute}: {feedName: string; workspaceCompanyCardRoute: string}) =>
                     `La conexión ${feedName} está rota. Para restaurar las importaciones de tarjetas, <a href='${workspaceCompanyCardRoute}'>inicia sesión en tu banco</a>.`,
                 plaidBalanceFailure: ({maskedAccountNumber, walletRoute}: {maskedAccountNumber: string; walletRoute: string}) =>
                     `la conexión Plaid con tu cuenta bancaria de empresa está rota. Por favor, <a href='${walletRoute}'>reconecta tu cuenta bancaria ${maskedAccountNumber}</a> para poder seguir usando tus Tarjetas Expensify.`,
-                addEmployee: (email: string, role: string, didJoinPolicy?: boolean) => {
-                    const translatedRole = String(translations.workspace.common.roleName(role)).toLowerCase();
-                    const article = role === CONST.POLICY.ROLE.AUDITOR ? 'un' : 'a';
-                    return didJoinPolicy ? `${email} se unió a través del enlace de invitación del espacio de trabajo` : `añadió ${email} como ${article} ${translatedRole}`;
-                },
+                addEmployee: (email, role) => `agregó a ${email} como ${role}`,
                 updateRole: ({email, currentRole, newRole}) => `actualizó el rol ${email} a ${newRole} (previamente ${currentRole})`,
-                updatedCustomField1: (email, newValue, previousValue) => {
+                updatedCustomField1: ({email, previousValue, newValue}) => {
                     if (!newValue) {
                         return `eliminó el campo personalizado 1 de ${email} (previamente "${previousValue}")`;
                     }
+
                     return !previousValue
                         ? `añadió "${newValue}" al campo personalizado 1 de ${email}`
                         : `cambió el campo personalizado 1 de ${email} a "${newValue}" (previamente "${previousValue}")`;
                 },
-                updatedCustomField2: (email, newValue, previousValue) => {
+                updatedCustomField2: ({email, previousValue, newValue}) => {
                     if (!newValue) {
                         return `eliminó el campo personalizado 2 de ${email} (previamente "${previousValue}")`;
                     }
+
                     return !previousValue
                         ? `añadió "${newValue}" al campo personalizado 2 de ${email}`
                         : `cambió el campo personalizado 2 de ${email} a "${newValue}" (previamente "${previousValue}")`;
@@ -8363,23 +7144,6 @@ ${amount} para ${merchant} - ${date}`,
     chronos: {
         oooEventSummaryFullDay: (summary, dayCount, date) => `${summary} por ${dayCount} ${dayCount === 1 ? 'día' : 'días'} hasta el ${date}`,
         oooEventSummaryPartialDay: (summary, timePeriod, date) => `${summary} de ${timePeriod} del ${date}`,
-        startTimer: 'Iniciar temporizador',
-        stopTimer: (duration: string) => `Detener temporizador (${duration})`,
-        scheduleOOO: 'Programar ausencia',
-        scheduleOOOTitle: 'Programar fuera de oficina',
-        date: 'Fecha',
-        time: 'Hora (formato de 24 horas)',
-        durationAmount: 'Duración',
-        durationUnit: 'Unidad',
-        reason: 'Motivo',
-        workingPercentage: 'Porcentaje de trabajo',
-        dateRequired: 'La fecha es obligatoria.',
-        invalidTimeFormat: 'Ingresa una hora válida (ej., 14:30).',
-        enterANumber: 'Ingresa un número.',
-        hour: 'horas',
-        day: 'días',
-        week: 'semanas',
-        month: 'meses',
     },
     footer: {
         features: 'Características',
@@ -8882,24 +7646,8 @@ ${amount} para ${merchant} - ${date}`,
         workspaceName: 'Nombre del espacio de trabajo',
         chatUserDisplayNames: 'Nombres de los miembros del chat',
         scrollToNewestMessages: 'Desplázate a los mensajes más recientes',
-        scrollToActionBadgeTarget: 'Desplázate a la acción que requiere atención',
         preStyledText: 'texto preestilizado',
         viewAttachment: 'Ver archivo adjunto',
-        contextMenuAvailable: 'Menú contextual disponible. Pulsa Shift+F10 para abrirlo.',
-        contextMenuAvailableMacOS: 'Menú contextual disponible. Pulsa VO-Shift-M para abrirlo.',
-        contextMenuAvailableNative: 'Menú contextual disponible. Pulsa dos veces y mantén pulsado para abrir.',
-        selectAllFeatures: 'Seleccionar todas las características',
-        selectAllItems: 'Seleccionar todos los elementos',
-        selectAllTransactions: 'Seleccionar todas las transacciones',
-        openActionsMenu: 'Abrir menú de acciones',
-        selectAllCategories: 'Seleccionar todas las categorías',
-        selectAllDistanceRates: 'Seleccionar todas las tarifas de distancia',
-        selectAllTags: 'Seleccionar todas las etiquetas',
-        selectAllTaxes: 'Seleccionar todos los impuestos',
-        selectAllPerDiemRates: 'Seleccionar todas las tarifas de viáticos',
-        selectAllMembers: 'Seleccionar todos los miembros',
-        selectAllValues: 'Seleccionar todos los valores',
-        selectAllRules: 'Seleccionar todas las reglas',
     },
     parentReportAction: {
         deletedReport: 'Informe eliminado',
@@ -8918,7 +7666,6 @@ ${amount} para ${merchant} - ${date}`,
         parentNavigationSummary: ({reportName, workspaceName}) => `De ${reportName}${workspaceName ? ` en ${workspaceName}` : ''}`,
     },
     qrCodes: {
-        qrCode: 'Código QR',
         copy: 'Copiar URL',
         copied: '¡Copiado!',
     },
@@ -8964,11 +7711,6 @@ ${amount} para ${merchant} - ${date}`,
         joinExpensifyOrg: 'Únete a Expensify.org para eliminar la injusticia en todo el mundo y ayuda a los profesores a dividir sus gastos para las aulas más necesitadas.',
         iKnowATeacher: 'Yo conozco a un profesor',
         iAmATeacher: 'Soy profesor',
-        personalKarma: {
-            title: 'Activar Karma personal',
-            description: 'Dona $1 a Expensify.org por cada $500 que gastes cada mes',
-            stopDonationsPrompt: '¿Seguro que quieres dejar de donar a Expensify.org?',
-        },
         getInTouch: '¡Excelente! Por favor, comparte tu información para que podamos ponernos en contacto con ellos.',
         introSchoolPrincipal: 'Introducción al director del colegio',
         schoolPrincipalVerifyExpense:
@@ -8991,11 +7733,6 @@ ${amount} para ${merchant} - ${date}`,
         notActivated: 'No activado',
         outOfPocket: 'Reembolsable',
         companySpend: 'No reembolsable',
-        personalCard: 'Tarjeta personal',
-        companyCard: 'Tarjeta corporativa',
-        expensifyCard: 'Tarjeta Expensify',
-        travelInvoicing: 'Facturación de viajes',
-        travelCard: 'Tarjeta de viaje',
     },
     distance: {
         addStop: 'Añadir parada',
@@ -9021,13 +7758,8 @@ ${amount} para ${merchant} - ${date}`,
             totalDistance: 'Distancia total',
             startTitle: 'Foto inicial del odómetro',
             endTitle: 'Foto final del odómetro',
-            deleteOdometerPhoto: 'Eliminar foto del odómetro',
-            deleteOdometerPhotoConfirmation: '¿Estás seguro de que deseas eliminar esta foto del odómetro?',
             startMessageWeb: 'Añade una foto de tu odómetro al <strong>inicio</strong> de tu viaje. Arrastra un archivo aquí o elige uno para subirlo.',
             endMessageWeb: 'Añade una foto de tu odómetro al <strong>final</strong> de tu viaje. Arrastra un archivo aquí o elige uno para subirlo.',
-            cameraAccessRequired: 'Se requiere acceso a la cámara para tomar fotos.',
-            snapPhotoStart: '<muted-text-label>Haz una foto de tu odómetro al <strong>inicio</strong> de tu viaje.</muted-text-label>',
-            snapPhotoEnd: '<muted-text-label>Haz una foto de tu odómetro al <strong>final</strong> de tu viaje.</muted-text-label>',
         },
     },
     reportCardLostOrDamaged: {
@@ -9055,13 +7787,11 @@ ${amount} para ${merchant} - ${date}`,
         [CONST.REFERRAL_PROGRAM.CONTENT_TYPES.START_CHAT]: {
             buttonText: 'Inicia un chat y <success><strong>recomienda a un amigo</strong></success>',
             header: 'Inicia un chat, recomienda a un amigo',
-            closeAccessibilityLabel: 'Cerrar, iniciar un chat, recomendar a un amigo, banner',
             body: '¿Quieres que tus amigos también usen Expensify? Simplemente inicia un chat con ellos y nosotros nos encargaremos del resto.',
         },
         [CONST.REFERRAL_PROGRAM.CONTENT_TYPES.SUBMIT_EXPENSE]: {
             buttonText: 'Presenta un gasto y <success><strong>recomienda a tu equipo</strong></success>',
             header: 'Envía un gasto, recomienda a tu equipo',
-            closeAccessibilityLabel: 'Cerrar, enviar un gasto, recomendar a tu equipo, banner',
             body: '¿Quieres que tu equipo también use Expensify? Simplemente envíale un gasto y nosotros nos encargaremos del resto.',
         },
         [CONST.REFERRAL_PROGRAM.CONTENT_TYPES.REFER_FRIEND]: {
@@ -9076,28 +7806,26 @@ ${amount} para ${merchant} - ${date}`,
         copyReferralLink: 'Copiar enlace de invitación',
     },
     systemChatFooterMessage: {
-        [CONST.INTRO_CHOICES.MANAGE_TEAM]: ({adminReportName, href}: {adminReportName: string; href: string}) =>
-            `Chatea con tu ejecutivo de cuenta en <a href="${href}">${adminReportName}</a> para obtener ayuda`,
-        default: `Envía un mensaje a <concierge-link>${CONST.CONCIERGE_CHAT_NAME}</concierge-link> para obtener ayuda con la configuración`,
+        [CONST.INTRO_CHOICES.MANAGE_TEAM]: ({adminReportName, href}) => `Chatea con tu especialista asignado en <a href="${href}">${adminReportName}</a> para obtener ayuda`,
+        default: `Envía un correo electrónico a <concierge-link>${CONST.CONCIERGE_CHAT_NAME}</concierge-link> para obtener ayuda con la configuración`,
     },
     violations: {
         allTagLevelsRequired: 'Todas las etiquetas son obligatorias',
         autoReportedRejectedExpense: 'Este gasto fue rechazado.',
         billableExpense: 'La opción facturable ya no es válida',
-        cashExpenseWithNoReceipt: (formattedLimit) => `Recibo obligatorio para importes mayores de ${formattedLimit}`,
+        cashExpenseWithNoReceipt: ({formattedLimit} = {}) => `Recibo obligatorio para cantidades mayores de ${formattedLimit}`,
         categoryOutOfPolicy: 'La categoría ya no es válida',
-        conversionSurcharge: (surcharge) => `${surcharge}% de recargo aplicado`,
+        conversionSurcharge: ({surcharge}) => `${surcharge}% de recargo aplicado`,
         customUnitOutOfPolicy: 'Tasa inválida para este espacio de trabajo',
         duplicatedTransaction: 'Posible duplicado',
         fieldRequired: 'Los campos del informe son obligatorios',
         futureDate: 'Fecha futura no permitida',
-        inactiveVendor: 'El proveedor ya no es válido',
-        invoiceMarkup: (invoiceMarkup) => `Incrementado un ${invoiceMarkup}%`,
-        maxAge: (maxAge) => `Fecha de más de ${maxAge} días`,
+        invoiceMarkup: ({invoiceMarkup}) => `Incrementado un ${invoiceMarkup}%`,
+        maxAge: ({maxAge}) => `Fecha de más de ${maxAge} días`,
         missingCategory: 'Falta categoría',
         missingComment: 'Descripción obligatoria para la categoría seleccionada',
         missingAttendees: 'Se requieren múltiples asistentes para esta categoría',
-        missingTag: (tagName) => `Falta ${tagName ?? 'etiqueta'}`,
+        missingTag: ({tagName} = {}) => `Falta ${tagName ?? 'etiqueta'}`,
         modifiedAmount: ({type, displayPercentVariance}) => {
             switch (type) {
                 case 'distance':
@@ -9112,30 +7840,31 @@ ${amount} para ${merchant} - ${date}`,
             }
         },
         modifiedDate: 'Fecha difiere del recibo escaneado',
-        increasedDistance: ({formattedRouteDistance}) =>
-            formattedRouteDistance ? `La distancia supera la ruta calculada de ${formattedRouteDistance}` : 'La distancia supera la ruta calculada',
         nonExpensiworksExpense: 'Gasto no proviene de Expensiworks',
-        overAutoApprovalLimit: (formattedLimit) => `Importe supera el límite de aprobación automática${formattedLimit ? ` de ${formattedLimit}` : ''}`,
-        overCategoryLimit: (formattedLimit) => `Importe supera el límite para la categoría${formattedLimit ? ` de ${formattedLimit}/persona` : ''}`,
-        overLimit: (formattedLimit) => `Importe supera el límite${formattedLimit ? ` de ${formattedLimit}/persona` : ''}`,
-        overTripLimit: (formattedLimit) => `Importe supera el límite${formattedLimit ? ` de ${formattedLimit}/viaje` : ''}`,
-        overLimitAttendee: (formattedLimit) => `Importe supera el límite${formattedLimit ? ` de ${formattedLimit}/persona` : ''}`,
-        perDayLimit: (formattedLimit) => `Importe supera el límite diario de la categoría${formattedLimit ? ` de ${formattedLimit}/persona` : ''}`,
+        overAutoApprovalLimit: ({formattedLimit}) => `Importe supera el límite de aprobación automática${formattedLimit ? ` de ${formattedLimit}` : ''}`,
+        overCategoryLimit: ({formattedLimit}) => `Importe supera el límite para la categoría${formattedLimit ? ` de ${formattedLimit}/persona` : ''}`,
+        overLimit: ({formattedLimit}) => `Importe supera el límite${formattedLimit ? ` de ${formattedLimit}/persona` : ''}`,
+        overTripLimit: ({formattedLimit}) => `Importe supera el límite${formattedLimit ? ` de ${formattedLimit}/viaje` : ''}`,
+        overLimitAttendee: ({formattedLimit}) => `Importe supera el límite${formattedLimit ? ` de ${formattedLimit}/persona` : ''}`,
+        perDayLimit: ({formattedLimit}) => `Importe supera el límite diario de la categoría${formattedLimit ? ` de ${formattedLimit}/persona` : ''}`,
         receiptNotSmartScanned: 'Detalles del recibo y del gasto añadidos manualmente.',
-        receiptRequired: (formattedLimit, category) => {
+        receiptRequired: ({formattedLimit, category}) => {
             if (formattedLimit && category) {
                 return `Recibo obligatorio para importes sobre ${formattedLimit} el límite de la categoría`;
             }
+
             if (formattedLimit) {
                 return `Recibo obligatorio para importes sobre ${formattedLimit}`;
             }
+
             if (category) {
                 return 'Recibo obligatorio para importes sobre el límite de la categoría';
             }
+
             return 'Recibo obligatorio';
         },
-        itemizedReceiptRequired: (formattedLimit) => `Recibo detallado requerido${formattedLimit ? ` para importes sobre ${formattedLimit}` : ''}`,
-        prohibitedExpense: (prohibitedExpenseTypes) => {
+        itemizedReceiptRequired: ({formattedLimit}) => `Recibo detallado requerido${formattedLimit ? ` para importes sobre ${formattedLimit}` : ''}`,
+        prohibitedExpense: ({prohibitedExpenseTypes}) => {
             const preMessage = 'Gastos prohibidos:';
             const getProhibitedExpenseTypeText = (prohibitedExpenseType: string) => {
                 switch (prohibitedExpenseType) {
@@ -9149,10 +7878,6 @@ ${amount} para ${merchant} - ${date}`,
                         return `entretenimiento para adultos`;
                     case 'hotelIncidentals':
                         return `gastos adicionales de hotel`;
-                    case 'giftCard':
-                        return `compras de tarjetas regalo`;
-                    case 'handwrittenReceipt':
-                        return `recibos escritos a mano`;
                     default:
                         return `${prohibitedExpenseType}`;
                 }
@@ -9168,20 +7893,12 @@ ${amount} para ${merchant} - ${date}`,
             }
             return `${preMessage} ${types.map(getProhibitedExpenseTypeText).join(', ')}`;
         },
-        customRules: (message) => message,
+        customRules: ({message}) => message,
         reviewRequired: 'Revisión requerida',
-        rter: (brokenBankConnection, isAdmin, isTransactionOlderThan7Days, member, rterType, companyCardPageURL, connectionLink, isPersonalCard, isMarkAsCash) => {
+        rter: ({brokenBankConnection, isAdmin, isTransactionOlderThan7Days, member, rterType, companyCardPageURL}: ViolationsRterParams) => {
             if (rterType === CONST.RTER_VIOLATION_TYPES.BROKEN_CARD_CONNECTION_530) {
                 return 'No se puede emparejar automáticamente el recibo debido a una conexión bancaria interrumpida.';
             }
-            if (isPersonalCard && (rterType === CONST.RTER_VIOLATION_TYPES.BROKEN_CARD_CONNECTION || brokenBankConnection)) {
-                if (!connectionLink) {
-                    return 'No se puede emparejar automáticamente el recibo debido a una conexión bancaria interrumpida.';
-                }
-                return isMarkAsCash
-                    ? `No se puede vincular automáticamente el recibo debido a un problema de conexión de la tarjeta. Márcalo como efectivo para ignorarlo o <a href="${connectionLink}">soluciona la conexión de la tarjeta</a> para asociar el recibo.`
-                    : `No se puede vincular automáticamente el recibo debido a un problema de conexión de la tarjeta. <a href="${connectionLink}">Soluciona la conexión de la tarjeta</a> para asociar el recibo.`;
-            }
             if (brokenBankConnection || rterType === CONST.RTER_VIOLATION_TYPES.BROKEN_CARD_CONNECTION) {
                 return isAdmin
                     ? `Conexión bancaria interrumpida. <a href="${companyCardPageURL}">Vuelve a conectarte para emparejar el recibo</a>`
@@ -9199,21 +7916,12 @@ ${amount} para ${merchant} - ${date}`,
             `<muted-text-label>Recibo pendiente debido a una conexión bancaria rota. Por favor, resuélvelo en <a href="${workspaceCompanyCardRoute}">Tarjetas de empresa</a>.</muted-text-label>`,
         memberBrokenConnectionError: 'Recibo pendiente debido a una conexión bancaria rota. Por favor, pide a un administrador del espacio de trabajo que lo resuelva.',
         markAsCashToIgnore: 'Márcalo como efectivo para ignorar y solicitar el pago.',
-        smartscanFailed: ({canEdit = true, missingFields = []}: {canEdit?: boolean; missingFields?: string[]}) => {
-            if (missingFields.length > 0) {
-                const fieldNames: Record<string, string> = {merchant: 'comerciante', date: 'fecha', amount: 'importe'};
-                const translated = missingFields.map((f) => fieldNames[f] ?? f);
-                const fieldList = translated.join(translated.length > 2 ? ', ' : ' y ');
-                const verb = translated.length === 1 ? 'falta' : 'faltan';
-                return `No se pudo escanear el recibo — ${verb} ${fieldList}.${canEdit ? ' Introduce los datos manualmente.' : ''}`;
-            }
-            return `No se pudo escanear el recibo.${canEdit ? ' Introduce los datos manualmente.' : ''}`;
-        },
+        smartscanFailed: ({canEdit = true}) => `No se pudo escanear el recibo.${canEdit ? ' Introduce los datos manualmente.' : ''}`,
         receiptGeneratedWithAI: 'Posible recibo generado por IA',
-        someTagLevelsRequired: (tagName) => `Falta ${tagName ?? 'Tag'}`,
-        tagOutOfPolicy: (tagName) => `La etiqueta ${tagName ? `${tagName} ` : ''}ya no es válida`,
+        someTagLevelsRequired: ({tagName} = {}) => `Falta ${tagName ?? 'Tag'}`,
+        tagOutOfPolicy: ({tagName} = {}) => `La etiqueta ${tagName ? `${tagName} ` : ''}ya no es válida`,
         taxAmountChanged: 'El importe del impuesto fue modificado',
-        taxOutOfPolicy: (taxName) => `${taxName ?? 'El impuesto'} ya no es válido`,
+        taxOutOfPolicy: ({taxName} = {}) => `${taxName ?? 'El impuesto'} ya no es válido`,
         taxRateChanged: 'La tasa de impuesto fue modificada',
         taxRequired: 'Falta la tasa de impuesto',
         none: 'Ninguno',
@@ -9233,7 +7941,7 @@ ${amount} para ${merchant} - ${date}`,
         noRoute: 'Por favor, selecciona una dirección válida',
     },
     reportViolations: {
-        [CONST.REPORT_VIOLATIONS.FIELD_REQUIRED]: (fieldName) => `${fieldName} es obligatorio`,
+        [CONST.REPORT_VIOLATIONS.FIELD_REQUIRED]: ({fieldName}) => `${fieldName} es obligatorio`,
         reportContainsExpensesWithViolations: 'El informe contiene gastos con violaciones.',
     },
     violationDismissal: {
@@ -9289,7 +7997,6 @@ ${amount} para ${merchant} - ${date}`,
         bookACallTextTop: 'Al cambiar a Expensify Classic, se perderá:',
         bookACallTextBottom: 'Nos encantaría hablar con usted para entender por qué. Puede concertar una llamada con uno de nuestros jefes de producto para hablar de sus necesidades.',
         takeMeToExpensifyClassic: 'Llévame a Expensify Classic',
-        goBackJustOnce: 'Volver solo esta vez',
     },
     listBoundary: {
         errorMessage: 'Se ha producido un error al cargar más mensajes',
@@ -9313,8 +8020,8 @@ ${amount} para ${merchant} - ${date}`,
                 title: 'No se pudo procesar tu pago',
                 subtitle: (date, purchaseAmountOwed) =>
                     date && purchaseAmountOwed
-                        ? `No se ha podido procesar tu cargo de ${purchaseAmountOwed} del día ${date}. Por favor, añade una tarjeta de pago para saldar el importe adeudado.`
-                        : 'Por favor, añade una tarjeta de pago para saldar el importe adeudado.',
+                        ? `No se ha podido procesar tu cargo de ${purchaseAmountOwed} del día ${date}. Por favor, añade una tarjeta de pago para saldar la cantidad adeudada.`
+                        : 'Por favor, añade una tarjeta de pago para saldar la cantidad adeudada.',
             },
             policyOwnerUnderInvoicing: {
                 title: 'Tu información de pago está desactualizada',
@@ -9363,7 +8070,7 @@ ${amount} para ${merchant} - ${date}`,
                 subtitle: 'El próximo paso es <a href="#">completar la configuración</a> para que tu equipo pueda empezar a enviar gastos.',
             },
             trialStarted: {
-                title: (numOfDays) => `Prueba gratuita: ¡${numOfDays === 1 ? `queda 1 día` : `${numOfDays} días`}!`,
+                title: ({numOfDays}) => `Prueba gratuita: ¡${numOfDays === 1 ? `queda 1 día` : `${numOfDays} días`}!`,
                 subtitle: 'Añade una tarjeta de pago para seguir utilizando tus funciones favoritas.',
             },
             trialEnded: {
@@ -9401,9 +8108,9 @@ ${amount} para ${merchant} - ${date}`,
             title: 'Tu plan',
             exploreAllPlans: 'Explorar todos los planes',
             customPricing: 'Precios personalizados',
-            asLowAs: (price) => `desde ${price} por miembro activo/mes`,
-            pricePerMemberMonth: (price) => `${price} por miembro/mes`,
-            pricePerMemberPerMonth: (price) => `${price} por miembro por mes`,
+            asLowAs: ({price}) => `desde ${price} por miembro activo/mes`,
+            pricePerMemberMonth: ({price}) => `${price} por miembro/mes`,
+            pricePerMemberPerMonth: ({price}) => `${price} por miembro por mes`,
             perMemberMonth: 'por miembro/mes',
             collect: {
                 title: 'Recopilar',
@@ -9448,7 +8155,6 @@ ${amount} para ${merchant} - ${date}`,
         details: {
             title: 'Datos de suscripción',
             annual: 'Suscripción anual',
-            creditBalance: 'Saldo de crédito',
             taxExempt: 'Solicitar estado de exención de impuestos',
             taxExemptEnabled: 'Exento de impuestos',
             taxExemptStatus: 'Estado de exención de impuestos',
@@ -9466,10 +8172,10 @@ ${amount} para ${merchant} - ${date}`,
             note: 'Nota: Un miembro activo es cualquiera que haya creado, editado, enviado, aprobado, reembolsado, o exportado datos de gastos vinculados al espacio de trabajo de tu empresa.',
             confirmDetails: 'Confirma los datos de tu nueva suscripción anual:',
             subscriptionSize: 'Tamaño de suscripción',
-            activeMembers: (size) => `${size} miembros activos/mes`,
+            activeMembers: ({size}) => `${size} miembros activos/mes`,
             subscriptionRenews: 'Renovación de la suscripción',
             youCantDowngrade: 'No puedes bajar de categoría durante tu suscripción anual.',
-            youAlreadyCommitted: (size, date) =>
+            youAlreadyCommitted: ({size, date}) =>
                 `Ya se ha comprometido a un tamaño de suscripción anual de ${size} miembros activos al mes hasta el ${date}. Puede cambiar a una suscripción de pago por uso en ${date} desactivando la auto-renovación.`,
             error: {
                 size: 'Por favor ingrese un tamaño de suscripción valido',
@@ -9482,50 +8188,37 @@ ${amount} para ${merchant} - ${date}`,
             security: 'Expensify es PCI-DSS obediente, utiliza cifrado a nivel bancario, y emplea infraestructura redundante para proteger tus datos.',
             learnMoreAboutSecurity: 'Obtén más información sobre nuestra seguridad.',
         },
-        expensifyCode: {
-            title: 'Código Expensify',
-            discountCode: 'Código de descuento',
-            enterCode: 'Introduce un código Expensify para aplicarlo a tu suscripción.',
-            discountMessage: (promoDiscount: string, validBillingCycles: string) =>
-                `Obtendrás un ${promoDiscount}% de descuento en tus próximos ${validBillingCycles ? `${validBillingCycles} ` : ''}cargos de facturación.`,
-            apply: 'Aplicar',
-            error: {
-                invalid: 'Este código no es válido',
-            },
-        },
         subscriptionSettings: {
             title: 'Configuración de suscripción',
-            summary: (subscriptionType, subscriptionSize, expensifyCode, autoRenew, autoIncrease) =>
-                `Tipo de suscripción: ${subscriptionType}, Tamaño de suscripción: ${subscriptionSize}${expensifyCode ? `, Código Expensify: ${expensifyCode}` : ''}, Renovación automática: ${autoRenew}, Aumento automático de asientos anuales: ${autoIncrease}`,
+            summary: ({subscriptionType, subscriptionSize, autoRenew, autoIncrease}) =>
+                `Tipo de suscripción: ${subscriptionType}, Tamaño de suscripción: ${subscriptionSize}, Renovación automática: ${autoRenew}, Aumento automático de asientos anuales: ${autoIncrease}`,
             none: 'ninguno',
             on: 'activado',
             off: 'desactivado',
             annual: 'Anual',
             autoRenew: 'Auto-renovación',
             autoIncrease: 'Auto-incremento',
-            saveUpTo: (amountWithCurrency) => `Ahorre hasta ${amountWithCurrency} al mes por miembro activo`,
+            saveUpTo: ({amountWithCurrency}) => `Ahorre hasta ${amountWithCurrency} al mes por miembro activo`,
             automaticallyIncrease:
                 'Aumenta automáticamente tus plazas anuales para dar lugar a los miembros activos que superen el tamaño de tu suscripción. Nota: Esto ampliará la fecha de finalización de tu suscripción anual.',
             disableAutoRenew: 'Desactivar auto-renovación',
             helpUsImprove: 'Ayúdanos a mejorar Expensify',
             whatsMainReason: '¿Cuál es la razón principal por la que deseas desactivar la auto-renovación?',
-            renewsOn: (date) => `Se renovará el ${date}.`,
+            renewsOn: ({date}) => `Se renovará el ${date}.`,
             pricingConfiguration: 'El precio depende de la configuración. Para obtener el precio más bajo, elige una suscripción anual y obtén la Tarjeta Expensify.',
-            learnMore: (hasAdminsRoom) =>
+            learnMore: ({hasAdminsRoom}) =>
                 `<muted-text>Obtén más información en nuestra <a href="${CONST.PRICING}">página de precios</a> o chatea con nuestro equipo en tu ${hasAdminsRoom ? `<a href="adminsRoom">sala #admins.</a>` : '#admins room.'}</muted-text>`,
             estimatedPrice: 'Precio estimado',
             changesBasedOn: 'Esto varía según el uso de tu Tarjeta Expensify y las opciones de suscripción que elijas a continuación.',
-            collectBillingDescription: 'Los espacios de trabajo del plan Collect se facturan mensualmente por miembro, sin compromiso anual.',
-            pricing: 'Precios',
         },
-        cancelSubscription: {
-            title: 'Cancelar suscripción',
-            subtitle: '¿Cuál es la razón principal por la que solicitas cancelar tu suscripción?',
+        requestEarlyCancellation: {
+            title: 'Solicitar cancelación anticipada',
+            subtitle: '¿Cuál es la razón principal por la que solicitas la cancelación anticipada?',
             subscriptionCanceled: {
                 title: 'Suscripción cancelada',
                 subtitle: 'Tu suscripción anual ha sido cancelada.',
                 info: 'Ya puedes seguir utilizando tu(s) espacio(s) de trabajo en la modalidad de pago por uso.',
-                preventFutureActivity: (workspacesListRoute) =>
+                preventFutureActivity: ({workspacesListRoute}) =>
                     `Si quieres evitar actividad y cargos futuros, debes <a href="${workspacesListRoute}">eliminar tu(s) espacio(s) de trabajo.</a> Ten en cuenta que cuando elimines tu(s) espacio(s) de trabajo, se te cobrará cualquier actividad pendienteque se haya incurrido durante el mes en curso.`,
             },
             requestSubmitted: {
@@ -9533,7 +8226,7 @@ ${amount} para ${merchant} - ${date}`,
                 subtitle:
                     'Gracias por hacernos saber que deseas cancelar tu suscripción. Estamos revisando tu solicitud y nos comunicaremos contigo en breve a través de tu chat con <concierge-link>Concierge</concierge-link>.',
             },
-            acknowledgement: `Al solicitar la cancelación, reconozco y acepto que Expensify no tiene ninguna obligación de conceder dicha solicitud en virtud de las <a href=${CONST.OLD_DOT_PUBLIC_URLS.TERMS_URL}>Condiciones de Servicio</a> de Expensify u otro acuerdo de servicios aplicable entre Expensify y yo, y que Expensify se reserva el derecho exclusivo a conceder dicha solicitud.`,
+            acknowledgement: `Al solicitar la cancelación anticipada, reconozco y acepto que Expensify no tiene ninguna obligación de conceder dicha solicitud en virtud de las <a href=${CONST.OLD_DOT_PUBLIC_URLS.TERMS_URL}>Condiciones de Servicio</a> de Expensify u otro acuerdo de servicios aplicable entre Expensify y yo, y que Expensify se reserva el derecho exclusivo a conceder dicha solicitud.`,
         },
     },
     feedbackSurvey: {
@@ -9552,14 +8245,11 @@ ${amount} para ${merchant} - ${date}`,
     },
     delegate: {
         switchAccount: 'Cambiar de cuenta:',
-        switch: 'Cambiar',
-        copilot: 'Copiloto',
         copilotDelegatedAccess: 'Copilot: Acceso delegado',
         copilotDelegatedAccessDescription: 'Permitir que otros miembros accedan a tu cuenta.',
-        learnMoreAboutDelegatedAccess: 'Más información sobre acceso delegado',
-        addCopilot: 'Añade un copiloto',
+        addCopilot: 'Agregar copiloto',
         membersCanAccessYourAccount: 'Estos miembros pueden acceder a tu cuenta:',
-        youCanAccessTheseAccounts: 'Puedes acceder a estas cuentas:',
+        youCanAccessTheseAccounts: 'Puedes acceder a estas cuentas a través del conmutador de cuentas:',
         role: ({role} = {}) => {
             switch (role) {
                 case CONST.DELEGATE_ROLE.ALL:
@@ -9675,7 +8365,6 @@ ${amount} para ${merchant} - ${date}`,
             theresWasAProblemDuringAWorkspaceConnectionSync: 'Hubo un problema durante la sincronización de la conexión del espacio de trabajo',
             theresAProblemWithYourWallet: 'Hay un problema con tu billetera',
             theresAProblemWithYourWalletTerms: 'Hay un problema con los términos de tu billetera',
-            aBankAccountIsLocked: 'Una cuenta bancaria está bloqueada',
         },
     },
     emptySearchView: {
@@ -9693,13 +8382,20 @@ ${amount} para ${merchant} - ${date}`,
         },
     },
     productTrainingTooltip: {
+        // TODO: CONCIERGE_LHN_GBR tooltip will be replaced by a tooltip in the #admins room
+        // https://github.com/Expensify/App/issues/57045#issuecomment-2701455668
         conciergeLHNGBR: '<tooltip>¡Comienza <strong>aquí</strong>!</tooltip>',
         saveSearchTooltip: '<tooltip><strong>Renombra tus búsquedas guardadas</strong> aquí</tooltip>',
         accountSwitcher: '<tooltip>Accede a tus <strong>cuentas copiloto</strong> aquí</tooltip>',
+        scanTestTooltip: {
+            main: '<tooltip>¡<strong>Escanea nuestro recibo de prueba</strong> para ver cómo funciona!</tooltip>',
+            manager: '<tooltip>¡Elige a <strong>nuestro gerente</strong> de prueba para probarlo!</tooltip>',
+            confirmation: '<tooltip>Ahora, <strong>envía tu gasto y</strong>\n¡observa cómo ocurre la magia!</tooltip>',
+            tryItOut: 'Prueba esto',
+        },
         outstandingFilter: '<tooltip>Filtra los gastos\nque <strong>necesitan aprobación</strong></tooltip>',
         scanTestDriveTooltip: '<tooltip>¡Envía este recibo para\n<strong>completar la prueba</strong>!</tooltip>',
         gpsTooltip: '<tooltip>¡Seguimiento por GPS en curso! Cuando termines, detén el seguimiento a continuación.</tooltip>',
-        hasFilterNegation: '<tooltip>Busca gastos sin recibos usando <strong>-has:receipt</strong>.</tooltip>',
     },
     discardChangesConfirmation: {
         title: '¿Descartar cambios?',
@@ -9715,7 +8411,7 @@ ${amount} para ${merchant} - ${date}`,
         confirmation: {
             title: 'Confirmar llamada',
             description: 'Asegúrate de que los detalles a continuación sean correctos. Una vez que confirmes la llamada, enviaremos una invitación con más información.',
-            setupSpecialist: 'Tu ejecutivo de cuenta',
+            setupSpecialist: 'Tu especialista asignado',
             meetingLength: 'Duración de la reunión',
             dateTime: 'Fecha y hora',
             minutes: '30 minutos',
@@ -9761,20 +8457,6 @@ ${amount} para ${merchant} - ${date}`,
         exportInProgress: 'Exportación en curso',
         conciergeWillSend: 'Concierge te enviará el archivo en breve.',
     },
-    exportDownload: {
-        preparingTitle: 'Preparando descarga...',
-        preparingBody: 'Puedes esperar a que termine la descarga o Concierge puede enviártelo por chat.',
-        sendFromConcierge: 'Envíame el archivo cuando esté listo',
-        conciergeTitle: '¡Por supuesto!',
-        conciergeBody: 'Concierge te enviará un mensaje cuando el archivo esté listo.',
-        goToConcierge: 'Ir a Concierge',
-        dismiss: 'Descartar',
-        readyTitle: '¡Tu archivo está listo!',
-        readyBody: 'Si no se descargó automáticamente, usa el botón de abajo.',
-        downloadFile: 'Descargar archivo',
-        failedTitle: 'Exportación fallida',
-        close: 'Cerrar',
-    },
     openAppFailureModal: {
         title: 'Algo salió mal...',
         subtitle: `No hemos podido cargar todos sus datos. Hemos sido notificados y estamos investigando el problema. Si esto persiste, por favor comuníquese con`,
@@ -9814,7 +8496,7 @@ ${amount} para ${merchant} - ${date}`,
         goToDomain: 'Ir al dominio',
         samlLogin: {
             title: 'Inicio de sesión SAML',
-            subtitle: `<muted-text>Configura el inicio de sesión de los miembros con <a href="${CONST.SAML_HELP_URL}">Inicio de sesión único SAML (SSO)</a>.</muted-text>`,
+            subtitle: `<muted-text>Configura el inicio de sesión de los miembros con <a href="${CONST.SAML_HELP_URL}">Inicio de sesión único SAML (SSO).</a></muted-text>`,
             enableSamlLogin: 'Habilitar inicio de sesión SAML',
             allowMembers: 'Permitir que los miembros inicien sesión con SAML.',
             requireSamlLogin: 'Requerir inicio de sesión SAML',
@@ -9824,8 +8506,6 @@ ${amount} para ${merchant} - ${date}`,
             disableSamlRequired: 'Deshabilitar requisito de SAML',
             oktaWarningPrompt: '¿Estás seguro? Esto también deshabilitará Okta SCIM.',
             requireWithEmptyMetadataError: 'Por favor, añade los metadatos del Proveedor de Identidad a continuación para habilitar',
-            pleaseDisableTwoFactorAuth: (twoFactorAuthSettingsUrl: string) =>
-                `<muted-text>Por favor, deshabilita <a href="${twoFactorAuthSettingsUrl}">forzar la autenticación de dos factores</a> para habilitar el inicio de sesión con SAML.</muted-text>`,
         },
         samlConfigurationDetails: {
             title: 'Detalles de configuración de SAML',
@@ -9874,6 +8554,7 @@ ${amount} para ${merchant} - ${date}`,
             primaryContact: 'Contacto principal',
             addPrimaryContact: 'Añadir contacto principal',
             setPrimaryContactError: 'No se pudo establecer el contacto principal. Por favor, inténtalo de nuevo más tarde.',
+            settings: 'Configuración',
             consolidatedDomainBilling: 'Facturación consolidada del dominio',
             consolidatedDomainBillingDescription: (domainName: string) =>
                 `<comment><muted-text-label>Cuando está habilitada, el contacto principal pagará todos los espacios de trabajo de los miembros de <strong>${domainName}</strong> y recibirá todos los recibos de facturación.</muted-text-label></comment>`,
@@ -9890,115 +8571,28 @@ ${amount} para ${merchant} - ${date}`,
             resetDomain: 'Restablecer dominio',
             resetDomainExplanation: ({domainName}: {domainName?: string}) => `Por favor escribe <strong>${domainName}</strong> para confirmar el restablecimiento del dominio.`,
             enterDomainName: 'Introduce aquí tu nombre de dominio',
-            resetDomainInfo: `Esta acción es <strong>permanente</strong> y se eliminarán los siguientes datos: <br/> <bullet-list><bullet-item>Conexiones de tarjeta corporativa y cualquier gasto no reportado de esas tarjetas</bullet-item><bullet-item>Configuración de SAML y grupos</bullet-item><bullet-item>Datos de viaje y acceso a Expensify Travel</bullet-item></bullet-list> Todas las cuentas, espacios de trabajo, informes, gastos y otros datos se conservarán. <br/><br/>Nota: Puedes eliminar este dominio de tu lista de dominios eliminando el correo electrónico asociado de tus <a href="#">métodos de contacto</a>.`,
+            resetDomainInfo: `Esta acción es <strong>permanente</strong> y se eliminarán los siguientes datos: <br/> <ul><li>Conexiones de tarjeta corporativa y cualquier gasto no reportado de esas tarjetas</li> <li>Configuración de SAML y grupos</li> </ul> Todas las cuentas, espacios de trabajo, informes, gastos y otros datos se conservarán. <br/><br/>Nota: Puedes eliminar este dominio de tu lista de dominios eliminando el correo electrónico asociado de tus <a href="#">métodos de contacto</a>.`,
         },
         domainMembers: 'Miembros del dominio',
         members: {
             title: 'Miembros',
             findMember: 'Buscar miembro',
             addMember: 'Añadir miembro',
-            emptyMembers: {
-                title: 'No hay miembros en este grupo',
-                subtitle: 'Añade un miembro o intenta cambiar el filtro de arriba.',
-            },
-            allMembers: 'Todos los miembros',
             email: 'Dirección de correo electrónico',
-            closeAccount: () => ({
-                one: 'Cerrar cuenta',
-                other: 'Cerrar cuentas',
-            }),
+            closeAccount: 'Cerrar cuenta',
             closeAccountPrompt: '¿Estás seguro? Esta acción es permanente.',
-            forceCloseAccount: () => ({
-                one: 'Forzar cierre de cuenta',
-                other: 'Forzar cierre de cuentas',
-            }),
-            safeCloseAccount: () => ({
-                one: 'Cierre seguro de cuenta',
-                other: 'Cierre seguro de cuentas',
-            }),
-            closeAccountInfo: () => ({
-                one: 'Recomendamos cerrar la cuenta de forma segura para omitir el cierre si hay: <bullet-list><bullet-item>Aprobaciones pendientes</bullet-item><bullet-item>Reembolsos en curso</bullet-item><bullet-item>No hay otro método de inicio de sesión</bullet-item></bullet-list>De lo contrario, puedes ignorar las precauciones de seguridad anteriores y forzar el cierre de la cuenta seleccionada.',
-                other: 'Recomendamos cerrar las cuentas de forma segura para omitir el cierre si hay: <bullet-list><bullet-item>Aprobaciones pendientes</bullet-item><bullet-item>Reembolsos en curso</bullet-item><bullet-item>No hay otro método de inicio de sesión</bullet-item></bullet-list>De lo contrario, puedes ignorar las precauciones de seguridad anteriores y forzar el cierre de las cuentas seleccionadas.',
-            }),
+            forceCloseAccount: 'Forzar cierre de cuenta',
+            safeCloseAccount: 'Cierre seguro de cuenta',
+            closeAccountInfo:
+                'Recomendamos cerrar la cuenta de forma segura para omitir el cierre si hay: <ul><li>Aprobaciones pendientes</li><li>Reembolsos en curso</li><li>No hay otro método de inicio de sesión</li></ul>De lo contrario, puedes ignorar las precauciones de seguridad anteriores y forzar el cierre de las cuentas seleccionadas.',
             error: {
                 removeMember: 'No se pudo eliminar a este usuario. Por favor, inténtalo de nuevo.',
                 addMember: 'No se pudo añadir este miembro. Por favor, inténtalo de nuevo.',
-                vacationDelegate: 'No se pudo establecer a este usuario como delegado de vacaciones. Por favor, inténtalo de nuevo.',
-                moveMember: 'No se pudo mover este miembro. Por favor, inténtalo de nuevo.',
-                moveMemberNotPolicyAdmin:
-                    'No se puede mover al miembro al grupo de dominio. Debes ser Administrador de Políticas para la Política Preferida establecida en el grupo de dominio al que intentas mover a este usuario.',
-            },
-            cannotSetVacationDelegateForMember: (email: string) =>
-                `No puedes establecer un delegado de vacaciones para ${email} porque actualmente es el delegado de los siguientes miembros:`,
-            reportSuspiciousActivityPrompt: (email: string) =>
-                `¿Estás seguro? Esto bloqueará la cuenta de <strong>${email}</strong>. <br /><br /> Nuestro equipo revisará la cuenta y eliminará cualquier acceso no autorizado. Para recuperar el acceso, deberá comunicarse con Concierge.`,
-            reportSuspiciousActivityConfirmationPrompt:
-                'Revisaremos la cuenta para verificar que sea seguro desbloquearla y nos comunicaremos a través de Concierge si tenemos alguna pregunta.',
-            moveToGroup: 'Mover al grupo',
-            domainGroup: 'Grupo de dominio',
-            chooseWhereToMove: ({count}: {count: number}) => `Elige a dónde mover ${count} ${count === 1 ? 'miembro' : 'miembros'}.`,
-            chooseWhereToMoveName: ({name}: {name: string}) => `Elige a dónde mover a ${name}.`,
-            membersFeatureList: {
-                subtitle: ({domainName}: {domainName: string}) =>
-                    `<muted-text>Verifica tu dominio para tener más control sobre los miembros de <strong>${domainName}</strong> en Expensify.</muted-text>`,
-                controlPolicyCreation: 'Restringir la creación de espacios de trabajo',
-                enableSamlSso: 'Habilitar SSO SAML',
-                enforce2FA: 'Forzar 2FA',
             },
         },
-        common: {
-            settings: 'Configuración',
-            forceTwoFactorAuth: 'Forzar la autenticación de dos factores',
-            forceTwoFactorAuthSAMLEnabledDescription: (samlPageUrl: string) =>
-                `<muted-text>Por favor, deshabilita <a href="${samlPageUrl}">SAML</a> para forzar la autenticación de dos factores.</muted-text>`,
-            forceTwoFactorAuthDescription: `<muted-text>Requiere la autenticación de dos factores para todos los miembros de este dominio. Se les pedirá a los miembros del dominio que configuren la autenticación de dos factores en su cuenta cuando inicien sesión.</muted-text>`,
-            forceTwoFactorAuthError: 'No se pudo cambiar la autenticación de dos factores forzada. Por favor, inténtalo de nuevo más tarde.',
-            resetTwoFactorAuth: 'Restablecer la autenticación de dos factores',
-            error: 'No se pudo guardar este cambio. Por favor, inténtalo de nuevo.',
-        },
-        groups: {
-            title: 'Grupos',
-            memberCount: () => {
-                return {
-                    one: '1 miembro',
-                    other: (count: number) => `${count} miembros`,
-                };
-            },
-            defaultGroup: 'Grupo predeterminado para nuevos miembros',
-            defaultGroupPrompt: (currentName, newName) =>
-                `¿Estás seguro de que quieres establecer ${newName} como el grupo predeterminado? Los nuevos miembros serán invitados a este grupo en lugar del grupo predeterminado anterior (${currentName}). `,
-            makeDefault: 'Establecer como predeterminado',
-            neverMind: 'No importa',
-            createGroupError: 'No se pudo crear este grupo. Inténtalo de nuevo.',
-            permissions: 'Permisos de grupo',
-            createNewGroupButton: 'Nuevo grupo',
-            createGroupSubmitButton: 'Crear grupo',
-            expensifyCardPreferredWorkspace: 'Espacio de trabajo preferido para Expensify Card',
-            expensifyCardPreferredWorkspaceDescription:
-                'Todas las transacciones de Expensify Card se crearán en el espacio de trabajo preferido de Expensify Card en lugar del espacio de trabajo preferido. Al habilitar esta función, la configuración de espacio de trabajo preferido se aplicará solo a las transacciones de Expensify Card.',
-            strictlyEnforceWorkspaceRules: 'Hacer cumplir estrictamente las reglas del espacio de trabajo',
-            strictlyEnforceWorkspaceRulesDescription: 'Todas las reglas del espacio de trabajo deben cumplirse antes de enviar un informe. No se permiten excepciones manuales.',
-            restrictExpenseWorkspaceCreation: 'Restringir la creación/eliminación de espacios de trabajo de gastos',
-            restrictExpenseWorkspaceCreationDescription:
-                'Evita que los miembros creen un espacio de trabajo de gastos o se eliminen a sí mismos de uno. Esto, cuando se combina con la aplicación estricta de espacios de trabajo, es útil para evitar que se utilice Expensify para enviar informes destinados a usarse fuera de tu dominio.',
-            deleteGroup: 'Eliminar grupo',
-            deleteGroupDangerConfirmationModal: 'Eliminar grupo',
-            deleteGroupDangerConfirmationModalDescription: (defaultGroupName: string) =>
-                `¿Estás seguro? Esto reasignará a todos los miembros al grupo predeterminado (${defaultGroupName}) y no se puede deshacer.`,
-            deleteGroupError: 'No se pudo eliminar este grupo. Por favor, inténtalo de nuevo.',
-            preferredWorkspace: 'Espacio de trabajo preferido',
-            preferredWorkspaceDescription: (enabled) =>
-                `Todos los nuevos informes y gastos se crearán en ${enabled ? 'el espacio de trabajo preferido seleccionado' : 'este espacio de trabajo'}.`,
-            preferredWorkspaceSelectDescription: 'Todos los nuevos gastos e informes se crearán en este espacio de trabajo.',
-            noWorkspacesMessage: 'No hay espacios de trabajo en este dominio. Se requiere un espacio de trabajo para habilitar esta restricción.',
-            restrictDefaultLoginSelection: 'Restringir el inicio de sesión predeterminado',
-            restrictDefaultLoginSelectionDescription: 'Evita que los miembros cambien su correo de inicio de sesión fuera del dominio de la empresa para eludir restricciones de políticas.',
-            expensifyCardPreferredWorkspaceDisabledMessage:
-                'Para habilitar esta configuración, primero habilita un espacio de trabajo preferido y configura las Tarjetas Expensify en tu dominio.',
-            findGroup: 'Encontrar grupo',
-        },
     },
     gps: {
+        disclaimer: 'Utiliza el GPS para crear un gasto a partir de tu trayecto. Toca Iniciar a continuación para comenzar el seguimiento.',
         error: {
             failedToStart: 'No se pudo iniciar el seguimiento de la ubicación.',
             failedToGetPermissions: 'No se pudieron obtener los permisos de ubicación necesarios.',
@@ -10007,9 +8601,13 @@ ${amount} para ${merchant} - ${date}`,
         stopped: 'Detenido',
         start: 'Iniciar',
         stop: 'Detener',
-        save: 'Guardar',
-        resume: 'Reanudar',
         discard: 'Descartar',
+        stopGpsTrackingModal: {
+            title: 'Detener seguimiento por GPS',
+            prompt: '¿Estás seguro? Esto finalizará tu trayecto actual.',
+            cancel: 'Reanudar seguimiento',
+            confirm: 'Detener seguimiento por GPS',
+        },
         discardDistanceTrackingModal: {
             title: 'Descartar seguimiento de distancia',
             prompt: '¿Estás seguro? Esto descartará tu trayecto actual y no se puede deshacer.',
@@ -10057,23 +8655,13 @@ ${amount} para ${merchant} - ${date}`,
             prompt: '¿Seguro que quieres detener el seguimiento por GPS y cambiar a Expensify Classic?',
             confirm: 'Detener y cambiar',
         },
-        switchAccountWarningTripInProgress: {
-            title: 'Seguimiento GPS en curso',
-            prompt: '¿Seguro que quieres detener el seguimiento GPS y cambiar de cuenta?',
-            confirm: 'Detener y cambiar',
-        },
         locationServicesRequiredModal: {
             title: 'Se requiere acceso a la ubicación',
             confirm: 'Abrir ajustes',
             prompt: 'Por favor, permite el acceso a la ubicación en los ajustes de tu dispositivo para iniciar el seguimiento de distancia por GPS.',
         },
-        gpsFloatingPillText: 'Seguimiento GPS en curso...',
-        liveActivity: {
-            subtitle: 'Seguimiento de distancia',
-            button: 'Ver progreso',
-            lockScreenBadgeText: 'Distancia',
-            lockScreenTrackingText: 'Siguiendo...',
-        },
+        fabGpsTripExplained: 'Ir a la pantalla de GPS (Acción flotante)',
     },
 };
+
 export default translations;
diff --git a/src/languages/fr.ts b/src/languages/fr.ts
index f8551557c51b..31f92dde1e62 100644
--- a/src/languages/fr.ts
+++ b/src/languages/fr.ts
@@ -11,52 +11,189 @@
  */
 import {CONST as COMMON_CONST} from 'expensify-common';
 import startCase from 'lodash/startCase';
-import type {ValueOf} from 'type-fest';
 import type {OnboardingTask} from '@libs/actions/Welcome/OnboardingFlow';
 import StringUtils from '@libs/StringUtils';
 import dedent from '@libs/StringUtils/dedent';
 import CONST from '@src/CONST';
 import type {Country} from '@src/CONST';
 import type OriginalMessage from '@src/types/onyx/OriginalMessage';
-import type {OriginalMessageSettlementAccountLocked, PersonalRulesModifiedFields, PolicyRulesModifiedFields} from '@src/types/onyx/OriginalMessage';
+import type {OriginalMessageSettlementAccountLocked, PolicyRulesModifiedFields} from '@src/types/onyx/OriginalMessage';
+import ObjectUtils from '@src/types/utils/ObjectUtils';
 import type en from './en';
 import type {
+    AddBudgetParams,
+    AddedOrDeletedPolicyReportFieldParams,
+    AddOrDeletePolicyCustomUnitRateParams,
     ChangeFieldParams,
-    ConciergeBrokenCardConnectionParams,
     ConnectionNameParams,
+    CreatedReportForUnapprovedTransactionsParams,
     DelegateRoleParams,
     DeleteActionParams,
+    DeleteBudgetParams,
     DeleteConfirmationParams,
     EditActionParams,
     ExportAgainModalDescriptionParams,
     ExportIntegrationSelectedParams,
+    ImportPolicyCustomUnitRatesParams,
     IntacctMappingTitleParams,
     InvalidPropertyParams,
     InvalidValueParams,
     MarkReimbursedFromIntegrationParams,
     MissingPropertyParams,
     MovedFromPersonalSpaceParams,
+    MultifactorAuthenticationTranslationParams,
+    NextStepParams,
     NotAllowedExtensionParams,
     OptionalParam,
     PaidElsewhereParams,
     ParentNavigationSummaryParams,
     RemovedFromApprovalWorkflowParams,
+    RemovedPolicyCustomUnitSubRateParams,
     ReportArchiveReasonsClosedParams,
     ReportArchiveReasonsInvoiceReceiverPolicyDeletedParams,
     ReportArchiveReasonsMergedParams,
     ReportArchiveReasonsRemovedFromPolicyParams,
+    ReportFieldParams,
+    ReportPolicyNameParams,
+    RequestAmountParams,
+    RequiredFieldParams,
     ResolutionConstraintsParams,
+    ReviewParams,
+    RoleNamesParams,
+    RoomNameReservedErrorParams,
+    RoomRenamedToParams,
+    RoutedDueToDEWParams,
+    RulesEnableWorkflowsParams,
+    SecondaryLoginParams,
+    SetTheDistanceMerchantParams,
+    SetTheRequestParams,
+    SettledAfterAddedBankAccountParams,
+    SettleExpensifyCardParams,
+    SettlementAccountInfoParams,
+    SettlementAccountReconciliationParams,
+    SettlementDateParams,
     ShareParams,
+    SignerInfoMessageParams,
+    SignUpNewFaceCodeParams,
     SizeExceededParams,
+    SplitAmountParams,
+    SplitDateRangeParams,
+    SplitExpenseEditTitleParams,
+    SplitExpenseSubtitleParams,
+    StatementTitleParams,
     StepCounterParams,
+    StripePaidParams,
+    SubmitsToParams,
+    SubmittedToVacationDelegateParams,
+    SubmittedWithMemoParams,
+    SubscriptionCommitmentParams,
+    SubscriptionSettingsLearnMoreParams,
+    SubscriptionSettingsRenewsOnParams,
+    SubscriptionSettingsSaveUpToParams,
+    SubscriptionSettingsSummaryParams,
+    SubscriptionSizeParams,
     SyncStageNameConnectionsParams,
+    TaskCreatedActionParams,
+    TaxAmountParams,
+    TermsParams,
+    ThreadRequestReportNameParams,
+    ThreadSentMoneyReportNameParams,
+    ToggleImportTitleParams,
+    TotalAmountGreaterOrLessThanOriginalParams,
+    ToValidateLoginParams,
+    TransferParams,
+    TravelTypeParams,
+    TrialStartedTitleParams,
+    UnapproveWithIntegrationWarningParams,
     UnshareParams,
-    UnsupportedFormulaValueErrorParams,
+    UntilTimeParams,
+    UpdatedBudgetParams,
+    UpdatedCustomFieldParams,
+    UpdatedPolicyApprovalRuleParams,
+    UpdatedPolicyAuditRateParams,
+    UpdatedPolicyAutoHarvestingParams,
+    UpdatedPolicyBudgetNotificationParams,
+    UpdatedPolicyCategoriesParams,
+    UpdatedPolicyCategoryDescriptionHintTypeParams,
+    UpdatedPolicyCategoryExpenseLimitTypeParams,
+    UpdatedPolicyCategoryGLCodeParams,
+    UpdatedPolicyCategoryMaxAmountNoReceiptParams,
+    UpdatedPolicyCategoryMaxExpenseAmountParams,
+    UpdatedPolicyCategoryNameParams,
+    UpdatedPolicyCategoryParams,
+    UpdatedPolicyCurrencyParams,
+    UpdatedPolicyCustomUnitRateEnabledParams,
+    UpdatedPolicyCustomUnitRateParams,
+    UpdatedPolicyCustomUnitSubRateParams,
+    UpdatedPolicyCustomUnitTaxClaimablePercentageParams,
+    UpdatedPolicyCustomUnitTaxRateExternalIDParams,
+    UpdatedPolicyDefaultTitleParams,
+    UpdatedPolicyDescriptionParams,
+    UpdatedPolicyFieldWithNewAndOldValueParams,
+    UpdatedPolicyFieldWithValueParams,
+    UpdatedPolicyFrequencyParams,
+    UpdatedPolicyManualApprovalThresholdParams,
+    UpdatedPolicyOwnershipParams,
+    UpdatedPolicyPreventSelfApprovalParams,
+    UpdatedPolicyReimbursementChoiceParams,
+    UpdatedPolicyReimbursementEnabledParams,
+    UpdatedPolicyReimburserParams,
+    UpdatedPolicyReportFieldDefaultValueParams,
+    UpdatedPolicyTagFieldParams,
+    UpdatedPolicyTagListParams,
+    UpdatedPolicyTagListRequiredParams,
+    UpdatedPolicyTagNameParams,
+    UpdatedPolicyTagParams,
+    UpdatedPolicyTaxParams,
+    UpdatedPolicyTimeEnabledParams,
+    UpdatedPolicyTimeRateParams,
+    UpdatedTheDistanceMerchantParams,
+    UpdatedTheRequestParams,
+    UpdatePolicyCustomUnitDefaultCategoryParams,
+    UpdatePolicyCustomUnitParams,
+    UpdatePolicyCustomUnitTaxEnabledParams,
     UpdateRoleParams,
-    ViolationsIncreasedDistanceParams,
+    UpgradeSuccessMessageParams,
+    UsePlusButtonParams,
+    UserIsAlreadyMemberParams,
+    UserSplitParams,
+    VacationDelegateParams,
+    ViolationsCashExpenseWithNoReceiptParams,
+    ViolationsConversionSurchargeParams,
+    ViolationsCustomRulesParams,
+    ViolationsInvoiceMarkupParams,
+    ViolationsMaxAgeParams,
+    ViolationsMissingTagParams,
     ViolationsModifiedAmountParams,
+    ViolationsOverCategoryLimitParams,
+    ViolationsOverLimitParams,
+    ViolationsPerDayLimitParams,
+    ViolationsProhibitedExpenseParams,
+    ViolationsReceiptRequiredParams,
+    ViolationsRterParams,
+    ViolationsTagOutOfPolicyParams,
+    ViolationsTaxOutOfPolicyParams,
+    WaitingOnBankAccountParams,
+    WalletAgreementParams,
+    WalletProgramParams,
+    WelcomeEnterMagicCodeParams,
+    WelcomeToRoomParams,
+    WeSentYouMagicSignInLinkParams,
+    WorkEmailMergingBlockedParams,
+    WorkEmailResendCodeParams,
+    WorkflowSettingsParam,
     WorkspaceLockedPlanTypeParams,
+    WorkspaceMemberList,
+    WorkspaceMembersCountParams,
+    WorkspaceOwnerWillNeedToAddOrUpdatePaymentCardParams,
+    WorkspaceRouteParams,
+    WorkspaceShareNoteParams,
+    WorkspacesListRouteParams,
+    WorkspaceUpgradeNoteParams,
+    WorkspaceYouMayJoin,
     YourPlanPriceParams,
+    YourPlanPriceValueParams,
+    ZipCodeExampleFormatParams,
 } from './params';
 import type {TranslationDeepObject} from './types';
 
@@ -90,10 +227,8 @@ const translations: TranslationDeepObject<typeof en> = {
         optional: 'Facultatif',
         new: 'Nouveau',
         newFeature: 'Nouvelle fonctionnalité',
-        beta: 'Bêta',
         search: 'Rechercher',
         reports: 'Notes de frais',
-        spend: 'Dépenses',
         find: 'Rechercher',
         searchWithThreeDots: 'Rechercher...',
         next: 'Suivant',
@@ -118,14 +253,6 @@ const translations: TranslationDeepObject<typeof en> = {
         workspaces: 'Espaces de travail',
         home: 'Accueil',
         inbox: 'Boîte de réception',
-        yourReviewIsRequired: 'Votre révision est requise',
-        actionBadge: {
-            submit: 'Soumettre',
-            approve: 'Approuver',
-            pay: 'Payer',
-            fix: 'Corriger',
-            task: 'Tâche',
-        },
         success: 'Réussi',
         group: 'Groupe',
         profile: 'Profil',
@@ -135,7 +262,7 @@ const translations: TranslationDeepObject<typeof en> = {
         wallet: 'Portefeuille',
         preferences: 'Préférences',
         view: 'Afficher',
-        review: (amount?: string) => `Examiner${amount ? ` ${amount}` : ''}`,
+        review: (reviewParams?: ReviewParams) => `Examiner${reviewParams?.amount ? ` ${reviewParams?.amount}` : ''}`,
         not: 'Non',
         signIn: 'Se connecter',
         signInWithGoogle: 'Se connecter avec Google',
@@ -146,7 +273,6 @@ const translations: TranslationDeepObject<typeof en> = {
         lastName: 'Nom de famille',
         scanning: 'Analyse en cours',
         analyzing: 'Analyse en cours...',
-        thinking: 'Concierge réfléchit...',
         addCardTermsOfService: 'Conditions d’utilisation d’Expensify',
         perPerson: 'par personne',
         phone: 'Téléphone',
@@ -208,12 +334,10 @@ const translations: TranslationDeepObject<typeof en> = {
         admin: 'Administrateur',
         owner: 'Responsable',
         dateFormat: 'AAAA-MM-JJ',
-        calendarOpened: 'calendrier ouvert',
         send: 'Envoyer',
         na: 'N/D',
         noResultsFound: 'Aucun résultat trouvé',
         noResultsFoundMatching: (searchString: string) => `Aucun résultat trouvé correspondant à « ${searchString} »`,
-        suggestionsAvailableFor: (searchString: string) => (searchString ? `Suggestions disponibles pour « ${searchString} ».` : 'Suggestions disponibles.'),
         recentDestinations: 'Destinations récentes',
         timePrefix: "C'est",
         conjunctionFor: 'pour',
@@ -224,7 +348,6 @@ const translations: TranslationDeepObject<typeof en> = {
         conjunctionTo: 'à',
         genericErrorMessage: 'Oups... une erreur s’est produite et votre requête n’a pas pu être effectuée. Veuillez réessayer plus tard.',
         percentage: 'Pourcentage',
-        progressBarLabel: "Progression de l'intégration",
         converted: 'Converti',
         error: {
             invalidAmount: 'Montant invalide',
@@ -263,7 +386,6 @@ const translations: TranslationDeepObject<typeof en> = {
         reset: 'Réinitialiser',
         done: 'Terminé',
         more: 'Plus',
-        other: 'Autre',
         debitCard: 'Carte de débit',
         bankAccount: 'Compte bancaire',
         personalBankAccount: 'Compte bancaire personnel',
@@ -289,7 +411,7 @@ const translations: TranslationDeepObject<typeof en> = {
         verify: 'Vérifier',
         yesContinue: 'Oui, continuer',
         websiteExample: 'p. ex. https://www.expensify.com',
-        zipCodeExampleFormat: (zipSampleFormat: string) => (zipSampleFormat ? `par ex. ${zipSampleFormat}` : ''),
+        zipCodeExampleFormat: ({zipSampleFormat}: ZipCodeExampleFormatParams) => (zipSampleFormat ? `par ex. ${zipSampleFormat}` : ''),
         description: 'Description',
         title: 'Titre',
         assignee: 'Attribué',
@@ -300,8 +422,6 @@ const translations: TranslationDeepObject<typeof en> = {
         per: 'par',
         mi: 'mile',
         km: 'kilomètre',
-        milesAbbreviated: 'mi',
-        kilometersAbbreviated: 'km',
         copied: 'Copié !',
         someone: 'Quelqu’un',
         total: 'Total',
@@ -310,7 +430,6 @@ const translations: TranslationDeepObject<typeof en> = {
         letsStart: `Commençons`,
         showMore: 'Afficher plus',
         showLess: 'Afficher moins',
-        plusMore: ({count}: {count: number}) => `+${count} de plus`,
         merchant: 'Commerçant',
         change: 'Modifier',
         category: 'Catégorie',
@@ -334,11 +453,8 @@ const translations: TranslationDeepObject<typeof en> = {
         selectCurrency: 'Sélectionner une devise',
         selectSymbolOrCurrency: 'Sélectionner un symbole ou une devise',
         card: 'Carte',
-        mcc: 'MCC',
-        categoryGLCode: 'Code GL de catégorie',
         whyDoWeAskForThis: 'Pourquoi demandons-nous cela ?',
         required: 'Obligatoire',
-        automatic: 'Automatique',
         showing: 'Affichage',
         of: 'de',
         default: 'Par défaut',
@@ -346,7 +462,6 @@ const translations: TranslationDeepObject<typeof en> = {
         member: 'Membre',
         auditor: 'Auditeur',
         role: 'Rôle',
-        roleCannotBeChanged: (workflowsLinkPage: string) => `Le rôle ne peut pas être modifié car ce membre est un <a href="${workflowsLinkPage}">payeur</a> dans cet espace de travail.`,
         currency: 'Devise',
         groupCurrency: 'Devise du groupe',
         rate: 'Taux',
@@ -384,7 +499,6 @@ const translations: TranslationDeepObject<typeof en> = {
         reportID: 'ID de note de frais',
         longReportID: 'ID de note de frais longue',
         withdrawalID: 'ID de retrait',
-        withdrawalStatus: 'Statut de retrait',
         bankAccounts: 'Comptes bancaires',
         chooseFile: 'Choisir un fichier',
         chooseFiles: 'Choisir des fichiers',
@@ -419,21 +533,19 @@ const translations: TranslationDeepObject<typeof en> = {
         validate: 'Valider',
         downloadAsPDF: 'Télécharger en PDF',
         downloadAsCSV: 'Télécharger au format CSV',
-        print: 'Imprimer',
         help: 'Aide',
-        collapsed: 'Réduit',
-        expanded: 'Développé',
         expenseReport: 'Note de frais',
+        expenseReports: 'Notes de frais',
         rateOutOfPolicy: 'Taux hors politique',
         leaveWorkspace: 'Quitter l’espace de travail',
         leaveWorkspaceConfirmation: 'Si vous quittez cet espace de travail, vous ne pourrez plus lui soumettre de dépenses.',
         leaveWorkspaceConfirmationAuditor: 'Si vous quittez cet espace de travail, vous ne pourrez plus voir ses notes de frais ni ses paramètres.',
         leaveWorkspaceConfirmationAdmin: 'Si vous quittez cet espace de travail, vous ne pourrez plus gérer ses paramètres.',
-        leaveWorkspaceConfirmationApprover: (workspaceOwner: string) =>
+        leaveWorkspaceConfirmationApprover: ({workspaceOwner}: {workspaceOwner: string}) =>
             `Si vous quittez cet espace de travail, vous serez remplacé dans le flux d’approbation par ${workspaceOwner}, le responsable de l’espace de travail.`,
-        leaveWorkspaceConfirmationExporter: (workspaceOwner: string) =>
+        leaveWorkspaceConfirmationExporter: ({workspaceOwner}: {workspaceOwner: string}) =>
             `Si vous quittez cet espace de travail, vous serez remplacé en tant qu’exportateur préféré par ${workspaceOwner}, le responsable de l’espace de travail.`,
-        leaveWorkspaceConfirmationTechContact: (workspaceOwner: string) =>
+        leaveWorkspaceConfirmationTechContact: ({workspaceOwner}: {workspaceOwner: string}) =>
             `Si vous quittez cet espace de travail, vous serez remplacé en tant que contact technique par ${workspaceOwner}, le responsable de l'espace de travail.`,
         leaveWorkspaceReimburser:
             'Vous ne pouvez pas quitter cet espace de travail en tant que rembourseur. Définissez un nouveau rembourseur dans Espaces de travail > Effectuer ou suivre les paiements, puis réessayez.',
@@ -442,6 +554,9 @@ const translations: TranslationDeepObject<typeof en> = {
         comments: 'Commentaires',
         sharedIn: 'Partagé dans',
         unreported: 'Non déclarée',
+        explore: 'Explorer',
+        insights: 'Analyses',
+        todo: 'À faire',
         invoice: 'Facture',
         expense: 'Dépense',
         chat: 'Discussion',
@@ -452,15 +567,12 @@ const translations: TranslationDeepObject<typeof en> = {
         on: 'Activé',
         before: 'Avant',
         after: 'Après',
-        range: 'Intervalle',
         reschedule: 'Reprogrammer',
         general: 'Général',
         workspacesTabTitle: 'Espaces de travail',
         headsUp: 'Attention !',
         submitTo: 'Soumettre à',
         forwardTo: 'Transférer à',
-        approvalLimit: "Limite d'approbation",
-        overLimitForwardTo: 'Transférer si dépassement de limite',
         merge: 'Fusionner',
         none: 'Aucun',
         unstableInternetConnection: 'Connexion Internet instable. Veuillez vérifier votre réseau et réessayer.',
@@ -481,44 +593,19 @@ const translations: TranslationDeepObject<typeof en> = {
         exchangeRate: 'Taux de change',
         reimbursableTotal: 'Total remboursable',
         nonReimbursableTotal: 'Total non remboursable',
-        opensInNewTab: 'S’ouvre dans un nouvel onglet',
         locked: 'Verrouillé',
         month: 'Mois',
         week: 'Semaine',
         year: 'Année',
         quarter: 'Trimestre',
-        vacationDelegate: 'Délégué de vacances',
-        expensifyLogo: 'Logo Expensify',
-        concierge: {greeting: 'Bonjour, comment puis-je vous aider ?', showHistory: 'Afficher l’historique'},
-        duplicateReport: 'Note de frais en double',
-        approver: 'Approbateur',
-        goToConcierge: 'Aller à Concierge',
-        allSet: 'Tout est prêt !',
-        enterDigitLabel: ({digitIndex, totalDigits}: {digitIndex: number; totalDigits: number}) => `saisir le chiffre ${digitIndex} sur ${totalDigits}`,
-        copyOfReportName: (reportName: string) => `Copie de ${reportName}`,
-        previousMonth: 'Mois précédent',
-        nextMonth: 'Le mois prochain',
-        previousYear: 'Année précédente',
-        nextYear: 'L’an prochain',
-        avatar: 'Avatar',
-        editor: 'Éditeur',
-        restrictions: 'Restrictions',
-    },
-    socials: {
-        podcast: 'Suivez-nous sur Podcast',
-        twitter: 'Suivez-nous sur Twitter',
-        instagram: 'Suivez-nous sur Instagram',
-        facebook: 'Suivez-nous sur Facebook',
-        linkedin: 'Suivez-nous sur LinkedIn',
-    },
-    concierge: {
-        collapseReasoning: 'Réduire le raisonnement',
-        expandReasoning: 'Développer le raisonnement',
-        enableNotifications: {prompt: 'Vous souhaitez être averti lorsque Concierge répond ?', cta: 'Notifier'},
     },
     supportalNoAccess: {
         title: 'Pas si vite',
-        descriptionWithCommand: (command?: string) =>
+        descriptionWithCommand: ({
+            command,
+        }: {
+            command?: string;
+        } = {}) =>
             `Vous n’êtes pas autorisé à effectuer cette action lorsque le support est connecté (commande : ${command ?? ''}). Si vous pensez que Success devrait pouvoir effectuer cette action, veuillez démarrer une conversation dans Slack.`,
     },
     lockedAccount: {
@@ -554,7 +641,7 @@ const translations: TranslationDeepObject<typeof en> = {
         chooseDocument: 'Choisir un fichier',
         attachmentTooLarge: 'La pièce jointe est trop volumineuse',
         sizeExceeded: 'La taille de la pièce jointe dépasse la limite de 24 Mo',
-        sizeExceededWithLimit: (maxUploadSizeInMB: number) => `La taille de la pièce jointe dépasse la limite de ${maxUploadSizeInMB} Mo`,
+        sizeExceededWithLimit: ({maxUploadSizeInMB}: SizeExceededParams) => `La taille de la pièce jointe dépasse la limite de ${maxUploadSizeInMB} Mo`,
         attachmentTooSmall: 'La pièce jointe est trop petite',
         sizeNotMet: 'La taille de la pièce jointe doit être supérieure à 240 octets',
         wrongFileType: 'Type de fichier non valide',
@@ -565,9 +652,10 @@ const translations: TranslationDeepObject<typeof en> = {
         attachmentImageTooLarge: 'Cette image est trop volumineuse pour être prévisualisée avant le téléversement.',
         imageDimensionsTooLarge: "Les dimensions de l'image sont trop grandes pour être traitées. Veuillez utiliser une image plus petite.",
         tooManyFiles: (fileLimit: number) => `Vous pouvez téléverser au maximum ${fileLimit} fichiers à la fois.`,
-        sizeExceededWithValue: (maxUploadSizeInMB: number) => `Les fichiers dépassent ${maxUploadSizeInMB} Mo. Veuillez réessayer.`,
+        sizeExceededWithValue: ({maxUploadSizeInMB}: SizeExceededParams) => `Les fichiers dépassent ${maxUploadSizeInMB} Mo. Veuillez réessayer.`,
         someFilesCantBeUploaded: 'Certains fichiers ne peuvent pas être téléversés',
-        sizeLimitExceeded: (maxUploadSizeInMB: number) => `Les fichiers doivent être inférieurs à ${maxUploadSizeInMB} Mo. Les fichiers plus volumineux ne seront pas téléversés.`,
+        sizeLimitExceeded: ({maxUploadSizeInMB}: SizeExceededParams) =>
+            `Les fichiers doivent être inférieurs à ${maxUploadSizeInMB} Mo. Les fichiers plus volumineux ne seront pas téléversés.`,
         maxFileLimitExceeded: "Vous pouvez téléverser jusqu'à 30 reçus à la fois. Les reçus supplémentaires ne seront pas téléversés.",
         unsupportedFileType: (fileType: string) => `Les fichiers ${fileType} ne sont pas pris en charge. Seuls les types de fichiers pris en charge seront téléchargés.`,
         learnMoreAboutSupportedFiles: 'En savoir plus sur les formats pris en charge.',
@@ -608,55 +696,17 @@ const translations: TranslationDeepObject<typeof en> = {
         signIn: 'Veuillez vous reconnecter.',
     },
     multifactorAuthentication: {
-        reviewTransaction: {
-            reviewTransaction: 'Examiner la transaction',
-            pleaseReview: 'Veuillez examiner cette transaction',
-            requiresYourReview: 'Une transaction par carte Expensify nécessite votre examen ci-dessous.',
-            transactionDetails: 'Détails de la transaction',
-            deny: 'Refuser',
-            approve: 'Approuver',
-            denyTransaction: 'Refuser la transaction',
-            transactionDenied: 'Transaction refusée',
-            transactionApproved: 'Transaction approuvée !',
-            areYouSureToDeny: 'Voulez-vous continuer ? La transaction sera refusée si vous fermez cet écran.',
-            youCanTryAgainAtMerchantOrReachOut:
-                'Vous pouvez réessayer chez le commerçant. Si vous n’êtes pas à l’origine de cette transaction, <concierge-link>contactez Concierge</concierge-link> pour signaler une fraude potentielle.',
-            youNeedToTryAgainAtMerchant: 'Cette transaction n’a pas été vérifiée, nous l’avons donc refusée. Vous devrez réessayer auprès du commerçant.',
-            goBackToTheMerchant: 'Retournez sur le site du commerçant pour continuer la transaction.',
-            attemptedTransaction: 'Transaction tentée',
-            transactionFailed: 'Échec de la transaction',
-            transactionCouldNotBeCompleted: 'Votre transaction n’a pas pu être effectuée. Veuillez réessayer chez le commerçant.',
-            transactionCouldNotBeCompletedReachOut:
-                'Votre transaction n’a pas pu être effectuée. Si vous n’êtes pas à l’origine de cette transaction, <concierge-link>contactez Concierge</concierge-link> pour signaler une éventuelle fraude.',
-            reviewFailed: 'Échec de l’examen',
-            alreadyReviewedSubtitle:
-                'Vous avez déjà examiné cette transaction. Veuillez vérifier votre <transaction-history-link>historique des transactions</transaction-history-link> ou contacter <concierge-link>Concierge</concierge-link> pour signaler tout problème.',
-        },
         biometricsTest: {
             biometricsTest: 'Test biométrique',
             authenticationSuccessful: 'Authentification réussie',
-            successfullyAuthenticatedUsing: (authType?: string) => `Vous vous êtes authentifié avec succès à l’aide de ${authType}.`,
-            troubleshootBiometricsStatus: ({status}: {status?: string}) => `Données biométriques (${status})`,
+            successfullyAuthenticatedUsing: ({authType}: MultifactorAuthenticationTranslationParams) => `Vous vous êtes authentifié avec succès en utilisant ${authType}.`,
+            troubleshootBiometricsStatus: ({registered}: MultifactorAuthenticationTranslationParams) => `Données biométriques (${registered ? 'Enregistré' : 'Non inscrit'})`,
             yourAttemptWasUnsuccessful: 'Votre tentative d’authentification a échoué.',
             youCouldNotBeAuthenticated: 'Vous n’avez pas pu être authentifié',
             areYouSureToReject: 'Voulez-vous vraiment continuer ? La tentative d’authentification sera rejetée si vous fermez cet écran.',
             rejectAuthentication: 'Rejeter l’authentification',
             test: 'Test',
             biometricsAuthentication: 'Authentification biométrique',
-            authType: {
-                unknown: 'Inconnu',
-                none: 'Aucun',
-                credentials: 'Identifiants',
-                biometrics: 'Biométrie',
-                faceId: 'Face ID',
-                touchId: 'Touch ID',
-                opticId: 'Optic ID',
-                passkey: 'Passkey',
-            },
-            statusNeverRegistered: 'Jamais enregistré',
-            statusNotRegistered: 'Non enregistré',
-            statusRegisteredThisDevice: 'Enregistré',
-            statusRegisteredOtherDevice: () => ({one: 'Un autre appareil enregistré', other: 'Autres appareils enregistrés'}),
         },
         pleaseEnableInSystemSettings: {
             start: 'Veuillez activer la vérification par reconnaissance faciale/empreinte digitale ou définir un code d’accès à l’appareil dans vos',
@@ -669,43 +719,28 @@ const translations: TranslationDeepObject<typeof en> = {
         letsVerifyItsYou: 'Vérifions qu’il s’agit bien de vous',
         nowLetsAuthenticateYou: 'Maintenant, procédons à votre authentification…',
         letsAuthenticateYou: 'Authentifions votre identité…',
-        verifyYourself: {biometrics: 'Vérifiez votre identité avec votre visage ou votre empreinte digitale', passkeys: 'Vérifiez votre identité avec une clé d’accès'},
+        verifyYourself: {
+            biometrics: 'Vérifiez votre identité avec votre visage ou votre empreinte digitale',
+        },
         enableQuickVerification: {
             biometrics: 'Activez une vérification rapide et sécurisée à l’aide de votre visage ou de votre empreinte digitale. Aucun mot de passe ni code requis.',
-            passkeys: 'Activez une vérification rapide et sécurisée à l’aide d’une clé d’accès. Aucun mot de passe ni code requis.',
         },
         revoke: {
+            remove: 'Supprimer',
             title: 'Reconnaissance faciale/empreinte digitale et passkeys',
             explanation:
-                'La vérification par reconnaissance faciale/empreinte digitale ou par clé d’accès est activée sur un ou plusieurs appareils. Révoquer l’accès exigera un code magique pour la prochaine vérification sur cet appareil.',
-            confirmationPrompt: 'Êtes-vous sûr(e) ? Vous aurez besoin d’un code magique pour la prochaine vérification sur cet appareil.',
+                'La vérification par reconnaissance faciale/empreinte digitale ou par passkey est activée sur un ou plusieurs appareils. Révoquer l’accès exigera un code magique pour la prochaine vérification sur n’importe quel appareil.',
+            confirmationPrompt: 'Vous êtes sûr(e) ? Vous aurez besoin d’un code magique pour la prochaine vérification sur n’importe quel appareil.',
             cta: 'Révoquer l’accès',
             noDevices:
-                'Vous n’avez enregistré aucun appareil pour la vérification par reconnaissance faciale/empreinte digitale ou par passkey. Si vous en enregistrez, vous pourrez révoquer cet accès ici.',
+                'Vous n’avez enregistré aucun appareil pour la vérification par reconnaissance faciale, empreinte digitale ou passkey. Si vous en enregistrez, vous pourrez révoquer cet accès ici.',
             dismiss: 'Compris',
             error: 'La requête a échoué. Réessayez plus tard.',
-            revoke: 'Révoquer',
-            confirmationPromptAll: 'Êtes-vous sûr ? Vous aurez besoin d’un code magique pour la prochaine vérification sur n’importe quel appareil.',
-            ctaAll: 'Tout révoquer',
-            thisDevice: 'Cet appareil',
-            otherDevices: (otherDeviceCount?: number) => {
-                const numberWords = ['Un', 'Deux', 'Trois', 'Quatre', 'Cinq', 'Six', 'Sept', 'Huit', 'Neuf'];
-                const displayCount = otherDeviceCount !== undefined && otherDeviceCount >= 1 && otherDeviceCount <= 9 ? numberWords.at(otherDeviceCount - 1) : `${otherDeviceCount}`;
-                return `${displayCount} autre(s) ${otherDeviceCount === 1 ? 'appareil' : 'appareils'}`;
-            },
-            confirmationPromptThisDevice: 'Êtes-vous sûr ? Vous aurez besoin d’un code magique pour la prochaine vérification sur cet appareil.',
-            confirmationPromptMultiple: 'Voulez-vous vraiment continuer ? Vous aurez besoin d’un code magique pour la prochaine vérification sur ces appareils.',
         },
         unsupportedDevice: {
             unsupportedDevice: 'Appareil non pris en charge',
-            pleaseDownloadMobileApp: `Cette action n'est pas prise en charge sur votre appareil. Veuillez télécharger l'application Expensify depuis l'<a href="${CONST.APP_DOWNLOAD_LINKS.IOS}">App Store</a> ou le <a href="${CONST.APP_DOWNLOAD_LINKS.ANDROID}">Google Play Store</a> et réessayer.`,
-            pleaseUseWebApp: `Cette action n'est pas prise en charge sur votre appareil. Veuillez utiliser l'<a href="${CONST.NEW_EXPENSIFY_URL}">application web Expensify</a> et réessayer.`,
+            pleaseDownloadMobileApp: `<centered-text><muted-text> Cette action n'est pas prise en charge sur votre appareil. Veuillez télécharger l'application Expensify depuis l'<a href="${CONST.APP_DOWNLOAD_LINKS.IOS}">App Store</a> ou le <a href="${CONST.APP_DOWNLOAD_LINKS.ANDROID}">Google Play Store</a> et réessayer.</muted-text></centered-text>`,
         },
-        verificationFailed: 'Échec de la vérification',
-        setPin: {didNotShipCard: 'Nous n’avons pas envoyé votre carte. Veuillez réessayer.'},
-        revealPin: {couldNotReveal: "Nous n'avons pas pu afficher votre code PIN. Veuillez réessayer."},
-        changePin: {didNotChange: "Nous n'avons pas modifié votre code PIN. Veuillez réessayer."},
-        revealCardDetail: {couldNotReveal: 'Nous n’avons pas pu afficher les détails de votre carte. Veuillez réessayer.'},
     },
     validateCodeModal: {
         successfulSignInTitle: dedent(`
@@ -744,7 +779,11 @@ const translations: TranslationDeepObject<typeof en> = {
         nameEmailOrPhoneNumber: 'Nom, e-mail ou numéro de téléphone',
         findMember: 'Trouver un membre',
         searchForSomeone: 'Rechercher une personne',
-        userSelected: (username: string) => `${username} sélectionné`,
+    },
+    customApprovalWorkflow: {
+        title: 'Workflow d’approbation personnalisé',
+        description: 'Votre entreprise utilise un flux d’approbation personnalisé sur cet espace de travail. Veuillez effectuer cette action dans Expensify Classic',
+        goToExpensifyClassic: 'Passer à Expensify Classic',
     },
     emptyList: {
         [CONST.IOU.TYPE.CREATE]: {
@@ -766,8 +805,8 @@ const translations: TranslationDeepObject<typeof en> = {
         phrase2: 'L’argent parle. Et maintenant que la messagerie et les paiements sont réunis au même endroit, c’est aussi simple.',
         phrase3: 'Vos paiements vous parviennent aussi vite que vous faites passer votre message.',
         enterPassword: 'Veuillez saisir votre mot de passe',
-        welcomeNewFace: (login: string) => `${login}, c’est toujours un plaisir de voir un nouveau visage par ici !`,
-        welcomeEnterMagicCode: (login: string) => `Veuillez saisir le code magique envoyé à ${login}. Il devrait arriver dans une minute ou deux.`,
+        welcomeNewFace: ({login}: SignUpNewFaceCodeParams) => `${login}, c’est toujours un plaisir de voir un nouveau visage par ici !`,
+        welcomeEnterMagicCode: ({login}: WelcomeEnterMagicCodeParams) => `Veuillez saisir le code magique envoyé à ${login}. Il devrait arriver dans une minute ou deux.`,
     },
     login: {
         hero: {
@@ -795,9 +834,6 @@ const translations: TranslationDeepObject<typeof en> = {
         emoji: 'Émoji',
         collapse: 'Réduire',
         expand: 'Agrandir',
-        askConciergeToUpdate: 'Essayez « Mettre à jour une dépense »…',
-        askConciergeToCorrect: 'Essayez « Corriger une dépense »...',
-        askConciergeForHelp: "Demander de l'aide à Concierge IA…",
     },
     reportActionContextMenu: {
         copyMessage: 'Copier le message',
@@ -862,9 +898,9 @@ const translations: TranslationDeepObject<typeof en> = {
         askMeAnything: 'Posez-moi vos questions !',
         sayHello: 'Dites bonjour !',
         yourSpace: 'Votre espace',
-        welcomeToRoom: (roomName: string) => `Bienvenue dans ${roomName} !`,
-        usePlusButton: (additionalText: string) => `Utilisez le bouton + pour ${additionalText} une dépense.`,
-        askConcierge: 'Concierge peut répondre aux questions, mettre à jour les dépenses, et plus encore.',
+        welcomeToRoom: ({roomName}: WelcomeToRoomParams) => `Bienvenue dans ${roomName} !`,
+        usePlusButton: ({additionalText}: UsePlusButtonParams) => `Utilisez le bouton + pour ${additionalText} une dépense.`,
+        askConcierge: 'Posez-moi vos questions !',
         conciergeSupport: 'Votre agent IA personnel',
         create: 'créer',
         iouTypes: {
@@ -876,17 +912,12 @@ const translations: TranslationDeepObject<typeof en> = {
         },
     },
     adminOnlyCanPost: 'Seuls les administrateurs peuvent envoyer des messages dans ce salon.',
-    readOnlyConversation: 'Cette conversation est en lecture seule.',
     reportAction: {
         asCopilot: 'en tant que copilote pour',
-        assistedBy: (agentName: string) => `assisté par ${agentName}`,
-        humanSupportAgent: 'un agent humain',
         harvestCreatedExpenseReport: (reportUrl: string, reportName: string) =>
             `a créé cette note de frais pour regrouper toutes les dépenses de <a href="${reportUrl}">${reportName}</a> qui n'ont pas pu être soumises à la fréquence que vous avez choisie`,
-        createdReportForUnapprovedTransactions: (reportUrl: string, reportName: string, reportID: string, isReportDeleted: boolean) =>
-            isReportDeleted
-                ? `a créé cette note de frais pour toutes les dépenses retenues de la note de frais supprimée n°${reportID}`
-                : `a créé cette note de frais pour toutes les dépenses retenues provenant de <a href="${reportUrl}">${reportName}</a>`,
+        createdReportForUnapprovedTransactions: ({reportUrl, reportName}: CreatedReportForUnapprovedTransactionsParams) =>
+            `a créé cette note de frais pour toutes les dépenses en attente de <a href="${reportUrl}">${reportName}</a>`,
     },
     mentionSuggestions: {
         hereAlternateText: 'Notifier tout le monde dans cette conversation',
@@ -925,6 +956,7 @@ const translations: TranslationDeepObject<typeof en> = {
         buttonFind: 'Trouver quelque chose...',
         buttonMySettings: 'Mes paramètres',
         fabNewChat: 'Commencer la discussion',
+        fabNewChatExplained: 'Ouvrir le menu des actions',
         fabScanReceiptExplained: 'Scanner le reçu',
         chatPinned: 'Discussion épinglée',
         draftedMessage: 'Message rédigé',
@@ -932,44 +964,41 @@ const translations: TranslationDeepObject<typeof en> = {
         listOfChats: 'Liste des discussions',
         saveTheWorld: 'Sauver le monde',
         tooltip: 'Commencez ici !',
+        redirectToExpensifyClassicModal: {
+            title: 'Bientôt disponible',
+            description:
+                'Nous sommes en train d’ajuster encore quelques éléments de New Expensify pour l’adapter à votre configuration spécifique. En attendant, rendez-vous sur Expensify Classic.',
+        },
     },
     homePage: {
         forYou: 'Pour vous',
         timeSensitiveSection: {
             title: 'Urgent',
-            addShippingAddress: {title: 'Nous avons besoin de votre adresse de livraison', subtitle: 'Indiquez une adresse pour recevoir votre Carte Expensify.', cta: 'Ajouter une adresse'},
-            addPaymentCard: {title: 'Ajoutez une carte de paiement pour continuer à utiliser Expensify', subtitle: 'Compte > Abonnement', cta: 'Ajouter'},
-            activateCard: {title: 'Activer votre Carte Expensify', subtitle: 'Validez votre carte et commencez à dépenser.', cta: 'Activer'},
-            reviewCardFraud: {
-                title: 'Examiner une éventuelle fraude sur votre Carte Expensify',
-                titleWithDetails: ({amount, merchant}: {amount: string; merchant: string}) => `Examiner ${amount} de fraude potentielle chez ${merchant}`,
-                subtitle: 'Carte Expensify',
-                cta: 'Examiner',
+            cta: 'Réclamer',
+            offer50off: {
+                title: 'Bénéficiez de 50 % de réduction sur votre première année !',
+                subtitle: ({formattedTime}: {formattedTime: string}) => `${formattedTime} restant`,
             },
-            ctaFix: 'Corriger',
-            fixCompanyCardConnection: {
-                title: ({feedName}: {feedName: string}) => (feedName ? `Corriger la connexion de la carte d'entreprise ${feedName}` : 'Corriger la connexion de la carte entreprise'),
-                defaultSubtitle: 'Espace de travail',
-                subtitle: ({policyName}: {policyName: string}) => `${policyName} > Cartes d'entreprise`,
+            offer25off: {
+                title: 'Bénéficiez de 25 % de réduction sur votre première année !',
+                subtitle: ({days}: {days: number}) => `${days} ${days === 1 ? 'jour' : 'jours'} restants`,
             },
-            fixPolicyConnection: {
-                title: ({integrationName}: {integrationName: string}) => `Corriger la connexion ${integrationName}`,
-                defaultSubtitle: 'Espace de travail',
-                subtitle: ({policyName}: {policyName: string}) => `${policyName} > Comptabilité`,
+            addShippingAddress: {
+                title: 'Nous avons besoin de votre adresse de livraison',
+                subtitle: 'Indiquez une adresse pour recevoir votre carte Expensify.',
+                cta: 'Ajouter une adresse',
             },
-            fixPersonalCardConnection: {
-                title: ({cardName}: {cardName?: string}) => (cardName ? `Réparer la connexion de la carte personnelle ${cardName}` : 'Corriger la connexion de la carte personnelle'),
-                subtitle: 'Portefeuille',
+            activateCard: {
+                title: 'Activez votre carte Expensify',
+                subtitle: 'Validez votre carte et commencez à dépenser.',
+                cta: 'Activer',
             },
-            validateAccount: {title: 'Validez votre compte', subtitle: 'Compte', cta: 'Valider'},
-            fixFailedBilling: {title: 'Nous n’avons pas pu débiter votre carte enregistrée', subtitle: 'Abonnement'},
-            unlockBankAccount: {
-                workspaceTitle: 'Votre compte bancaire professionnel a été verrouillé',
-                personalTitle: 'Votre compte bancaire a été verrouillé',
-                workspaceSubtitle: ({policyName}: {policyName: string}) => policyName,
-                personalSubtitle: 'Portefeuille',
+            ctaFix: 'Corriger',
+            fixCompanyCardConnection: {
+                title: ({feedName}: {feedName: string}) => (feedName ? `Corriger la connexion de la carte d'entreprise ${feedName}` : 'Corriger la connexion de la carte entreprise'),
+                subtitle: 'Espace de travail > Cartes d’entreprise',
             },
-            enterSignerInfo: {title: 'Informations du signataire requises', subtitle: ({bankAccountLastFour}: {bankAccountLastFour: string}) => `Compte bancaire ${bankAccountLastFour}`},
+            fixAccountingConnection: {title: ({integrationName}: {integrationName: string}) => `Corriger la connexion ${integrationName}`, subtitle: 'Espace de travail > Comptabilité'},
         },
         announcements: 'Annonces',
         discoverSection: {
@@ -985,78 +1014,12 @@ const translations: TranslationDeepObject<typeof en> = {
             export: ({count}: {count: number}) => `Exporter ${count} ${count === 1 ? 'Note de frais' : 'notes de frais'}`,
             begin: 'Commencer',
             emptyStateMessages: {
-                thumbsUpStarsTitle: 'C’est terminé !',
-                thumbsUpStarsDescription: 'Un grand bravo à vous, restez à l’affût de nouvelles tâches.',
-                smallRocketTitle: 'Tout est à jour',
-                smallRocketDescription: 'Les prochaines tâches à faire apparaîtront ici.',
-                cowboyHatTitle: 'C’est terminé !',
-                cowboyHatDescription: 'Toutes les tâches sont maîtrisées, gardez un œil ouvert pour la suite.',
-                trophy1Title: 'Rien à afficher',
-                trophy1Description: 'Vous y êtes arrivé ! Gardez un œil ouvert pour d’autres tâches.',
-                palmTreeTitle: 'Tout est à jour',
-                palmTreeDescription: 'Il est temps de se détendre, mais restez à l’affût des futures tâches.',
-                fishbowlBlueTitle: 'C’est terminé !',
-                fishbowlBlueDescription: 'Nous ferons remonter les futures tâches ici.',
-                targetTitle: 'Tout est à jour',
-                targetDescription: 'Bravo, vous restez dans la bonne direction. Revenez pour plus de tâches !',
-                chairTitle: 'Rien à afficher',
-                chairDescription: 'Allez vous détendre, nous listerons les prochaines tâches ici.',
-                broomTitle: 'C’est terminé !',
-                broomDescription: 'Les tâches sont terminées, mais restez à l’affût de nouvelles tâches.',
-                houseTitle: 'Tout est à jour',
-                houseDescription: 'Voici votre base pour les prochaines tâches à faire.',
-                conciergeBotTitle: 'Rien à afficher',
-                conciergeBotDescription: 'Bip bop bip bop, revenez pour plus de tâches !',
-                checkboxTextTitle: 'Tout est à jour',
-                checkboxTextDescription: 'Cochez vos prochaines tâches à faire ici.',
-                flashTitle: 'C’est terminé !',
-                flashDescription: 'Nous traiterons vos futures tâches ici.',
-                sunglassesTitle: 'Rien à afficher',
-                sunglassesDescription: 'Temps de se détendre, mais restez à l’affût de ce qui arrive !',
-                f1FlagsTitle: 'Tout est à jour',
-                f1FlagsDescription: 'Vous avez terminé toutes les tâches en cours.',
-            },
-        },
-        upcomingTravel: 'Voyages à venir',
-        upcomingTravelSection: {
-            flightTo: ({destination}: {destination: string}) => `Vol vers ${destination}`,
-            trainTo: ({destination}: {destination: string}) => `Train pour ${destination}`,
-            hotelIn: ({destination}: {destination: string}) => `Hôtel à ${destination}`,
-            carRentalIn: ({destination}: {destination: string}) => `Location de voiture à ${destination}`,
-            inOneWeek: 'Dans 1 semaine',
-            inDays: () => ({one: 'Dans 1 jour', other: (count: number) => `Dans ${count} jours`}),
-            today: 'Aujourd’hui',
-        },
-        freeTrialSection: {
-            title: ({days}: {days: number}) => `Essai gratuit : plus que ${days} ${days === 1 ? 'jour' : 'jours'} !`,
-            offer50Body: 'Profitez de 50 % de réduction sur votre première année',
-            offer25Body: 'Obtenez 25 % de réduction sur votre première année',
-            addCardBody: 'Ajouter une carte de paiement',
-            ctaClaim: 'Demande',
-            ctaAdd: 'Ajouter une carte',
-            timeRemaining: ({formattedTime}: {formattedTime: string}) => `Temps restant : ${formattedTime}`,
-            timeRemainingDays: () => ({
-                one: 'Temps restant : 1 jour',
-                other: (pluralCount: number) => `Temps restant : ${pluralCount} jours`,
-            }),
-        },
-        gettingStartedSection: {
-            title: 'Premiers pas',
-            createWorkspace: 'Créer un espace de travail',
-            connectAccounting: ({integrationName}: {integrationName: string}) => `Se connecter à ${integrationName}`,
-            connectAccountingDefault: 'Connecter à la comptabilité',
-            customizeCategories: 'Personnaliser les catégories comptables',
-            linkCompanyCards: 'Lier des cartes d’entreprise',
-            setupRules: 'Configurer les règles de dépense',
-            inviteAccountant: 'Inviter votre comptable',
-        },
-        yourSpend: {
-            title: 'Vos dépenses',
-            awaitingApproval: 'En attente d’approbation',
-            repaidLast30Days: 'Remboursé au cours des 30 derniers jours',
-            recentTransactions: ({lastFour}: {lastFour: string}) => `Transactions récentes • ${lastFour}`,
+                nicelyDone: 'Bien joué',
+                keepAnEyeOut: 'Restez à l’affût de ce qui arrive ensuite !',
+                allCaughtUp: 'Vous êtes à jour',
+                upcomingTodos: 'Les tâches à venir apparaîtront ici.',
+            },
         },
-        seeMore: ({count}: {count: number}) => `Voir ${count} de plus`,
     },
     allSettingsScreen: {
         subscription: 'Abonnement',
@@ -1086,20 +1049,7 @@ const translations: TranslationDeepObject<typeof en> = {
         singleFieldMultipleColumns: (fieldName: string) => `Oups ! Vous avez associé un seul champ (« ${fieldName} ») à plusieurs colonnes. Veuillez vérifier et réessayer.`,
         emptyMappedField: (fieldName: string) => `Oups ! Le champ (« ${fieldName} ») contient une ou plusieurs valeurs vides. Veuillez vérifier et réessayer.`,
         importSuccessfulTitle: 'Importation réussie',
-        importCategoriesSuccessfulDescription: ({added, updated}: {added: number; updated: number}) => {
-            if (!added && !updated) {
-                return 'Aucune catégorie n’a été ajoutée ou mise à jour.';
-            }
-            if (added && updated) {
-                return `${added} ${added === 1 ? 'catégorie' : 'catégories'} ajouté(s), ${updated} ${updated === 1 ? 'catégorie' : 'catégories'} mis(es) à jour.`;
-            }
-            if (added) {
-                return added === 1 ? '1 catégorie a été ajoutée.' : `${added} catégories ont été ajoutées.`;
-            }
-            return updated === 1 ? '1 catégorie a été mise à jour.' : `${updated} catégories ont été mises à jour.`;
-        },
-        importCompanyCardTransactionsSuccessfulDescription: ({transactions}: {transactions: number}) =>
-            transactions > 1 ? `${transactions} transactions ont été ajoutées.` : '1 transaction a été ajoutée.',
+        importCategoriesSuccessfulDescription: ({categories}: {categories: number}) => (categories > 1 ? `${categories} catégories ont été ajoutées.` : '1 catégorie a été ajoutée.'),
         importMembersSuccessfulDescription: ({added, updated}: {added: number; updated: number}) => {
             if (!added && !updated) {
                 return 'Aucun membre n’a été ajouté ni mis à jour.';
@@ -1131,7 +1081,6 @@ const translations: TranslationDeepObject<typeof en> = {
             other: (count: number) =>
                 `Veuillez confirmer les détails ci-dessous pour les ${count} nouveaux membres de l’espace de travail qui seront ajoutés dans le cadre de ce téléversement. Les membres existants ne recevront aucune mise à jour de rôle ni message d’invitation.`,
         }),
-        importCompanyCardTransactionsPendingMessage: 'L’apparition de nouvelles cartes et transactions peut prendre un certain temps, veuillez patienter.',
     },
     receipt: {
         upload: 'Télécharger le reçu',
@@ -1164,9 +1113,7 @@ const translations: TranslationDeepObject<typeof en> = {
         deleteReceipt: 'Supprimer le reçu',
         deleteConfirmation: 'Voulez-vous vraiment supprimer ce reçu ?',
         addReceipt: 'Ajouter un reçu',
-        addAdditionalReceipt: 'Ajouter un reçu supplémentaire',
         scanFailed: 'Le reçu n’a pas pu être scanné, car il lui manque un commerçant, une date ou un montant.',
-        crop: 'Recadrer',
         addAReceipt: {
             phrase1: 'Ajouter un reçu',
             phrase2: 'ou faites-en glisser un ici',
@@ -1186,7 +1133,6 @@ const translations: TranslationDeepObject<typeof en> = {
         noLongerHaveReportAccess: 'Vous n’avez plus accès à votre précédente destination d’action rapide. Choisissez-en une nouvelle ci-dessous.',
         updateDestination: 'Mettre à jour la destination',
         createReport: 'Créer une note de frais',
-        createTimeExpense: 'Créer une dépense de temps',
     },
     iou: {
         amount: 'Montant',
@@ -1206,18 +1152,18 @@ const translations: TranslationDeepObject<typeof en> = {
         split: 'Diviser',
         splitExpense: 'Fractionner la dépense',
         splitDates: 'Diviser les dates',
-        splitDateRange: (startDate: string, endDate: string, count: number) => `Du ${startDate} au ${endDate} (${count} jours)`,
-        splitExpenseSubtitle: (amount: string, merchant: string) => `${amount} de ${merchant}`,
+        splitDateRange: ({startDate, endDate, count}: SplitDateRangeParams) => `Du ${startDate} au ${endDate} (${count} jours)`,
+        splitExpenseSubtitle: ({amount, merchant}: SplitExpenseSubtitleParams) => `${amount} de ${merchant}`,
         splitByPercentage: 'Diviser par pourcentage',
         splitByDate: 'Diviser par date',
         addSplit: 'Ajouter une répartition',
         makeSplitsEven: 'Rendre les répartitions égales',
         editSplits: 'Modifier les répartitions',
-        totalAmountGreaterThanOriginal: (amount: string) => `Le montant total est supérieur de ${amount} à la dépense initiale.`,
-        totalAmountLessThanOriginal: (amount: string) => `Le montant total est inférieur de ${amount} à la dépense initiale.`,
+        totalAmountGreaterThanOriginal: ({amount}: TotalAmountGreaterOrLessThanOriginalParams) => `Le montant total est supérieur de ${amount} à la dépense initiale.`,
+        totalAmountLessThanOriginal: ({amount}: TotalAmountGreaterOrLessThanOriginalParams) => `Le montant total est inférieur de ${amount} à la dépense initiale.`,
         splitExpenseZeroAmount: 'Veuillez saisir un montant valide avant de continuer.',
         splitExpenseOneMoreSplit: 'Aucune répartition ajoutée. Ajoutez-en au moins une pour enregistrer.',
-        splitExpenseEditTitle: (amount: string, merchant: string) => `Modifier ${amount} pour ${merchant}`,
+        splitExpenseEditTitle: ({amount, merchant}: SplitExpenseEditTitleParams) => `Modifier ${amount} pour ${merchant}`,
         removeSplit: 'Supprimer la répartition',
         splitExpenseCannotBeEditedModalTitle: 'Cette dépense ne peut pas être modifiée',
         splitExpenseCannotBeEditedModalDescription: 'Les dépenses approuvées ou payées ne peuvent pas être modifiées',
@@ -1248,12 +1194,9 @@ const translations: TranslationDeepObject<typeof en> = {
         deleteReceipt: 'Supprimer le reçu',
         findExpense: 'Trouver une dépense',
         deletedTransaction: (amount: string, merchant: string) => `a supprimé une dépense (${amount} pour ${merchant})`,
-        movedFromReport: (reportName: string) => `a déplacé une dépense depuis ${reportName}`,
-        movedFromReportNoName: 'a déplacé une dépense',
-        movedTransactionTo: (reportUrl: string, reportName: string) => `a déplacé cette dépense vers <a href="${reportUrl}">${reportName}</a>`,
-        movedTransactionToAnotherReport: 'a déplacé cette dépense vers un autre rapport',
-        movedTransactionFrom: (reportUrl: string, reportName: string) => `a déplacé cette dépense depuis <a href="${reportUrl}">${reportName}</a>`,
-        movedTransactionFromAnotherReport: 'a déplacé cette dépense depuis un autre rapport',
+        movedFromReport: (reportName: string) => `a déplacé une dépense${reportName ? `de ${reportName}` : ''}`,
+        movedTransactionTo: (reportUrl: string, reportName?: string) => `a déplacé cette dépense${reportName ? `vers <a href="${reportUrl}">${reportName}</a>` : ''}`,
+        movedTransactionFrom: (reportUrl: string, reportName?: string) => `a déplacé cette dépense${reportName ? `depuis <a href="${reportUrl}">${reportName}</a>` : ''}`,
         unreportedTransaction: (reportUrl: string) => `a déplacé cette dépense vers votre <a href="${reportUrl}">espace personnel</a>`,
         movedAction: (shouldHideMovedReportUrl: boolean, movedReportUrl: string, newParentReportUrl: string, toPolicyName: string) => {
             if (shouldHideMovedReportUrl) {
@@ -1265,10 +1208,7 @@ const translations: TranslationDeepObject<typeof en> = {
         pendingMatch: 'Correspondance en attente',
         pendingMatchWithCreditCardDescription: 'Reçu en attente de rapprochement avec une transaction par carte. Marquez comme paiement en espèces pour annuler.',
         markAsCash: 'Marquer comme espèces',
-        pendingMatchSubmitTitle: 'Soumettre le rapport',
-        pendingMatchSubmitDescription: 'Certaines dépenses sont en attente de rapprochement avec une transaction par carte de crédit. Voulez-vous les marquer comme espèces ?',
         routePending: 'Acheminement en attente...',
-        automaticallyEnterExpenseDetails: 'Concierge remplira les détails pour vous.',
         receiptScanning: () => ({
             one: 'Scan des reçus...',
             other: 'Scan des reçus...',
@@ -1295,8 +1235,7 @@ const translations: TranslationDeepObject<typeof en> = {
         receiptStatusTitle: 'Analyse en cours…',
         receiptStatusText: 'Vous seul pouvez voir ce reçu pendant son analyse. Revenez plus tard ou saisissez les détails maintenant.',
         receiptScanningFailed: 'L’analyse du reçu a échoué. Veuillez saisir les détails manuellement.',
-        allTransactionsPendingNextStep:
-            "Toutes les transactions sont en attente. Vous ne pouvez pas soumettre cette note de frais avant qu'elles ne soient comptabilisées dans quelques jours.",
+        transactionPendingDescription: "Transaction en attente. L'inscription peut prendre quelques jours.",
         companyInfo: 'Informations sur l’entreprise',
         companyInfoDescription: 'Nous avons besoin de quelques informations supplémentaires avant que vous puissiez envoyer votre première facture.',
         yourCompanyName: 'Nom de votre entreprise',
@@ -1331,18 +1270,20 @@ const translations: TranslationDeepObject<typeof en> = {
         settledElsewhere: 'Payé ailleurs',
         individual: 'Individuel',
         business: 'Professionnel',
-        settlePersonal: (formattedAmount?: string) => (formattedAmount ? `Payer ${formattedAmount} en tant que particulier` : `Payer avec un compte personnel`),
-        settleWallet: (formattedAmount?: string) => (formattedAmount ? `Payer ${formattedAmount} avec le portefeuille` : `Payer avec le portefeuille`),
-        settlePayment: (formattedAmount: string) => `Payer ${formattedAmount}`,
-        settleBusiness: (formattedAmount?: string) => (formattedAmount ? `Payer ${formattedAmount} en tant qu’entreprise` : `Payer avec le compte professionnel`),
-        payElsewhere: (formattedAmount?: string) => (formattedAmount ? `Marquer ${formattedAmount} comme payé` : `Marquer comme payé`),
-        confirmPaymentReceivedModalTitle: 'Confirmer la réception du paiement',
-        receivedPayment: 'Paiement reçu',
-        receivedPaymentConfirmation: 'Veuillez continuer uniquement si vous avez déjà reçu le paiement en dehors d’Expensify.',
-        confirmReceivedPayment: 'Oui, j’ai reçu le paiement.',
+        settleExpensify: ({formattedAmount}: SettleExpensifyCardParams) => (formattedAmount ? `Payer ${formattedAmount} avec Expensify` : `Payer avec Expensify`),
+        settlePersonal: ({formattedAmount}: SettleExpensifyCardParams) => (formattedAmount ? `Payer ${formattedAmount} en tant que particulier` : `Payer avec un compte personnel`),
+        settleWallet: ({formattedAmount}: SettleExpensifyCardParams) => (formattedAmount ? `Payer ${formattedAmount} avec le portefeuille` : `Payer avec le portefeuille`),
+        settlePayment: ({formattedAmount}: SettleExpensifyCardParams) => `Payer ${formattedAmount}`,
+        settleBusiness: ({formattedAmount}: SettleExpensifyCardParams) => (formattedAmount ? `Payer ${formattedAmount} en tant qu’entreprise` : `Payer avec le compte professionnel`),
+        payElsewhere: ({formattedAmount}: SettleExpensifyCardParams) => (formattedAmount ? `Marquer ${formattedAmount} comme payé` : `Marquer comme payé`),
         settleInvoicePersonal: (amount?: string, last4Digits?: string) => (amount ? `a payé ${amount} avec le compte personnel ${last4Digits}` : `Payé avec un compte personnel`),
         settleInvoiceBusiness: (amount?: string, last4Digits?: string) => (amount ? `a payé ${amount} avec le compte professionnel ${last4Digits}` : `Payé avec le compte professionnel`),
-        payWithPolicy: (policyName: string, formattedAmount?: string) => (formattedAmount ? `Payer ${formattedAmount} via ${policyName}` : `Payer via ${policyName}`),
+        payWithPolicy: ({
+            formattedAmount,
+            policyName,
+        }: SettleExpensifyCardParams & {
+            policyName: string;
+        }) => (formattedAmount ? `Payer ${formattedAmount} via ${policyName}` : `Payer via ${policyName}`),
         businessBankAccount: (amount?: string, last4Digits?: string) => (amount ? `a payé ${amount} avec le compte bancaire ${last4Digits}` : `payé avec le compte bancaire ${last4Digits}`),
         automaticallyPaidWithBusinessBankAccount: (amount?: string, last4Digits?: string) =>
             `payé ${amount ? `${amount} ` : ''} avec le compte bancaire ${last4Digits} via les <a href="${CONST.CONFIGURE_EXPENSE_REPORT_RULES_HELP_URL}">règles d’espace de travail</a>`,
@@ -1351,16 +1292,16 @@ const translations: TranslationDeepObject<typeof en> = {
         nextStep: 'Étapes suivantes',
         finished: 'Terminé',
         flip: 'Retourner',
-        sendInvoice: (amount: string) => `Envoyer la facture de ${amount}`,
+        sendInvoice: ({amount}: RequestAmountParams) => `Envoyer la facture de ${amount}`,
         expenseAmount: (formattedAmount: string, comment?: string) => `${formattedAmount}${comment ? `pour ${comment}` : ''}`,
-        submitted: (memo?: string) => `soumis${memo ? `, indiquant « ${memo} »` : ''}`,
+        submitted: ({memo}: SubmittedWithMemoParams) => `soumis${memo ? `, indiquant « ${memo} »` : ''}`,
         automaticallySubmitted: `soumis via <a href="${CONST.SELECT_WORKFLOWS_HELP_URL}">soumissions différées</a>`,
         queuedToSubmitViaDEW: 'en file d’attente pour être soumis via le circuit d’approbation personnalisé',
         queuedToApproveViaDEW: 'mis en file d’attente pour approbation via un processus d’approbation personnalisé',
         trackedAmount: (formattedAmount: string, comment?: string) => `suivi de ${formattedAmount}${comment ? `pour ${comment}` : ''}`,
-        splitAmount: (amount: string) => `diviser ${amount}`,
-        didSplitAmount: (formattedAmount: string, comment?: string) => `diviser ${formattedAmount}${comment ? `pour ${comment}` : ''}`,
-        yourSplit: (amount: string) => `Votre part ${amount}`,
+        splitAmount: ({amount}: SplitAmountParams) => `diviser ${amount}`,
+        didSplitAmount: (formattedAmount: string, comment: string) => `diviser ${formattedAmount}${comment ? `pour ${comment}` : ''}`,
+        yourSplit: ({amount}: UserSplitParams) => `Votre part ${amount}`,
         payerOwesAmount: (amount: number | string, payer: string, comment?: string) => `${payer} doit ${amount}${comment ? `pour ${comment}` : ''}`,
         payerOwes: (payer: string) => `${payer} doit :`,
         payerPaidAmount: (amount: number | string, payer?: string) => `${payer ? `${payer} ` : ''}a payé ${amount}`,
@@ -1376,71 +1317,34 @@ const translations: TranslationDeepObject<typeof en> = {
         approvedMessage: `approuvé`,
         unapproved: `Non approuvé`,
         automaticallyForwarded: `approuvé via les <a href="${CONST.CONFIGURE_EXPENSE_REPORT_RULES_HELP_URL}">règles de l'espace de travail</a>`,
-        forwarded: (memo?: string) => `approuvé${memo ? `, indiquant « ${memo} »` : ''}`,
-        rejectedThisReport: 'rejeté',
-        waitingOnBankAccount: (submitterDisplayName: string) => `a commencé le paiement, mais attend que ${submitterDisplayName} ajoute un compte bancaire.`,
+        forwarded: `approuvé`,
+        rejectedThisReport: 'a rejeté cette note de frais',
+        waitingOnBankAccount: ({submitterDisplayName}: WaitingOnBankAccountParams) => `a commencé le paiement, mais attend que ${submitterDisplayName} ajoute un compte bancaire.`,
         adminCanceledRequest: 'a annulé le paiement',
         canceledRequest: (amount: string, submitterDisplayName: string) =>
             `a annulé le paiement de ${amount}, car ${submitterDisplayName} n’a pas activé son Portefeuille Expensify dans un délai de 30 jours`,
-        settledAfterAddedBankAccount: (submitterDisplayName: string, amount: string) => `${submitterDisplayName} a ajouté un compte bancaire. Le paiement de ${amount} a été effectué.`,
+        settledAfterAddedBankAccount: ({submitterDisplayName, amount}: SettledAfterAddedBankAccountParams) =>
+            `${submitterDisplayName} a ajouté un compte bancaire. Le paiement de ${amount} a été effectué.`,
         paidElsewhere: ({payer, comment}: PaidElsewhereParams = {}) => `${payer ? `${payer} ` : ''}marqué comme payé${comment ? `, en disant « ${comment} »` : ''}`,
         paidWithExpensify: (payer?: string) => `${payer ? `${payer} ` : ''}payé avec le portefeuille`,
         automaticallyPaidWithExpensify: (payer?: string) =>
             `${payer ? `${payer} ` : ''}payé avec Expensify via les <a href="${CONST.CONFIGURE_EXPENSE_REPORT_RULES_HELP_URL}">règles de l’espace de travail</a>`,
-        reimbursedThisReport: 'a remboursé cette note de frais',
-        paidThisBill: 'a payé cette facture',
-        reimbursedOnBehalfOf: (actor: string) => `au nom de ${actor}`,
-        reimbursedFromBankAccount: (debitBankAccount: string) => `à partir du compte bancaire se terminant par ${debitBankAccount}`,
-        reimbursedSubmitterAddedBankAccount: (submitter: string) => `${submitter} a ajouté un compte bancaire, retirant la note de frais de la mise en attente. Le remboursement est lancé`,
-        reimbursedWithFastACH: ({
-            isCurrentUser,
-            submitterLogin,
-            creditBankAccount,
-            expectedDate,
-        }: {
-            isCurrentUser: boolean;
-            submitterLogin: string;
-            creditBankAccount: string;
-            expectedDate: string;
-        }) =>
-            isCurrentUser
-                ? `. L’argent est en route vers votre ${creditBankAccount ? `compte bancaire se terminant par ${creditBankAccount}` : 'compte'}. Remboursement estimé pour être terminé le ${expectedDate}.`
-                : `. L’argent est en route vers le compte bancaire de ${submitterLogin}${creditBankAccount ? ` se terminant par ${creditBankAccount}` : ''}. Remboursement estimé pour le ${expectedDate}.`,
-        reimbursedWithCheck: ' par chèque.',
-        reimbursedWithStripeConnect: ({
-            isCurrentUser,
-            submitterLogin,
-            creditBankAccount,
-            isCard,
-        }: {
-            isCurrentUser: boolean;
-            submitterLogin: string;
-            creditBankAccount: string;
-            isCard: boolean;
-        }) => {
-            const paymentMethod = isCard ? 'carte' : 'compte bancaire';
-            return isCurrentUser
-                ? `. L’argent est en route vers votre ${creditBankAccount ? `compte bancaire se terminant par ${creditBankAccount}` : 'compte'} (payé via ${paymentMethod}). Cela peut prendre jusqu’à 10 jours ouvrables.`
-                : `. L’argent est en route vers le compte bancaire de ${submitterLogin}${creditBankAccount ? ` se terminant par ${creditBankAccount}` : ''} (payé via ${paymentMethod}). Cela peut prendre jusqu’à 10 jours ouvrés.`;
-        },
-        reimbursedWithACH: ({creditBankAccount, expectedDate}: {creditBankAccount?: string; expectedDate?: string}) =>
-            ` par dépôt direct (ACH)${creditBankAccount ? ` vers le compte bancaire se terminant par ${creditBankAccount}.` : '. '}${expectedDate ? `Le remboursement devrait être terminé d'ici le ${expectedDate}.` : 'Cela prend généralement 4 à 5 jours ouvrables.'}`,
         noReimbursableExpenses: 'Cette note de frais a un montant non valide',
         pendingConversionMessage: 'Le total sera mis à jour quand vous serez de nouveau en ligne',
         changedTheExpense: 'a modifié la dépense',
-        setTheRequest: (valueName: string, newValueToDisplay: string) => `le ${valueName} sur ${newValueToDisplay}`,
-        setTheDistanceMerchant: (translatedChangedField: string, newMerchant: string, newAmountToDisplay: string) =>
+        setTheRequest: ({valueName, newValueToDisplay}: SetTheRequestParams) => `le ${valueName} sur ${newValueToDisplay}`,
+        setTheDistanceMerchant: ({translatedChangedField, newMerchant, newAmountToDisplay}: SetTheDistanceMerchantParams) =>
             `défini le ${translatedChangedField} sur ${newMerchant}, ce qui a défini le montant sur ${newAmountToDisplay}`,
         removedTheRequest: (valueName: string, oldValueToDisplay: string) => `le ${valueName} (anciennement ${oldValueToDisplay})`,
-        updatedTheRequest: (valueName: string, newValueToDisplay: string, oldValueToDisplay: string) => `le ${valueName} sur ${newValueToDisplay} (précédemment ${oldValueToDisplay})`,
-        updatedTheDistanceMerchant: (translatedChangedField: string, newMerchant: string, oldMerchant: string, newAmountToDisplay: string, oldAmountToDisplay: string) =>
+        updatedTheRequest: ({valueName, newValueToDisplay, oldValueToDisplay}: UpdatedTheRequestParams) => `le ${valueName} sur ${newValueToDisplay} (précédemment ${oldValueToDisplay})`,
+        updatedTheDistanceMerchant: ({translatedChangedField, newMerchant, oldMerchant, newAmountToDisplay, oldAmountToDisplay}: UpdatedTheDistanceMerchantParams) =>
             `a modifié ${translatedChangedField} en ${newMerchant} (auparavant ${oldMerchant}), ce qui a mis à jour le montant à ${newAmountToDisplay} (auparavant ${oldAmountToDisplay})`,
         basedOnAI: 'd’après l’activité précédente',
         basedOnMCC: ({rulesLink}: {rulesLink: string}) =>
             rulesLink ? `en fonction des <a href="${rulesLink}">règles de l’espace de travail</a>` : 'en fonction de la règle de l’espace de travail',
-        threadExpenseReportName: (formattedAmount: string, comment?: string) => `${formattedAmount} ${comment ? `pour ${comment}` : 'dépense'}`,
+        threadExpenseReportName: ({formattedAmount, comment}: ThreadRequestReportNameParams) => `${formattedAmount} ${comment ? `pour ${comment}` : 'dépense'}`,
         invoiceReportName: ({linkedReportID}: OriginalMessage<typeof CONST.REPORT.ACTIONS.TYPE.REPORT_PREVIEW>) => `Note de frais de facture n° ${linkedReportID}`,
-        threadPaySomeoneReportName: (formattedAmount: string, comment?: string) => `${formattedAmount} envoyé${comment ? `pour ${comment}` : ''}`,
+        threadPaySomeoneReportName: ({formattedAmount, comment}: ThreadSentMoneyReportNameParams) => `${formattedAmount} envoyé${comment ? `pour ${comment}` : ''}`,
         movedFromPersonalSpace: ({workspaceName, reportName}: MovedFromPersonalSpaceParams) =>
             `a déplacé la dépense de l’espace personnel vers ${workspaceName ?? `discuter avec ${reportName}`}`,
         movedToPersonalSpace: 'a déplacé la dépense vers l’espace personnel',
@@ -1449,14 +1353,10 @@ const translations: TranslationDeepObject<typeof en> = {
             invalidTagLength: 'Le nom du tag dépasse 255 caractères. Veuillez le raccourcir ou choisir un autre tag.',
             invalidAmount: 'Veuillez saisir un montant valide avant de continuer',
             invalidDistance: 'Veuillez saisir une distance valide avant de continuer',
-            invalidReadings: 'Veuillez saisir les relevés de début et de fin pour continuer',
+            invalidReadings: 'Veuillez saisir les relevés de début et de fin',
             negativeDistanceNotAllowed: 'Le relevé de fin doit être supérieur au relevé de début',
-            distanceAmountTooLarge: 'Le montant total est trop élevé. Réduisez la distance ou diminuez le taux.',
-            distanceAmountTooLargeReduceDistance: 'Le montant total est trop élevé. Réduisez la distance.',
-            distanceAmountTooLargeReduceRate: 'Le montant total est trop élevé. Diminuez le taux.',
-            odometerReadingTooLarge: (formattedMax: string) => `Les lectures du compteur kilométrique ne peuvent pas dépasser ${formattedMax}.`,
             invalidIntegerAmount: 'Veuillez saisir un montant entier en dollars avant de continuer',
-            invalidTaxAmount: (amount: string) => `Le montant maximal de taxe est de ${amount}`,
+            invalidTaxAmount: ({amount}: RequestAmountParams) => `Le montant maximal de taxe est de ${amount}`,
             invalidSplit: 'La somme des répartitions doit être égale au montant total',
             invalidSplitParticipants: 'Veuillez saisir un montant supérieur à zéro pour au moins deux participants',
             invalidSplitYourself: 'Veuillez saisir un montant non nul pour votre répartition',
@@ -1470,8 +1370,6 @@ const translations: TranslationDeepObject<typeof en> = {
             receiptFailureMessage:
                 '<rbr>Une erreur s’est produite lors du téléchargement de votre reçu. Veuillez <a href="download">enregistrer le reçu</a> et <a href="retry">réessayer</a> plus tard.</rbr>',
             receiptFailureMessageShort: 'Une erreur s’est produite lors du téléchargement de votre reçu.',
-            receiptUploadFailedMessage: 'Échec du téléchargement du reçu. Enregistrez le reçu ou supprimez la dépense et perdez-la.',
-            saveReceipt: 'Enregistrer le reçu',
             genericDeleteFailureMessage: 'Erreur inattendue lors de la suppression de cette dépense. Veuillez réessayer plus tard.',
             genericEditFailureMessage: 'Erreur inattendue lors de la modification de cette dépense. Veuillez réessayer plus tard.',
             genericSmartscanFailureMessage: 'Des champs manquent à la transaction',
@@ -1488,15 +1386,11 @@ const translations: TranslationDeepObject<typeof en> = {
             endDateSameAsStartDate: 'La date de fin ne peut pas être identique à la date de début',
             manySplitsProvided: `Le nombre maximal de répartitions autorisées est de ${CONST.IOU.SPLITS_LIMIT}.`,
             dateRangeExceedsMaxDays: `La plage de dates ne peut pas dépasser ${CONST.IOU.SPLITS_LIMIT} jours.`,
-            unableToSubmitReport: 'Impossible de soumettre la note de frais',
-            allTransactionsPendingDescription:
-                'Vous ne pouvez pas soumettre cette note de frais, car toutes les transactions sont en attente. Leur comptabilisation peut prendre quelques jours.',
-            stitchOdometerImagesFailed: 'Échec de la combinaison des images de l’odomètre. Veuillez réessayer plus tard.',
-            failedToSaveOdometerDraft: 'Impossible d’enregistrer votre brouillon de compteur kilométrique. Veuillez réessayer.',
         },
         dismissReceiptError: 'Ignorer l’erreur',
         dismissReceiptErrorConfirmation: 'Attention ! Ignorer cette erreur supprimera complètement votre reçu téléversé. Êtes-vous sûr ?',
-        waitingOnEnabledWallet: (submitterDisplayName: string) => `a commencé à régler. Le paiement est en attente jusqu’à ce que ${submitterDisplayName} active son portefeuille.`,
+        waitingOnEnabledWallet: ({submitterDisplayName}: WaitingOnBankAccountParams) =>
+            `a commencé à régler. Le paiement est en attente jusqu’à ce que ${submitterDisplayName} active son portefeuille.`,
         enableWallet: 'Activer le portefeuille',
         hold: 'En attente',
         unhold: 'Supprimer la mise en attente',
@@ -1508,20 +1402,16 @@ const translations: TranslationDeepObject<typeof en> = {
         heldExpense: 'a mis cette dépense en attente',
         unheldExpense: 'blocage levé pour cette dépense',
         moveUnreportedExpense: 'Déplacer la dépense non déclarée',
-        addExistingExpense: 'Ajouter une dépense existante',
-        selectExistingExpense: 'Sélectionnez au moins une dépense à ajouter à la note de frais.',
-        emptyStateExistingExpenseTitle: 'Aucune dépense existante',
-        emptyStateExistingExpenseSubtitle: 'Il semble que vous n’ayez aucune dépense existante. Essayez d’en créer une ci-dessous.',
-        addExistingExpenseConfirm: 'Ajouter à la note de frais',
+        addUnreportedExpense: 'Ajouter une dépense non déclarée',
+        selectUnreportedExpense: 'Sélectionnez au moins une dépense à ajouter à la note de frais.',
+        emptyStateUnreportedExpenseTitle: 'Aucune dépense non déclarée',
+        emptyStateUnreportedExpenseSubtitle: 'Il semble que vous n’ayez aucune dépense non déclarée. Essayez d’en créer une ci-dessous.',
+        addUnreportedExpenseConfirm: 'Ajouter à la note de frais',
         newReport: 'Nouvelle note de frais',
         explainHold: () => ({
             one: 'Expliquez pourquoi vous retenez cette dépense.',
             other: 'Expliquez pourquoi vous retenez ces dépenses.',
         }),
-        explainHoldApprover: () => ({
-            one: "Expliquez ce dont vous avez besoin avant d'approuver cette dépense.",
-            other: "Expliquez ce dont vous avez besoin avant d'approuver ces dépenses.",
-        }),
         retracted: 'Retiré',
         retract: 'Retirer',
         reopened: 'rouvert',
@@ -1537,9 +1427,6 @@ const translations: TranslationDeepObject<typeof en> = {
         someDuplicatesArePaid: 'Certains de ces doublons ont déjà été approuvés ou payés.',
         reviewDuplicates: 'Examiner les doublons',
         keepAll: 'Tout garder',
-        keepSelected: 'Garder la sélection',
-        noDuplicatesTitle: 'Tout est en ordre !',
-        noDuplicatesDescription: "Il n'y a aucune transaction en double à vérifier ici.",
         confirmApprove: 'Confirmer le montant approuvé',
         confirmApprovalAmount: 'Approuvez uniquement les dépenses conformes, ou approuvez l’intégralité de la note de frais.',
         confirmApprovalAllHoldAmount: () => ({
@@ -1573,7 +1460,7 @@ const translations: TranslationDeepObject<typeof en> = {
         unapprove: 'Annuler l’approbation',
         unapproveReport: 'Retirer l’approbation de la note de frais',
         headsUp: 'Attention !',
-        unapproveWithIntegrationWarning: (accountingIntegration: string) =>
+        unapproveWithIntegrationWarning: ({accountingIntegration}: UnapproveWithIntegrationWarningParams) =>
             `Cette note de frais a déjà été exportée vers ${accountingIntegration}. La modifier peut entraîner des incohérences de données. Voulez-vous vraiment annuler l’approbation de cette note de frais ?`,
         reimbursable: 'remboursable',
         nonReimbursable: 'non remboursable',
@@ -1582,7 +1469,6 @@ const translations: TranslationDeepObject<typeof en> = {
         bookingArchived: 'Cette réservation est archivée',
         bookingArchivedDescription: 'Cette réservation est archivée car la date du voyage est passée. Ajoutez une dépense pour le montant final si nécessaire.',
         attendees: 'Participants',
-        totalPerAttendee: 'Par participant',
         whoIsYourAccountant: 'Qui est votre comptable ?',
         paymentComplete: 'Paiement terminé',
         time: 'Heure',
@@ -1609,7 +1495,7 @@ const translations: TranslationDeepObject<typeof en> = {
         }),
         dates: 'Dates',
         rates: 'Taux',
-        submitsTo: (name: string) => `Soumet à ${name}`,
+        submitsTo: ({name}: SubmitsToParams) => `Soumet à ${name}`,
         reject: {
             educationalTitle: 'Faut-il mettre en attente ou rejeter ?',
             educationalText: 'Si vous n’êtes pas prêt à approuver ou à payer une dépense, vous pouvez la mettre en attente ou la rejeter.',
@@ -1618,7 +1504,7 @@ const translations: TranslationDeepObject<typeof en> = {
             heldExpenseLeftBehindTitle: 'Les dépenses en attente sont laissées de côté lorsque vous approuvez une note de frais entière.',
             rejectExpenseTitle: 'Rejetez une dépense que vous n’avez pas l’intention d’approuver ou de payer.',
             reasonPageTitle: 'Rejeter la dépense',
-            reasonPageDescription: "Expliquez pourquoi vous n'approuverez pas cette dépense.",
+            reasonPageDescription: 'Expliquez pourquoi vous rejetez cette dépense.',
             rejectReason: 'Motif de rejet',
             markAsResolved: 'Marquer comme résolu',
             rejectedStatus: 'Cette dépense a été rejetée. Nous attendons que vous corrigiez les problèmes et la marquiez comme résolue pour permettre la soumission.',
@@ -1627,27 +1513,14 @@ const translations: TranslationDeepObject<typeof en> = {
                 markedAsResolved: 'a marqué le motif de rejet comme résolu',
             },
         },
-        rejectReport: {
-            title: 'Rejeter la note de frais',
-            description: 'Expliquez pourquoi vous n’allez pas approuver cette note de frais :',
-            rejectReason: 'Motif de rejet',
-            selectTarget: 'Choisissez le membre vers qui renvoyer cette note de frais pour examen :',
-            lastApprover: 'Dernier approbateur',
-            submitter: 'Déclarant',
-            rejectedReportMessage: 'Cette note de frais a été rejetée.',
-            rejectedNextStep: 'Cette note de frais a été rejetée. En attente de votre action pour corriger les problèmes et la soumettre manuellement à nouveau.',
-            selectMemberError: 'Sélectionnez un membre vers qui rejeter cette note de frais.',
-            couldNotReject: 'La note de frais n’a pas pu être rejetée. Veuillez réessayer.',
-        },
-        moveExpenses: 'Déplacer vers le rapport',
+        moveExpenses: () => ({one: 'Déplacer la dépense', other: 'Déplacer des dépenses'}),
         moveExpensesError:
             'Vous ne pouvez pas déplacer des frais de per diem vers des notes de frais d’autres espaces de travail, car les taux de per diem peuvent varier d’un espace de travail à l’autre.',
         changeApprover: {
             title: 'Modifier l’approbateur',
-            header: (workflowSettingLink: string) =>
+            header: ({workflowSettingLink}: WorkflowSettingsParam) =>
                 `Choisissez une option pour modifier l’approbateur de cette note de frais. (Mettez à jour vos <a href="${workflowSettingLink}">paramètres d’espace de travail</a> pour changer cela définitivement pour toutes les notes de frais.)`,
             changedApproverMessage: (managerID: number) => `a changé l'approbateur en <mention-user accountID="${managerID}"/>`,
-            reassignedApproverMessage: (managerID: number) => `a réaffecté l'approbateur à <mention-user accountID="${managerID}"/> via une mise à jour du flux de travail`,
             actions: {
                 addApprover: 'Ajouter un approbateur',
                 addApproverSubtitle: 'Ajouter un approbateur supplémentaire au circuit d’approbation existant.',
@@ -1656,12 +1529,10 @@ const translations: TranslationDeepObject<typeof en> = {
             },
             addApprover: {
                 subtitle: 'Choisissez un approbateur supplémentaire pour cette note de frais avant que nous la fassions passer par le reste du flux d’approbation.',
-                bulkSubtitle: 'Choisissez un approbateur supplémentaire pour ces rapports avant que nous ne les transmettions pour le reste du flux de validation.',
             },
-            bulkSubtitle: 'Choisissez une option pour changer l’approbateur de ces rapports.',
         },
         chooseWorkspace: 'Choisir un espace de travail',
-        routedDueToDEW: (to: string, reason?: string) => `note de frais acheminée vers ${to}${reason ? ` parce que ${reason}` : ''}`,
+        routedDueToDEW: ({to}: RoutedDueToDEWParams) => `note de frais transmise à ${to} en raison du flux d’approbation personnalisé`,
         timeTracking: {
             hoursAt: (hours: number, rate: string) => `${hours} ${hours === 1 ? 'heure' : 'heures'} @ ${rate} / heure`,
             hrs: 'h',
@@ -1669,35 +1540,34 @@ const translations: TranslationDeepObject<typeof en> = {
             ratePreview: (rate: string) => `${rate} / heure`,
             amountTooLargeError: 'Le montant total est trop élevé. Réduisez le nombre d’heures ou diminuez le taux.',
         },
-        correctRateError: 'Corrigez l’erreur de taux et réessayez.',
-        AskToExplain: `. <a href="${CONST.CONCIERGE_EXPLAIN_LINK_PATH}">Expliquer<sparkles-icon/></a>`,
-        duplicateNonDefaultWorkspacePerDiemError:
-            'Vous ne pouvez pas dupliquer les indemnités journalières entre plusieurs espaces de travail, car les taux peuvent différer d’un espace de travail à l’autre.',
-        rulesModifiedFields: {
-            reimbursable: (value: boolean) => (value ? 'a marqué la dépense comme « remboursable »' : 'a marqué la dépense comme « non remboursable »'),
-            billable: (value: boolean) => (value ? 'a marqué la dépense comme « facturable »' : 'a marqué la dépense comme « non refacturable »'),
-            tax: (value: string, isFirst: boolean) => (isFirst ? `définir le taux de taxe sur « ${value} »` : `taux de taxe à « ${value} »`),
-            reportName: (value: string) => `a déplacé cette dépense vers la note de frais « ${value} »`,
-            common: (key: keyof PolicyRulesModifiedFields | keyof PersonalRulesModifiedFields, value: string, isFirst: boolean) => {
-                const field = translations.common[key].toLowerCase();
-                return isFirst ? `définir ${field} sur « ${value} »` : `${field} à « ${value} »`;
-            },
-            formatPersonalRules: (fragments: string, route: string) => `${fragments} via <a href="${route}">règles de dépenses personnelles</a>`,
-            formatPolicyRules: (fragments: string, route: string) => `${fragments} via <a href="${route}">règles d’espace de travail</a>`,
-        },
-        failedToAutoSubmitViaDEW: (reason: string) => `échec de la soumission de la note de frais via <a href="${CONST.SELECT_WORKFLOWS_HELP_URL}">soumissions différées</a>. ${reason}`,
-        failedToSubmitViaDEW: (reason: string) => `échec de la soumission de la note de frais. ${reason}`,
-        failedToAutoApproveViaDEW: (reason: string) =>
-            `impossible d’approuver via les <a href="${CONST.CONFIGURE_EXPENSE_REPORT_RULES_HELP_URL}">règles de l’espace de travail</a>. ${reason}`,
-        failedToApproveViaDEW: (reason: string) => `échec de l’approbation. ${reason}`,
-        cannotDuplicateDistanceExpense: 'Vous ne pouvez pas dupliquer des dépenses de distance entre espaces de travail, car les taux peuvent différer d’un espace de travail à l’autre.',
-        taxDisabledAlert: {
-            title: 'Taxe désactivée',
-            prompt: 'Activez le suivi des taxes dans l’espace de travail pour modifier les détails de la dépense ou supprimer la taxe de cette dépense.',
-            confirmText: 'Supprimer la taxe',
-        },
-        bulkDuplicateLimit: `Vous pouvez dupliquer jusqu’à ${CONST.SEARCH.BULK_DUPLICATE_LIMIT} dépenses à la fois. Veuillez sélectionner moins de dépenses et réessayer.`,
-        deleted: 'Supprimé',
+        correctDistanceRateError: 'Corrigez l’erreur de taux de distance, puis réessayez.',
+        AskToExplain: `. <a href="${CONST.CONCIERGE_EXPLAIN_LINK_PATH}"><strong>Expliquer</strong></a> &#x2728;`,
+        policyRulesModifiedFields: (policyRulesModifiedFields: PolicyRulesModifiedFields, policyRulesRoute: string, formatList: (list: string[]) => string) => {
+            const entries = ObjectUtils.typedEntries(policyRulesModifiedFields);
+            const fragments = entries.map(([key, value], i) => {
+                const isFirst = i === 0;
+                if (key === 'reimbursable') {
+                    return value ? 'a marqué la dépense comme « remboursable »' : 'a marqué la dépense comme « non remboursable »';
+                }
+                if (key === 'billable') {
+                    return value ? 'a marqué la dépense comme « facturable »' : 'a marqué la dépense comme « non refacturable »';
+                }
+                if (key === 'tax') {
+                    const taxEntry = value as PolicyRulesModifiedFields['tax'];
+                    const taxRateName = taxEntry?.field_id_TAX.name ?? '';
+                    if (isFirst) {
+                        return `définir le taux de taxe sur « ${taxRateName} »`;
+                    }
+                    return `taux de taxe à « ${taxRateName} »`;
+                }
+                const updatedValue = value as string | boolean;
+                if (isFirst) {
+                    return `définir ${translations.common[key].toLowerCase()} sur « ${updatedValue} »`;
+                }
+                return `${translations.common[key].toLowerCase()} à « ${updatedValue} »`;
+            });
+            return `${formatList(fragments)} via les <a href="${policyRulesRoute}">règles de l’espace de travail</a>`;
+        },
     },
     transactionMerge: {
         listPage: {
@@ -1770,12 +1640,7 @@ const translations: TranslationDeepObject<typeof en> = {
     },
     nextStep: {
         message: {
-            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_TO_ADD_TRANSACTIONS]: (
-                actor: string,
-                actorType: ValueOf<typeof CONST.NEXT_STEP.ACTOR_TYPE>,
-                _eta?: string,
-                _etaType?: ValueOf<typeof CONST.NEXT_STEP.ETA_TYPE>,
-            ) => {
+            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_TO_ADD_TRANSACTIONS]: ({actor, actorType}: NextStepParams) => {
                 switch (actorType) {
                     case CONST.NEXT_STEP.ACTOR_TYPE.CURRENT_USER:
                         return `En attente que <strong>vous</strong> ajoutiez des dépenses.`;
@@ -1785,12 +1650,7 @@ const translations: TranslationDeepObject<typeof en> = {
                         return `En attente qu’un administrateur ajoute des dépenses.`;
                 }
             },
-            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_TO_SUBMIT]: (
-                actor: string,
-                actorType: ValueOf<typeof CONST.NEXT_STEP.ACTOR_TYPE>,
-                _eta?: string,
-                _etaType?: ValueOf<typeof CONST.NEXT_STEP.ETA_TYPE>,
-            ) => {
+            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_TO_SUBMIT]: ({actor, actorType}: NextStepParams) => {
                 switch (actorType) {
                     case CONST.NEXT_STEP.ACTOR_TYPE.CURRENT_USER:
                         return `En attente que <strong>vous</strong> soumettiez des dépenses.`;
@@ -1800,18 +1660,8 @@ const translations: TranslationDeepObject<typeof en> = {
                         return `En attente qu’un administrateur soumette des dépenses.`;
                 }
             },
-            [CONST.NEXT_STEP.MESSAGE_KEY.NO_FURTHER_ACTION]: (
-                _actor: string,
-                _actorType: ValueOf<typeof CONST.NEXT_STEP.ACTOR_TYPE>,
-                _eta?: string,
-                _etaType?: ValueOf<typeof CONST.NEXT_STEP.ETA_TYPE>,
-            ) => `Aucune autre action n’est requise !`,
-            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_FOR_SUBMITTER_ACCOUNT]: (
-                actor: string,
-                actorType: ValueOf<typeof CONST.NEXT_STEP.ACTOR_TYPE>,
-                _eta?: string,
-                _etaType?: ValueOf<typeof CONST.NEXT_STEP.ETA_TYPE>,
-            ) => {
+            [CONST.NEXT_STEP.MESSAGE_KEY.NO_FURTHER_ACTION]: (_: NextStepParams) => `Aucune autre action requise !`,
+            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_FOR_SUBMITTER_ACCOUNT]: ({actor, actorType}: NextStepParams) => {
                 switch (actorType) {
                     case CONST.NEXT_STEP.ACTOR_TYPE.CURRENT_USER:
                         return `En attente que <strong>vous</strong> ajoutiez un compte bancaire.`;
@@ -1821,31 +1671,21 @@ const translations: TranslationDeepObject<typeof en> = {
                         return `En attente qu’un administrateur ajoute un compte bancaire.`;
                 }
             },
-            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_FOR_AUTOMATIC_SUBMIT]: (
-                actor: string,
-                actorType: ValueOf<typeof CONST.NEXT_STEP.ACTOR_TYPE>,
-                eta?: string,
-                etaType?: ValueOf<typeof CONST.NEXT_STEP.ETA_TYPE>,
-            ) => {
+            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_FOR_AUTOMATIC_SUBMIT]: ({actor, actorType, eta, etaType}: NextStepParams) => {
                 let formattedETA = '';
                 if (eta) {
-                    formattedETA = etaType === CONST.NEXT_STEP.ETA_TYPE.DATE_TIME ? `le ${eta} de chaque mois` : ` ${eta}`;
+                    formattedETA = etaType === CONST.NEXT_STEP.ETA_TYPE.DATE_TIME ? `le ${eta}` : ` ${eta}`;
                 }
                 switch (actorType) {
                     case CONST.NEXT_STEP.ACTOR_TYPE.CURRENT_USER:
-                        return `En attente que <strong>vos</strong> dépenses soient automatiquement soumises${formattedETA}.`;
+                        return `En attente de la soumission automatique de <strong>vos</strong> dépenses${formattedETA}.`;
                     case CONST.NEXT_STEP.ACTOR_TYPE.OTHER_USER:
                         return `En attente de la soumission automatique des dépenses de <strong>${actor}</strong>${formattedETA}.`;
                     case CONST.NEXT_STEP.ACTOR_TYPE.UNSPECIFIED_ADMIN:
                         return `En attente de la soumission automatique des dépenses d’un administrateur${formattedETA}.`;
                 }
             },
-            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_TO_FIX_ISSUES]: (
-                actor: string,
-                actorType: ValueOf<typeof CONST.NEXT_STEP.ACTOR_TYPE>,
-                _eta?: string,
-                _etaType?: ValueOf<typeof CONST.NEXT_STEP.ETA_TYPE>,
-            ) => {
+            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_TO_FIX_ISSUES]: ({actor, actorType}: NextStepParams) => {
                 switch (actorType) {
                     case CONST.NEXT_STEP.ACTOR_TYPE.CURRENT_USER:
                         return `En attente que <strong>vous</strong> corrigiez les problèmes.`;
@@ -1855,27 +1695,17 @@ const translations: TranslationDeepObject<typeof en> = {
                         return `En attente qu’un administrateur corrige les problèmes.`;
                 }
             },
-            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_TO_APPROVE]: (
-                actor: string,
-                actorType: ValueOf<typeof CONST.NEXT_STEP.ACTOR_TYPE>,
-                _eta?: string,
-                _etaType?: ValueOf<typeof CONST.NEXT_STEP.ETA_TYPE>,
-            ) => {
+            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_TO_APPROVE]: ({actor, actorType}: NextStepParams) => {
                 switch (actorType) {
                     case CONST.NEXT_STEP.ACTOR_TYPE.CURRENT_USER:
                         return `En attente de <strong>votre</strong> approbation des dépenses.`;
                     case CONST.NEXT_STEP.ACTOR_TYPE.OTHER_USER:
                         return `En attente de l’approbation des dépenses par <strong>${actor}</strong>.`;
                     case CONST.NEXT_STEP.ACTOR_TYPE.UNSPECIFIED_ADMIN:
-                        return `En attente qu’un administrateur approuve les dépenses.`;
+                        return `En attente de l’approbation des dépenses par un administrateur.`;
                 }
             },
-            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_TO_EXPORT]: (
-                actor: string,
-                actorType: ValueOf<typeof CONST.NEXT_STEP.ACTOR_TYPE>,
-                _eta?: string,
-                _etaType?: ValueOf<typeof CONST.NEXT_STEP.ETA_TYPE>,
-            ) => {
+            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_TO_EXPORT]: ({actor, actorType}: NextStepParams) => {
                 switch (actorType) {
                     case CONST.NEXT_STEP.ACTOR_TYPE.CURRENT_USER:
                         return `En attente que <strong>vous</strong> exportiez cette note de frais.`;
@@ -1885,70 +1715,35 @@ const translations: TranslationDeepObject<typeof en> = {
                         return `En attente qu’un administrateur exporte cette note de frais.`;
                 }
             },
-            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_TO_PAY]: (
-                actor: string,
-                actorType: ValueOf<typeof CONST.NEXT_STEP.ACTOR_TYPE>,
-                _eta?: string,
-                _etaType?: ValueOf<typeof CONST.NEXT_STEP.ETA_TYPE>,
-            ) => {
+            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_TO_PAY]: ({actor, actorType}: NextStepParams) => {
                 switch (actorType) {
                     case CONST.NEXT_STEP.ACTOR_TYPE.CURRENT_USER:
                         return `En attente que <strong>vous</strong> payiez les dépenses.`;
                     case CONST.NEXT_STEP.ACTOR_TYPE.OTHER_USER:
-                        return `En attente que <strong>${actor}</strong> paie les dépenses.`;
+                        return `En attente que <strong>${actor}</strong> rembourse les dépenses.`;
                     case CONST.NEXT_STEP.ACTOR_TYPE.UNSPECIFIED_ADMIN:
                         return `En attente qu’un administrateur paie les dépenses.`;
                 }
             },
-            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_FOR_POLICY_BANK_ACCOUNT]: (
-                actor: string,
-                actorType: ValueOf<typeof CONST.NEXT_STEP.ACTOR_TYPE>,
-                _eta?: string,
-                _etaType?: ValueOf<typeof CONST.NEXT_STEP.ETA_TYPE>,
-            ) => {
+            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_FOR_POLICY_BANK_ACCOUNT]: ({actor, actorType}: NextStepParams) => {
                 switch (actorType) {
                     case CONST.NEXT_STEP.ACTOR_TYPE.CURRENT_USER:
-                        return `En attente que <strong>vous</strong> terminiez la configuration d’un compte bancaire professionnel.`;
+                        return `En attente que <strong>vous</strong> ayez terminé la configuration d’un compte bancaire professionnel.`;
                     case CONST.NEXT_STEP.ACTOR_TYPE.OTHER_USER:
-                        return `En attente que <strong>${actor}</strong> ait fini de configurer un compte bancaire professionnel.`;
+                        return `En attente que <strong>${actor}</strong> termine la configuration d’un compte bancaire professionnel.`;
                     case CONST.NEXT_STEP.ACTOR_TYPE.UNSPECIFIED_ADMIN:
                         return `En attente qu’un administrateur termine la configuration d’un compte bancaire professionnel.`;
                 }
             },
-            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_FOR_PAYMENT]: (
-                _actor: string,
-                _actorType: ValueOf<typeof CONST.NEXT_STEP.ACTOR_TYPE>,
-                eta?: string,
-                etaType?: ValueOf<typeof CONST.NEXT_STEP.ETA_TYPE>,
-            ) => {
+            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_FOR_PAYMENT]: ({eta, etaType}: NextStepParams) => {
                 let formattedETA = '';
                 if (eta) {
                     formattedETA = etaType === CONST.NEXT_STEP.ETA_TYPE.DATE_TIME ? `d’ici ${eta}` : ` ${eta}`;
                 }
                 return `En attente de la finalisation du paiement${formattedETA}.`;
             },
-            [CONST.NEXT_STEP.MESSAGE_KEY.SUBMITTING_TO_SELF]: (
-                _actor: string,
-                _actorType: ValueOf<typeof CONST.NEXT_STEP.ACTOR_TYPE>,
-                _eta?: string,
-                _etaType?: ValueOf<typeof CONST.NEXT_STEP.ETA_TYPE>,
-            ) =>
-                `Oups ! On dirait que vous soumettez à <strong>vous-même</strong>. L’approbation de vos propres notes de frais est <strong>interdite</strong> par votre espace de travail. Veuillez soumettre cette note de frais à une autre personne ou contacter votre administrateur pour modifier la personne à qui vous soumettez.`,
-            [CONST.NEXT_STEP.MESSAGE_KEY.REJECTED_REPORT]: (
-                actor: string,
-                actorType: ValueOf<typeof CONST.NEXT_STEP.ACTOR_TYPE>,
-                _eta?: string,
-                _etaType?: ValueOf<typeof CONST.NEXT_STEP.ETA_TYPE>,
-            ) => {
-                switch (actorType) {
-                    case CONST.NEXT_STEP.ACTOR_TYPE.CURRENT_USER:
-                        return `Cette note de frais a été rejetée. En attente que <strong>vous</strong> corrigiez les problèmes et la soumettiez à nouveau manuellement.`;
-                    case CONST.NEXT_STEP.ACTOR_TYPE.OTHER_USER:
-                        return `Cette note de frais a été rejetée. En attente que <strong>${actor}</strong> corrige les problèmes et la soumette manuellement à nouveau.`;
-                    case CONST.NEXT_STEP.ACTOR_TYPE.UNSPECIFIED_ADMIN:
-                        return `Cette note de frais a été rejetée. En attente qu’un administrateur corrige les problèmes et la soumette manuellement à nouveau.`;
-                }
-            },
+            [CONST.NEXT_STEP.MESSAGE_KEY.SUBMITTING_TO_SELF]: (_: NextStepParams) =>
+                `Oups ! Il semble que vous soumettiez cette note de frais à <strong>vous-même</strong>. L’approbation de vos propres notes de frais est <strong>interdite</strong> par votre espace de travail. Veuillez soumettre cette note de frais à quelqu’un d’autre ou contacter votre administrateur pour modifier la personne à qui vous la soumettez.`,
         },
         eta: {
             [CONST.NEXT_STEP.ETA_KEY.SHORTLY]: 'bientôt',
@@ -1974,8 +1769,6 @@ const translations: TranslationDeepObject<typeof en> = {
         offline: 'Hors ligne',
         syncing: 'Synchronisation en cours',
         profileAvatar: 'Avatar de profil',
-        customInstructions: 'Instructions personnalisées',
-        copilotIntoAccount: 'Copilot dans le compte',
         publicSection: {
             title: 'Public',
             subtitle: 'Ces informations sont affichées sur votre profil public. Tout le monde peut les voir.',
@@ -1984,16 +1777,12 @@ const translations: TranslationDeepObject<typeof en> = {
             title: 'Privé',
             subtitle: 'Ces informations sont utilisées pour les déplacements et les paiements. Elles n’apparaissent jamais sur votre profil public.',
         },
-        aiPromptSection: {
-            title: 'Invite IA',
-            subtitle: 'Rédiger des instructions personnalisées',
-            prompt: 'Invite',
-            editPrompt: "Modifier l'invite",
-            promptCannotBeEmpty: "L'invite ne peut pas être vide",
-            saved: 'Enregistré',
-        },
     },
-    securityPage: {title: 'Sécurité', subtitle: 'Protégez votre compte.', goToSecurity: 'Revenir à la page de sécurité'},
+    securityPage: {
+        title: 'Options de sécurité',
+        subtitle: 'Activez l’authentification à deux facteurs pour sécuriser votre compte.',
+        goToSecurity: 'Revenir à la page de sécurité',
+    },
     shareCodePage: {
         title: 'Votre code',
         subtitle: 'Invitez des membres sur Expensify en partageant votre code QR personnel ou votre lien de parrainage.',
@@ -2008,7 +1797,7 @@ const translations: TranslationDeepObject<typeof en> = {
         featureRequiresValidate: 'Cette fonctionnalité exige que vous validiez votre compte.',
         validateAccount: 'Validez votre compte',
         helpText: ({email}: {email: string}) =>
-            `Ajoutez d'autres moyens de vous connecter et d'envoyer des reçus à Expensify.<br/><br/>Ajoutez une adresse e-mail pour transférer des reçus à <a href="mailto:${email}">${email}</a> ou ajoutez un numéro de téléphone pour envoyer des reçus par SMS au 47777 (numéros américains uniquement).`,
+            `Ajoutez d’autres moyens de vous connecter et d’envoyer des reçus à Expensify.<br/><br/>Ajoutez une adresse e-mail pour transférer des reçus à <a href="mailto:${email}">${email}</a> ou ajoutez un numéro de téléphone pour envoyer des reçus par SMS au 47777 (numéros américains uniquement).`,
         pleaseVerify: 'Veuillez vérifier cette méthode de contact.',
         getInTouch: 'Nous utiliserons cette méthode pour vous contacter.',
         enterMagicCode: (contactMethod: string) => `Veuillez saisir le code magique envoyé à ${contactMethod}. Il devrait arriver d'ici une à deux minutes.`,
@@ -2031,7 +1820,6 @@ const translations: TranslationDeepObject<typeof en> = {
         },
         newContactMethod: 'Nouveau moyen de contact',
         goBackContactMethods: 'Revenir aux méthodes de contact',
-        yourDefaultContactMethodRestrictedSwitch: 'Ceci est votre méthode de contact par défaut actuelle. Votre entreprise a restreint sa suppression ou sa modification.',
     },
     pronouns: {
         coCos: 'Copropriétaire / Cosigner',
@@ -2091,6 +1879,8 @@ const translations: TranslationDeepObject<typeof en> = {
         },
         troubleshoot: {
             clearCacheAndRestart: 'Vider le cache et redémarrer',
+            viewConsole: 'Afficher la console de débogage',
+            debugConsole: 'Console de débogage',
             description:
                 '<muted-text>Utilisez les outils ci-dessous pour vous aider à diagnostiquer les problèmes avec Expensify. Si vous rencontrez des problèmes, veuillez <concierge-link>soumettre un bug</concierge-link>.</muted-text>',
             confirmResetDescription: 'Tous les brouillons de messages non envoyés seront perdus, mais le reste de vos données est en sécurité.',
@@ -2122,47 +1912,36 @@ const translations: TranslationDeepObject<typeof en> = {
             invalidateWithDelay: 'Invalider avec délai',
             leftHandNavCache: 'Cache de la navigation de gauche',
             clearleftHandNavCache: 'Effacer',
+            recordTroubleshootData: 'Enregistrer les données de diagnostic',
             softKillTheApp: 'Arrêter l’application en douceur',
             kill: 'Tuer',
             sentryDebug: 'Débogage Sentry',
-            sentrySendDescription: 'Envoyer les données à Sentry',
             sentryDebugDescription: 'Journaliser les requêtes Sentry dans la console',
             sentryHighlightedSpanOps: 'Noms de segments surlignés',
             sentryHighlightedSpanOpsPlaceholder: 'ui.interaction.clic, navigation, ui.chargement',
-            showBranchNameInTitle: 'Afficher le nom de la branche dans le titre du navigateur',
+        },
+        debugConsole: {
+            saveLog: 'Enregistrer le journal',
+            shareLog: 'Partager le journal',
+            enterCommand: 'Saisissez la commande',
+            execute: 'Exécuter',
+            noLogsAvailable: 'Aucun journal disponible',
+            logSizeTooLarge: (size: number) =>
+                `La taille du journal dépasse la limite de ${size} Mo. Veuillez utiliser « Enregistrer le journal » pour télécharger le fichier journal à la place.`,
+            logs: 'Journaux',
+            viewConsole: 'Afficher la console',
         },
         security: 'Sécurité',
         signOut: 'Se déconnecter',
         restoreStashed: 'Restaurer la connexion mise de côté',
         signOutConfirmationText: 'Vous perdrez toutes les modifications hors ligne si vous vous déconnectez.',
         versionLetter: 'v',
-        readTheTermsAndPrivacy: `Lisez les <a href="${CONST.OLD_DOT_PUBLIC_URLS.TERMS_URL}">Conditions d'utilisation</a> et la <a href="${CONST.OLD_DOT_PUBLIC_URLS.PRIVACY_URL}">Politique de confidentialité</a>.`,
+        readTheTermsAndPrivacy: `<muted-text-micro>Lisez les <a href="${CONST.OLD_DOT_PUBLIC_URLS.TERMS_URL}">Conditions d'utilisation</a> et la <a href="${CONST.OLD_DOT_PUBLIC_URLS.PRIVACY_URL}">Politique de confidentialité</a>.</muted-text-micro>`,
         help: 'Aide',
         whatIsNew: 'Quoi de neuf',
         accountSettings: 'Paramètres du compte',
         account: 'Compte',
         general: 'Général',
-        helpPage: {
-            title: 'Aide et assistance',
-            description: 'Nous sommes là pour vous aider, à toute heure.',
-            helpSite: "Site d'aide",
-            helpSiteDescription: 'Articles, tutoriels et plus',
-            conciergeChat: 'Concierge',
-            conciergeChatDescription: 'Votre agent IA personnel',
-            accountManager: 'Gestionnaire de compte',
-            yourAccountManager: 'Votre chargé de compte',
-            accountManagerDescription: 'Poser des questions et obtenir l’assistance client',
-            partnerManager: 'Gestionnaire Partenaires',
-            yourPartnerManager: 'Votre gestionnaire partenaire',
-            partnerManagerDescription: 'Optimisez votre partenariat et stimulez les recommandations',
-            guideDescription: 'Votre chargé de compte',
-            approvedPartnerTeamTitle: 'Rencontrez l’équipe de votre partenaire Approved!',
-            approvedPartnerTeamDescription:
-                'Une équipe dédiée, centrée sur la croissance de votre cabinet, l’intégration plus rapide de vos clients et un accompagnement d’experts dès que vous en avez besoin.',
-            accountExecutive: 'Responsable de compte',
-            accountExecutiveDescription: 'Configurer les clients avec succès',
-            moreResources: 'Plus de ressources',
-        },
     },
     closeAccountPage: {
         closeAccount: 'Fermer le compte',
@@ -2235,13 +2014,11 @@ const translations: TranslationDeepObject<typeof en> = {
         lockAccount: 'Verrouiller le compte',
         unlockAccount: 'Déverrouiller le compte',
         compromisedDescription:
-            'Vous remarquez quelque chose d’inhabituel sur votre compte ? Le signaler bloquera immédiatement votre compte, empêchera les nouvelles transactions avec la Carte Expensify et interdira toute modification du compte.',
+            'Vous remarquez quelque chose d’inhabituel sur votre compte ? Le signaler verrouillera immédiatement votre compte, bloquera les nouvelles transactions par carte Expensify et empêchera toute modification du compte.',
         domainAdminsDescription:
-            "Pour les administrateurs de domaine : cela met également en pause toute l'activité de Carte Expensify et toutes les actions d'administration sur l’ensemble de votre (vos) domaine(s).",
+            'Pour les administrateurs de domaine : ceci met également en pause toute activité de carte Expensify et toutes les actions d’administrateur sur l’ensemble de vos domaines.',
         areYouSure: 'Voulez-vous vraiment verrouiller votre compte Expensify ?',
         onceLocked: 'Une fois verrouillé, votre compte sera restreint en attendant une demande de déverrouillage et un contrôle de sécurité',
-        unlockTitle: 'Nous avons bien reçu votre demande',
-        unlockDescription: 'Nous examinerons le compte pour vérifier qu’il est sûr de le déverrouiller et nous vous contacterons via Concierge si nous avons des questions.',
     },
     failedToLockAccountPage: {
         failedToLockAccount: 'Échec du verrouillage du compte',
@@ -2254,13 +2031,6 @@ const translations: TranslationDeepObject<typeof en> = {
         chatToConciergeToUnlock: 'Discutez avec Concierge pour résoudre vos problèmes de sécurité et déverrouiller votre compte.',
         chatWithConcierge: 'Discuter avec Concierge',
     },
-    deviceManagementPage: {
-        title: 'Gestion des appareils',
-        description:
-            'Gérez tous les appareils sur lesquels vous vous êtes connecté avec votre compte Expensify. <a href="https://help.expensify.com/articles/new-expensify/settings/Manage-Logged-in-Devices">En savoir plus</a>.',
-        revoke: 'Révoquer',
-        unknownDevice: 'Appareil Inconnu',
-    },
     twoFactorAuth: {
         headerTitle: 'Authentification à deux facteurs',
         twoFactorAuthEnabled: 'Authentification à deux facteurs activée',
@@ -2272,10 +2042,11 @@ const translations: TranslationDeepObject<typeof en> = {
         disabled: 'L’authentification à deux facteurs est maintenant désactivée',
         noAuthenticatorApp: 'Vous n’aurez plus besoin d’une application d’authentification pour vous connecter à Expensify.',
         stepCodes: 'Codes de récupération',
-        keepCodesSafe: 'Conservez ces codes en lieu sûr !',
+        keepCodesSafe: 'Conservez ces codes de récupération en lieu sûr !',
         codesLoseAccess: dedent(`
-            Si vous perdez l’accès à votre application d’authentification et que vous n’avez pas ces codes, vous serez bloqué hors de votre compte.<br><br>
-            <strong>Remarque</strong> : L’activation de la 2FA vous déconnecte de toutes les autres sessions.
+            Si vous perdez l’accès à votre application d’authentification et que vous n’avez pas ces codes, vous perdrez l’accès à votre compte.
+
+            Remarque : la configuration de l’authentification à deux facteurs vous déconnectera de toutes les autres sessions actives.
         `),
         errorStepCodes: 'Veuillez copier ou télécharger les codes avant de continuer',
         stepVerify: 'Vérifier',
@@ -2283,7 +2054,6 @@ const translations: TranslationDeepObject<typeof en> = {
         authenticatorApp: 'application d’authentification',
         addKey: 'Ou ajoutez cette clé secrète à votre application d’authentification :',
         enterCode: 'Saisissez ensuite le code à six chiffres généré par votre application d’authentification.',
-        secretKey: 'clé secrète',
         stepSuccess: 'Terminé',
         enabled: 'Authentification à deux facteurs activée',
         congrats: 'Félicitations ! Vous bénéficiez désormais de cette sécurité supplémentaire.',
@@ -2298,14 +2068,6 @@ const translations: TranslationDeepObject<typeof en> = {
         twoFactorAuthIsRequiredCompany: 'Votre entreprise exige l’authentification à deux facteurs.',
         twoFactorAuthCannotDisable: 'Impossible de désactiver la 2FA',
         twoFactorAuthRequired: 'L’authentification à deux facteurs (2FA) est requise pour votre connexion Xero et ne peut pas être désactivée.',
-        replaceDevice: 'Remplacer l’appareil',
-        replaceDeviceTitle: 'Remplacer l’appareil d’authentification à deux facteurs',
-        verifyOldDeviceTitle: 'Vérifier l’ancien appareil',
-        verifyOldDeviceDescription: 'Saisissez le code à six chiffres de votre application d’authentification actuelle pour confirmer que vous y avez accès.',
-        verifyNewDeviceTitle: 'Configurer un nouvel appareil',
-        verifyNewDeviceDescription: 'Scannez le code QR avec votre nouvel appareil, puis saisissez le code pour terminer la configuration.',
-        downloadCodes: 'Télécharger les codes',
-        copyCodes: 'Copier les codes',
     },
     recoveryCodeForm: {
         error: {
@@ -2393,39 +2155,6 @@ const translations: TranslationDeepObject<typeof en> = {
             password: 'Veuillez saisir votre mot de passe Expensify',
         },
     },
-    personalCard: {
-        addPersonalCard: 'Ajouter une carte personnelle',
-        addCompanyCard: "Ajouter une carte d'entreprise",
-        lookingForCompanyCards: "Vous devez ajouter des cartes d'entreprise ?",
-        lookingForCompanyCardsDescription: 'Connectez vos propres cartes auprès de plus de 10 000 banques dans le monde.',
-        personalCardAdded: 'Carte personnelle ajoutée!',
-        personalCardAddedDescription: 'Félicitations, nous allons commencer à importer les transactions de votre carte.',
-        isPersonalCard: "S'agit-il d'une carte personnelle?",
-        thisIsPersonalCard: "Il s'agit d'une carte personnelle",
-        thisIsCompanyCard: "Il s'agit d'une carte d'entreprise",
-        askAdmin: 'Demander à votre administrateur',
-        warningDescription: ({isAdmin}: {isAdmin?: boolean}) =>
-            `Si oui, parfait ! Mais si c'est une carte d'<strong>entreprise</strong>, veuillez ${isAdmin ? "l'assigner depuis votre espace de travail." : "demander à votre administrateur de vous l'assigner depuis l'espace de travail."}`,
-        bankConnectionError: 'Problème de connexion bancaire',
-        bankConnectionDescription: "Veuillez réessayer d'ajouter vos cartes. Sinon, vous pouvez",
-        connectWithPlaid: 'vous connecter via Plaid.',
-        fixCard: 'Réparer la carte',
-        brokenConnection: 'La connexion de votre carte est rompue.',
-        conciergeBrokenConnection: ({cardName, connectionLink}: ConciergeBrokenCardConnectionParams) =>
-            connectionLink
-                ? `La connexion de votre carte ${cardName} est rompue. <a href="${connectionLink}">Connectez-vous à votre banque</a> pour corriger la carte.`
-                : `La connexion de votre carte ${cardName} est rompue. Connectez-vous à votre banque pour corriger la carte.`,
-        addAdditionalCards: "Ajouter d'autres cartes",
-        upgradeDescription: "Vous devez ajouter plus de cartes ? Créez un espace de travail pour ajouter des cartes personnelles ou assigner des cartes d'entreprise à toute l'équipe.",
-        onlyAvailableOnPlan: ({formattedPrice}: {formattedPrice: string}) =>
-            `<muted-text>Disponible dans le forfait Collect, à <strong>${formattedPrice}</strong> par membre et par mois.</muted-text>`,
-        note: (subscriptionLink: string) =>
-            `<muted-text>Créez un espace de travail pour accéder à cette fonctionnalité, ou <a href="${subscriptionLink}">en savoir plus</a> sur nos forfaits et tarifs.</muted-text>`,
-        workspaceCreated: 'Espace de travail créé',
-        newWorkspace: 'Vous avez créé un espace de travail !',
-        successMessage: ({subscriptionLink}: {subscriptionLink: string}) =>
-            `<centered-text>Vous pouvez maintenant ajouter d'autres cartes. <a href="${subscriptionLink}">Voir votre abonnement</a> pour plus de détails.</centered-text>`,
-    },
     walletPage: {
         balance: 'Solde',
         paymentMethodsTitle: 'Moyens de paiement',
@@ -2453,9 +2182,8 @@ const translations: TranslationDeepObject<typeof en> = {
         enableWallet: 'Activer le portefeuille',
         addBankAccountToSendAndReceive: 'Ajoutez un compte bancaire pour effectuer ou recevoir des paiements.',
         addDebitOrCreditCard: 'Ajouter une carte de débit ou de crédit',
-        cardInactive: 'Inactif',
-        assignedCards: 'Cartes',
-        assignedCardsDescription: 'Les transactions des cartes assignées se synchronisent automatiquement.',
+        assignedCards: 'Cartes assignées',
+        assignedCardsDescription: 'Les transactions de ces cartes se synchronisent automatiquement.',
         expensifyCard: 'Carte Expensify',
         walletActivationPending: 'Nous examinons vos informations. Veuillez revenir vérifier dans quelques minutes !',
         walletActivationFailed: 'Malheureusement, votre portefeuille ne peut pas être activé pour le moment. Veuillez discuter avec Concierge pour obtenir une assistance supplémentaire.',
@@ -2479,13 +2207,8 @@ const translations: TranslationDeepObject<typeof en> = {
         unshareBankAccountDescription:
             'Toutes les personnes ci-dessous ont accès à ce compte bancaire. Vous pouvez supprimer l’accès à tout moment. Nous finaliserons tout de même les paiements en cours.',
         unshareBankAccountWarning: ({admin}: {admin?: string | null}) => `${admin} perdra l’accès à ce compte bancaire professionnel. Nous terminerons tout de même les paiements en cours.`,
-        reachOutForHelp: 'Elle est utilisée avec la Carte Expensify. <concierge-link>Contactez Concierge</concierge-link> si vous devez arrêter de la partager.',
+        reachOutForHelp: 'Elle est utilisée avec la carte Expensify. <concierge-link>Contactez Concierge</concierge-link> si vous devez arrêter de la partager.',
         unshareErrorModalTitle: 'Impossible d’annuler le partage du compte bancaire',
-        travelCVV: {
-            title: 'Cryptogramme visuel de la carte de voyage (CVV)',
-            subtitle: 'À utiliser lors de la réservation de voyages',
-            description: 'Utilisez cette carte pour vos réservations Expensify Travel. Elle apparaîtra comme “Travel Card” lors du paiement.',
-        },
         chaseAccountNumberDifferent: 'Pourquoi mon numéro de compte est-il différent ?',
     },
     cardPage: {
@@ -2494,16 +2217,16 @@ const translations: TranslationDeepObject<typeof en> = {
         availableSpend: 'Plafond restant',
         smartLimit: {
             name: 'Limite intelligente',
-            title: (formattedLimit: string) =>
+            title: ({formattedLimit}: ViolationsOverLimitParams) =>
                 `Vous pouvez dépenser jusqu'à ${formattedLimit} avec cette carte, et la limite sera réinitialisée au fur et à mesure que vos dépenses soumises seront approuvées.`,
         },
         fixedLimit: {
             name: 'Limite fixe',
-            title: (formattedLimit: string) => `Vous pouvez dépenser jusqu’à ${formattedLimit} avec cette carte, après quoi elle sera désactivée.`,
+            title: ({formattedLimit}: ViolationsOverLimitParams) => `Vous pouvez dépenser jusqu’à ${formattedLimit} avec cette carte, après quoi elle sera désactivée.`,
         },
         monthlyLimit: {
             name: 'Plafond mensuel',
-            title: (formattedLimit: string) =>
+            title: ({formattedLimit}: ViolationsOverLimitParams) =>
                 `Vous pouvez dépenser jusqu’à ${formattedLimit} avec cette carte par mois. La limite sera réinitialisée le 1er jour de chaque mois calendaire.`,
         },
         virtualCardNumber: 'Numéro de carte virtuelle',
@@ -2525,11 +2248,9 @@ const translations: TranslationDeepObject<typeof en> = {
             expiration: 'Expiration',
             cvv: 'Cryptogramme visuel (CVV)',
             address: 'Adresse',
-            reveal: 'Afficher',
             revealDetails: 'Afficher les détails',
             revealCvv: 'Afficher le cryptogramme',
             copyCardNumber: 'Copier le numéro de carte',
-            copyCvv: 'Copier le CVV',
             updateAddress: 'Mettre à jour l’adresse',
         },
         cardAddedToWallet: ({platform}: {platform: 'Google' | 'Apple'}) => `Ajouté au portefeuille ${platform}`,
@@ -2537,6 +2258,7 @@ const translations: TranslationDeepObject<typeof en> = {
         validateCardTitle: 'Vérifions que c’est bien vous',
         enterMagicCode: (contactMethod: string) =>
             `Veuillez saisir le code magique envoyé à ${contactMethod} pour afficher les détails de votre carte. Il devrait arriver d’ici une à deux minutes.`,
+        missingPrivateDetails: ({missingDetailsLink}: {missingDetailsLink: string}) => `Veuillez <a href="${missingDetailsLink}">ajouter vos informations personnelles</a>, puis réessayer.`,
         unexpectedError: 'Une erreur s’est produite lors de la récupération des détails de votre carte Expensify. Veuillez réessayer.',
         cardFraudAlert: {
             confirmButtonText: 'Oui, je veux bien',
@@ -2558,43 +2280,6 @@ const translations: TranslationDeepObject<typeof en> = {
 
 ${amount} pour ${merchant} - ${date}`,
         },
-        setYourPin: 'Définir votre code PIN.',
-        confirmYourPin: 'Confirmez votre code PIN.',
-        changeYourPin: 'Saisissez un nouveau code PIN pour votre carte.',
-        confirmYourChangedPin: 'Confirmez votre nouveau code PIN.',
-        pinMustBeFourDigits: 'Le code PIN doit comporter exactement 4 chiffres.',
-        invalidPin: 'Veuillez choisir un code PIN plus sécurisé.',
-        pinMismatch: 'Les codes PIN ne correspondent pas. Veuillez réessayer.',
-        revealPin: 'Afficher le code PIN',
-        hidePin: 'Masquer le code PIN',
-        pin: 'Code PIN',
-        changePin: 'Modifier le code PIN',
-        pinChanged: 'Code PIN modifié !',
-        pinChangedHeader: 'Code PIN modifié',
-        pinChangedDescription: 'Vous êtes maintenant prêt à utiliser votre code PIN.',
-        changePinAtATM: 'Modifiez votre code PIN à n’importe quel distributeur automatique de billets',
-        changePinAtATMDescription: 'Ceci est obligatoire dans votre région. <concierge-link>Contacter Concierge</concierge-link> si vous avez des questions.',
-        freezeCard: 'Geler la carte',
-        unfreeze: 'Dégeler',
-        unfreezeCard: 'Dégeler la carte',
-        askToUnfreeze: 'Demander le dégel',
-        freezeDescription: 'Une carte gelée ne peut pas être utilisée pour des achats ni des transactions. Vous pouvez la dégeler à tout moment.',
-        unfreezeDescription:
-            'Dégeler cette carte permettra à nouveau les achats et les transactions. Continuez uniquement si vous êtes sûr(e) que la carte peut être utilisée en toute sécurité.',
-        frozen: 'Gelée',
-        youFroze: ({date}: {date: string}) => `Vous avez gelé cette carte le ${date}.`,
-        frozenBy: ({person, date}: {person: string; date: string}) => `${person} a gelé cette carte le ${date}.`,
-        frozenByAdminPrefix: ({date}: {date: string}) => `Cette carte a été gelée le ${date} par `,
-        frozenByAdminNeedsUnfreezePrefix: 'Cette carte a été gelée par ',
-        frozenByAdminNeedsUnfreezeSuffix: '. Veuillez contacter un administrateur pour la dégeler.',
-        frozenByAdminNeedsUnfreeze: ({person}: {person: string}) => `Cette carte a été gelée par ${person}. Veuillez contacter un administrateur pour la dégeler.`,
-        spendRules: 'Règles de dépense',
-        editSpendRules: 'Modifier les règles de dépenses',
-        cardUnblocked: 'Carte débloquée !',
-        cardUnblockedDescription: 'Il se peut que vous soyez invité à insérer votre carte dans le lecteur la prochaine fois que vous effectuerez un achat.',
-        pinBlocked: 'Votre carte a été bloquée en raison de saisies de code PIN incorrectes.',
-        unblock: 'Débloquer',
-        unblockCard: 'Débloquer la carte',
     },
     workflowsPage: {
         workflowTitle: 'Dépense',
@@ -2606,14 +2291,9 @@ ${amount} pour ${merchant} - ${date}`,
         addApprovalsTitle: 'Approbations',
         accessibilityLabel: ({members, approvers}: {members: string; approvers: string}) => `dépenses de ${members}, et l'approbateur est ${approvers}`,
         addApprovalButton: 'Ajouter un workflow d’approbation',
-        editWorkflowAction: 'Modifier',
-        addAgentAction: 'Ajouter un agent',
-        findWorkflow: 'Rechercher un flux de travail',
         addApprovalTip: 'Ce workflow par défaut s’applique à tous les membres, sauf si un workflow plus spécifique existe.',
         approver: 'Approbateur',
         addApprovalsDescription: 'Exiger une approbation supplémentaire avant d’autoriser un paiement.',
-        automateApprovalsWithAgentsTitle: 'Automatisez les approbations avec des agents',
-        automateApprovalsWithAgentsSubtitle: 'Ajoutez l’agent ci-dessous au flux de travail pour automatiser les approbations.',
         makeOrTrackPaymentsTitle: 'Paiements',
         makeOrTrackPaymentsDescription: 'Ajoutez un payeur autorisé pour les paiements effectués dans Expensify ou suivez les paiements effectués ailleurs.',
         customApprovalWorkflowEnabled:
@@ -2658,15 +2338,7 @@ ${amount} pour ${merchant} - ${date}`,
             title: 'Aucun membre à afficher',
             expensesFromSubtitle: 'Tous les membres de l’espace de travail appartiennent déjà à un circuit d’approbation existant.',
             approverSubtitle: 'Tous les approbateurs appartiennent à un workflow existant.',
-            bulkApproverSubtitle: 'Aucun approbateur ne correspond aux critères pour les rapports sélectionnés.',
         },
-        configureViaHR: ({provider}: {provider: string}) => `Configurer via ${provider}.`,
-        hrApprovalWorkflowLockedPrompt: ({provider}: {provider: string}) =>
-            `Les validations sont gérées par votre intégration ${provider}. Pour mettre à jour votre workflow de validation, accédez aux paramètres de connexion ${provider}.`,
-        goToHRSettings: ({provider}: {provider: string}) => `Aller aux paramètres ${provider}`,
-        approverFromProvider: ({provider}: {provider: string}) => `de la part de ${provider}`,
-        finalApprover: 'Approbateur final',
-        manager: 'Manager',
     },
     workflowsDelayedSubmissionPage: {
         autoReportingFrequencyErrorMessage: "La fréquence de soumission n'a pas pu être modifiée. Veuillez réessayer ou contacter l'assistance.",
@@ -2685,9 +2357,6 @@ ${amount} pour ${merchant} - ${date}`,
     },
     workflowsExpensesFromPage: {
         title: 'Dépenses de',
-        memberAlreadyInWorkflowTitle: 'Membre déjà dans un workflow',
-        memberAlreadyInWorkflowPrompt: ({memberName, approverName}: {memberName: string; approverName: string}) =>
-            `${memberName} fait déjà partie d’un workflow d’approbation qui soumet à ${approverName}. L’ajouter ici le déplacera vers ce workflow.`,
         header: 'Quand les membres suivants soumettent des dépenses :',
     },
     workflowsApproverPage: {
@@ -2719,16 +2388,6 @@ ${amount} pour ${merchant} - ${date}`,
         admins: 'Administrateurs',
         payer: 'Payer',
         paymentAccount: 'Compte de paiement',
-        shareBankAccount: {
-            shareTitle: "Partager l'accès au compte bancaire?",
-            shareDescription: ({admin}: {admin: string}) => `Vous devrez partager l'accès au compte bancaire avec ${admin} pour qu'il/elle soit le payeur.`,
-            validationTitle: 'Compte bancaire en attente de validation',
-            validationDescription: ({admin}: {admin: string}) =>
-                `Vous devez <a href="#">valider ce compte bancaire</a>. Une fois cette opération effectuée, vous pourrez partager l'accès au compte bancaire avec ${admin} pour en faire le payeur.`,
-            errorTitle: 'Impossible de modifier le payeur',
-            errorDescription: ({admin, owner}: {admin: string; owner: string}) =>
-                `${admin} n'a pas accès à ce compte bancaire, vous ne pouvez donc pas le désigner comme payeur. <a href="#">Discutez avec ${owner}</a> si le compte bancaire doit être partagé.`,
-        },
     },
     reportFraudPage: {
         title: 'Signaler une fraude à la carte virtuelle',
@@ -2740,7 +2399,6 @@ ${amount} pour ${merchant} - ${date}`,
     reportFraudConfirmationPage: {
         title: 'Fraude à la carte signalée',
         description: 'Nous avons définitivement désactivé votre carte actuelle. Lorsque vous retournerez consulter les détails de votre carte, une nouvelle carte virtuelle sera disponible.',
-        descriptionCardNotReplaced: 'Votre carte a été désactivée définitivement. Veuillez contacter un administrateur pour émettre une nouvelle carte.',
         buttonText: 'Compris, merci !',
     },
     activateCardPage: {
@@ -2750,7 +2408,7 @@ ${amount} pour ${merchant} - ${date}`,
         error: {
             thatDidNotMatch: 'Cela ne correspond pas aux 4 derniers chiffres de votre carte. Veuillez réessayer.',
             throttled:
-                'Vous avez saisi de manière incorrecte les 4 derniers chiffres de votre Carte Expensify trop de fois. Si vous êtes sûr que les chiffres sont corrects, veuillez contacter Concierge pour résoudre le problème. Sinon, réessayez plus tard.',
+                'Vous avez saisi de manière incorrecte les 4 derniers chiffres de votre carte Expensify trop de fois. Si vous êtes certain que les numéros sont corrects, veuillez contacter Concierge pour résoudre le problème. Sinon, réessayez plus tard.',
         },
     },
     getPhysicalCard: {
@@ -2775,7 +2433,7 @@ ${amount} pour ${merchant} - ${date}`,
         shipCard: 'Expédier la carte',
     },
     transferAmountPage: {
-        transfer: (amount: string) => `Virement${amount ? ` ${amount}` : ''}`,
+        transfer: ({amount}: TransferParams) => `Virement${amount ? ` ${amount}` : ''}`,
         instant: 'Instantané (carte de débit)',
         instantSummary: (rate: string, minAmount: string) => `Frais de ${rate} % (${minAmount} minimum)`,
         ach: '1 à 3 jours ouvrables (compte bancaire)',
@@ -2802,46 +2460,14 @@ ${amount} pour ${merchant} - ${date}`,
         defaultPaymentMethod: 'Par défaut',
         bankAccountLastFour: (lastFour: string) => `Compte bancaire • ${lastFour}`,
     },
-    agentsPage: {
-        title: 'Agents',
-        subtitle: 'Créez des agents pour gérer votre flux de travail. Évitez le travail manuel et gagnez des heures dans votre journée.',
-        newAgent: 'Nouvel agent',
-        emptyAgents: {title: 'Aucun agent créé', subtitle: 'Arrêtez de faire les choses manuellement. Donnez plutôt des instructions à un agent et gagnez beaucoup de temps.'},
-        error: {
-            genericAdd: "Un problème est survenu lors de l'ajout de cet agent",
-            genericUpdate: 'Un problème est survenu lors de la mise à jour de cet agent',
-            updateName: 'Un problème est survenu lors de la mise à jour du nom de cet agent',
-            updatePrompt: 'Un problème est survenu lors de la mise à jour des instructions de cet agent',
-            updateAvatar: "Un problème est survenu lors de la mise à jour de l'avatar de cet agent",
-        },
-    },
-    addAgentPage: {
-        title: 'Nouvel agent',
-        agentName: 'Nom de l’agent',
-        instructions: 'Rédiger des instructions personnalisées',
-        createAgent: 'Créer un agent',
-        editAvatar: "Changer d'avatar",
-        defaultAgentName: (displayName: string) => `Agent de ${displayName}`,
-        defaultPrompt:
-            'Rejeter les dépenses liées aux jeux d’argent, aux films ou à d’autres motifs manifestement non professionnels.\n\nRappeler à l’utilisateur d’inclure systématiquement une image du reçu où le pourboire est clairement visible.\n\nApprouver le rapport s’il est très similaire aux rapports précédents du même utilisateur.\n\nRejeter les rapports contenant plus de 500 $ de frais de déplacement.',
-    },
-    editAgentPage: {
-        title: 'Modifier l’agent',
-        agentName: 'Nom de l’agent',
-        instructions: 'Écrire des instructions personnalisées',
-        chatWithAgent: 'Discuter avec l’agent',
-        copilotIntoAccount: 'Copilote dans le compte',
-        deleteAgent: 'Supprimer l’agent',
-        deleteAgentTitle: 'Supprimer l’agent ?',
-        deleteAgentMessage: 'Voulez-vous vraiment supprimer cet agent ? Cette action est irréversible.',
-    },
-    editAgentAvatarPage: {title: 'Modifier l’avatar'},
-    editAgentNamePage: {title: 'Nom de l’agent'},
-    editAgentPromptPage: {title: 'Écrire des instructions personnalisées', error: {emptyPrompt: 'Veuillez saisir des instructions pour votre agent.'}},
     expenseRulesPage: {
         title: 'Règles de dépenses',
+        subtitle: 'Ces règles s’appliqueront à vos dépenses. Si vous soumettez dans un espace de travail, alors les règles de cet espace de travail peuvent les remplacer.',
         findRule: 'Rechercher une règle',
-        emptyRules: {title: 'Aucune règle pour le moment', subtitle: 'Ajoutez une règle pour automatiser la création de notes de frais.'},
+        emptyRules: {
+            title: 'Vous n’avez créé aucune règle',
+            subtitle: 'Ajoutez une règle pour automatiser la création de notes de frais.',
+        },
         changes: {
             billableUpdate: (value: boolean) => `Mettre à jour la dépense ${value ? 'facturable' : 'non refacturable'}`,
             categoryUpdate: (value: string) => `Mettre à jour la catégorie sur « ${value} »`,
@@ -2882,7 +2508,6 @@ ${amount} pour ${merchant} - ${date}`,
             deleteSinglePrompt: 'Voulez-vous vraiment supprimer cette règle ?',
             deleteMultiplePrompt: 'Voulez-vous vraiment supprimer ces règles ?',
         },
-        subtitle: 'Ces règles s’appliqueront à vos dépenses.',
     },
     preferencesPage: {
         appSection: {
@@ -2910,12 +2535,11 @@ ${amount} pour ${merchant} - ${date}`,
         },
     },
     reportDetailsPage: {
-        inWorkspace: (policyName: string) => `dans ${policyName}`,
+        inWorkspace: ({policyName}: ReportPolicyNameParams) => `dans ${policyName}`,
         generatingPDF: 'Générer le PDF',
         waitForPDF: 'Veuillez patienter pendant que nous générons le PDF.',
         errorPDF: 'Une erreur s’est produite lors de la tentative de génération de votre PDF',
         successPDF: 'Votre PDF a été généré ! S’il ne s’est pas téléchargé automatiquement, utilisez le bouton ci-dessous.',
-        goToRoom: 'Aller à la salle',
     },
     reportDescriptionPage: {
         roomDescription: 'Description de la salle',
@@ -2925,7 +2549,7 @@ ${amount} pour ${merchant} - ${date}`,
     groupChat: {
         lastMemberTitle: 'Attention !',
         lastMemberWarning: 'Comme vous êtes la dernière personne ici, partir rendra cette discussion inaccessible à tous les membres. Êtes-vous sûr de vouloir partir ?',
-        defaultReportName: (displayName: string) => `Discussion de groupe de ${displayName}`,
+        defaultReportName: ({displayName}: ReportArchiveReasonsClosedParams) => `Discussion de groupe de ${displayName}`,
     },
     languagePage: {
         language: 'Langue',
@@ -2944,26 +2568,19 @@ ${amount} pour ${merchant} - ${date}`,
                 label: 'Utiliser les paramètres de l’appareil',
             },
         },
-        highContrastMode: 'Mode contraste élevé',
-        enableHighContrast: 'Activer le contraste élevé',
-        disableHighContrast: 'Désactiver le contraste élevé',
         chooseThemeBelowOrSync: 'Choisissez un thème ci-dessous ou synchronisez avec les réglages de votre appareil.',
     },
     termsOfUse: {
         terms: `<muted-text-xs>En vous connectant, vous acceptez les <a href="${CONST.OLD_DOT_PUBLIC_URLS.TERMS_URL}">Conditions d'utilisation</a> et la <a href="${CONST.OLD_DOT_PUBLIC_URLS.PRIVACY_URL}">Politique de confidentialité</a>.</muted-text-xs>`,
-        license: `Les services de transfert d’argent sont fournis par ${CONST.WALLET.PROGRAM_ISSUERS.EXPENSIFY_PAYMENTS} (ID NMLS :2017010) conformément à ses <a href="${CONST.OLD_DOT_PUBLIC_URLS.LICENSES_URL}">licences</a>.`,
+        license: `<muted-text-xs>Le transfert d’argent est fourni par ${CONST.WALLET.PROGRAM_ISSUERS.EXPENSIFY_PAYMENTS} (NMLS ID:2017010) conformément à ses <a href="${CONST.OLD_DOT_PUBLIC_URLS.LICENSES_URL}">licences</a>.</muted-text-xs>`,
     },
     validateCodeForm: {
         magicCodeNotReceived: "Vous n'avez pas reçu de code magique ?",
-        avoidScamsMessage:
-            '<strong>Évitez les arnaques. Ne partagez votre code avec personne.</strong> Notre équipe ne vous appellera, ne vous enverra jamais de SMS ni d’e-mail pour demander ce code.',
         enterAuthenticatorCode: 'Veuillez saisir votre code d’authentification',
         enterRecoveryCode: 'Veuillez saisir votre code de récupération',
         requiredWhen2FAEnabled: 'Obligatoire lorsque l’authentification à deux facteurs est activée',
         requestNewCode: ({timeRemaining}: {timeRemaining: string}) => `Demander un nouveau code dans <a>${timeRemaining}</a>`,
         requestNewCodeAfterErrorOccurred: 'Demander un nouveau code',
-        timeRemainingAnnouncement: ({timeRemaining}) => `Temps restant : ${timeRemaining} ${timeRemaining === 1 ? 'seconde' : 'secondes'}`,
-        timeExpiredAnnouncement: 'Le temps est écoulé',
         error: {
             pleaseFillMagicCode: 'Veuillez saisir votre code magique',
             incorrectMagicCode: 'Code magique incorrect ou non valide. Veuillez réessayer ou demander un nouveau code.',
@@ -2993,8 +2610,6 @@ ${amount} pour ${merchant} - ${date}`,
     loginForm: {
         phoneOrEmail: 'Téléphone ou e-mail',
         error: {
-            agentSignInBlocked:
-                'Les comptes d’agent ne permettent pas de se connecter directement. Pour utiliser un agent, connectez-vous avec votre propre compte et accédez-y via Copilot.',
             invalidFormatEmailLogin: 'L’adresse e-mail saisie est invalide. Veuillez corriger le format et réessayer.',
         },
         cannotGetAccountDetails: 'Impossible de récupérer les détails du compte. Veuillez essayer de vous reconnecter.',
@@ -3014,37 +2629,25 @@ ${amount} pour ${merchant} - ${date}`,
         },
         getStarted: 'Commencer',
         whatsYourName: 'Comment vous appelez-vous ?',
-        peopleYouMayKnow: 'Vérifier si votre équipe est sur Expensify',
-        workspaceYouMayJoin: (domain: string, email: string) =>
-            `Saisissez le code envoyé à ${email} pour vérifier si quelqu’un de ${domain} a un espace de travail que vous pouvez rejoindre.`,
+        peopleYouMayKnow: 'Des personnes que vous connaissez probablement sont déjà ici ! Vérifiez votre adresse e-mail pour les rejoindre.',
+        workspaceYouMayJoin: ({domain, email}: WorkspaceYouMayJoin) => `Quelqu’un de ${domain} a déjà créé un espace de travail. Veuillez saisir le code magique envoyé à ${email}.`,
         joinAWorkspace: 'Rejoindre un espace de travail',
-        listOfWorkspaces: 'Voici la liste des espaces de travail auxquels vous pouvez rejoindre.',
-        skipForNow: 'Passer pour le moment',
-        workspaceMemberList: (employeeCount: number, policyOwner: string) => `${employeeCount} membre${employeeCount > 1 ? 's' : ''} • ${policyOwner}`,
+        listOfWorkspaces: 'Voici la liste des espaces de travail que vous pouvez rejoindre. Ne vous inquiétez pas, vous pourrez toujours les rejoindre plus tard si vous préférez.',
+        workspaceMemberList: ({employeeCount, policyOwner}: WorkspaceMemberList) => `${employeeCount} membre${employeeCount > 1 ? 's' : ''} • ${policyOwner}`,
         whereYouWork: 'Où travaillez-vous ?',
         errorSelection: 'Sélectionnez une option pour continuer',
         purpose: {
             title: 'Que voulez-vous faire aujourd’hui ?',
             errorContinue: 'Veuillez appuyer sur Continuer pour procéder à la configuration',
             errorBackButton: 'Veuillez terminer les questions de configuration pour commencer à utiliser l’application',
-            [CONST.ONBOARDING_CHOICES.EMPLOYER]: 'Soumettre des dépenses à mon employeur',
+            [CONST.ONBOARDING_CHOICES.EMPLOYER]: 'Me faire rembourser par mon employeur',
             [CONST.ONBOARDING_CHOICES.MANAGE_TEAM]: 'Gérer les dépenses de mon équipe',
-            [CONST.ONBOARDING_CHOICES.TRACK_BUSINESS]: 'Suivre les dépenses de mon entreprise',
-            [CONST.ONBOARDING_CHOICES.TRACK_PERSONAL]: 'Organiser mes dépenses personnelles',
+            [CONST.ONBOARDING_CHOICES.PERSONAL_SPEND]: 'Suivre et budgéter les dépenses',
+            [CONST.ONBOARDING_CHOICES.CHAT_SPLIT]: 'Discutez et partagez les dépenses avec des amis',
             [CONST.ONBOARDING_CHOICES.LOOKING_AROUND]: 'Autre chose',
         },
-        personalTrackGoal: {
-            title: 'Que souhaitez-vous suivre ?',
-            [CONST.ONBOARDING_PERSONAL_TRACK_GOALS.INVESTMENT_TRACKING]: 'Coûts pour un bien locatif',
-            [CONST.ONBOARDING_PERSONAL_TRACK_GOALS.HOUSEHOLD_TRACKING]: 'Dépenses ménagères',
-            [CONST.ONBOARDING_PERSONAL_TRACK_GOALS.SIDEPROJECT_TRACKING]: 'Dépenses de projet annexe',
-            [CONST.ONBOARDING_PERSONAL_TRACK_GOALS.SOMETHING_ELSE]: 'Autre chose',
-            somethingElsePlaceholder: 'Qu’est-ce que vous suivez ?',
-        },
         employees: {
             title: 'Combien d’employés avez-vous ?',
-            [CONST.ONBOARDING_COMPANY_SIZE.MICRO_SMALL]: '1 à 4 employés',
-            [CONST.ONBOARDING_COMPANY_SIZE.MICRO_MEDIUM]: '5 à 10 employés',
             [CONST.ONBOARDING_COMPANY_SIZE.MICRO]: '1 à 10 employés',
             [CONST.ONBOARDING_COMPANY_SIZE.SMALL]: '11 à 50 employés',
             [CONST.ONBOARDING_COMPANY_SIZE.MEDIUM_SMALL]: '51 à 100 employés',
@@ -3075,19 +2678,16 @@ ${amount} pour ${merchant} - ${date}`,
         },
         workEmailValidation: {
             title: 'Vérifiez votre adresse e-mail professionnelle',
-            magicCodeSent: (workEmail: string | undefined) => `Veuillez saisir le code magique envoyé à ${workEmail}. Il devrait arriver d’ici une à deux minutes.`,
+            magicCodeSent: ({workEmail}: WorkEmailResendCodeParams) => `Veuillez saisir le code magique envoyé à ${workEmail}. Il devrait arriver d’ici une à deux minutes.`,
         },
         workEmailValidationError: {
             publicEmail: 'Veuillez saisir une adresse e-mail professionnelle valide provenant d’un domaine privé, par ex. mitch@company.com',
-            sameAsSignupEmail: 'Veuillez saisir une adresse e-mail différente de celle avec laquelle vous vous êtes inscrit',
             offline: 'Nous n’avons pas pu ajouter votre adresse e-mail professionnelle, car vous semblez être hors ligne',
         },
         mergeBlockScreen: {
             title: 'Impossible d’ajouter l’adresse e-mail professionnelle',
-            subtitle: (workEmail: string | undefined) =>
+            subtitle: ({workEmail}: WorkEmailMergingBlockedParams) =>
                 `Nous n’avons pas pu ajouter ${workEmail}. Veuillez réessayer plus tard dans les Paramètres ou discuter avec Concierge pour obtenir de l’aide.`,
-            workAccountClosedSubtitle:
-                'Le compte professionnel associé à cet e-mail est fermé. Veuillez contacter l’administrateur de votre entreprise pour le réactiver, ou inscrivez-vous avec un autre e-mail.',
         },
         tasks: {
             testDriveAdminTask: {
@@ -3118,7 +2718,7 @@ ${amount} pour ${merchant} - ${date}`,
             },
             createTestDriveAdminWorkspaceTask: {
                 title: ({workspaceConfirmationLink}) => `[Créer](${workspaceConfirmationLink}) un espace de travail`,
-                description: 'Créez un espace de travail et configurez les paramètres avec l’aide de votre chargé de compte !',
+                description: 'Créez un espace de travail et configurez les paramètres avec l’aide de votre spécialiste de configuration !',
             },
             createWorkspaceTask: {
                 title: ({workspaceSettingsLink}) => `Créer un [espace de travail](${workspaceSettingsLink})`,
@@ -3134,7 +2734,7 @@ ${amount} pour ${merchant} - ${date}`,
                 title: ({workspaceCategoriesLink}) => `Configurer les [catégories](${workspaceCategoriesLink})`,
                 description: ({workspaceCategoriesLink}) =>
                     dedent(`
-                        *Configurez les catégories* pour que votre équipe puisse coder les dépenses et faciliter le reporting.
+                        *Configurez des catégories* pour que votre équipe puisse coder les dépenses afin de faciliter les rapports.
 
                         1. Cliquez sur *Espaces de travail*.
                         2. Sélectionnez votre espace de travail.
@@ -3150,7 +2750,7 @@ ${amount} pour ${merchant} - ${date}`,
                 description: dedent(`
                     *Soumettez une dépense* en saisissant un montant ou en scannant un reçu.
 
-                    1. Cliquez sur le bouton *+*.
+                    1. Cliquez sur le bouton ${CONST.CUSTOM_EMOJIS.GLOBAL_CREATE}.
                     2. Choisissez *Créer une dépense*.
                     3. Saisissez un montant ou scannez un reçu.
                     4. Ajoutez l’e-mail ou le numéro de téléphone de votre responsable.
@@ -3164,7 +2764,7 @@ ${amount} pour ${merchant} - ${date}`,
                 description: dedent(`
                     *Soumettez une dépense* en saisissant un montant ou en scannant un reçu.
 
-                    1. Cliquez sur le bouton *+*.
+                    1. Cliquez sur le bouton ${CONST.CUSTOM_EMOJIS.GLOBAL_CREATE}.
                     2. Choisissez *Créer une dépense*.
                     3. Saisissez un montant ou scannez un reçu.
                     4. Confirmez les détails.
@@ -3178,7 +2778,7 @@ ${amount} pour ${merchant} - ${date}`,
                 description: dedent(`
                     *Enregistrez une dépense* dans n’importe quelle devise, que vous ayez un reçu ou non.
 
-                    1. Cliquez sur le bouton *+*.
+                    1. Cliquez sur le bouton ${CONST.CUSTOM_EMOJIS.GLOBAL_CREATE}.
                     2. Choisissez *Créer une dépense*.
                     3. Saisissez un montant ou scannez un reçu.
                     4. Choisissez votre espace *personnel*.
@@ -3200,8 +2800,13 @@ ${amount} pour ${merchant} - ${date}`,
                         4. Recherchez ${integrationName}.
                         5. Cliquez sur *Connecter*.
 
-                        [Accéder à la comptabilité](${workspaceAccountingLink}).
-                    `),
+${
+    integrationName && CONST.connectionsVideoPaths[integrationName]
+        ? `[Accéder à la comptabilité](${workspaceAccountingLink}).
+
+                        ![Se connecter à ${integrationName}](${CONST.CLOUDFRONT_URL}/${CONST.connectionsVideoPaths[integrationName]})`
+        : `[Accéder à la comptabilité](${workspaceAccountingLink}).`
+}`),
             },
             connectCorporateCardTask: {
                 title: ({corporateCardLink}) => `Connectez [vos cartes d’entreprise](${corporateCardLink})`,
@@ -3220,12 +2825,12 @@ ${amount} pour ${merchant} - ${date}`,
                 title: ({workspaceMembersLink}) => `Invitez [votre équipe](${workspaceMembersLink})`,
                 description: ({workspaceMembersLink}) =>
                     dedent(`
-                        *Invitez votre équipe* sur Expensify afin qu’elle puisse commencer à suivre ses dépenses dès aujourd’hui.
+                        *Invitez votre équipe* sur Expensify pour qu’elle puisse commencer à suivre ses dépenses dès aujourd’hui.
 
                         1. Cliquez sur *Espaces de travail*.
                         2. Sélectionnez votre espace de travail.
                         3. Cliquez sur *Membres* > *Inviter un membre*.
-                        4. Saisissez des e-mails ou des numéros de téléphone.
+                        4. Saisissez des adresses e-mail ou des numéros de téléphone.
                         5. Ajoutez un message d’invitation personnalisé si vous le souhaitez !
 
                         [Aller aux membres de l’espace de travail](${workspaceMembersLink}).
@@ -3243,7 +2848,7 @@ ${amount} pour ${merchant} - ${date}`,
                 title: ({workspaceTagsLink}) => `Configurer les [tags](${workspaceTagsLink})`,
                 description: ({workspaceMoreFeaturesLink}) =>
                     dedent(`
-                        Utilisez les tags pour ajouter des détails supplémentaires sur les dépenses, comme les projets, les clients, les lieux et les services. Si vous avez besoin de plusieurs niveaux de tags, vous pouvez passer au plan Control.
+                        Utilisez des tags pour ajouter des détails supplémentaires à vos dépenses, comme les projets, clients, lieux et services. Si vous avez besoin de plusieurs niveaux de tags, vous pouvez passer au plan Contrôle.
 
                         1. Cliquez sur *Espaces de travail*.
                         2. Sélectionnez votre espace de travail.
@@ -3275,7 +2880,7 @@ ${amount} pour ${merchant} - ${date}`,
                 description: dedent(`
                     *Lancez une discussion* avec n'importe qui en utilisant son e-mail ou son numéro de téléphone.
 
-                    1. Cliquez sur le bouton *+*.
+                    1. Cliquez sur le bouton ${CONST.CUSTOM_EMOJIS.GLOBAL_CREATE}.
                     2. Choisissez *Démarrer une discussion*.
                     3. Saisissez une adresse e-mail ou un numéro de téléphone.
 
@@ -3289,7 +2894,7 @@ ${amount} pour ${merchant} - ${date}`,
                 description: dedent(`
                     *Répartissez les dépenses* avec une ou plusieurs personnes.
 
-                    1. Cliquez sur le bouton *+*.
+                    1. Cliquez sur le bouton ${CONST.CUSTOM_EMOJIS.GLOBAL_CREATE}.
                     2. Choisissez *Démarrer une discussion*.
                     3. Saisissez des e-mails ou des numéros de téléphone.
                     4. Cliquez sur le bouton *+* gris dans la discussion > *Répartir la dépense*.
@@ -3313,7 +2918,7 @@ ${amount} pour ${merchant} - ${date}`,
                 description: dedent(`
                     Voici comment créer une note de frais :
 
-                    1. Cliquez sur le bouton *+*.
+                    1. Cliquez sur le bouton ${CONST.CUSTOM_EMOJIS.GLOBAL_CREATE}.
                     2. Choisissez *Créer une note de frais*.
                     3. Cliquez sur *Ajouter une dépense*.
                     4. Ajoutez votre première dépense.
@@ -3336,15 +2941,18 @@ ${amount} pour ${merchant} - ${date}`,
                 isOnboardingFlow
                     ? dedent(`
                         # Votre essai gratuit a commencé ! Configurons tout cela.
-                        👋 Bonjour, je suis votre chargé de compte Expensify. J’ai déjà créé un espace de travail pour vous aider à gérer les reçus et les dépenses de votre équipe. Pour tirer le meilleur parti de votre essai gratuit de 30 jours, il vous suffit de suivre les dernières étapes de configuration ci-dessous !
+                        👋 Bonjour, je suis votre spécialiste de configuration Expensify. J’ai déjà créé un espace de travail pour vous aider à gérer les reçus et les dépenses de votre équipe. Pour tirer le meilleur parti de votre essai gratuit de 30 jours, il vous suffit de suivre les étapes de configuration restantes ci-dessous !
                     `)
                     : dedent(`
                         # Votre essai gratuit a commencé ! Configurons tout cela.
-                        👋 Bonjour, je suis votre chargé de compte Expensify. Maintenant que vous avez créé un espace de travail, profitez au maximum de vos 30 jours d’essai gratuit en suivant les étapes ci-dessous !
+                        👋 Bonjour, je suis votre spécialiste de configuration Expensify. Maintenant que vous avez créé un espace de travail, profitez au maximum de votre essai gratuit de 30 jours en suivant les étapes ci-dessous !
                     `),
-            onboardingTrackWorkspaceMessage: 'Pour tirer le meilleur parti de votre essai gratuit de 30 jours, suivez les étapes restantes ci-dessous :',
+            onboardingTrackWorkspaceMessage:
+                '# Nous allons vous configurer tout ça\n👋 Bonjour, je suis votre spécialiste de configuration Expensify. J’ai déjà créé un espace de travail pour vous aider à gérer vos reçus et vos dépenses. Pour profiter pleinement de vos 30 jours d’essai gratuit, suivez simplement les dernières étapes de configuration ci-dessous !',
             onboardingChatSplitMessage: 'Partager des notes de frais avec des amis est aussi simple que d’envoyer un message. Voici comment faire.',
             onboardingAdminMessage: 'Découvrez comment gérer l’espace de travail de votre équipe en tant qu’administrateur et soumettre vos propres dépenses.',
+            onboardingLookingAroundMessage:
+                'Expensify est surtout connu pour la gestion des dépenses, des voyages et des cartes d’entreprise, mais nous faisons bien plus que cela. Dites-moi ce qui vous intéresse et je vous aiderai à démarrer.',
             onboardingTestDriveReceiverMessage: '*Vous bénéficiez de 3 mois gratuits ! Commencez ci-dessous.*',
         },
         workspace: {
@@ -3355,7 +2963,7 @@ ${amount} pour ${merchant} - ${date}`,
                 descriptionTwo: 'Catégoriser et taguer les dépenses',
                 descriptionThree: 'Créer et partager des notes de frais',
             },
-            price: (price?: string) => `Essayez-le gratuitement pendant 30 jours, puis passez à l’offre supérieure pour seulement <strong>${price ?? '5 $'}/utilisateur/mois</strong>.`,
+            price: 'Essayez-le gratuitement pendant 30 jours, puis passez à l’offre supérieure pour seulement <strong>5 $/utilisateur/mois</strong>.',
             createWorkspace: 'Créer un espace de travail',
         },
         confirmWorkspace: {
@@ -3367,8 +2975,6 @@ ${amount} pour ${merchant} - ${date}`,
             title: 'Inviter des membres',
             subtitle: 'Ajoutez votre équipe ou invitez votre comptable. Plus on est de fous, plus on rit !',
         },
-        workEmail2FAError: 'Cette connexion est un compte existant avec l’authentification à deux facteurs (2FA) activée.',
-        singleSignOnError: 'Cette connexion correspond à un compte existant avec SSO/SAML activé.',
     },
     featureTraining: {
         doNotShowAgain: 'Ne plus m’afficher ceci',
@@ -3388,7 +2994,6 @@ ${amount} pour ${merchant} - ${date}`,
         enterPhoneNumber: 'Quel est votre numéro de téléphone ?',
         personalDetails: 'Informations personnelles',
         privateDataMessage: 'Ces informations sont utilisées pour les déplacements et les paiements. Elles ne s’affichent jamais sur votre profil public.',
-        basicDetails: 'Détails de base',
         legalName: 'Nom légal',
         legalFirstName: 'Prénom légal',
         legalLastName: 'Nom de famille légal',
@@ -3397,18 +3002,18 @@ ${amount} pour ${merchant} - ${date}`,
             dateShouldBeBefore: (dateString: string) => `La date doit être antérieure au ${dateString}`,
             dateShouldBeAfter: (dateString: string) => `La date doit être postérieure au ${dateString}`,
             hasInvalidCharacter: 'Le nom peut uniquement contenir des caractères latins',
-            cannotIncludeCommaOrSemicolon: 'Le nom ne peut pas contenir de virgule ni de point-virgule',
             incorrectZipFormat: (zipFormat?: string) => `Format de code postal incorrect${zipFormat ? `Format acceptable : ${zipFormat}` : ''}`,
             invalidPhoneNumber: `Veuillez vous assurer que le numéro de téléphone est valide (p. ex. ${CONST.EXAMPLE_PHONE_NUMBER})`,
         },
     },
     resendValidationForm: {
         linkHasBeenResent: 'Le lien a été renvoyé',
-        weSentYouMagicSignInLink: (login: string, loginType: string) => `J’ai envoyé un lien magique de connexion à ${login}. Veuillez consulter votre ${loginType} pour vous connecter.`,
+        weSentYouMagicSignInLink: ({login, loginType}: WeSentYouMagicSignInLinkParams) =>
+            `J’ai envoyé un lien magique de connexion à ${login}. Veuillez consulter votre ${loginType} pour vous connecter.`,
         resendLink: 'Renvoyer le lien',
     },
     unlinkLoginForm: {
-        toValidateLogin: (primaryLogin: string, secondaryLogin: string) =>
+        toValidateLogin: ({primaryLogin, secondaryLogin}: ToValidateLoginParams) =>
             `Pour valider ${secondaryLogin}, veuillez renvoyer le code magique depuis les paramètres de compte de ${primaryLogin}.`,
         noLongerHaveAccess: (primaryLogin: string) => `Si vous n'avez plus accès à ${primaryLogin}, veuillez dissocier vos comptes.`,
         unlink: 'Dissocier',
@@ -3466,7 +3071,6 @@ ${amount} pour ${merchant} - ${date}`,
     },
     welcomeSignUpForm: {
         join: 'Rejoindre',
-        marketingSMSConsent: "J'accepte de recevoir des SMS marketing d'Expensify",
     },
     detailsPage: {
         localTime: 'Heure locale',
@@ -3474,7 +3078,6 @@ ${amount} pour ${merchant} - ${date}`,
     newChatPage: {
         startGroup: 'Commencer le groupe',
         addToGroup: 'Ajouter au groupe',
-        addUserToGroup: (username: string) => `Ajouter ${username} au groupe`,
     },
     yearPickerPage: {
         year: 'Année',
@@ -3518,18 +3121,18 @@ ${amount} pour ${merchant} - ${date}`,
             custom: 'Personnalisé',
         },
         untilTomorrow: 'Jusqu’à demain',
-        untilTime: (time: string) => `Jusqu’à ${time}`,
+        untilTime: ({time}: UntilTimeParams) => `Jusqu’à ${time}`,
         date: 'Date',
         time: 'Heure',
         clearAfter: 'Effacer après',
         whenClearStatus: 'Quand devons-nous effacer votre statut ?',
+        vacationDelegate: 'Délégué de vacances',
         setVacationDelegate: `Définissez un délégué de vacances pour approuver les notes de frais en votre nom pendant votre absence du bureau.`,
-        cannotSetVacationDelegate: `Vous ne pouvez pas définir un délégué de vacances car vous êtes actuellement le délégué des membres suivants :`,
-        addVacationDelegate: 'Ajouter un délégué de vacances',
         vacationDelegateError: 'Une erreur s’est produite lors de la mise à jour de votre remplaçant de congés.',
-        asVacationDelegate: (nameOrEmail: string) => `en tant que délégué de vacances de ${nameOrEmail}`,
-        toAsVacationDelegate: (submittedToName: string, vacationDelegateName: string) => `à ${submittedToName} en tant que délégué de congés pour ${vacationDelegateName}`,
-        vacationDelegateWarning: (nameOrEmail: string) =>
+        asVacationDelegate: ({nameOrEmail}: VacationDelegateParams) => `en tant que délégué de vacances de ${nameOrEmail}`,
+        toAsVacationDelegate: ({submittedToName, vacationDelegateName}: SubmittedToVacationDelegateParams) =>
+            `à ${submittedToName} en tant que délégué de congés pour ${vacationDelegateName}`,
+        vacationDelegateWarning: ({nameOrEmail}: VacationDelegateParams) =>
             `Vous assignez ${nameOrEmail} comme remplaçant pendant vos congés. Cette personne n’est pas encore présente dans tous vos espaces de travail. Si vous choisissez de continuer, un e-mail sera envoyé aux administrateurs de tous vos espaces de travail pour l’ajouter.`,
     },
     stepCounter: ({step, total, text}: StepCounterParams) => {
@@ -3559,35 +3162,23 @@ ${amount} pour ${merchant} - ${date}`,
         desktopConnection: 'Remarque : pour vous connecter à Chase, Wells Fargo, Capital One ou Bank of America, veuillez cliquer ici pour terminer cette procédure dans un navigateur.',
         yourDataIsSecure: 'Vos données sont sécurisées',
         toGetStarted:
-            'Ajoutez un compte bancaire pour rembourser des dépenses, émettre des Cartes Expensify, encaisser des paiements de factures et payer des factures, le tout à partir d’un seul endroit.',
+            'Ajoutez un compte bancaire pour rembourser des dépenses, émettre des cartes Expensify, encaisser des paiements de factures et payer des factures, le tout à partir d’un seul endroit.',
         plaidBodyCopy: 'Offrez à vos employés un moyen plus simple de payer – et d’être remboursés – pour les dépenses de l’entreprise.',
         checkHelpLine: 'Votre numéro de routage et votre numéro de compte se trouvent sur un chèque lié à ce compte.',
-        bankAccountPurposeTitle: 'Que voulez-vous faire avec votre compte bancaire?',
-        getReimbursed: 'Être remboursé',
-        getReimbursedDescription: "Par l'employeur ou d'autres",
-        makePayments: 'Effectuer des paiements',
-        makePaymentsDescription: 'Payer des dépenses ou émettre des Cartes Expensify',
         hasPhoneLoginError: (contactMethodRoute: string) =>
             `Pour connecter un compte bancaire, veuillez <a href="${contactMethodRoute}">ajouter une adresse e-mail comme identifiant principal</a> puis réessayer. Vous pouvez ajouter votre numéro de téléphone comme identifiant secondaire.`,
         hasBeenThrottledError: 'Une erreur s’est produite lors de l’ajout de votre compte bancaire. Veuillez patienter quelques minutes, puis réessayer.',
-        hasCurrencyError: (workspaceRoute: string) =>
+        hasCurrencyError: ({workspaceRoute}: WorkspaceRouteParams) =>
             `Oups ! Il semble que la devise de votre espace de travail soit définie sur une devise différente du dollar américain (USD). Pour continuer, veuillez accéder aux <a href="${workspaceRoute}">paramètres de votre espace de travail</a>, la définir sur USD, puis réessayer.`,
         bbaAdded: 'Compte bancaire professionnel ajouté !',
         bbaAddedDescription: 'Il est prêt à être utilisé pour les paiements.',
-        lockedBankAccount: 'Compte bancaire verrouillé',
-        unlockBankAccount: 'Déverrouiller le compte bancaire',
-        youCantPayThis: `Vous ne pouvez pas payer ce rapport car vous avez un <a href="${CONST.UNLOCK_BANK_ACCOUNT_HELP_URL}">compte bancaire verrouillé</a>. Appuyez ci-dessous et le Concierge vous aidera à le déverrouiller.`,
-        htmlUnlockMessage: (maskedAccountNumber: string) =>
-            `<h1>Expensify Business Bank Account ${maskedAccountNumber}</h1><p>Merci d'avoir soumis une demande de déblocage de votre compte bancaire. Les demandes de retrait peuvent être rejetées en raison de fonds insuffisants ou si le compte bancaire n'a pas été activé pour le prélèvement automatique. Nous examinerons votre dossier et vous contacterons si nous avons besoin d'informations supplémentaires pour résoudre ce problème.</p>`,
-        textUnlockMessage: (maskedAccountNumber: string) =>
-            `Expensify Business Bank Account ${maskedAccountNumber}\nMerci d'avoir soumis une demande de déblocage de votre compte bancaire. Les demandes de retrait peuvent être rejetées en raison de fonds insuffisants ou si le compte bancaire n'a pas été activé pour le prélèvement automatique. Nous examinerons votre dossier et vous contacterons si nous avons besoin d'informations supplémentaires pour résoudre ce problème.`,
         error: {
             youNeedToSelectAnOption: 'Veuillez sélectionner une option pour continuer',
             noBankAccountAvailable: 'Désolé, aucun compte bancaire n’est disponible',
             noBankAccountSelected: 'Veuillez choisir un compte',
             taxID: 'Veuillez saisir un numéro d’identification fiscale valide',
             website: 'Veuillez saisir un site web valide',
-            zipCode: `Veuillez saisir un code postal valide au format : ${COMMON_CONST.COUNTRY_ZIP_REGEX_DATA.US.samples}`,
+            zipCode: `Veuillez saisir un code postal valide au format : ${CONST.COUNTRY_ZIP_REGEX_DATA.US.samples}`,
             phoneNumber: 'Veuillez saisir un numéro de téléphone valide',
             email: 'Veuillez saisir une adresse e-mail valide',
             companyName: 'Veuillez saisir un nom d’entreprise valide',
@@ -3615,7 +3206,7 @@ ${amount} pour ${merchant} - ${date}`,
             fullName: 'Veuillez saisir un nom complet valide',
             ownershipPercentage: 'Veuillez saisir un nombre de pourcentage valide',
             deletePaymentBankAccount:
-                'Ce compte bancaire ne peut pas être supprimé car il est utilisé pour les paiements par Carte Expensify. Si vous souhaitez tout de même supprimer ce compte, veuillez contacter Concierge.',
+                'Ce compte bancaire ne peut pas être supprimé car il est utilisé pour les paiements de la Carte Expensify. Si vous souhaitez malgré tout le supprimer, veuillez contacter Concierge.',
             sameDepositAndWithdrawalAccount: 'Les comptes de dépôt et de retrait sont identiques.',
         },
     },
@@ -3630,11 +3221,6 @@ ${amount} pour ${merchant} - ${date}`,
         confirmationStepHeader: 'Vérifiez vos informations.',
         confirmationStepSubHeader: 'Vérifiez attentivement les détails ci-dessous et cochez la case des conditions pour confirmer.',
         toGetStarted: 'Ajoutez un compte bancaire personnel pour recevoir des remboursements, payer des factures ou activer le Portefeuille Expensify.',
-        updatePersonalInfo: 'Mettre à jour le compte bancaire',
-        updatePersonalInfoFailure: 'Impossible de mettre à jour les informations du compte bancaire. Veuillez réessayer plus tard.',
-        updateSuccessTitle: 'Compte bancaire mis à jour !',
-        updateSuccessHeader: 'Compte bancaire mis à jour',
-        updateSuccessMessage: 'Félicitations, votre compte bancaire est configuré et prêt à recevoir des remboursements.',
     },
     addPersonalBankAccountPage: {
         enterPassword: 'Saisissez le mot de passe Expensify',
@@ -3662,8 +3248,8 @@ ${amount} pour ${merchant} - ${date}`,
     messages: {
         errorMessageInvalidPhone: `Veuillez saisir un numéro de téléphone valide sans parenthèses ni tirets. Si vous êtes en dehors des États-Unis, veuillez inclure votre indicatif de pays (p. ex. ${CONST.EXAMPLE_PHONE_NUMBER}).`,
         errorMessageInvalidEmail: 'E-mail invalide',
-        userIsAlreadyMember: (login: string, name: string) => `${login} est déjà membre de ${name}`,
-        userIsAlreadyAnAdmin: (login: string, name: string) => `${login} est déjà administrateur de ${name}`,
+        userIsAlreadyMember: ({login, name}: UserIsAlreadyMemberParams) => `${login} est déjà membre de ${name}`,
+        userIsAlreadyAnAdmin: ({login, name}: UserIsAlreadyMemberParams) => `${login} est déjà administrateur de ${name}`,
     },
     onfidoStep: {
         acceptTerms: 'En poursuivant la demande d’activation de votre Portefeuille Expensify, vous confirmez que vous avez lu, compris et accepté',
@@ -3710,7 +3296,7 @@ ${amount} pour ${merchant} - ${date}`,
         haveReadAndAgreePlain: 'J’ai lu et j’accepte de recevoir les communications électroniques.',
         haveReadAndAgree: `J’ai lu et j’accepte de recevoir les <a href="${CONST.ELECTRONIC_DISCLOSURES_URL}">notifications électroniques</a>.`,
         agreeToThePlain: "J'accepte la politique de confidentialité et l'accord de portefeuille.",
-        agreeToThe: (walletAgreementUrl: string) =>
+        agreeToThe: ({walletAgreementUrl}: WalletAgreementParams) =>
             `J’accepte la <a href="${CONST.OLD_DOT_PUBLIC_URLS.PRIVACY_URL}">politique de confidentialité</a> et le <a href="${walletAgreementUrl}">contrat du portefeuille</a>.`,
         enablePayments: 'Activer les paiements',
         monthlyFee: 'Frais mensuels',
@@ -3722,7 +3308,7 @@ ${amount} pour ${merchant} - ${date}`,
         checkTheBoxes: 'Veuillez cocher les cases ci-dessous.',
         agreeToTerms: 'Acceptez les conditions et vous serez prêt à démarrer !',
         shortTermsForm: {
-            expensifyPaymentsAccount: (walletProgram: string) => `Le portefeuille Expensify est émis par ${walletProgram}.`,
+            expensifyPaymentsAccount: ({walletProgram}: WalletProgramParams) => `Le portefeuille Expensify est émis par ${walletProgram}.`,
             perPurchase: 'Par achat',
             atmWithdrawal: 'Retrait au distributeur',
             cashReload: 'Rechargement en espèces',
@@ -3736,7 +3322,7 @@ ${amount} pour ${merchant} - ${date}`,
             generalInfo: `Pour des informations générales sur les comptes prépayés, visitez <a href="${CONST.CFPB_PREPAID_URL}">${CONST.TERMS.CFPB_PREPAID}</a>.`,
             conditionsDetails: `Pour plus de détails et les conditions relatives à tous les frais et services, consultez <a href="${CONST.FEES_URL}">${CONST.FEES_URL}</a> ou appelez le +1 833-400-0904.`,
             electronicFundsWithdrawalInstant: 'Retrait de fonds électronique (instantané)',
-            electronicFundsInstantFeeMin: (amount: string) => `(min. ${amount})`,
+            electronicFundsInstantFeeMin: ({amount}: TermsParams) => `(min. ${amount})`,
         },
         longTermsForm: {
             listOfAllFees: 'Liste de tous les frais du Portefeuille Expensify',
@@ -3756,7 +3342,7 @@ ${amount} pour ${merchant} - ${date}`,
             electronicFundsInstantDetails: (percentage: string, amount: string) =>
                 'Des frais s’appliquent pour transférer des fonds de votre Portefeuille Expensify vers votre carte de débit liée en utilisant l’option de transfert instantané. Ce transfert est généralement effectué en quelques minutes.' +
                 `Les frais s’élèvent à ${percentage} % du montant du virement (avec des frais minimum de ${amount}).`,
-            fdicInsuranceBancorp: (amount: string) =>
+            fdicInsuranceBancorp: ({amount}: TermsParams) =>
                 `Vos fonds sont éligibles à l’assurance de la FDIC. Vos fonds seront détenus ou transférés à ${CONST.WALLET.PROGRAM_ISSUERS.BANCORP_BANK}, une institution assurée par la FDIC.` +
                 `Une fois là-bas, vos fonds sont assurés jusqu'à ${amount} par la FDIC au cas où ${CONST.WALLET.PROGRAM_ISSUERS.BANCORP_BANK} ferait défaut, si des exigences spécifiques en matière d’assurance des dépôts sont respectées et que votre carte est enregistrée. Voir ${CONST.TERMS.FDIC_PREPAID} pour plus de détails.`,
             contactExpensifyPayments: `Contactez ${CONST.WALLET.PROGRAM_ISSUERS.EXPENSIFY_PAYMENTS} en appelant le +1 833-400-0904, par e-mail à ${CONST.EMAIL.CONCIERGE} ou connectez-vous sur ${CONST.NEW_EXPENSIFY_URL}.`,
@@ -3765,7 +3351,7 @@ ${amount} pour ${merchant} - ${date}`,
             automated: 'Automatisé',
             liveAgent: 'Agent en direct',
             instant: 'Instantané',
-            electronicFundsInstantFeeMin: (amount: string) => `Min ${amount}`,
+            electronicFundsInstantFeeMin: ({amount}: TermsParams) => `Min ${amount}`,
         },
     },
     activateStep: {
@@ -4052,10 +3638,6 @@ ${amount} pour ${merchant} - ${date}`,
         youCanChange: 'Vous pouvez modifier la devise de votre espace de travail dans vos',
         findCountry: 'Rechercher un pays',
         selectCountry: 'Sélectionner un pays',
-        error: {
-            connectToWorkspace: (workspaceRoute: string) =>
-                `Ce compte bancaire doit être lié à un espace de travail. Allez dans <a href="${workspaceRoute}">Espaces de travail</a>, sélectionnez votre espace de travail, puis accédez à Flux de travail > Paiements > Ajouter un compte bancaire.`,
-        },
     },
     bankInfoStep: {
         whatAreYour: 'Quelles sont les coordonnées de votre compte bancaire professionnel ?',
@@ -4099,7 +3681,7 @@ ${amount} pour ${merchant} - ${date}`,
         pleaseUpload: 'Veuillez téléverser ci-dessous des documents supplémentaires pour nous aider à vérifier votre identité en tant que dirigeant(e) de l’entreprise.',
         enterSignerInfo: 'Saisir les informations du signataire',
         thisStep: 'Cette étape a été terminée',
-        isConnecting: (bankAccountLastFour: string | undefined, currency: string | undefined) =>
+        isConnecting: ({bankAccountLastFour, currency}: SignerInfoMessageParams) =>
             `est en train de connecter un compte bancaire professionnel en ${currency} se terminant par ${bankAccountLastFour} à Expensify pour payer des employés en ${currency}. L’étape suivante nécessite les informations de signature d’un directeur.`,
         error: {
             emailsMustBeDifferent: 'Les e-mails doivent être différents',
@@ -4111,7 +3693,7 @@ ${amount} pour ${merchant} - ${date}`,
         regulationRequiresUs: 'La réglementation nous oblige à vérifier l’identité de toute personne détenant plus de 25 % de l’entreprise.',
         iAmAuthorized: 'Je suis autorisé à utiliser le compte bancaire professionnel pour les dépenses professionnelles.',
         iCertify: 'Je certifie que les informations fournies sont exactes et véridiques.',
-        iAcceptTheTermsAndConditions: `J'accepte les <a href="https://www.corpay.com/cross-border/terms">conditions générales</a>.`,
+        iAcceptTheTermsAndConditions: `J'accepte les <a href="https://cross-border.corpay.com/tc/">conditions générales</a>.`,
         iAcceptTheTermsAndConditionsAccessibility: 'J’accepte les conditions générales.',
         accept: 'Accepter et ajouter un compte bancaire',
         iConsentToThePrivacyNotice: 'Je consens à l’<a href="https://payments.corpay.com/compliance">avis de confidentialité</a>.',
@@ -4143,38 +3725,6 @@ ${amount} pour ${merchant} - ${date}`,
         weTake: 'Nous accordons une grande importance à votre sécurité. Veuillez configurer l’authentification à deux facteurs (2FA) maintenant pour ajouter une couche de protection supplémentaire à votre compte.',
         secure: 'Sécurisez votre compte',
     },
-    documentsStep: {
-        beforeYouGo: 'Avant de continuer, nous avons besoin de certains documents pour vérifier certaines informations',
-        subheader: 'Vérification',
-        verificationFailed: 'La vérification a échoué, nous aurons donc besoin de documents supplémentaires pour te vérifier ainsi que ton entreprise',
-        taxIDVerification: 'Vérification de l’identifiant fiscal',
-        taxIDVerificationDescription: dedent(`
-        Veuillez téléverser l’un des fichiers suivants :
-        • Lettre d’attribution TIN/EIN de l’IRS
-        • Confirmation de demande TIN/EIN de l’IRS (indique généralement « Congratulations! The EIN has been successfully assigned »)
-        • Lettre d’exonération fiscale de l’IRS indiquant le nom de l’entreprise et l’EIN`),
-        nameChangeDocument: 'Document de changement de nom',
-        nameChangeDocumentDescription:
-            'Si le nom de ton entreprise a changé depuis la demande du TIN/EIN, ce document est nécessaire pour vérifier le numéro d’identification fiscale fourni',
-        companyAddressVerification: 'Vérification de l’adresse de l’entreprise',
-        companyAddressVerificationDescription: dedent(`
-        Veuillez téléverser l’un des fichiers suivants :
-        • Facture récente de services publics indiquant le nom et l’adresse de l’entreprise
-        • Relevé bancaire indiquant le nom et l’adresse de l’entreprise
-        • Contrat de location en cours incluant la page de signature avec le nom et l’adresse actuelle de l’entreprise
-        • Attestation d’assurance indiquant le nom et l’adresse de l’entreprise
-        • Document d’attribution TIN indiquant le nom et l’adresse de l’entreprise`),
-        userAddressVerification: 'Vérification de l’adresse',
-        userAddressVerificationDescription: dedent(`
-        Veuillez téléverser l’un des fichiers suivants :
-        • Carte d’inscription électorale
-        • Permis de conduire
-        • Relevé bancaire
-        • Facture de services publics`),
-        userDOBVerification: 'Vérification de la date de naissance',
-        userDOBVerificationDescription: 'Veuillez téléverser une pièce d’identité délivrée aux États-Unis',
-        finishViaChat: 'Finaliser via le chat',
-    },
     reimbursementAccountLoadingAnimation: {
         oneMoment: 'Un instant',
         explanationLine: 'Nous examinons vos informations. Vous pourrez poursuivre les prochaines étapes sous peu.',
@@ -4313,15 +3863,15 @@ ${amount} pour ${merchant} - ${date}`,
             flightSeatChanged: (airlineCode: string) => `Votre siège attribué sur le vol ${airlineCode} a été modifié.`,
             flightSeatCancelled: (airlineCode: string) => `Votre siège attribué sur le vol ${airlineCode} a été supprimé.`,
             paymentDeclined: 'Le paiement de votre réservation de vol a échoué. Veuillez réessayer.',
-            bookingCancelledByTraveler: (type: string, id = '') => `Vous avez annulé votre réservation de ${type} ${id}.`,
-            bookingCancelledByVendor: (type: string, id = '') => `Le fournisseur a annulé votre réservation de ${type} ${id}.`,
-            bookingRebooked: (type: string, id = '') => `Votre réservation de ${type} a été à nouveau effectuée. Nouveau numéro de confirmation : ${id}.`,
-            bookingUpdated: (type: string) => `Votre réservation de ${type} a été mise à jour. Examinez les nouveaux détails dans l’itinéraire.`,
+            bookingCancelledByTraveler: ({type, id = ''}: TravelTypeParams) => `Vous avez annulé votre réservation de ${type} ${id}.`,
+            bookingCancelledByVendor: ({type, id = ''}: TravelTypeParams) => `Le fournisseur a annulé votre réservation de ${type} ${id}.`,
+            bookingRebooked: ({type, id = ''}: TravelTypeParams) => `Votre réservation de ${type} a été à nouveau effectuée. Nouveau numéro de confirmation : ${id}.`,
+            bookingUpdated: ({type}: TravelTypeParams) => `Votre réservation de ${type} a été mise à jour. Examinez les nouveaux détails dans l’itinéraire.`,
             railTicketRefund: (origin: string, destination: string, startDate: string) =>
                 `Votre billet de train pour ${origin} → ${destination} du ${startDate} a été remboursé. Un avoir sera traité.`,
             railTicketExchange: (origin: string, destination: string, startDate: string) => `Votre billet de train pour ${origin} → ${destination} le ${startDate} a été échangé.`,
             railTicketUpdate: (origin: string, destination: string, startDate: string) => `Votre billet de train pour ${origin} → ${destination} le ${startDate} a été mis à jour.`,
-            defaultUpdate: (type: string) => `Votre réservation de ${type} a été mise à jour.`,
+            defaultUpdate: ({type}: TravelTypeParams) => `Votre réservation de ${type} a été mise à jour.`,
         },
         flightTo: 'Vol à destination de',
         trainTo: 'Train pour',
@@ -4338,13 +3888,13 @@ ${amount} pour ${merchant} - ${date}`,
             workflows: 'Workflows',
             workspace: 'Espace de travail',
             findWorkspace: 'Trouver un espace de travail',
-            findRoom: 'Trouver un salon',
             edit: 'Modifier l’espace de travail',
             enabled: 'Activé',
             disabled: 'Désactivé',
             everyone: 'Tout le monde',
             delete: 'Supprimer l’espace de travail',
             settings: 'Paramètres',
+            reimburse: 'Remboursements',
             categories: 'Catégories',
             tags: 'Tags',
             customField1: 'Champ personnalisé 1',
@@ -4352,7 +3902,6 @@ ${amount} pour ${merchant} - ${date}`,
             customFieldHint: 'Ajoutez un codage personnalisé qui s’applique à toutes les dépenses de ce membre.',
             reports: 'Notes de frais',
             reportFields: 'Champs de note de frais',
-            invoiceFields: 'Champs de facture',
             reportTitle: 'Titre de la note de frais',
             reportField: 'Champ de note de frais',
             taxes: 'Taxes',
@@ -4381,10 +3930,6 @@ ${amount} pour ${merchant} - ${date}`,
             defaultNote: `Les reçus envoyés à ${CONST.EMAIL.RECEIPTS} apparaîtront dans cet espace de travail.`,
             deleteConfirmation: 'Voulez-vous vraiment supprimer cet espace de travail ?',
             deleteWithCardsConfirmation: 'Voulez-vous vraiment supprimer cet espace de travail ? Cela supprimera tous les flux de cartes et les cartes assignées.',
-            deleteOpenExpensifyCardsError: 'Votre entreprise a encore des cartes Expensify actives.',
-            outstandingBalanceWarning:
-                'Vous avez un solde impayé qui doit être réglé avant de supprimer votre dernier espace de travail. Veuillez accéder à vos paramètres d’abonnement pour résoudre le paiement.',
-            settleBalance: 'Aller à l’abonnement',
             unavailable: 'Espace de travail indisponible',
             memberNotFound: 'Membre introuvable. Pour inviter un nouveau membre dans l’espace de travail, veuillez utiliser le bouton d’invitation ci-dessus.',
             notAuthorized: `Vous n’avez pas accès à cette page. Si vous essayez de rejoindre cet espace de travail, demandez simplement au responsable de l’espace de travail de vous ajouter en tant que membre. Autre chose ? Contactez ${CONST.EMAIL.CONCIERGE}.`,
@@ -4397,9 +3942,6 @@ ${amount} pour ${merchant} - ${date}`,
             workspaceOwner: 'Responsable',
             workspaceType: 'Type d’espace de travail',
             workspaceAvatar: "Avatar de l'espace de travail",
-            keepMeAsAdmin: 'Me garder comme administrateur',
-            clientID: 'ID client',
-            clientIDInputHint: "Entrez l'identifiant unique du client",
             mustBeOnlineToViewMembers: 'Vous devez être en ligne pour voir les membres de cet espace de travail.',
             moreFeatures: 'Plus de fonctionnalités',
             requested: 'Demandé',
@@ -4418,7 +3960,7 @@ ${amount} pour ${merchant} - ${date}`,
             appliedOnExport: 'Non importé dans Expensify, appliqué à l’export',
             shareNote: {
                 header: 'Partagez votre espace de travail avec d’autres membres',
-                content: (adminsRoomLink: string) =>
+                content: ({adminsRoomLink}: WorkspaceShareNoteParams) =>
                     `Partagez ce code QR ou copiez le lien ci-dessous pour permettre aux membres de demander facilement l’accès à votre espace de travail. Toutes les demandes pour rejoindre l’espace de travail apparaîtront dans le salon <a href="${adminsRoomLink}">${CONST.REPORT.WORKSPACE_CHAT_ROOMS.ADMINS}</a> pour votre examen.`,
             },
             connectTo: ({connectionName}: ConnectionNameParams) => `Se connecter à ${CONST.POLICY.CONNECTIONS.NAME_USER_FRIENDLY[connectionName]}`,
@@ -4433,20 +3975,12 @@ ${amount} pour ${merchant} - ${date}`,
             memberAlternateText: 'Soumettre et approuver des notes de frais.',
             adminAlternateText: 'Gérer les notes de frais et les paramètres de l’espace de travail.',
             auditorAlternateText: 'Afficher et commenter les notes de frais.',
-            roleName: (role?: string) => {
+            roleName: ({role}: OptionalParam<RoleNamesParams> = {}) => {
                 switch (role) {
                     case CONST.POLICY.ROLE.ADMIN:
-                        return 'Administrateur d’espace de travail';
+                        return 'Administrateur';
                     case CONST.POLICY.ROLE.AUDITOR:
                         return 'Auditeur';
-                    case CONST.POLICY.ROLE.EDITOR:
-                        return 'Éditeur';
-                    case CONST.POLICY.ROLE.CARD_ADMIN:
-                        return 'Administrateur de carte';
-                    case CONST.POLICY.ROLE.PEOPLE_ADMIN:
-                        return 'Administration des personnes';
-                    case CONST.POLICY.ROLE.PAYMENTS_ADMIN:
-                        return 'Administrateur des paiements';
                     case CONST.POLICY.ROLE.USER:
                         return 'Membre';
                     default:
@@ -4476,22 +4010,7 @@ ${amount} pour ${merchant} - ${date}`,
             budgetFrequencyUnit: {monthly: 'mois', yearly: 'année'},
             budgetTypeForNotificationMessage: {tag: 'tag', category: 'catégorie'},
             policyExpenseChatName: (displayName: string) => `Dépenses de ${displayName}`,
-            deepDiveExpensifyCard: `<muted-text-label>Les transactions de la Carte Expensify seront automatiquement exportées vers un « compte de passif Carte Expensify » créé avec <a href="${CONST.DEEP_DIVE_EXPENSIFY_CARD}">notre intégration</a>.</muted-text-label>`,
-            travelInvoicing: 'Exporter les frais de facturation de voyages en tant que',
-            travelInvoicingVendor: 'Fournisseur de voyages',
-            travelInvoicingPayableAccount: 'Compte fournisseur déplacements',
-            hr: 'RH',
-            rooms: 'Salons',
-            findDomain: 'Trouver un domaine',
-            cardAdminAlternateText: 'Gérer les cartes de l’espace de travail.',
-            peopleAdminAlternateText: 'Gérez les membres et les workflows d’approbation.',
-            paymentsAdminAlternateText: 'Gérer les paiements de workflow.',
-            readOnlyActionTitle: 'Pas si vite...',
-            readOnlyActionPrompt: 'Votre rôle dans cet espace de travail peut afficher ces paramètres, mais ne peut pas les modifier.',
-        },
-        createdForClient: {
-            title: 'Vous avez créé un espace de travail pour votre client !',
-            description: "Excellente nouvelle 🎉. Contactez-nous si votre client a besoin d'aide pour la configuration.",
+            deepDiveExpensifyCard: `<muted-text-label>Les transactions de la carte Expensify seront automatiquement exportées vers un « compte de passif de carte Expensify » créé avec <a href="${CONST.DEEP_DIVE_EXPENSIFY_CARD}">notre intégration</a>.</muted-text-label>`,
         },
         receiptPartners: {
             uber: {
@@ -4556,7 +4075,7 @@ ${amount} pour ${merchant} - ${date}`,
             exportDescription: 'Configurez comment les données Expensify sont exportées vers QuickBooks Desktop.',
             date: 'Date d’exportation',
             exportInvoices: 'Exporter les factures vers',
-            exportExpensifyCard: 'Exporter les transactions de Carte Expensify en tant que',
+            exportExpensifyCard: 'Exporter les transactions de la carte Expensify en tant que',
             account: 'Compte',
             accountDescription: 'Choisissez où comptabiliser les écritures de journal.',
             accountsPayable: 'Comptes fournisseurs',
@@ -4679,7 +4198,7 @@ ${amount} pour ${merchant} - ${date}`,
             exportDescription: 'Configurer l’exportation des données Expensify vers QuickBooks Online.',
             date: 'Date d’exportation',
             exportInvoices: 'Exporter les factures vers',
-            exportExpensifyCard: 'Exporter les transactions de Carte Expensify en tant que',
+            exportExpensifyCard: 'Exporter les transactions de la carte Expensify en tant que',
             exportDate: {
                 label: 'Date d’exportation',
                 description: 'Utiliser cette date lors de l’export des notes de frais vers QuickBooks Online.',
@@ -4717,9 +4236,8 @@ ${amount} pour ${merchant} - ${date}`,
             notConfigured: 'Non configuré',
             bankAccountDescription: 'Choisissez d’où envoyer les chèques.',
             creditCardAccount: 'Compte de carte de crédit',
-            travelInvoicingDescription: 'Les frais de voyage seront exportés comme des débits de carte de crédit vers le compte QuickBooks Online indiqué ci-dessous.',
             companyCardsLocationEnabledDescription:
-                'QuickBooks Online ne prend pas en charge les emplacements dans les exports de factures fournisseur lorsque les emplacements sont importés en tant que tags. Comme vous avez des emplacements importés en tant que tags dans votre espace de travail, cette option d’export n’est pas disponible.',
+                'QuickBooks Online ne prend pas en charge les emplacements pour l’exportation des factures fournisseur. Comme vous avez activé les emplacements sur votre espace de travail, cette option d’exportation n’est pas disponible.',
             outOfPocketTaxEnabledDescription:
                 'QuickBooks Online ne prend pas en charge les taxes sur les exportations d’écritures comptables. Comme les taxes sont activées sur votre espace de travail, cette option d’exportation n’est pas disponible.',
             outOfPocketTaxEnabledError: 'Les écritures comptables ne sont pas disponibles lorsque les taxes sont activées. Veuillez choisir une autre option d’export.',
@@ -4815,7 +4333,6 @@ ${amount} pour ${merchant} - ${date}`,
             exportDeepDiveCompanyCard:
                 'Les dépenses exportées seront enregistrées comme des transactions bancaires sur le compte bancaire Xero ci-dessous, et les dates de transaction correspondront aux dates figurant sur votre relevé bancaire.',
             bankTransactions: 'Transactions bancaires',
-            travelInvoicingDescription: 'Les frais de voyage seront exportés sous forme de transactions bancaires vers le compte Xero indiqué ci-dessous.',
             xeroBankAccount: 'Compte bancaire Xero',
             xeroBankAccountDescription: 'Choisissez où les dépenses seront enregistrées comme transactions bancaires.',
             exportExpensesDescription: 'Les notes de frais seront exportées sous forme de facture d’achat avec la date et le statut sélectionnés ci-dessous.',
@@ -4910,7 +4427,6 @@ ${amount} pour ${merchant} - ${date}`,
                     [CONST.SAGE_INTACCT_NON_REIMBURSABLE_EXPENSE_TYPE.VENDOR_BILL]: 'Factures fournisseurs',
                 },
             },
-            travelInvoicingDescription: 'Les frais de voyage seront exportés comme des débits de carte de crédit vers le compte Sage Intacct indiqué ci-dessous.',
             creditCardAccount: 'Compte de carte de crédit',
             defaultVendor: 'Fournisseur par défaut',
             defaultVendorDescription: (isReimbursable: boolean) =>
@@ -4943,68 +4459,6 @@ ${amount} pour ${merchant} - ${date}`,
                 },
             },
         },
-        certinia: {
-            title: 'Certinia',
-            titleFFA: 'Certinia (FFA)',
-            autoSyncDescription: 'Expensify se synchronisera automatiquement avec Certinia chaque jour.',
-            syncReimbursedReportsDescription:
-                'Lorsque cette option est activée, chaque fois qu’une facture à payer est réglée dans FFA, la note de frais Expensify associée est automatiquement marquée comme remboursée.',
-            exportDescription: 'Configurez comment les données Expensify sont exportées vers Certinia.',
-            payableInvoices: 'Factures à payer',
-            exportStatus: {
-                label: 'Statut de facture à payer',
-                values: {
-                    [CONST.CERTINIA_EXPORT_STATUS.APPROVED]: 'Terminé',
-                    [CONST.CERTINIA_EXPORT_STATUS.IN_PROGRESS]: 'En cours',
-                    [CONST.CERTINIA_EXPORT_STATUS.SUBMITTED]: 'Soumis',
-                },
-            },
-            exportDate: {
-                label: 'Date d’échéance de la facture',
-                values: {
-                    [CONST.CERTINIA_EXPORT_DATE.LAST_EXPENSE]: 'Date de la dernière dépense',
-                    [CONST.CERTINIA_EXPORT_DATE.REPORT_SUBMITTED]: 'Date de soumission de la note de frais',
-                    [CONST.CERTINIA_EXPORT_DATE.REPORT_EXPORTED]: 'Date d’exportation',
-                },
-            },
-            exportReimbursable: {
-                label: 'Exporter les dépenses remboursables en tant que',
-                helperText: 'Les dépenses marquées comme remboursables seront exportées en tant que factures à payer établies au nom de l’employé.',
-            },
-            exportNonReimbursable: {label: 'Exporter les dépenses non remboursables en tant que'},
-            noVendorsFound: 'Aucun fournisseur trouvé',
-            noVendorsFoundDescription: 'Veuillez synchroniser à nouveau la connexion après l’ajout des fournisseurs dans Certinia.',
-            prerequisites: {
-                title: 'Avant de vous connecter',
-                installBundle: 'Pour les connexions FFA',
-                installBundleDescription: ({href, version}: {href: string; version: string}) =>
-                    `Installez le bundle Expensify dans Salesforce en cliquant sur ce lien : <a href="${href}">Installer le bundle FFA Expensify (version ${version})</a>`,
-                installBundleConfirm: 'J’ai installé le paquet',
-                setupContacts: 'Configurer l’utilisateur et les contacts',
-                setupContactsBullet1:
-                    'Créez à la fois un Utilisateur et un Contact pour vous-même s’ils n’existent pas encore dans Certinia, en veillant à ce que l’adresse e-mail corresponde à votre adresse e-mail principale dans Expensify.',
-                setupContactsBullet2:
-                    'Créez des contacts pour chaque employé qui soumettra des notes de frais et pour chaque approbateur de notes de frais. Assurez-vous que l’adresse e-mail de chaque contact corresponde à l’adresse e-mail du compte Expensify de l’employé.',
-                setupContactsBullet3: 'Définissez des contrôles d’autorisation pour votre utilisateur pour chaque contact/ressource.',
-                setupContactsConfirm: 'J’ai configuré l’utilisateur et les contacts',
-                oauth: 'Se connecter via Salesforce',
-                oauthDescription: 'Pour terminer la configuration, vous devez vous connecter via Salesforce et Certinia.\n\nUtilisez le bouton ci-dessous pour continuer.',
-                connectButton: 'Se connecter à Certinia',
-            },
-            import: {
-                chartOfAccounts: 'Plan comptable',
-                chartOfAccountsDescription: 'Le plan comptable est importé dans Expensify en tant que catégories.',
-                dimensionMapping: ({n}: {n: number}) => `Dimension ${n}`,
-                dimensions: {dimension1: 'Dimension 1', dimension2: 'Dimension 2', dimension3: 'Dimension 3', dimension4: 'Dimension 4'},
-                doNotMap: 'Ne pas mapper',
-                doNotMapSubtitle: 'Utiliser la ressource employé par défaut',
-                mappingTypes: {
-                    [CONST.CERTINIA_MAPPING_VALUE.DEFAULT]: 'Ne pas mapper',
-                    [CONST.CERTINIA_MAPPING_VALUE.TAG]: 'Importé comme tags',
-                    [CONST.CERTINIA_MAPPING_VALUE.REPORT_FIELD]: 'Importé en tant que champs de note de frais',
-                },
-            },
-        },
         netsuite: {
             subsidiary: 'Filiale',
             subsidiarySelectDescription: 'Choisissez la filiale dans NetSuite à partir de laquelle vous souhaitez importer des données.',
@@ -5019,8 +4473,8 @@ ${amount} pour ${merchant} - ${date}`,
             journalPostingPreference: {
                 label: 'Préférence de comptabilisation des écritures de journal',
                 values: {
-                    [CONST.NETSUITE_JOURNAL_POSTING_PREFERENCE.JOURNALS_POSTING_INDIVIDUAL_LINE]: 'Saisie unique pour chaque dépense',
-                    [CONST.NETSUITE_JOURNAL_POSTING_PREFERENCE.JOURNALS_POSTING_TOTAL_LINE]: 'Entrée unique et détaillée pour chaque rapport',
+                    [CONST.NETSUITE_JOURNAL_POSTING_PREFERENCE.JOURNALS_POSTING_INDIVIDUAL_LINE]: 'Saisie unique et détaillée pour chaque note de frais',
+                    [CONST.NETSUITE_JOURNAL_POSTING_PREFERENCE.JOURNALS_POSTING_TOTAL_LINE]: 'Une seule entrée pour chaque dépense',
                 },
             },
             invoiceItem: {
@@ -5086,7 +4540,6 @@ ${amount} pour ${merchant} - ${date}`,
 
                             Si vous souhaitez définir un fournisseur spécifique pour chaque carte, accédez à *Paramètres > Domaines > Cartes d’entreprise*.
                         `),
-                        travelDescription: 'Les frais de voyage seront exportés sous forme d’écritures de journal vers le compte NetSuite indiqué ci-dessous.',
                     },
                 },
                 expenseReportDestinationConfirmDescription:
@@ -5231,7 +4684,7 @@ ${amount} pour ${merchant} - ${date}`,
                 importCustomFields: {
                     chooseOptionBelow: 'Choisissez une option ci-dessous :',
                     label: (importedTypes: string[]) => `Importé en tant que ${importedTypes.join('et')}`,
-                    requiredFieldError: (fieldName: string) => `Veuillez saisir le ${fieldName}`,
+                    requiredFieldError: ({fieldName}: RequiredFieldParams) => `Veuillez saisir le ${fieldName}`,
                     customSegments: {
                         title: 'Segments/enregistrements personnalisés',
                         addText: 'Ajouter un segment/enregistrement personnalisé',
@@ -5284,7 +4737,7 @@ _Pour des instructions plus détaillées, [consultez notre site d’aide](${CONS
 
 _Pour des instructions plus détaillées, [visitez notre site d’aide](${CONST.NETSUITE_IMPORT.HELP_LINKS.CUSTOM_SEGMENTS})._`,
                             customSegmentScriptIDTitle: 'Quel est l’ID du script ?',
-                            customSegmentScriptIDFooter: `Vous pouvez trouver les ID de script de segment personnalisé dans NetSuite sous :
+                            customSegmentScriptIDFooter: `Vous pouvez trouver les ID de script de segment personnalisé dans NetSuite sous : 
 
 1. *Customization > Lists, Records, & Fields > Custom Segments*.
 2. Cliquez sur un segment personnalisé.
@@ -5305,7 +4758,7 @@ _Pour des instructions plus détaillées, [visitez notre site d’aide](${CONST.
                             customRecordMappingTitle: 'Comment cet enregistrement personnalisé doit-il être affiché dans Expensify ?',
                         },
                         errors: {
-                            uniqueFieldError: (fieldName: string) => `Un segment/enregistrement personnalisé avec ce ${fieldName?.toLowerCase()} existe déjà`,
+                            uniqueFieldError: ({fieldName}: RequiredFieldParams) => `Un segment/enregistrement personnalisé avec ce ${fieldName?.toLowerCase()} existe déjà`,
                         },
                     },
                     customLists: {
@@ -5372,7 +4825,7 @@ _Pour des instructions plus détaillées, [visitez notre site d’aide](${CONST.
             employeeDefaultDescription: 'Le service par défaut de l’employé sera appliqué à ses dépenses dans Sage Intacct s’il en existe un.',
             displayedAsTagDescription: 'Le service pourra être sélectionné pour chaque dépense individuelle sur la note de frais d’un employé.',
             displayedAsReportFieldDescription: 'La sélection de département sera appliquée à toutes les dépenses sur la note de frais d’un employé.',
-            toggleImportTitle: (mappingTitle: string) => `Choisissez comment gérer Sage Intacct <strong>${mappingTitle}</strong> dans Expensify.`,
+            toggleImportTitle: ({mappingTitle}: ToggleImportTitleParams) => `Choisissez comment gérer Sage Intacct <strong>${mappingTitle}</strong> dans Expensify.`,
             expenseTypes: 'Types de dépenses',
             expenseTypesDescription: 'Vos types de dépenses Sage Intacct seront importés dans Expensify en tant que catégories.',
             accountTypesDescription: 'Votre plan comptable Sage Intacct sera importé dans Expensify en tant que catégories.',
@@ -5412,14 +4865,10 @@ _Pour des instructions plus détaillées, [visitez notre site d’aide](${CONST.
             free: 'Gratuit',
             control: 'Contrôle',
             collect: 'Encaisser',
-            submit: 'Soumettre',
         },
         companyCards: {
             addCards: 'Ajouter des cartes',
             selectCards: 'Sélectionner des cartes',
-            fromOtherWorkspaces: "D'autres espaces de travail",
-            addWorkEmail: 'Ajoutez votre adresse e-mail professionnelle',
-            addWorkEmailDescription: "Veuillez ajouter votre e-mail professionnel pour utiliser les flux existants d'autres espaces de travail.",
             error: {
                 workspaceFeedsCouldNotBeLoadedTitle: 'Impossible de charger les flux de cartes',
                 workspaceFeedsCouldNotBeLoadedMessage:
@@ -5430,11 +4879,6 @@ _Pour des instructions plus détaillées, [visitez notre site d’aide](${CONST.
             },
             addNewCard: {
                 other: 'Autre',
-                fileImport: 'Importer des transactions depuis un fichier',
-                createFileFeedHelpText: `<muted-text>Veuillez suivre ce <a href="${CONST.COMPANY_CARDS_CREATE_FILE_FEED_HELP_URL}">guide d’aide</a> pour importer les dépenses de votre carte d’entreprise !</muted-text>`,
-                companyCardLayoutName: 'Nom de la disposition de carte entreprise',
-                cardLayoutNameRequired: 'Le nom du layout de la carte entreprise est requis',
-                useAdvancedFields: 'Utiliser les champs avancés (non recommandé)',
                 cardProviders: {
                     gl1025: 'Cartes American Express Corporate',
                     cdf: 'Cartes commerciales Mastercard',
@@ -5515,26 +4959,6 @@ _Pour des instructions plus détaillées, [visitez notre site d’aide](${CONST.
                     confirmText: 'Signaler un problème',
                     cancelText: 'Ignorer',
                 },
-                csvColumns: {
-                    cardNumber: 'Numéro de carte',
-                    postedDate: 'Date',
-                    merchant: 'Commerçant',
-                    amount: 'Montant',
-                    currency: 'Devise',
-                    ignore: 'Ignorer',
-                    originalTransactionDate: 'Date de transaction d’origine',
-                    originalAmount: 'Montant d’origine',
-                    originalCurrency: 'Devise d’origine',
-                    comment: 'Commentaire',
-                    category: 'Catégorie',
-                    tag: 'Étiquette',
-                },
-                csvErrors: {
-                    requiredColumns: (missingColumns: string) => `Veuillez attribuer une colonne à chacun des attributs : ${missingColumns}.`,
-                    duplicateColumns: (duplicateColumn: string) => `Oups ! Vous avez associé un seul champ (« ${duplicateColumn} ») à plusieurs colonnes. Veuillez vérifier et réessayer.`,
-                },
-                fileImportDescription: 'Une option manuelle si votre banque ne peut pas envoyer de flux.',
-                duplicateFeedModal: {title: 'Flux de carte déjà connecté', prompt: 'Vous ne pouvez pas ajouter deux fois le même flux de carte au même espace de travail.'},
             },
             statementCloseDate: {
                 [CONST.COMPANY_CARDS.STATEMENT_CLOSE_DATE.LAST_DAY_OF_MONTH]: 'Dernier jour du mois',
@@ -5587,14 +5011,12 @@ _Pour des instructions plus détaillées, [visitez notre site d’aide](${CONST.
                 flipAmountSign: 'Inverser le signe du montant',
                 importButton: 'Importer des transactions',
             },
-            deletedCard: 'Carte supprimée',
-            assignNewCards: {title: 'Assigner de nouvelles cartes', description: 'Obtenez les dernières cartes à assigner depuis votre banque'},
         },
         expensifyCard: {
-            issueAndManageCards: 'Émettre et gérer vos Cartes Expensify',
+            issueAndManageCards: 'Émettre et gérer vos cartes Expensify',
             getStartedIssuing: 'Commencez par émettre votre première carte virtuelle ou physique.',
             verificationInProgress: 'Vérification en cours...',
-            verifyingTheDetails: 'Nous vérifions quelques détails. Concierge vous informera lorsque les Cartes Expensify seront prêtes à être émises.',
+            verifyingTheDetails: 'Nous vérifions quelques informations. Concierge vous informera lorsque les cartes Expensify seront prêtes à être émises.',
             disclaimer:
                 'La carte commerciale Visa® Expensify est émise par The Bancorp Bank, N.A., membre de la FDIC, conformément à une licence de Visa U.S.A. Inc. et ne peut pas être utilisée chez tous les commerçants qui acceptent les cartes Visa. Apple® et le logo Apple® sont des marques d’Apple Inc., déposées aux États-Unis et dans d’autres pays. App Store est une marque de service d’Apple Inc. Google Play et le logo Google Play sont des marques de Google LLC.',
             euUkDisclaimer:
@@ -5606,8 +5028,8 @@ _Pour des instructions plus détaillées, [visitez notre site d’aide](${CONST.
             lastFour: '4 derniers',
             limit: 'Limite',
             currentBalance: 'Solde actuel',
-            currentBalanceDescription: 'Le solde actuel est la somme de toutes les transactions Carte Expensify comptabilisées depuis la dernière date de règlement.',
-            balanceWillBeSettledOn: (settlementDate: string) => `Le solde sera réglé le ${settlementDate}`,
+            currentBalanceDescription: 'Le solde actuel est la somme de toutes les transactions Expensify Card comptabilisées depuis la dernière date de règlement.',
+            balanceWillBeSettledOn: ({settlementDate}: SettlementDateParams) => `Le solde sera réglé le ${settlementDate}`,
             settleBalance: 'Régler le solde',
             cardLimit: 'Plafond de carte',
             remainingLimit: 'Plafond restant',
@@ -5615,28 +5037,27 @@ _Pour des instructions plus détaillées, [visitez notre site d’aide](${CONST.
             remainingLimitDescription:
                 'Nous prenons en compte plusieurs facteurs pour calculer votre plafond restant : votre ancienneté en tant que client, les informations liées à votre entreprise fournies lors de l’inscription et la trésorerie disponible sur votre compte bancaire professionnel. Votre plafond restant peut fluctuer quotidiennement.',
             earnedCashback: 'Remise en argent',
-            earnedCashbackDescription: 'Le solde de remise en argent est basé sur les dépenses mensuelles réglées effectuées avec la Carte Expensify dans votre espace de travail.',
+            earnedCashbackDescription: 'Le solde de remise en argent est basé sur les dépenses mensuelles réglées avec la Carte Expensify dans votre espace de travail.',
             issueNewCard: 'Émettre une nouvelle carte',
             finishSetup: 'Terminer la configuration',
             chooseBankAccount: 'Choisir un compte bancaire',
-            chooseExistingBank: 'Choisissez un compte bancaire professionnel existant pour régler le solde de votre Carte Expensify ou ajoutez un nouveau compte bancaire',
+            chooseExistingBank: 'Choisissez un compte bancaire professionnel existant pour payer le solde de votre carte Expensify, ou ajoutez un nouveau compte bancaire',
             accountEndingIn: 'Compte se terminant par',
             addNewBankAccount: 'Ajouter un nouveau compte bancaire',
             settlementAccount: 'Compte de règlement',
-            settlementAccountDescription: 'Choisissez un compte pour payer le solde de votre Carte Expensify.',
-            settlementAccountInfo: (reconciliationAccountSettingsLink: string, accountNumber: string) =>
+            settlementAccountDescription: 'Choisissez un compte pour régler le solde de votre carte Expensify.',
+            settlementAccountInfo: ({reconciliationAccountSettingsLink, accountNumber}: SettlementAccountInfoParams) =>
                 `Assurez-vous que ce compte correspond à votre <a href="${reconciliationAccountSettingsLink}">Compte de rapprochement</a> (${accountNumber}) afin que le rapprochement continu fonctionne correctement.`,
             settlementFrequency: 'Fréquence de règlement',
-            settlementFrequencyDescription: 'Choisissez la fréquence à laquelle vous réglerez le solde de votre Carte Expensify.',
+            settlementFrequencyDescription: 'Choisissez la fréquence à laquelle vous paierez le solde de votre carte Expensify.',
             settlementFrequencyInfo:
                 'Si vous souhaitez passer à un règlement mensuel, vous devrez connecter votre compte bancaire via Plaid et disposer d’un historique de solde positif sur 90 jours.',
-            applyCashbackToBill: 'Appliquer le cashback à ma facture Expensify',
-            applyCashbackToBillDescription: 'Le cashback de la carte Expensify sera utilisé pour le paiement de votre facture Expensify.',
             frequency: {
                 daily: 'Quotidien',
                 monthly: 'Mensuel',
             },
             cardDetails: 'Détails de la carte',
+            cardPending: ({name}: {name: string}) => `La carte est actuellement en attente et sera émise une fois le compte de ${name} validé.`,
             virtual: 'Virtuelle',
             physical: 'Physique',
             deactivate: 'Désactiver la carte',
@@ -5653,28 +5074,24 @@ _Pour des instructions plus détaillées, [visitez notre site d’aide](${CONST.
             changeCardMonthlyLimitTypeWarning: (limit: number | string) =>
                 `Si vous changez le type de plafond de cette carte en Mensuel, les nouvelles transactions seront refusées, car le plafond mensuel de ${limit} a déjà été atteint.`,
             addShippingDetails: 'Ajouter les détails de livraison',
-            issuedCard: (assignee: string) => `a émis une Carte Expensify à ${assignee} ! La carte arrivera dans 2 à 3 jours ouvrés.`,
-            issuedCardNoShippingDetails: (assignee: string) => `a émis une Carte Expensify à ${assignee} ! La carte sera expédiée une fois les informations de livraison confirmées.`,
-            issuedCardVirtual: (assignee: string, link: string) => `a attribué une Carte Expensify virtuelle à ${assignee} ! Le ${link} peut être utilisé immédiatement.`,
-            addedShippingDetails: (assignee: string) => `${assignee} a ajouté les informations de livraison. La Carte Expensify arrivera sous 2 à 3 jours ouvrés.`,
-            replacedCard: (assignee: string) => `${assignee} a remplacé sa Carte Expensify. La nouvelle carte arrivera sous 2 à 3 jours ouvrés.`,
-            replacedVirtualCard: (assignee: string, link: string) => `${assignee} a remplacé sa Carte Expensify virtuelle ! Le ${link} peut être utilisé immédiatement.`,
+            issuedCard: (assignee: string) => `a délivré une carte Expensify à ${assignee} ! La carte arrivera sous 2 à 3 jours ouvrés.`,
+            issuedCardNoShippingDetails: (assignee: string) => `a émis une carte Expensify à ${assignee} ! La carte sera expédiée une fois les informations de livraison confirmées.`,
+            issuedCardVirtual: (assignee: string, link: string) => `a émis une carte Expensify virtuelle à ${assignee} ! Le ${link} peut être utilisé immédiatement.`,
+            addedShippingDetails: (assignee: string) => `${assignee} a ajouté les détails de livraison. La carte Expensify arrivera dans 2 à 3 jours ouvrables.`,
+            replacedCard: (assignee: string) => `${assignee} a remplacé sa carte Expensify. La nouvelle carte arrivera sous 2 à 3 jours ouvrables.`,
+            replacedVirtualCard: (assignee: string, link: string) => `${assignee} a remplacé sa carte Expensify virtuelle ! Le ${link} peut être utilisé immédiatement.`,
             card: 'carte',
             replacementCard: 'carte de remplacement',
             verifyingHeader: 'Vérification',
             bankAccountVerifiedHeader: 'Compte bancaire vérifié',
             verifyingBankAccount: 'Vérification du compte bancaire...',
-            verifyingBankAccountDescription: 'Veuillez patienter pendant que nous confirmons que ce compte peut être utilisé pour émettre des Cartes Expensify.',
+            verifyingBankAccountDescription: 'Veuillez patienter pendant que nous confirmons que ce compte peut être utilisé pour émettre des cartes Expensify.',
             bankAccountVerified: 'Compte bancaire vérifié !',
-            bankAccountVerifiedDescription: 'Vous pouvez maintenant émettre des Cartes Expensify aux membres de votre espace de travail.',
+            bankAccountVerifiedDescription: 'Vous pouvez désormais émettre des cartes Expensify aux membres de votre espace de travail.',
             oneMoreStep: 'Encore une étape…',
             oneMoreStepDescription: 'Il semble que nous devions vérifier votre compte bancaire manuellement. Rendez-vous dans Concierge, où vos instructions vous attendent.',
             gotIt: 'Compris',
             goToConcierge: 'Aller à Concierge',
-            exportAsCSV: 'Exporter en CSV',
-            csvColumnType: 'Type',
-            csvColumnLimitType: 'Type de limite',
-            csvColumnLimit: 'Limite',
         },
         categories: {
             deleteCategories: 'Supprimer des catégories',
@@ -5693,10 +5110,10 @@ _Pour des instructions plus détaillées, [visitez notre site d’aide](${CONST.
             needCategoryForExportToIntegration: (connectionName: string) => `Toutes les dépenses doivent être catégorisées afin de pouvoir être exportées vers ${connectionName}.`,
             subtitle: 'Obtenez une meilleure vue d’ensemble de l’endroit où l’argent est dépensé. Utilisez nos catégories par défaut ou ajoutez les vôtres.',
             emptyCategories: {
-                title: 'Aucune catégorie pour le moment',
+                title: "Vous n'avez créé aucune catégorie",
                 subtitle: 'Ajoutez une catégorie pour organiser vos dépenses.',
-                subtitleWithAccounting: (accountingPageURL: string, canManage = true) =>
-                    `<muted-text><centered-text>Vos catégories sont actuellement importées depuis une connexion comptable.${canManage ? ` Rendez-vous dans la section <a href="${accountingPageURL}">comptabilité</a> pour effectuer des modifications.` : ''}</centered-text></muted-text>`,
+                subtitleWithAccounting: (accountingPageURL: string) =>
+                    `<muted-text><centered-text>Vos catégories sont actuellement importées depuis une connexion comptable. Rendez-vous dans la section <a href="${accountingPageURL}">comptabilité</a> pour effectuer des modifications.</centered-text></muted-text>`,
             },
             updateFailureMessage: 'Une erreur s’est produite lors de la mise à jour de la catégorie, veuillez réessayer.',
             createFailureMessage: 'Une erreur s’est produite lors de la création de la catégorie, veuillez réessayer.',
@@ -5752,9 +5169,6 @@ _Pour des instructions plus détaillées, [visitez notre site d’aide](${CONST.
             travel: {
                 title: 'Déplacements',
                 subtitle: 'Réservez, gérez et rapprochez tous vos déplacements professionnels.',
-                disableTravelTitle: 'Désactivez d’abord la facturation des déplacements',
-                disableTravelPrompt: 'La facturation de voyage est activée pour cet espace de travail. Désactivez-la avant de pouvoir désactiver Travel.',
-                disableTravelButton: 'Accéder aux paramètres de voyage',
                 getStarted: {
                     title: 'Commencez avec Expensify Travel',
                     subtitle: 'Nous avons simplement besoin de quelques informations supplémentaires sur votre entreprise, puis vous serez prêt à décoller.',
@@ -5766,15 +5180,9 @@ _Pour des instructions plus détaillées, [visitez notre site d’aide](${CONST.
                     ctaText: 'Demande envoyée',
                 },
                 bookOrManageYourTrip: {
-                    title: 'Réservation de voyage',
-                    subtitle: 'Félicitations ! Vous êtes prêt à réserver et gérer des voyages dans cet espace de travail.',
-                    ctaText: 'Gérer les déplacements',
-                },
-                settings: {
-                    autoAddTripName: {
-                        title: 'Ajouter des noms de voyage aux dépenses',
-                        subtitle: 'Ajouter automatiquement les noms de voyage aux descriptions des dépenses pour les voyages réservés dans Expensify.',
-                    },
+                    title: 'Réserver ou gérer votre voyage',
+                    subtitle: 'Utilisez Expensify Travel pour obtenir les meilleures offres de voyage et gérer toutes vos dépenses professionnelles en un seul endroit.',
+                    ctaText: 'Réserver ou gérer',
                 },
                 travelInvoicing: {
                     travelBookingSection: {
@@ -5782,59 +5190,30 @@ _Pour des instructions plus détaillées, [visitez notre site d’aide](${CONST.
                         subtitle: 'Félicitations ! Vous êtes prêt à réserver et gérer des voyages sur cet espace de travail.',
                         manageTravelLabel: 'Gérer les déplacements',
                     },
-                    travelInvoicingSection: {
-                        title: 'Facturation de voyages',
+                    centralInvoicingSection: {
+                        title: 'Facturation centralisée',
                         subtitle: 'Centralisez toutes les dépenses de voyage dans une facture mensuelle au lieu de payer au moment de l’achat.',
                         learnHow: 'Découvrez comment.',
                         subsections: {
                             currentTravelSpendLabel: 'Dépenses de voyage actuelles',
-                            currentTravelSpendPaymentQueued: (amount: string) => `Le paiement de ${amount} est en file d’attente et sera traité bientôt.`,
                             currentTravelSpendCta: 'Payer le solde',
                             currentTravelLimitLabel: 'Plafond de déplacement actuel',
                             settlementAccountLabel: 'Compte de règlement',
                             settlementFrequencyLabel: 'Fréquence de règlement',
                             settlementFrequencyDescription:
                                 'Fréquence à laquelle Expensify prélèvera sur votre compte bancaire professionnel pour régler les transactions récentes d’Expensify Travel.',
-                            monthlySpendLimitLabel: 'Limite de dépenses mensuelle par membre',
-                            monthlySpendLimitDescription: 'Le montant maximum que chaque membre peut dépenser en déplacements par mois.',
-                            reduceLimitTitle: 'Réduire la limite de dépenses de voyage ?',
-                            reduceLimitWarning:
-                                'Si vous réduisez la limite, les membres ayant déjà dépensé plus que ce montant ne pourront pas effectuer de nouvelles réservations de voyage avant le mois prochain.',
-                            provisioningError:
-                                'Nous n’avons pas pu provisionner certains membres de votre espace de travail pour la facturation de voyage. Veuillez réessayer plus tard ou contacter Concierge pour obtenir de l’aide.',
                         },
                     },
-                    disableModal: {
-                        title: 'Désactiver la facturation de voyage?',
-                        body: "Les prochaines réservations d'hôtel et de location de voiture devront peut-être être réservées à nouveau avec un autre mode de paiement pour éviter une annulation.",
-                        confirm: 'Désactiver',
-                    },
-                    outstandingBalanceModal: {
-                        title: 'Impossible de désactiver la facturation Voyage',
-                        body: 'Vous avez encore un solde de voyage impayé. Veuillez d’abord régler ce solde.',
-                        confirm: 'Compris',
-                    },
-                    payBalanceModal: {
-                        title: (amount: string) => `Régler le solde de ${amount} ?`,
-                        body: 'Le paiement sera mis en file d’attente et traité peu après. Cette action ne peut plus être annulée une fois lancée.',
-                    },
-                    exportToPDF: 'Exporter en PDF',
-                    exportToCSV: 'Exporter en CSV',
-                    selectDateRangeError: 'Veuillez sélectionner une plage de dates à exporter',
-                    invalidDateRangeError: 'La date de début doit être antérieure à la date de fin',
-                    enabled: 'Facturation des déplacements activée !',
-                    enabledDescription: 'Toutes les dépenses de voyage sur cet espace de travail seront désormais centralisées dans une facture mensuelle.',
                 },
-                personalDetailsDescription: 'Pour pouvoir réserver un voyage, veuillez saisir votre nom légal tel qu’il apparaît sur votre pièce d’identité délivrée par le gouvernement.',
             },
             expensifyCard: {
                 title: 'Carte Expensify',
                 subtitle: 'Obtenez une vision claire et un contrôle sur les dépenses.',
-                disableCardTitle: 'Désactiver la Carte Expensify',
-                disableCardPrompt: 'Vous ne pouvez pas désactiver la Carte Expensify car elle est déjà en cours d’utilisation. Contactez Concierge pour connaître les prochaines étapes.',
+                disableCardTitle: 'Désactiver la carte Expensify',
+                disableCardPrompt: 'Vous ne pouvez pas désactiver la carte Expensify car elle est déjà utilisée. Contactez Concierge pour connaître les prochaines étapes.',
                 disableCardButton: 'Discuter avec Concierge',
                 feed: {
-                    title: 'Obtenir la Carte Expensify',
+                    title: 'Obtenir la carte Expensify',
                     subTitle: 'Rationalisez les dépenses de votre entreprise et économisez jusqu’à 50 % sur votre facture Expensify, plus :',
                     features: {
                         cashBack: 'Cashback sur chaque achat aux États-Unis',
@@ -5880,10 +5259,8 @@ _Pour des instructions plus détaillées, [visitez notre site d’aide](${CONST.
                 updateCard: 'Mettre à jour la carte',
                 unassignCard: 'Retirer l’assignation de la carte',
                 unassign: "Retirer l'assignation",
-                unassignCardDescription: "Retirer l'assignation de cette carte supprimera toutes les transactions non soumises.",
-                removeCard: 'Supprimer la carte',
-                remove: 'Supprimer',
-                removeCardDescription: 'La suppression de cette carte effacera toutes les transactions non soumises.',
+                unassignCardDescription:
+                    "Retirer l'assignation de cette carte supprimera toutes les transactions figurant sur les notes de frais en brouillon du compte du titulaire de la carte.",
                 assignCard: 'Assigner une carte',
                 cardFeedName: 'Nom du flux de carte',
                 cardFeedNameDescription: 'Donnez au flux de carte un nom unique afin de pouvoir le distinguer des autres.',
@@ -5916,9 +5293,9 @@ _Pour des instructions plus détaillées, [visitez notre site d’aide](${CONST.
                 noAccountsFound: 'Aucun compte trouvé',
                 defaultCard: 'Carte par défaut',
                 downgradeTitle: `Impossible de rétrograder l’espace de travail`,
-                downgradeSubTitle: `Cet espace de travail ne peut pas être rétrogradé, car plusieurs flux de cartes sont connectés (hors Cartes Expensify). Veuillez <a href="#">ne garder qu’un seul flux de cartes</a> pour continuer.`,
+                downgradeSubTitle: `Cet espace de travail ne peut pas être rétrogradé, car plusieurs flux de cartes sont connectés (à l’exception des cartes Expensify). Veuillez <a href="#">ne conserver qu’un seul flux de carte</a> pour continuer.`,
                 noAccountsFoundDescription: (connection: string) => `Veuillez ajouter le compte dans ${connection} et synchroniser à nouveau la connexion`,
-                expensifyCardBannerTitle: 'Obtenir la Carte Expensify',
+                expensifyCardBannerTitle: 'Obtenir la carte Expensify',
                 expensifyCardBannerSubtitle:
                     'Profitez de remises en argent sur chaque achat aux États-Unis, jusqu’à 50 % de réduction sur votre facture Expensify, de cartes virtuelles illimitées et bien plus encore.',
                 expensifyCardBannerLearnMoreButton: 'En savoir plus',
@@ -5929,7 +5306,7 @@ _Pour des instructions plus détaillées, [visitez notre site d’aide](${CONST.
                 title: 'Workflows',
                 subtitle: 'Configurez comment les dépenses sont approuvées et payées.',
                 disableApprovalPrompt:
-                    'Les Cartes Expensify de cet espace de travail dépendent actuellement de l’approbation pour définir leurs Smart Limits. Veuillez modifier les types de limite de toutes les Cartes Expensify avec Smart Limits avant de désactiver les approbations.',
+                    'Les cartes Expensify de cet espace de travail dépendent actuellement de l’approbation pour définir leurs Smart Limits. Veuillez modifier les types de limites de toutes les cartes Expensify avec Smart Limits avant de désactiver les approbations.',
             },
             invoices: {
                 title: 'Factures',
@@ -5974,7 +5351,7 @@ _Pour des instructions plus détaillées, [visitez notre site d’aide](${CONST.
             workflowWarningModal: {
                 featureEnabledTitle: 'Pas si vite…',
                 featureEnabledText:
-                    'Les Cartes Expensify de cet espace de travail s’appuient sur des workflows d’approbation pour définir leurs Limites intelligentes.\n\nVeuillez modifier les types de limite de toutes les cartes ayant des Limites intelligentes avant de désactiver les workflows.',
+                    "Les cartes Expensify de cet espace de travail s'appuient sur des workflows d'approbation pour définir leurs limites intelligentes.\n\nVeuillez modifier les types de limite de toutes les cartes avec limites intelligentes avant de désactiver les workflows.",
                 confirmText: 'Aller aux cartes Expensify',
             },
             rules: {
@@ -5986,7 +5363,6 @@ _Pour des instructions plus détaillées, [visitez notre site d’aide](${CONST.
                 subtitle: 'Définissez un taux horaire facturable pour le suivi du temps.',
                 defaultHourlyRate: 'Taux horaire par défaut',
             },
-            hrWarningModal: {disconnectText: ({integration}: {integration: string}) => `Pour désactiver les RH, veuillez d'abord déconnecter ${integration} de cet espace de travail.`},
         },
         reports: {
             reportsCustomTitleExamples: 'Exemples :',
@@ -6009,7 +5385,7 @@ _Pour des instructions plus détaillées, [visitez notre site d’aide](${CONST.
             deleteConfirmation: 'Voulez-vous vraiment supprimer ce champ de note de frais ?',
             deleteFieldsConfirmation: 'Voulez-vous vraiment supprimer ces champs de note de frais ?',
             emptyReportFields: {
-                title: 'Aucun champ de note de frais pour le moment',
+                title: 'Vous n’avez créé aucun champ de note de frais',
                 subtitle: 'Ajoutez un champ personnalisé (texte, date ou liste déroulante) qui apparaît sur les notes de frais.',
             },
             subtitle: 'Les champs de note de frais s’appliquent à toutes les dépenses et peuvent être utiles lorsque vous souhaitez demander des informations supplémentaires.',
@@ -6035,7 +5411,10 @@ _Pour des instructions plus détaillées, [visitez notre site d’aide](${CONST.
             disableValues: 'Désactiver les valeurs',
             enableValue: 'Activer la valeur',
             enableValues: 'Activer les valeurs',
-            emptyReportFieldsValues: {title: 'Pas encore de valeurs de liste', subtitle: 'Ajoutez des valeurs personnalisées à faire apparaître sur les notes de frais.'},
+            emptyReportFieldsValues: {
+                title: "Vous n'avez créé aucune valeur de liste",
+                subtitle: 'Ajoutez des valeurs personnalisées à faire apparaître sur les notes de frais.',
+            },
             deleteValuePrompt: 'Voulez-vous vraiment supprimer cette valeur de liste ?',
             deleteValuesPrompt: 'Voulez-vous vraiment supprimer ces valeurs de liste ?',
             listValueRequiredError: 'Veuillez saisir un nom de valeur de liste',
@@ -6047,33 +5426,9 @@ _Pour des instructions plus détaillées, [visitez notre site d’aide](${CONST.
             reportFieldNameRequiredError: 'Veuillez saisir un nom de champ de note de frais',
             reportFieldTypeRequiredError: 'Veuillez choisir un type de champ de note de frais',
             circularReferenceError: 'Ce champ ne peut pas faire référence à lui-même. Veuillez le mettre à jour.',
-            unsupportedFormulaValueError: ({value}: UnsupportedFormulaValueErrorParams) => `Champ de formule ${value} non reconnu`,
             reportFieldInitialValueRequiredError: 'Veuillez choisir une valeur initiale pour le champ de note de frais',
             genericFailureMessage: 'Une erreur s’est produite lors de la mise à jour du champ de note de frais. Veuillez réessayer.',
         },
-        invoiceFields: {
-            subtitle: 'Les champs de facture peuvent être utiles lorsque vous souhaitez inclure des informations supplémentaires.',
-            importedFromAccountingSoftware: 'Les champs de facture ci-dessous sont importés depuis votre',
-            disableInvoiceFields: 'Désactiver les champs de facture',
-            disableInvoiceFieldsConfirmation: 'Êtes-vous sûr ? Les champs de facture seront désactivés sur les factures.',
-            delete: 'Supprimer le champ de facture',
-            deleteConfirmation: 'Voulez-vous vraiment supprimer ce champ de facture ?',
-            findInvoiceField: 'Trouver un champ de facture',
-            nameInputSubtitle: 'Choisissez un nom pour le champ de facture.',
-            typeInputSubtitle: 'Choisissez le type de champ de facture à utiliser.',
-            initialValueInputSubtitle: 'Saisissez une valeur de départ à afficher dans le champ de facture.',
-            listValuesInputSubtitle: 'Ces valeurs apparaîtront dans la liste déroulante du champ de facture. Les valeurs activées peuvent être sélectionnées par les membres.',
-            listInputSubtitle: 'Ces valeurs apparaîtront dans la liste du champ de facture. Les valeurs activées peuvent être sélectionnées par les membres.',
-            emptyInvoiceFieldsValues: {
-                title: 'Aucune valeur de liste pour le moment',
-                subtitle: 'Ajoutez des valeurs personnalisées à afficher sur les factures.',
-            },
-            existingInvoiceFieldNameError: 'Un champ de facture portant ce nom existe déjà',
-            invoiceFieldNameRequiredError: 'Veuillez saisir un nom de champ de facture',
-            invoiceFieldTypeRequiredError: 'Veuillez choisir un type de champ de facture',
-            invoiceFieldInitialValueRequiredError: 'Veuillez choisir une valeur initiale de champ de facture',
-            addField: 'Ajouter un champ',
-        },
         tags: {
             tagName: 'Nom du tag',
             requiresTag: 'Les membres doivent taguer toutes les dépenses',
@@ -6091,14 +5446,14 @@ _Pour des instructions plus détaillées, [visitez notre site d’aide](${CONST.
             editTags: 'Modifier les tags',
             findTag: 'Trouver un tag',
             subtitle: 'Les tags ajoutent des moyens plus détaillés de classer les coûts.',
-            subtitleWithDependentTags: (importSpreadsheetLink: string, canReimport = true) =>
-                `<muted-text>Les tags ajoutent des moyens plus détaillés de classer les coûts. Vous utilisez des <a href="${CONST.IMPORT_TAGS_EXPENSIFY_URL_DEPENDENT_TAGS}">tags dépendants</a>.${canReimport ? ` Vous pouvez <a href="${importSpreadsheetLink}">réimporter une feuille de calcul</a> pour mettre à jour vos tags.` : ''}</muted-text>`,
+            dependentMultiLevelTagsSubtitle: (importSpreadsheetLink: string) =>
+                `<muted-text>Vous utilisez des <a href="${CONST.IMPORT_TAGS_EXPENSIFY_URL_DEPENDENT_TAGS}">tags dépendants</a>. Vous pouvez <a href="${importSpreadsheetLink}">réimporter une feuille de calcul</a> pour mettre à jour vos tags.</muted-text>`,
             emptyTags: {
-                title: 'Aucun tag pour le moment',
+                title: 'Vous n’avez créé aucun tag',
                 subtitle: 'Ajoutez un tag pour suivre les projets, les lieux, les services et plus encore.',
                 subtitleHTML: `<muted-text><centered-text>Ajoutez des tags pour suivre les projets, les emplacements, les services, et plus encore. <a href="${CONST.IMPORT_TAGS_EXPENSIFY_URL}">En savoir plus</a> sur le formatage des fichiers de tags pour l’importation.</centered-text></muted-text>`,
-                subtitleWithAccounting: (accountingPageURL: string, canManage = true) =>
-                    `<muted-text><centered-text>Vos tags sont actuellement importés depuis une connexion comptable.${canManage ? ` Rendez-vous dans la section <a href="${accountingPageURL}">comptabilité</a> pour effectuer des modifications.` : ''}</centered-text></muted-text>`,
+                subtitleWithAccounting: (accountingPageURL: string) =>
+                    `<muted-text><centered-text>Vos tags sont actuellement importés depuis une connexion comptable. Rendez-vous dans la section <a href="${accountingPageURL}">comptabilité</a> pour effectuer des modifications.</centered-text></muted-text>`,
             },
             deleteTag: 'Supprimer le tag',
             deleteTags: 'Supprimer les tags',
@@ -6184,7 +5539,7 @@ _Pour des instructions plus détaillées, [visitez notre site d’aide](${CONST.
                 updateTaxClaimableFailureMessage: 'La partie récupérable doit être inférieure au montant du taux kilométrique',
             },
             deleteTaxConfirmation: 'Voulez-vous vraiment supprimer cette taxe ?',
-            deleteMultipleTaxConfirmation: (taxAmount: number) => `Voulez-vous vraiment supprimer les taxes ${taxAmount} ?`,
+            deleteMultipleTaxConfirmation: ({taxAmount}: TaxAmountParams) => `Voulez-vous vraiment supprimer les taxes ${taxAmount} ?`,
             actions: {
                 delete: 'Supprimer le taux',
                 deleteMultiple: 'Supprimer les taux',
@@ -6212,47 +5567,10 @@ _Pour des instructions plus détaillées, [visitez notre site d’aide](${CONST.
             reimbursementAccount: 'compte de remboursement',
             welcomeNote: 'Veuillez commencer à utiliser mon nouvel espace de travail',
             delayedSubmission: 'soumission retardée',
-            merchantRules: 'Règles de commerçant',
-            merchantRulesCount: () => ({
-                one: '1 règle de commerçant',
-                other: (count: number) => `${count} règles de commerçant`,
-            }),
             confirmTitle: ({newWorkspaceName, totalMembers}: {newWorkspaceName?: string; totalMembers?: number}) =>
                 `Vous êtes sur le point de créer et de partager ${newWorkspaceName ?? ''} avec ${totalMembers ?? 0} membres de l’espace de travail d’origine.`,
             error: 'Une erreur s’est produite lors de la duplication de votre nouvel espace de travail. Veuillez réessayer.',
         },
-        copyPolicySettings: {
-            title: 'Copier les paramètres',
-            error: 'Une erreur s’est produite lors de la copie des paramètres de l’espace de travail. Veuillez réessayer.',
-            selectWorkspaces: {
-                title: 'Sélectionner des espaces de travail',
-                description: 'Choisissez les espaces de travail vers lesquels vous souhaitez copier les paramètres, puis sélectionnez les paramètres que vous souhaitez copier.',
-                searchPlaceholder: 'Rechercher des espaces de travail',
-            },
-            selectSettings: {
-                title: 'Sélectionner les fonctionnalités à copier',
-                description: 'Sélectionnez les paramètres à écraser sur vos espaces de travail existants.',
-                accountingMismatch: ({part}: {part: string}) =>
-                    `Vous ne pouvez copier ${part} que si tous les espaces de travail utilisent le même système de comptabilité et la même connexion d’entreprise.`,
-            },
-            confirmSettings: {
-                title: 'Assurons-nous que tout est correct.',
-                description: ({workspaceName}: {workspaceName: string}) =>
-                    `Nous copierons les paramètres suivants de <strong>${workspaceName}</strong> vers les espaces de travail que vous avez indiqués`,
-            },
-            confirmWorkflows: {
-                continue: 'Continuer sans membres',
-                description: 'La copie d’espaces de travail sans membres ne copiera pas les workflows d’approbation. Les paramètres de soumission et de paiement seront tout de même copiés.',
-            },
-            progress: {
-                copyInProgressTitle: 'Copie en cours...',
-                copyInProgressDescription: 'Vous pouvez soit attendre la fin du processus, soit laisser Concierge vous prévenir lorsque ce sera terminé.',
-                letMeKnowPrompt: 'Prévenez-moi quand ce sera fait',
-                conciergeNotificationTitle: 'Concierge vous en informera',
-                conciergeNotificationDescription: 'Une fois le processus terminé, Concierge vous enverra un message.',
-                copyCompleted: 'Les paramètres de votre espace de travail ont été copiés.',
-            },
-        },
         emptyWorkspace: {
             title: 'Vous n’avez aucun espace de travail',
             subtitle: 'Suivez les reçus, remboursez les dépenses, gérez les voyages, envoyez des factures, et plus encore.',
@@ -6310,12 +5628,12 @@ _Pour des instructions plus détaillées, [visitez notre site d’aide](${CONST.
                 genericRemove: 'Un problème est survenu lors de la suppression de ce membre de l’espace de travail',
             },
             addedWithPrimary: 'Certains membres ont été ajoutés avec leurs identifiants principaux.',
-            invitedBySecondaryLogin: (secondaryLogin: string) => `Ajouté par la connexion secondaire ${secondaryLogin}.`,
-            workspaceMembersCount: (count: number) => `Nombre total de membres de l'espace de travail : ${count}`,
+            invitedBySecondaryLogin: ({secondaryLogin}: SecondaryLoginParams) => `Ajouté par la connexion secondaire ${secondaryLogin}.`,
+            workspaceMembersCount: ({count}: WorkspaceMembersCountParams) => `Nombre total de membres de l'espace de travail : ${count}`,
             importMembers: 'Importer des membres',
-            removeMemberPromptApprover: (approver: string, workspaceOwner: string) =>
+            removeMemberPromptApprover: ({approver, workspaceOwner}: {approver: string; workspaceOwner: string}) =>
                 `Si vous supprimez ${approver} de cet espace de travail, nous le remplacerons dans le workflow d’approbation par ${workspaceOwner}, le responsable de l’espace de travail.`,
-            removeMemberPromptPendingApproval: (memberName: string) =>
+            removeMemberPromptPendingApproval: ({memberName}: {memberName: string}) =>
                 `${memberName} a des notes de frais en attente d’approbation. Veuillez lui demander de les approuver ou prendre le contrôle de ses notes de frais avant de le retirer de l’espace de travail.`,
             removeMemberPromptReimburser: ({memberName}: {memberName: string}) =>
                 `Vous ne pouvez pas supprimer ${memberName} de cet espace de travail. Veuillez définir un nouveau responsable des remboursements dans Workflows > Effectuer ou suivre les paiements, puis réessayez.`,
@@ -6325,20 +5643,10 @@ _Pour des instructions plus détaillées, [visitez notre site d’aide](${CONST.
                 `Si vous supprimez ${memberName} de cet espace de travail, nous le remplacerons en tant que contact technique par ${workspaceOwner}, le responsable de l’espace de travail.`,
             cannotRemoveUserDueToReport: ({memberName}: {memberName: string}) =>
                 `${memberName} a une note de frais en cours de traitement sur laquelle il doit agir. Veuillez lui demander d’effectuer l’action requise avant de le retirer de l’espace de travail.`,
-            allMembers: 'Tous les membres',
-            admins: 'Administrateurs de l’espace de travail',
-            cardAdmins: 'Administrateurs de cartes',
-            approvers: 'Approbateurs',
-            auditors: 'Auditeurs',
-            emptyRoleFilter: {title: 'Aucun membre ne correspond à ce filtre', subtitle: 'Invitez un membre ou modifiez le filtre ci-dessus.'},
-            configureHRSync: (providerName: string) => `Configurer la synchronisation ${providerName}.`,
-            syncWithHR: (providerName: string) => `Synchroniser avec ${providerName}`,
-            makeCardAdmin: () => ({one: 'Nommer administrateur de carte', other: 'Nommer des administrateurs de carte'}),
         },
         card: {
             getStartedIssuing: 'Commencez par émettre votre première carte virtuelle ou physique.',
             issueCard: 'Émettre une carte',
-            chooseRule: 'Choisir une règle',
             issueNewCard: {
                 whoNeedsCard: 'Qui a besoin d’une carte ?',
                 inviteNewMember: 'Inviter un nouveau membre',
@@ -6381,27 +5689,22 @@ _Pour des instructions plus détaillées, [visitez notre site d’aide](${CONST.
                 enterValidDate: 'Entrez une date valide',
                 expirationDate: 'Date d’expiration',
                 limitAmount: 'Montant de la limite',
-                setCardRules: 'Définir les règles de carte',
-                addSpendRule: 'Ajouter une règle de dépense',
-                addExpirationDate: 'Ajouter une date d’expiration',
-                addExpirationDateDescription: 'Si aucune date spécifique n’est définie, la carte expirera en fonction de la date d’expiration déjà indiquée sur la carte',
+                setExpiryOptions: 'Définir les options d’expiration',
+                setExpiryDate: 'Définir la date d’expiration',
+                setExpiryDateDescription: 'La carte expirera comme indiqué sur la carte',
                 amount: 'Montant',
-                copyExisting: 'Copier l’existant',
-                createNew: 'Créer nouveau',
-                spendRulesEmptyStateTitle: 'Aucune règle à sélectionner',
-                spendRulesEmptyStateSubtitle: 'Aucune règle pour le moment. Vous pouvez en créer une depuis l’écran précédent.',
             },
             deactivateCardModal: {
                 deactivate: 'Désactiver',
                 deactivateCard: 'Désactiver la carte',
                 deactivateConfirmation: 'La désactivation de cette carte entraînera le refus de toutes les futures transactions et est irréversible.',
             },
-            searchRules: 'Rechercher une règle de dépense',
         },
         accounting: {
             settings: 'paramètres',
             title: 'Connexions',
-            subtitle: 'Connectez votre logiciel de comptabilité pour une synchronisation automatique.',
+            subtitle:
+                'Connectez votre système comptable pour imputer les opérations à votre plan comptable, faire correspondre automatiquement les paiements et garder vos finances synchronisées.',
             qbo: 'QuickBooks Online',
             qbd: 'QuickBooks Desktop',
             xero: 'Xero',
@@ -6410,7 +5713,7 @@ _Pour des instructions plus détaillées, [visitez notre site d’aide](${CONST.
             sap: 'SAP',
             oracle: 'Oracle',
             microsoftDynamics: 'Microsoft Dynamics',
-            talkYourOnboardingSpecialist: 'Discutez avec votre chargé de compte.',
+            talkYourOnboardingSpecialist: 'Discutez avec votre spécialiste de configuration.',
             talkYourAccountManager: 'Discuter avec votre gestionnaire de compte.',
             talkToConcierge: 'Discuter avec Concierge.',
             needAnotherAccounting: 'Besoin d’un autre logiciel comptable ?',
@@ -6485,8 +5788,6 @@ _Pour des instructions plus détaillées, [visitez notre site d’aide](${CONST.
             connectPrompt: ({connectionName}: ConnectionNameParams) =>
                 `Voulez-vous vraiment connecter ${CONST.POLICY.CONNECTIONS.NAME_USER_FRIENDLY[connectionName] ?? 'cette intégration comptable'} ? Cette action supprimera toutes les connexions comptables existantes.`,
             enterCredentials: 'Saisissez vos identifiants',
-            reconnect: 'Reconnecter',
-            updateCredentials: 'Mettre à jour les identifiants',
             claimOffer: {
                 badgeText: 'Offre disponible !',
                 xero: {
@@ -6630,26 +5931,6 @@ _Pour des instructions plus détaillées, [visitez notre site d’aide](${CONST.
                             return 'Importation des dimensions Sage Intacct';
                         case 'intacctImportTitle':
                             return 'Importation des données Sage Intacct';
-                        case 'financialForceSyncTitle':
-                            return 'Synchronisation des données Certinia';
-                        case 'financialForceSyncStep':
-                            return 'Synchronisation de la connexion Certinia';
-                        case 'financialForceSyncCategories':
-                            return 'Importation des catégories';
-                        case 'financialForceSyncTags':
-                            return 'Importation des tags';
-                        case 'financialForceSyncVendors':
-                            return 'Importation des fournisseurs';
-                        case 'financialForceSyncContacts':
-                            return 'Importation des contacts';
-                        case 'financialForceSyncCompanies':
-                            return 'Importation des entreprises';
-                        case 'financialForceSyncUsers':
-                            return 'Importation des utilisateurs';
-                        case 'financialForceSyncDimensions':
-                            return 'Importation des dimensions';
-                        case 'financialForceMarkAsReimbursed':
-                            return 'Marquage des notes de frais comme remboursées';
                         default: {
                             return `Traduction manquante pour l’étape : ${stage}`;
                         }
@@ -6672,18 +5953,14 @@ _Pour des instructions plus détaillées, [visitez notre site d’aide](${CONST.
             reconciliationAccount: 'Compte de rapprochement',
             continuousReconciliation: 'Rapprochement continu',
             saveHoursOnReconciliation:
-                'Gagnez des heures lors de chaque période comptable en laissant Expensify rapprocher en continu, pour vous, les relevés et règlements de Carte Expensify.',
+                'Gagnez des heures à chaque période comptable en laissant Expensify rapprocher en continu les relevés et les règlements de la carte Expensify pour vous.',
             enableContinuousReconciliation: (accountingAdvancedSettingsLink: string, connectionName: string) =>
                 `<muted-text-label>Afin d’activer le rapprochement continu, veuillez activer la <a href="${accountingAdvancedSettingsLink}">synchronisation automatique</a> pour ${connectionName}.</muted-text-label>`,
             chooseReconciliationAccount: {
-                chooseBankAccount: 'Choisissez le compte bancaire avec lequel les paiements de votre Carte Expensify seront rapprochés.',
-                settlementAccountReconciliation: (settlementAccountUrl: string, lastFourPAN: string) =>
-                    `Assurez-vous que ce compte correspond à votre <a href="${settlementAccountUrl}">compte de règlement Carte Expensify</a> (se terminant par ${lastFourPAN}) afin que la réconciliation continue fonctionne correctement.`,
-                chooseTravelInvoicingBankAccount: 'Choisissez le compte bancaire sur lequel les paiements de facturation de voyage seront rapprochés.',
-                travelInvoicingSettlementAccountReconciliation: (lastFourPAN: string) =>
-                    `Assurez-vous que ce compte correspond à votre compte de règlement de facturation de voyage (se terminant par ${lastFourPAN}) afin que le rapprochement continu fonctionne correctement.`,
+                chooseBankAccount: 'Choisissez le compte bancaire avec lequel les paiements de votre carte Expensify seront rapprochés.',
+                settlementAccountReconciliation: ({settlementAccountUrl, lastFourPAN}: SettlementAccountReconciliationParams) =>
+                    `Assurez-vous que ce compte correspond à votre <a href="${settlementAccountUrl}">compte de règlement de la carte Expensify</a> (se terminant par ${lastFourPAN}) afin que le rapprochement continu fonctionne correctement.`,
             },
-            syncTravelInvoicingSettlements: 'Synchroniser les règlements de facturation de voyage',
         },
         export: {
             notReadyHeading: 'Pas prêt à être exporté',
@@ -6764,13 +6041,7 @@ _Pour des instructions plus détaillées, [visitez notre site d’aide](${CONST.
             errors: {
                 rateNameRequired: 'Le nom du taux est obligatoire',
                 existingRateName: 'Un taux kilométrique portant ce nom existe déjà',
-                nameRequired: 'Le nom est obligatoire',
-                startDateMustBeBeforeEndDate: 'La date de début doit être antérieure à la date de fin',
-                amountRequired: 'Le montant est obligatoire',
             },
-            amountPerUnit: (unit: string) => `Montant par ${unit}`,
-            startDate: 'Date de début',
-            endDate: 'Date de fin',
         },
         editor: {
             descriptionInputLabel: 'Description',
@@ -6815,7 +6086,7 @@ _Pour des instructions plus détaillées, [visitez notre site d’aide](${CONST.
             updateToUSD: 'Mettre à jour en USD',
             updateWorkspaceCurrency: 'Mettre à jour la devise de l’espace de travail',
             workspaceCurrencyNotSupported: "Devise de l'espace de travail non prise en charge",
-            yourWorkspace: `Votre espace de travail est défini sur une devise non prise en charge. Consultez la <a href="${CONST.ENABLE_GLOBAL_REIMBURSEMENT_HELP_URL}">liste des devises prises en charge</a>.`,
+            yourWorkspace: `Votre espace de travail est défini sur une devise non prise en charge. Consultez la <a href="${CONST.CONNECT_A_BUSINESS_BANK_ACCOUNT_HELP_URL}">liste des devises prises en charge</a>.`,
             chooseAnExisting: 'Choisissez un compte bancaire existant pour payer les dépenses ou ajoutez-en un nouveau.',
         },
         changeOwner: {
@@ -6852,7 +6123,7 @@ Si vous souhaitez prendre en charge la facturation de l’ensemble de son abonne
             hasFailedSettlementsTitle: 'Impossible de transférer la responsabilité',
             hasFailedSettlementsButtonText: 'Compris',
             hasFailedSettlementsText: (email: string) =>
-                `Vous ne pouvez pas prendre en charge la facturation, car ${email} a un règlement en retard de Carte Expensify. Veuillez lui demander de contacter concierge@expensify.com pour résoudre le problème. Ensuite, vous pourrez prendre en charge la facturation pour cet espace de travail.`,
+                `Vous ne pouvez pas prendre en charge la facturation, car ${email} a un règlement de carte Expensify en retard. Veuillez lui demander de contacter concierge@expensify.com pour résoudre le problème. Ensuite, vous pourrez prendre en charge la facturation de cet espace de travail.`,
             failedToClearBalanceTitle: 'Échec de l’annulation du solde',
             failedToClearBalanceButtonText: 'OK',
             failedToClearBalanceText: 'Nous n’avons pas pu effacer le solde. Veuillez réessayer plus tard.',
@@ -6881,12 +6152,6 @@ Voulez-vous vraiment les exporter à nouveau ?`,
                 onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
                     `<muted-text>Les champs de note de frais sont uniquement disponibles avec l’offre Control, à partir de <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `par membre et par mois.` : `par membre actif et par mois.`}</muted-text>`,
             },
-            invoiceFields: {
-                title: 'Champs de facture',
-                description: `Les champs de facture vous permettent d'inclure des détails supplémentaires au niveau de la facture.`,
-                onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
-                    `<muted-text>Les champs de facture sont uniquement disponibles avec l’offre Control, à partir de <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `par membre et par mois.` : `par membre actif et par mois.`}</muted-text>`,
-            },
             [CONST.POLICY.CONNECTIONS.NAME.NETSUITE]: {
                 title: 'NetSuite',
                 description: `Profitez de la synchronisation automatisée et réduisez les saisies manuelles grâce à l’intégration Expensify + NetSuite. Obtenez des informations financières détaillées et en temps réel avec la prise en charge des segments natifs et personnalisés, y compris la correspondance des projets et des clients.`,
@@ -6905,12 +6170,6 @@ Voulez-vous vraiment les exporter à nouveau ?`,
                 onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
                     `<muted-text>Notre intégration QuickBooks Desktop est uniquement disponible avec l’abonnement Control, à partir de <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `par membre et par mois.` : `par membre actif et par mois.`}</muted-text>`,
             },
-            [CONST.POLICY.CONNECTIONS.NAME.CERTINIA]: {
-                title: 'Certinia',
-                description: `Profitez de la synchronisation automatisée et réduisez les saisies manuelles grâce à l’intégration Expensify + Certinia. Alignez les dimensions de codage des dépenses et la synchronisation fiscale sur votre configuration Certinia pour une meilleure visibilité financière.`,
-                onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
-                    `<muted-text>Notre intégration Certinia est disponible uniquement avec l’offre Control, à partir de <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `par membre et par mois.` : `par membre actif et par mois.`}</muted-text>`,
-            },
             [CONST.UPGRADE_FEATURE_INTRO_MAPPING.approvals.id]: {
                 title: 'Approbations avancées',
                 description: `Si vous souhaitez ajouter plusieurs niveaux d’approbation au processus – ou simplement vous assurer que les plus grosses dépenses sont examinées une fois de plus – nous avons ce qu’il vous faut. Les approbations avancées vous aident à mettre en place les bons contrôles à chaque niveau afin de garder les dépenses de votre équipe sous contrôle.`,
@@ -6988,7 +6247,7 @@ Rendez obligatoires des informations de dépense comme les reçus et les descrip
                 onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
                     `<muted-text>Les taux de distance sont disponibles avec l’abonnement Collect, à partir de <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `par membre et par mois.` : `par membre actif et par mois.`}</muted-text>`,
             },
-            controlPolicyRoles: {
+            auditor: {
                 title: 'Auditeur',
                 description: 'Les auditeurs obtiennent un accès en lecture seule à toutes les notes de frais pour une visibilité complète et le suivi de la conformité.',
                 onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
@@ -7005,12 +6264,13 @@ Rendez obligatoires des informations de dépense comme les reçus et les descrip
                 perActiveMember: 'par membre actif et par mois.',
                 perMember: 'par membre et par mois.',
             },
-            note: (subscriptionLink: string) => `<muted-text><a href="${subscriptionLink}">En savoir plus</a> sur nos offres et nos tarifs.</muted-text>`,
+            note: ({subscriptionLink}: WorkspaceUpgradeNoteParams) =>
+                `<muted-text>Mettez à niveau pour accéder à cette fonctionnalité, ou <a href="${subscriptionLink}">en savoir plus</a> sur nos offres et nos tarifs.</muted-text>`,
             upgradeToUnlock: 'Débloquer cette fonctionnalité',
             completed: {
                 headline: `Vous avez mis à niveau votre espace de travail !`,
-                successMessage: (policyName: string, planName: string, subscriptionLink: string) =>
-                    `<centered-text>Vous avez réussi à passer ${policyName} au plan ${planName} ! <a href="${subscriptionLink}">Afficher votre abonnement</a> pour plus de détails.</centered-text>`,
+                successMessage: ({policyName, subscriptionLink}: UpgradeSuccessMessageParams) =>
+                    `<centered-text>Vous avez réussi à passer ${policyName} au plan Control ! <a href="${subscriptionLink}">Afficher votre abonnement</a> pour plus de détails.</centered-text>`,
                 categorizeMessage: `Vous êtes passé avec succès au forfait Collect. Vous pouvez maintenant catégoriser vos dépenses !`,
                 travelMessage: `Vous êtes passé avec succès au plan Collect. Vous pouvez maintenant commencer à réserver et gérer vos voyages !`,
                 distanceRateMessage: `Vous êtes passé avec succès au forfait Collect. Vous pouvez maintenant modifier le taux de distance !`,
@@ -7034,87 +6294,24 @@ Rendez obligatoires des informations de dépense comme les reçus et les descrip
                 upgradeWorkspaceWarningForRestrictedPolicyCreationPrompt:
                     'Votre entreprise a restreint la création d’espaces de travail. Veuillez contacter un administrateur pour obtenir de l’aide.',
             },
-            hr: {
-                title: 'Intégrations RH',
-                description:
-                    'Connectez votre fournisseur RH pour synchroniser automatiquement les employés et gérer les workflows d’approbation. Maintenez la liste de votre équipe et la structure de reporting à jour sans travail manuel.',
-                onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
-                    `<muted-text>Les intégrations RH sont uniquement disponibles avec l’offre Control, à partir de <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `par membre et par mois.` : `par membre actif et par mois.`}</muted-text>`,
-            },
-            approvalSubmit: {
-                title: 'Approbations',
-                description: 'Configurez de manière centralisée à qui tous les membres soumettent en activant les approbations.',
-                onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
-                    `<muted-text>Les validations sont disponibles avec les forfaits Collect et Control, à partir de <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `par membre et par mois.` : `par membre actif et par mois.`}</muted-text>`,
-            },
-            companyCardSubmit: {
-                title: 'Cartes d’entreprise',
-                description: `Apportez votre propre carte professionnelle dans Expensify pour bénéficier de l’importation automatique, de la catégorisation automatique, de règles personnalisables et du rapprochement intégré.`,
-                onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
-                    `<muted-text>L’importation de cartes d’entreprise est disponible avec les offres Collect et Control, à partir de <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `par membre et par mois.` : `par membre actif et par mois.`}</muted-text>`,
-            },
-            travelSubmit: {
-                title: 'Expensify Travel',
-                description:
-                    'Réservez des vols, hôtels, voitures et trains à tarif réduit partout dans le monde depuis Expensify, avec rapports de devoir de diligence et gestion intégrée des dépenses.',
-                onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
-                    `<muted-text>Expensify Travel est disponible avec les forfaits Collect et Control, à partir de <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `par membre et par mois.` : `par membre actif et par mois.`}</muted-text>`,
-            },
-            roles: {
-                title: 'Rôles',
-                description: 'Attribuez différents rôles aux différents membres pour augmenter ou réduire la visibilité et le contrôle selon les besoins.',
-                onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
-                    `<muted-text>Les rôles sont disponibles avec les formules Collect et Control, à partir de <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `par membre et par mois.` : `par membre actif et par mois.`}</muted-text>`,
-            },
-            payments: {
-                title: 'Paiements',
-                description: 'Remboursez vos employé·e·s directement depuis le compte bancaire de votre entreprise.',
-                onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
-                    `<muted-text>Les paiements sont disponibles avec les offres Collect et Control, à partir de <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `par membre et par mois.` : `par membre actif et par mois.`}</muted-text>`,
-            },
-            accounting: {
-                title: 'Comptabilité',
-                description:
-                    'Synchronisez les catégories, les tags, les taux de taxe et plus encore depuis votre système comptable vers Expensify, et exportez également les notes de frais et les transactions par carte – sans saisie (ni fautes de frappe) !',
-                onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
-                    `<muted-text>La comptabilité est disponible avec les offres Collect et Control, à partir de <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `par membre et par mois.` : `par membre actif et par mois.`}</muted-text>`,
-            },
-            expensifyCard: {
-                title: 'Carte Expensify',
-                description:
-                    'Émettez des cartes d’entreprise (y compris des cartes virtuelles) directement depuis votre propre compte bancaire pour bénéficier d’un contrôle des dépenses en temps réel avec une connexion infaillible, et jusqu’à 2 % de cashback !',
-                onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
-                    `<muted-text>La carte Expensify est disponible avec les offres Collect et Control, à partir de <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `par membre et par mois.` : `par membre actif et par mois.`}</muted-text>`,
-                upgradeButton: 'Mettre à niveau et activer',
-            },
-            invoicing: {
-                title: 'Facturation',
-                description:
-                    'Créez, envoyez et suivez des factures professionnelles, le tout dans Expensify. Soyez payé plus rapidement grâce aux paiements intégrés et à la visibilité en temps réel.',
-                onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
-                    `<muted-text>La facturation est disponible avec les offres Collect et Control, à partir de <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `par membre et par mois.` : `par membre actif et par mois.`}</muted-text>`,
-            },
         },
         downgrade: {
             commonFeatures: {
-                title: 'Rétrograder vers Collect',
-                note: "Vous perdrez l'accès aux fonctionnalités suivantes",
+                title: 'Passer au forfait Collect inférieur',
+                note: 'Si vous rétrogradez, vous perdrez l’accès à ces fonctionnalités et plus encore :',
                 benefits: {
-                    confirm: 'Vous devrez modifier le « Type de plan » de chaque espace de travail en « Collect » afin de bénéficier du tarif Collect.',
-                    benefit1: 'NetSuite, Sage Intacct, QuickBooks Desktop, Oracle, Microsoft Dynamics',
-                    benefit2: 'Workday, Certinia',
-                    benefit3: 'SSO/SAML',
-                    benefit4: 'Règles de dépenses intelligentes, indemnités journalières, approbations multi-niveaux, rapports personnalisés et budgétisation',
+                    note: 'Pour une comparaison complète de nos offres, consultez notre',
+                    pricingPage: 'page des tarifs',
+                    confirm: 'Voulez-vous vraiment rétrograder et supprimer vos configurations ?',
+                    warning: 'Cette action est irréversible.',
+                    benefit1: 'Connexions comptables (sauf QuickBooks Online et Xero)',
+                    benefit2: 'Règles de dépenses intelligentes',
+                    benefit3: 'Flux d’approbation multi-niveaux',
+                    benefit4: 'Contrôles de sécurité renforcés',
                     headsUp: 'Attention !',
                     multiWorkspaceNote: 'Vous devrez rétrograder tous vos espaces de travail avant votre premier paiement mensuel pour commencer un abonnement au tarif Collect. Cliquez',
                     selectStep: '> sélectionnez chaque espace de travail > modifiez le type d’abonnement en',
-                    benefit1Label: 'Intégrations ERP',
-                    benefit2Label: 'Intégrations RH',
-                    benefit3Label: 'Sécurité',
-                    benefit4Label: 'Avancé',
-                    important: 'IMPORTANT :',
                 },
-                noteAndMore: 'et plus :',
             },
             completed: {
                 headline: 'Votre espace de travail a été rétrogradé',
@@ -7134,7 +6331,7 @@ Rendez obligatoires des informations de dépense comme les reçus et les descrip
         restrictedAction: {
             restricted: 'Restreint',
             actionsAreCurrentlyRestricted: (workspaceName: string) => `Les actions sur l’espace de travail ${workspaceName} sont actuellement restreintes`,
-            workspaceOwnerWillNeedToAddOrUpdatePaymentCard: (workspaceOwnerName: string) =>
+            workspaceOwnerWillNeedToAddOrUpdatePaymentCard: ({workspaceOwnerName}: WorkspaceOwnerWillNeedToAddOrUpdatePaymentCardParams) =>
                 `Le responsable de l’espace de travail, ${workspaceOwnerName}, doit ajouter ou mettre à jour la carte de paiement enregistrée pour débloquer la nouvelle activité de l’espace de travail.`,
             youWillNeedToAddOrUpdatePaymentCard: 'Vous devez ajouter ou mettre à jour la carte de paiement enregistrée afin de débloquer la nouvelle activité de l’espace de travail.',
             addPaymentCardToUnlock: 'Ajoutez une carte de paiement pour tout débloquer !',
@@ -7187,18 +6384,16 @@ Rendez obligatoires des informations de dépense comme les reçus et les descrip
                 eReceiptsHint: `Les e-reçus sont créés automatiquement [pour la plupart des transactions par carte en USD](${CONST.DEEP_DIVE_ERECEIPTS}).`,
                 attendeeTracking: 'Suivi des participants',
                 attendeeTrackingHint: 'Suivez le coût par personne pour chaque dépense.',
-                prohibitedDefaultDescription: 'Signaler les reçus contenant ces postes pour examen manuel.',
+                prohibitedDefaultDescription:
+                    'Signalez tous les reçus où figurent de l’alcool, des jeux d’argent ou d’autres articles restreints. Les dépenses accompagnées de reçus contenant ces postes devront être examinées manuellement.',
                 prohibitedExpenses: 'Dépenses interdites',
                 alcohol: 'Alcool',
                 hotelIncidentals: 'Frais annexes d’hôtel',
                 gambling: 'Jeux d’argent',
                 tobacco: 'Tabac',
                 adultEntertainment: 'Divertissement pour adultes',
-                giftCard: 'Achats de cartes-cadeaux',
-                handwrittenReceipt: 'Reçus manuscrits',
                 requireCompanyCard: "Exiger l'utilisation de cartes d'entreprise pour tous les achats",
                 requireCompanyCardDescription: 'Signaler toutes les dépenses en espèces, y compris le kilométrage et les indemnités journalières.',
-                requireCompanyCardDisabledTooltip: 'Activez les cartes d’entreprise (dans Plus de fonctionnalités) pour déverrouiller.',
             },
             expenseReportRules: {
                 title: 'Avancé',
@@ -7207,8 +6402,8 @@ Rendez obligatoires des informations de dépense comme les reçus et les descrip
                 preventSelfApprovalsSubtitle: 'Empêcher les membres de l’espace de travail d’approuver leurs propres notes de frais.',
                 autoApproveCompliantReportsTitle: 'Approuver automatiquement les notes de frais conformes',
                 autoApproveCompliantReportsSubtitle: 'Configurer quelles notes de frais sont éligibles à l’auto-approbation.',
-                autoApproveReportsUnderTitle: 'Approuver automatiquement les notes de frais dont toutes les dépenses sont inférieures à',
-                autoApproveReportsUnderDescription: 'Les notes de frais entièrement conformes dont toutes les dépenses sont en dessous de ce montant seront automatiquement approuvées.',
+                autoApproveReportsUnderTitle: 'Approuver automatiquement les notes de frais inférieures à',
+                autoApproveReportsUnderDescription: 'Les notes de frais entièrement conformes en dessous de ce montant seront automatiquement approuvées.',
                 randomReportAuditTitle: 'Audit aléatoire de notes de frais',
                 randomReportAuditDescription: 'Exiger que certaines notes de frais soient approuvées manuellement, même si elles sont éligibles à l’auto-approbation.',
                 autoPayApprovedReportsTitle: 'Payer automatiquement les notes de frais approuvées',
@@ -7221,11 +6416,6 @@ Rendez obligatoires des informations de dépense comme les reçus et les descrip
                 enableFeatureSubtitle: (featureName: string, moreFeaturesLink?: string) =>
                     `Allez dans [plus de fonctionnalités](${moreFeaturesLink}) et activez ${featureName} pour déverrouiller cette fonctionnalité.`,
             },
-            agentsPromoBanner: {
-                title: 'Vous ne voyez pas la règle dont vous avez besoin ? Ajoutez un agent',
-                subtitle: 'Ajoutez des règles complexes et réduisez les approbations manuelles grâce à des agents personnalisés.',
-                cta: 'Essayer',
-            },
             merchantRules: {
                 title: 'Commerçant',
                 subtitle: 'Définissez les règles de commerçant pour que les dépenses arrivent correctement codées et nécessitent moins de nettoyage.',
@@ -7253,10 +6443,9 @@ Rendez obligatoires des informations de dépense comme les reçus et les descrip
                 matchTypeContains: 'Contient',
                 matchTypeExact: 'Correspond exactement',
                 duplicateRuleTitle: 'Une règle de commerçant similaire existe déjà',
-                duplicateRulePrompt: (merchantName: string) => `Votre règle existante pour « ${merchantName} » aura la priorité sur celle-ci. Enregistrer quand même ?`,
+                duplicateRulePrompt: (merchantName: string) => `Voulez-vous enregistrer une nouvelle règle pour « ${merchantName} » même si vous en avez déjà une ?`,
                 saveAnyway: 'Enregistrer quand même',
                 applyToExistingUnsubmittedExpenses: 'Appliquer aux dépenses non soumises existantes',
-                findRule: 'Règle de recherche de commerçant',
             },
             categoryRules: {
                 title: 'Règles de catégorie',
@@ -7295,131 +6484,12 @@ Rendez obligatoires des informations de dépense comme les reçus et les descrip
                     always: 'Toujours exiger des reçus détaillés',
                 },
                 defaultTaxRate: 'Taux de taxe par défaut',
-                enableWorkflows: (moreFeaturesLink: string) =>
+                enableWorkflows: ({moreFeaturesLink}: RulesEnableWorkflowsParams) =>
                     `Allez dans [Plus de fonctionnalités](${moreFeaturesLink}) et activez les workflows, puis ajoutez des approbations pour déverrouiller cette fonctionnalité.`,
             },
             customRules: {
                 title: 'Politique de dépenses',
                 cardSubtitle: 'C’est ici que se trouve la politique de dépenses de votre équipe, pour que tout le monde soit d’accord sur ce qui est couvert.',
-                policyDocument: 'Document de politique',
-                policyText: 'Texte de politique',
-            },
-            spendRules: {
-                title: 'Dépenser',
-                subtitle: 'Approuvez ou refusez les transactions Carte Expensify en temps réel.',
-                defaultRuleDescription: 'Toutes les cartes',
-                block: 'Bloquer',
-                defaultRuleTitle: 'Catégories : services pour adultes, DAB, jeux d’argent, transferts d’argent',
-                builtInProtectionModal: {
-                    title: 'Les Cartes Expensify offrent une protection intégrée – en permanence',
-                    description: `Expensify refuse toujours ces dépenses :
-
-  • Services pour adultes
-  • DAB
-  • Jeux d’argent
-  • Transferts d’argent
-
-Ajoutez davantage de règles de dépenses pour protéger la trésorerie de l’entreprise.`,
-                },
-                addSpendRule: 'Ajouter une règle de dépense',
-                cardPageTitle: 'Carte',
-                cardsSectionTitle: 'Cartes',
-                chooseCards: 'Choisir des cartes',
-                saveRule: 'Enregistrer la règle',
-                allow: 'Autoriser',
-                spendRuleSectionTitle: 'Règle de dépense',
-                restrictionType: 'Type de restriction',
-                restrictionTypeHelpAllow: 'Les frais sont approuvés s’ils correspondent à n’importe quel commerçant ou catégorie et ne dépassent pas un montant maximal.',
-                restrictionTypeHelpBlock: 'Les frais sont refusés s’ils correspondent à un commerçant ou à une catégorie, ou s’ils dépassent un montant maximal.',
-                addMerchant: 'Ajouter un commerçant',
-                merchantContains: 'Le commerçant contient',
-                merchantExactlyMatches: 'Le commerçant correspond exactement',
-                noBlockedMerchants: 'Aucun commerçant bloqué',
-                addMerchantToBlockSpend: 'Ajouter un commerçant pour bloquer les dépenses',
-                noAllowedMerchants: 'Aucun commerçant autorisé',
-                addMerchantToAllowSpend: 'Ajouter un commerçant pour autoriser les dépenses',
-                matchType: 'Type de correspondance',
-                matchTypeContains: 'Contient',
-                matchTypeExact: 'Correspond exactement',
-                spendCategory: 'Catégorie de dépense',
-                maxAmount: 'Montant maximal',
-                maxAmountHelp: 'Toute transaction supérieure à ce montant sera refusée, indépendamment des restrictions liées au commerçant et à la catégorie de dépense.',
-                currencyMismatchTitle: 'Incompatibilité de devise',
-                currencyMismatchPrompt: 'Pour définir un montant maximal, sélectionnez des cartes qui sont réglées dans la même devise.',
-                reviewSelectedCards: 'Examiner les cartes sélectionnées',
-                summaryMoreCount: ({summary, count}: {summary: string; count: number}) => (count > 0 ? `${summary}, +${count} de plus` : summary),
-                confirmErrorApplyAtLeastOneSpendRuleToOneCard: 'Appliquez au moins une règle de dépense à une carte',
-                confirmErrorCardRequired: 'La carte est un champ obligatoire',
-                confirmErrorApplyAtLeastOneSpendRule: 'Appliquez au moins une règle de dépense',
-                categories: 'Catégories',
-                merchants: 'Commerçants',
-                noAvailableCards: 'Toutes les cartes ont déjà une règle',
-                noAvailableCardsSubtitle: 'Modifier une règle de carte existante pour apporter des changements',
-                noCardsIssuedTitle: 'Aucune Carte Expensify émise',
-                noCardsIssuedSubtitle: 'Émettre des cartes Expensify pour créer des règles de dépense',
-                max: 'Max',
-                categoryOptions: {
-                    [CONST.SPEND_RULES.CATEGORIES.AIRLINES]: 'Compagnies aériennes',
-                    [CONST.SPEND_RULES.CATEGORIES.ALCOHOL_AND_BARS]: 'Alcool et bars',
-                    [CONST.SPEND_RULES.CATEGORIES.AMAZON_AND_BOOKSTORES]: 'Amazon et les librairies',
-                    [CONST.SPEND_RULES.CATEGORIES.AUTOMOTIVE]: 'Automobile',
-                    [CONST.SPEND_RULES.CATEGORIES.CAR_RENTALS]: 'Locations de voiture',
-                    [CONST.SPEND_RULES.CATEGORIES.DINING]: 'Restauration',
-                    [CONST.SPEND_RULES.CATEGORIES.FUEL_AND_GAS]: 'Carburant et gaz',
-                    [CONST.SPEND_RULES.CATEGORIES.GOVERNMENT_AND_NON_PROFITS]: 'Secteur public et organisations à but non lucratif',
-                    [CONST.SPEND_RULES.CATEGORIES.GROCERIES]: 'Courses',
-                    [CONST.SPEND_RULES.CATEGORIES.GYMS_AND_FITNESS]: 'Salles de sport et fitness',
-                    [CONST.SPEND_RULES.CATEGORIES.HEALTHCARE]: 'Santé',
-                    [CONST.SPEND_RULES.CATEGORIES.HOTELS]: 'Hôtels',
-                    [CONST.SPEND_RULES.CATEGORIES.INTERNET_AND_PHONE]: 'Internet et téléphone',
-                    [CONST.SPEND_RULES.CATEGORIES.OFFICE_SUPPLIES]: 'Fournitures de bureau',
-                    [CONST.SPEND_RULES.CATEGORIES.PARKING_AND_TOLLS]: 'Parking et péages',
-                    [CONST.SPEND_RULES.CATEGORIES.PROFESSIONAL_SERVICES]: 'Services professionnels',
-                    [CONST.SPEND_RULES.CATEGORIES.RETAIL]: 'Vente au détail',
-                    [CONST.SPEND_RULES.CATEGORIES.SHIPPING_AND_DELIVERY]: 'Expédition et livraison',
-                    [CONST.SPEND_RULES.CATEGORIES.SOFTWARE]: 'Logiciel',
-                    [CONST.SPEND_RULES.CATEGORIES.TRANSIT_AND_RIDESHARE]: 'Transports en commun et VTC',
-                    [CONST.SPEND_RULES.CATEGORIES.TRAVEL_AGENCIES]: 'Agences de voyages',
-                },
-                editRuleTitle: 'Modifier la règle',
-                deleteRule: 'Supprimer la règle',
-                deleteRuleConfirmation: 'Êtes-vous sûr de vouloir supprimer cette règle ?',
-                summaryMerchants: ({
-                    merchants,
-                    hiddenCount,
-                    shownCount,
-                    action,
-                }: {
-                    merchants: string;
-                    hiddenCount: number;
-                    shownCount: number;
-                    action: ValueOf<typeof CONST.SPEND_RULES.ACTION>;
-                }) =>
-                    `${action === CONST.SPEND_RULES.ACTION.BLOCK ? 'Bloqué' : 'Autorisé'} ${shownCount > 1 ? 'commerçants' : 'commerçant'}: ${merchants}${hiddenCount > 0 ? `, +${hiddenCount} de plus` : ''}`,
-                summaryCategories: ({
-                    categories,
-                    hiddenCount,
-                    shownCount,
-                    action,
-                }: {
-                    categories: string;
-                    hiddenCount: number;
-                    shownCount: number;
-                    action: ValueOf<typeof CONST.SPEND_RULES.ACTION>;
-                }) =>
-                    `${action === CONST.SPEND_RULES.ACTION.BLOCK ? 'Bloqué' : 'Autorisé'} ${shownCount > 1 ? 'catégories' : 'catégorie'}: ${categories}${hiddenCount > 0 ? `, +${hiddenCount} de plus` : ''}`,
-            },
-            aiRules: {
-                title: 'Règles IA',
-                subtitle: 'Décrivez des règles flexibles qui s’exécutent quand vous en avez besoin',
-                addRule: 'Ajouter une règle IA',
-                findRule: 'Rechercher une règle d’IA',
-                addRuleTitle: 'Ajouter une règle',
-                editRuleTitle: 'Modifier la règle',
-                deleteRule: 'Supprimer la règle',
-                deleteRuleConfirmation: 'Voulez-vous vraiment supprimer cette règle ?',
-                describeRuleTitle: 'Décrivez votre règle',
-                describeRuleSubtitle: 'Décrivez votre règle et Concierge la créera',
             },
         },
         planTypePage: {
@@ -7432,111 +6502,15 @@ Ajoutez davantage de règles de dépenses pour protéger la trésorerie de l’e
                     label: 'Contrôle',
                     description: 'Pour les organisations ayant des exigences avancées.',
                 },
-                submit2026: {
-                    label: 'Soumettre',
-                    description: 'Pour les employés souhaitant soumettre des dépenses à leur employeur.',
-                },
             },
-            description: 'Choisissez l’offre qui vous convient.',
-            subscriptionLink: 'En savoir plus',
+            description: 'Choisissez l’offre qui vous convient. Pour une liste détaillée des fonctionnalités et des tarifs, consultez notre',
+            subscriptionLink: "page d'aide sur les types de forfaits et les tarifs",
             lockedPlanDescription: ({count, annualSubscriptionEndDate}: WorkspaceLockedPlanTypeParams) => ({
                 one: `Vous vous êtes engagé à 1 membre actif sur le plan Control jusqu'à la fin de votre abonnement annuel, le ${annualSubscriptionEndDate}. Vous pourrez passer à un abonnement à l’usage et rétrograder vers le plan Collect à partir du ${annualSubscriptionEndDate} en désactivant le renouvellement automatique dans`,
                 other: `Vous vous êtes engagé·e à avoir ${count} membres actifs sur le forfait Control jusqu’à la fin de votre abonnement annuel le ${annualSubscriptionEndDate}. Vous pouvez passer à un abonnement à l’usage et rétrograder vers le forfait Collect à partir du ${annualSubscriptionEndDate} en désactivant le renouvellement automatique dans`,
             }),
             subscriptions: 'Abonnements',
         },
-        hr: {
-            title: 'RH',
-            connections: 'Connexions',
-            connectionsSubtitle:
-                'Connectez votre système RH pour synchroniser les données des employé·es, faire correspondre automatiquement les remboursements aux bonnes personnes et garder les dépenses de votre équipe exactes, sans travail manuel.',
-            subtitle: 'Connectez vos outils RH et gardez les approbations des employés synchronisées.',
-            connect: 'Connecter',
-            syncNow: 'Synchroniser maintenant',
-            disconnect: 'Déconnecter',
-            disconnectTitle: (providerName: string) => `Déconnecter ${providerName}`,
-            disconnectPrompt: (providerName: string) => `Êtes-vous sûr de vouloir déconnecter ${providerName} ?`,
-            alreadyConnectedTitle: 'Impossible de se connecter à plusieurs plateformes RH',
-            alreadyConnectedPrompt: 'Vous devez déconnecter votre plateforme RH actuelle avant d’en connecter une autre.',
-            lastSync: (relativeDate: string) => `Dernière synchronisation ${relativeDate}`,
-            syncError: (providerName: string) => `Impossible de se connecter à ${providerName}`,
-            connectionDescription: (providerName: string) => `Connectez ${providerName} pour synchroniser les approbations des employés avec votre espace de travail.`,
-            approvalMode: "Mode d'approbation",
-            providerApprovalMode: (providerName: string) => `Mode d'approbation ${providerName}`,
-            finalApprover: 'Approbateur final',
-            providerFinalApprover: (providerName: string) => `Approbateur final ${providerName}`,
-            notSet: 'Non défini',
-            approvalModeDescription: (providerName: string) => `Les membres et les responsables sont configurés pour se synchroniser avec ${providerName}.`,
-            approvalModeWarningTitle: 'Changer le mode d’approbation ?',
-            approvalModeWarningPrompt: (providerName: string, helpSiteURL: string) =>
-                `Êtes-vous sûr·e de vouloir modifier le mode d’approbation de cet espace de travail ? En savoir plus sur les différents modes de workflow compatibles avec ${providerName} sur notre <a href="${helpSiteURL}">site d’aide</a>.`,
-            approvalModeWarningConfirm: 'Modifier le mode d’approbation',
-            approvalModes: {
-                basic: {
-                    label: 'Approbation simple',
-                    description: 'Tous les utilisateurs soumettent à une seule personne pour traitement et approbation.',
-                },
-                manager: {
-                    label: 'Approbation du responsable',
-                    description: (providerName: string) => `Les employé·e·s soumettent leurs rapports à leur responsable direct configuré dans ${providerName}.`,
-                },
-                custom: {
-                    label: 'Approbation personnalisée',
-                    description: 'Je configurerai manuellement les circuits de validation dans Expensify.',
-                },
-            },
-            syncStageName: ({stage}: SyncStageNameConnectionsParams) => {
-                switch (stage) {
-                    case 'gustoSyncTitle':
-                        return 'Synchronisation des employés Gusto';
-                    case 'gustoSyncLoadData':
-                        return 'Chargement des données depuis Gusto';
-                    case 'gustoSyncProvisioning':
-                        return 'Affectation des employés à la politique';
-                    case 'zenefitsSyncTitle':
-                        return 'Synchronisation des employés TriNet';
-                    case 'zenefitsSyncLoadData':
-                        return 'Chargement des données depuis TriNet';
-                    case 'zenefitsSyncProvisioning':
-                        return 'Affectation des employés à la politique';
-                    case 'jobDone':
-                        return 'En attente du chargement des données importées';
-                    default: {
-                        return `Traduction manquante pour l'étape : ${stage}`;
-                    }
-                }
-            },
-            syncResults: {
-                title: (provider: string) => `Synchronisation ${provider} terminée`,
-                successTitle: (provider: string) => `Connexion ${provider} synchronisée avec succès !`,
-                added: 'Ajouté',
-                removed: 'Supprimé',
-                skipped: 'Ignoré',
-                employeeCount: () => ({
-                    one: '1 employé',
-                    other: (count: number) => `${count} employés`,
-                }),
-            },
-            gusto: {
-                title: 'Gusto',
-            },
-            zenefits: {
-                title: 'TriNet',
-            },
-            syncingModalTitle: 'Votre connexion est en cours de synchronisation',
-            syncingModalDescription: 'La première connexion peut prendre un certain temps. Vous serez informé de toute erreur.',
-            syncing: 'Synchronisation des employés',
-            mergeHR: {
-                completeSetup: 'Terminer la configuration',
-                setupIncomplete: (setupLink: string | undefined) =>
-                    `<muted-text-label>Connecté. ${setupLink ? `<a href="${setupLink}">Terminer la configuration</a>` : 'Terminer la configuration'} pour importer les employés.</muted-text-label>`,
-                groups: {title: 'Groupes', description: 'Choisissez les groupes d’employés que vous souhaitez synchroniser avec cet espace de travail'},
-            },
-        },
-        emptyDomain: {
-            title: 'Renforcez votre sécurité avec des domaines',
-            subtitle: 'Obligez les membres de votre domaine à se connecter via l’authentification unique, restreignez la création d’espaces de travail, et plus encore.',
-        },
     },
     getAssistancePage: {
         title: 'Obtenir de l’aide',
@@ -7564,7 +6538,6 @@ Ajoutez davantage de règles de dépenses pour protéger la trésorerie de l’e
             symbols: 'Symboles',
             flags: 'Drapeaux',
         },
-        emojiNotSelected: 'Emoji non sélectionné',
     },
     newRoomPage: {
         newRoom: 'Nouvelle salle',
@@ -7577,7 +6550,7 @@ Ajoutez davantage de règles de dépenses pour protéger la trésorerie de l’e
         public_announceDescription: 'Tout le monde peut trouver cette salle',
         createRoom: 'Créer un salon',
         roomAlreadyExistsError: 'Une salle portant ce nom existe déjà',
-        roomNameReservedError: (reservedName: string) => `${reservedName} est un salon par défaut sur tous les espaces de travail. Veuillez choisir un autre nom.`,
+        roomNameReservedError: ({reservedName}: RoomNameReservedErrorParams) => `${reservedName} est un salon par défaut sur tous les espaces de travail. Veuillez choisir un autre nom.`,
         roomNameInvalidError: 'Les noms de salle peuvent uniquement contenir des lettres minuscules, des chiffres et des tirets',
         pleaseEnterRoomName: 'Veuillez saisir un nom de salle',
         pleaseSelectWorkspace: 'Veuillez sélectionner un espace de travail',
@@ -7585,7 +6558,7 @@ Ajoutez davantage de règles de dépenses pour protéger la trésorerie de l’e
             const actor = actorName ? `${actorName} ` : '';
             return isExpenseReport ? `${actor}renommé en « ${newName} » (précédemment « ${oldName} »)` : `${actor}a renommé cette salle en « ${newName} » (auparavant « ${oldName} »)`;
         },
-        roomRenamedTo: (newName: string) => `Salon renommé en ${newName}`,
+        roomRenamedTo: ({newName}: RoomRenamedToParams) => `Salon renommé en ${newName}`,
         social: 'réseaux sociaux',
         selectAWorkspace: 'Sélectionner un espace de travail',
         growlMessageOnRenameError: 'Impossible de renommer la salle de l’espace de travail. Veuillez vérifier votre connexion et réessayer.',
@@ -7627,14 +6600,14 @@ Ajoutez davantage de règles de dépenses pour protéger la trésorerie de l’e
             `a ajouté ${approverName} (${approverEmail}) comme approbateur pour le champ ${field} « ${name} »`,
         deleteApprovalRule: (approverEmail: string, approverName: string, field: string, name: string) =>
             `a retiré ${approverName} (${approverEmail}) en tant qu'approbateur pour le champ ${field} « ${name} »`,
-        updateApprovalRule: (field: string, name: string, newApproverEmail: string, newApproverName: string | undefined, oldApproverEmail: string, oldApproverName: string | undefined) => {
+        updateApprovalRule: ({field, name, newApproverEmail, newApproverName, oldApproverEmail, oldApproverName}: UpdatedPolicyApprovalRuleParams) => {
             const formatApprover = (displayName?: string, email?: string) => (displayName ? `${displayName} (${email})` : email);
             return `a modifié l’approbateur pour le champ ${field} « ${name} » en ${formatApprover(newApproverName, newApproverEmail)} (auparavant ${formatApprover(oldApproverName, oldApproverEmail)})`;
         },
-        addCategory: (categoryName: string) => `a ajouté la catégorie « ${categoryName} »`,
-        deleteCategory: (categoryName: string) => `a supprimé la catégorie « ${categoryName} »`,
-        updateCategory: (categoryName: string, oldValue: boolean) => `${oldValue ? 'Désactivé' : 'Activé'} la catégorie « ${categoryName} »`,
-        updateCategoryPayrollCode: (categoryName: string, newValue?: string, oldValue?: string) => {
+        addCategory: ({categoryName}: UpdatedPolicyCategoryParams) => `a ajouté la catégorie « ${categoryName} »`,
+        deleteCategory: ({categoryName}: UpdatedPolicyCategoryParams) => `a supprimé la catégorie « ${categoryName} »`,
+        updateCategory: ({oldValue, categoryName}: UpdatedPolicyCategoryParams) => `${oldValue ? 'Désactivé' : 'Activé'} la catégorie « ${categoryName} »`,
+        updateCategoryPayrollCode: ({oldValue, categoryName, newValue}: UpdatedPolicyCategoryGLCodeParams) => {
             if (!oldValue) {
                 return `a ajouté le code de paie « ${newValue} » à la catégorie « ${categoryName} »`;
             }
@@ -7643,7 +6616,7 @@ Ajoutez davantage de règles de dépenses pour protéger la trésorerie de l’e
             }
             return `a modifié le code de paie de la catégorie « ${categoryName} » en « ${newValue} » (auparavant « ${oldValue} »)`;
         },
-        updateCategoryGLCode: (categoryName: string, newValue?: string, oldValue?: string) => {
+        updateCategoryGLCode: ({oldValue, categoryName, newValue}: UpdatedPolicyCategoryGLCodeParams) => {
             if (!oldValue) {
                 return `a ajouté le code de grand livre « ${newValue} » à la catégorie « ${categoryName} »`;
             }
@@ -7652,10 +6625,10 @@ Ajoutez davantage de règles de dépenses pour protéger la trésorerie de l’e
             }
             return `a modifié le code GL de la catégorie « ${categoryName} » en « ${newValue} » (précédemment « ${oldValue} »)`;
         },
-        updateAreCommentsRequired: (categoryName: string, oldValue: boolean) => {
+        updateAreCommentsRequired: ({oldValue, categoryName}: UpdatedPolicyCategoryParams) => {
             return `a modifié la description de la catégorie « ${categoryName} » en ${!oldValue ? 'obligatoire' : 'non obligatoire'} (auparavant ${!oldValue ? 'non obligatoire' : 'obligatoire'})`;
         },
-        updateCategoryMaxExpenseAmount: (categoryName: string, newAmount?: string, oldAmount?: string) => {
+        updateCategoryMaxExpenseAmount: ({categoryName, oldAmount, newAmount}: UpdatedPolicyCategoryMaxExpenseAmountParams) => {
             if (newAmount && !oldAmount) {
                 return `a ajouté un montant maximal de ${newAmount} à la catégorie « ${categoryName} »`;
             }
@@ -7664,26 +6637,26 @@ Ajoutez davantage de règles de dépenses pour protéger la trésorerie de l’e
             }
             return `a modifié le montant maximal de la catégorie « ${categoryName} » à ${newAmount} (auparavant ${oldAmount})`;
         },
-        updateCategoryExpenseLimitType: (categoryName: string, newValue: string, oldValue?: string) => {
+        updateCategoryExpenseLimitType: ({categoryName, oldValue, newValue}: UpdatedPolicyCategoryExpenseLimitTypeParams) => {
             if (!oldValue) {
                 return `a ajouté un type de limite de ${newValue} à la catégorie « ${categoryName} »`;
             }
             return `a modifié le type de limite de la catégorie « ${categoryName} » en ${newValue} (auparavant ${oldValue})`;
         },
-        updateCategoryMaxAmountNoReceipt: (categoryName: string, newValue: string, oldValue?: string) => {
+        updateCategoryMaxAmountNoReceipt: ({categoryName, oldValue, newValue}: UpdatedPolicyCategoryMaxAmountNoReceiptParams) => {
             if (!oldValue) {
                 return `a mis à jour la catégorie « ${categoryName} » en modifiant Reçus en ${newValue}`;
             }
             return `a modifié la catégorie « ${categoryName} » en ${newValue} (précédemment ${oldValue})`;
         },
-        updateCategoryMaxAmountNoItemizedReceipt: (categoryName: string, oldValue: string | undefined, newValue: string) => {
+        updateCategoryMaxAmountNoItemizedReceipt: ({categoryName, oldValue, newValue}: UpdatedPolicyCategoryMaxAmountNoReceiptParams) => {
             if (!oldValue) {
                 return `a mis à jour la catégorie « ${categoryName} » en changeant Reçus détaillés en ${newValue}`;
             }
             return `a modifié les reçus détaillés de la catégorie « ${categoryName} » en ${newValue} (auparavant ${oldValue})`;
         },
-        setCategoryName: (oldName: string, newName: string) => `a renommé la catégorie « ${oldName} » en « ${newName} »`,
-        updatedDescriptionHint: (categoryName: string, newValue?: string, oldValue?: string) => {
+        setCategoryName: ({oldName, newName}: UpdatedPolicyCategoryNameParams) => `a renommé la catégorie « ${oldName} » en « ${newName} »`,
+        updatedDescriptionHint: ({categoryName, oldValue, newValue}: UpdatedPolicyCategoryDescriptionHintTypeParams) => {
             if (!newValue) {
                 return `a supprimé l’indication de description « ${oldValue} » de la catégorie « ${categoryName} »`;
             }
@@ -7691,42 +6664,44 @@ Ajoutez davantage de règles de dépenses pour protéger la trésorerie de l’e
                 ? `a ajouté l’indication de description « ${newValue} » à la catégorie « ${categoryName} »`
                 : `a modifié l’aide à la description de la catégorie « ${categoryName} » en « ${newValue} » (auparavant « ${oldValue} »)`;
         },
-        updateTagListName: (oldName: string, newName: string) => `a changé le nom de la liste de tags en « ${newName} » (précédemment « ${oldName} »)`,
-        addTag: (tagListName: string, tagName?: string) => `a ajouté le tag « ${tagName} » à la liste « ${tagListName} »`,
-        updateTagName: (tagListName: string, newName: string, oldName: string) => `a mis à jour la liste de tags « ${tagListName} » en remplaçant le tag « ${oldName} » par « ${newName} »`,
-        updateTagEnabled: (tagListName: string, tagName?: string, enabled?: boolean) => `${enabled ? 'activé' : 'Désactivé'} l’étiquette « ${tagName} » sur la liste « ${tagListName} »`,
-        deleteTag: (tagListName: string, tagName?: string) => `a supprimé la balise « ${tagName} » de la liste « ${tagListName} »`,
-        deleteMultipleTags: (count?: string, tagListName?: string) => `a supprimé les balises « ${count} » de la liste « ${tagListName} »`,
-        updateTag: (tagListName: string, newValue: string, tagName: string, updatedField: string, oldValue?: string) => {
+        updateTagListName: ({oldName, newName}: UpdatedPolicyCategoryNameParams) => `a changé le nom de la liste de tags en « ${newName} » (précédemment « ${oldName} »)`,
+        addTag: ({tagListName, tagName}: UpdatedPolicyTagParams) => `a ajouté le tag « ${tagName} » à la liste « ${tagListName} »`,
+        updateTagName: ({tagListName, newName, oldName}: UpdatedPolicyTagNameParams) =>
+            `a mis à jour la liste de tags « ${tagListName} » en remplaçant le tag « ${oldName} » par « ${newName} »`,
+        updateTagEnabled: ({tagListName, tagName, enabled}: UpdatedPolicyTagParams) => `${enabled ? 'activé' : 'Désactivé'} l’étiquette « ${tagName} » sur la liste « ${tagListName} »`,
+        deleteTag: ({tagListName, tagName}: UpdatedPolicyTagParams) => `a supprimé la balise « ${tagName} » de la liste « ${tagListName} »`,
+        deleteMultipleTags: ({count, tagListName}: UpdatedPolicyTagParams) => `a supprimé les balises « ${count} » de la liste « ${tagListName} »`,
+        updateTag: ({tagListName, newValue, tagName, updatedField, oldValue}: UpdatedPolicyTagFieldParams) => {
             if (oldValue) {
                 return `a mis à jour le tag « ${tagName} » dans la liste « ${tagListName} » en modifiant ${updatedField} en « ${newValue} » (auparavant « ${oldValue} »)`;
             }
             return `a mis à jour le tag « ${tagName} » dans la liste « ${tagListName} » en ajoutant un(e) ${updatedField} de « ${newValue} »`;
         },
-        updateCustomUnit: (customUnitName: string, newValue: string, oldValue: string, updatedField: string) =>
+        updateCustomUnit: ({customUnitName, newValue, oldValue, updatedField}: UpdatePolicyCustomUnitParams) =>
             `a modifié le ${customUnitName} ${updatedField} en « ${newValue} » (auparavant « ${oldValue} »)`,
-        updateCustomUnitTaxEnabled: (newValue: boolean) => `Suivi fiscal ${newValue ? 'activé' : 'Désactivé'} sur les taux de distance`,
-        addCustomUnitRate: (customUnitName: string, rateName: string) => `a ajouté le taux ${customUnitName} « ${rateName} »`,
-        updatedCustomUnitRate: (customUnitName: string, customUnitRateName: string, updatedField: string, newValue: string, oldValue: string) =>
+        updateCustomUnitTaxEnabled: ({newValue}: UpdatePolicyCustomUnitTaxEnabledParams) => `Suivi fiscal ${newValue ? 'activé' : 'Désactivé'} sur les taux de distance`,
+        addCustomUnitRate: ({customUnitName, rateName}: AddOrDeletePolicyCustomUnitRateParams) => `a ajouté un nouveau taux ${customUnitName} « ${rateName} »`,
+        updatedCustomUnitRate: ({customUnitName, customUnitRateName, newValue, oldValue, updatedField}: UpdatedPolicyCustomUnitRateParams) =>
             `a modifié le taux de ${customUnitName} ${updatedField} « ${customUnitRateName} » en « ${newValue} » (auparavant « ${oldValue} »)`,
-        updatedCustomUnitTaxRateExternalID: (customUnitRateName: string, newValue: string, newTaxPercentage: string, oldTaxPercentage?: string, oldValue?: string) => {
+        updatedCustomUnitTaxRateExternalID: ({customUnitRateName, newValue, newTaxPercentage, oldTaxPercentage, oldValue}: UpdatedPolicyCustomUnitTaxRateExternalIDParams) => {
             if (oldTaxPercentage && oldValue) {
                 return `a modifié le taux de taxe du taux de distance « ${customUnitRateName} » à « ${newValue} (${newTaxPercentage}) » (auparavant « ${oldValue} (${oldTaxPercentage}) »)`;
             }
             return `a ajouté le taux de taxe « ${newValue} (${newTaxPercentage}) » au taux de distance « ${customUnitRateName} »`;
         },
-        updatedCustomUnitTaxClaimablePercentage: (customUnitRateName: string, newValue: number, oldValue?: number) => {
+        updatedCustomUnitTaxClaimablePercentage: ({customUnitRateName, newValue, oldValue}: UpdatedPolicyCustomUnitTaxClaimablePercentageParams) => {
             if (oldValue) {
                 return `a modifié la part de taxe récupérable sur le taux de distance « ${customUnitRateName} » à « ${newValue} » (auparavant « ${oldValue} »)`;
             }
             return `a ajouté une partie de taxe récupérable de « ${newValue} » au taux de distance « ${customUnitRateName} »`;
         },
-        updatedCustomUnitRateName: (customUnitName: string, oldValue: string, newValue: string) => `a renommé le taux ${customUnitName} de « ${oldValue} » en « ${newValue} »`,
-        updatedCustomUnitRateEnabled: (customUnitName: string, customUnitRateName: string, newValue: boolean) => {
+        updatedCustomUnitRateEnabled: ({customUnitName, customUnitRateName, newValue}: UpdatedPolicyCustomUnitRateEnabledParams) => {
             return `${newValue ? 'Activé' : 'Désactivé'} le taux de ${customUnitName} « ${customUnitRateName} »`;
         },
-        deleteCustomUnitRate: (customUnitName: string, rateName: string) => `a supprimé le taux « ${customUnitName} » « ${rateName} »`,
-        updateReportFieldDefaultValue: (defaultValue?: string, fieldName?: string) => `définir la valeur par défaut du champ de note de frais « ${fieldName} » sur « ${defaultValue} »`,
+        deleteCustomUnitRate: ({customUnitName, rateName}: AddOrDeletePolicyCustomUnitRateParams) => `a supprimé le taux « ${customUnitName} » « ${rateName} »`,
+        addedReportField: ({fieldType, fieldName}: AddedOrDeletedPolicyReportFieldParams) => `a ajouté le champ de note de frais ${fieldType} « ${fieldName} »`,
+        updateReportFieldDefaultValue: ({defaultValue, fieldName}: UpdatedPolicyReportFieldDefaultValueParams) =>
+            `définir la valeur par défaut du champ de note de frais « ${fieldName} » sur « ${defaultValue} »`,
         addedReportFieldOption: (fieldName: string, optionName: string) => `a ajouté l’option « ${optionName} » au champ de note de frais « ${fieldName} »`,
         removedReportFieldOption: (fieldName: string, optionName: string) => `a supprimé l’option « ${optionName} » du champ de note de frais « ${fieldName} »`,
         updateReportFieldOptionDisabled: (fieldName: string, optionName: string, optionEnabled: boolean) =>
@@ -7738,20 +6713,23 @@ Ajoutez davantage de règles de dépenses pour protéger la trésorerie de l’e
             return `${allEnabled ? 'Activé' : 'Désactivé'} l’option « ${optionName} » pour le champ de note de frais « ${fieldName} », rendant toutes les options ${allEnabled ? 'Activé' : 'Désactivé'}`;
         },
         deleteReportField: ({fieldType, fieldName}: {fieldType: string; fieldName?: string}) => `a supprimé le champ de note de frais ${fieldType} « ${fieldName} »`,
-        preventSelfApproval: (oldValue: string, newValue: string) =>
+        preventSelfApproval: ({oldValue, newValue}: UpdatedPolicyPreventSelfApprovalParams) =>
             `mis à jour « Empêcher l’auto-approbation » vers « ${newValue === 'true' ? 'Activé' : 'Désactivé'} » (auparavant « ${oldValue === 'true' ? 'Activé' : 'Désactivé'} »)`,
-        updateMonthlyOffset: (oldValue: string, newValue: string) => {
+        updateMonthlyOffset: ({oldValue, newValue}: UpdatedPolicyFieldWithNewAndOldValueParams) => {
             if (!oldValue) {
                 return `définir la date mensuelle de soumission des notes de frais sur « ${newValue} »`;
             }
             return `a mis à jour la date de soumission mensuelle de la note de frais sur « ${newValue} » (auparavant « ${oldValue} »)`;
         },
-        updateDefaultBillable: (oldValue: string, newValue: string) => `a mis à jour « Refacturer les dépenses aux clients » sur « ${newValue} » (auparavant « ${oldValue} »)`,
-        updateDefaultReimbursable: (oldValue: string, newValue: string) => `mis à jour « Dépense en espèces par défaut » en « ${newValue} » (précédemment « ${oldValue} »)`,
-        updateDefaultTitleEnforced: (value: boolean) => `a activé « Appliquer les titres de note de frais par défaut » ${value ? 'activé' : 'désactivé'}`,
-        changedCustomReportNameFormula: (oldValue: string, newValue: string) => `a modifié la formule du nom de note de frais personnalisée en « ${newValue} » (auparavant « ${oldValue} »)`,
+        updateDefaultBillable: ({oldValue, newValue}: UpdatedPolicyFieldWithNewAndOldValueParams) =>
+            `a mis à jour « Refacturer les dépenses aux clients » sur « ${newValue} » (auparavant « ${oldValue} »)`,
+        updateDefaultReimbursable: ({oldValue, newValue}: UpdatedPolicyFieldWithNewAndOldValueParams) =>
+            `mis à jour « Dépense en espèces par défaut » en « ${newValue} » (précédemment « ${oldValue} »)`,
+        updateDefaultTitleEnforced: ({value}: UpdatedPolicyFieldWithValueParams) => `a activé « Appliquer les titres de note de frais par défaut » ${value ? 'activé' : 'désactivé'}`,
+        changedCustomReportNameFormula: ({newValue, oldValue}: UpdatedPolicyFieldWithNewAndOldValueParams) =>
+            `a modifié la formule du nom de note de frais personnalisée en « ${newValue} » (auparavant « ${oldValue} »)`,
         renamedWorkspaceNameAction: (oldName: string, newName: string) => `a mis à jour le nom de cet espace de travail en « ${newName} » (auparavant « ${oldName} »)`,
-        updateWorkspaceDescription: (newDescription: string, oldDescription: string) =>
+        updateWorkspaceDescription: ({newDescription, oldDescription}: UpdatedPolicyDescriptionParams) =>
             !oldDescription
                 ? `définir la description de cet espace de travail sur « ${newDescription} »`
                 : `a mis à jour la description de cet espace de travail en « ${newDescription} » (auparavant « ${oldDescription} »)`,
@@ -7771,46 +6749,45 @@ Ajoutez davantage de règles de dépenses pour protéger la trésorerie de l’e
         },
         demotedFromWorkspace: (policyName: string, oldRole: string) =>
             `a mis à jour votre rôle dans ${policyName}, passant de ${oldRole} à utilisateur. Vous avez été retiré de toutes les discussions de dépenses des déclarants, sauf de la vôtre.`,
-        updatedWorkspaceCurrencyAction: (oldCurrency: string, newCurrency: string) => `a mis à jour la devise par défaut en ${newCurrency} (auparavant ${oldCurrency})`,
-        updatedWorkspaceFrequencyAction: (oldFrequency: string, newFrequency: string) =>
+        updatedWorkspaceCurrencyAction: ({oldCurrency, newCurrency}: UpdatedPolicyCurrencyParams) => `a mis à jour la devise par défaut en ${newCurrency} (auparavant ${oldCurrency})`,
+        updatedWorkspaceFrequencyAction: ({oldFrequency, newFrequency}: UpdatedPolicyFrequencyParams) =>
             `a mis à jour la fréquence de création automatique de notes de frais sur « ${newFrequency} » (auparavant « ${oldFrequency} »)`,
         updateApprovalMode: ({newValue, oldValue}: ChangeFieldParams) => `a mis à jour le mode d’approbation sur « ${newValue} » (auparavant « ${oldValue} »)`,
         upgradedWorkspace: 'a fait passer cet espace de travail au forfait Control',
         forcedCorporateUpgrade: `Cet espace de travail a été mis à niveau vers l’offre Control. Cliquez <a href="${CONST.COLLECT_UPGRADE_HELP_URL}">ici</a> pour plus d’informations.`,
         downgradedWorkspace: 'a rétrogradé cet espace de travail vers l’offre Collect',
-        updatedAuditRate: (oldAuditRate: number, newAuditRate: number) =>
+        updatedAuditRate: ({oldAuditRate, newAuditRate}: UpdatedPolicyAuditRateParams) =>
             `a modifié le taux de notes de frais envoyées aléatoirement pour approbation manuelle à ${Math.round(newAuditRate * 100)} % (auparavant ${Math.round(oldAuditRate * 100)} %)`,
-        updatedManualApprovalThreshold: (oldLimit: string, newLimit: string) => `a modifié le seuil d’approbation manuelle pour toutes les dépenses à ${newLimit} (auparavant ${oldLimit})`,
+        updatedManualApprovalThreshold: ({oldLimit, newLimit}: UpdatedPolicyManualApprovalThresholdParams) =>
+            `a modifié le seuil d’approbation manuelle pour toutes les dépenses à ${newLimit} (auparavant ${oldLimit})`,
         updatedFeatureEnabled: ({enabled, featureName}: {enabled: boolean; featureName: string}) => {
             switch (featureName) {
                 case 'categories':
-                    return `${enabled ? 'activé' : 'Désactivé'} catégories`;
+                    return `${enabled ? 'Activé' : 'Désactivé'} catégories`;
                 case 'tags':
-                    return `${enabled ? 'activé' : 'Désactivé'} tags`;
+                    return `${enabled ? 'Activé' : 'Désactivé'} tags`;
                 case 'workflows':
-                    return `Flux de travail ${enabled ? 'activé' : 'Désactivé'}`;
+                    return `flux de travail ${enabled ? 'Activé' : 'Désactivé'}`;
                 case 'distance rates':
-                    return `Tarifs de distance ${enabled ? 'activé' : 'Désactivé'}`;
+                    return `Taux de distance ${enabled ? 'Activé' : 'Désactivé'}`;
                 case 'accounting':
-                    return `Comptabilité ${enabled ? 'activé' : 'Désactivé'}`;
+                    return `${enabled ? 'Activé' : 'Désactivé'} comptabilité`;
                 case 'Expensify Cards':
-                    return `${enabled ? 'activé' : 'Désactivé'} Cartes Expensify`;
-                case 'travel invoicing':
-                    return `Facturation de voyages ${enabled ? 'activé' : 'Désactivé'}`;
+                    return `${enabled ? 'Activé' : 'Désactivé'} Cartes Expensify`;
                 case 'company cards':
-                    return `${enabled ? 'activé' : 'Désactivé'} cartes de société`;
+                    return `${enabled ? 'Activé' : 'Désactivé'} cartes d’entreprise`;
                 case 'invoicing':
-                    return `Facturation ${enabled ? 'activé' : 'Désactivé'}`;
+                    return `Facturation ${enabled ? 'Activé' : 'Désactivé'}`;
                 case 'per diem':
-                    return `${enabled ? 'activé' : 'Désactivé'} par jour`;
+                    return `${enabled ? 'Activé' : 'Désactivé'} par jour`;
                 case 'receipt partners':
-                    return `Partenaires de reçus ${enabled ? 'activé' : 'Désactivé'}`;
+                    return `Partenaires de reçus ${enabled ? 'Activé' : 'Désactivé'}`;
                 case 'rules':
-                    return `${enabled ? 'activé' : 'Désactivé'} règles`;
+                    return `Règles ${enabled ? 'Activé' : 'Désactivé'}`;
                 case 'tax tracking':
-                    return `Suivi fiscal ${enabled ? 'activé' : 'Désactivé'}`;
+                    return `Suivi de la taxe ${enabled ? 'Activé' : 'Désactivé'}`;
                 default:
-                    return `${enabled ? 'activé' : 'Désactivé'} ${featureName}`;
+                    return `${enabled ? 'Activé' : 'Désactivé'} ${featureName}`;
             }
         },
         updatedAttendeeTracking: ({enabled}: {enabled: boolean}) => `Suivi des participants ${enabled ? 'Activé' : 'Désactivé'}`,
@@ -7879,16 +6856,12 @@ Ajoutez davantage de règles de dépenses pour protéger la trésorerie de l’e
             oldValue
                 ? `a modifié le site web de l'entreprise de facturation en « ${newValue} » (précédemment « ${oldValue} »)`
                 : `définir le site web de l’entreprise de la facture sur « ${newValue} »`,
-        changedReimburser: (newReimburser: string, previousReimburser?: string) =>
+        changedReimburser: ({newReimburser, previousReimburser}: UpdatedPolicyReimburserParams) =>
             previousReimburser ? `a modifié le payeur autorisé en « ${newReimburser} » (auparavant « ${previousReimburser} »)` : `a modifié le payeur autorisé en « ${newReimburser} »`,
-        updateReimbursementEnabled: (enabled: boolean) => `Remboursements ${enabled ? 'Activé' : 'Désactivé'}`,
-        updateCustomTaxName: (oldName: string, newName: string) => `a modifié le nom de taxe personnalisé en « ${newName} » (auparavant « ${oldName} »)`,
-        updateCurrencyDefaultTax: (oldName: string, newName: string) =>
-            `a modifié le taux de taxe par défaut de la devise de l'espace de travail en « ${newName} » (auparavant « ${oldName} »)`,
-        updateForeignCurrencyDefaultTax: (oldName: string, newName: string) => `a modifié le taux de taxe par défaut en devise étrangère en « ${newName} » (auparavant « ${oldName} »)`,
-        addTax: (taxName: string) => `a ajouté la taxe « ${taxName} »`,
-        deleteTax: (taxName: string) => `a supprimé la taxe « ${taxName} »`,
-        updateTax: (oldValue?: string | boolean | number, taxName?: string, updatedField?: string, newValue?: string | boolean | number) => {
+        updateReimbursementEnabled: ({enabled}: UpdatedPolicyReimbursementEnabledParams) => `Remboursements ${enabled ? 'Activé' : 'Désactivé'}`,
+        addTax: ({taxName}: UpdatedPolicyTaxParams) => `a ajouté la taxe « ${taxName} »`,
+        deleteTax: ({taxName}: UpdatedPolicyTaxParams) => `a supprimé la taxe « ${taxName} »`,
+        updateTax: ({oldValue, taxName, updatedField, newValue}: UpdatedPolicyTaxParams) => {
             if (!updatedField) {
                 return '';
             }
@@ -7910,31 +6883,30 @@ Ajoutez davantage de règles de dépenses pour protéger la trésorerie de l’e
                 }
             }
         },
-        setReceiptRequiredAmount: (newValue: string) => `définir le montant de reçu obligatoire sur « ${newValue} »`,
-        changedReceiptRequiredAmount: (oldValue: string, newValue: string) => `a modifié le montant requis pour le reçu à « ${newValue} » (auparavant « ${oldValue} »)`,
-        removedReceiptRequiredAmount: (oldValue: string) => `a supprimé le montant requis pour le reçu (précédemment « ${oldValue} »)`,
-        setItemizedReceiptRequiredAmount: (newValue: string) => `définir le montant requis pour le reçu détaillé sur « ${newValue} »`,
-        changedItemizedReceiptRequiredAmount: (oldValue: string, newValue: string) => `a modifié le montant requis pour le reçu détaillé à « ${newValue} » (auparavant « ${oldValue} »)`,
-        removedItemizedReceiptRequiredAmount: (oldValue: string) => `a supprimé le montant requis pour le reçu détaillé (précédemment « ${oldValue} »)`,
-        setMaxExpenseAmount: (newValue: string) => `définir le montant maximal de dépense sur « ${newValue} »`,
-        changedMaxExpenseAmount: (oldValue: string, newValue: string) => `montant maximal de dépense modifié en « ${newValue} » (précédemment « ${oldValue} »)`,
-        removedMaxExpenseAmount: (oldValue: string) => `montant de dépense maximal supprimé (précédemment « ${oldValue} »)`,
-        setMaxExpenseAge: (newValue: string) => `définir l’ancienneté maximale des dépenses à « ${newValue} » jours`,
-        changedMaxExpenseAge: (oldValue: string, newValue: string) => `âge maximal de dépense modifié à « ${newValue} » jours (auparavant « ${oldValue} »)`,
-        removedMaxExpenseAge: (oldValue: string) => `âge maximal de dépense supprimé (auparavant « ${oldValue} » jours)`,
-        updateCategories: (count: number) => `${count} catégories mises à jour`,
-        updateTagList: (tagListName: string) => `a mis à jour les tags dans la liste « ${tagListName} »`,
-        updateTagListRequired: (tagListsName: string, isRequired: boolean) => `a modifié la liste de tags « ${tagListsName} » en ${isRequired ? 'obligatoire' : 'non obligatoire'}`,
+        setReceiptRequiredAmount: ({newValue}: UpdatedPolicyFieldWithNewAndOldValueParams) => `définir le montant de reçu obligatoire sur « ${newValue} »`,
+        changedReceiptRequiredAmount: ({oldValue, newValue}: UpdatedPolicyFieldWithNewAndOldValueParams) =>
+            `a modifié le montant requis pour le reçu à « ${newValue} » (auparavant « ${oldValue} »)`,
+        removedReceiptRequiredAmount: ({oldValue}: UpdatedPolicyFieldWithNewAndOldValueParams) => `a supprimé le montant requis pour le reçu (précédemment « ${oldValue} »)`,
+        setMaxExpenseAmount: ({newValue}: UpdatedPolicyFieldWithNewAndOldValueParams) => `définir le montant maximal de dépense sur « ${newValue} »`,
+        changedMaxExpenseAmount: ({oldValue, newValue}: UpdatedPolicyFieldWithNewAndOldValueParams) => `montant maximal de dépense modifié en « ${newValue} » (précédemment « ${oldValue} »)`,
+        removedMaxExpenseAmount: ({oldValue}: UpdatedPolicyFieldWithNewAndOldValueParams) => `montant de dépense maximal supprimé (précédemment « ${oldValue} »)`,
+        setMaxExpenseAge: ({newValue}: UpdatedPolicyFieldWithNewAndOldValueParams) => `définir l’ancienneté maximale des dépenses à « ${newValue} » jours`,
+        changedMaxExpenseAge: ({oldValue, newValue}: UpdatedPolicyFieldWithNewAndOldValueParams) => `âge maximal de dépense modifié à « ${newValue} » jours (auparavant « ${oldValue} »)`,
+        removedMaxExpenseAge: ({oldValue}: UpdatedPolicyFieldWithNewAndOldValueParams) => `âge maximal de dépense supprimé (auparavant « ${oldValue} » jours)`,
+        updateCategories: ({count}: UpdatedPolicyCategoriesParams) => `${count} catégories mises à jour`,
+        updateTagList: ({tagListName}: UpdatedPolicyTagListParams) => `a mis à jour les tags dans la liste « ${tagListName} »`,
+        updateTagListRequired: ({tagListsName, isRequired}: UpdatedPolicyTagListRequiredParams) =>
+            `a modifié la liste de tags « ${tagListsName} » en ${isRequired ? 'obligatoire' : 'non obligatoire'}`,
         importTags: 'tags importés depuis une feuille de calcul',
         deletedAllTags: 'a supprimé tous les tags',
-        updateCustomUnitDefaultCategory: (customUnitName: string, newValue?: string, oldValue?: string) =>
+        updateCustomUnitDefaultCategory: ({customUnitName, newValue, oldValue}: UpdatePolicyCustomUnitDefaultCategoryParams) =>
             `a modifié la catégorie par défaut pour ${customUnitName} en « ${newValue} » ${oldValue ? `(auparavant « ${oldValue} »)` : ''}`,
-        importCustomUnitRates: (customUnitName: string) => `taux importés pour l’unité personnalisée « ${customUnitName} »`,
-        updateCustomUnitSubRate: (customUnitName: string, customUnitRateName: string, customUnitSubRateName: string, oldValue: string, newValue: string, updatedField: string) =>
+        importCustomUnitRates: ({customUnitName}: ImportPolicyCustomUnitRatesParams) => `taux importés pour l’unité personnalisée « ${customUnitName} »`,
+        updateCustomUnitSubRate: ({customUnitName, customUnitRateName, customUnitSubRateName, oldValue, newValue, updatedField}: UpdatedPolicyCustomUnitSubRateParams) =>
             `a modifié le taux « ${customUnitName} », le sous-taux « ${customUnitRateName} », le sous-taux « ${customUnitSubRateName} » ${updatedField} en « ${newValue} » (auparavant « ${oldValue} »)`,
-        removedCustomUnitSubRate: (customUnitName: string, customUnitRateName: string, removedSubRateName: string) =>
+        removedCustomUnitSubRate: ({customUnitName, customUnitRateName, removedSubRateName}: RemovedPolicyCustomUnitSubRateParams) =>
             `a supprimé le taux « ${customUnitName} », le sous-taux « ${customUnitRateName} », le sous-taux « ${removedSubRateName} »`,
-        addBudget: (frequency: string, entityName: string, entityType: string, shared?: string, individual?: string, notificationThreshold?: number) => {
+        addBudget: ({frequency, entityName, entityType, shared, individual, notificationThreshold}: AddBudgetParams) => {
             const thresholdSuffix = typeof notificationThreshold === 'number' ? `avec un seuil de notification de « ${notificationThreshold}% »` : '';
             if (typeof shared !== 'undefined' && typeof individual !== 'undefined') {
                 return `a ajouté ${frequency} budget individuel de « ${individual} » et ${frequency} budget partagé de « ${shared} »${thresholdSuffix} au ${entityType} « ${entityName} »`;
@@ -7944,18 +6916,18 @@ Ajoutez davantage de règles de dépenses pour protéger la trésorerie de l’e
             }
             return `a ajouté un budget partagé ${frequency} de « ${shared} »${thresholdSuffix} à l’${entityType} « ${entityName} »`;
         },
-        updateBudget: (
-            entityType: string,
-            entityName: string,
-            oldFrequency?: string,
-            newFrequency?: string,
-            oldIndividual?: string,
-            newIndividual?: string,
-            oldShared?: string,
-            newShared?: string,
-            oldNotificationThreshold?: number,
-            newNotificationThreshold?: number,
-        ) => {
+        updateBudget: ({
+            entityType,
+            entityName,
+            oldFrequency,
+            newFrequency,
+            oldIndividual,
+            newIndividual,
+            oldShared,
+            newShared,
+            oldNotificationThreshold,
+            newNotificationThreshold,
+        }: UpdatedBudgetParams) => {
             const frequencyChanged = !!(newFrequency && oldFrequency !== newFrequency);
             const sharedChanged = !!(newShared && oldShared !== newShared);
             const individualChanged = !!(newIndividual && oldIndividual !== newIndividual);
@@ -7990,7 +6962,7 @@ Ajoutez davantage de règles de dépenses pour protéger la trésorerie de l’e
             }
             return `budget mis à jour pour le/la ${entityType} « ${entityName} » : ${changesList.join('; ')}`;
         },
-        deleteBudget: (entityType: string, entityName: string, frequency?: string, individual?: string, shared?: string, notificationThreshold?: number) => {
+        deleteBudget: ({entityType, entityName, frequency, individual, shared, notificationThreshold}: DeleteBudgetParams) => {
             const thresholdSuffix = typeof notificationThreshold === 'number' ? `avec un seuil de notification de « ${notificationThreshold}% »` : '';
             if (shared && individual) {
                 return `a supprimé un budget partagé de ${frequency} « ${shared} » et un budget individuel de « ${individual} »${thresholdSuffix} du ${entityType} « ${entityName} »`;
@@ -8003,126 +6975,49 @@ Ajoutez davantage de règles de dépenses pour protéger la trésorerie de l’e
             }
             return `a supprimé le budget de ${entityType} « ${entityName} »`;
         },
-        updatedTimeEnabled: (enabled?: boolean) => {
+        updatedTimeEnabled: ({enabled}: UpdatedPolicyTimeEnabledParams) => {
             return `Suivi du temps ${enabled ? 'activé' : 'désactivé'}`;
         },
-        updatedTimeRate: (newRate?: string, oldRate?: string) => {
+        updatedTimeRate: ({newRate, oldRate}: UpdatedPolicyTimeRateParams) => {
             return `a modifié le taux horaire à « ${newRate} » (auparavant « ${oldRate} »)`;
         },
         addedProhibitedExpense: ({prohibitedExpense}: {prohibitedExpense: string}) => `a ajouté « ${prohibitedExpense} » aux dépenses interdites`,
         removedProhibitedExpense: ({prohibitedExpense}: {prohibitedExpense: string}) => `a supprimé « ${prohibitedExpense} » des dépenses interdites`,
-        updatedReimbursementChoice: (newReimbursementChoice: string, oldReimbursementChoice: string) =>
+        updatedReimbursementChoice: ({newReimbursementChoice, oldReimbursementChoice}: UpdatedPolicyReimbursementChoiceParams) =>
             `a modifié le mode de remboursement en « ${newReimbursementChoice} » (auparavant « ${oldReimbursementChoice} »)`,
         setAutoJoin: ({enabled}: {enabled: boolean}) => `${enabled ? 'activé' : 'désactivé'} pré-approbation des demandes de rejoindre l’espace de travail`,
-        updatedDefaultTitle: (newDefaultTitle: string, oldDefaultTitle: string) =>
+        updatedDefaultTitle: ({newDefaultTitle, oldDefaultTitle}: UpdatedPolicyDefaultTitleParams) =>
             `a modifié la formule du nom de note de frais personnalisée en « ${newDefaultTitle} » (précédemment « ${oldDefaultTitle} »)`,
-        updatedOwnership: (oldOwnerEmail: string, oldOwnerName: string, policyName: string) => `a pris la responsabilité de ${policyName} à la place de ${oldOwnerName} (${oldOwnerEmail})`,
-        updatedAutoHarvesting: (enabled: boolean) => `Soumission planifiée pour ${enabled ? 'activé' : 'désactivé'}`,
-        updatedIndividualBudgetNotification: (
-            budgetAmount: string,
-            budgetFrequency: string,
-            budgetName: string,
-            budgetTypeForNotificationMessage: string,
-            thresholdPercentage: number,
-            totalSpend: number,
-            unsubmittedSpend: number,
-            awaitingApprovalSpend: number,
-            approvedReimbursedClosedSpend: number,
-            summaryLink?: string,
-            userEmail?: string,
-        ) =>
+        updatedOwnership: ({oldOwnerEmail, oldOwnerName, policyName}: UpdatedPolicyOwnershipParams) =>
+            `a pris la responsabilité de ${policyName} à la place de ${oldOwnerName} (${oldOwnerEmail})`,
+        updatedAutoHarvesting: ({enabled}: UpdatedPolicyAutoHarvestingParams) => `Soumission planifiée pour ${enabled ? 'activé' : 'désactivé'}`,
+        updatedIndividualBudgetNotification: ({
+            budgetAmount,
+            budgetFrequency,
+            budgetName,
+            budgetTypeForNotificationMessage,
+            summaryLink,
+            thresholdPercentage,
+            totalSpend,
+            unsubmittedSpend,
+            userEmail,
+            awaitingApprovalSpend,
+            approvedReimbursedClosedSpend,
+        }: UpdatedPolicyBudgetNotificationParams) =>
             `Attention ! Cet espace de travail a un budget ${budgetFrequency} de « ${budgetAmount} » pour le/la ${budgetTypeForNotificationMessage} « ${budgetName} ». ${userEmail} est actuellement à ${approvedReimbursedClosedSpend}, ce qui dépasse ${thresholdPercentage}% du budget. Il y a aussi ${awaitingApprovalSpend} en attente d’approbation, et ${unsubmittedSpend} qui n’a pas encore été soumise, pour un total de ${totalSpend}.${summaryLink ? `<a href="${summaryLink}">Voici une note de frais</a> avec toutes ces dépenses pour vos dossiers !` : ''}`,
-        updatedSharedBudgetNotification: (
-            budgetAmount: string,
-            budgetFrequency: string,
-            budgetName: string,
-            budgetTypeForNotificationMessage: string,
-            summaryLink: string | undefined,
-            thresholdPercentage: number,
-            totalSpend: number,
-            unsubmittedSpend: number,
-            awaitingApprovalSpend: number,
-            approvedReimbursedClosedSpend: number,
-        ) =>
+        updatedSharedBudgetNotification: ({
+            budgetAmount,
+            budgetFrequency,
+            budgetName,
+            budgetTypeForNotificationMessage,
+            summaryLink,
+            thresholdPercentage,
+            totalSpend,
+            unsubmittedSpend,
+            awaitingApprovalSpend,
+            approvedReimbursedClosedSpend,
+        }: UpdatedPolicyBudgetNotificationParams) =>
             `Attention ! Cet espace de travail a un budget ${budgetFrequency} de « ${budgetAmount} » pour le/la ${budgetTypeForNotificationMessage} « ${budgetName} ». Vous en êtes actuellement à ${approvedReimbursedClosedSpend}, ce qui dépasse ${thresholdPercentage}% du budget. Il y a aussi ${awaitingApprovalSpend} en attente d’approbation et ${unsubmittedSpend} qui n’a pas encore été soumis, pour un total de ${totalSpend}. ${summaryLink ? `<a href="${summaryLink}">Voici une note de frais</a> avec toutes ces dépenses pour vos dossiers !` : ''}`,
-        addedCardFeed: (feedName: string) => `a ajouté le flux de carte « ${feedName} »`,
-        removedCardFeed: (feedName: string) => `a supprimé le flux de carte « ${feedName} »`,
-        renamedCardFeed: (newName: string, oldName: string) => `a renommé le flux de carte en « ${newName} » (auparavant « ${oldName} »)`,
-        assignedCompanyCard: (email: string, feedName: string, cardLastFour: string) =>
-            `a assigné ${email} ${feedName ? `« ${feedName} » ` : ''}carte de société se terminant par ${cardLastFour}`,
-        unassignedCompanyCard: (email: string, feedName: string, cardLastFour: string) =>
-            `carte d’entreprise ${feedName ? `« ${feedName} » ` : ''}se terminant par ${cardLastFour} désassignée de ${email}`,
-        updatedCardFeedLiability: (feedName: string, enabled: boolean) =>
-            `Autoriser les porteurs de carte ${enabled ? 'activé' : 'Désactivé'} à supprimer les transactions de carte pour le flux de cartes « ${feedName} »`,
-        updatedCardFeedStatementPeriod: (feedName: string, newValue?: string, previousValue?: string) =>
-            `a modifié le jour de fin de période de relevé du flux de carte « ${feedName} »${newValue ? ` à « ${newValue} »` : ''}${previousValue ? ` (précédemment « ${previousValue} »)` : ''}`,
-        addedReportField: (fieldType: string, fieldName?: string, defaultValue?: string) =>
-            `a ajouté le champ de note de frais ${fieldType} « ${fieldName} »${defaultValue ? ` avec la valeur par défaut « ${defaultValue} »` : ''}`,
-        updatedMccGroupCategory: ({mccGroupName, oldCategory, newCategory}: {mccGroupName: string; oldCategory: string; newCategory: string}) =>
-            `a modifié la catégorie de dépense par défaut pour « ${mccGroupName} » en « ${newCategory} » (auparavant « ${oldCategory} »)`,
-        updatedRequireCompanyCards: ({enabled}: {enabled: boolean}) => `${enabled ? 'activé' : 'désactivé'} l’exigence d’achats par carte d’entreprise`,
-        expensifyCardRule: {
-            actionVerb: {block: 'bloqué', allow: 'autorisé'},
-            amountOperator: {over: 'terminé', under: 'sous'},
-            amountFilter: ({operator, amount}: {operator: string; amount: string}) => `montants ${operator} ${amount}`,
-            theCard: 'la carte',
-            multipleCards: ({count}: {count: number}) => ({
-                one: '1 carte',
-                other: `${count} cartes`,
-            }),
-            addRule: ({verb, filters, cards}: {verb: string; filters: string; cards: string}) => {
-                let text = verb;
-                if (filters !== '') {
-                    text += ` ${filters}`;
-                }
-                text += ` sur ${cards}`;
-                return text;
-            },
-            removeRule: ({cards}: {cards: string}) => `a supprimé la règle de dépense de ${cards}`,
-            restrictionVerb: {block: 'bloquer', allow: 'autoriser uniquement'},
-            update: {
-                modeChange: ({fromAction, toAction, cards}: {fromAction: string; toAction: string; cards: string}) =>
-                    `a modifié la règle de dépense de ${fromAction} à ${toAction} sur ${cards}`,
-                appliedToAdditionalCards: ({count}: {count: number}) => ({
-                    one: 'règle de dépense appliquée à 1 carte supplémentaire',
-                    other: `règle de dépense appliquée à ${count} cartes supplémentaires`,
-                }),
-                phraseVerb: {added: 'ajouté', removed: 'supprimé', changed: 'modifié', set: 'définir', applied: 'appliqué'},
-                bodyMerchant: ({adjective, value}: {adjective: string; value: string}) => (adjective !== '' ? `${adjective} commerçant « ${value} »` : `commerçant « ${value} »`),
-                bodyMerchantChange: ({adjective, oldValue, newValue}: {adjective: string; oldValue: string; newValue: string}) =>
-                    adjective !== '' ? `${adjective} marchand de « ${oldValue} » à « ${newValue} »` : `commerçant de « ${oldValue} » à « ${newValue} »`,
-                bodySpendCategory: ({adjective, value}: {adjective: string; value: string}) =>
-                    adjective !== '' ? `Catégorie de dépense ${adjective} « ${value} »` : `catégorie de dépense « ${value} »`,
-                bodySpendCategoryChange: ({adjective, oldValue, newValue}: {adjective: string; oldValue: string; newValue: string}) =>
-                    adjective !== '' ? `Catégorie de dépense ${adjective} de « ${oldValue} » à « ${newValue} »` : `catégorie de dépense de « ${oldValue} » à « ${newValue} »`,
-                bodyMaxAmount: 'montant maximal',
-                bodyMaxAmountSet: ({value}: {value: string}) => `montant maximum à ${value}`,
-                bodyMaxAmountChange: ({oldValue, newValue}: {oldValue: string; newValue: string}) => `montant maximal de ${oldValue} à ${newValue}`,
-                bodyAppliedToAdditionalCards: ({count}: {count: number}) => ({
-                    one: 'règle de dépense pour 1 carte supplémentaire',
-                    other: `règle de dépense pour ${count} cartes supplémentaires`,
-                }),
-                bodyRemovedFromCards: ({cards}: {cards: string}) => `règle de dépense provenant de ${cards}`,
-                composeOnCards: ({content, cards}: {content: string; cards: string}) => `${content} sur ${cards}`,
-                composeFromCards: ({content, cards}: {content: string; cards: string}) => `${content} de ${cards}`,
-            },
-        },
-        addCustomUnitRateWithAmount: (rateName: string, rateValue: string) => `a ajouté le taux « ${rateName} » de ${rateValue}`,
-        addCustomUnitRateWithAmountAndStartDate: (rateName: string, rateValue: string, startDate: string) =>
-            `a ajouté le taux « ${rateName} » de ${rateValue}, valable à partir du ${startDate}`,
-        addCustomUnitRateWithAmountAndEndDate: (rateName: string, rateValue: string, endDate: string) => `a ajouté le taux « ${rateName} » de ${rateValue}, valable jusqu’au ${endDate}`,
-        addCustomUnitRateWithAmountAndDates: (rateName: string, rateValue: string, startDate: string, endDate: string) =>
-            `a ajouté le taux « ${rateName} » de ${rateValue}, valable du ${startDate} au ${endDate}`,
-        updatedCustomUnitRateStartDate: (rateName: string, newDate: string, oldDate?: string) =>
-            oldDate ? `a mis à jour la date de début du taux « ${rateName} » à ${newDate} (auparavant ${oldDate})` : `définir la date de début du taux « ${rateName} » sur ${newDate}`,
-        updatedCustomUnitRateEndDate: (rateName: string, newDate: string, oldDate?: string) =>
-            oldDate ? `a mis à jour la date de fin du taux « ${rateName} » à ${newDate} (auparavant ${oldDate})` : `définir la date de fin du taux « ${rateName} » sur ${newDate}`,
-        updatedCustomUnitRateStartAndEndDate: (rateName: string, newStartDate: string, newEndDate: string, oldStartDate?: string, oldEndDate?: string) =>
-            oldStartDate && oldEndDate
-                ? `a mis à jour les dates de début et de fin du taux « ${rateName} » en ${newStartDate} - ${newEndDate} (précédemment ${oldStartDate} - ${oldEndDate})`
-                : `définir les dates de début et de fin du taux « ${rateName} » sur ${newStartDate} - ${newEndDate}`,
-        removedCustomUnitRateStartDate: (rateName: string, oldDate: string) => `a supprimé la date de début du taux « ${rateName} » (précédemment ${oldDate})`,
-        removedCustomUnitRateEndDate: (rateName: string, oldDate: string) => `a supprimé la date de fin du taux « ${rateName} » (auparavant ${oldDate})`,
     },
     roomMembersPage: {
         memberNotFound: 'Membre introuvable.',
@@ -8154,7 +7049,7 @@ Ajoutez davantage de règles de dépenses pour protéger la trésorerie de l’e
         completed: 'Terminé',
         action: 'Terminé',
         messages: {
-            created: (title: string) => `tâche pour ${title}`,
+            created: ({title}: TaskCreatedActionParams) => `tâche pour ${title}`,
             completed: 'marqué comme terminé',
             canceled: 'tâche supprimée',
             reopened: 'marqué comme incomplet',
@@ -8168,7 +7063,7 @@ Ajoutez davantage de règles de dépenses pour protéger la trésorerie de l’e
         deleteConfirmation: 'Voulez-vous vraiment supprimer cette tâche ?',
     },
     statementPage: {
-        title: (year: number | string, monthName: string) => `Relevé de ${monthName} ${year}`,
+        title: ({year, monthName}: StatementTitleParams) => `Relevé de ${monthName} ${year}`,
     },
     keyboardShortcutsPage: {
         title: 'Raccourcis clavier',
@@ -8181,8 +7076,6 @@ Ajoutez davantage de règles de dépenses pour protéger la trésorerie de l’e
             newChat: 'Nouvel écran de discussion',
             copy: 'Copier le commentaire',
             openDebug: 'Ouvrir la boîte de dialogue des préférences de test',
-            expenseReportSearch: 'Rechercher des notes de frais',
-            goToWorkspace: "Aller à l'espace de travail de la note de frais actuelle",
         },
     },
     guides: {
@@ -8192,8 +7085,6 @@ Ajoutez davantage de règles de dépenses pour protéger la trésorerie de l’e
     search: {
         resultsAreLimited: 'Les résultats de recherche sont limités.',
         viewResults: 'Afficher les résultats',
-        applyFilters: 'Appliquer des filtres',
-        appliedFilters: 'Filtres appliqués',
         resetFilters: 'Réinitialiser les filtres',
         searchResults: {
             emptyResults: {
@@ -8201,23 +7092,27 @@ Ajoutez davantage de règles de dépenses pour protéger la trésorerie de l’e
                 subtitle: `Essayez de modifier vos critères de recherche ou de créer quelque chose avec le bouton +.`,
             },
             emptyExpenseResults: {
-                title: 'Aucune dépense pour le moment',
+                title: 'Vous n’avez encore créé aucune dépense',
                 subtitle: 'Créez une dépense ou faites un essai d’Expensify pour en savoir plus.',
                 subtitleWithOnlyCreateButton: 'Utilisez le bouton vert ci-dessous pour créer une dépense.',
             },
             emptyReportResults: {
-                title: 'Aucune note de frais pour le moment',
+                title: 'Vous n’avez encore créé aucune note de frais',
                 subtitle: 'Créez une note de frais ou faites un essai d’Expensify pour en savoir plus.',
                 subtitleWithOnlyCreateButton: 'Utilisez le bouton vert ci-dessous pour créer une note de frais.',
             },
             emptyInvoiceResults: {
-                title: 'Aucune facture pour le moment',
+                title: dedent(`
+                    Vous n'avez pas encore créé de factures
+                `),
                 subtitle: 'Envoyez une facture ou faites un essai d’Expensify pour en savoir plus.',
                 subtitleWithOnlyCreateButton: 'Utilisez le bouton vert ci-dessous pour envoyer une facture.',
-                subtitleCannotSend: "Vous avez besoin d'un espace de travail avec Invoices activé pour envoyer des factures.",
-                subtitleCannotSendWithTestDrive: "Vous avez besoin d'un espace de travail avec Invoices activé pour envoyer des factures. Faites un essai d'Expensify pour en savoir plus.",
             },
-            emptyTripResults: {title: 'Aucun voyage pour le moment', subtitle: 'Commencez en réservant votre premier voyage ci-dessous.', buttonText: 'Réserver un voyage'},
+            emptyTripResults: {
+                title: 'Aucun voyage à afficher',
+                subtitle: 'Commencez en réservant votre premier voyage ci-dessous.',
+                buttonText: 'Réserver un voyage',
+            },
             emptySubmitResults: {
                 title: 'Aucune dépense à soumettre',
                 subtitle: 'Tout est bon. Faites un tour d’honneur !',
@@ -8245,31 +7140,30 @@ Ajoutez davantage de règles de dépenses pour protéger la trésorerie de l’e
             },
         },
         columns: 'Colonnes',
-        editColumns: 'Modifier les colonnes',
         resetColumns: 'Réinitialiser les colonnes',
         groupColumns: 'Regrouper les colonnes',
         expenseColumns: 'Colonnes de dépenses',
-        saveView: 'Enregistrer la vue',
+        statements: 'Relevés',
+        unapprovedCash: 'Espèces non approuvées',
+        unapprovedCard: 'Carte non approuvée',
+        reconciliation: 'Rapprochement',
+        topSpenders: 'Plus gros dépensiers',
+        saveSearch: 'Enregistrer la recherche',
         deleteSavedSearch: 'Supprimer la recherche enregistrée',
         deleteSavedSearchConfirm: 'Voulez-vous vraiment supprimer cette recherche ?',
         searchName: 'Rechercher un nom',
         savedSearchesMenuItemTitle: 'Enregistré',
-        urlCopied: 'URL copiée',
+        topCategories: 'Catégories principales',
+        topMerchants: 'Commerçants principaux',
         groupedExpenses: 'dépenses groupées',
         bulkActions: {
-            editMultiple: 'Modifier plusieurs',
-            editMultipleTitle: 'Modifier plusieurs dépenses',
-            editMultipleDescription: 'Les modifications seront définies pour toutes les dépenses sélectionnées et remplaceront toutes les valeurs définies précédemment.',
             approve: 'Approuver',
             pay: 'Payer',
             delete: 'Supprimer',
             hold: 'En attente',
             unhold: 'Supprimer la mise en attente',
             reject: 'Rejeter',
-            duplicateExpense: ({count}: {count: number}) => `Dupliquer ${count === 1 ? 'la dépense' : 'les dépenses'}`,
             noOptionsAvailable: 'Aucune option n’est disponible pour le groupe de dépenses sélectionné.',
-            undelete: 'Restaurer',
-            duplicateReport: ({count}: {count: number}) => `Dupliquer ${count === 1 ? 'note de frais' : 'notes de frais'}`,
         },
         filtersHeader: 'Filtres',
         filters: {
@@ -8277,14 +7171,11 @@ Ajoutez davantage de règles de dépenses pour protéger la trésorerie de l’e
                 before: (date?: string) => `Avant ${date ?? ''}`,
                 after: (date?: string) => `Après ${date ?? ''}`,
                 on: (date?: string) => `Le ${date ?? ''}`,
-                customDate: 'Date personnalisée',
-                customRange: 'Intervalle personnalisé',
                 presets: {
                     [CONST.SEARCH.DATE_PRESETS.NEVER]: 'Jamais',
                     [CONST.SEARCH.DATE_PRESETS.LAST_MONTH]: 'Mois dernier',
                     [CONST.SEARCH.DATE_PRESETS.THIS_MONTH]: 'Ce mois-ci',
                     [CONST.SEARCH.DATE_PRESETS.YEAR_TO_DATE]: 'Depuis le début de l’année',
-                    [CONST.SEARCH.DATE_PRESETS.LAST_12_MONTHS]: '12 derniers mois',
                     [CONST.SEARCH.DATE_PRESETS.LAST_STATEMENT]: 'Dernier relevé',
                 },
             },
@@ -8296,15 +7187,10 @@ Ajoutez davantage de règles de dépenses pour protéger la trésorerie de l’e
             currency: 'Devise',
             completed: 'Terminé',
             amount: {
-                lessThan: (amount?: string) => `Inférieur à ${amount ?? ''}`,
-                greaterThan: (amount?: string) => `Supérieur à ${amount ?? ''}`,
-                between: (greaterThan?: string, lessThan?: string) => {
-                    if (greaterThan && lessThan) {
-                        return `Entre ${greaterThan} et ${lessThan}`;
-                    }
-                    return 'Entre';
-                },
-                equalTo: (amount?: string) => `Égal à ${amount ?? ''}`,
+                lessThan: ({amount}: OptionalParam<RequestAmountParams> = {}) => `Inférieur à ${amount ?? ''}`,
+                greaterThan: ({amount}: OptionalParam<RequestAmountParams> = {}) => `Supérieur à ${amount ?? ''}`,
+                between: (greaterThan: string, lessThan: string) => `Entre ${greaterThan} et ${lessThan}`,
+                equalTo: ({amount}: OptionalParam<RequestAmountParams> = {}) => `Égal à ${amount ?? ''}`,
             },
             card: {
                 expensify: 'Expensify',
@@ -8314,9 +7200,8 @@ Ajoutez davantage de règles de dépenses pour protéger la trésorerie de l’e
                 cardFeedName: ({cardFeedBankName, cardFeedLabel}: {cardFeedBankName: string; cardFeedLabel?: string}) =>
                     `Tous les ${cardFeedBankName}${cardFeedLabel ? ` - ${cardFeedLabel}` : ''}`,
                 cardFeedNameCSV: ({cardFeedLabel}: {cardFeedLabel?: string}) => `Toutes les cartes CSV importées${cardFeedLabel ? ` - ${cardFeedLabel}` : ''}`,
-                travelInvoicing: 'Facturation de voyages',
             },
-            reportField: (name: string, value: string) => `${name} est ${value}`,
+            reportField: ({name, value}: OptionalParam<ReportFieldParams>) => `${name} est ${value}`,
             current: 'Actuel',
             past: 'Passé',
             submitted: 'Soumis',
@@ -8328,10 +7213,6 @@ Ajoutez davantage de règles de dépenses pour protéger la trésorerie de l’e
             billable: 'Facturable',
             reimbursable: 'Remboursable',
             purchaseCurrency: 'Devise d’achat',
-            sortOrder: {
-                [CONST.SEARCH.SORT_ORDER.ASC]: 'Croissant',
-                [CONST.SEARCH.SORT_ORDER.DESC]: 'Descendant',
-            },
             groupBy: {
                 [CONST.SEARCH.GROUP_BY.FROM]: 'De',
                 [CONST.SEARCH.GROUP_BY.CARD]: 'Carte',
@@ -8348,7 +7229,6 @@ Ajoutez davantage de règles de dépenses pour protéger la trésorerie de l’e
             withdrawalType: {
                 [CONST.SEARCH.WITHDRAWAL_TYPE.EXPENSIFY_CARD]: 'Carte Expensify',
                 [CONST.SEARCH.WITHDRAWAL_TYPE.REIMBURSEMENT]: 'Remboursement',
-                [CONST.SEARCH.WITHDRAWAL_TYPE.CENTRAL_TRAVEL_INVOICING]: 'Facturation de voyages',
             },
             is: 'Est',
             action: {
@@ -8358,20 +7238,13 @@ Ajoutez davantage de règles de dépenses pour protéger la trésorerie de l’e
                 [CONST.SEARCH.ACTION_FILTERS.EXPORT]: 'Exporter',
             },
         },
-        display: {
-            label: 'Affichage',
-            sortBy: 'Trier par',
-            sortOrder: 'Ordre de tri',
-            groupBy: 'Regrouper par',
-            limitResults: 'Limiter les résultats',
-        },
         has: 'A A',
+        groupBy: 'Regrouper par',
         view: {
             label: 'Afficher',
             table: 'Table',
             bar: 'Bar',
             line: 'Ligne',
-            pie: 'Tarte',
         },
         chartTitles: {
             [CONST.SEARCH.GROUP_BY.FROM]: 'De',
@@ -8396,22 +7269,9 @@ Ajoutez davantage de règles de dépenses pour protéger la trésorerie de l’e
         withdrawalType: 'Type de retrait',
         recentSearches: 'Recherches récentes',
         recentChats: 'Discussions récentes',
-        serverResults: 'Résultats de recherche',
         searchIn: 'Rechercher dans',
-        askConcierge: (message: string) => `Demander à Concierge « ${message} »`,
-        searchPlaceholder: 'Rechercher quelque chose...',
+        searchPlaceholder: 'Rechercher quelque chose',
         suggestions: 'Suggestions',
-        suggestionsAvailable: (
-            {
-                count,
-            }: {
-                count: number;
-            },
-            query = '',
-        ) => ({
-            one: `Suggestions disponibles${query ? ` pour ${query}` : ''}. ${count} résultat.`,
-            other: (resultCount: number) => `Suggestions disponibles${query ? ` pour ${query}` : ''}. ${resultCount} résultats.`,
-        }),
         exportSearchResults: {
             title: 'Créer l’export',
             description: 'Ouah, ça fait beaucoup d’éléments ! Nous allons les regrouper et Concierge vous enverra un fichier sous peu.',
@@ -8420,29 +7280,6 @@ Ajoutez davantage de règles de dépenses pour protéger la trésorerie de l’e
         exportAll: {
             selectAllMatchingItems: 'Sélectionnez tous les éléments correspondants',
             allMatchingItemsSelected: 'Tous les éléments correspondants sont sélectionnés',
-            selectAllOnThisPage: 'Tout sélectionner sur cette page',
-        },
-        errors: {
-            pleaseSelectDatesForBothFromAndTo: 'Veuillez sélectionner des dates pour De et À',
-        },
-        spendOverTime: 'Dépenses dans le temps',
-        tabs: {
-            expenseReports: 'Notes de frais',
-            reports: 'Notes de frais',
-            expenses: 'Dépenses',
-            submit: 'Brouillons',
-            approve: 'Nécessite une approbation',
-            pay: 'Prêt à payer',
-            accounting: 'Comptabilité',
-            export: 'En attente d’exportation',
-            unapprovedCash: 'Provisions de trésorerie',
-            unapprovedCard: 'Provisions sur cartes',
-            statements: 'Relevés de carte',
-            reconciliation: 'Rapprochement bancaire',
-            insights: 'Analyses',
-            topSpenders: 'Plus gros dépensiers',
-            topCategories: 'Catégories principales',
-            topMerchants: 'Meilleurs commerçants',
         },
     },
     genericErrorPage: {
@@ -8499,6 +7336,7 @@ Ajoutez davantage de règles de dépenses pour protéger la trésorerie de l’e
             emptyReportConfirmationTitle: 'Vous avez déjà une note de frais vide',
             emptyReportConfirmationPrompt: ({workspaceName}: {workspaceName: string}) =>
                 `Voulez-vous vraiment créer une autre note de frais dans ${workspaceName} ? Vous pouvez accéder à vos notes de frais vides dans`,
+            emptyReportConfirmationPromptLink: 'Notes de frais',
             emptyReportConfirmationDontShowAgain: 'Ne plus m’afficher ceci',
             genericWorkspaceName: 'cet espace de travail',
         },
@@ -8536,7 +7374,6 @@ Ajoutez davantage de règles de dépenses pour protéger la trésorerie de l’e
                     reimburseableLink: 'dépenses personnelles',
                     nonReimbursableLink: 'Dépenses de carte d’entreprise',
                     pending: (label: string) => `a commencé à exporter cette note de frais vers ${label}...`,
-                    travelCardLink: 'dépenses par carte de voyage',
                 },
                 integrationsMessage: (errorMessage: string, label: string, linkText?: string, linkURL?: string) =>
                     `échec de l’exportation de cette note de frais vers ${label} (« ${errorMessage}${linkText ? `<a href="${linkURL}">${linkText}</a>` : ''} »)`,
@@ -8545,8 +7382,7 @@ Ajoutez davantage de règles de dépenses pour protéger la trésorerie de l’e
                 markedReimbursed: (amount: string, currency: string) => `payé ${amount} ${currency} ailleurs`,
                 markedReimbursedFromIntegration: ({amount, currency}: MarkReimbursedFromIntegrationParams) => `a payé ${currency}${amount} via intégration`,
                 outdatedBankAccount: `n’a pas pu traiter le paiement en raison d’un problème avec le compte bancaire du payeur`,
-                reimbursementACHBounceDefault: `impossible de traiter le paiement en raison d’un numéro de routage/de compte incorrect ou d’un compte clôturé`,
-                reimbursementACHBounceWithReason: ({returnReason}: {returnReason: string}) => `impossible de traiter le paiement : ${returnReason}`,
+                reimbursementACHBounce: `impossible de traiter le paiement en raison d’un problème de compte bancaire`,
                 reimbursementACHCancelled: `a annulé le paiement`,
                 reimbursementAccountChanged: `impossible de traiter le paiement, car le payeur a changé de compte bancaire`,
                 reimbursementDelayed: `a traité le paiement, mais il est retardé de 1 à 2 jours ouvrables supplémentaires`,
@@ -8554,22 +7390,17 @@ Ajoutez davantage de règles de dépenses pour protéger la trésorerie de l’e
                 selectedForRandomAuditMarkdown: `[sélectionné aléatoirement](https://help.expensify.com/articles/expensify-classic/reports/Set-a-random-report-audit-schedule) pour examen`,
                 share: ({to}: ShareParams) => `a invité le membre ${to}`,
                 unshare: ({to}: UnshareParams) => `a retiré le membre ${to}`,
-                stripePaid: (amount: string, currency: string) => `payé ${amount} ${currency}`,
+                stripePaid: ({amount, currency}: StripePaidParams) => `payé ${amount} ${currency}`,
                 takeControl: `a pris le contrôle`,
                 integrationSyncFailed: (label: string, errorMessage: string, workspaceAccountingLink?: string) =>
                     `un problème est survenu lors de la synchronisation avec ${label}${errorMessage ? ` ("${errorMessage}")` : ''}. Veuillez corriger le problème dans les <a href="${workspaceAccountingLink}">paramètres de l’espace de travail</a>.`,
-                integrationSyncFailedRecurrence: ({count}: {count: number}) => `(Répété ${count} fois.)`,
                 companyCardConnectionBroken: ({feedName, workspaceCompanyCardRoute}: {feedName: string; workspaceCompanyCardRoute: string}) =>
                     `La connexion ${feedName} est interrompue. Pour rétablir l’importation des cartes, <a href='${workspaceCompanyCardRoute}'>connectez-vous à votre banque</a>.`,
                 plaidBalanceFailure: ({maskedAccountNumber, walletRoute}: {maskedAccountNumber: string; walletRoute: string}) =>
-                    `la connexion Plaid à votre compte bancaire professionnel est rompue. Veuillez <a href='${walletRoute}'>reconnecter votre compte bancaire ${maskedAccountNumber}</a> afin de pouvoir continuer à utiliser vos Cartes Expensify.`,
-                addEmployee: (email: string, role: string, didJoinPolicy?: boolean) => {
-                    const translatedRole = String(translations.workspace.common.roleName(role)).toLowerCase();
-                    const article = role === CONST.POLICY.ROLE.AUDITOR ? 'un' : 'un';
-                    return didJoinPolicy ? `${email} a rejoint via le lien d’invitation à l’espace de travail` : `a ajouté ${email} en tant que ${article} ${translatedRole}`;
-                },
+                    `la connexion Plaid à votre compte bancaire professionnel est rompue. Veuillez <a href='${walletRoute}'>reconnecter votre compte bancaire ${maskedAccountNumber}</a> pour pouvoir continuer à utiliser vos cartes Expensify.`,
+                addEmployee: (email: string, role: string) => `a ajouté ${email} en tant que ${role === 'member' ? 'un' : 'un'} ${role}`,
                 updateRole: ({email, currentRole, newRole}: UpdateRoleParams) => `a mis à jour le rôle de ${email} en ${newRole} (précédemment ${currentRole})`,
-                updatedCustomField1: (email: string, newValue: string, previousValue: string) => {
+                updatedCustomField1: ({email, previousValue, newValue}: UpdatedCustomFieldParams) => {
                     if (!newValue) {
                         return `a supprimé le champ personnalisé 1 de ${email} (précédemment « ${previousValue} »)`;
                     }
@@ -8577,7 +7408,7 @@ Ajoutez davantage de règles de dépenses pour protéger la trésorerie de l’e
                         ? `a ajouté « ${newValue} » au champ personnalisé 1 de ${email}`
                         : `a modifié le champ personnalisé 1 de ${email} en « ${newValue} » (auparavant « ${previousValue} »)`;
                 },
-                updatedCustomField2: (email: string, newValue: string, previousValue: string) => {
+                updatedCustomField2: ({email, previousValue, newValue}: UpdatedCustomFieldParams) => {
                     if (!newValue) {
                         return `a supprimé le champ personnalisé 2 de ${email} (auparavant « ${previousValue} »)`;
                     }
@@ -8591,12 +7422,8 @@ Ajoutez davantage de règles de dépenses pour protéger la trésorerie de l’e
                 addedConnection: ({connectionName}: ConnectionNameParams) => `connecté à ${CONST.POLICY.CONNECTIONS.NAME_USER_FRIENDLY[connectionName]}`,
                 leftTheChat: 'a quitté la discussion',
                 settlementAccountLocked: ({maskedBankAccountNumber}: OriginalMessageSettlementAccountLocked, linkURL: string) =>
-                    `le compte bancaire professionnel ${maskedBankAccountNumber} a été automatiquement verrouillé en raison d’un problème lié soit au remboursement, soit au règlement de la Carte Expensify. Veuillez corriger le problème dans vos <a href="${linkURL}">paramètres d’espace de travail</a>.`,
+                    `le compte bancaire professionnel ${maskedBankAccountNumber} a été automatiquement verrouillé en raison d’un problème avec le remboursement ou le règlement de la carte Expensify. Veuillez corriger ce problème dans vos <a href="${linkURL}">paramètres d’espace de travail</a>.`,
                 leftTheChatWithName: (nameOrEmail: string) => `${nameOrEmail ? `${nameOrEmail}: ` : ''} a quitté la discussion`,
-                actionableCard3DSTransactionApproval: (amount: string, merchant: string | undefined) => {
-                    const amountAndMerchantText = [amount, merchant].filter((s) => !!s?.length).join(' ');
-                    return `Ouvrez l'application mobile Expensify pour examiner votre transaction de${amountAndMerchantText ? ` ${amountAndMerchantText}` : ''}`;
-                },
             },
             error: {
                 invalidCredentials: 'Identifiants invalides, veuillez vérifier la configuration de votre connexion.',
@@ -8606,23 +7433,6 @@ Ajoutez davantage de règles de dépenses pour protéger la trésorerie de l’e
     chronos: {
         oooEventSummaryFullDay: (summary: string, dayCount: number, date: string) => `${summary} pour ${dayCount} ${dayCount === 1 ? 'jour' : 'jours'} jusqu’au ${date}`,
         oooEventSummaryPartialDay: (summary: string, timePeriod: string, date: string) => `${summary} du ${timePeriod} le ${date}`,
-        startTimer: 'Démarrer le minuteur',
-        stopTimer: (duration: string) => `Arrêter le minuteur (${duration})`,
-        scheduleOOO: 'Planifier une absence',
-        scheduleOOOTitle: 'Planifier une absence du bureau',
-        date: 'Date',
-        time: 'Heure (format 24 heures)',
-        durationAmount: 'Durée',
-        durationUnit: 'Unité',
-        reason: 'Raison',
-        workingPercentage: 'Pourcentage de travail',
-        dateRequired: 'La date est obligatoire.',
-        invalidTimeFormat: 'Veuillez entrer une heure valide au format 24 heures (par ex. 14:30).',
-        enterANumber: 'Veuillez saisir un nombre.',
-        hour: 'heures',
-        day: 'jours',
-        week: 'semaines',
-        month: 'mois',
     },
     footer: {
         features: 'Fonctionnalités',
@@ -8665,24 +7475,8 @@ Ajoutez davantage de règles de dépenses pour protéger la trésorerie de l’e
         workspaceName: 'Nom de l’espace de travail',
         chatUserDisplayNames: 'Noms d’affichage des membres de discussion',
         scrollToNewestMessages: 'Aller au dernier message',
-        scrollToActionBadgeTarget: "Aller à l'action nécessitant votre attention",
         preStyledText: 'Texte pré-stylé',
         viewAttachment: 'Afficher la pièce jointe',
-        contextMenuAvailable: 'Menu contextuel disponible. Appuyez sur Shift+F10 pour l’ouvrir.',
-        contextMenuAvailableMacOS: 'Menu contextuel disponible. Appuyez sur VO-Shift-M pour l’ouvrir.',
-        contextMenuAvailableNative: 'Menu contextuel disponible. Appuyez deux fois et maintenez pour l’ouvrir.',
-        selectAllFeatures: 'Sélectionner toutes les fonctionnalités',
-        selectAllTransactions: 'Sélectionner toutes les transactions',
-        selectAllItems: 'Sélectionner tous les éléments',
-        openActionsMenu: 'Ouvrir le menu des actions',
-        selectAllCategories: 'Sélectionner toutes les catégories',
-        selectAllDistanceRates: 'Sélectionner tous les taux de distance',
-        selectAllTags: 'Sélectionner toutes les étiquettes',
-        selectAllTaxes: 'Sélectionner toutes les taxes',
-        selectAllPerDiemRates: 'Sélectionner tous les taux de per diem',
-        selectAllMembers: 'Sélectionner tous les membres',
-        selectAllValues: 'Sélectionner toutes les valeurs',
-        selectAllRules: 'Sélectionner toutes les règles',
     },
     parentReportAction: {
         deletedReport: 'Note de frais supprimée',
@@ -8701,7 +7495,6 @@ Ajoutez davantage de règles de dépenses pour protéger la trésorerie de l’e
         parentNavigationSummary: ({reportName, workspaceName}: ParentNavigationSummaryParams) => `De ${reportName}${workspaceName ? `dans ${workspaceName}` : ''}`,
     },
     qrCodes: {
-        qrCode: 'Code QR',
         copy: 'Copier l’URL',
         copied: 'Copié !',
     },
@@ -8748,11 +7541,6 @@ Ajoutez davantage de règles de dépenses pour protéger la trésorerie de l’e
             'Rejoignez Expensify.org pour éliminer l’injustice dans le monde entier. La campagne actuelle « Teachers Unite » soutient les enseignants partout en partageant le coût des fournitures scolaires essentielles.',
         iKnowATeacher: 'Je connais un enseignant',
         iAmATeacher: 'Je suis enseignant',
-        personalKarma: {
-            title: 'Activer le Karma personnel',
-            description: 'Faites un don de 1 $ à Expensify.org pour chaque tranche de 500 $ dépensée chaque mois',
-            stopDonationsPrompt: 'Êtes-vous sûr de vouloir arrêter de faire des dons à Expensify.org ?',
-        },
         getInTouch: 'Excellent ! Veuillez partager leurs coordonnées afin que nous puissions les contacter.',
         introSchoolPrincipal: 'Présentation de la direction de votre école',
         schoolPrincipalVerifyExpense:
@@ -8775,11 +7563,6 @@ Ajoutez davantage de règles de dépenses pour protéger la trésorerie de l’e
         notActivated: 'Non activé',
         outOfPocket: 'Remboursable',
         companySpend: 'Non remboursable',
-        personalCard: 'Carte personnelle',
-        companyCard: 'Carte d’entreprise',
-        expensifyCard: 'Carte Expensify',
-        travelInvoicing: 'Facturation de voyages',
-        travelCard: 'Carte de voyage',
     },
     distance: {
         addStop: 'Ajouter un arrêt',
@@ -8803,19 +7586,15 @@ Ajoutez davantage de règles de dépenses pour protéger la trésorerie de l’e
             endReading: 'Fin de lecture',
             saveForLater: 'Enregistrer pour plus tard',
             totalDistance: 'Distance totale',
+            startTitle: 'Photo du compteur au départ',
+            endTitle: 'Photo de fin d’odomètre',
             startMessageWeb:
                 'Ajoutez une photo de votre compteur kilométrique prise au <strong>début</strong> de votre trajet. Faites glisser un fichier ici ou choisissez-en un à télécharger.',
             endMessageWeb: 'Ajoutez une photo du compteur kilométrique prise à la <strong>fin</strong> de votre trajet. Faites glisser un fichier ici ou choisissez-en un à télécharger.',
-            startTitle: 'Photo du compteur de départ',
-            endTitle: 'Photo du compteur (arrivée)',
-            deleteOdometerPhoto: 'Supprimer la photo du compteur kilométrique',
-            deleteOdometerPhotoConfirmation: 'Voulez-vous vraiment supprimer cette photo de l’odomètre ?',
-            cameraAccessRequired: "L'accès à l'appareil photo est requis pour prendre des photos.",
-            snapPhotoStart: '<muted-text-label>Prenez une photo de votre compteur kilométrique au <strong>début</strong> de votre trajet.</muted-text-label>',
-            snapPhotoEnd: '<muted-text-label>Prenez une photo de votre compteur kilométrique à la <strong>fin</strong> de votre trajet.</muted-text-label>',
         },
     },
     gps: {
+        disclaimer: 'Utilisez le GPS pour créer une dépense à partir de votre trajet. Appuyez sur Démarrer ci-dessous pour commencer le suivi.',
         error: {
             failedToStart: 'Échec du démarrage du suivi de la localisation.',
             failedToGetPermissions: 'Échec de l’obtention des autorisations de localisation requises.',
@@ -8824,9 +7603,13 @@ Ajoutez davantage de règles de dépenses pour protéger la trésorerie de l’e
         stopped: 'Arrêté',
         start: 'Démarrer',
         stop: 'Arrêter',
-        save: 'Enregistrer',
-        resume: 'Reprendre',
         discard: 'Ignorer',
+        stopGpsTrackingModal: {
+            title: 'Arrêter le suivi GPS',
+            prompt: 'Êtes-vous sûr(e) ? Cela mettra fin à votre parcours actuel.',
+            cancel: 'Reprendre le suivi',
+            confirm: 'Arrêter le suivi GPS',
+        },
         discardDistanceTrackingModal: {
             title: 'Abandonner le suivi de distance',
             prompt: 'Êtes-vous sûr(e) ? Cela supprimera votre parcours en cours et ne pourra pas être annulé.',
@@ -8874,18 +7657,12 @@ Ajoutez davantage de règles de dépenses pour protéger la trésorerie de l’e
             prompt: 'Voulez-vous vraiment arrêter le suivi GPS et passer à Expensify Classic ?',
             confirm: 'Arrêter et changer',
         },
-        switchAccountWarningTripInProgress: {
-            title: 'Suivi GPS en cours',
-            prompt: 'Voulez-vous vraiment arrêter le suivi GPS et changer de compte ?',
-            confirm: 'Arrêter et passer à autre chose',
-        },
         locationServicesRequiredModal: {
             title: 'Accès à la localisation requis',
             confirm: 'Ouvrir les paramètres',
             prompt: 'Veuillez autoriser l’accès à la localisation dans les réglages de votre appareil pour commencer le suivi de distance GPS.',
         },
-        gpsFloatingPillText: 'Suivi GPS en cours...',
-        liveActivity: {subtitle: 'Suivi de la distance', button: 'Voir la progression', lockScreenBadgeText: 'Distance', lockScreenTrackingText: 'Suivi...'},
+        fabGpsTripExplained: 'Aller à l’écran GPS (action flottante)',
     },
     reportCardLostOrDamaged: {
         screenTitle: 'relevé de notes perdu ou endommagé',
@@ -8912,13 +7689,11 @@ Ajoutez davantage de règles de dépenses pour protéger la trésorerie de l’e
         [CONST.REFERRAL_PROGRAM.CONTENT_TYPES.START_CHAT]: {
             buttonText: 'Démarrez une discussion, <success><strong>parrainez un ami</strong></success>.',
             header: 'Commencez une discussion, parrainez un ami',
-            closeAccessibilityLabel: 'Fermer, démarrer un chat, parrainer un ami, bannière',
             body: 'Vous voulez que vos amis utilisent Expensify, eux aussi ? Il vous suffit de commencer une discussion avec eux et nous nous occupons du reste.',
         },
         [CONST.REFERRAL_PROGRAM.CONTENT_TYPES.SUBMIT_EXPENSE]: {
             buttonText: 'Soumettez une dépense, <success><strong>parrainez votre équipe</strong></success>.',
             header: 'Soumettez une dépense, parrainez votre équipe',
-            closeAccessibilityLabel: 'Fermer, soumettre une dépense, parrainer votre équipe, bannière',
             body: 'Vous voulez que votre équipe utilise Expensify, elle aussi ? Soumettez-leur simplement une dépense et nous nous occupons du reste.',
         },
         [CONST.REFERRAL_PROGRAM.CONTENT_TYPES.REFER_FRIEND]: {
@@ -8934,27 +7709,26 @@ Ajoutez davantage de règles de dépenses pour protéger la trésorerie de l’e
     },
     systemChatFooterMessage: {
         [CONST.INTRO_CHOICES.MANAGE_TEAM]: ({adminReportName, href}: {adminReportName: string; href: string}) =>
-            `Discutez avec votre chargé de compte dans <a href="${href}">${adminReportName}</a> pour obtenir de l'aide`,
+            `Discutez avec votre spécialiste de configuration dans <a href="${href}">${adminReportName}</a> pour obtenir de l’aide`,
         default: `Envoyez un message à <concierge-link>${CONST.CONCIERGE_CHAT_NAME}</concierge-link> pour obtenir de l’aide pour la configuration`,
     },
     violations: {
         allTagLevelsRequired: 'Tous les tags sont obligatoires',
         autoReportedRejectedExpense: 'Cette dépense a été rejetée.',
         billableExpense: 'Facturable n’est plus valide',
-        cashExpenseWithNoReceipt: (formattedLimit?: string) => `Reçu obligatoire${formattedLimit ? `au-delà de ${formattedLimit}` : ''}`,
+        cashExpenseWithNoReceipt: ({formattedLimit}: ViolationsCashExpenseWithNoReceiptParams = {}) => `Reçu obligatoire${formattedLimit ? `au-delà de ${formattedLimit}` : ''}`,
         categoryOutOfPolicy: 'Catégorie plus valide',
-        conversionSurcharge: (surcharge: number) => `Surcharge de conversion de ${surcharge}% appliquée`,
+        conversionSurcharge: ({surcharge}: ViolationsConversionSurchargeParams) => `Surcharge de conversion de ${surcharge}% appliquée`,
         customUnitOutOfPolicy: 'Taux non valide pour cet espace de travail',
         duplicatedTransaction: 'Doublon potentiel',
         fieldRequired: 'Les champs de note de frais sont obligatoires',
         futureDate: 'Date future non autorisée',
-        inactiveVendor: 'Fournisseur plus valide',
-        invoiceMarkup: (invoiceMarkup: number) => `Majoration de ${invoiceMarkup} %`,
-        maxAge: (maxAge: number) => `Date antérieure de plus de ${maxAge} jours`,
+        invoiceMarkup: ({invoiceMarkup}: ViolationsInvoiceMarkupParams) => `Majoration de ${invoiceMarkup} %`,
+        maxAge: ({maxAge}: ViolationsMaxAgeParams) => `Date antérieure de plus de ${maxAge} jours`,
         missingCategory: 'Catégorie manquante',
         missingComment: 'Description requise pour la catégorie sélectionnée',
         missingAttendees: 'Plusieurs participants sont requis pour cette catégorie',
-        missingTag: (tagName?: string) => `${tagName ?? 'tag'} manquant`,
+        missingTag: ({tagName}: ViolationsMissingTagParams = {}) => `${tagName ?? 'tag'} manquant`,
         modifiedAmount: ({type, displayPercentVariance}: ViolationsModifiedAmountParams) => {
             switch (type) {
                 case 'distance':
@@ -8969,17 +7743,15 @@ Ajoutez davantage de règles de dépenses pour protéger la trésorerie de l’e
             }
         },
         modifiedDate: 'La date diffère du reçu scanné',
-        increasedDistance: ({formattedRouteDistance}: ViolationsIncreasedDistanceParams) =>
-            formattedRouteDistance ? `La distance dépasse l'itinéraire calculé de ${formattedRouteDistance}` : "La distance dépasse l'itinéraire calculé",
         nonExpensiworksExpense: 'Dépense non Expensiworks',
-        overAutoApprovalLimit: (formattedLimit: string) => `La dépense dépasse la limite d’auto-approbation de ${formattedLimit}`,
-        overCategoryLimit: (formattedLimit: string) => `Montant dépassant la limite de catégorie de ${formattedLimit}/personne`,
-        overLimit: (formattedLimit: string) => `Montant dépassant la limite de ${formattedLimit}/personne`,
-        overTripLimit: (formattedLimit: string) => `Montant dépassant la limite de ${formattedLimit}/trajet`,
-        overLimitAttendee: (formattedLimit: string) => `Montant dépassant la limite de ${formattedLimit}/personne`,
-        perDayLimit: (formattedLimit: string) => `Montant dépassant la limite quotidienne de catégorie de ${formattedLimit}/personne`,
+        overAutoApprovalLimit: ({formattedLimit}: ViolationsOverLimitParams) => `La dépense dépasse la limite d’auto-approbation de ${formattedLimit}`,
+        overCategoryLimit: ({formattedLimit}: ViolationsOverCategoryLimitParams) => `Montant dépassant la limite de catégorie de ${formattedLimit}/personne`,
+        overLimit: ({formattedLimit}: ViolationsOverLimitParams) => `Montant dépassant la limite de ${formattedLimit}/personne`,
+        overTripLimit: ({formattedLimit}: ViolationsOverLimitParams) => `Montant dépassant la limite de ${formattedLimit}/trajet`,
+        overLimitAttendee: ({formattedLimit}: ViolationsOverLimitParams) => `Montant dépassant la limite de ${formattedLimit}/personne`,
+        perDayLimit: ({formattedLimit}: ViolationsPerDayLimitParams) => `Montant dépassant la limite quotidienne de catégorie de ${formattedLimit}/personne`,
         receiptNotSmartScanned: 'Détails du reçu et de la dépense ajoutés manuellement.',
-        receiptRequired: (formattedLimit?: string, category?: string) => {
+        receiptRequired: ({formattedLimit, category}: ViolationsReceiptRequiredParams) => {
             if (formattedLimit && category) {
                 return `Reçu requis au-delà de la limite de catégorie de ${formattedLimit}`;
             }
@@ -8991,8 +7763,8 @@ Ajoutez davantage de règles de dépenses pour protéger la trésorerie de l’e
             }
             return 'Reçu obligatoire';
         },
-        itemizedReceiptRequired: (formattedLimit?: string) => `Reçu détaillé requis${formattedLimit ? `au-delà de ${formattedLimit}` : ''}`,
-        prohibitedExpense: (prohibitedExpenseTypes: string | string[]) => {
+        itemizedReceiptRequired: ({formattedLimit}: {formattedLimit?: string}) => `Reçu détaillé requis${formattedLimit ? `au-delà de ${formattedLimit}` : ''}`,
+        prohibitedExpense: ({prohibitedExpenseTypes}: ViolationsProhibitedExpenseParams) => {
             const preMessage = 'Dépense interdite :';
             const getProhibitedExpenseTypeText = (prohibitedExpenseType: string) => {
                 switch (prohibitedExpenseType) {
@@ -9006,10 +7778,6 @@ Ajoutez davantage de règles de dépenses pour protéger la trésorerie de l’e
                         return `divertissement pour adultes`;
                     case 'hotelIncidentals':
                         return `Frais annexes d'hôtel`;
-                    case 'giftCard':
-                        return `achats de cartes-cadeaux`;
-                    case 'handwrittenReceipt':
-                        return `reçus manuscrits`;
                     default:
                         return `${prohibitedExpenseType}`;
                 }
@@ -9025,37 +7793,19 @@ Ajoutez davantage de règles de dépenses pour protéger la trésorerie de l’e
             }
             return `${preMessage} ${types.map(getProhibitedExpenseTypeText).join(', ')}`;
         },
-        customRules: (message: string) => message,
+        customRules: ({message}: ViolationsCustomRulesParams) => message,
         reviewRequired: 'Examen requis',
-        rter: (
-            brokenBankConnection: boolean,
-            isAdmin: boolean,
-            isTransactionOlderThan7Days: boolean,
-            member?: string,
-            rterType?: ValueOf<typeof CONST.RTER_VIOLATION_TYPES>,
-            companyCardPageURL?: string,
-            connectionLink?: string,
-            isPersonalCard?: boolean,
-            isMarkAsCash?: boolean,
-        ) => {
+        rter: ({brokenBankConnection, isAdmin, isTransactionOlderThan7Days, member, rterType, companyCardPageURL}: ViolationsRterParams) => {
             if (rterType === CONST.RTER_VIOLATION_TYPES.BROKEN_CARD_CONNECTION_530) {
-                return 'Impossible d’apparier automatiquement le reçu en raison d’une connexion bancaire rompue.';
-            }
-            if (isPersonalCard && (rterType === CONST.RTER_VIOLATION_TYPES.BROKEN_CARD_CONNECTION || brokenBankConnection)) {
-                if (!connectionLink) {
-                    return 'Impossible d’apparier automatiquement le reçu en raison d’une connexion bancaire rompue.';
-                }
-                return isMarkAsCash
-                    ? `Impossible d'associer automatiquement le reçu en raison d'une connexion de carte défectueuse. Marquez-le comme paiement en espèces pour l'ignorer, ou <a href="${connectionLink}">corrigez la carte</a> pour associer le reçu.`
-                    : `Impossible d'associer automatiquement le reçu en raison d'une connexion de carte rompue. <a href="${connectionLink}">Réparez la carte</a> pour faire correspondre le reçu.`;
+                return 'Impossible d’associer automatiquement le reçu en raison d’une connexion bancaire interrompue';
             }
             if (brokenBankConnection || rterType === CONST.RTER_VIOLATION_TYPES.BROKEN_CARD_CONNECTION) {
                 return isAdmin
                     ? `Connexion bancaire rompue. <a href="${companyCardPageURL}">Reconnectez-vous pour faire correspondre le reçu</a>`
-                    : 'Connexion bancaire interrompue. Demandez à un administrateur de la reconnecter pour faire correspondre le reçu.';
+                    : 'Connexion bancaire rompue. Demandez à un administrateur de la reconnecter pour faire correspondre le reçu.';
             }
             if (!isTransactionOlderThan7Days) {
-                return isAdmin ? `Demandez à ${member} de marquer comme paiement en espèces ou attendez 7 jours et réessayez` : 'En attente de fusion avec la transaction par carte.';
+                return isAdmin ? `Demandez à ${member} de marquer comme espèce ou attendez 7 jours et réessayez` : 'En attente de fusion avec la transaction par carte.';
             }
             return '';
         },
@@ -9064,20 +7814,12 @@ Ajoutez davantage de règles de dépenses pour protéger la trésorerie de l’e
             `<muted-text-label>Reçu en attente en raison d’une connexion bancaire rompue. Veuillez résoudre le problème dans les <a href="${workspaceCompanyCardRoute}">Cartes d’entreprise</a>.</muted-text-label>`,
         memberBrokenConnectionError: 'Reçu en attente en raison d’une connexion bancaire rompue. Veuillez demander à un administrateur de l’espace de travail de résoudre le problème.',
         markAsCashToIgnore: 'Marquer comme paiement en espèces pour l’ignorer et demander un paiement.',
-        smartscanFailed: ({canEdit = true, missingFields = []}: {canEdit?: boolean; missingFields?: string[]}) => {
-            if (missingFields.length > 0) {
-                const fieldNames: Record<string, string> = {merchant: 'commerçant', date: 'date', amount: 'montant'};
-                const translated = missingFields.map((f) => fieldNames[f] ?? f);
-                const fieldList = translated.join(translated.length > 2 ? ', ' : ' et ');
-                return `L’analyse du reçu a échoué — champ(s) manquant(s) : ${fieldList}.${canEdit ? ' Saisir les détails manuellement.' : ''}`;
-            }
-            return `L’analyse du reçu a échoué.${canEdit ? 'Saisir les détails manuellement.' : ''}`;
-        },
+        smartscanFailed: ({canEdit = true}) => `L’analyse du reçu a échoué.${canEdit ? 'Saisir les détails manuellement.' : ''}`,
         receiptGeneratedWithAI: 'Reçu potentiellement généré par IA',
-        someTagLevelsRequired: (tagName?: string) => `${tagName ?? 'Tag'} manquant`,
-        tagOutOfPolicy: (tagName?: string) => `${tagName ?? 'Tag'} n’est plus valide`,
+        someTagLevelsRequired: ({tagName}: ViolationsTagOutOfPolicyParams = {}) => `${tagName ?? 'Tag'} manquant`,
+        tagOutOfPolicy: ({tagName}: ViolationsTagOutOfPolicyParams = {}) => `${tagName ?? 'Tag'} n’est plus valide`,
         taxAmountChanged: 'Le montant de la taxe a été modifié',
-        taxOutOfPolicy: (taxName?: string) => `${taxName ?? 'Tax'} n’est plus valide`,
+        taxOutOfPolicy: ({taxName}: ViolationsTaxOutOfPolicyParams = {}) => `${taxName ?? 'Tax'} n’est plus valide`,
         taxRateChanged: 'Le taux de taxe a été modifié',
         taxRequired: 'Taux de taxe manquant',
         none: 'Aucun',
@@ -9097,7 +7839,7 @@ Ajoutez davantage de règles de dépenses pour protéger la trésorerie de l’e
         noRoute: 'Veuillez sélectionner une adresse valide',
     },
     reportViolations: {
-        [CONST.REPORT_VIOLATIONS.FIELD_REQUIRED]: (fieldName: string) => `${fieldName} est obligatoire`,
+        [CONST.REPORT_VIOLATIONS.FIELD_REQUIRED]: ({fieldName}: RequiredFieldParams) => `${fieldName} est obligatoire`,
         reportContainsExpensesWithViolations: 'La note de frais contient des dépenses avec des violations.',
     },
     violationDismissal: {
@@ -9154,7 +7896,6 @@ Ajoutez davantage de règles de dépenses pour protéger la trésorerie de l’e
         bookACallTextBottom:
             'Nous serions ravis d’organiser un appel avec vous pour comprendre pourquoi. Vous pouvez réserver un appel avec l’un de nos chefs de produit senior pour discuter de vos besoins.',
         takeMeToExpensifyClassic: 'M’emmener vers Expensify Classic',
-        goBackJustOnce: 'Revenir une seule fois',
     },
     listBoundary: {
         errorMessage: 'Une erreur est survenue lors du chargement de messages supplémentaires',
@@ -9228,7 +7969,7 @@ Ajoutez davantage de règles de dépenses pour protéger la trésorerie de l’e
                 subtitle: 'Étape suivante, <a href="#">complétez votre liste de configuration</a> pour que votre équipe puisse commencer à déclarer des dépenses.',
             },
             trialStarted: {
-                title: (numOfDays: number) => `Essai : il reste ${numOfDays} ${numOfDays === 1 ? 'jour' : 'jours'} !`,
+                title: ({numOfDays}: TrialStartedTitleParams) => `Essai : il reste ${numOfDays} ${numOfDays === 1 ? 'jour' : 'jours'} !`,
                 subtitle: 'Ajoutez une carte de paiement pour continuer à utiliser toutes vos fonctionnalités préférées.',
             },
             trialEnded: {
@@ -9266,15 +8007,15 @@ Ajoutez davantage de règles de dépenses pour protéger la trésorerie de l’e
             title: 'Votre offre',
             exploreAllPlans: 'Découvrir toutes les offres',
             customPricing: 'Tarification personnalisée',
-            asLowAs: (price: string) => `à partir de ${price} par membre actif/mois`,
-            pricePerMemberMonth: (price: string) => `${price} par membre/mois`,
-            pricePerMemberPerMonth: (price: string) => `${price} par membre et par mois`,
+            asLowAs: ({price}: YourPlanPriceValueParams) => `à partir de ${price} par membre actif/mois`,
+            pricePerMemberMonth: ({price}: YourPlanPriceValueParams) => `${price} par membre/mois`,
+            pricePerMemberPerMonth: ({price}: YourPlanPriceValueParams) => `${price} par membre et par mois`,
             perMemberMonth: 'par membre/mois',
             collect: {
                 title: 'Encaisser',
                 description: 'L’offre pour petites entreprises qui vous offre les dépenses, les voyages et le chat.',
-                priceAnnual: ({lower, upper}: YourPlanPriceParams) => `De ${lower}/membre actif avec la Carte Expensify à ${upper}/membre actif sans la Carte Expensify.`,
-                pricePayPerUse: ({lower, upper}: YourPlanPriceParams) => `De ${lower}/membre actif avec la Carte Expensify à ${upper}/membre actif sans la Carte Expensify.`,
+                priceAnnual: ({lower, upper}: YourPlanPriceParams) => `De ${lower}/membre actif avec la carte Expensify, à ${upper}/membre actif sans la carte Expensify.`,
+                pricePayPerUse: ({lower, upper}: YourPlanPriceParams) => `De ${lower}/membre actif avec la carte Expensify, à ${upper}/membre actif sans la carte Expensify.`,
                 benefit1: 'Numérisation des reçus',
                 benefit2: 'Remboursements',
                 benefit3: 'Gestion des cartes d’entreprise',
@@ -9287,8 +8028,8 @@ Ajoutez davantage de règles de dépenses pour protéger la trésorerie de l’e
             control: {
                 title: 'Contrôle',
                 description: 'Gestion des dépenses, des voyages et des discussions pour les grandes entreprises.',
-                priceAnnual: ({lower, upper}: YourPlanPriceParams) => `De ${lower}/membre actif avec la Carte Expensify à ${upper}/membre actif sans la Carte Expensify.`,
-                pricePayPerUse: ({lower, upper}: YourPlanPriceParams) => `De ${lower}/membre actif avec la Carte Expensify à ${upper}/membre actif sans la Carte Expensify.`,
+                priceAnnual: ({lower, upper}: YourPlanPriceParams) => `De ${lower}/membre actif avec la carte Expensify, à ${upper}/membre actif sans la carte Expensify.`,
+                pricePayPerUse: ({lower, upper}: YourPlanPriceParams) => `De ${lower}/membre actif avec la carte Expensify, à ${upper}/membre actif sans la carte Expensify.`,
                 benefit1: 'Tout ce qui est inclus dans l’offre Collect',
                 benefit2: 'Flux d’approbation multi-niveaux',
                 benefit3: 'Règles de dépenses personnalisées',
@@ -9302,8 +8043,8 @@ Ajoutez davantage de règles de dépenses pour protéger la trésorerie de l’e
             downgrade: 'Rétrograder vers Collect',
             upgrade: 'Passer à Control',
             addMembers: 'Ajouter des membres',
-            saveWithExpensifyTitle: 'Économisez avec la Carte Expensify',
-            saveWithExpensifyDescription: 'Utilisez notre calculateur d’économies pour voir comment le cash back de la Carte Expensify peut réduire votre facture Expensify.',
+            saveWithExpensifyTitle: 'Économisez avec la carte Expensify',
+            saveWithExpensifyDescription: 'Utilisez notre calculatrice d’économies pour voir comment le cash-back de la carte Expensify peut réduire votre facture Expensify.',
             saveWithExpensifyButton: 'En savoir plus',
         },
         compareModal: {
@@ -9313,7 +8054,6 @@ Ajoutez davantage de règles de dépenses pour protéger la trésorerie de l’e
         details: {
             title: 'Détails de l’abonnement',
             annual: 'Abonnement annuel',
-            creditBalance: 'Solde créditeur',
             taxExempt: 'Demander le statut d’exonération fiscale',
             taxExemptEnabled: 'Exonéré d’impôt',
             taxExemptStatus: 'Statut d’exonération fiscale',
@@ -9331,10 +8071,10 @@ Ajoutez davantage de règles de dépenses pour protéger la trésorerie de l’e
             note: 'Remarque : un membre actif est toute personne qui a créé, modifié, soumis, approuvé, remboursé ou exporté des données de dépenses liées à votre espace de travail d’entreprise.',
             confirmDetails: 'Confirmez les détails de votre nouvel abonnement annuel :',
             subscriptionSize: 'Taille de l’abonnement',
-            activeMembers: (size: number) => `${size} membres actifs/mois`,
+            activeMembers: ({size}: SubscriptionSizeParams) => `${size} membres actifs/mois`,
             subscriptionRenews: 'Renouvellement de l’abonnement',
             youCantDowngrade: 'Vous ne pouvez pas changer pour une offre inférieure pendant votre abonnement annuel.',
-            youAlreadyCommitted: (size: number, date: string) =>
+            youAlreadyCommitted: ({size, date}: SubscriptionCommitmentParams) =>
                 `Vous avez déjà souscrit un abonnement annuel de ${size} membres actifs par mois jusqu’au ${date}. Vous pouvez passer à un abonnement à l’utilisation le ${date} en désactivant le renouvellement automatique.`,
             error: {
                 size: 'Veuillez saisir une taille d’abonnement valide',
@@ -9347,50 +8087,37 @@ Ajoutez davantage de règles de dépenses pour protéger la trésorerie de l’e
             security: 'Expensify est conforme à la norme PCI-DSS, utilise un chiffrement de niveau bancaire et une infrastructure redondante pour protéger vos données.',
             learnMoreAboutSecurity: 'En savoir plus sur notre sécurité.',
         },
-        expensifyCode: {
-            title: 'Code Expensify',
-            discountCode: 'Code de réduction',
-            enterCode: 'Saisissez un code Expensify à appliquer à votre abonnement.',
-            discountMessage: (promoDiscount: string, validBillingCycles: string) =>
-                `Vous bénéficierez de ${promoDiscount}% de réduction sur vos ${validBillingCycles ? `${validBillingCycles} ` : ''}prochaines facturations.`,
-            apply: 'Appliquer',
-            error: {
-                invalid: "Ce code n'est pas valide",
-            },
-        },
         subscriptionSettings: {
             title: 'Paramètres d’abonnement',
-            summary: (subscriptionType: string, subscriptionSize: string, expensifyCode: string, autoRenew: string, autoIncrease: string) =>
-                `Type d’abonnement : ${subscriptionType}, Taille de l’abonnement : ${subscriptionSize}${expensifyCode ? `, Code Expensify : ${expensifyCode}` : ''}, Renouvellement automatique : ${autoRenew}, Augmentation automatique des licences annuelles : ${autoIncrease}`,
+            summary: ({subscriptionType, subscriptionSize, autoRenew, autoIncrease}: SubscriptionSettingsSummaryParams) =>
+                `Type d’abonnement : ${subscriptionType}, Taille de l’abonnement : ${subscriptionSize}, Renouvellement automatique : ${autoRenew}, Augmentation automatique des licences annuelles : ${autoIncrease}`,
             none: 'aucun',
             on: 'activé',
             off: 'désactivé',
             annual: 'Annuel',
             autoRenew: 'Renouvellement automatique',
             autoIncrease: 'Augmenter automatiquement les licences annuelles',
-            saveUpTo: (amountWithCurrency: string) => `Économisez jusqu’à ${amountWithCurrency}/mois par membre actif`,
+            saveUpTo: ({amountWithCurrency}: SubscriptionSettingsSaveUpToParams) => `Économisez jusqu’à ${amountWithCurrency}/mois par membre actif`,
             automaticallyIncrease:
                 'Augmenter automatiquement vos licences annuelles pour tenir compte des membres actifs dépassant la taille de votre abonnement. Remarque : cela prolongera la date de fin de votre abonnement annuel.',
             disableAutoRenew: 'Désactiver le renouvellement automatique',
             helpUsImprove: 'Aidez-nous à améliorer Expensify',
             whatsMainReason: 'Quelle est la principale raison pour laquelle vous désactivez le renouvellement automatique ?',
-            renewsOn: (date: string) => `Se renouvelle le ${date}.`,
-            pricingConfiguration: 'Le prix dépend de la configuration. Pour le prix le plus bas, choisissez un abonnement annuel et obtenez la Carte Expensify.',
-            learnMore: (hasAdminsRoom: boolean) =>
+            renewsOn: ({date}: SubscriptionSettingsRenewsOnParams) => `Se renouvelle le ${date}.`,
+            pricingConfiguration: 'Le prix dépend de la configuration. Pour obtenir le tarif le plus bas, choisissez un abonnement annuel et commandez la carte Expensify.',
+            learnMore: ({hasAdminsRoom}: SubscriptionSettingsLearnMoreParams) =>
                 `<muted-text>En savoir plus sur notre <a href="${CONST.PRICING}">page des tarifs</a> ou discutez avec notre équipe dans votre ${hasAdminsRoom ? `<a href="adminsRoom">Salon #admins.</a>` : 'Salon #admins.'}</muted-text>`,
             estimatedPrice: 'Prix estimé',
-            changesBasedOn: 'Cela varie en fonction de votre utilisation de la Carte Expensify et des options d’abonnement ci-dessous.',
-            collectBillingDescription: 'Les espaces de travail Collect sont facturés mensuellement par membre, sans engagement annuel.',
-            pricing: 'Tarification',
+            changesBasedOn: 'Cela change en fonction de votre utilisation de la carte Expensify et des options d’abonnement ci-dessous.',
         },
-        cancelSubscription: {
-            title: "Annuler l'abonnement",
-            subtitle: 'Quelle est la principale raison pour laquelle vous souhaitez résilier votre abonnement ?',
+        requestEarlyCancellation: {
+            title: 'Demander une résiliation anticipée',
+            subtitle: 'Quelle est la principale raison pour laquelle vous demandez une résiliation anticipée ?',
             subscriptionCanceled: {
                 title: 'Abonnement annulé',
                 subtitle: 'Votre abonnement annuel a été annulé.',
                 info: 'Si vous souhaitez continuer à utiliser votre/vos espace(s) de travail à l’utilisation, tout est prêt.',
-                preventFutureActivity: (workspacesListRoute: string) =>
+                preventFutureActivity: ({workspacesListRoute}: WorkspacesListRouteParams) =>
                     `Si vous souhaitez empêcher toute activité et tout prélèvement futurs, vous devez <a href="${workspacesListRoute}">supprimer votre/vos espace(s) de travail</a>. Notez que lorsque vous supprimez votre/vos espace(s) de travail, vous serez facturé pour toute activité en cours survenue durant le mois civil en cours.`,
             },
             requestSubmitted: {
@@ -9398,7 +8125,7 @@ Ajoutez davantage de règles de dépenses pour protéger la trésorerie de l’e
                 subtitle:
                     'Merci de nous avoir informés que vous souhaitez résilier votre abonnement. Nous examinons votre demande et nous vous contacterons bientôt via votre discussion avec <concierge-link>Concierge</concierge-link>.',
             },
-            acknowledgement: `En demandant une résiliation, je reconnais et j’accepte qu’Expensify n’a aucune obligation d’accéder à une telle demande en vertu des <a href=${CONST.OLD_DOT_PUBLIC_URLS.TERMS_URL}>Conditions d’utilisation</a> d’Expensify ou de tout autre contrat de services applicable entre Expensify et moi, et qu’Expensify conserve toute latitude quant à l’acceptation ou non de cette demande.`,
+            acknowledgement: `En demandant une résiliation anticipée, je reconnais et j’accepte qu’Expensify n’a aucune obligation d’accéder à une telle demande en vertu des <a href=${CONST.OLD_DOT_PUBLIC_URLS.TERMS_URL}>Conditions d’utilisation</a> d’Expensify ou de tout autre contrat de services applicable entre Expensify et moi, et qu’Expensify conserve toute latitude quant à l’acceptation ou non de cette demande.`,
         },
     },
     feedbackSurvey: {
@@ -9419,12 +8146,9 @@ Ajoutez davantage de règles de dépenses pour protéger la trésorerie de l’e
         switchAccount: 'Changer de compte :',
         copilotDelegatedAccess: 'Copilot : Accès délégué',
         copilotDelegatedAccessDescription: 'Autoriser les autres membres à accéder à votre compte.',
-        learnMoreAboutDelegatedAccess: "En savoir plus sur l'accès délégué",
         addCopilot: 'Ajouter un copilote',
-        switch: 'Changer',
-        copilot: 'Copilot',
         membersCanAccessYourAccount: 'Ces membres peuvent accéder à votre compte :',
-        youCanAccessTheseAccounts: 'Vous pouvez accéder à ces comptes :',
+        youCanAccessTheseAccounts: 'Vous pouvez accéder à ces comptes via le sélecteur de compte :',
         role: ({role}: OptionalParam<DelegateRoleParams> = {}) => {
             switch (role) {
                 case CONST.DELEGATE_ROLE.ALL:
@@ -9543,7 +8267,6 @@ Ajoutez davantage de règles de dépenses pour protéger la trésorerie de l’e
             theresWasAProblemDuringAWorkspaceConnectionSync: 'Un problème est survenu lors de la synchronisation de connexion de l’espace de travail',
             theresAProblemWithYourWallet: 'Il y a un problème avec votre portefeuille',
             theresAProblemWithYourWalletTerms: 'Il y a un problème avec les conditions de votre portefeuille',
-            aBankAccountIsLocked: 'Un compte bancaire est verrouillé',
         },
     },
     emptySearchView: {
@@ -9564,10 +8287,15 @@ Ajoutez davantage de règles de dépenses pour protéger la trésorerie de l’e
         conciergeLHNGBR: '<tooltip>Commencez <strong>ici&nbsp;!</strong></tooltip>',
         saveSearchTooltip: '<tooltip><strong>Renommez vos recherches enregistrées</strong> ici !</tooltip>',
         accountSwitcher: '<tooltip>Accédez à vos <strong>comptes Copilot</strong> ici</tooltip>',
+        scanTestTooltip: {
+            main: '<tooltip><strong>Scannez notre reçu de test</strong> pour voir comment ça marche !</tooltip>',
+            manager: '<tooltip>Choisissez notre <strong>responsable des tests</strong> pour l’essayer&nbsp;!</tooltip>',
+            confirmation: '<tooltip>Maintenant, <strong>soumettez votre dépense</strong> et regardez la magie opérer&nbsp;!</tooltip>',
+            tryItOut: 'Essayer',
+        },
         outstandingFilter: '<tooltip>Filtrer les dépenses\nqui <strong>doivent être approuvées</strong></tooltip>',
         scanTestDriveTooltip: '<tooltip>Envoyez ce reçu pour\n<strong>terminer l’essai !</strong></tooltip>',
         gpsTooltip: '<tooltip>Suivi GPS en cours ! Lorsque vous avez terminé, arrêtez le suivi ci-dessous.</tooltip>',
-        hasFilterNegation: '<tooltip>Recherchez les dépenses sans reçus à l’aide de <strong>-has:receipt</strong>.</tooltip>',
     },
     discardChangesConfirmation: {
         title: 'Ignorer les modifications ?',
@@ -9583,7 +8311,7 @@ Ajoutez davantage de règles de dépenses pour protéger la trésorerie de l’e
         confirmation: {
             title: 'Confirmer l’appel',
             description: 'Assurez-vous que les détails ci-dessous vous conviennent. Une fois que vous aurez confirmé l’appel, nous enverrons une invitation avec plus d’informations.',
-            setupSpecialist: 'Votre chargé de compte',
+            setupSpecialist: 'Votre spécialiste de configuration',
             meetingLength: 'Durée de la réunion',
             dateTime: 'Date et heure',
             minutes: '30 minutes',
@@ -9631,20 +8359,6 @@ Voici un *reçu test* pour vous montrer comment ça fonctionne :`,
         exportInProgress: 'Export en cours',
         conciergeWillSend: 'Concierge vous enverra le fichier sous peu.',
     },
-    exportDownload: {
-        preparingTitle: 'Preparing download...',
-        preparingBody: 'You can either wait for the download to finish or Concierge can send it to you via chat.',
-        sendFromConcierge: "Send me the file when it's ready",
-        conciergeTitle: 'You bet!',
-        conciergeBody: 'Concierge will send you a message when the file is ready.',
-        goToConcierge: 'Go to Concierge',
-        dismiss: 'Dismiss',
-        readyTitle: 'Your file is ready!',
-        readyBody: "If it didn't automatically download, use the button below.",
-        downloadFile: 'Download file',
-        failedTitle: 'Export failed',
-        close: 'Close',
-    },
     domain: {
         notVerified: 'Non vérifié',
         retry: 'Réessayer',
@@ -9678,7 +8392,7 @@ Voici un *reçu test* pour vous montrer comment ça fonctionne :`,
         goToDomain: 'Aller au domaine',
         samlLogin: {
             title: 'Connexion SAML',
-            subtitle: `<muted-text>Configurer la connexion des membres avec la <a href="${CONST.SAML_HELP_URL}">connexion unique SAML (SSO)</a>.</muted-text>`,
+            subtitle: `<muted-text>Configurer la connexion des membres avec la <a href="${CONST.SAML_HELP_URL}">connexion unique SAML (SSO).</a></muted-text>`,
             enableSamlLogin: 'Activer la connexion SAML',
             allowMembers: 'Autoriser les membres à se connecter avec SAML.',
             requireSamlLogin: 'Exiger la connexion SAML',
@@ -9688,8 +8402,6 @@ Voici un *reçu test* pour vous montrer comment ça fonctionne :`,
             disableSamlRequired: 'Désactiver SAML obligatoire',
             oktaWarningPrompt: 'Voulez-vous continuer ? Cela désactivera également Okta SCIM.',
             requireWithEmptyMetadataError: "Veuillez ajouter ci-dessous les métadonnées du fournisseur d'identité pour activer",
-            pleaseDisableTwoFactorAuth: (twoFactorAuthSettingsUrl: string) =>
-                `<muted-text>Désactivez <a href="${twoFactorAuthSettingsUrl}">forcer l’authentification à deux facteurs</a> pour activer la connexion SAML.</muted-text>`,
         },
         samlConfigurationDetails: {
             title: 'Détails de configuration SAML',
@@ -9739,6 +8451,7 @@ Voici un *reçu test* pour vous montrer comment ça fonctionne :`,
             primaryContact: 'Contact principal',
             addPrimaryContact: 'Ajouter un contact principal',
             setPrimaryContactError: 'Impossible de définir le contact principal. Veuillez réessayer plus tard.',
+            settings: 'Paramètres',
             consolidatedDomainBilling: 'Facturation de domaine consolidée',
             consolidatedDomainBillingDescription: (domainName: string) =>
                 `<comment><muted-text-label>Lorsque cette option est activée, le contact principal paiera pour tous les espaces de travail appartenant aux membres de <strong>${domainName}</strong> et recevra tous les reçus de facturation.</muted-text-label></comment>`,
@@ -9755,111 +8468,25 @@ Voici un *reçu test* pour vous montrer comment ça fonctionne :`,
             resetDomain: 'Réinitialiser le domaine',
             resetDomainExplanation: ({domainName}: {domainName?: string}) => `Veuillez saisir <strong>${domainName}</strong> pour confirmer la réinitialisation du domaine.`,
             enterDomainName: 'Saisissez votre nom de domaine ici',
-            resetDomainInfo: `Cette action est <strong>définitive</strong> et les données suivantes seront supprimées : <br/> <bullet-list><bullet-item>Connexions aux cartes d’entreprise et toutes les dépenses non encore déclarées associées à ces cartes</bullet-item><bullet-item>Paramètres SAML et de groupe</bullet-item><bullet-item>Données de voyage et accès à Expensify Travel</bullet-item></bullet-list> Tous les comptes, espaces de travail, rapports, dépenses et autres données resteront. <br/><br/>Remarque : Vous pouvez supprimer ce domaine de votre liste de domaines en retirant l’adresse e-mail associée de vos <a href="#">moyens de contact</a>.`,
+            resetDomainInfo: `Cette action est <strong>définitive</strong> et les données suivantes seront supprimées : <br/> <ul><li>Connexions de cartes d’entreprise et toutes les dépenses non déclarées associées à ces cartes</li> <li>Paramètres SAML et de groupe</li> </ul> Tous les comptes, espaces de travail, notes de frais, dépenses et autres données seront conservés. <br/><br/>Remarque : vous pouvez supprimer ce domaine de votre liste de domaines en retirant l’adresse e-mail associée de vos <a href="#">méthodes de contact</a>.`,
         },
         domainMembers: 'Membres du domaine',
         members: {
             title: 'Membres',
             findMember: 'Trouver un membre',
             addMember: 'Ajouter un membre',
-            allMembers: 'Tous les membres',
             email: 'Adresse e-mail',
-            closeAccount: () => ({
-                one: 'Fermer le compte',
-                other: 'Fermer les comptes',
-            }),
+            closeAccount: 'Fermer le compte',
             closeAccountPrompt: 'Êtes-vous sûr(e) ? Cette action est définitive.',
-            forceCloseAccount: () => ({one: 'Forcer la fermeture du compte', other: 'Forcer la fermeture des comptes'}),
-            safeCloseAccount: () => ({
-                one: 'Fermer le compte en toute sécurité',
-                other: 'Fermer les comptes en toute sécurité',
-            }),
-            closeAccountInfo: () => ({
-                one: 'Nous recommandons de fermer le compte en toute sécurité afin d’éviter de le fermer dans le cas où il y aurait : <bullet-list><bullet-item>Des validations en attente</bullet-item><bullet-item>Des remboursements actifs</bullet-item><bullet-item>Aucune autre méthode de connexion</bullet-item></bullet-list>Sinon, vous pouvez ignorer les précautions de sécurité ci-dessus et forcer la fermeture du compte sélectionné.',
-                other: 'Nous recommandons de fermer les comptes en toute sécurité afin d’éviter de les fermer dans le cas où il y aurait : <bullet-list><bullet-item>Des validations en attente</bullet-item><bullet-item>Des remboursements actifs</bullet-item><bullet-item>Aucune autre méthode de connexion</bullet-item></bullet-list>Sinon, vous pouvez ignorer les précautions de sécurité ci-dessus et forcer la fermeture des comptes sélectionnés.',
-            }),
+            forceCloseAccount: 'Forcer la fermeture du compte',
+            safeCloseAccount: 'Fermer le compte en toute sécurité',
+            closeAccountInfo:
+                'Nous recommandons de fermer le compte en toute sécurité afin d’éviter de le fermer dans le cas où il y aurait : <ul><li>Des validations en attente</li><li>Des remboursements actifs</li><li>Aucune autre méthode de connexion</li></ul>Sinon, vous pouvez ignorer les précautions de sécurité ci-dessus et forcer la fermeture du compte sélectionné.',
             error: {
                 removeMember: 'Impossible de supprimer cet utilisateur. Veuillez réessayer.',
                 addMember: 'Impossible d’ajouter ce membre. Veuillez réessayer.',
-                vacationDelegate: 'Impossible de définir cet utilisateur comme délégué de vacances. Veuillez réessayer.',
-                moveMember: 'Impossible de déplacer ce membre. Veuillez réessayer.',
-                moveMemberNotPolicyAdmin:
-                    'Impossible de déplacer le membre vers le groupe de domaine. Vous devez être Administrateur de Politique pour la Politique Préférée définie sur le groupe de domaine vers lequel vous essayez de déplacer cet utilisateur.',
-            },
-            cannotSetVacationDelegateForMember: (email: string) =>
-                `Vous ne pouvez pas définir un délégué de vacances pour ${email}, car cette personne est actuellement le délégué des membres suivants :`,
-            reportSuspiciousActivityPrompt: (email: string) =>
-                `Voulez-vous continuer ? Cela va verrouiller le compte de <strong>${email}</strong>. <br /><br /> Notre équipe examinera ensuite le compte et supprimera tout accès non autorisé. Pour retrouver l’accès, il faudra collaborer avec Concierge.`,
-            reportSuspiciousActivityConfirmationPrompt:
-                'Nous examinerons le compte pour vérifier qu’il est sûr de le déverrouiller et nous vous contacterons via Concierge si nous avons des questions.',
-            emptyMembers: {title: 'Aucun membre dans ce groupe', subtitle: 'Ajoutez un membre ou essayez de modifier le filtre ci-dessus.'},
-            moveToGroup: 'Déplacer vers le groupe',
-            chooseWhereToMove: ({count}: {count: number}) => `Choisissez où déplacer ${count} ${count === 1 ? 'membre' : 'membres'}.`,
-            domainGroup: 'Groupe de domaines',
-            chooseWhereToMoveName: ({name}: {name: string}) => `Choisissez où déplacer ${name}.`,
-            membersFeatureList: {
-                subtitle: ({domainName}: {domainName: string}) =>
-                    `<muted-text>Vérifiez votre domaine pour mieux contrôler les membres de <strong>${domainName}</strong> dans Expensify.</muted-text>`,
-                controlPolicyCreation: "Restreindre la création d'espaces de travail",
-                enableSamlSso: 'Activer SAML SSO',
-                enforce2FA: 'Imposer la 2FA',
             },
         },
-        common: {
-            settings: 'Paramètres',
-            forceTwoFactorAuth: 'Imposer l’authentification à deux facteurs',
-            forceTwoFactorAuthSAMLEnabledDescription: (samlPageUrl: string) =>
-                `<muted-text>Veuillez désactiver <a href="${samlPageUrl}">SAML</a> pour imposer l’authentification à deux facteurs.</muted-text>`,
-            forceTwoFactorAuthDescription: `<muted-text>Exiger l’authentification à deux facteurs pour tous les membres de ce domaine. Les membres du domaine seront invités à configurer l’authentification à deux facteurs sur leur compte lorsqu’ils se connectent.</muted-text>`,
-            forceTwoFactorAuthError: 'L’activation forcée de l’authentification à deux facteurs n’a pas pu être modifiée. Veuillez réessayer plus tard.',
-            resetTwoFactorAuth: 'Réinitialiser l’authentification à deux facteurs',
-            error: 'Impossible d\’enregistrer cette modification. Veuillez réessayer.',
-        },
-        groups: {
-            title: 'Groupes',
-            memberCount: () => ({one: '1 membre', other: (count: number) => `${count} membres`}),
-            defaultGroup: 'Groupe par défaut pour les nouveaux membres',
-            defaultGroupPrompt: (currentName: string, newName: string) =>
-                `Êtes-vous sûr de vouloir faire de ${newName} le groupe par défaut ? Les nouveaux membres seront invités à ce groupe au lieu du groupe par défaut précédent (${currentName}). `,
-            makeDefault: 'Définir par défaut',
-            neverMind: 'Peu importe',
-            createGroupError: 'Impossible de créer ce groupe. Veuillez réessayer.',
-            permissions: 'Autorisations du groupe',
-            createNewGroupButton: 'Nouveau groupe',
-            createGroupSubmitButton: 'Créer le groupe',
-            expensifyCardPreferredWorkspace: 'Espace de travail préféré pour la carte Expensify',
-            expensifyCardPreferredWorkspaceDescription:
-                "Toutes les transactions Expensify Card seront créées dans l'espace de travail préféré Expensify Card au lieu de l'espace de travail préféré.",
-            strictlyEnforceWorkspaceRules: 'Appliquer strictement les règles de l’espace de travail',
-            strictlyEnforceWorkspaceRulesDescription:
-                'Toutes les règles de l’espace de travail doivent être respectées avant de soumettre un rapport. Aucune exception manuelle n’est autorisée.',
-            restrictExpenseWorkspaceCreation: 'Restreindre la création/suppression d’espaces de travail de dépenses',
-            restrictExpenseWorkspaceCreationDescription:
-                'Empêchez les membres de pouvoir créer un espace de travail de dépenses ou de se retirer d’un espace de travail de dépenses. Ceci est utile pour empêcher les gens d’utiliser Expensify afin de soumettre des rapports destinés à un usage hors de votre domaine, lorsqu’il est combiné à une application stricte des espaces de travail.',
-            deleteGroup: 'Supprimer le groupe',
-            deleteGroupDangerConfirmationModal: 'Supprimer le groupe',
-            deleteGroupDangerConfirmationModalDescription: (defaultGroupName: string) =>
-                `Êtes-vous sûr ? Cela réaffectera tous les membres au groupe par défaut (${defaultGroupName}) et ne pourra pas être annulé.`,
-            deleteGroupError: 'Impossible de supprimer ce groupe. Veuillez réessayer.',
-            preferredWorkspace: 'Espace de travail préféré',
-            preferredWorkspaceDescription: (enabled: boolean) =>
-                `Tous les nouveaux rapports et dépenses seront créés dans ${enabled ? "l'espace de travail préféré sélectionné" : 'cet espace de travail'}.`,
-            preferredWorkspaceSelectDescription: 'Toutes les nouvelles dépenses et tous les nouveaux rapports seront créés dans cet espace de travail.',
-            noWorkspacesMessage: "Il n'y a aucun espace de travail sur ce domaine. Un espace de travail est requis pour activer cette restriction.",
-            restrictDefaultLoginSelection: 'Restreindre la sélection de connexion par défaut',
-            restrictDefaultLoginSelectionDescription:
-                'Empêche les membres de modifier leur e-mail de connexion en dehors du domaine de leur entreprise afin d’éviter les restrictions de politique.',
-            expensifyCardPreferredWorkspaceDisabledMessage:
-                'Pour activer ce paramètre, veuillez d’abord activer un espace de travail préféré et configurer les cartes Expensify sur votre domaine.',
-            findGroup: 'Trouver un groupe',
-        },
-    },
-    proactiveAppReview: {
-        title: 'Vous appréciez le nouveau Expensify ?',
-        description: 'Faites-le-nous savoir afin que nous puissions rendre votre expérience de gestion de notes de frais encore meilleure.',
-        positiveButton: 'Oui !',
-        negativeButton: 'Pas vraiment',
-    },
-    monthPickerPage: {month: 'Mois', selectMonth: 'Veuillez sélectionner un mois'},
+    },
 };
 export default translations;
diff --git a/src/languages/it.ts b/src/languages/it.ts
index c257f5e04100..96cdb08c82b4 100644
--- a/src/languages/it.ts
+++ b/src/languages/it.ts
@@ -11,52 +11,189 @@
  */
 import {CONST as COMMON_CONST} from 'expensify-common';
 import startCase from 'lodash/startCase';
-import type {ValueOf} from 'type-fest';
 import type {OnboardingTask} from '@libs/actions/Welcome/OnboardingFlow';
 import StringUtils from '@libs/StringUtils';
 import dedent from '@libs/StringUtils/dedent';
 import CONST from '@src/CONST';
 import type {Country} from '@src/CONST';
 import type OriginalMessage from '@src/types/onyx/OriginalMessage';
-import type {OriginalMessageSettlementAccountLocked, PersonalRulesModifiedFields, PolicyRulesModifiedFields} from '@src/types/onyx/OriginalMessage';
+import type {OriginalMessageSettlementAccountLocked, PolicyRulesModifiedFields} from '@src/types/onyx/OriginalMessage';
+import ObjectUtils from '@src/types/utils/ObjectUtils';
 import type en from './en';
 import type {
+    AddBudgetParams,
+    AddedOrDeletedPolicyReportFieldParams,
+    AddOrDeletePolicyCustomUnitRateParams,
     ChangeFieldParams,
-    ConciergeBrokenCardConnectionParams,
     ConnectionNameParams,
+    CreatedReportForUnapprovedTransactionsParams,
     DelegateRoleParams,
     DeleteActionParams,
+    DeleteBudgetParams,
     DeleteConfirmationParams,
     EditActionParams,
     ExportAgainModalDescriptionParams,
     ExportIntegrationSelectedParams,
+    ImportPolicyCustomUnitRatesParams,
     IntacctMappingTitleParams,
     InvalidPropertyParams,
     InvalidValueParams,
     MarkReimbursedFromIntegrationParams,
     MissingPropertyParams,
     MovedFromPersonalSpaceParams,
+    MultifactorAuthenticationTranslationParams,
+    NextStepParams,
     NotAllowedExtensionParams,
     OptionalParam,
     PaidElsewhereParams,
     ParentNavigationSummaryParams,
     RemovedFromApprovalWorkflowParams,
+    RemovedPolicyCustomUnitSubRateParams,
     ReportArchiveReasonsClosedParams,
     ReportArchiveReasonsInvoiceReceiverPolicyDeletedParams,
     ReportArchiveReasonsMergedParams,
     ReportArchiveReasonsRemovedFromPolicyParams,
+    ReportFieldParams,
+    ReportPolicyNameParams,
+    RequestAmountParams,
+    RequiredFieldParams,
     ResolutionConstraintsParams,
+    ReviewParams,
+    RoleNamesParams,
+    RoomNameReservedErrorParams,
+    RoomRenamedToParams,
+    RoutedDueToDEWParams,
+    RulesEnableWorkflowsParams,
+    SecondaryLoginParams,
+    SetTheDistanceMerchantParams,
+    SetTheRequestParams,
+    SettledAfterAddedBankAccountParams,
+    SettleExpensifyCardParams,
+    SettlementAccountInfoParams,
+    SettlementAccountReconciliationParams,
+    SettlementDateParams,
     ShareParams,
+    SignerInfoMessageParams,
+    SignUpNewFaceCodeParams,
     SizeExceededParams,
+    SplitAmountParams,
+    SplitDateRangeParams,
+    SplitExpenseEditTitleParams,
+    SplitExpenseSubtitleParams,
+    StatementTitleParams,
     StepCounterParams,
+    StripePaidParams,
+    SubmitsToParams,
+    SubmittedToVacationDelegateParams,
+    SubmittedWithMemoParams,
+    SubscriptionCommitmentParams,
+    SubscriptionSettingsLearnMoreParams,
+    SubscriptionSettingsRenewsOnParams,
+    SubscriptionSettingsSaveUpToParams,
+    SubscriptionSettingsSummaryParams,
+    SubscriptionSizeParams,
     SyncStageNameConnectionsParams,
+    TaskCreatedActionParams,
+    TaxAmountParams,
+    TermsParams,
+    ThreadRequestReportNameParams,
+    ThreadSentMoneyReportNameParams,
+    ToggleImportTitleParams,
+    TotalAmountGreaterOrLessThanOriginalParams,
+    ToValidateLoginParams,
+    TransferParams,
+    TravelTypeParams,
+    TrialStartedTitleParams,
+    UnapproveWithIntegrationWarningParams,
     UnshareParams,
-    UnsupportedFormulaValueErrorParams,
+    UntilTimeParams,
+    UpdatedBudgetParams,
+    UpdatedCustomFieldParams,
+    UpdatedPolicyApprovalRuleParams,
+    UpdatedPolicyAuditRateParams,
+    UpdatedPolicyAutoHarvestingParams,
+    UpdatedPolicyBudgetNotificationParams,
+    UpdatedPolicyCategoriesParams,
+    UpdatedPolicyCategoryDescriptionHintTypeParams,
+    UpdatedPolicyCategoryExpenseLimitTypeParams,
+    UpdatedPolicyCategoryGLCodeParams,
+    UpdatedPolicyCategoryMaxAmountNoReceiptParams,
+    UpdatedPolicyCategoryMaxExpenseAmountParams,
+    UpdatedPolicyCategoryNameParams,
+    UpdatedPolicyCategoryParams,
+    UpdatedPolicyCurrencyParams,
+    UpdatedPolicyCustomUnitRateEnabledParams,
+    UpdatedPolicyCustomUnitRateParams,
+    UpdatedPolicyCustomUnitSubRateParams,
+    UpdatedPolicyCustomUnitTaxClaimablePercentageParams,
+    UpdatedPolicyCustomUnitTaxRateExternalIDParams,
+    UpdatedPolicyDefaultTitleParams,
+    UpdatedPolicyDescriptionParams,
+    UpdatedPolicyFieldWithNewAndOldValueParams,
+    UpdatedPolicyFieldWithValueParams,
+    UpdatedPolicyFrequencyParams,
+    UpdatedPolicyManualApprovalThresholdParams,
+    UpdatedPolicyOwnershipParams,
+    UpdatedPolicyPreventSelfApprovalParams,
+    UpdatedPolicyReimbursementChoiceParams,
+    UpdatedPolicyReimbursementEnabledParams,
+    UpdatedPolicyReimburserParams,
+    UpdatedPolicyReportFieldDefaultValueParams,
+    UpdatedPolicyTagFieldParams,
+    UpdatedPolicyTagListParams,
+    UpdatedPolicyTagListRequiredParams,
+    UpdatedPolicyTagNameParams,
+    UpdatedPolicyTagParams,
+    UpdatedPolicyTaxParams,
+    UpdatedPolicyTimeEnabledParams,
+    UpdatedPolicyTimeRateParams,
+    UpdatedTheDistanceMerchantParams,
+    UpdatedTheRequestParams,
+    UpdatePolicyCustomUnitDefaultCategoryParams,
+    UpdatePolicyCustomUnitParams,
+    UpdatePolicyCustomUnitTaxEnabledParams,
     UpdateRoleParams,
-    ViolationsIncreasedDistanceParams,
+    UpgradeSuccessMessageParams,
+    UsePlusButtonParams,
+    UserIsAlreadyMemberParams,
+    UserSplitParams,
+    VacationDelegateParams,
+    ViolationsCashExpenseWithNoReceiptParams,
+    ViolationsConversionSurchargeParams,
+    ViolationsCustomRulesParams,
+    ViolationsInvoiceMarkupParams,
+    ViolationsMaxAgeParams,
+    ViolationsMissingTagParams,
     ViolationsModifiedAmountParams,
+    ViolationsOverCategoryLimitParams,
+    ViolationsOverLimitParams,
+    ViolationsPerDayLimitParams,
+    ViolationsProhibitedExpenseParams,
+    ViolationsReceiptRequiredParams,
+    ViolationsRterParams,
+    ViolationsTagOutOfPolicyParams,
+    ViolationsTaxOutOfPolicyParams,
+    WaitingOnBankAccountParams,
+    WalletAgreementParams,
+    WalletProgramParams,
+    WelcomeEnterMagicCodeParams,
+    WelcomeToRoomParams,
+    WeSentYouMagicSignInLinkParams,
+    WorkEmailMergingBlockedParams,
+    WorkEmailResendCodeParams,
+    WorkflowSettingsParam,
     WorkspaceLockedPlanTypeParams,
+    WorkspaceMemberList,
+    WorkspaceMembersCountParams,
+    WorkspaceOwnerWillNeedToAddOrUpdatePaymentCardParams,
+    WorkspaceRouteParams,
+    WorkspaceShareNoteParams,
+    WorkspacesListRouteParams,
+    WorkspaceUpgradeNoteParams,
+    WorkspaceYouMayJoin,
     YourPlanPriceParams,
+    YourPlanPriceValueParams,
+    ZipCodeExampleFormatParams,
 } from './params';
 import type {TranslationDeepObject} from './types';
 
@@ -90,10 +227,8 @@ const translations: TranslationDeepObject<typeof en> = {
         optional: 'Facoltativo',
         new: 'Nuovo',
         newFeature: 'Nuova funzionalità',
-        beta: 'Beta',
         search: 'Cerca',
         reports: 'Report',
-        spend: 'Spese',
         find: 'Trova',
         searchWithThreeDots: 'Cerca...',
         next: 'Avanti',
@@ -118,14 +253,6 @@ const translations: TranslationDeepObject<typeof en> = {
         workspaces: 'Area di lavoro',
         home: 'Home',
         inbox: 'Posta in arrivo',
-        yourReviewIsRequired: 'È richiesta la tua revisione',
-        actionBadge: {
-            submit: 'Invia',
-            approve: 'Approva',
-            pay: 'Paga',
-            fix: 'Correggi',
-            task: 'Attività',
-        },
         success: 'Operazione riuscita',
         group: 'Gruppo',
         profile: 'Profilo',
@@ -135,7 +262,7 @@ const translations: TranslationDeepObject<typeof en> = {
         wallet: 'Portafoglio',
         preferences: 'Preferenze',
         view: 'Visualizza',
-        review: (amount?: string) => `Revisione${amount ? ` ${amount}` : ''}`,
+        review: (reviewParams?: ReviewParams) => `Revisione${reviewParams?.amount ? ` ${reviewParams?.amount}` : ''}`,
         not: 'Non',
         signIn: 'Accedi',
         signInWithGoogle: 'Accedi con Google',
@@ -146,7 +273,6 @@ const translations: TranslationDeepObject<typeof en> = {
         lastName: 'Cognome',
         scanning: 'Scansione',
         analyzing: 'Analisi in corso...',
-        thinking: 'Concierge sta pensando...',
         addCardTermsOfService: 'Termini di servizio di Expensify',
         perPerson: 'per persona',
         phone: 'Telefono',
@@ -208,12 +334,10 @@ const translations: TranslationDeepObject<typeof en> = {
         admin: 'Amministrazione',
         owner: 'Proprietario',
         dateFormat: 'YYYY-MM-DD',
-        calendarOpened: 'calendario aperto',
         send: 'Invia',
         na: 'N/D',
         noResultsFound: 'Nessun risultato trovato',
         noResultsFoundMatching: (searchString: string) => `Nessun risultato trovato per "${searchString}"`,
-        suggestionsAvailableFor: (searchString: string) => (searchString ? `Suggerimenti disponibili per "${searchString}".` : 'Suggerimenti disponibili.'),
         recentDestinations: 'Destinazioni recenti',
         timePrefix: 'È',
         conjunctionFor: 'per',
@@ -224,7 +348,6 @@ const translations: TranslationDeepObject<typeof en> = {
         conjunctionTo: 'a',
         genericErrorMessage: 'Ops... qualcosa è andato storto e la tua richiesta non può essere completata. Riprova più tardi.',
         percentage: 'Percentuale',
-        progressBarLabel: 'Progresso onboarding',
         converted: 'Convertito',
         error: {
             invalidAmount: 'Importo non valido',
@@ -263,7 +386,6 @@ const translations: TranslationDeepObject<typeof en> = {
         reset: 'Reimposta',
         done: 'Completato',
         more: 'Altro',
-        other: 'Altro',
         debitCard: 'Carta di debito',
         bankAccount: 'Conto bancario',
         personalBankAccount: 'Conto bancario personale',
@@ -289,7 +411,7 @@ const translations: TranslationDeepObject<typeof en> = {
         verify: 'Verifica',
         yesContinue: 'Sì, continua',
         websiteExample: 'es. https://www.expensify.com',
-        zipCodeExampleFormat: (zipSampleFormat: string) => (zipSampleFormat ? `ad es. ${zipSampleFormat}` : ''),
+        zipCodeExampleFormat: ({zipSampleFormat}: ZipCodeExampleFormatParams) => (zipSampleFormat ? `ad es. ${zipSampleFormat}` : ''),
         description: 'Descrizione',
         title: 'Titolo',
         assignee: 'Assegnatario',
@@ -300,8 +422,6 @@ const translations: TranslationDeepObject<typeof en> = {
         per: 'for',
         mi: 'miglio',
         km: 'chilometro',
-        milesAbbreviated: 'mi',
-        kilometersAbbreviated: 'km',
         copied: 'Copiato!',
         someone: 'Qualcuno',
         total: 'Totale',
@@ -310,7 +430,6 @@ const translations: TranslationDeepObject<typeof en> = {
         letsStart: `Iniziamo`,
         showMore: 'Mostra di più',
         showLess: 'Mostra meno',
-        plusMore: ({count}: {count: number}) => `+${count} altri`,
         merchant: 'Esercente',
         change: 'Modifica',
         category: 'Categoria',
@@ -334,11 +453,8 @@ const translations: TranslationDeepObject<typeof en> = {
         selectCurrency: 'Seleziona una valuta',
         selectSymbolOrCurrency: 'Seleziona un simbolo o una valuta',
         card: 'Carta',
-        mcc: 'MCC',
-        categoryGLCode: 'Codice CO categoria',
         whyDoWeAskForThis: 'Perché lo chiediamo?',
         required: 'Obbligatorio',
-        automatic: 'Automatico',
         showing: 'Mostrando',
         of: 'di',
         default: 'Predefinito',
@@ -346,8 +462,6 @@ const translations: TranslationDeepObject<typeof en> = {
         member: 'Membro',
         auditor: 'Revisore',
         role: 'Ruolo',
-        roleCannotBeChanged: (workflowsLinkPage: string) =>
-            `Il ruolo non può essere modificato perché questo membro è un <a href="${workflowsLinkPage}">pagatore</a> in questo spazio di lavoro.`,
         currency: 'Valuta',
         groupCurrency: 'Valuta del gruppo',
         rate: 'Valuta',
@@ -385,7 +499,6 @@ const translations: TranslationDeepObject<typeof en> = {
         reportID: 'ID report',
         longReportID: 'ID report dettagliato',
         withdrawalID: 'ID prelievo',
-        withdrawalStatus: 'Stato del prelievo',
         bankAccounts: 'Conti bancari',
         chooseFile: 'Scegli file',
         chooseFiles: 'Scegli file',
@@ -419,21 +532,19 @@ const translations: TranslationDeepObject<typeof en> = {
         validate: 'Convalida',
         downloadAsPDF: 'Scarica come PDF',
         downloadAsCSV: 'Scarica come CSV',
-        print: 'Stampa',
         help: 'Aiuto',
-        collapsed: 'Comprresso',
-        expanded: 'Espanso',
         expenseReport: 'Nota spese',
-        rateOutOfPolicy: 'Tariffa fuori dalla policy',
+        expenseReports: 'Note spese',
+        rateOutOfPolicy: 'Tariffa fuori policy',
         leaveWorkspace: 'Esci dallo spazio di lavoro',
         leaveWorkspaceConfirmation: 'Se lasci questo spazio di lavoro, non potrai più inviarvi note spese.',
         leaveWorkspaceConfirmationAuditor: 'Se lasci questo spazio di lavoro, non potrai visualizzarne i report e le impostazioni.',
         leaveWorkspaceConfirmationAdmin: 'Se lasci questo spazio di lavoro, non potrai più gestirne le impostazioni.',
-        leaveWorkspaceConfirmationApprover: (workspaceOwner: string) =>
+        leaveWorkspaceConfirmationApprover: ({workspaceOwner}: {workspaceOwner: string}) =>
             `Se lasci questo spazio di lavoro, verrai sostituito nel flusso di approvazione da ${workspaceOwner}, il proprietario dello spazio di lavoro.`,
-        leaveWorkspaceConfirmationExporter: (workspaceOwner: string) =>
+        leaveWorkspaceConfirmationExporter: ({workspaceOwner}: {workspaceOwner: string}) =>
             `Se lasci questo spazio di lavoro, verrai sostituito come esportatore preferito con ${workspaceOwner}, il proprietario dello spazio di lavoro.`,
-        leaveWorkspaceConfirmationTechContact: (workspaceOwner: string) =>
+        leaveWorkspaceConfirmationTechContact: ({workspaceOwner}: {workspaceOwner: string}) =>
             `Se lasci questo workspace, verrai sostituito come referente tecnico con ${workspaceOwner}, il proprietario del workspace.`,
         leaveWorkspaceReimburser:
             'Non puoi lasciare questo spazio di lavoro come rimborsatore. Imposta un nuovo rimborsatore in Spazi di lavoro > Effettua o monitora pagamenti, quindi riprova.',
@@ -442,6 +553,9 @@ const translations: TranslationDeepObject<typeof en> = {
         comments: 'Commenti',
         sharedIn: 'Condiviso in',
         unreported: 'Non rendicontato',
+        explore: 'Esplora',
+        insights: 'Approfondimenti',
+        todo: 'Da fare',
         invoice: 'Fattura',
         expense: 'Spesa',
         chat: 'Chat',
@@ -452,15 +566,12 @@ const translations: TranslationDeepObject<typeof en> = {
         on: 'Attivo',
         before: 'Prima',
         after: 'Dopo',
-        range: 'Intervallo',
         reschedule: 'Ripianifica',
         general: 'Generale',
         workspacesTabTitle: 'Area di lavoro',
         headsUp: 'Attenzione!',
         submitTo: 'Invia a',
         forwardTo: 'Inoltra a',
-        approvalLimit: 'Limite di approvazione',
-        overLimitForwardTo: 'Inoltra se supera il limite',
         merge: 'Unisci',
         none: 'Nessuno',
         unstableInternetConnection: 'Connessione Internet instabile. Controlla la rete e riprova.',
@@ -481,44 +592,19 @@ const translations: TranslationDeepObject<typeof en> = {
         exchangeRate: 'Tasso di cambio',
         reimbursableTotal: 'Totale rimborsabile',
         nonReimbursableTotal: 'Totale non rimborsabile',
-        opensInNewTab: 'Si apre in una nuova scheda',
         locked: 'Bloccato',
         month: 'Mese',
         week: 'Settimana',
         year: 'Anno',
         quarter: 'Trimestre',
-        vacationDelegate: 'Delega ferie',
-        expensifyLogo: 'Logo Expensify',
-        concierge: {greeting: 'Ciao, come posso aiutarti?', showHistory: 'Mostra cronologia'},
-        duplicateReport: 'Report duplicato',
-        approver: 'Approvante',
-        goToConcierge: 'Vai a Concierge',
-        allSet: 'Tutto pronto!',
-        enterDigitLabel: ({digitIndex, totalDigits}: {digitIndex: number; totalDigits: number}) => `inserire la cifra ${digitIndex} di ${totalDigits}`,
-        copyOfReportName: (reportName: string) => `Copia di ${reportName}`,
-        previousMonth: 'Mese precedente',
-        nextMonth: 'Il prossimo mese',
-        previousYear: 'Anno precedente',
-        nextYear: "L'anno prossimo",
-        avatar: 'Avatar',
-        editor: 'Editor',
-        restrictions: 'Restrizioni',
-    },
-    socials: {
-        podcast: 'Seguici su Podcast',
-        twitter: 'Seguici su Twitter',
-        instagram: 'Seguici su Instagram',
-        facebook: 'Seguici su Facebook',
-        linkedin: 'Seguici su LinkedIn',
-    },
-    concierge: {
-        collapseReasoning: 'Comprimi ragionamento',
-        expandReasoning: 'Espandi ragionamento',
-        enableNotifications: {prompt: 'Vuoi ricevere una notifica quando Concierge risponde?', cta: 'Notifica'},
     },
     supportalNoAccess: {
         title: 'Non così in fretta',
-        descriptionWithCommand: (command?: string) =>
+        descriptionWithCommand: ({
+            command,
+        }: {
+            command?: string;
+        } = {}) =>
             `Non sei autorizzato a eseguire questa azione quando il supporto ha effettuato l’accesso (comando: ${command ?? ''}). Se ritieni che Success debba poter eseguire questa azione, avvia una conversazione in Slack.`,
     },
     lockedAccount: {
@@ -554,7 +640,7 @@ const translations: TranslationDeepObject<typeof en> = {
         chooseDocument: 'Scegli file',
         attachmentTooLarge: 'L’allegato è troppo grande',
         sizeExceeded: 'La dimensione dell’allegato supera il limite di 24 MB',
-        sizeExceededWithLimit: (maxUploadSizeInMB: number) => `La dimensione dell'allegato supera il limite di ${maxUploadSizeInMB} MB`,
+        sizeExceededWithLimit: ({maxUploadSizeInMB}: SizeExceededParams) => `La dimensione dell'allegato supera il limite di ${maxUploadSizeInMB} MB`,
         attachmentTooSmall: 'L’allegato è troppo piccolo',
         sizeNotMet: "La dimensione dell'allegato deve essere maggiore di 240 byte",
         wrongFileType: 'Tipo di file non valido',
@@ -565,9 +651,9 @@ const translations: TranslationDeepObject<typeof en> = {
         attachmentImageTooLarge: 'Questa immagine è troppo grande per essere visualizzata in anteprima prima del caricamento.',
         imageDimensionsTooLarge: "Le dimensioni dell'immagine sono troppo grandi per essere elaborate. Utilizza un'immagine più piccola.",
         tooManyFiles: (fileLimit: number) => `Puoi caricare al massimo ${fileLimit} file alla volta.`,
-        sizeExceededWithValue: (maxUploadSizeInMB: number) => `I file superano ${maxUploadSizeInMB} MB. Riprova.`,
+        sizeExceededWithValue: ({maxUploadSizeInMB}: SizeExceededParams) => `I file superano ${maxUploadSizeInMB} MB. Riprova.`,
         someFilesCantBeUploaded: 'Impossibile caricare alcuni file',
-        sizeLimitExceeded: (maxUploadSizeInMB: number) => `I file devono essere inferiori a ${maxUploadSizeInMB} MB. I file più grandi non verranno caricati.`,
+        sizeLimitExceeded: ({maxUploadSizeInMB}: SizeExceededParams) => `I file devono essere inferiori a ${maxUploadSizeInMB} MB. I file più grandi non verranno caricati.`,
         maxFileLimitExceeded: 'Puoi caricare fino a 30 ricevute alla volta. Le eventuali aggiuntive non verranno caricate.',
         unsupportedFileType: (fileType: string) => `I file ${fileType} non sono supportati. Verranno caricati solo i tipi di file supportati.`,
         learnMoreAboutSupportedFiles: 'Ulteriori informazioni sui formati supportati.',
@@ -607,55 +693,17 @@ const translations: TranslationDeepObject<typeof en> = {
         signIn: 'Accedi di nuovo.',
     },
     multifactorAuthentication: {
-        reviewTransaction: {
-            reviewTransaction: 'Verifica transazione',
-            pleaseReview: 'Esamina questa transazione',
-            requiresYourReview: 'Una transazione con Expensify Card richiede la tua revisione qui sotto.',
-            transactionDetails: 'Dettagli transazione',
-            deny: 'Nega',
-            approve: 'Approva',
-            denyTransaction: 'Rifiuta transazione',
-            transactionDenied: 'Transazione rifiutata',
-            transactionApproved: 'Transazione approvata!',
-            areYouSureToDeny: 'Sei sicuro? La transazione verrà rifiutata se chiudi questa schermata.',
-            youCanTryAgainAtMerchantOrReachOut:
-                'Puoi riprovare presso l’esercente. Se non hai effettuato tu questa transazione, <concierge-link>contatta Concierge</concierge-link> per segnalare un possibile uso fraudolento.',
-            youNeedToTryAgainAtMerchant: 'Questa transazione non è stata verificata, quindi l’abbiamo rifiutata. Dovrai riprovare direttamente presso l’esercente.',
-            goBackToTheMerchant: 'Torna al sito dell’esercente per continuare la transazione.',
-            attemptedTransaction: 'Transazione tentata',
-            transactionFailed: 'Transazione non riuscita',
-            transactionCouldNotBeCompleted: 'Impossibile completare la transazione. Riprova presso l’esercente.',
-            transactionCouldNotBeCompletedReachOut:
-                'La tua transazione non può essere completata. Se non hai tentato questa transazione, <concierge-link>contatta Concierge</concierge-link> per segnalare un possibile tentativo di frode.',
-            reviewFailed: 'Revisione non riuscita',
-            alreadyReviewedSubtitle:
-                'Hai già verificato questa transazione. Controlla la tua <transaction-history-link>cronologia transazioni</transaction-history-link> oppure contatta <concierge-link>Concierge</concierge-link> per segnalare eventuali problemi.',
-        },
         biometricsTest: {
             biometricsTest: 'Test biometrico',
             authenticationSuccessful: 'Autenticazione riuscita',
-            successfullyAuthenticatedUsing: (authType?: string) => `Hai effettuato l’autenticazione con successo usando ${authType}.`,
-            troubleshootBiometricsStatus: ({status}: {status?: string}) => `Dati biometrici (${status})`,
+            successfullyAuthenticatedUsing: ({authType}: MultifactorAuthenticationTranslationParams) => `Autenticazione completata correttamente tramite ${authType}.`,
+            troubleshootBiometricsStatus: ({registered}: MultifactorAuthenticationTranslationParams) => `Dati biometrici (${registered ? 'Registrato' : 'Non registrato'})`,
             yourAttemptWasUnsuccessful: 'Il tentativo di autenticazione non è andato a buon fine.',
             youCouldNotBeAuthenticated: 'Autenticazione non riuscita',
             areYouSureToReject: 'Sei sicuro? Il tentativo di autenticazione verrà rifiutato se chiudi questa schermata.',
             rejectAuthentication: 'Rifiuta autenticazione',
             test: 'Test',
             biometricsAuthentication: 'Autenticazione biometrica',
-            authType: {
-                unknown: 'Sconosciuto',
-                none: 'Nessuno',
-                credentials: 'Credenziali',
-                biometrics: 'Biometria',
-                faceId: 'Face ID',
-                touchId: 'Touch ID',
-                opticId: 'Optic ID',
-                passkey: 'Passkey',
-            },
-            statusNeverRegistered: 'Mai registrato',
-            statusNotRegistered: 'Non registrato',
-            statusRegisteredThisDevice: 'Registrato',
-            statusRegisteredOtherDevice: () => ({one: 'Un altro dispositivo registrato', other: 'Altri dispositivi registrati'}),
         },
         pleaseEnableInSystemSettings: {
             start: 'Abilita la verifica tramite volto/impronta digitale oppure imposta un codice di sblocco del dispositivo nel tuo',
@@ -668,43 +716,28 @@ const translations: TranslationDeepObject<typeof en> = {
         letsVerifyItsYou: 'Verifichiamo che sia tu',
         nowLetsAuthenticateYou: 'Ora procediamo con l’autenticazione...',
         letsAuthenticateYou: 'Autentichiamo la tua identità...',
-        verifyYourself: {biometrics: 'Verificati con il volto o l’impronta digitale', passkeys: 'Verificati con una passkey'},
+        verifyYourself: {
+            biometrics: 'Verificati con il volto o l’impronta digitale',
+        },
         enableQuickVerification: {
             biometrics: 'Attiva una verifica rapida e sicura utilizzando il volto o l’impronta digitale. Nessuna password o codice richiesto.',
-            passkeys: 'Abilita una verifica rapida e sicura usando una passkey. Nessuna password o codice richiesto.',
         },
         revoke: {
+            remove: 'Rimuovi',
             title: 'Volto/impronta digitale e passkey',
             explanation:
-                'La verifica tramite volto/impronta o passkey è attiva su uno o più dispositivi. Revocare l’accesso richiederà un codice magico per la prossima verifica su quel dispositivo.',
-            confirmationPrompt: 'Sei sicuro? Ti servirà un codice magico per la prossima verifica su quel dispositivo.',
+                'La verifica con volto/impronta digitale o passkey è abilitata su uno o più dispositivi. La revoca dell’accesso richiederà un codice magico per la prossima verifica su qualsiasi dispositivo.',
+            confirmationPrompt: 'Sei sicuro? Avrai bisogno di un codice magico per la prossima verifica su qualsiasi dispositivo.',
             cta: 'Revoca accesso',
             noDevices:
-                'Non hai alcun dispositivo registrato per il riconoscimento facciale/impronta digitale o la verifica tramite passkey. Se ne registri qualcuno, potrai revocare qui tale accesso.',
-            dismiss: 'Ricevuto',
+                'Non hai alcun dispositivo registrato per il riconoscimento facciale/impronta digitale o la verifica con passkey. Se ne registri uno, potrai revocare tale accesso qui.',
+            dismiss: 'Ho capito',
             error: 'Richiesta non riuscita. Riprova più tardi.',
-            revoke: 'Revoca',
-            confirmationPromptAll: 'Sei sicuro? Avrai bisogno di un codice magico per la prossima verifica su qualsiasi dispositivo.',
-            ctaAll: 'Revoca tutto',
-            thisDevice: 'Questo dispositivo',
-            otherDevices: (otherDeviceCount?: number) => {
-                const numberWords = ['Uno', 'Due', 'Tre', 'Quattro', 'Cinque', 'Sei', 'Sette', 'Otto', 'Nove'];
-                const displayCount = otherDeviceCount !== undefined && otherDeviceCount >= 1 && otherDeviceCount <= 9 ? numberWords.at(otherDeviceCount - 1) : `${otherDeviceCount}`;
-                return `${displayCount} altro ${otherDeviceCount === 1 ? 'dispositivo' : 'dispositivi'}`;
-            },
-            confirmationPromptThisDevice: 'Sei sicuro? Ti servirà un codice magico per la prossima verifica su questo dispositivo.',
-            confirmationPromptMultiple: 'Sei sicuro? Ti servirà un codice magico per la prossima verifica su quei dispositivi.',
         },
         unsupportedDevice: {
             unsupportedDevice: 'Dispositivo non supportato',
-            pleaseDownloadMobileApp: `Questa azione non è supportata sul tuo dispositivo. Scarica l'app Expensify dall'<a href="${CONST.APP_DOWNLOAD_LINKS.IOS}">App Store</a> o da <a href="${CONST.APP_DOWNLOAD_LINKS.ANDROID}">Google Play Store</a> e riprova.`,
-            pleaseUseWebApp: `Questa azione non è supportata sul tuo dispositivo. Utilizza l'<a href="${CONST.NEW_EXPENSIFY_URL}">app web Expensify</a> e riprova.`,
+            pleaseDownloadMobileApp: `<centered-text><muted-text> Questa azione non è supportata sul tuo dispositivo. Scarica l'app Expensify dall'<a href="${CONST.APP_DOWNLOAD_LINKS.IOS}">App Store</a> o da <a href="${CONST.APP_DOWNLOAD_LINKS.ANDROID}">Google Play Store</a> e riprova.</muted-text></centered-text>`,
         },
-        verificationFailed: 'Verifica non riuscita',
-        setPin: {didNotShipCard: 'Non abbiamo spedito la tua carta. Riprova.'},
-        revealPin: {couldNotReveal: 'Non siamo riusciti a mostrare il tuo PIN. Riprova.'},
-        changePin: {didNotChange: 'Non abbiamo modificato il tuo PIN. Riprova.'},
-        revealCardDetail: {couldNotReveal: 'Non siamo riusciti a mostrare i dettagli della tua carta. Riprova.'},
     },
     validateCodeModal: {
         successfulSignInTitle: dedent(`
@@ -718,7 +751,7 @@ const translations: TranslationDeepObject<typeof en> = {
             in cui è stato originariamente richiesto
         `),
         doNotShare: dedent(`
-            Non condividere il tuo codice con nessuno.
+            Non condividere il tuo codice con nessuno.  
             Expensify non te lo chiederà mai!
         `),
         or: ', oppure',
@@ -727,7 +760,7 @@ const translations: TranslationDeepObject<typeof en> = {
         expiredCodeDescription: 'Torna al dispositivo originale e richiedi un nuovo codice',
         successfulNewCodeRequest: 'Codice richiesto. Controlla il tuo dispositivo.',
         tfaRequiredTitle: dedent(`
-            Autenticazione a due fattori
+            Autenticazione a due fattori  
             obbligatoria
         `),
         tfaRequiredDescription: dedent(`
@@ -743,7 +776,11 @@ const translations: TranslationDeepObject<typeof en> = {
         nameEmailOrPhoneNumber: 'Nome, email o numero di telefono',
         findMember: 'Trova un membro',
         searchForSomeone: 'Cerca qualcuno',
-        userSelected: (username: string) => `${username} selezionato`,
+    },
+    customApprovalWorkflow: {
+        title: 'Flusso di approvazione personalizzato',
+        description: 'La tua azienda utilizza un flusso di approvazione personalizzato in questo spazio di lavoro. Esegui questa azione in Expensify Classic',
+        goToExpensifyClassic: 'Passa a Expensify Classic',
     },
     emptyList: {
         [CONST.IOU.TYPE.CREATE]: {
@@ -765,8 +802,8 @@ const translations: TranslationDeepObject<typeof en> = {
         phrase2: 'I soldi parlano. E ora che chat e pagamenti sono in un unico posto, è anche facile.',
         phrase3: 'I tuoi rimborsi arrivano veloci quanto riesci a farti capire.',
         enterPassword: 'Inserisci la tua password',
-        welcomeNewFace: (login: string) => `${login}, è sempre un piacere vedere un volto nuovo da queste parti!`,
-        welcomeEnterMagicCode: (login: string) => `Inserisci il codice magico inviato a ${login}. Dovrebbe arrivare entro uno o due minuti.`,
+        welcomeNewFace: ({login}: SignUpNewFaceCodeParams) => `${login}, è sempre un piacere vedere un volto nuovo da queste parti!`,
+        welcomeEnterMagicCode: ({login}: WelcomeEnterMagicCodeParams) => `Inserisci il codice magico inviato a ${login}. Dovrebbe arrivare entro uno o due minuti.`,
     },
     login: {
         hero: {
@@ -794,9 +831,6 @@ const translations: TranslationDeepObject<typeof en> = {
         emoji: 'Emoji',
         collapse: 'Comprimi',
         expand: 'Espandi',
-        askConciergeToUpdate: 'Prova con "Aggiorna una spesa"...',
-        askConciergeToCorrect: 'Prova con "Correggi una spesa"...',
-        askConciergeForHelp: 'Chiedi aiuto a Concierge AI...',
     },
     reportActionContextMenu: {
         copyMessage: 'Copia messaggio',
@@ -860,9 +894,9 @@ const translations: TranslationDeepObject<typeof en> = {
         askMeAnything: 'Chiedimi qualsiasi cosa!',
         sayHello: 'Di’ ciao!',
         yourSpace: 'Il tuo spazio',
-        welcomeToRoom: (roomName: string) => `Benvenuto in ${roomName}!`,
-        usePlusButton: (additionalText: string) => `Usa il pulsante + per ${additionalText} una spesa.`,
-        askConcierge: 'Concierge può rispondere alle domande, aggiornare le spese e altro ancora.',
+        welcomeToRoom: ({roomName}: WelcomeToRoomParams) => `Benvenuto in ${roomName}!`,
+        usePlusButton: ({additionalText}: UsePlusButtonParams) => `Usa il pulsante + per ${additionalText} una spesa.`,
+        askConcierge: 'Chiedimi qualsiasi cosa!',
         conciergeSupport: 'Il tuo agente IA personale',
         create: 'crea',
         iouTypes: {
@@ -874,17 +908,12 @@ const translations: TranslationDeepObject<typeof en> = {
         },
     },
     adminOnlyCanPost: 'Solo gli amministratori possono inviare messaggi in questa stanza.',
-    readOnlyConversation: 'Questa conversazione è di sola lettura.',
     reportAction: {
         asCopilot: 'come copilota per',
-        assistedBy: (agentName: string) => `assistito da ${agentName}`,
-        humanSupportAgent: 'un agente di supporto umano',
         harvestCreatedExpenseReport: (reportUrl: string, reportName: string) =>
             `ha creato questo report per raccogliere tutte le spese da <a href="${reportUrl}">${reportName}</a> che non potevano essere inviate con la frequenza scelta`,
-        createdReportForUnapprovedTransactions: (reportUrl: string, reportName: string, reportID: string, isReportDeleted: boolean) =>
-            isReportDeleted
-                ? `ha creato questo rendiconto per tutte le spese in sospeso dal rendiconto eliminato n. ${reportID}`
-                : `ha creato questo report per tutte le spese in sospeso da <a href="${reportUrl}">${reportName}</a>`,
+        createdReportForUnapprovedTransactions: ({reportUrl, reportName}: CreatedReportForUnapprovedTransactionsParams) =>
+            `ha creato questo report per tutte le spese in sospeso da <a href="${reportUrl}">${reportName}</a>`,
     },
     mentionSuggestions: {
         hereAlternateText: 'Notifica tutti in questa conversazione',
@@ -923,6 +952,7 @@ const translations: TranslationDeepObject<typeof en> = {
         buttonFind: 'Trova qualcosa...',
         buttonMySettings: 'Le mie impostazioni',
         fabNewChat: 'Avvia chat',
+        fabNewChatExplained: 'Apri il menu azioni',
         fabScanReceiptExplained: 'Scansiona ricevuta',
         chatPinned: 'Chat fissata',
         draftedMessage: 'Bozza di messaggio',
@@ -930,44 +960,40 @@ const translations: TranslationDeepObject<typeof en> = {
         listOfChats: 'Elenco chat',
         saveTheWorld: 'Salva il mondo',
         tooltip: 'Inizia qui!',
+        redirectToExpensifyClassicModal: {
+            title: 'Prossimamente',
+            description: 'Stiamo rifinendo ancora alcuni dettagli della nuova Expensify per adattarla alla tua configurazione specifica. Nel frattempo, passa a Expensify Classic.',
+        },
     },
     homePage: {
         forYou: 'Per te',
         timeSensitiveSection: {
             title: 'Sensibile al tempo',
-            addShippingAddress: {title: 'Ci serve il tuo indirizzo di spedizione', subtitle: 'Fornisci un indirizzo per ricevere la tua Carta Expensify.', cta: 'Aggiungi indirizzo'},
-            addPaymentCard: {title: 'Aggiungi una carta di pagamento per continuare a usare Expensify', subtitle: 'Account > Abbonamento', cta: 'Aggiungi'},
-            activateCard: {title: 'Attiva la tua Carta Expensify', subtitle: 'Convalida la tua carta e inizia a spendere.', cta: 'Attiva'},
-            reviewCardFraud: {
-                title: 'Esamina una possibile frode sulla tua Carta Expensify',
-                titleWithDetails: ({amount, merchant}: {amount: string; merchant: string}) => `Verifica ${amount} di potenziale frode presso ${merchant}`,
-                subtitle: 'Carta Expensify',
-                cta: 'Rivedi',
+            cta: 'Richiesta',
+            offer50off: {
+                title: 'Ottieni il 50% di sconto sul primo anno!',
+                subtitle: ({formattedTime}: {formattedTime: string}) => `${formattedTime} rimanenti`,
             },
-            ctaFix: 'Correggi',
-            fixCompanyCardConnection: {
-                title: ({feedName}: {feedName: string}) => (feedName ? `Correggi la connessione della carta aziendale ${feedName}` : 'Correggi connessione carta aziendale'),
-                defaultSubtitle: 'Area di lavoro',
-                subtitle: ({policyName}: {policyName: string}) => `${policyName} > Carte aziendali`,
+            offer25off: {
+                title: 'Ottieni il 25% di sconto sul tuo primo anno!',
+                subtitle: ({days}: {days: number}) => `Restano ${days} ${days === 1 ? 'giorno' : 'giorni'}`,
             },
-            fixPolicyConnection: {
-                title: ({integrationName}: {integrationName: string}) => `Correggi connessione ${integrationName}`,
-                defaultSubtitle: 'Area di lavoro',
-                subtitle: ({policyName}: {policyName: string}) => `${policyName} > Contabilità`,
+            addShippingAddress: {
+                title: 'Ci serve il tuo indirizzo di spedizione',
+                subtitle: 'Fornisci un indirizzo per ricevere la tua Expensify Card.',
+                cta: 'Aggiungi indirizzo',
             },
-            fixPersonalCardConnection: {
-                title: ({cardName}: {cardName?: string}) => (cardName ? `Correggi la connessione della carta personale ${cardName}` : 'Correggi connessione carta personale'),
-                subtitle: 'Portafoglio',
+            activateCard: {
+                title: 'Attiva la tua Expensify Card',
+                subtitle: 'Convalida la tua carta e inizia a spendere.',
+                cta: 'Attiva',
             },
-            validateAccount: {title: 'Conferma il tuo account', subtitle: 'Account', cta: 'Conferma'},
-            fixFailedBilling: {title: 'Non abbiamo potuto addebitare la carta salvata nel profilo', subtitle: 'Abbonamento'},
-            unlockBankAccount: {
-                workspaceTitle: 'Il conto bancario della tua azienda è stato bloccato',
-                personalTitle: 'Il tuo conto bancario è stato bloccato',
-                workspaceSubtitle: ({policyName}: {policyName: string}) => policyName,
-                personalSubtitle: 'Portafoglio',
+            ctaFix: 'Correggi',
+            fixCompanyCardConnection: {
+                title: ({feedName}: {feedName: string}) => (feedName ? `Correggi la connessione della carta aziendale ${feedName}` : 'Correggi connessione carta aziendale'),
+                subtitle: 'Spazio di lavoro > Carte aziendali',
             },
-            enterSignerInfo: {title: 'Informazioni del firmatario necessarie', subtitle: ({bankAccountLastFour}: {bankAccountLastFour: string}) => `Conto bancario ${bankAccountLastFour}`},
+            fixAccountingConnection: {title: ({integrationName}: {integrationName: string}) => `Correggi connessione ${integrationName}`, subtitle: 'Spazio di lavoro > Contabilità'},
         },
         announcements: 'Annunci',
         discoverSection: {
@@ -983,78 +1009,12 @@ const translations: TranslationDeepObject<typeof en> = {
             export: ({count}: {count: number}) => `Esporta ${count} ${count === 1 ? 'report' : 'report'}`,
             begin: 'Inizia',
             emptyStateMessages: {
-                thumbsUpStarsTitle: 'Hai finito!',
-                thumbsUpStarsDescription: 'Pollice in su per te, resta in attesa di altre attività.',
-                smallRocketTitle: 'Tutto a posto',
-                smallRocketDescription: 'Le prossime attività da fare verranno visualizzate qui.',
-                cowboyHatTitle: 'Hai finito!',
-                cowboyHatDescription: 'Tutte le attività sono sotto controllo, tieni d’occhio le prossime.',
-                trophy1Title: 'Niente da mostrare',
-                trophy1Description: 'Ce l’hai fatta! Tieni d’occhio le prossime cose da fare.',
-                palmTreeTitle: 'Tutto a posto',
-                palmTreeDescription: 'È il momento di rilassarsi, ma resta in attesa di future attività.',
-                fishbowlBlueTitle: 'Hai finito!',
-                fishbowlBlueDescription: 'Le future attività appariranno qui.',
-                targetTitle: 'Tutto a posto',
-                targetDescription: 'Ottimo, resti sulla giusta rotta. Ricontrolla per altre attività!',
-                chairTitle: 'Niente da mostrare',
-                chairDescription: 'Vai a rilassarti, elencheremo le prossime cose da fare qui.',
-                broomTitle: 'Hai finito!',
-                broomDescription: 'Le attività sono a posto, ma resta in attesa di altre cose da fare.',
-                houseTitle: 'Tutto a posto',
-                houseDescription: 'Questa è la tua base per le prossime cose da fare.',
-                conciergeBotTitle: 'Niente da mostrare',
-                conciergeBotDescription: 'Beep boop beep boop, ricontrolla per altre attività!',
-                checkboxTextTitle: 'Tutto a posto',
-                checkboxTextDescription: 'Spunta qui le tue prossime cose da fare.',
-                flashTitle: 'Hai finito!',
-                flashDescription: 'Qui mostreremo le tue future attività.',
-                sunglassesTitle: 'Niente da mostrare',
-                sunglassesDescription: 'È il momento di rilassarti, ma resta in attesa di ciò che arriva!',
-                f1FlagsTitle: 'Tutto a posto',
-                f1FlagsDescription: 'Hai completato tutte le attività in sospeso.',
-            },
-        },
-        upcomingTravel: 'Prossimi viaggi',
-        upcomingTravelSection: {
-            flightTo: ({destination}: {destination: string}) => `Volo per ${destination}`,
-            trainTo: ({destination}: {destination: string}) => `Treno per ${destination}`,
-            hotelIn: ({destination}: {destination: string}) => `Hotel a ${destination}`,
-            carRentalIn: ({destination}: {destination: string}) => `Noleggio auto a ${destination}`,
-            inOneWeek: 'Tra 1 settimana',
-            inDays: () => ({one: 'Tra 1 giorno', other: (count: number) => `Tra ${count} giorni`}),
-            today: 'Oggi',
-        },
-        freeTrialSection: {
-            title: ({days}: {days: number}) => `Prova gratuita: ${days} ${days === 1 ? 'giorno' : 'giorni'} rimanenti!`,
-            offer50Body: 'Ottieni il 50% di sconto sul tuo primo anno',
-            offer25Body: 'Ottieni il 25% di sconto sul tuo primo anno',
-            addCardBody: 'Aggiungi una carta di pagamento',
-            ctaClaim: 'Richiesta',
-            ctaAdd: 'Aggiungi carta',
-            timeRemaining: ({formattedTime}: {formattedTime: string}) => `Tempo rimanente: ${formattedTime}`,
-            timeRemainingDays: () => ({
-                one: 'Tempo rimanente: 1 giorno',
-                other: (pluralCount: number) => `Tempo rimanente: ${pluralCount} giorni`,
-            }),
-        },
-        gettingStartedSection: {
-            title: 'Per iniziare',
-            createWorkspace: 'Crea uno spazio di lavoro',
-            connectAccounting: ({integrationName}: {integrationName: string}) => `Connetti a ${integrationName}`,
-            connectAccountingDefault: 'Connetti alla contabilità',
-            customizeCategories: 'Personalizza le categorie contabili',
-            linkCompanyCards: 'Collega carte aziendali',
-            setupRules: 'Configura le regole di spesa',
-            inviteAccountant: 'Invita il tuo commercialista',
-        },
-        yourSpend: {
-            title: 'Le tue spese',
-            awaitingApproval: 'In attesa di approvazione',
-            repaidLast30Days: 'Rimborsato negli ultimi 30 giorni',
-            recentTransactions: ({lastFour}: {lastFour: string}) => `Transazioni recenti • ${lastFour}`,
+                nicelyDone: 'Ben fatto',
+                keepAnEyeOut: 'Tieniti pronto per ciò che arriverà dopo!',
+                allCaughtUp: 'Hai letto tutto',
+                upcomingTodos: 'Le prossime attività da fare verranno visualizzate qui.',
+            },
         },
-        seeMore: ({count}: {count: number}) => `Vedi altri ${count}`,
     },
     allSettingsScreen: {
         subscription: 'Abbonamento',
@@ -1083,20 +1043,7 @@ const translations: TranslationDeepObject<typeof en> = {
         singleFieldMultipleColumns: (fieldName: string) => `Ops! Hai associato un singolo campo ("${fieldName}") a più colonne. Controlla e riprova.`,
         emptyMappedField: (fieldName: string) => `Ops! Il campo ("${fieldName}") contiene uno o più valori vuoti. Controlla e riprova.`,
         importSuccessfulTitle: 'Importazione riuscita',
-        importCategoriesSuccessfulDescription: ({added, updated}: {added: number; updated: number}) => {
-            if (!added && !updated) {
-                return 'Nessuna categoria è stata aggiunta o aggiornata.';
-            }
-            if (added && updated) {
-                return `${added} ${added === 1 ? 'categoria aggiunta' : 'categorie aggiunte'}, ${updated} ${updated === 1 ? 'categoria aggiornata' : 'categorie aggiornate'}.`;
-            }
-            if (added) {
-                return added === 1 ? 'È stata aggiunta 1 categoria.' : `Sono state aggiunte ${added} categorie.`;
-            }
-            return updated === 1 ? 'È stata aggiornata 1 categoria.' : `Sono state aggiornate ${updated} categorie.`;
-        },
-        importCompanyCardTransactionsSuccessfulDescription: ({transactions}: {transactions: number}) =>
-            transactions > 1 ? `${transactions} transazioni sono state aggiunte.` : '1 transazione è stata aggiunta.',
+        importCategoriesSuccessfulDescription: ({categories}: {categories: number}) => (categories > 1 ? `Sono state aggiunte ${categories} categorie.` : 'È stata aggiunta 1 categoria.'),
         importMembersSuccessfulDescription: ({added, updated}: {added: number; updated: number}) => {
             if (!added && !updated) {
                 return 'Non è stato aggiunto o aggiornato alcun membro.';
@@ -1128,7 +1075,6 @@ const translations: TranslationDeepObject<typeof en> = {
             other: (count: number) =>
                 `Conferma i dettagli riportati di seguito per i ${count} nuovi membri dello spazio di lavoro che verranno aggiunti come parte di questo caricamento. I membri già esistenti non riceveranno aggiornamenti di ruolo o messaggi di invito.`,
         }),
-        importCompanyCardTransactionsPendingMessage: 'Le nuove carte e transazioni potrebbero impiegare un po’ di tempo per apparire, attendi per favore.',
     },
     receipt: {
         upload: 'Carica ricevuta',
@@ -1160,9 +1106,7 @@ const translations: TranslationDeepObject<typeof en> = {
         deleteReceipt: 'Elimina ricevuta',
         deleteConfirmation: 'Sei sicuro di voler eliminare questa ricevuta?',
         addReceipt: 'Aggiungi ricevuta',
-        addAdditionalReceipt: 'Aggiungi ricevuta aggiuntiva',
         scanFailed: 'La ricevuta non può essere acquisita perché manca il nome dell’esercente, la data o l’importo.',
-        crop: 'Ritaglia',
         addAReceipt: {
             phrase1: 'Aggiungi una ricevuta',
             phrase2: 'o trascinalo qui',
@@ -1182,7 +1126,6 @@ const translations: TranslationDeepObject<typeof en> = {
         noLongerHaveReportAccess: 'Non hai più accesso alla precedente destinazione dell’azione rapida. Selezionane una nuova qui sotto.',
         updateDestination: 'Aggiorna destinazione',
         createReport: 'Crea resoconto',
-        createTimeExpense: 'Crea nota spese tempo',
     },
     iou: {
         amount: 'Importo',
@@ -1202,18 +1145,18 @@ const translations: TranslationDeepObject<typeof en> = {
         split: 'Dividi',
         splitExpense: 'Dividi spesa',
         splitDates: 'Date divise',
-        splitDateRange: (startDate: string, endDate: string, count: number) => `dal ${startDate} al ${endDate} (${count} giorni)`,
-        splitExpenseSubtitle: (amount: string, merchant: string) => `${amount} da ${merchant}`,
+        splitDateRange: ({startDate, endDate, count}: SplitDateRangeParams) => `dal ${startDate} al ${endDate} (${count} giorni)`,
+        splitExpenseSubtitle: ({amount, merchant}: SplitExpenseSubtitleParams) => `${amount} da ${merchant}`,
         splitByPercentage: 'Dividi per percentuale',
         splitByDate: 'Dividi per data',
         addSplit: 'Aggiungi suddivisione',
         makeSplitsEven: 'Rendi divisioni uguali',
         editSplits: 'Modifica suddivisioni',
-        totalAmountGreaterThanOriginal: (amount: string) => `L’importo totale è ${amount} superiore rispetto alla spesa originale.`,
-        totalAmountLessThanOriginal: (amount: string) => `L’importo totale è di ${amount} inferiore rispetto alla spesa originale.`,
+        totalAmountGreaterThanOriginal: ({amount}: TotalAmountGreaterOrLessThanOriginalParams) => `L’importo totale è ${amount} superiore rispetto alla spesa originale.`,
+        totalAmountLessThanOriginal: ({amount}: TotalAmountGreaterOrLessThanOriginalParams) => `L’importo totale è di ${amount} inferiore rispetto alla spesa originale.`,
         splitExpenseZeroAmount: 'Inserisci un importo valido prima di continuare.',
         splitExpenseOneMoreSplit: 'Nessuna suddivisione aggiunta. Aggiungine almeno una per salvare.',
-        splitExpenseEditTitle: (amount: string, merchant: string) => `Modifica ${amount} per ${merchant}`,
+        splitExpenseEditTitle: ({amount, merchant}: SplitExpenseEditTitleParams) => `Modifica ${amount} per ${merchant}`,
         removeSplit: 'Rimuovi suddivisione',
         splitExpenseCannotBeEditedModalTitle: 'Questa spesa non può essere modificata',
         splitExpenseCannotBeEditedModalDescription: 'Le spese approvate o pagate non possono essere modificate',
@@ -1244,12 +1187,9 @@ const translations: TranslationDeepObject<typeof en> = {
         deleteReceipt: 'Elimina ricevuta',
         findExpense: 'Trova spesa',
         deletedTransaction: (amount: string, merchant: string) => `ha eliminato una spesa (${amount} per ${merchant})`,
-        movedFromReport: (reportName: string) => `ha spostato una spesa da ${reportName}`,
-        movedFromReportNoName: 'ha spostato una spesa',
-        movedTransactionTo: (reportUrl: string, reportName: string) => `ha spostato questa spesa su <a href="${reportUrl}">${reportName}</a>`,
-        movedTransactionToAnotherReport: 'ha spostato questa spesa in un altro report',
-        movedTransactionFrom: (reportUrl: string, reportName: string) => `ha spostato questa spesa da <a href="${reportUrl}">${reportName}</a>`,
-        movedTransactionFromAnotherReport: 'ha spostato questa nota spese da un altro report',
+        movedFromReport: (reportName: string) => `ha spostato una spesa${reportName ? `da ${reportName}` : ''}`,
+        movedTransactionTo: (reportUrl: string, reportName?: string) => `ha spostato questa spesa${reportName ? `a <a href="${reportUrl}">${reportName}</a>` : ''}`,
+        movedTransactionFrom: (reportUrl: string, reportName?: string) => `ha spostato questa spesa${reportName ? `da <a href="${reportUrl}">${reportName}</a>` : ''}`,
         unreportedTransaction: (reportUrl: string) => `ha spostato questa spesa nel tuo <a href="${reportUrl}">spazio personale</a>`,
         movedAction: (shouldHideMovedReportUrl: boolean, movedReportUrl: string, newParentReportUrl: string, toPolicyName: string) => {
             if (shouldHideMovedReportUrl) {
@@ -1261,10 +1201,7 @@ const translations: TranslationDeepObject<typeof en> = {
         pendingMatch: 'Corrispondenza in sospeso',
         pendingMatchWithCreditCardDescription: 'Ricevuta in attesa di abbinamento con la transazione della carta. Contrassegna come contante per annullare.',
         markAsCash: 'Segna come contante',
-        pendingMatchSubmitTitle: 'Invia report',
-        pendingMatchSubmitDescription: 'Alcune spese sono in attesa di abbinamento con una transazione della carta di credito. Vuoi segnarle come contante?',
         routePending: 'Instradamento in sospeso...',
-        automaticallyEnterExpenseDetails: 'Concierge compilerà i dettagli per te.',
         receiptScanning: () => ({
             one: 'Scansione della ricevuta in corso...',
             other: 'Scansione delle ricevute in corso...',
@@ -1291,7 +1228,7 @@ const translations: TranslationDeepObject<typeof en> = {
         receiptStatusTitle: 'Scansione in corso…',
         receiptStatusText: 'Solo tu puoi vedere questa ricevuta mentre viene scansionata. Controlla più tardi o inserisci i dettagli ora.',
         receiptScanningFailed: 'Scansione della ricevuta non riuscita. Inserisci i dettagli manualmente.',
-        allTransactionsPendingNextStep: 'Tutte le transazioni sono in sospeso. Non puoi inviare questo rendiconto finché non saranno registrate tra qualche giorno.',
+        transactionPendingDescription: 'Transazione in sospeso. Potrebbero essere necessari alcuni giorni prima che venga registrata.',
         companyInfo: 'Informazioni azienda',
         companyInfoDescription: 'Ci servono ancora alcuni dettagli prima che tu possa inviare la tua prima fattura.',
         yourCompanyName: 'Nome dell’azienda',
@@ -1326,18 +1263,20 @@ const translations: TranslationDeepObject<typeof en> = {
         settledElsewhere: 'Pagato altrove',
         individual: 'Personale',
         business: 'Business',
-        settlePersonal: (formattedAmount?: string) => (formattedAmount ? `Paga ${formattedAmount} come persona fisica` : `Paga con conto personale`),
-        settleWallet: (formattedAmount?: string) => (formattedAmount ? `Paga ${formattedAmount} con il wallet` : `Paga con portafoglio`),
-        settlePayment: (formattedAmount: string) => `Paga ${formattedAmount}`,
-        settleBusiness: (formattedAmount?: string) => (formattedAmount ? `Paga ${formattedAmount} come azienda` : `Paga con conto aziendale`),
-        payElsewhere: (formattedAmount?: string) => (formattedAmount ? `Segna ${formattedAmount} come pagato` : `Segna come pagata`),
-        confirmPaymentReceivedModalTitle: 'Conferma la ricezione del pagamento',
-        receivedPayment: 'Pagamento ricevuto',
-        receivedPaymentConfirmation: 'Procedi solo se hai già ricevuto il pagamento al di fuori di Expensify.',
-        confirmReceivedPayment: 'Sì, ho ricevuto il pagamento.',
+        settleExpensify: ({formattedAmount}: SettleExpensifyCardParams) => (formattedAmount ? `Paga ${formattedAmount} con Expensify` : `Paga con Expensify`),
+        settlePersonal: ({formattedAmount}: SettleExpensifyCardParams) => (formattedAmount ? `Paga ${formattedAmount} come persona fisica` : `Paga con conto personale`),
+        settleWallet: ({formattedAmount}: SettleExpensifyCardParams) => (formattedAmount ? `Paga ${formattedAmount} con il wallet` : `Paga con portafoglio`),
+        settlePayment: ({formattedAmount}: SettleExpensifyCardParams) => `Paga ${formattedAmount}`,
+        settleBusiness: ({formattedAmount}: SettleExpensifyCardParams) => (formattedAmount ? `Paga ${formattedAmount} come azienda` : `Paga con conto aziendale`),
+        payElsewhere: ({formattedAmount}: SettleExpensifyCardParams) => (formattedAmount ? `Segna ${formattedAmount} come pagato` : `Segna come pagata`),
         settleInvoicePersonal: (amount?: string, last4Digits?: string) => (amount ? `pagato ${amount} con conto personale ${last4Digits}` : `Pagato con conto personale`),
         settleInvoiceBusiness: (amount?: string, last4Digits?: string) => (amount ? `ha pagato ${amount} con il conto aziendale ${last4Digits}` : `Pagato con conto aziendale`),
-        payWithPolicy: (policyName: string, formattedAmount?: string) => (formattedAmount ? `Paga ${formattedAmount} tramite ${policyName}` : `Paga tramite ${policyName}`),
+        payWithPolicy: ({
+            formattedAmount,
+            policyName,
+        }: SettleExpensifyCardParams & {
+            policyName: string;
+        }) => (formattedAmount ? `Paga ${formattedAmount} tramite ${policyName}` : `Paga tramite ${policyName}`),
         businessBankAccount: (amount?: string, last4Digits?: string) => (amount ? `pagato ${amount} con il conto bancario ${last4Digits}` : `pagato con conto bancario ${last4Digits}`),
         automaticallyPaidWithBusinessBankAccount: (amount?: string, last4Digits?: string) =>
             `pagato ${amount ? `${amount} ` : ''} con il conto bancario ${last4Digits} tramite le <a href="${CONST.CONFIGURE_EXPENSE_REPORT_RULES_HELP_URL}">regole dello spazio di lavoro</a>`,
@@ -1346,16 +1285,16 @@ const translations: TranslationDeepObject<typeof en> = {
         nextStep: 'Prossimi passaggi',
         finished: 'Completato',
         flip: 'Ruota',
-        sendInvoice: (amount: string) => `Invia fattura da ${amount}`,
+        sendInvoice: ({amount}: RequestAmountParams) => `Invia fattura da ${amount}`,
         expenseAmount: (formattedAmount: string, comment?: string) => `${formattedAmount}${comment ? `per ${comment}` : ''}`,
-        submitted: (memo?: string) => `inviato${memo ? `, con nota: ${memo}` : ''}`,
+        submitted: ({memo}: SubmittedWithMemoParams) => `inviato${memo ? `, con nota: ${memo}` : ''}`,
         automaticallySubmitted: `inviato tramite <a href="${CONST.SELECT_WORKFLOWS_HELP_URL}">invio posticipato</a>`,
         queuedToSubmitViaDEW: 'in coda per l’invio tramite flusso di approvazione personalizzato',
         queuedToApproveViaDEW: 'in coda per l’approvazione tramite flusso di approvazione personalizzato',
         trackedAmount: (formattedAmount: string, comment?: string) => `monitoraggio di ${formattedAmount}${comment ? `per ${comment}` : ''}`,
-        splitAmount: (amount: string) => `dividi ${amount}`,
-        didSplitAmount: (formattedAmount: string, comment?: string) => `suddividi ${formattedAmount}${comment ? `per ${comment}` : ''}`,
-        yourSplit: (amount: string) => `La tua quota ${amount}`,
+        splitAmount: ({amount}: SplitAmountParams) => `dividi ${amount}`,
+        didSplitAmount: (formattedAmount: string, comment: string) => `suddividi ${formattedAmount}${comment ? `per ${comment}` : ''}`,
+        yourSplit: ({amount}: UserSplitParams) => `La tua quota ${amount}`,
         payerOwesAmount: (amount: number | string, payer: string, comment?: string) => `${payer} deve ${amount}${comment ? `per ${comment}` : ''}`,
         payerOwes: (payer: string) => `${payer} deve:`,
         payerPaidAmount: (amount: number | string, payer?: string) => `${payer ? `${payer} ` : ''}ha pagato ${amount}`,
@@ -1371,71 +1310,33 @@ const translations: TranslationDeepObject<typeof en> = {
         approvedMessage: `approvato`,
         unapproved: `non approvata`,
         automaticallyForwarded: `approvata tramite le <a href="${CONST.CONFIGURE_EXPENSE_REPORT_RULES_HELP_URL}">regole dello spazio di lavoro</a>`,
-        forwarded: (memo?: string) => `approvato${memo ? `, con nota: ${memo}` : ''}`,
-        rejectedThisReport: 'rifiutato',
-        waitingOnBankAccount: (submitterDisplayName: string) => `ha avviato il pagamento, ma sta aspettando che ${submitterDisplayName} aggiunga un conto bancario.`,
+        forwarded: `approvato`,
+        rejectedThisReport: 'ha rifiutato questo report',
+        waitingOnBankAccount: ({submitterDisplayName}: WaitingOnBankAccountParams) => `ha avviato il pagamento, ma sta aspettando che ${submitterDisplayName} aggiunga un conto bancario.`,
         adminCanceledRequest: 'ha annullato il pagamento',
         canceledRequest: (amount: string, submitterDisplayName: string) =>
             `ha annullato il pagamento di ${amount}, perché ${submitterDisplayName} non ha abilitato il proprio Expensify Wallet entro 30 giorni`,
-        settledAfterAddedBankAccount: (submitterDisplayName: string, amount: string) =>
+        settledAfterAddedBankAccount: ({submitterDisplayName, amount}: SettledAfterAddedBankAccountParams) =>
             `${submitterDisplayName} ha aggiunto un conto bancario. Il pagamento di ${amount} è stato effettuato.`,
         paidElsewhere: ({payer, comment}: PaidElsewhereParams = {}) => `${payer ? `${payer} ` : ''}contrassegnato come pagato${comment ? `, dicendo «${comment}»` : ''}`,
         paidWithExpensify: (payer?: string) => `${payer ? `${payer} ` : ''}pagato con portafoglio`,
         automaticallyPaidWithExpensify: (payer?: string) =>
             `${payer ? `${payer} ` : ''}pagato con Expensify tramite le <a href="${CONST.CONFIGURE_EXPENSE_REPORT_RULES_HELP_URL}">regole dello spazio di lavoro</a>`,
-        reimbursedThisReport: 'ha rimborsato questo resoconto',
-        paidThisBill: 'ha pagato questa fattura',
-        reimbursedOnBehalfOf: (actor: string) => `per conto di ${actor}`,
-        reimbursedFromBankAccount: (debitBankAccount: string) => `dal conto bancario che termina con ${debitBankAccount}`,
-        reimbursedSubmitterAddedBankAccount: (submitter: string) => `${submitter} ha aggiunto un conto bancario, rimuovendo il blocco sul resoconto. Il rimborso è stato avviato`,
-        reimbursedWithFastACH: ({
-            isCurrentUser,
-            submitterLogin,
-            creditBankAccount,
-            expectedDate,
-        }: {
-            isCurrentUser: boolean;
-            submitterLogin: string;
-            creditBankAccount: string;
-            expectedDate: string;
-        }) =>
-            isCurrentUser
-                ? `. Il denaro è in arrivo sul tuo ${creditBankAccount ? `conto bancario che termina con ${creditBankAccount}` : 'conto'}. Rimborso previsto per il ${expectedDate}.`
-                : `. Il denaro è in arrivo sul conto bancario di ${submitterLogin}${creditBankAccount ? ` che termina con ${creditBankAccount}` : ''}. Rimborso previsto per il ${expectedDate}.`,
-        reimbursedWithCheck: ' tramite assegno.',
-        reimbursedWithStripeConnect: ({
-            isCurrentUser,
-            submitterLogin,
-            creditBankAccount,
-            isCard,
-        }: {
-            isCurrentUser: boolean;
-            submitterLogin: string;
-            creditBankAccount: string;
-            isCard: boolean;
-        }) => {
-            const paymentMethod = isCard ? 'carta' : 'conto bancario';
-            return isCurrentUser
-                ? `. Il denaro è in arrivo sul tuo ${creditBankAccount ? `conto bancario che termina con ${creditBankAccount}` : 'conto'} (pagato tramite ${paymentMethod}). Questo potrebbe richiedere fino a 10 giorni lavorativi.`
-                : `. Il denaro è in arrivo sul conto bancario di ${submitterLogin}${creditBankAccount ? ` che termina con ${creditBankAccount}` : ''} (pagato tramite ${paymentMethod}). Potrebbero volerci fino a 10 giorni lavorativi.`;
-        },
-        reimbursedWithACH: ({creditBankAccount, expectedDate}: {creditBankAccount?: string; expectedDate?: string}) =>
-            ` con accredito diretto (ACH)${creditBankAccount ? ` al conto bancario che termina con ${creditBankAccount}.` : '. '}${expectedDate ? `Il rimborso dovrebbe essere completato entro il ${expectedDate}.` : 'In genere richiede 4-5 giorni lavorativi.'}`,
         noReimbursableExpenses: 'Questo rendiconto contiene un importo non valido',
         pendingConversionMessage: 'Il totale verrà aggiornato quando torni online',
         changedTheExpense: 'ha modificato la spesa',
-        setTheRequest: (valueName: string, newValueToDisplay: string) => `${valueName} a ${newValueToDisplay}`,
-        setTheDistanceMerchant: (translatedChangedField: string, newMerchant: string, newAmountToDisplay: string) =>
+        setTheRequest: ({valueName, newValueToDisplay}: SetTheRequestParams) => `${valueName} a ${newValueToDisplay}`,
+        setTheDistanceMerchant: ({translatedChangedField, newMerchant, newAmountToDisplay}: SetTheDistanceMerchantParams) =>
             `imposta ${translatedChangedField} su ${newMerchant}, che ha impostato l’importo su ${newAmountToDisplay}`,
         removedTheRequest: (valueName: string, oldValueToDisplay: string) => `il/la ${valueName} (precedentemente ${oldValueToDisplay})`,
-        updatedTheRequest: (valueName: string, newValueToDisplay: string, oldValueToDisplay: string) => `${valueName} a ${newValueToDisplay} (in precedenza ${oldValueToDisplay})`,
-        updatedTheDistanceMerchant: (translatedChangedField: string, newMerchant: string, oldMerchant: string, newAmountToDisplay: string, oldAmountToDisplay: string) =>
+        updatedTheRequest: ({valueName, newValueToDisplay, oldValueToDisplay}: UpdatedTheRequestParams) => `${valueName} a ${newValueToDisplay} (in precedenza ${oldValueToDisplay})`,
+        updatedTheDistanceMerchant: ({translatedChangedField, newMerchant, oldMerchant, newAmountToDisplay, oldAmountToDisplay}: UpdatedTheDistanceMerchantParams) =>
             `ha modificato ${translatedChangedField} in ${newMerchant} (precedentemente ${oldMerchant}), aggiornando l'importo a ${newAmountToDisplay} (precedentemente ${oldAmountToDisplay})`,
         basedOnAI: 'in base all’attività precedente',
         basedOnMCC: ({rulesLink}: {rulesLink: string}) => (rulesLink ? `in base alle <a href="${rulesLink}">regole dello spazio di lavoro</a>` : 'in base alle regole della workspace'),
-        threadExpenseReportName: (formattedAmount: string, comment?: string) => `${formattedAmount} ${comment ? `per ${comment}` : 'spesa'}`,
+        threadExpenseReportName: ({formattedAmount, comment}: ThreadRequestReportNameParams) => `${formattedAmount} ${comment ? `per ${comment}` : 'spesa'}`,
         invoiceReportName: ({linkedReportID}: OriginalMessage<typeof CONST.REPORT.ACTIONS.TYPE.REPORT_PREVIEW>) => `Report fattura n. ${linkedReportID}`,
-        threadPaySomeoneReportName: (formattedAmount: string, comment?: string) => `${formattedAmount} inviato${comment ? `per ${comment}` : ''}`,
+        threadPaySomeoneReportName: ({formattedAmount, comment}: ThreadSentMoneyReportNameParams) => `${formattedAmount} inviato${comment ? `per ${comment}` : ''}`,
         movedFromPersonalSpace: ({workspaceName, reportName}: MovedFromPersonalSpaceParams) => `ha spostato la spesa dallo spazio personale a ${workspaceName ?? `chatta con ${reportName}`}`,
         movedToPersonalSpace: 'ha spostato la spesa nello spazio personale',
         error: {
@@ -1443,14 +1344,10 @@ const translations: TranslationDeepObject<typeof en> = {
             invalidTagLength: 'Il nome del tag supera i 255 caratteri. Per favore accorcialo o scegli un tag diverso.',
             invalidAmount: 'Inserisci un importo valido prima di continuare',
             invalidDistance: 'Inserisci una distanza valida prima di continuare',
-            invalidReadings: 'Inserisci sia la lettura iniziale che quella finale per continuare',
+            invalidReadings: 'Inserisci sia la lettura iniziale che quella finale',
             negativeDistanceNotAllowed: 'La lettura finale deve essere maggiore della lettura iniziale',
-            distanceAmountTooLarge: "L'importo totale è troppo alto. Riduci la distanza o abbassa la tariffa.",
-            distanceAmountTooLargeReduceDistance: "L'importo totale è troppo alto. Riduci la distanza.",
-            distanceAmountTooLargeReduceRate: "L'importo totale è troppo alto. Abbassa la tariffa.",
-            odometerReadingTooLarge: (formattedMax: string) => `Le letture del contachilometri non possono superare ${formattedMax}.`,
             invalidIntegerAmount: 'Inserisci un importo in dollari intero prima di continuare',
-            invalidTaxAmount: (amount: string) => `L’importo massimo dell’imposta è ${amount}`,
+            invalidTaxAmount: ({amount}: RequestAmountParams) => `L’importo massimo dell’imposta è ${amount}`,
             invalidSplit: 'La somma delle suddivisioni deve essere uguale all’importo totale',
             invalidSplitParticipants: 'Inserisci un importo maggiore di zero per almeno due partecipanti',
             invalidSplitYourself: 'Inserisci un importo diverso da zero per la tua suddivisione',
@@ -1464,8 +1361,6 @@ const translations: TranslationDeepObject<typeof en> = {
             receiptFailureMessage:
                 '<rbr>Si è verificato un errore durante il caricamento della ricevuta. <a href="download">Salva la ricevuta</a> e <a href="retry">riprova</a> più tardi.</rbr>',
             receiptFailureMessageShort: 'Si è verificato un errore durante il caricamento della ricevuta.',
-            receiptUploadFailedMessage: 'Caricamento della ricevuta non riuscito. Salva la ricevuta oppure elimina la spesa e perdila.',
-            saveReceipt: 'Salva ricevuta',
             genericDeleteFailureMessage: 'Errore imprevisto durante l’eliminazione di questa spesa. Riprova più tardi.',
             genericEditFailureMessage: 'Errore imprevisto durante la modifica di questa spesa. Riprova più tardi.',
             genericSmartscanFailureMessage: 'Alla transazione mancano dei campi',
@@ -1481,15 +1376,11 @@ const translations: TranslationDeepObject<typeof en> = {
             endDateBeforeStartDate: 'La data di fine non può essere precedente alla data di inizio',
             endDateSameAsStartDate: 'La data di fine non può essere uguale alla data di inizio',
             manySplitsProvided: `Il numero massimo di suddivisioni consentite è ${CONST.IOU.SPLITS_LIMIT}.`,
-            unableToSubmitReport: 'Impossibile inviare il report',
-            allTransactionsPendingDescription: 'Non puoi inviare questo report perché tutte le transazioni sono in sospeso. Potrebbero volerci alcuni giorni prima che vengano registrate.',
             dateRangeExceedsMaxDays: `L’intervallo di date non può superare ${CONST.IOU.SPLITS_LIMIT} giorni.`,
-            stitchOdometerImagesFailed: 'Impossibile combinare le immagini del contachilometri. Riprova più tardi.',
-            failedToSaveOdometerDraft: 'Impossibile salvare la tua bozza del contachilometri. Riprova.',
         },
         dismissReceiptError: 'Ignora errore',
         dismissReceiptErrorConfirmation: 'Attenzione! Chiudere questo errore rimuoverà completamente la ricevuta che hai caricato. Sei sicuro?',
-        waitingOnEnabledWallet: (submitterDisplayName: string) =>
+        waitingOnEnabledWallet: ({submitterDisplayName}: WaitingOnBankAccountParams) =>
             `ha iniziato a saldare il conto. Il pagamento è in sospeso finché ${submitterDisplayName} non abilita il proprio portafoglio.`,
         enableWallet: 'Abilita portafoglio',
         hold: 'Metti in attesa',
@@ -1502,20 +1393,16 @@ const translations: TranslationDeepObject<typeof en> = {
         heldExpense: 'ha messo in sospeso questa spesa',
         unheldExpense: 'ha sbloccato questa spesa',
         moveUnreportedExpense: 'Sposta spesa non rendicontata',
-        addExistingExpense: 'Aggiungi spesa esistente',
-        selectExistingExpense: 'Seleziona almeno una spesa da aggiungere al rapporto.',
-        emptyStateExistingExpenseTitle: 'Nessuna spesa esistente',
-        emptyStateExistingExpenseSubtitle: 'Sembra che tu non abbia alcuna spesa esistente. Prova a crearne una qui sotto.',
-        addExistingExpenseConfirm: 'Aggiungi al report',
+        addUnreportedExpense: 'Aggiungi spesa non rendicontata',
+        selectUnreportedExpense: 'Seleziona almeno una spesa da aggiungere al rapporto.',
+        emptyStateUnreportedExpenseTitle: 'Nessuna spesa non dichiarata',
+        emptyStateUnreportedExpenseSubtitle: 'Sembra che tu non abbia alcuna spesa non rendicontata. Prova a crearne una qui sotto.',
+        addUnreportedExpenseConfirm: 'Aggiungi al report',
         newReport: 'Nuovo report',
         explainHold: () => ({
             one: 'Spiega perché stai trattenendo questa spesa.',
             other: 'Spiega perché stai trattenendo queste spese.',
         }),
-        explainHoldApprover: () => ({
-            one: 'Spiega cosa ti serve prima di approvare questa spesa.',
-            other: 'Spiega cosa ti serve prima di approvare queste spese.',
-        }),
         retracted: 'ritirato',
         retract: 'Revoca',
         reopened: 'riaperto',
@@ -1529,11 +1416,8 @@ const translations: TranslationDeepObject<typeof en> = {
         expensesOnHold: 'Tutte le spese sono state messe in sospeso. Controlla i commenti per conoscere i prossimi passaggi.',
         expenseDuplicate: 'Questa spesa ha dettagli simili a un’altra. Controlla i duplicati per continuare.',
         someDuplicatesArePaid: 'Alcuni di questi duplicati sono già stati approvati o pagati.',
-        reviewDuplicates: 'Controlla duplicati',
+        reviewDuplicates: 'Controlla i duplicati',
         keepAll: 'Mantieni tutto',
-        keepSelected: 'Mantieni selezionati',
-        noDuplicatesTitle: 'Tutto a posto!',
-        noDuplicatesDescription: 'Non ci sono transazioni duplicate da verificare qui.',
         confirmApprove: 'Conferma l’importo approvato',
         confirmApprovalAmount: 'Approva solo le spese conformi oppure approva l’intero rapporto.',
         confirmApprovalAllHoldAmount: () => ({
@@ -1567,7 +1451,7 @@ const translations: TranslationDeepObject<typeof en> = {
         unapprove: 'Revoca approvazione',
         unapproveReport: 'Annulla approvazione rapporto',
         headsUp: 'Attenzione!',
-        unapproveWithIntegrationWarning: (accountingIntegration: string) =>
+        unapproveWithIntegrationWarning: ({accountingIntegration}: UnapproveWithIntegrationWarningParams) =>
             `Questo report è già stato esportato in ${accountingIntegration}. Modificarlo potrebbe causare discrepanze nei dati. Sei sicuro di voler revocare l’approvazione di questo report?`,
         reimbursable: 'rimborsabile',
         nonReimbursable: 'non rimborsabile',
@@ -1576,7 +1460,6 @@ const translations: TranslationDeepObject<typeof en> = {
         bookingArchived: 'Questa prenotazione è archiviata',
         bookingArchivedDescription: 'Questa prenotazione è archiviata perché la data del viaggio è passata. Aggiungi una spesa per l’importo finale, se necessario.',
         attendees: 'Partecipanti',
-        totalPerAttendee: 'Per partecipante',
         whoIsYourAccountant: 'Chi è il tuo commercialista?',
         paymentComplete: 'Pagamento completato',
         time: 'Ora',
@@ -1603,7 +1486,7 @@ const translations: TranslationDeepObject<typeof en> = {
         }),
         dates: 'Date',
         rates: 'Tariffe',
-        submitsTo: (name: string) => `Invia a ${name}`,
+        submitsTo: ({name}: SubmitsToParams) => `Invia a ${name}`,
         reject: {
             educationalTitle: 'Vuoi mettere in sospeso o rifiutare?',
             educationalText: 'Se non sei prontə ad approvare o pagare una spesa, puoi metterla in sospeso o rifiutarla.',
@@ -1612,7 +1495,7 @@ const translations: TranslationDeepObject<typeof en> = {
             heldExpenseLeftBehindTitle: 'Le spese in sospeso vengono escluse quando approvi l’intero report.',
             rejectExpenseTitle: 'Rifiuta una spesa che non intendi approvare o pagare.',
             reasonPageTitle: 'Rifiuta spesa',
-            reasonPageDescription: 'Spiega perché non approverai questa spesa.',
+            reasonPageDescription: 'Spiega perché stai rifiutando questa spesa.',
             rejectReason: 'Motivo del rifiuto',
             markAsResolved: 'Segna come risolto',
             rejectedStatus: 'Questa spesa è stata rifiutata. In attesa che tu risolva i problemi e la contrassegni come risolta per consentirne l’invio.',
@@ -1621,26 +1504,13 @@ const translations: TranslationDeepObject<typeof en> = {
                 markedAsResolved: 'ha segnato il motivo del rifiuto come risolto',
             },
         },
-        rejectReport: {
-            title: 'Rifiuta rapporto',
-            description: 'Spiega perché non approverai questo report:',
-            rejectReason: 'Motivo del rifiuto',
-            selectTarget: 'Scegli il membro a cui rimandare questo report per la revisione:',
-            lastApprover: 'Ultimo approvatore',
-            submitter: 'Proponente',
-            rejectedReportMessage: 'Questo rendiconto è stato rifiutato.',
-            rejectedNextStep: 'Questo report è stato rifiutato. In attesa che tu risolva i problemi e lo invii di nuovo manualmente.',
-            selectMemberError: 'Seleziona un membro a cui rimandare indietro questo report per rifiutarlo.',
-            couldNotReject: 'Non è stato possibile rifiutare il report. Riprova.',
-        },
-        moveExpenses: 'Sposta nel report',
+        moveExpenses: () => ({one: 'Sposta spesa', other: 'Sposta spese'}),
         moveExpensesError: 'Non puoi spostare le spese di diaria nei report di altri spazi di lavoro, perché le tariffe di diaria possono variare tra gli spazi di lavoro.',
         changeApprover: {
             title: 'Cambia approvatore',
-            header: (workflowSettingLink: string) =>
+            header: ({workflowSettingLink}: WorkflowSettingsParam) =>
                 `Scegli un'opzione per cambiare l'approvatore di questo report. (Aggiorna le <a href="${workflowSettingLink}">impostazioni dello spazio di lavoro</a> per cambiarlo in modo permanente per tutti i report.)`,
             changedApproverMessage: (managerID: number) => `ha cambiato l’approvatore in <mention-user accountID="${managerID}"/>`,
-            reassignedApproverMessage: (managerID: number) => `ha riassegnato l'approvatore a <mention-user accountID="${managerID}"/> tramite un aggiornamento del flusso di lavoro`,
             actions: {
                 addApprover: 'Aggiungi approvatore',
                 addApproverSubtitle: 'Aggiungi un ulteriore approvatore al flusso di approvazione esistente.',
@@ -1649,12 +1519,10 @@ const translations: TranslationDeepObject<typeof en> = {
             },
             addApprover: {
                 subtitle: 'Scegli un approvatore aggiuntivo per questo report prima che venga instradato attraverso il resto del flusso di approvazione.',
-                bulkSubtitle: 'Scegli un approvatore aggiuntivo per questi report prima che li instradiamo attraverso il resto del flusso di approvazione.',
             },
-            bulkSubtitle: "Scegli un'opzione per cambiare l'approvatore di questi report.",
         },
         chooseWorkspace: 'Scegli uno spazio di lavoro',
-        routedDueToDEW: (to: string, reason?: string) => `report indirizzato a ${to}${reason ? ` perché ${reason}` : ''}`,
+        routedDueToDEW: ({to}: RoutedDueToDEWParams) => `rendiconto instradato a ${to} a causa del flusso di approvazione personalizzato`,
         timeTracking: {
             hoursAt: (hours: number, rate: string) => `${hours} ${hours === 1 ? 'ora' : 'ore'} @ ${rate} / ora`,
             hrs: 'ore',
@@ -1662,34 +1530,34 @@ const translations: TranslationDeepObject<typeof en> = {
             ratePreview: (rate: string) => `${rate} / ora`,
             amountTooLargeError: 'L’importo totale è troppo alto. Riduci le ore o abbassa la tariffa.',
         },
-        correctRateError: "Correggi l'errore di tariffa e riprova.",
-        AskToExplain: `. <a href="${CONST.CONCIERGE_EXPLAIN_LINK_PATH}">Spiega<sparkles-icon/></a>`,
-        duplicateNonDefaultWorkspacePerDiemError: 'Non puoi duplicare le spese di diaria tra diversi spazi di lavoro perché le tariffe potrebbero essere diverse tra gli spazi di lavoro.',
-        rulesModifiedFields: {
-            reimbursable: (value: boolean) => (value ? 'ha contrassegnato la spesa come "rimborsabile"' : 'ha contrassegnato la spesa come "non rimborsabile"'),
-            billable: (value: boolean) => (value ? 'ha contrassegnato la spesa come "fatturabile"' : 'ha contrassegnato la spesa come "non fatturabile"'),
-            tax: (value: string, isFirst: boolean) => (isFirst ? `imposta l’aliquota fiscale su "${value}"` : `aliquota fiscale a "${value}"`),
-            reportName: (value: string) => `ha spostato questa spesa nel report "${value}"`,
-            common: (key: keyof PolicyRulesModifiedFields | keyof PersonalRulesModifiedFields, value: string, isFirst: boolean) => {
-                const field = translations.common[key].toLowerCase();
-                return isFirst ? `imposta ${field} su "${value}"` : `${field} a "${value}"`;
-            },
-            formatPersonalRules: (fragments: string, route: string) => `${fragments} tramite <a href="${route}">regole spese personali</a>`,
-            formatPolicyRules: (fragments: string, route: string) => `${fragments} tramite <a href="${route}">regole spazio di lavoro</a>`,
-        },
-        failedToAutoSubmitViaDEW: (reason: string) => `invio del resoconto non riuscito tramite <a href="${CONST.SELECT_WORKFLOWS_HELP_URL}">rimanda invii</a>. ${reason}`,
-        failedToSubmitViaDEW: (reason: string) => `invio del rapporto non riuscito. ${reason}`,
-        failedToAutoApproveViaDEW: (reason: string) =>
-            `approvazione non riuscita tramite le <a href="${CONST.CONFIGURE_EXPENSE_REPORT_RULES_HELP_URL}">regole dello spazio di lavoro</a>. ${reason}`,
-        failedToApproveViaDEW: (reason: string) => `approvazione non riuscita. ${reason}`,
-        cannotDuplicateDistanceExpense: 'Non puoi duplicare le spese chilometriche tra diversi spazi di lavoro perché le tariffe potrebbero essere diverse.',
-        taxDisabledAlert: {
-            title: 'Imposta disattivata',
-            prompt: 'Abilita il monitoraggio delle imposte nello spazio di lavoro per modificare i dettagli della spesa o eliminare l’imposta da questa spesa.',
-            confirmText: 'Elimina imposta',
-        },
-        bulkDuplicateLimit: `Puoi duplicare fino a ${CONST.SEARCH.BULK_DUPLICATE_LIMIT} spese alla volta. Seleziona meno spese e riprova.`,
-        deleted: 'Eliminato',
+        correctDistanceRateError: 'Correggi l’errore nella tariffa distanza e riprova.',
+        AskToExplain: `. <a href="${CONST.CONCIERGE_EXPLAIN_LINK_PATH}"><strong>Spiega</strong></a> &#x2728;`,
+        policyRulesModifiedFields: (policyRulesModifiedFields: PolicyRulesModifiedFields, policyRulesRoute: string, formatList: (list: string[]) => string) => {
+            const entries = ObjectUtils.typedEntries(policyRulesModifiedFields);
+            const fragments = entries.map(([key, value], i) => {
+                const isFirst = i === 0;
+                if (key === 'reimbursable') {
+                    return value ? 'ha contrassegnato la spesa come "rimborsabile"' : 'ha contrassegnato la spesa come "non rimborsabile"';
+                }
+                if (key === 'billable') {
+                    return value ? 'ha contrassegnato la spesa come "fatturabile"' : 'ha contrassegnato la spesa come "non fatturabile"';
+                }
+                if (key === 'tax') {
+                    const taxEntry = value as PolicyRulesModifiedFields['tax'];
+                    const taxRateName = taxEntry?.field_id_TAX.name ?? '';
+                    if (isFirst) {
+                        return `imposta l’aliquota fiscale su "${taxRateName}"`;
+                    }
+                    return `aliquota fiscale a "${taxRateName}"`;
+                }
+                const updatedValue = value as string | boolean;
+                if (isFirst) {
+                    return `imposta ${translations.common[key].toLowerCase()} su "${updatedValue}"`;
+                }
+                return `${translations.common[key].toLowerCase()} a "${updatedValue}"`;
+            });
+            return `${formatList(fragments)} tramite le <a href="${policyRulesRoute}">regole dello spazio di lavoro</a>`;
+        },
     },
     transactionMerge: {
         listPage: {
@@ -1762,12 +1630,7 @@ const translations: TranslationDeepObject<typeof en> = {
     },
     nextStep: {
         message: {
-            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_TO_ADD_TRANSACTIONS]: (
-                actor: string,
-                actorType: ValueOf<typeof CONST.NEXT_STEP.ACTOR_TYPE>,
-                _eta?: string,
-                _etaType?: ValueOf<typeof CONST.NEXT_STEP.ETA_TYPE>,
-            ) => {
+            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_TO_ADD_TRANSACTIONS]: ({actor, actorType}: NextStepParams) => {
                 switch (actorType) {
                     case CONST.NEXT_STEP.ACTOR_TYPE.CURRENT_USER:
                         return `In attesa che <strong>tu</strong> aggiunga delle spese.`;
@@ -1777,33 +1640,18 @@ const translations: TranslationDeepObject<typeof en> = {
                         return `In attesa che un amministratore aggiunga delle spese.`;
                 }
             },
-            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_TO_SUBMIT]: (
-                actor: string,
-                actorType: ValueOf<typeof CONST.NEXT_STEP.ACTOR_TYPE>,
-                _eta?: string,
-                _etaType?: ValueOf<typeof CONST.NEXT_STEP.ETA_TYPE>,
-            ) => {
+            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_TO_SUBMIT]: ({actor, actorType}: NextStepParams) => {
                 switch (actorType) {
                     case CONST.NEXT_STEP.ACTOR_TYPE.CURRENT_USER:
-                        return `In attesa che <strong>tu</strong> invii le note spese.`;
+                        return `In attesa che <strong>tu</strong> invii le spese.`;
                     case CONST.NEXT_STEP.ACTOR_TYPE.OTHER_USER:
                         return `In attesa che <strong>${actor}</strong> invii le spese.`;
                     case CONST.NEXT_STEP.ACTOR_TYPE.UNSPECIFIED_ADMIN:
                         return `In attesa che un amministratore invii le spese.`;
                 }
             },
-            [CONST.NEXT_STEP.MESSAGE_KEY.NO_FURTHER_ACTION]: (
-                _actor: string,
-                _actorType: ValueOf<typeof CONST.NEXT_STEP.ACTOR_TYPE>,
-                _eta?: string,
-                _etaType?: ValueOf<typeof CONST.NEXT_STEP.ETA_TYPE>,
-            ) => `Nessuna ulteriore azione richiesta!`,
-            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_FOR_SUBMITTER_ACCOUNT]: (
-                actor: string,
-                actorType: ValueOf<typeof CONST.NEXT_STEP.ACTOR_TYPE>,
-                _eta?: string,
-                _etaType?: ValueOf<typeof CONST.NEXT_STEP.ETA_TYPE>,
-            ) => {
+            [CONST.NEXT_STEP.MESSAGE_KEY.NO_FURTHER_ACTION]: (_: NextStepParams) => `Nessuna ulteriore azione richiesta!`,
+            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_FOR_SUBMITTER_ACCOUNT]: ({actor, actorType}: NextStepParams) => {
                 switch (actorType) {
                     case CONST.NEXT_STEP.ACTOR_TYPE.CURRENT_USER:
                         return `In attesa che <strong>tu</strong> aggiunga un conto bancario.`;
@@ -1813,15 +1661,10 @@ const translations: TranslationDeepObject<typeof en> = {
                         return `In attesa che un amministratore aggiunga un conto bancario.`;
                 }
             },
-            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_FOR_AUTOMATIC_SUBMIT]: (
-                actor: string,
-                actorType: ValueOf<typeof CONST.NEXT_STEP.ACTOR_TYPE>,
-                eta?: string,
-                etaType?: ValueOf<typeof CONST.NEXT_STEP.ETA_TYPE>,
-            ) => {
+            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_FOR_AUTOMATIC_SUBMIT]: ({actor, actorType, eta, etaType}: NextStepParams) => {
                 let formattedETA = '';
                 if (eta) {
-                    formattedETA = etaType === CONST.NEXT_STEP.ETA_TYPE.DATE_TIME ? `il ${eta} di ogni mese` : ` ${eta}`;
+                    formattedETA = etaType === CONST.NEXT_STEP.ETA_TYPE.DATE_TIME ? `il ${eta}` : ` ${eta}`;
                 }
                 switch (actorType) {
                     case CONST.NEXT_STEP.ACTOR_TYPE.CURRENT_USER:
@@ -1832,27 +1675,17 @@ const translations: TranslationDeepObject<typeof en> = {
                         return `In attesa che le spese di un amministratore vengano inviate automaticamente${formattedETA}.`;
                 }
             },
-            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_TO_FIX_ISSUES]: (
-                actor: string,
-                actorType: ValueOf<typeof CONST.NEXT_STEP.ACTOR_TYPE>,
-                _eta?: string,
-                _etaType?: ValueOf<typeof CONST.NEXT_STEP.ETA_TYPE>,
-            ) => {
+            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_TO_FIX_ISSUES]: ({actor, actorType}: NextStepParams) => {
                 switch (actorType) {
                     case CONST.NEXT_STEP.ACTOR_TYPE.CURRENT_USER:
-                        return `In attesa che <strong>tu</strong> sistemi i problemi.`;
+                        return `In attesa che <strong>tu</strong> risolva i problemi.`;
                     case CONST.NEXT_STEP.ACTOR_TYPE.OTHER_USER:
                         return `In attesa che <strong>${actor}</strong> risolva i problemi.`;
                     case CONST.NEXT_STEP.ACTOR_TYPE.UNSPECIFIED_ADMIN:
                         return `In attesa che un amministratore risolva i problemi.`;
                 }
             },
-            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_TO_APPROVE]: (
-                actor: string,
-                actorType: ValueOf<typeof CONST.NEXT_STEP.ACTOR_TYPE>,
-                _eta?: string,
-                _etaType?: ValueOf<typeof CONST.NEXT_STEP.ETA_TYPE>,
-            ) => {
+            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_TO_APPROVE]: ({actor, actorType}: NextStepParams) => {
                 switch (actorType) {
                     case CONST.NEXT_STEP.ACTOR_TYPE.CURRENT_USER:
                         return `In attesa che <strong>tu</strong> approvi le spese.`;
@@ -1862,85 +1695,45 @@ const translations: TranslationDeepObject<typeof en> = {
                         return `In attesa che un amministratore approvi le spese.`;
                 }
             },
-            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_TO_EXPORT]: (
-                actor: string,
-                actorType: ValueOf<typeof CONST.NEXT_STEP.ACTOR_TYPE>,
-                _eta?: string,
-                _etaType?: ValueOf<typeof CONST.NEXT_STEP.ETA_TYPE>,
-            ) => {
+            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_TO_EXPORT]: ({actor, actorType}: NextStepParams) => {
                 switch (actorType) {
                     case CONST.NEXT_STEP.ACTOR_TYPE.CURRENT_USER:
                         return `In attesa che <strong>tu</strong> esporti questo report.`;
                     case CONST.NEXT_STEP.ACTOR_TYPE.OTHER_USER:
                         return `In attesa che <strong>${actor}</strong> esporti questo report.`;
                     case CONST.NEXT_STEP.ACTOR_TYPE.UNSPECIFIED_ADMIN:
-                        return `In attesa che un amministratore esporti questo resoconto.`;
+                        return `In attesa che un amministratore esporti questo report.`;
                 }
             },
-            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_TO_PAY]: (
-                actor: string,
-                actorType: ValueOf<typeof CONST.NEXT_STEP.ACTOR_TYPE>,
-                _eta?: string,
-                _etaType?: ValueOf<typeof CONST.NEXT_STEP.ETA_TYPE>,
-            ) => {
+            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_TO_PAY]: ({actor, actorType}: NextStepParams) => {
                 switch (actorType) {
                     case CONST.NEXT_STEP.ACTOR_TYPE.CURRENT_USER:
                         return `In attesa che <strong>tu</strong> rimborsi le spese.`;
                     case CONST.NEXT_STEP.ACTOR_TYPE.OTHER_USER:
                         return `In attesa che <strong>${actor}</strong> rimborsi le spese.`;
                     case CONST.NEXT_STEP.ACTOR_TYPE.UNSPECIFIED_ADMIN:
-                        return `In attesa che un admin rimborsi le spese.`;
+                        return `In attesa che un amministratore rimborsi le spese.`;
                 }
             },
-            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_FOR_POLICY_BANK_ACCOUNT]: (
-                actor: string,
-                actorType: ValueOf<typeof CONST.NEXT_STEP.ACTOR_TYPE>,
-                _eta?: string,
-                _etaType?: ValueOf<typeof CONST.NEXT_STEP.ETA_TYPE>,
-            ) => {
+            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_FOR_POLICY_BANK_ACCOUNT]: ({actor, actorType}: NextStepParams) => {
                 switch (actorType) {
                     case CONST.NEXT_STEP.ACTOR_TYPE.CURRENT_USER:
-                        return `In attesa che <strong>tu</strong> finisca di configurare un conto bancario aziendale.`;
+                        return `In attesa che <strong>tu</strong> completi la configurazione di un conto bancario aziendale.`;
                     case CONST.NEXT_STEP.ACTOR_TYPE.OTHER_USER:
                         return `In attesa che <strong>${actor}</strong> completi la configurazione di un conto bancario aziendale.`;
                     case CONST.NEXT_STEP.ACTOR_TYPE.UNSPECIFIED_ADMIN:
                         return `In attesa che un amministratore completi la configurazione di un conto bancario aziendale.`;
                 }
             },
-            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_FOR_PAYMENT]: (
-                _actor: string,
-                _actorType: ValueOf<typeof CONST.NEXT_STEP.ACTOR_TYPE>,
-                eta?: string,
-                etaType?: ValueOf<typeof CONST.NEXT_STEP.ETA_TYPE>,
-            ) => {
+            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_FOR_PAYMENT]: ({eta, etaType}: NextStepParams) => {
                 let formattedETA = '';
                 if (eta) {
                     formattedETA = etaType === CONST.NEXT_STEP.ETA_TYPE.DATE_TIME ? `entro le ${eta}` : ` ${eta}`;
                 }
                 return `In attesa che il pagamento venga completato${formattedETA}.`;
             },
-            [CONST.NEXT_STEP.MESSAGE_KEY.SUBMITTING_TO_SELF]: (
-                _actor: string,
-                _actorType: ValueOf<typeof CONST.NEXT_STEP.ACTOR_TYPE>,
-                _eta?: string,
-                _etaType?: ValueOf<typeof CONST.NEXT_STEP.ETA_TYPE>,
-            ) =>
-                `Ops! Sembra che tu stia inviando il report a <strong>te stessə</strong>. L'approvazione dei tuoi stessi report è <strong>vietata</strong> dal tuo spazio di lavoro. Invia questo report a qualcun altro oppure contatta il tuo amministratore per modificare la persona a cui invii i report.`,
-            [CONST.NEXT_STEP.MESSAGE_KEY.REJECTED_REPORT]: (
-                actor: string,
-                actorType: ValueOf<typeof CONST.NEXT_STEP.ACTOR_TYPE>,
-                _eta?: string,
-                _etaType?: ValueOf<typeof CONST.NEXT_STEP.ETA_TYPE>,
-            ) => {
-                switch (actorType) {
-                    case CONST.NEXT_STEP.ACTOR_TYPE.CURRENT_USER:
-                        return `Questo report è stato rifiutato. In attesa che <strong>tu</strong> corregga i problemi e lo invii di nuovo manualmente.`;
-                    case CONST.NEXT_STEP.ACTOR_TYPE.OTHER_USER:
-                        return `Questo report è stato rifiutato. In attesa che <strong>${actor}</strong> risolva i problemi e lo invii di nuovo manualmente.`;
-                    case CONST.NEXT_STEP.ACTOR_TYPE.UNSPECIFIED_ADMIN:
-                        return `Questo report è stato rifiutato. In attesa che un amministratore risolva i problemi e lo invii di nuovo manualmente.`;
-                }
-            },
+            [CONST.NEXT_STEP.MESSAGE_KEY.SUBMITTING_TO_SELF]: (_: NextStepParams) =>
+                `Ops! Sembra che tu stia inviando il report a <strong>te stessə</strong>. Approvare i propri report è <strong>vietato</strong> dal tuo spazio di lavoro. Invia questo report a qualcun altro oppure contatta il tuo amministratore per cambiare la persona a cui lo invii.`,
         },
         eta: {
             [CONST.NEXT_STEP.ETA_KEY.SHORTLY]: 'presto',
@@ -1966,8 +1759,6 @@ const translations: TranslationDeepObject<typeof en> = {
         offline: 'Offline',
         syncing: 'Sincronizzazione',
         profileAvatar: 'Avatar profilo',
-        customInstructions: 'Istruzioni personalizzate',
-        copilotIntoAccount: "Copilot nell'account",
         publicSection: {
             title: 'Pubblico',
             subtitle: 'Questi dettagli vengono visualizzati nel tuo profilo pubblico. Chiunque può vederli.',
@@ -1976,16 +1767,12 @@ const translations: TranslationDeepObject<typeof en> = {
             title: 'Privato',
             subtitle: 'Questi dettagli vengono utilizzati per i viaggi e i pagamenti. Non vengono mai mostrati sul tuo profilo pubblico.',
         },
-        aiPromptSection: {
-            title: 'Prompt IA',
-            subtitle: 'Scrivi istruzioni personalizzate',
-            prompt: 'Prompt',
-            editPrompt: 'Modifica prompt',
-            promptCannotBeEmpty: 'Il prompt non può essere vuoto',
-            saved: 'Salvato',
-        },
     },
-    securityPage: {title: 'Sicurezza', subtitle: 'Tieni al sicuro il tuo account.', goToSecurity: 'Torna alla pagina di sicurezza'},
+    securityPage: {
+        title: 'Opzioni di sicurezza',
+        subtitle: 'Attiva l’autenticazione a due fattori per mantenere al sicuro il tuo account.',
+        goToSecurity: 'Torna alla pagina di sicurezza',
+    },
     shareCodePage: {
         title: 'Il tuo codice',
         subtitle: 'Invita membri su Expensify condividendo il tuo codice QR personale o il tuo link di riferimento.',
@@ -2023,7 +1810,6 @@ const translations: TranslationDeepObject<typeof en> = {
         },
         newContactMethod: 'Nuovo metodo di contatto',
         goBackContactMethods: 'Torna ai metodi di contatto',
-        yourDefaultContactMethodRestrictedSwitch: 'Questo è il tuo metodo di contatto predefinito attuale. La tua azienda ne ha limitato la rimozione o la modifica.',
     },
     pronouns: {
         coCos: 'Co / Cos',
@@ -2083,6 +1869,8 @@ const translations: TranslationDeepObject<typeof en> = {
         },
         troubleshoot: {
             clearCacheAndRestart: 'Cancella la cache e riavvia',
+            viewConsole: 'Visualizza console di debug',
+            debugConsole: 'Console di debug',
             description:
                 '<muted-text>Usa gli strumenti qui sotto per risolvere i problemi con Expensify. Se riscontri dei problemi, <concierge-link>invia una segnalazione di bug</concierge-link>.</muted-text>',
             confirmResetDescription: 'Tutti i messaggi in bozza non inviati andranno persi, ma il resto dei tuoi dati è al sicuro.',
@@ -2114,47 +1902,35 @@ const translations: TranslationDeepObject<typeof en> = {
             invalidateWithDelay: 'Invalidare con ritardo',
             leftHandNavCache: 'Cache di navigazione sinistra',
             clearleftHandNavCache: 'Pulisci',
+            recordTroubleshootData: 'Registra dati di diagnostica',
             softKillTheApp: "Termina dolcemente l'app",
             kill: 'Termina',
             sentryDebug: 'Debug Sentry',
-            sentrySendDescription: 'Invia dati a Sentry',
             sentryDebugDescription: 'Registra le richieste Sentry nella console',
             sentryHighlightedSpanOps: 'Nomi degli intervalli evidenziati',
             sentryHighlightedSpanOpsPlaceholder: 'ui.interaction.click, navigazione, ui.load',
-            showBranchNameInTitle: 'Mostra nome del ramo nel titolo del browser',
+        },
+        debugConsole: {
+            saveLog: 'Salva registro',
+            shareLog: 'Condividi registro',
+            enterCommand: 'Inserisci comando',
+            execute: 'Esegui',
+            noLogsAvailable: 'Nessun registro disponibile',
+            logSizeTooLarge: (size: number) => `La dimensione del registro supera il limite di ${size} MB. Usa “Salva registro” per scaricare il file di registro.`,
+            logs: 'Registri',
+            viewConsole: 'Visualizza console',
         },
         security: 'Sicurezza',
         signOut: 'Esci',
         restoreStashed: 'Ripristina accesso nascosto',
         signOutConfirmationText: 'Perderai tutte le modifiche offline se esci.',
         versionLetter: 'v',
-        readTheTermsAndPrivacy: `Leggi i <a href="${CONST.OLD_DOT_PUBLIC_URLS.TERMS_URL}">Termini di servizio</a> e l’<a href="${CONST.OLD_DOT_PUBLIC_URLS.PRIVACY_URL}">Informativa sulla privacy</a>.`,
+        readTheTermsAndPrivacy: `<muted-text-micro>Leggi i <a href="${CONST.OLD_DOT_PUBLIC_URLS.TERMS_URL}">Termini di servizio</a> e l’<a href="${CONST.OLD_DOT_PUBLIC_URLS.PRIVACY_URL}">Informativa sulla privacy</a>.</muted-text-micro>`,
         help: 'Aiuto',
         whatIsNew: 'Novità',
         accountSettings: 'Impostazioni account',
         account: 'Account',
         general: 'Generale',
-        helpPage: {
-            title: 'Aiuto e supporto',
-            description: 'Siamo qui per aiutarti, a qualsiasi ora.',
-            helpSite: 'Sito di assistenza',
-            helpSiteDescription: 'Articoli, tutorial e altro',
-            conciergeChat: 'Concierge',
-            conciergeChatDescription: 'Il tuo agente IA personale',
-            accountManager: 'Responsabile account',
-            yourAccountManager: 'Il tuo account manager',
-            accountManagerDescription: 'Fai domande e ottieni assistenza clienti',
-            partnerManager: 'Responsabile partner',
-            yourPartnerManager: 'Il tuo partner manager',
-            partnerManagerDescription: 'Massimizza la tua partnership e genera referral',
-            guideDescription: 'Il tuo account executive',
-            approvedPartnerTeamTitle: 'Incontra il tuo team partner Approved!',
-            approvedPartnerTeamDescription:
-                'Un team dedicato che ti aiuta a far crescere il tuo studio, ad attivare i clienti più velocemente e a ottenere supporto di esperti ogni volta che ne hai bisogno.',
-            accountExecutive: 'Account Executive',
-            accountExecutiveDescription: 'Configura correttamente i clienti',
-            moreResources: 'Altre risorse',
-        },
     },
     closeAccountPage: {
         closeAccount: 'Chiudi account',
@@ -2227,13 +2003,10 @@ const translations: TranslationDeepObject<typeof en> = {
         lockAccount: 'Blocca account',
         unlockAccount: 'Sblocca conto',
         compromisedDescription:
-            'Hai notato qualcosa di strano nel tuo account? Segnalarlo bloccherà immediatamente il tuo account, fermerà le nuove transazioni con la Carta Expensify e impedirà qualsiasi modifica all’account.',
-        domainAdminsDescription:
-            'Per gli amministratori di dominio: questo mette in pausa anche tutta l’attività della Carta Expensify e le azioni di amministratore in tutti i tuoi domini.',
+            'Hai notato qualcosa di strano sul tuo account? Segnalalo per bloccare immediatamente il tuo account, impedire nuove transazioni con la Expensify Card e prevenire qualsiasi modifica all’account.',
+        domainAdminsDescription: 'Per gli amministratori di dominio: questo mette anche in pausa tutte le attività delle Expensify Card e le azioni amministrative in tutti i tuoi domini.',
         areYouSure: 'Sei sicuro di voler bloccare il tuo account Expensify?',
         onceLocked: 'Una volta bloccato, il tuo account sarà limitato in attesa di una richiesta di sblocco e di una revisione di sicurezza',
-        unlockTitle: 'Abbiamo ricevuto la tua richiesta',
-        unlockDescription: 'Esamineremo l’account per verificare che sia sicuro sbloccarlo e ti contatteremo tramite Concierge per qualsiasi domanda.',
     },
     failedToLockAccountPage: {
         failedToLockAccount: 'Impossibile bloccare l’account',
@@ -2246,35 +2019,28 @@ const translations: TranslationDeepObject<typeof en> = {
         chatToConciergeToUnlock: 'Chatta con Concierge per risolvere i problemi di sicurezza e sbloccare il tuo account.',
         chatWithConcierge: 'Chatta con Concierge',
     },
-    deviceManagementPage: {
-        title: 'Gestione dei dispositivi',
-        description:
-            'Gestisci tutti i dispositivi su cui hai effettuato l\'accesso con il tuo account Expensify. <a href="https://help.expensify.com/articles/new-expensify/settings/Manage-Logged-in-Devices">Scopri di più</a>.',
-        revoke: 'Revoca',
-        unknownDevice: 'Dispositivo Sconosciuto',
-    },
     twoFactorAuth: {
         headerTitle: 'Autenticazione a due fattori',
         twoFactorAuthEnabled: 'Autenticazione a due fattori abilitata',
         whatIsTwoFactorAuth:
             'L’autenticazione a due fattori (2FA) contribuisce a mantenere il tuo account al sicuro. Quando effettui l’accesso, dovrai inserire un codice generato dalla tua app di autenticazione preferita.',
         disableTwoFactorAuth: 'Disattiva l’autenticazione a due fattori',
-        explainProcessToRemove: 'Per disabilitare l’autenticazione a due fattori (2FA), inserisci un codice valido dalla tua app di autenticazione.',
-        explainProcessToRemoveWithRecovery: 'Per disabilitare l’autenticazione a due fattori (2FA), inserisci un codice di recupero valido.',
+        explainProcessToRemove: 'Per disattivare l’autenticazione a due fattori (2FA), inserisci un codice valido dalla tua app di autenticazione.',
+        explainProcessToRemoveWithRecovery: 'Per disattivare l’autenticazione a due fattori (2FA), inserisci un codice di recupero valido.',
         disabled: "L'autenticazione a due fattori è ora disattivata",
         noAuthenticatorApp: 'Non sarà più necessaria un’app di autenticazione per accedere a Expensify.',
         stepCodes: 'Codici di recupero',
-        keepCodesSafe: 'Conserva questi codici al sicuro!',
+        keepCodesSafe: 'Conserva questi codici di recupero in un luogo sicuro!',
         codesLoseAccess: dedent(`
-            Se perdi l’accesso alla tua app di autenticazione e non hai questi codici, verrà bloccato l’accesso al tuo account.<br><br>
-            <strong>Nota</strong>: l’abilitazione della 2FA ti disconnette da tutte le altre sessioni.
+            Se perdi l'accesso alla tua app di autenticazione e non hai questi codici, perderai l'accesso al tuo account.
+
+            Nota: Configurare l'autenticazione a due fattori ti disconnetterà da tutte le altre sessioni attive.
         `),
         errorStepCodes: 'Copia o scarica i codici prima di continuare',
         stepVerify: 'Verifica',
         scanCode: 'Scansiona il codice QR usando il tuo',
         authenticatorApp: 'app di autenticazione',
         addKey: 'Oppure aggiungi questa chiave segreta alla tua app di autenticazione:',
-        secretKey: 'chiave segreta',
         enterCode: 'Quindi inserisci il codice a sei cifre generato dalla tua app di autenticazione.',
         stepSuccess: 'Completato',
         enabled: 'Autenticazione a due fattori abilitata',
@@ -2290,14 +2056,6 @@ const translations: TranslationDeepObject<typeof en> = {
         twoFactorAuthIsRequiredCompany: 'La tua azienda richiede l’autenticazione a due fattori.',
         twoFactorAuthCannotDisable: "Impossibile disabilitare l'autenticazione a due fattori",
         twoFactorAuthRequired: 'Per la connessione a Xero è richiesta l’autenticazione a due fattori (2FA) e non può essere disattivata.',
-        replaceDevice: 'Sostituisci dispositivo',
-        replaceDeviceTitle: 'Sostituisci dispositivo a due fattori',
-        verifyOldDeviceTitle: 'Verifica il vecchio dispositivo',
-        verifyOldDeviceDescription: 'Inserisci il codice a sei cifre dalla tua attuale app di autenticazione per confermare che hai accesso ad essa.',
-        verifyNewDeviceTitle: 'Configura nuovo dispositivo',
-        verifyNewDeviceDescription: 'Scansiona il codice QR con il tuo nuovo dispositivo, poi inserisci il codice per completare la configurazione.',
-        downloadCodes: 'Scarica codici',
-        copyCodes: 'Copia codici',
     },
     recoveryCodeForm: {
         error: {
@@ -2385,38 +2143,6 @@ const translations: TranslationDeepObject<typeof en> = {
             password: 'Inserisci la tua password Expensify',
         },
     },
-    personalCard: {
-        addPersonalCard: 'Aggiungi carta personale',
-        addCompanyCard: 'Aggiungi carta aziendale',
-        lookingForCompanyCards: 'Devi aggiungere carte aziendali?',
-        lookingForCompanyCardsDescription: 'Collega le tue carte da oltre 10.000 banche in tutto il mondo.',
-        personalCardAdded: 'Carta personale aggiunta!',
-        personalCardAddedDescription: 'Congratulazioni, inizieremo a importare le transazioni dalla tua carta.',
-        isPersonalCard: 'È una carta personale?',
-        thisIsPersonalCard: 'Questa è una carta personale',
-        thisIsCompanyCard: 'Questa è una carta aziendale',
-        askAdmin: 'Chiedi al tuo amministratore',
-        warningDescription: ({isAdmin}: {isAdmin?: boolean}) =>
-            `Se sì, ottimo! Ma se è una carta <strong>aziendale</strong>, ${isAdmin ? 'assegnala dal tuo spazio di lavoro.' : 'chiedi al tuo amministratore di assegnartela dallo spazio di lavoro.'}`,
-        bankConnectionError: 'Problema di connessione bancaria',
-        bankConnectionDescription: 'Riprova ad aggiungere le tue carte. Altrimenti puoi',
-        connectWithPlaid: 'connetterti tramite Plaid.',
-        fixCard: 'Correggi carta',
-        brokenConnection: 'La connessione della tua carta è interrotta.',
-        conciergeBrokenConnection: ({cardName, connectionLink}: ConciergeBrokenCardConnectionParams) =>
-            connectionLink
-                ? `La connessione della tua carta ${cardName} non funziona. <a href="${connectionLink}">Accedi alla tua banca</a> per sistemare la carta.`
-                : `La connessione della tua carta ${cardName} non funziona. Accedi alla tua banca per sistemare la carta.`,
-        addAdditionalCards: 'Aggiungi altre carte',
-        upgradeDescription: 'Devi aggiungere altre carte? Crea uno spazio di lavoro per aggiungere carte personali o assegnare carte aziendali a tutto il team.',
-        onlyAvailableOnPlan: ({formattedPrice}: {formattedPrice: string}) => `<muted-text>Disponibile nel piano Collect, <strong>${formattedPrice}</strong> per membro al mese.</muted-text>`,
-        note: (subscriptionLink: string) =>
-            `<muted-text>Crea uno spazio di lavoro per usare questa funzione, o <a href="${subscriptionLink}">scopri di più</a> su piani e prezzi.</muted-text>`,
-        workspaceCreated: 'Spazio di lavoro creato',
-        newWorkspace: 'Hai creato uno spazio di lavoro!',
-        successMessage: ({subscriptionLink}: {subscriptionLink: string}) =>
-            `<centered-text>Ora puoi aggiungere altre carte. <a href="${subscriptionLink}">Visualizza l'abbonamento</a> per i dettagli.</centered-text>`,
-    },
     walletPage: {
         balance: 'Saldo',
         paymentMethodsTitle: 'Metodi di pagamento',
@@ -2444,9 +2170,8 @@ const translations: TranslationDeepObject<typeof en> = {
         enableWallet: 'Abilita portafoglio',
         addBankAccountToSendAndReceive: 'Aggiungi un conto bancario per effettuare o ricevere pagamenti.',
         addDebitOrCreditCard: 'Aggiungi carta di debito o di credito',
-        cardInactive: 'Inattivo',
-        assignedCards: 'Carte',
-        assignedCardsDescription: 'Le transazioni delle carte assegnate si sincronizzano automaticamente.',
+        assignedCards: 'Carte assegnate',
+        assignedCardsDescription: 'Le transazioni di queste carte si sincronizzano automaticamente.',
         expensifyCard: 'Carta Expensify',
         walletActivationPending: 'Stiamo verificando le tue informazioni. Riprova tra qualche minuto!',
         walletActivationFailed: 'Sfortunatamente, il tuo portafoglio non può essere abilitato in questo momento. Chatta con Concierge per ulteriore assistenza.',
@@ -2470,13 +2195,8 @@ const translations: TranslationDeepObject<typeof en> = {
         unshareBankAccountDescription:
             'Tutte le persone elencate di seguito hanno accesso a questo conto bancario. Puoi revocare l’accesso in qualsiasi momento. Completeremo comunque tutti i pagamenti in corso.',
         unshareBankAccountWarning: ({admin}: {admin?: string | null}) => `${admin} perderà l’accesso a questo conto bancario aziendale. Completeremo comunque tutti i pagamenti in corso.`,
-        reachOutForHelp: 'Viene utilizzata con la Carta Expensify. <concierge-link>Contatta Concierge</concierge-link> se hai bisogno di interrompere la condivisione.',
+        reachOutForHelp: 'Viene usato con la Expensify Card. <concierge-link>Contatta Concierge</concierge-link> se hai bisogno di interrompere la condivisione.',
         unshareErrorModalTitle: 'Impossibile annullare la condivisione del conto bancario',
-        travelCVV: {
-            title: 'CVV di viaggio',
-            subtitle: 'Usa questo quando prenoti viaggi',
-            description: 'Usa questa carta per le tue prenotazioni con Expensify Travel. Verrà visualizzata come “Travel Card” al momento del pagamento.',
-        },
         chaseAccountNumberDifferent: 'Perché il mio numero di conto è diverso?',
     },
     cardPage: {
@@ -2485,15 +2205,17 @@ const translations: TranslationDeepObject<typeof en> = {
         availableSpend: 'Limite rimanente',
         smartLimit: {
             name: 'Limite intelligente',
-            title: (formattedLimit: string) => `Puoi spendere fino a ${formattedLimit} con questa carta e il limite verrà reimpostato man mano che le tue spese inviate vengono approvate.`,
+            title: ({formattedLimit}: ViolationsOverLimitParams) =>
+                `Puoi spendere fino a ${formattedLimit} con questa carta e il limite verrà reimpostato man mano che le tue spese inviate vengono approvate.`,
         },
         fixedLimit: {
             name: 'Limite fisso',
-            title: (formattedLimit: string) => `Puoi spendere fino a ${formattedLimit} con questa carta, dopodiché verrà disattivata.`,
+            title: ({formattedLimit}: ViolationsOverLimitParams) => `Puoi spendere fino a ${formattedLimit} con questa carta, dopodiché verrà disattivata.`,
         },
         monthlyLimit: {
             name: 'Limite mensile',
-            title: (formattedLimit: string) => `Puoi spendere fino a ${formattedLimit} al mese con questa carta. Il limite verrà reimpostato il primo giorno di ogni mese di calendario.`,
+            title: ({formattedLimit}: ViolationsOverLimitParams) =>
+                `Puoi spendere fino a ${formattedLimit} al mese con questa carta. Il limite verrà reimpostato il primo giorno di ogni mese di calendario.`,
         },
         virtualCardNumber: 'Numero carta virtuale',
         travelCardCvv: 'CVV carta viaggio',
@@ -2514,11 +2236,9 @@ const translations: TranslationDeepObject<typeof en> = {
             expiration: 'Scadenza',
             cvv: 'CVV',
             address: 'Indirizzo',
-            reveal: 'Mostra',
             revealDetails: 'Mostra dettagli',
             revealCvv: 'Mostra CVV',
             copyCardNumber: 'Copia numero carta',
-            copyCvv: 'Copia CVV',
             updateAddress: 'Aggiorna indirizzo',
         },
         cardAddedToWallet: ({platform}: {platform: 'Google' | 'Apple'}) => `Aggiunto al portafoglio ${platform}`,
@@ -2526,6 +2246,7 @@ const translations: TranslationDeepObject<typeof en> = {
         validateCardTitle: 'Verifichiamo che sia davvero tu',
         enterMagicCode: (contactMethod: string) =>
             `Inserisci il codice magico inviato a ${contactMethod} per visualizzare i dettagli della tua carta. Dovrebbe arrivare entro uno o due minuti.`,
+        missingPrivateDetails: ({missingDetailsLink}: {missingDetailsLink: string}) => `Per favore <a href="${missingDetailsLink}">aggiungi i tuoi dati personali</a>, quindi riprova.`,
         unexpectedError: 'Si è verificato un errore durante il recupero dei dettagli della tua carta Expensify. Riprova.',
         cardFraudAlert: {
             confirmButtonText: 'Sì, lo voglio',
@@ -2547,42 +2268,6 @@ const translations: TranslationDeepObject<typeof en> = {
 
 ${amount} per ${merchant} - ${date}`,
         },
-        setYourPin: 'Imposta il tuo PIN.',
-        confirmYourPin: 'Conferma il tuo PIN.',
-        changeYourPin: 'Inserisci un nuovo PIN per la tua carta.',
-        confirmYourChangedPin: 'Conferma il tuo nuovo PIN.',
-        pinMustBeFourDigits: 'Il PIN deve essere composto da esattamente 4 cifre.',
-        invalidPin: 'Scegli un PIN più sicuro.',
-        pinMismatch: 'I PIN non corrispondono. Riprova.',
-        revealPin: 'Mostra PIN',
-        hidePin: 'Nascondi PIN',
-        pin: 'PIN',
-        changePin: 'Cambia PIN',
-        pinChanged: 'PIN cambiato!',
-        pinChangedHeader: 'PIN modificato',
-        pinChangedDescription: 'Ora sei pronto a usare il tuo PIN.',
-        changePinAtATM: 'Cambia il tuo PIN a qualsiasi bancomat',
-        changePinAtATMDescription: 'Questo è obbligatorio nella tua regione. <concierge-link>Contatta Concierge</concierge-link> se hai domande.',
-        freezeCard: 'Blocca carta',
-        unfreeze: 'Sblocca',
-        unfreezeCard: 'Sblocca carta',
-        askToUnfreeze: 'Richiedi sblocco',
-        freezeDescription: 'Una carta bloccata non può essere usata per acquisti e transazioni. Puoi sbloccarla in qualsiasi momento.',
-        unfreezeDescription: 'Sbloccando questa carta torneranno ad essere consentiti acquisti e transazioni. Procedi solo se sei sicuro che la carta sia sicura da usare.',
-        frozen: 'Bloccata',
-        youFroze: ({date}: {date: string}) => `Hai bloccato questa carta il ${date}.`,
-        frozenBy: ({person, date}: {person: string; date: string}) => `${person} ha bloccato questa carta il ${date}.`,
-        frozenByAdminPrefix: ({date}: {date: string}) => `Questa carta è stata bloccata il ${date} da `,
-        frozenByAdminNeedsUnfreezePrefix: 'Questa carta è stata bloccata da ',
-        frozenByAdminNeedsUnfreezeSuffix: '. Contatta un amministratore per sbloccarla.',
-        frozenByAdminNeedsUnfreeze: ({person}: {person: string}) => `Questa carta è stata bloccata da ${person}. Contatta un amministratore per sbloccarla.`,
-        spendRules: 'Regole di spesa',
-        editSpendRules: 'Modifica regole di spesa',
-        cardUnblocked: 'Carta sbloccata!',
-        cardUnblockedDescription: 'Potrebbe esserti richiesto di inserire la carta nel lettore la prossima volta che effettui un acquisto.',
-        pinBlocked: 'La tua carta è stata bloccata a causa di PIN inseriti in modo errato.',
-        unblock: 'Sblocca',
-        unblockCard: 'Sblocca carta',
     },
     workflowsPage: {
         workflowTitle: 'Spesa',
@@ -2594,14 +2279,9 @@ ${amount} per ${merchant} - ${date}`,
         addApprovalsTitle: 'Approvazioni',
         accessibilityLabel: ({members, approvers}: {members: string; approvers: string}) => `spese di ${members} e l'approvatore è ${approvers}`,
         addApprovalButton: 'Aggiungi flusso di approvazione',
-        editWorkflowAction: 'Modifica',
-        addAgentAction: 'Aggiungi agente',
-        findWorkflow: 'Cerca flusso di lavoro',
         addApprovalTip: 'Questo flusso di lavoro predefinito si applica a tutti i membri, a meno che non esista un flusso di lavoro più specifico.',
         approver: 'Approvante',
         addApprovalsDescription: 'Richiedi un’approvazione aggiuntiva prima di autorizzare un pagamento.',
-        automateApprovalsWithAgentsTitle: 'Automatizza le approvazioni con gli agenti',
-        automateApprovalsWithAgentsSubtitle: 'Aggiungi l’agente qui sotto al workflow per automatizzare le approvazioni.',
         makeOrTrackPaymentsTitle: 'Pagamenti',
         makeOrTrackPaymentsDescription: 'Aggiungi un pagatore autorizzato per i pagamenti effettuati in Expensify o tieni traccia dei pagamenti effettuati altrove.',
         customApprovalWorkflowEnabled:
@@ -2646,15 +2326,7 @@ ${amount} per ${merchant} - ${date}`,
             title: 'Nessun membro da visualizzare',
             expensesFromSubtitle: 'Tutti i membri dello spazio di lavoro appartengono già a un flusso di approvazione esistente.',
             approverSubtitle: 'Tutti gli approvatori appartengono a un workflow esistente.',
-            bulkApproverSubtitle: 'Nessun approvatore corrisponde ai criteri per i report selezionati.',
         },
-        configureViaHR: ({provider}: {provider: string}) => `Configura tramite ${provider}.`,
-        hrApprovalWorkflowLockedPrompt: ({provider}: {provider: string}) =>
-            `Le approvazioni sono gestite dalla tua integrazione con ${provider}. Per aggiornare il flusso di approvazione, vai alle impostazioni di connessione di ${provider}.`,
-        goToHRSettings: ({provider}: {provider: string}) => `Vai alle impostazioni di ${provider}`,
-        approverFromProvider: ({provider}: {provider: string}) => `da ${provider}`,
-        finalApprover: 'Approvazione finale',
-        manager: 'Responsabile',
     },
     workflowsDelayedSubmissionPage: {
         autoReportingFrequencyErrorMessage: 'Impossibile modificare la frequenza di invio. Riprova oppure contatta l’assistenza.',
@@ -2674,9 +2346,6 @@ ${amount} per ${merchant} - ${date}`,
     workflowsExpensesFromPage: {
         title: 'Spese dal',
         header: 'Quando i seguenti membri inviano note spese:',
-        memberAlreadyInWorkflowTitle: 'Membro già in un flusso di lavoro',
-        memberAlreadyInWorkflowPrompt: ({memberName, approverName}: {memberName: string; approverName: string}) =>
-            `${memberName} è già in un flusso di approvazione che invia a ${approverName}. Aggiungendolo qui lo sposterà in questo flusso di lavoro.`,
     },
     workflowsApproverPage: {
         genericErrorMessage: "Non è stato possibile modificare l'approvatore. Riprova o contatta l'assistenza.",
@@ -2707,16 +2376,6 @@ ${amount} per ${merchant} - ${date}`,
         admins: 'Amministratori',
         payer: 'Pagatore',
         paymentAccount: 'Conto di pagamento',
-        shareBankAccount: {
-            shareTitle: "Condividere l'accesso al conto bancario?",
-            shareDescription: ({admin}: {admin: string}) => `Dovrai condividere l'accesso al conto bancario con ${admin} per renderlo il pagatore.`,
-            validationTitle: 'Conto bancario in attesa di convalida',
-            validationDescription: ({admin}: {admin: string}) =>
-                `Devi <a href="#">convalidare questo conto bancario</a>. Una volta fatto, puoi condividere l'accesso al conto bancario con ${admin} per renderlo il pagatore.`,
-            errorTitle: 'Impossibile cambiare il pagatore',
-            errorDescription: ({admin, owner}: {admin: string; owner: string}) =>
-                `${admin} non ha accesso a questo conto bancario, quindi non puoi impostarlo come pagatore. <a href="#">Chatta con ${owner}</a> se il conto bancario deve essere condiviso.`,
-        },
     },
     reportFraudPage: {
         title: 'Segnala frode con carta virtuale',
@@ -2728,7 +2387,6 @@ ${amount} per ${merchant} - ${date}`,
     reportFraudConfirmationPage: {
         title: 'Frode della carta segnalata',
         description: 'Abbiamo disattivato definitivamente la tua carta esistente. Quando tornerai a visualizzare i dettagli della carta, avrai a disposizione una nuova carta virtuale.',
-        descriptionCardNotReplaced: 'La tua carta è stata disattivata permanentemente. Contatta un amministratore per emettere una nuova carta.',
         buttonText: 'Ricevuto, grazie!',
     },
     activateCardPage: {
@@ -2738,7 +2396,7 @@ ${amount} per ${merchant} - ${date}`,
         error: {
             thatDidNotMatch: 'Quello non corrispondeva alle ultime 4 cifre della tua carta. Riprova.',
             throttled:
-                'Hai inserito illeggittimamente le ultime 4 cifre della tua Carta Expensify troppe volte. Se sei sicuro che i numeri siano corretti, contatta Concierge per risolvere il problema. Altrimenti, riprova più tardi.',
+                'Hai inserito in modo errato le ultime 4 cifre della tua Expensify Card troppe volte. Se sei sicuro che i numeri siano corretti, contatta Concierge per risolvere il problema. In caso contrario, riprova più tardi.',
         },
     },
     getPhysicalCard: {
@@ -2763,7 +2421,7 @@ ${amount} per ${merchant} - ${date}`,
         shipCard: 'Spedisci carta',
     },
     transferAmountPage: {
-        transfer: (amount: string) => `Trasferisci${amount ? ` ${amount}` : ''}`,
+        transfer: ({amount}: TransferParams) => `Trasferisci${amount ? ` ${amount}` : ''}`,
         instant: 'Immediato (carta di debito)',
         instantSummary: (rate: string, minAmount: string) => `Commissione del ${rate}% (${minAmount} minimo)`,
         ach: '1-3 giorni lavorativi (conto bancario)',
@@ -2790,46 +2448,14 @@ ${amount} per ${merchant} - ${date}`,
         defaultPaymentMethod: 'Predefinito',
         bankAccountLastFour: (lastFour: string) => `Conto bancario • ${lastFour}`,
     },
-    agentsPage: {
-        title: 'Agenti',
-        subtitle: 'Crea agenti per gestire il tuo flusso di lavoro. Elimina il lavoro manuale e recupera ore della tua giornata.',
-        newAgent: 'Nuovo agente',
-        emptyAgents: {title: 'Nessun agente creato', subtitle: 'Smetti di fare le cose manualmente. Dai istruzioni a un agente e risparmia un sacco di tempo.'},
-        error: {
-            genericAdd: "Si è verificato un problema durante l'aggiunta di questo agente",
-            genericUpdate: "Si è verificato un problema durante l'aggiornamento di questo agente",
-            updateName: "Si è verificato un problema durante l'aggiornamento del nome di questo agente",
-            updatePrompt: "Si è verificato un problema durante l'aggiornamento delle istruzioni di questo agente",
-            updateAvatar: "Si è verificato un problema durante l'aggiornamento dell'avatar di questo agente",
-        },
-    },
-    addAgentPage: {
-        title: 'Nuovo agente',
-        agentName: 'Nome agente',
-        instructions: 'Scrivi istruzioni personalizzate',
-        createAgent: 'Crea agente',
-        editAvatar: 'Cambia avatar',
-        defaultAgentName: (displayName: string) => `Agente di ${displayName}`,
-        defaultPrompt:
-            "Rifiuta le spese relative a gioco d'azzardo, cinema o altri motivi chiaramente non legati all'attività.\n\nRicorda all'utente di includere sempre un'immagine della ricevuta in cui la mancia sia ben visibile.\n\nApprova il report se è molto simile ai report precedenti dello stesso utente.\n\nRifiuta i report con più di 500 $ di spese di viaggio.",
-    },
-    editAgentPage: {
-        title: 'Modifica agente',
-        agentName: 'Nome agente',
-        instructions: 'Scrivi istruzioni personalizzate',
-        chatWithAgent: 'Chatta con l’agente',
-        copilotIntoAccount: 'Copilot nell’account',
-        deleteAgent: 'Elimina agente',
-        deleteAgentTitle: 'Eliminare agente?',
-        deleteAgentMessage: 'Sei sicuro di voler eliminare questo agente? Questa azione non può essere annullata.',
-    },
-    editAgentAvatarPage: {title: 'Modifica avatar'},
-    editAgentNamePage: {title: 'Nome agente'},
-    editAgentPromptPage: {title: 'Scrivi istruzioni personalizzate', error: {emptyPrompt: 'Inserisci le istruzioni per il tuo agente.'}},
     expenseRulesPage: {
         title: 'Regole spese',
+        subtitle: 'Queste regole saranno applicate alle tue spese. Se le invii a un workspace, le regole del workspace potrebbero sostituirle.',
         findRule: 'Trova regola',
-        emptyRules: {title: 'Ancuna nessuna regola', subtitle: 'Aggiungi una regola per automatizzare la rendicontazione delle spese.'},
+        emptyRules: {
+            title: 'Non hai creato alcuna regola',
+            subtitle: 'Aggiungi una regola per automatizzare la rendicontazione delle spese.',
+        },
         changes: {
             billableUpdate: (value: boolean) => `Aggiorna spesa ${value ? 'fatturabile' : 'non fatturabile'}`,
             categoryUpdate: (value: string) => `Aggiorna categoria in “${value}”`,
@@ -2870,7 +2496,6 @@ ${amount} per ${merchant} - ${date}`,
             deleteSinglePrompt: 'Sei sicuro di voler eliminare questa regola?',
             deleteMultiplePrompt: 'Sei sicuro di voler eliminare queste regole?',
         },
-        subtitle: 'Queste regole verranno applicate alle tue spese.',
     },
     preferencesPage: {
         appSection: {
@@ -2898,12 +2523,11 @@ ${amount} per ${merchant} - ${date}`,
         },
     },
     reportDetailsPage: {
-        inWorkspace: (policyName: string) => `in ${policyName}`,
+        inWorkspace: ({policyName}: ReportPolicyNameParams) => `in ${policyName}`,
         generatingPDF: 'Genera PDF',
         waitForPDF: 'Attendi mentre generiamo il PDF.',
         errorPDF: 'Si è verificato un errore durante il tentativo di generare il tuo PDF',
         successPDF: 'Il tuo PDF è stato generato! Se non è stato scaricato automaticamente, usa il pulsante qui sotto.',
-        goToRoom: 'Vai alla stanza',
     },
     reportDescriptionPage: {
         roomDescription: 'Descrizione stanza',
@@ -2913,7 +2537,7 @@ ${amount} per ${merchant} - ${date}`,
     groupChat: {
         lastMemberTitle: 'Attenzione!',
         lastMemberWarning: 'Dato che sei l’ultima persona qui, se lasci la chat diventerà inaccessibile a tutti i membri. Sei sicuro di voler uscire?',
-        defaultReportName: (displayName: string) => `Chat di gruppo di ${displayName}`,
+        defaultReportName: ({displayName}: ReportArchiveReasonsClosedParams) => `Chat di gruppo di ${displayName}`,
     },
     languagePage: {
         language: 'Lingua',
@@ -2932,26 +2556,19 @@ ${amount} per ${merchant} - ${date}`,
                 label: 'Usa le impostazioni del dispositivo',
             },
         },
-        highContrastMode: 'Modalità alto contrasto',
-        enableHighContrast: 'Attiva alto contrasto',
-        disableHighContrast: 'Disattiva alto contrasto',
         chooseThemeBelowOrSync: 'Scegli un tema qui sotto o sincronizza con le impostazioni del tuo dispositivo.',
     },
     termsOfUse: {
         terms: `<muted-text-xs>Accedendo, accetti i <a href="${CONST.OLD_DOT_PUBLIC_URLS.TERMS_URL}">Termini di servizio</a> e l’<a href="${CONST.OLD_DOT_PUBLIC_URLS.PRIVACY_URL}">Informativa sulla privacy</a>.</muted-text-xs>`,
-        license: `L’attività di trasmissione di denaro è fornita da ${CONST.WALLET.PROGRAM_ISSUERS.EXPENSIFY_PAYMENTS} (NMLS ID:2017010) in conformità alle sue <a href="${CONST.OLD_DOT_PUBLIC_URLS.LICENSES_URL}">licenze</a>.`,
+        license: `<muted-text-xs>Il servizio di trasferimento di denaro è fornito da ${CONST.WALLET.PROGRAM_ISSUERS.EXPENSIFY_PAYMENTS} (NMLS ID:2017010) in conformità alle sue <a href="${CONST.OLD_DOT_PUBLIC_URLS.LICENSES_URL}">licenze</a>.</muted-text-xs>`,
     },
     validateCodeForm: {
         magicCodeNotReceived: 'Non hai ricevuto un codice magico?',
-        avoidScamsMessage:
-            '<strong>Evita le truffe. Non condividere il tuo codice con nessuno.</strong> Il nostro team non ti chiamerà, invierà SMS o manderà email per chiederti questo codice.',
         enterAuthenticatorCode: "Inserisci il tuo codice dell'autenticatore",
         enterRecoveryCode: 'Inserisci il tuo codice di recupero',
         requiredWhen2FAEnabled: 'Obbligatorio quando l’autenticazione a due fattori è abilitata',
         requestNewCode: ({timeRemaining}: {timeRemaining: string}) => `Richiedi un nuovo codice tra <a>${timeRemaining}</a>`,
         requestNewCodeAfterErrorOccurred: 'Richiedi un nuovo codice',
-        timeRemainingAnnouncement: ({timeRemaining}) => `Tempo rimanente: ${timeRemaining} ${timeRemaining === 1 ? 'secondo' : 'secondi'}`,
-        timeExpiredAnnouncement: 'Il tempo è scaduto',
         error: {
             pleaseFillMagicCode: 'Inserisci il tuo codice magico',
             incorrectMagicCode: 'Codice magico errato o non valido. Riprova o richiedi un nuovo codice.',
@@ -2981,7 +2598,6 @@ ${amount} per ${merchant} - ${date}`,
     loginForm: {
         phoneOrEmail: 'Telefono o email',
         error: {
-            agentSignInBlocked: 'Non puoi accedere direttamente agli account agente. Per usare un agente, accedi con il tuo account e raggiungilo tramite Copilot.',
             invalidFormatEmailLogin: 'L’email inserita non è valida. Correggi il formato e riprova.',
         },
         cannotGetAccountDetails: 'Impossibile recuperare i dettagli dell’account. Prova ad accedere di nuovo.',
@@ -2999,40 +2615,29 @@ ${amount} per ${merchant} - ${date}`,
         },
         getStarted: 'Inizia',
         whatsYourName: 'Come ti chiami?',
-        peopleYouMayKnow: 'Verifica se il tuo team è su Expensify',
-        workspaceYouMayJoin: (domain: string, email: string) => `Inserisci il codice inviato a ${email} per verificare se qualcuno di ${domain} ha uno spazio di lavoro a cui puoi unirti.`,
+        peopleYouMayKnow: 'Alcune persone che potresti conoscere sono già qui! Verifica la tua email per unirti a loro.',
+        workspaceYouMayJoin: ({domain, email}: WorkspaceYouMayJoin) => `Qualcuno di ${domain} ha già creato uno spazio di lavoro. Inserisci il codice magico inviato a ${email}.`,
         joinAWorkspace: 'Unisciti a uno spazio di lavoro',
-        listOfWorkspaces: "Ecco l'elenco degli spazi di lavoro a cui puoi unirti.",
-        skipForNow: 'Salta per ora',
-        workspaceMemberList: (employeeCount: number, policyOwner: string) => `${employeeCount} membro${employeeCount > 1 ? 's' : ''} • ${policyOwner}`,
+        listOfWorkspaces: "Ecco l'elenco degli spazi di lavoro a cui puoi unirti. Non preoccuparti, potrai sempre unirti anche in un secondo momento, se preferisci.",
+        workspaceMemberList: ({employeeCount, policyOwner}: WorkspaceMemberList) => `${employeeCount} membro${employeeCount > 1 ? 's' : ''} • ${policyOwner}`,
         whereYouWork: 'Dove lavori?',
         errorSelection: 'Seleziona un’opzione per procedere',
         purpose: {
             title: 'Cosa vuoi fare oggi?',
             errorContinue: 'Premi Continua per completare la configurazione',
             errorBackButton: 'Completa le domande di configurazione per iniziare a usare l’app',
-            [CONST.ONBOARDING_CHOICES.EMPLOYER]: 'Inviare le spese al mio datore di lavoro',
+            [CONST.ONBOARDING_CHOICES.EMPLOYER]: 'Essere rimborsato dal mio datore di lavoro',
             [CONST.ONBOARDING_CHOICES.MANAGE_TEAM]: 'Gestisci le spese del mio team',
-            [CONST.ONBOARDING_CHOICES.TRACK_BUSINESS]: 'Tieni traccia delle spese aziendali',
-            [CONST.ONBOARDING_CHOICES.TRACK_PERSONAL]: 'Organizza le mie spese personali',
+            [CONST.ONBOARDING_CHOICES.PERSONAL_SPEND]: 'Tieni traccia delle spese e del budget',
+            [CONST.ONBOARDING_CHOICES.CHAT_SPLIT]: 'Chatta e dividi le spese con gli amici',
             [CONST.ONBOARDING_CHOICES.LOOKING_AROUND]: 'Altro',
         },
-        personalTrackGoal: {
-            title: 'Che cosa vuoi tenere traccia?',
-            [CONST.ONBOARDING_PERSONAL_TRACK_GOALS.INVESTMENT_TRACKING]: 'Costi per un immobile a scopo di investimento',
-            [CONST.ONBOARDING_PERSONAL_TRACK_GOALS.HOUSEHOLD_TRACKING]: 'Spese domestiche',
-            [CONST.ONBOARDING_PERSONAL_TRACK_GOALS.SIDEPROJECT_TRACKING]: 'Spese per progetti secondari',
-            [CONST.ONBOARDING_PERSONAL_TRACK_GOALS.SOMETHING_ELSE]: 'Altro',
-            somethingElsePlaceholder: 'Cosa stai monitorando?',
-        },
         employees: {
             title: 'Quanti dipendenti hai?',
-            [CONST.ONBOARDING_COMPANY_SIZE.MICRO_SMALL]: '1-4 dipendenti',
-            [CONST.ONBOARDING_COMPANY_SIZE.MICRO_MEDIUM]: '5-10 dipendenti',
             [CONST.ONBOARDING_COMPANY_SIZE.MICRO]: '1-10 dipendenti',
             [CONST.ONBOARDING_COMPANY_SIZE.SMALL]: '11-50 dipendenti',
             [CONST.ONBOARDING_COMPANY_SIZE.MEDIUM_SMALL]: '51-100 dipendenti',
-            [CONST.ONBOARDING_COMPANY_SIZE.MEDIUM]: 'Da 101 a 1.000 dipendenti',
+            [CONST.ONBOARDING_COMPANY_SIZE.MEDIUM]: '101-1.000 dipendenti',
             [CONST.ONBOARDING_COMPANY_SIZE.LARGE]: 'Più di 1.000 dipendenti',
         },
         accounting: {
@@ -3059,19 +2664,16 @@ ${amount} per ${merchant} - ${date}`,
         },
         workEmailValidation: {
             title: 'Verifica la tua email di lavoro',
-            magicCodeSent: (workEmail: string | undefined) => `Inserisci il codice magico inviato a ${workEmail}. Dovrebbe arrivare tra un minuto o due.`,
+            magicCodeSent: ({workEmail}: WorkEmailResendCodeParams) => `Inserisci il codice magico inviato a ${workEmail}. Dovrebbe arrivare tra un minuto o due.`,
         },
         workEmailValidationError: {
             publicEmail: 'Inserisci un’email di lavoro valida con dominio privato, ad es. mitch@company.com',
-            sameAsSignupEmail: 'Inserisci un’email diversa da quella con cui ti sei registrato',
             offline: 'Non è stato possibile aggiungere la tua email di lavoro perché sembri offline',
         },
         mergeBlockScreen: {
             title: "Impossibile aggiungere l'email di lavoro",
-            subtitle: (workEmail: string | undefined) =>
+            subtitle: ({workEmail}: WorkEmailMergingBlockedParams) =>
                 `Non è stato possibile aggiungere ${workEmail}. Riprova più tardi in Impostazioni oppure chatta con Concierge per ricevere assistenza.`,
-            workAccountClosedSubtitle:
-                'L’account di lavoro associato a questa email è chiuso. Contatta l’amministratore della tua azienda per riattivarlo oppure registrati con un’altra email.',
         },
         tasks: {
             testDriveAdminTask: {
@@ -3102,7 +2704,7 @@ ${amount} per ${merchant} - ${date}`,
             },
             createTestDriveAdminWorkspaceTask: {
                 title: ({workspaceConfirmationLink}) => `[Crea](${workspaceConfirmationLink}) uno spazio di lavoro`,
-                description: 'Crea uno spazio di lavoro e configura le impostazioni con l’aiuto del tuo account executive!',
+                description: 'Crea uno spazio di lavoro e configura le impostazioni con l’aiuto del tuo/tuа specialista di configurazione!',
             },
             createWorkspaceTask: {
                 title: ({workspaceSettingsLink}) => `Crea uno [spazio di lavoro](${workspaceSettingsLink})`,
@@ -3118,11 +2720,11 @@ ${amount} per ${merchant} - ${date}`,
                 title: ({workspaceCategoriesLink}) => `Configura le [categorie](${workspaceCategoriesLink})`,
                 description: ({workspaceCategoriesLink}) =>
                     dedent(`
-                        *Configura le categorie* in modo che il tuo team possa codificare le spese per creare report facilmente.
+                        *Configura le categorie* in modo che il tuo team possa classificare le spese per una rendicontazione più semplice.
 
-                        1. Fai clic su *Spazi di lavoro*.
-                        2. Seleziona il tuo spazio di lavoro.
-                        3. Fai clic su *Categorie*.
+                        1. Fai clic su *Workspaces*.
+                        2. Seleziona il tuo workspace.
+                        3. Fai clic su *Categories*.
                         4. Disattiva le categorie di cui non hai bisogno.
                         5. Aggiungi le tue categorie in alto a destra.
 
@@ -3134,7 +2736,7 @@ ${amount} per ${merchant} - ${date}`,
                 description: dedent(`
                     *Invia una spesa* inserendo un importo o scansionando una ricevuta.
 
-                    1. Fai clic sul pulsante *+*.
+                    1. Fai clic sul pulsante ${CONST.CUSTOM_EMOJIS.GLOBAL_CREATE}.
                     2. Scegli *Crea spesa*.
                     3. Inserisci un importo o scansiona una ricevuta.
                     4. Aggiungi l’email o il numero di telefono del tuo responsabile.
@@ -3148,7 +2750,7 @@ ${amount} per ${merchant} - ${date}`,
                 description: dedent(`
                     *Invia una spesa* inserendo un importo o scansionando una ricevuta.
 
-                    1. Fai clic sul pulsante *+*.
+                    1. Fai clic sul pulsante ${CONST.CUSTOM_EMOJIS.GLOBAL_CREATE}.
                     2. Scegli *Crea spesa*.
                     3. Inserisci un importo o scansiona una ricevuta.
                     4. Conferma i dettagli.
@@ -3162,7 +2764,7 @@ ${amount} per ${merchant} - ${date}`,
                 description: dedent(`
                     *Registra una spesa* in qualsiasi valuta, che tu abbia una ricevuta o meno.
 
-                    1. Fai clic sul pulsante *+*.
+                    1. Fai clic sul pulsante ${CONST.CUSTOM_EMOJIS.GLOBAL_CREATE}.
                     2. Scegli *Crea spesa*.
                     3. Inserisci un importo oppure scansiona una ricevuta.
                     4. Scegli il tuo spazio *personale*.
@@ -3184,8 +2786,13 @@ ${amount} per ${merchant} - ${date}`,
                         4. Trova ${integrationName}.
                         5. Fai clic su *Connetti*.
 
-                        [Portami alla contabilità](${workspaceAccountingLink}).
-                    `),
+${
+    integrationName && CONST.connectionsVideoPaths[integrationName]
+        ? `[Portami alla contabilità](${workspaceAccountingLink}).
+
+                        ![Connetti a ${integrationName}](${CONST.CLOUDFRONT_URL}/${CONST.connectionsVideoPaths[integrationName]})`
+        : `[Portami alla contabilità](${workspaceAccountingLink}).`
+}`),
             },
             connectCorporateCardTask: {
                 title: ({corporateCardLink}) => `Collega [le tue carte aziendali](${corporateCardLink})`,
@@ -3206,11 +2813,11 @@ ${amount} per ${merchant} - ${date}`,
                     dedent(`
                         *Invita il tuo team* su Expensify così potrà iniziare a tracciare le spese oggi stesso.
 
-                        1. Fai clic su *Workspaces*.
-                        2. Seleziona il tuo workspace.
-                        3. Fai clic su *Members* > *Invite member*.
+                        1. Fai clic su *Spazi di lavoro*.
+                        2. Seleziona il tuo spazio di lavoro.
+                        3. Fai clic su *Membri* > *Invita membro*.
                         4. Inserisci email o numeri di telefono.
-                        5. Aggiungi un messaggio di invito personalizzato se vuoi!
+                        5. Aggiungi un messaggio di invito personalizzato, se vuoi!
 
                         [Portami ai membri dello spazio di lavoro](${workspaceMembersLink}).
                     `),
@@ -3227,16 +2834,16 @@ ${amount} per ${merchant} - ${date}`,
                 title: ({workspaceTagsLink}) => `Configura i [tag](${workspaceTagsLink})`,
                 description: ({workspaceMoreFeaturesLink}) =>
                     dedent(`
-                        Usa i tag per aggiungere dettagli extra alle spese, come progetti, clienti, sedi e reparti. Se ti servono più livelli di tag, puoi passare al piano Control.
+                        Usa i tag per aggiungere dettagli extra alle spese, come progetti, clienti, sedi e reparti. Se ti servono più livelli di tag, puoi eseguire l’upgrade al piano Control.
 
-                        1. Fai clic su *Spazi di lavoro*.
-                        2. Seleziona il tuo spazio di lavoro.
-                        3. Fai clic su *Altre funzionalità*.
-                        4. Attiva *Tag*.
-                        5. Vai su *Tag* nell’editor dello spazio di lavoro.
-                        6. Fai clic su *+ Aggiungi tag* per creare i tuoi.
+                        1. Fai clic su *Workspaces*.
+                        2. Seleziona il tuo workspace.
+                        3. Fai clic su *More features*.
+                        4. Attiva *Tags*.
+                        5. Vai a *Tags* nell’editor del workspace.
+                        6. Fai clic su *+ Add tag* per crearne uno personalizzato.
 
-                        [Portami alle altre funzionalità](${workspaceMoreFeaturesLink}).
+                        [Portami a More features](${workspaceMoreFeaturesLink}).
 
                     `),
             },
@@ -3259,7 +2866,7 @@ ${amount} per ${merchant} - ${date}`,
                 description: dedent(`
                     *Avvia una chat* con chiunque utilizzando la sua email o il suo numero di telefono.
 
-                    1. Fai clic sul pulsante *+*.
+                    1. Fai clic sul pulsante ${CONST.CUSTOM_EMOJIS.GLOBAL_CREATE}.
                     2. Scegli *Avvia chat*.
                     3. Inserisci un'email o un numero di telefono.
 
@@ -3273,7 +2880,7 @@ ${amount} per ${merchant} - ${date}`,
                 description: dedent(`
                     *Dividi le spese* con una o più persone.
 
-                    1. Fai clic sul pulsante *+*.
+                    1. Fai clic sul pulsante ${CONST.CUSTOM_EMOJIS.GLOBAL_CREATE}.
                     2. Scegli *Avvia chat*.
                     3. Inserisci email o numeri di telefono.
                     4. Fai clic sul pulsante *+* grigio nella chat > *Dividi spesa*.
@@ -3297,7 +2904,7 @@ ${amount} per ${merchant} - ${date}`,
                 description: dedent(`
                     Ecco come creare un report:
 
-                    1. Fai clic sul pulsante *+*.
+                    1. Fai clic sul pulsante ${CONST.CUSTOM_EMOJIS.GLOBAL_CREATE}.
                     2. Scegli *Crea report*.
                     3. Fai clic su *Aggiungi spesa*.
                     4. Aggiungi la tua prima spesa.
@@ -3320,15 +2927,18 @@ ${amount} per ${merchant} - ${date}`,
                 isOnboardingFlow
                     ? dedent(`
                         # La tua prova gratuita è iniziata! Configuriamo il tuo account.
-                        👋 Ciao, sono il tuo account executive di Expensify. Ho già creato uno spazio di lavoro per aiutarti a gestire le ricevute e le spese del tuo team. Per sfruttare al meglio i tuoi 30 giorni di prova gratuita, segui semplicemente i passaggi di configurazione qui sotto!
+                        👋 Ciao, sono il tuo/​la tua specialista per la configurazione di Expensify. Ho già creato uno spazio di lavoro per aiutarti a gestire le ricevute e le spese del tuo team. Per sfruttare al massimo i 30 giorni di prova gratuita, segui i passaggi di configurazione rimanenti qui sotto!
                     `)
                     : dedent(`
                         # La tua prova gratuita è iniziata! Configuriamo il tuo account.
-                        👋 Ciao, sono il tuo account executive di Expensify. Ora che hai creato uno spazio di lavoro, sfrutta al massimo i tuoi 30 giorni di prova gratuita seguendo i passaggi qui sotto!
+                        👋 Ciao, sono il tuo specialista di configurazione Expensify. Ora che hai creato uno spazio di lavoro, sfrutta al massimo i tuoi 30 giorni di prova gratuita seguendo i passaggi qui sotto!
                     `),
-            onboardingTrackWorkspaceMessage: 'Per sfruttare al massimo la tua prova gratuita di 30 giorni, segui i passaggi rimanenti qui sotto:',
+            onboardingTrackWorkspaceMessage:
+                '# Configuriamo il tuo account\n👋 Ciao, sono il tuo specialista di configurazione Expensify. Ho già creato uno spazio di lavoro per aiutarti a gestire ricevute e spese. Per sfruttare al massimo la tua prova gratuita di 30 giorni, segui i passaggi di configurazione rimanenti qui sotto!',
             onboardingChatSplitMessage: 'Dividere le spese con gli amici è facile come inviare un messaggio. Ecco come fare.',
             onboardingAdminMessage: 'Scopri come gestire lo spazio di lavoro del tuo team come amministratore e inviare le tue spese.',
+            onboardingLookingAroundMessage:
+                'Expensify è conosciuta soprattutto per la gestione delle spese, dei viaggi e delle carte aziendali, ma facciamo molto di più. Dimmi che cosa ti interessa e ti aiuterò a iniziare.',
             onboardingTestDriveReceiverMessage: '*Hai 3 mesi gratis! Inizia qui sotto.*',
         },
         workspace: {
@@ -3339,7 +2949,7 @@ ${amount} per ${merchant} - ${date}`,
                 descriptionTwo: 'Classifica e tagga le spese',
                 descriptionThree: 'Crea e condividi report',
             },
-            price: (price?: string) => `Provalo gratis per 30 giorni, poi passa al piano a soli <strong>${price ?? '$5'}/utente/mese</strong>.`,
+            price: 'Provalo gratis per 30 giorni, poi passa al piano a soli <strong>$5/utente/mese</strong>.',
             createWorkspace: 'Crea spazio di lavoro',
         },
         confirmWorkspace: {
@@ -3350,8 +2960,6 @@ ${amount} per ${merchant} - ${date}`,
             title: 'Invita membri',
             subtitle: 'Aggiungi il tuo team o invita il tuo commercialista. Più siamo, meglio è!',
         },
-        workEmail2FAError: 'Questo login è associato a un account esistente con l’Autenticazione a Due Fattori (2FA) abilitata.',
-        singleSignOnError: 'Questo login è un account esistente con SSO/SAML abilitato.',
     },
     featureTraining: {
         doNotShowAgain: 'Non mostrarmelo più',
@@ -3371,7 +2979,6 @@ ${amount} per ${merchant} - ${date}`,
         enterPhoneNumber: 'Qual è il tuo numero di telefono?',
         personalDetails: 'Dati personali',
         privateDataMessage: 'Questi dettagli vengono utilizzati per viaggi e pagamenti. Non vengono mai mostrati sul tuo profilo pubblico.',
-        basicDetails: 'Dettagli di base',
         legalName: 'Nome legale',
         legalFirstName: 'Nome legale di battesimo',
         legalLastName: 'Cognome legale',
@@ -3380,18 +2987,17 @@ ${amount} per ${merchant} - ${date}`,
             dateShouldBeBefore: (dateString: string) => `La data deve essere precedente a ${dateString}`,
             dateShouldBeAfter: (dateString: string) => `La data deve essere successiva a ${dateString}`,
             hasInvalidCharacter: 'Il nome può includere solo caratteri latini',
-            cannotIncludeCommaOrSemicolon: 'Il nome non può contenere una virgola o un punto e virgola',
             incorrectZipFormat: (zipFormat?: string) => `Formato del codice postale non valido${zipFormat ? `Formato accettabile: ${zipFormat}` : ''}`,
             invalidPhoneNumber: `Assicurati che il numero di telefono sia valido (ad es. ${CONST.EXAMPLE_PHONE_NUMBER})`,
         },
     },
     resendValidationForm: {
         linkHasBeenResent: 'Il link è stato reinviato',
-        weSentYouMagicSignInLink: (login: string, loginType: string) => `Ho inviato un link magico di accesso a ${login}. Controlla il tuo ${loginType} per accedere.`,
+        weSentYouMagicSignInLink: ({login, loginType}: WeSentYouMagicSignInLinkParams) => `Ho inviato un link magico di accesso a ${login}. Controlla il tuo ${loginType} per accedere.`,
         resendLink: 'Invia di nuovo il link',
     },
     unlinkLoginForm: {
-        toValidateLogin: (primaryLogin: string, secondaryLogin: string) =>
+        toValidateLogin: ({primaryLogin, secondaryLogin}: ToValidateLoginParams) =>
             `Per convalidare ${secondaryLogin}, invia nuovamente il codice magico dalle Impostazioni account di ${primaryLogin}.`,
         noLongerHaveAccess: (primaryLogin: string) => `Se non hai più accesso a ${primaryLogin}, scollega i tuoi account.`,
         unlink: 'Scollega',
@@ -3450,12 +3056,14 @@ ${amount} per ${merchant} - ${date}`,
     },
     welcomeSignUpForm: {
         join: 'Partecipa',
-        marketingSMSConsent: 'Accetto di ricevere SMS di marketing da Expensify',
     },
     detailsPage: {
         localTime: 'Ora locale',
     },
-    newChatPage: {startGroup: 'Avvia gruppo', addToGroup: 'Aggiungi al gruppo', addUserToGroup: (username: string) => `Aggiungi ${username} al gruppo`},
+    newChatPage: {
+        startGroup: 'Avvia gruppo',
+        addToGroup: 'Aggiungi al gruppo',
+    },
     yearPickerPage: {
         year: 'Anno',
         selectYear: 'Seleziona un anno',
@@ -3498,18 +3106,17 @@ ${amount} per ${merchant} - ${date}`,
             custom: 'Personalizzato',
         },
         untilTomorrow: 'Fino a domani',
-        untilTime: (time: string) => `Fino alle ${time}`,
+        untilTime: ({time}: UntilTimeParams) => `Fino alle ${time}`,
         date: 'Data',
         time: 'Ora',
         clearAfter: 'Cancella dopo',
         whenClearStatus: 'Quando dovremmo cancellare il tuo stato?',
+        vacationDelegate: 'Delegato ferie',
         setVacationDelegate: `Imposta un delegato per le ferie per approvare i report per tuo conto mentre sei fuori ufficio.`,
-        cannotSetVacationDelegate: `Non puoi impostare un delegato per le ferie perché al momento sei il delegato per i seguenti membri:`,
-        addVacationDelegate: 'Aggiungi delegato per le ferie',
         vacationDelegateError: 'Si è verificato un errore durante l’aggiornamento del tuo delegato per le ferie.',
-        asVacationDelegate: (nameOrEmail: string) => `come delegato per le ferie di ${nameOrEmail}`,
-        toAsVacationDelegate: (submittedToName: string, vacationDelegateName: string) => `a ${submittedToName} come delegato ferie per ${vacationDelegateName}`,
-        vacationDelegateWarning: (nameOrEmail: string) =>
+        asVacationDelegate: ({nameOrEmail}: VacationDelegateParams) => `come delegato per le ferie di ${nameOrEmail}`,
+        toAsVacationDelegate: ({submittedToName, vacationDelegateName}: SubmittedToVacationDelegateParams) => `a ${submittedToName} come delegato ferie per ${vacationDelegateName}`,
+        vacationDelegateWarning: ({nameOrEmail}: VacationDelegateParams) =>
             `Stai assegnando ${nameOrEmail} come tuo delegato per le ferie. Non fa ancora parte di tutti i tuoi spazi di lavoro. Se scegli di continuare, verrà inviata un’email a tutti gli amministratori dei tuoi spazi di lavoro per aggiungerlo.`,
     },
     stepCounter: ({step, total, text}: StepCounterParams) => {
@@ -3538,35 +3145,23 @@ ${amount} per ${merchant} - ${date}`,
         connectManually: 'Connetti manualmente',
         desktopConnection: 'Nota: per collegarti con Chase, Wells Fargo, Capital One o Bank of America, fai clic qui per completare questo processo in un browser.',
         yourDataIsSecure: 'I tuoi dati sono al sicuro',
-        toGetStarted: 'Aggiungi un conto bancario per rimborsare le spese, emettere Carte Expensify, riscuotere i pagamenti delle fatture e pagare le bollette tutto da un unico posto.',
+        toGetStarted: 'Aggiungi un conto bancario per rimborsare le spese, emettere carte Expensify, riscuotere i pagamenti delle fatture e pagare le bollette, tutto da un unico posto.',
         plaidBodyCopy: 'Offri ai tuoi dipendenti un modo più semplice per pagare — e farsi rimborsare — le spese aziendali.',
         checkHelpLine: 'Il numero di instradamento e il numero di conto si trovano su un assegno relativo al conto.',
-        bankAccountPurposeTitle: 'Cosa vuoi fare con il tuo conto bancario?',
-        getReimbursed: 'Ottenere rimborsi',
-        getReimbursedDescription: 'Dal datore di lavoro o altri',
-        makePayments: 'Effettuare pagamenti',
-        makePaymentsDescription: 'Paga le spese o emetti Carte Expensify',
         hasPhoneLoginError: (contactMethodRoute: string) =>
             `Per collegare un conto bancario, <a href="${contactMethodRoute}">aggiungi un’email come accesso principale</a> e riprova. Puoi aggiungere il tuo numero di telefono come accesso secondario.`,
         hasBeenThrottledError: 'Si è verificato un errore durante l’aggiunta del tuo conto bancario. Attendi qualche minuto e riprova.',
-        hasCurrencyError: (workspaceRoute: string) =>
+        hasCurrencyError: ({workspaceRoute}: WorkspaceRouteParams) =>
             `Ops! Sembra che la valuta del tuo workspace sia impostata su una valuta diversa da USD. Per procedere, vai alle <a href="${workspaceRoute}">impostazioni del tuo workspace</a>, impostala su USD e riprova.`,
         bbaAdded: 'Conto bancario aziendale aggiunto!',
         bbaAddedDescription: 'È pronto per essere utilizzato per i pagamenti.',
-        lockedBankAccount: 'Conto bancario bloccato',
-        unlockBankAccount: 'Sblocca conto bancario',
-        youCantPayThis: `Non puoi pagare questo report perché hai un <a href="${CONST.UNLOCK_BANK_ACCOUNT_HELP_URL}">conto bancario bloccato</a>. Tocca qui sotto e il Concierge ti aiuterà con i prossimi passi per sbloccarlo.`,
-        htmlUnlockMessage: (maskedAccountNumber: string) =>
-            `<h1>Expensify Business Bank Account ${maskedAccountNumber}</h1><p>Grazie per aver inviato una richiesta di sblocco del tuo conto bancario. Le richieste di prelievo possono essere rifiutate a causa di fondi insufficienti o se il conto bancario non è stato abilitato per l'addebito diretto. Esamineremo il tuo caso e ti contatteremo se avremo bisogno di ulteriori informazioni per risolvere questo problema.</p>`,
-        textUnlockMessage: (maskedAccountNumber: string) =>
-            `Expensify Business Bank Account ${maskedAccountNumber}\nGrazie per aver inviato una richiesta di sblocco del tuo conto bancario. Le richieste di prelievo possono essere rifiutate a causa di fondi insufficienti o se il conto bancario non è stato abilitato per l'addebito diretto. Esamineremo il tuo caso e ti contatteremo se avremo bisogno di ulteriori informazioni per risolvere questo problema.`,
         error: {
             youNeedToSelectAnOption: "Seleziona un'opzione per continuare",
             noBankAccountAvailable: 'Spiacenti, non è disponibile alcun conto bancario',
             noBankAccountSelected: 'Scegli un account per favore',
             taxID: 'Inserisci un numero di codice fiscale valido',
             website: 'Inserisci un sito web valido',
-            zipCode: `Inserisci un CAP valido usando il formato: ${COMMON_CONST.COUNTRY_ZIP_REGEX_DATA.US.samples}`,
+            zipCode: `Inserisci un CAP valido usando il formato: ${CONST.COUNTRY_ZIP_REGEX_DATA.US.samples}`,
             phoneNumber: 'Inserisci un numero di telefono valido',
             email: 'Inserisci un indirizzo email valido',
             companyName: 'Inserisci un nome aziendale valido',
@@ -3593,7 +3188,7 @@ ${amount} per ${merchant} - ${date}`,
             fullName: 'Inserisci un nome completo valido',
             ownershipPercentage: 'Inserisci una percentuale valida',
             deletePaymentBankAccount:
-                'Questo conto bancario non può essere eliminato perché viene utilizzato per i pagamenti con Carta Expensify. Se desideri comunque eliminare questo conto, contatta Concierge.',
+                'Questo conto bancario non può essere eliminato perché viene utilizzato per i pagamenti con Expensify Card. Se desideri comunque eliminare questo conto, contatta Concierge.',
             sameDepositAndWithdrawalAccount: 'I conti di deposito e prelievo sono gli stessi.',
         },
     },
@@ -3608,11 +3203,6 @@ ${amount} per ${merchant} - ${date}`,
         confirmationStepHeader: 'Controlla le tue informazioni.',
         confirmationStepSubHeader: 'Controlla attentamente i dettagli qui sotto e seleziona la casella delle condizioni per confermare.',
         toGetStarted: 'Aggiungi un conto bancario personale per ricevere rimborsi, pagare fatture o attivare l’Expensify Wallet.',
-        updatePersonalInfo: 'Aggiorna conto bancario',
-        updatePersonalInfoFailure: 'Impossibile aggiornare le informazioni del conto bancario. Riprova più tardi.',
-        updateSuccessTitle: 'Conto bancario aggiornato!',
-        updateSuccessHeader: 'Conto bancario aggiornato',
-        updateSuccessMessage: 'Complimenti, il tuo conto bancario è configurato e pronto a ricevere rimborsi.',
     },
     addPersonalBankAccountPage: {
         enterPassword: 'Inserisci la password di Expensify',
@@ -3640,8 +3230,8 @@ ${amount} per ${merchant} - ${date}`,
     messages: {
         errorMessageInvalidPhone: `Inserisci un numero di telefono valido senza parentesi né trattini. Se ti trovi fuori dagli Stati Uniti, includi il prefisso internazionale del tuo paese (ad es. ${CONST.EXAMPLE_PHONE_NUMBER}).`,
         errorMessageInvalidEmail: 'Email non valida',
-        userIsAlreadyMember: (login: string, name: string) => `${login} è già membro di ${name}`,
-        userIsAlreadyAnAdmin: (login: string, name: string) => `${login} è già un amministratore di ${name}`,
+        userIsAlreadyMember: ({login, name}: UserIsAlreadyMemberParams) => `${login} è già membro di ${name}`,
+        userIsAlreadyAnAdmin: ({login, name}: UserIsAlreadyMemberParams) => `${login} è già un amministratore di ${name}`,
     },
     onfidoStep: {
         acceptTerms: 'Continuando con la richiesta di attivazione del tuo Expensify Wallet, confermi di aver letto, compreso e accettato',
@@ -3687,7 +3277,7 @@ ${amount} per ${merchant} - ${date}`,
         haveReadAndAgreePlain: 'Ho letto e accetto di ricevere comunicazioni elettroniche.',
         haveReadAndAgree: `Ho letto e accetto di ricevere le <a href="${CONST.ELECTRONIC_DISCLOSURES_URL}">informative elettroniche</a>.`,
         agreeToThePlain: 'Accetto l’Informativa sulla privacy e l’Accordo sul portafoglio.',
-        agreeToThe: (walletAgreementUrl: string) =>
+        agreeToThe: ({walletAgreementUrl}: WalletAgreementParams) =>
             `Accetto l’<a href="${CONST.OLD_DOT_PUBLIC_URLS.PRIVACY_URL}">informativa sulla privacy</a> e il <a href="${walletAgreementUrl}">contratto del Wallet</a>.`,
         enablePayments: 'Abilita pagamenti',
         monthlyFee: 'Commissione mensile',
@@ -3699,7 +3289,7 @@ ${amount} per ${merchant} - ${date}`,
         checkTheBoxes: 'Seleziona le caselle qui sotto.',
         agreeToTerms: 'Accetta i termini e sarai pronto per iniziare!',
         shortTermsForm: {
-            expensifyPaymentsAccount: (walletProgram: string) => `Il Portafoglio Expensify è emesso da ${walletProgram}.`,
+            expensifyPaymentsAccount: ({walletProgram}: WalletProgramParams) => `Il Portafoglio Expensify è emesso da ${walletProgram}.`,
             perPurchase: 'Per acquisto',
             atmWithdrawal: 'Prelievo bancomat',
             cashReload: 'Ricarica in contanti',
@@ -3713,7 +3303,7 @@ ${amount} per ${merchant} - ${date}`,
             generalInfo: `Per informazioni generali sui conti prepagati, visita <a href="${CONST.CFPB_PREPAID_URL}">${CONST.TERMS.CFPB_PREPAID}</a>.`,
             conditionsDetails: `Per dettagli e condizioni relativi a tutte le commissioni e ai servizi, visita <a href="${CONST.FEES_URL}">${CONST.FEES_URL}</a> o chiama il numero +1 833-400-0904.`,
             electronicFundsWithdrawalInstant: 'Prelievo elettronico di fondi (immediato)',
-            electronicFundsInstantFeeMin: (amount: string) => `(min ${amount})`,
+            electronicFundsInstantFeeMin: ({amount}: TermsParams) => `(min ${amount})`,
         },
         longTermsForm: {
             listOfAllFees: 'Elenco di tutte le commissioni del Wallet Expensify',
@@ -3733,7 +3323,7 @@ ${amount} per ${merchant} - ${date}`,
             electronicFundsInstantDetails: (percentage: string, amount: string) =>
                 'È prevista una commissione per trasferire fondi dal tuo Portafoglio Expensify alla carta di debito collegata utilizzando l’opzione di trasferimento istantaneo. Questo trasferimento di solito viene completato entro pochi minuti.' +
                 `La commissione è pari al ${percentage}% dell’importo del trasferimento (con una commissione minima di ${amount}).`,
-            fdicInsuranceBancorp: (amount: string) =>
+            fdicInsuranceBancorp: ({amount}: TermsParams) =>
                 `I tuoi fondi sono idonei per l’assicurazione FDIC. I tuoi fondi saranno detenuti presso o trasferiti a ${CONST.WALLET.PROGRAM_ISSUERS.BANCORP_BANK}, un’istituzione assicurata dalla FDIC.` +
                 `Una volta lì, i tuoi fondi sono assicurati fino a ${amount} dalla FDIC nel caso in cui ${CONST.WALLET.PROGRAM_ISSUERS.BANCORP_BANK} fallisca, se sono soddisfatti i requisiti specifici per l’assicurazione dei depositi e la tua carta è registrata. Consulta ${CONST.TERMS.FDIC_PREPAID} per i dettagli.`,
             contactExpensifyPayments: `Contatta ${CONST.WALLET.PROGRAM_ISSUERS.EXPENSIFY_PAYMENTS} chiamando il numero +1 833-400-0904, via email all'indirizzo ${CONST.EMAIL.CONCIERGE} oppure accedi su ${CONST.NEW_EXPENSIFY_URL}.`,
@@ -3742,7 +3332,7 @@ ${amount} per ${merchant} - ${date}`,
             automated: 'Automatizzato',
             liveAgent: 'Agente in tempo reale',
             instant: 'Immediato',
-            electronicFundsInstantFeeMin: (amount: string) => `Min ${amount}`,
+            electronicFundsInstantFeeMin: ({amount}: TermsParams) => `Min ${amount}`,
         },
     },
     activateStep: {
@@ -4027,10 +3617,6 @@ ${amount} per ${merchant} - ${date}`,
         youCanChange: 'Puoi cambiare la valuta dello spazio di lavoro nelle tue',
         findCountry: 'Trova paese',
         selectCountry: 'Seleziona paese',
-        error: {
-            connectToWorkspace: (workspaceRoute: string) =>
-                `Questo conto bancario deve essere collegato a uno spazio di lavoro. Vai su <a href="${workspaceRoute}">Spazi di lavoro</a>, seleziona il tuo spazio di lavoro, quindi vai su Flussi di lavoro > Pagamenti > Aggiungi conto bancario.`,
-        },
     },
     bankInfoStep: {
         whatAreYour: 'Quali sono i dati del tuo conto bancario aziendale?',
@@ -4074,7 +3660,7 @@ ${amount} per ${merchant} - ${date}`,
         pleaseUpload: 'Carica ulteriore documentazione qui sotto per aiutarci a verificare la tua identità come amministratore dell’azienda.',
         enterSignerInfo: 'Inserisci le informazioni del firmatario',
         thisStep: 'Questo passaggio è stato completato',
-        isConnecting: (bankAccountLastFour: string | undefined, currency: string | undefined) =>
+        isConnecting: ({bankAccountLastFour, currency}: SignerInfoMessageParams) =>
             `sta collegando un conto bancario aziendale in ${currency} che termina con ${bankAccountLastFour} a Expensify per pagare i dipendenti in ${currency}. Il prossimo passaggio richiede le informazioni del firmatario da un direttore.`,
         error: {
             emailsMustBeDifferent: 'Le email devono essere diverse',
@@ -4086,7 +3672,7 @@ ${amount} per ${merchant} - ${date}`,
         regulationRequiresUs: 'La normativa ci impone di verificare l’identità di ogni persona fisica che possiede più del 25% dell’attività.',
         iAmAuthorized: 'Sono autorizzato/a a usare il conto bancario aziendale per le spese aziendali.',
         iCertify: 'Dichiaro che le informazioni fornite sono veritiere e accurate.',
-        iAcceptTheTermsAndConditions: `Accetto i <a href="https://www.corpay.com/cross-border/terms">termini e condizioni</a>.`,
+        iAcceptTheTermsAndConditions: `Accetto i <a href="https://cross-border.corpay.com/tc/">termini e condizioni</a>.`,
         iAcceptTheTermsAndConditionsAccessibility: 'Accetto i termini e le condizioni.',
         accept: 'Accetta e aggiungi conto bancario',
         iConsentToThePrivacyNotice: 'Acconsento all’<a href="https://payments.corpay.com/compliance">informativa sulla privacy</a>.',
@@ -4118,38 +3704,6 @@ ${amount} per ${merchant} - ${date}`,
         weTake: 'Prendiamo molto sul serio la tua sicurezza. Configura ora l’autenticazione a due fattori (2FA) per aggiungere un ulteriore livello di protezione al tuo account.',
         secure: 'Proteggi il tuo account',
     },
-    documentsStep: {
-        beforeYouGo: 'Prima di continuare, abbiamo bisogno di alcuni documenti per verificare alcune informazioni',
-        subheader: 'Verifica',
-        verificationFailed: 'La verifica non è riuscita, quindi avremo bisogno di documenti aggiuntivi per verificare te e la tua azienda',
-        taxIDVerification: 'Verifica dell’ID fiscale',
-        taxIDVerificationDescription: dedent(`
-        Carica uno dei seguenti file:
-        • Lettera di assegnazione TIN/EIN dell’IRS
-        • Conferma della richiesta TIN/EIN dell’IRS (di solito indica "Congratulations! The EIN has been successfully assigned")
-        • Lettera di esenzione fiscale dell’IRS con nome dell’azienda ed EIN`),
-        nameChangeDocument: 'Documento di cambio nome',
-        nameChangeDocumentDescription:
-            'Se il nome della tua azienda è cambiato dopo la richiesta del TIN/EIN, abbiamo bisogno di questo documento per verificare il numero di ID fiscale fornito',
-        companyAddressVerification: 'Verifica dell’indirizzo aziendale',
-        companyAddressVerificationDescription: dedent(`
-        Carica uno dei seguenti file:
-        • Bolletta recente con nome e indirizzo dell’azienda
-        • Estratto conto bancario con nome e indirizzo dell’azienda
-        • Contratto di locazione attuale con pagina firme che mostri nome e indirizzo attuale dell’azienda
-        • Documento assicurativo con nome e indirizzo dell’azienda
-        • Documento di assegnazione TIN con nome e indirizzo dell’azienda`),
-        userAddressVerification: 'Verifica dell’indirizzo',
-        userAddressVerificationDescription: dedent(`
-        Carica uno dei seguenti file:
-        • Tessera elettorale
-        • Patente di guida
-        • Estratto conto bancario
-        • Bolletta`),
-        userDOBVerification: 'Verifica della data di nascita',
-        userDOBVerificationDescription: 'Carica un documento di identità rilasciato negli Stati Uniti',
-        finishViaChat: 'Completa via chat',
-    },
     reimbursementAccountLoadingAnimation: {
         oneMoment: 'Un momento',
         explanationLine: 'Stiamo esaminando le tue informazioni. Potrai procedere con i prossimi passaggi a breve.',
@@ -4287,15 +3841,15 @@ ${amount} per ${merchant} - ${date}`,
             flightSeatChanged: (airlineCode: string) => `La tua assegnazione del posto sul volo ${airlineCode} è stata modificata.`,
             flightSeatCancelled: (airlineCode: string) => `La tua assegnazione del posto sul volo ${airlineCode} è stata rimossa.`,
             paymentDeclined: 'Il pagamento per la tua prenotazione aerea non è andato a buon fine. Riprova.',
-            bookingCancelledByTraveler: (type: string, id = '') => `Hai annullato la tua prenotazione ${type} ${id}.`,
-            bookingCancelledByVendor: (type: string, id = '') => `Il fornitore ha annullato la tua prenotazione ${type} ${id}.`,
-            bookingRebooked: (type: string, id = '') => `La tua prenotazione ${type} è stata nuovamente effettuata. Nuovo numero di conferma: ${id}.`,
-            bookingUpdated: (type: string) => `La tua prenotazione ${type} è stata aggiornata. Controlla i nuovi dettagli nell’itinerario.`,
+            bookingCancelledByTraveler: ({type, id = ''}: TravelTypeParams) => `Hai annullato la tua prenotazione ${type} ${id}.`,
+            bookingCancelledByVendor: ({type, id = ''}: TravelTypeParams) => `Il fornitore ha annullato la tua prenotazione ${type} ${id}.`,
+            bookingRebooked: ({type, id = ''}: TravelTypeParams) => `La tua prenotazione ${type} è stata nuovamente effettuata. Nuovo numero di conferma: ${id}.`,
+            bookingUpdated: ({type}: TravelTypeParams) => `La tua prenotazione ${type} è stata aggiornata. Controlla i nuovi dettagli nell’itinerario.`,
             railTicketRefund: (origin: string, destination: string, startDate: string) =>
                 `Il tuo biglietto ferroviario per ${origin} → ${destination} del ${startDate} è stato rimborsato. Un accredito verrà elaborato.`,
             railTicketExchange: (origin: string, destination: string, startDate: string) => `Il tuo biglietto ferroviario per ${origin} → ${destination} del ${startDate} è stato cambiato.`,
             railTicketUpdate: (origin: string, destination: string, startDate: string) => `Il tuo biglietto del treno per ${origin} → ${destination} del ${startDate} è stato aggiornato.`,
-            defaultUpdate: (type: string) => `La tua prenotazione ${type} è stata aggiornata.`,
+            defaultUpdate: ({type}: TravelTypeParams) => `La tua prenotazione ${type} è stata aggiornata.`,
         },
         flightTo: 'Volo per',
         trainTo: 'Treno per',
@@ -4312,13 +3866,13 @@ ${amount} per ${merchant} - ${date}`,
             workflows: 'Flussi di lavoro',
             workspace: 'Spazio di lavoro',
             findWorkspace: 'Trova spazio di lavoro',
-            findRoom: 'Trova stanza',
             edit: 'Modifica spazio di lavoro',
             enabled: 'Abilitato',
             disabled: 'Disattivato',
             everyone: 'Tutti',
             delete: 'Elimina spazio di lavoro',
             settings: 'Impostazioni',
+            reimburse: 'Rimborsi',
             categories: 'Categorie',
             tags: 'Tag',
             customField1: 'Campo personalizzato 1',
@@ -4326,7 +3880,6 @@ ${amount} per ${merchant} - ${date}`,
             customFieldHint: 'Aggiungi una codifica personalizzata che si applichi a tutte le spese di questo membro.',
             reports: 'Report',
             reportFields: 'Campi del report',
-            invoiceFields: 'Campi fattura',
             reportTitle: 'Titolo del report',
             reportField: 'Campo report',
             taxes: 'Tasse',
@@ -4355,10 +3908,6 @@ ${amount} per ${merchant} - ${date}`,
             defaultNote: `Le ricevute inviate a ${CONST.EMAIL.RECEIPTS} verranno visualizzate in questo workspace.`,
             deleteConfirmation: 'Sei sicuro di voler eliminare questo spazio di lavoro?',
             deleteWithCardsConfirmation: 'Sei sicuro di voler eliminare questo spazio di lavoro? Questa azione rimuoverà tutti i feed delle carte e le carte assegnate.',
-            deleteOpenExpensifyCardsError: 'La tua azienda ha ancora carte Expensify attive.',
-            outstandingBalanceWarning:
-                'Hai un saldo in sospeso che deve essere saldato prima di eliminare il tuo ultimo workspace. Vai alle impostazioni dell’abbonamento per risolvere il pagamento.',
-            settleBalance: 'Vai all’abbonamento',
             unavailable: 'Spazio di lavoro non disponibile',
             memberNotFound: 'Membro non trovato. Per invitare un nuovo membro allo spazio di lavoro, usa il pulsante di invito qui sopra.',
             notAuthorized: `Non hai accesso a questa pagina. Se stai cercando di unirti a questo workspace, chiedi al proprietario del workspace di aggiungerti come membro. Qualcos'altro? Contatta ${CONST.EMAIL.CONCIERGE}.`,
@@ -4369,11 +3918,8 @@ ${amount} per ${merchant} - ${date}`,
             clearFilter: 'Cancella filtro',
             workspaceName: 'Nome workspace',
             workspaceOwner: 'Proprietario',
-            keepMeAsAdmin: 'Mantienimi come amministratore',
             workspaceType: 'Tipo di workspace',
             workspaceAvatar: 'Avatar spazio di lavoro',
-            clientID: 'ID cliente',
-            clientIDInputHint: "Inserisci l'identificativo univoco del cliente",
             mustBeOnlineToViewMembers: 'Devi essere online per visualizzare i membri di questo spazio di lavoro.',
             moreFeatures: 'Altre funzionalità',
             requested: 'Richiesto',
@@ -4392,7 +3938,7 @@ ${amount} per ${merchant} - ${date}`,
             appliedOnExport: 'Non importato in Expensify, applicato all’esportazione',
             shareNote: {
                 header: 'Condividi il tuo spazio di lavoro con altri membri',
-                content: (adminsRoomLink: string) =>
+                content: ({adminsRoomLink}: WorkspaceShareNoteParams) =>
                     `Condividi questo codice QR o copia il link qui sotto per facilitare ai membri la richiesta di accesso al tuo spazio di lavoro. Tutte le richieste di adesione allo spazio di lavoro verranno visualizzate nella stanza <a href="${adminsRoomLink}">${CONST.REPORT.WORKSPACE_CHAT_ROOMS.ADMINS}</a> per la tua revisione.`,
             },
             connectTo: ({connectionName}: ConnectionNameParams) => `Connetti a ${CONST.POLICY.CONNECTIONS.NAME_USER_FRIENDLY[connectionName]}`,
@@ -4407,20 +3953,12 @@ ${amount} per ${merchant} - ${date}`,
             memberAlternateText: 'Invia e approva i report.',
             adminAlternateText: 'Gestisci i report e le impostazioni dello spazio di lavoro.',
             auditorAlternateText: 'Visualizza e commenta i report.',
-            roleName: (role?: string) => {
+            roleName: ({role}: OptionalParam<RoleNamesParams> = {}) => {
                 switch (role) {
                     case CONST.POLICY.ROLE.ADMIN:
-                        return 'Amministratore spazio di lavoro';
+                        return 'Amministrazione';
                     case CONST.POLICY.ROLE.AUDITOR:
                         return 'Revisore';
-                    case CONST.POLICY.ROLE.EDITOR:
-                        return 'Editor';
-                    case CONST.POLICY.ROLE.CARD_ADMIN:
-                        return 'Amministratore carta';
-                    case CONST.POLICY.ROLE.PEOPLE_ADMIN:
-                        return 'Amministratore persone';
-                    case CONST.POLICY.ROLE.PAYMENTS_ADMIN:
-                        return 'Amministrazione pagamenti';
                     case CONST.POLICY.ROLE.USER:
                         return 'Membro';
                     default:
@@ -4450,22 +3988,7 @@ ${amount} per ${merchant} - ${date}`,
             budgetFrequency: {monthly: 'mensile', yearly: 'annuale'},
             budgetFrequencyUnit: {monthly: 'mese', yearly: 'anno'},
             budgetTypeForNotificationMessage: {tag: 'etichetta', category: 'categoria'},
-            deepDiveExpensifyCard: `<muted-text-label>Le transazioni della Carta Expensify verranno esportate automaticamente in un "Conto Passivo Carta Expensify" creato con <a href="${CONST.DEEP_DIVE_EXPENSIFY_CARD}">la nostra integrazione</a>.</muted-text-label>`,
-            travelInvoicing: 'Esporta le spese di fatturazione viaggi come',
-            travelInvoicingVendor: 'Fornitore di viaggi',
-            travelInvoicingPayableAccount: 'Conto debiti per viaggi',
-            hr: 'Risorse umane',
-            rooms: 'Stanze',
-            findDomain: 'Trova dominio',
-            cardAdminAlternateText: 'Gestisci le carte dello spazio di lavoro.',
-            peopleAdminAlternateText: 'Gestisci i membri e i flussi di approvazione.',
-            paymentsAdminAlternateText: 'Gestisci i pagamenti del flusso di lavoro.',
-            readOnlyActionTitle: 'Non così in fretta...',
-            readOnlyActionPrompt: 'Il tuo ruolo nello spazio di lavoro può visualizzare queste impostazioni, ma non può modificarle.',
-        },
-        createdForClient: {
-            title: 'Hai creato uno spazio di lavoro per il tuo cliente!',
-            description: 'Ottime notizie 🎉. Contattaci se hanno bisogno di aiuto con la configurazione.',
+            deepDiveExpensifyCard: `<muted-text-label>Le transazioni della Expensify Card verranno esportate automaticamente su un "Conto passività Expensify Card" creato con <a href="${CONST.DEEP_DIVE_EXPENSIFY_CARD}">la nostra integrazione</a>.</muted-text-label>`,
         },
         receiptPartners: {
             uber: {
@@ -4530,7 +4053,7 @@ ${amount} per ${merchant} - ${date}`,
             exportDescription: 'Configura come i dati di Expensify vengono esportati in QuickBooks Desktop.',
             date: 'Data di esportazione',
             exportInvoices: 'Esporta fatture in',
-            exportExpensifyCard: 'Esporta le transazioni Carta Expensify come',
+            exportExpensifyCard: 'Esporta le transazioni Expensify Card come',
             account: 'Account',
             accountDescription: 'Scegli dove registrare le scritture contabili.',
             accountsPayable: 'Debiti verso fornitori',
@@ -4651,7 +4174,7 @@ ${amount} per ${merchant} - ${date}`,
             exportDescription: 'Configura come i dati di Expensify vengono esportati in QuickBooks Online.',
             date: 'Data di esportazione',
             exportInvoices: 'Esporta fatture in',
-            exportExpensifyCard: 'Esporta le transazioni Carta Expensify come',
+            exportExpensifyCard: 'Esporta le transazioni Expensify Card come',
             exportDate: {
                 label: 'Data di esportazione',
                 description: 'Usa questa data quando esporti i report in QuickBooks Online.',
@@ -4689,9 +4212,8 @@ ${amount} per ${merchant} - ${date}`,
             notConfigured: 'Non configurato',
             bankAccountDescription: 'Scegli da dove inviare gli assegni.',
             creditCardAccount: 'Conto della carta di credito',
-            travelInvoicingDescription: 'Le spese di viaggio verranno esportate come addebiti su carta di credito nel conto QuickBooks Online specificato di seguito.',
             companyCardsLocationEnabledDescription:
-                'QuickBooks Online non supporta le sedi nelle esportazioni di fatture fornitore quando le sedi sono importate come tag. Poiché nel tuo spazio di lavoro hai sedi importate come tag, questa opzione di esportazione non è disponibile.',
+                'QuickBooks Online non supporta le sedi nell’esportazione delle fatture fornitore. Poiché hai le sedi abilitate nel tuo spazio di lavoro, questa opzione di esportazione non è disponibile.',
             outOfPocketTaxEnabledDescription:
                 'QuickBooks Online non supporta le imposte nelle esportazioni delle registrazioni contabili. Poiché hai le imposte abilitate nel tuo spazio di lavoro, questa opzione di esportazione non è disponibile.',
             outOfPocketTaxEnabledError: 'Le registrazioni contabili non sono disponibili quando le imposte sono abilitate. Scegli un’altra opzione di esportazione.',
@@ -4787,7 +4309,6 @@ ${amount} per ${merchant} - ${date}`,
             exportDeepDiveCompanyCard:
                 'Le spese esportate verranno registrate come transazioni bancarie sul conto bancario Xero indicato di seguito e le date delle transazioni corrisponderanno alle date sul tuo estratto conto bancario.',
             bankTransactions: 'Transazioni bancarie',
-            travelInvoicingDescription: 'Le spese di viaggio verranno esportate come transazioni bancarie nel conto Xero specificato di seguito.',
             xeroBankAccount: 'Conto bancario Xero',
             xeroBankAccountDescription: 'Scegli dove registrare le spese come transazioni bancarie.',
             exportExpensesDescription: 'I report verranno esportati come note di acquisto con la data e lo stato selezionati di seguito.',
@@ -4882,7 +4403,6 @@ ${amount} per ${merchant} - ${date}`,
                     [CONST.SAGE_INTACCT_NON_REIMBURSABLE_EXPENSE_TYPE.VENDOR_BILL]: 'Fatture fornitori',
                 },
             },
-            travelInvoicingDescription: 'Le spese di viaggio verranno esportate come addebiti su carta di credito nel conto Sage Intacct specificato di seguito.',
             creditCardAccount: 'Conto della carta di credito',
             defaultVendor: 'Fornitore predefinito',
             defaultVendorDescription: (isReimbursable: boolean) =>
@@ -4915,68 +4435,6 @@ ${amount} per ${merchant} - ${date}`,
                 },
             },
         },
-        certinia: {
-            title: 'Certinia',
-            titleFFA: 'Certinia (FFA)',
-            autoSyncDescription: 'Expensify si sincronizzerà automaticamente con Certinia ogni giorno.',
-            syncReimbursedReportsDescription:
-                'Con questa opzione abilitata, ogni volta che una fattura da pagare viene saldata in FFA, il relativo report Expensify sarà automaticamente contrassegnato come rimborsato.',
-            exportDescription: 'Configura come i dati di Expensify vengono esportati in Certinia.',
-            payableInvoices: 'Fatture da pagare',
-            exportStatus: {
-                label: 'Stato fattura da pagare',
-                values: {
-                    [CONST.CERTINIA_EXPORT_STATUS.APPROVED]: 'Completa',
-                    [CONST.CERTINIA_EXPORT_STATUS.IN_PROGRESS]: 'In corso',
-                    [CONST.CERTINIA_EXPORT_STATUS.SUBMITTED]: 'Inviato',
-                },
-            },
-            exportDate: {
-                label: 'Data fattura da pagare',
-                values: {
-                    [CONST.CERTINIA_EXPORT_DATE.LAST_EXPENSE]: "Data dell'ultima spesa",
-                    [CONST.CERTINIA_EXPORT_DATE.REPORT_SUBMITTED]: 'Data di invio del report',
-                    [CONST.CERTINIA_EXPORT_DATE.REPORT_EXPORTED]: 'Data di esportazione',
-                },
-            },
-            exportReimbursable: {
-                label: 'Esporta le spese rimborsabili come',
-                helperText: 'Le spese contrassegnate come rimborsabili verranno esportate come fatture passive intestate al dipendente.',
-            },
-            exportNonReimbursable: {label: 'Esporta le spese non rimborsabili come'},
-            noVendorsFound: 'Nessun fornitore trovato',
-            noVendorsFoundDescription: 'Sincronizza di nuovo la connessione dopo che i fornitori sono stati aggiunti in Certinia.',
-            prerequisites: {
-                title: 'Prima di connetterti',
-                installBundle: 'Per connessioni FFA',
-                installBundleDescription: ({href, version}: {href: string; version: string}) =>
-                    `Installa il bundle Expensify in Salesforce facendo clic su questo link: <a href="${href}">Installa FFA Expensify Bundle (Versione ${version})</a>`,
-                installBundleConfirm: 'Ho installato il pacchetto',
-                setupContacts: 'Configura utente e contatti',
-                setupContactsBullet1:
-                    'Crea sia un Utente che un Contatto per te se non esistono già in Certinia, assicurandoti che l’email corrisponda alla tua email principale in Expensify.',
-                setupContactsBullet2:
-                    'Crea contatti per ogni dipendente che invierà note spese e per ogni approvatore di report. Assicurati che l’indirizzo email di ciascun contatto corrisponda all’indirizzo email dell’account Expensify del dipendente.',
-                setupContactsBullet3: 'Imposta i controlli di autorizzazione per il tuo utente per ogni contatto/risorsa.',
-                setupContactsConfirm: 'Ho configurato l’utente e i contatti',
-                oauth: 'Accedi tramite Salesforce',
-                oauthDescription: 'Per completare la configurazione, dovrai accedere tramite Salesforce e Certinia.\n\nUsa il pulsante qui sotto per continuare.',
-                connectButton: 'Connetti a Certinia',
-            },
-            import: {
-                chartOfAccounts: 'Piano dei conti',
-                chartOfAccountsDescription: 'Il piano dei conti viene importato in Expensify come categorie.',
-                dimensionMapping: ({n}: {n: number}) => `Dimensione ${n}`,
-                dimensions: {dimension1: 'Dimensione 1', dimension2: 'Dimensione 2', dimension3: 'Dimensione 3', dimension4: 'Dimensione 4'},
-                doNotMap: 'Non mappare',
-                doNotMapSubtitle: 'Usa come predefinita la risorsa dipendente',
-                mappingTypes: {
-                    [CONST.CERTINIA_MAPPING_VALUE.DEFAULT]: 'Non mappare',
-                    [CONST.CERTINIA_MAPPING_VALUE.TAG]: 'Importato come tag',
-                    [CONST.CERTINIA_MAPPING_VALUE.REPORT_FIELD]: 'Importato come campi del report',
-                },
-            },
-        },
         netsuite: {
             subsidiary: 'Filiale',
             subsidiarySelectDescription: 'Scegli la consociata in NetSuite da cui desideri importare i dati.',
@@ -4991,8 +4449,8 @@ ${amount} per ${merchant} - ${date}`,
             journalPostingPreference: {
                 label: 'Preferenze di registrazione delle scritture contabili',
                 values: {
-                    [CONST.NETSUITE_JOURNAL_POSTING_PREFERENCE.JOURNALS_POSTING_INDIVIDUAL_LINE]: 'Voce singola per ogni spesa',
-                    [CONST.NETSUITE_JOURNAL_POSTING_PREFERENCE.JOURNALS_POSTING_TOTAL_LINE]: 'Voce singola e dettagliata per ogni report',
+                    [CONST.NETSUITE_JOURNAL_POSTING_PREFERENCE.JOURNALS_POSTING_INDIVIDUAL_LINE]: 'Voce singola, con dettagli per ogni report',
+                    [CONST.NETSUITE_JOURNAL_POSTING_PREFERENCE.JOURNALS_POSTING_TOTAL_LINE]: 'Voce singola per ogni spesa',
                 },
             },
             invoiceItem: {
@@ -5058,7 +4516,6 @@ ${amount} per ${merchant} - ${date}`,
 
                             Se desideri impostare un fornitore specifico per ogni carta, vai su *Impostazioni > Domini > Carte aziendali*.
                         `),
-                        travelDescription: 'Le spese di viaggio verranno esportate come registrazioni contabili sull’account NetSuite specificato di seguito.',
                     },
                 },
                 expenseReportDestinationConfirmDescription:
@@ -5203,7 +4660,7 @@ ${amount} per ${merchant} - ${date}`,
                 importCustomFields: {
                     chooseOptionBelow: 'Scegli un’opzione qui sotto:',
                     label: (importedTypes: string[]) => `Importato come ${importedTypes.join('e')}`,
-                    requiredFieldError: (fieldName: string) => `Inserisci ${fieldName}`,
+                    requiredFieldError: ({fieldName}: RequiredFieldParams) => `Inserisci ${fieldName}`,
                     customSegments: {
                         title: 'Segmenti/record personalizzati',
                         addText: 'Aggiungi segmento/record personalizzato',
@@ -5256,7 +4713,7 @@ _Per istruzioni più dettagliate, [visita il nostro sito di assistenza](${CONST.
 
 _Per istruzioni più dettagliate, [visita il nostro sito di assistenza](${CONST.NETSUITE_IMPORT.HELP_LINKS.CUSTOM_SEGMENTS})_.`,
                             customSegmentScriptIDTitle: "Qual è l'ID dello script?",
-                            customSegmentScriptIDFooter: `Puoi trovare gli ID script dei segmenti personalizzati in NetSuite in:
+                            customSegmentScriptIDFooter: `Puoi trovare gli ID script dei segmenti personalizzati in NetSuite in: 
 
 1. *Customization > Lists, Records, & Fields > Custom Segments*.
 2. Fai clic su un segmento personalizzato.
@@ -5277,7 +4734,7 @@ _Per istruzioni più dettagliate, [visita il nostro sito di assistenza](${CONST.
                             customRecordMappingTitle: 'Come deve essere visualizzato questo record personalizzato in Expensify?',
                         },
                         errors: {
-                            uniqueFieldError: (fieldName: string) => `Esiste già un segmento/record personalizzato con questo ${fieldName?.toLowerCase()}`,
+                            uniqueFieldError: ({fieldName}: RequiredFieldParams) => `Esiste già un segmento/record personalizzato con questo ${fieldName?.toLowerCase()}`,
                         },
                     },
                     customLists: {
@@ -5344,7 +4801,7 @@ _Per istruzioni più dettagliate, [visita il nostro sito di assistenza](${CONST.
             employeeDefaultDescription: 'Il reparto predefinito del dipendente verrà applicato alle sue spese in Sage Intacct, se esiste.',
             displayedAsTagDescription: 'Il reparto sarà selezionabile per ogni singola spesa nel report di un dipendente.',
             displayedAsReportFieldDescription: 'La selezione del reparto verrà applicata a tutte le spese nel report di un dipendente.',
-            toggleImportTitle: (mappingTitle: string) => `Scegli come gestire Sage Intacct <strong>${mappingTitle}</strong> in Expensify.`,
+            toggleImportTitle: ({mappingTitle}: ToggleImportTitleParams) => `Scegli come gestire Sage Intacct <strong>${mappingTitle}</strong> in Expensify.`,
             expenseTypes: 'Tipi di spesa',
             expenseTypesDescription: 'I tuoi tipi di spesa Sage Intacct verranno importati in Expensify come categorie.',
             accountTypesDescription: 'Il tuo piano dei conti di Sage Intacct verrà importato in Expensify come categorie.',
@@ -5384,14 +4841,10 @@ _Per istruzioni più dettagliate, [visita il nostro sito di assistenza](${CONST.
             free: 'Gratis',
             control: 'Controllo',
             collect: 'Riscuoti',
-            submit: 'Invia',
         },
         companyCards: {
             addCards: 'Aggiungi carte',
             selectCards: 'Seleziona carte',
-            fromOtherWorkspaces: 'Da altri spazi di lavoro',
-            addWorkEmail: 'Aggiungi la tua email di lavoro',
-            addWorkEmailDescription: 'Aggiungi la tua email di lavoro per utilizzare i feed esistenti di altri spazi di lavoro.',
             error: {
                 workspaceFeedsCouldNotBeLoadedTitle: 'Impossibile caricare i feed della carta',
                 workspaceFeedsCouldNotBeLoadedMessage:
@@ -5402,11 +4855,6 @@ _Per istruzioni più dettagliate, [visita il nostro sito di assistenza](${CONST.
             },
             addNewCard: {
                 other: 'Altro',
-                fileImport: 'Importa transazioni da file',
-                createFileFeedHelpText: `<muted-text>Segui questa <a href="${CONST.COMPANY_CARDS_CREATE_FILE_FEED_HELP_URL}">guida di supporto</a> per importare le spese della carta aziendale!</muted-text>`,
-                companyCardLayoutName: 'Nome layout carta aziendale',
-                cardLayoutNameRequired: 'Il nome del layout della carta aziendale è obbligatorio',
-                useAdvancedFields: 'Usa i campi avanzati (non consigliato)',
                 cardProviders: {
                     gl1025: 'Carte Corporate American Express',
                     cdf: 'Carte Commerciali Mastercard',
@@ -5486,26 +4934,6 @@ _Per istruzioni più dettagliate, [visita il nostro sito di assistenza](${CONST.
                     confirmText: 'Segnala problema',
                     cancelText: 'Salta',
                 },
-                csvColumns: {
-                    cardNumber: 'Numero di carta',
-                    postedDate: 'Data',
-                    merchant: 'Esercente',
-                    amount: 'Importo',
-                    currency: 'Valuta',
-                    ignore: 'Ignora',
-                    originalTransactionDate: 'Data originale della transazione',
-                    originalAmount: 'Importo originale',
-                    originalCurrency: 'Valuta originale',
-                    comment: 'Commento',
-                    category: 'Categoria',
-                    tag: 'Tag',
-                },
-                csvErrors: {
-                    requiredColumns: (missingColumns: string) => `Assegna una colonna a ciascuno degli attributi: ${missingColumns}.`,
-                    duplicateColumns: (duplicateColumn: string) => `Ops! Hai associato un singolo campo ("${duplicateColumn}") a più colonne. Controlla e riprova.`,
-                },
-                fileImportDescription: "Un'opzione manuale se la tua banca non può inviare un feed.",
-                duplicateFeedModal: {title: 'Feed carta già collegato', prompt: 'Non puoi aggiungere due volte lo stesso feed della carta allo stesso spazio di lavoro.'},
             },
             statementCloseDate: {
                 [CONST.COMPANY_CARDS.STATEMENT_CLOSE_DATE.LAST_DAY_OF_MONTH]: 'Ultimo giorno del mese',
@@ -5556,14 +4984,12 @@ _Per istruzioni più dettagliate, [visita il nostro sito di assistenza](${CONST.
                 flipAmountSign: 'Inverti segno importo',
                 importButton: 'Importa transazioni',
             },
-            deletedCard: 'Carta eliminata',
-            assignNewCards: {title: 'Assegna nuove carte', description: 'Ottieni le ultime carte da assegnare dalla tua banca'},
         },
         expensifyCard: {
-            issueAndManageCards: 'Emetti e gestisci le tue Carte Expensify',
+            issueAndManageCards: 'Emetti e gestisci le tue Expensify Card',
             getStartedIssuing: 'Inizia emettendo la tua prima carta virtuale o fisica.',
             verificationInProgress: 'Verifica in corso...',
-            verifyingTheDetails: 'Stiamo verificando alcuni dettagli. Concierge ti avviserà quando le Carte Expensify saranno pronte per essere emesse.',
+            verifyingTheDetails: 'Stiamo verificando alcuni dettagli. Concierge ti avviserà quando le Expensify Card saranno pronte per l’emissione.',
             disclaimer:
                 'La carta commerciale Expensify Visa® è emessa da The Bancorp Bank, N.A., membro FDIC, in virtù di una licenza di Visa U.S.A. Inc. e potrebbe non essere accettata da tutti gli esercenti che accettano carte Visa. Apple® e il logo Apple® sono marchi di Apple Inc., registrati negli Stati Uniti e in altri Paesi. App Store è un marchio di servizio di Apple Inc. Google Play e il logo Google Play sono marchi di Google LLC.',
             euUkDisclaimer:
@@ -5575,8 +5001,8 @@ _Per istruzioni più dettagliate, [visita il nostro sito di assistenza](${CONST.
             lastFour: 'Ultime 4',
             limit: 'Limite',
             currentBalance: 'Saldo attuale',
-            currentBalanceDescription: 'Il saldo attuale è la somma di tutte le transazioni contabilizzate della Carta Expensify che si sono verificate dalla data dell’ultima liquidazione.',
-            balanceWillBeSettledOn: (settlementDate: string) => `Il saldo sarà regolato il ${settlementDate}`,
+            currentBalanceDescription: 'Il saldo attuale è la somma di tutte le transazioni della Expensify Card contabilizzate dalla data dell’ultima liquidazione.',
+            balanceWillBeSettledOn: ({settlementDate}: SettlementDateParams) => `Il saldo sarà regolato il ${settlementDate}`,
             settleBalance: 'Saldo da saldare',
             cardLimit: 'Limite carta',
             remainingLimit: 'Limite rimanente',
@@ -5584,28 +5010,27 @@ _Per istruzioni più dettagliate, [visita il nostro sito di assistenza](${CONST.
             remainingLimitDescription:
                 'Consideriamo diversi fattori quando calcoliamo il tuo limite residuo: la tua anzianità come cliente, le informazioni aziendali fornite durante la registrazione e la liquidità disponibile sul conto bancario della tua azienda. Il tuo limite residuo può variare su base giornaliera.',
             earnedCashback: 'Cashback',
-            earnedCashbackDescription: 'Il saldo del cashback si basa sulle spese mensili consolidate della Carta Expensify nel tuo spazio di lavoro.',
+            earnedCashbackDescription: 'Il saldo del cashback si basa sulle spese mensili effettuate con la Expensify Card e contabilizzate nel tuo spazio di lavoro.',
             issueNewCard: 'Emetti nuova carta',
             finishSetup: 'Completa configurazione',
             chooseBankAccount: 'Scegli il conto bancario',
-            chooseExistingBank: 'Scegli un conto bancario aziendale esistente per pagare il saldo della tua Carta Expensify oppure aggiungi un nuovo conto bancario',
+            chooseExistingBank: 'Scegli un conto bancario aziendale esistente per pagare il saldo della tua Expensify Card oppure aggiungi un nuovo conto bancario',
             accountEndingIn: 'Conto che termina con',
             addNewBankAccount: 'Aggiungi un nuovo conto bancario',
             settlementAccount: 'Conto di regolamento',
-            settlementAccountDescription: 'Scegli un conto da cui pagare il saldo della tua Carta Expensify.',
-            settlementAccountInfo: (reconciliationAccountSettingsLink: string, accountNumber: string) =>
+            settlementAccountDescription: 'Scegli un conto per pagare il saldo della tua Expensify Card.',
+            settlementAccountInfo: ({reconciliationAccountSettingsLink, accountNumber}: SettlementAccountInfoParams) =>
                 `Assicurati che questo conto corrisponda al tuo <a href="${reconciliationAccountSettingsLink}">Conto di riconciliazione</a> (${accountNumber}) affinché la Riconciliazione continua funzioni correttamente.`,
             settlementFrequency: 'Frequenza di regolamento',
-            settlementFrequencyDescription: 'Scegli con quale frequenza pagherai il saldo della tua Carta Expensify.',
+            settlementFrequencyDescription: 'Scegli con quale frequenza pagherai il saldo della tua Expensify Card.',
             settlementFrequencyInfo:
                 'Se desideri passare alla liquidazione mensile, dovrai collegare il tuo conto bancario tramite Plaid e avere uno storico del saldo positivo di 90 giorni.',
-            applyCashbackToBill: 'Applica il cashback alla mia fattura Expensify',
-            applyCashbackToBillDescription: 'Il cashback della Carta Expensify verrà utilizzato per il pagamento della tua fattura Expensify.',
             frequency: {
                 daily: 'Quotidiano',
                 monthly: 'Mensile',
             },
             cardDetails: 'Dettagli carta',
+            cardPending: ({name}: {name: string}) => `La carta è al momento in sospeso e verrà emessa non appena l'account di ${name} sarà convalidato.`,
             virtual: 'Virtuale',
             physical: 'Fisico',
             deactivate: 'Disattiva carta',
@@ -5622,28 +5047,24 @@ _Per istruzioni più dettagliate, [visita il nostro sito di assistenza](${CONST.
             changeCardMonthlyLimitTypeWarning: (limit: number | string) =>
                 `Se cambi il tipo di limite di questa carta a Mensile, le nuove transazioni verranno rifiutate perché il limite mensile di ${limit} è già stato raggiunto.`,
             addShippingDetails: 'Aggiungi dettagli di spedizione',
-            issuedCard: (assignee: string) => `ha emesso una Carta Expensify per ${assignee}! La carta arriverà entro 2-3 giorni lavorativi.`,
-            issuedCardNoShippingDetails: (assignee: string) => `ha assegnato a ${assignee} una Carta Expensify! La carta sarà spedita una volta confermati i dettagli di spedizione.`,
-            issuedCardVirtual: (assignee: string, link: string) => `ha emesso una Carta Expensify virtuale per ${assignee}! Puoi usare subito il ${link}.`,
-            addedShippingDetails: (assignee: string) => `${assignee} ha aggiunto i dettagli di spedizione. La Carta Expensify arriverà in 2-3 giorni lavorativi.`,
-            replacedCard: (assignee: string) => `${assignee} ha sostituito la propria Carta Expensify. La nuova carta arriverà tra 2-3 giorni lavorativi.`,
-            replacedVirtualCard: (assignee: string, link: string) => `${assignee} ha sostituito la sua Carta Expensify virtuale! Il ${link} può essere usato subito.`,
+            issuedCard: (assignee: string) => `ha emesso una Expensify Card per ${assignee}! La carta arriverà tra 2-3 giorni lavorativi.`,
+            issuedCardNoShippingDetails: (assignee: string) => `ha emesso una Expensify Card per ${assignee}! La carta verrà spedita una volta confermati i dettagli di spedizione.`,
+            issuedCardVirtual: (assignee: string, link: string) => `ha emesso a ${assignee} una carta virtuale Expensify! Il/la ${link} può essere usato/a subito.`,
+            addedShippingDetails: (assignee: string) => `${assignee} ha aggiunto i dettagli di spedizione. La Expensify Card arriverà tra 2-3 giorni lavorativi.`,
+            replacedCard: (assignee: string) => `${assignee} ha sostituito la sua Expensify Card. La nuova carta arriverà tra 2-3 giorni lavorativi.`,
+            replacedVirtualCard: (assignee: string, link: string) => `${assignee} ha sostituito la sua Expensify Card virtuale! La ${link} può essere usata subito.`,
             card: 'carta',
             replacementCard: 'carta sostitutiva',
             verifyingHeader: 'Verifica in corso',
             bankAccountVerifiedHeader: 'Conto bancario verificato',
             verifyingBankAccount: 'Verifica del conto bancario in corso...',
-            verifyingBankAccountDescription: 'Attendi mentre verifichiamo che questo conto possa essere usato per emettere Carte Expensify.',
+            verifyingBankAccountDescription: 'Attendi mentre confermiamo che questo account possa essere utilizzato per emettere Expensify Card.',
             bankAccountVerified: 'Conto bancario verificato!',
-            bankAccountVerifiedDescription: 'Ora puoi emettere Carte Expensify ai membri del tuo spazio di lavoro.',
+            bankAccountVerifiedDescription: 'Ora puoi assegnare le Expensify Card ai membri del tuo workspace.',
             oneMoreStep: 'Ancora un passo...',
             oneMoreStepDescription: 'Sembra che dobbiamo verificare manualmente il tuo conto bancario. Vai su Concierge, dove ti aspettano le istruzioni.',
             gotIt: 'Ho capito',
             goToConcierge: 'Vai a Concierge',
-            exportAsCSV: 'Esporta come CSV',
-            csvColumnType: 'Tipo',
-            csvColumnLimitType: 'Tipo di limite',
-            csvColumnLimit: 'Limite',
         },
         categories: {
             deleteCategories: 'Elimina categorie',
@@ -5662,10 +5083,10 @@ _Per istruzioni più dettagliate, [visita il nostro sito di assistenza](${CONST.
             needCategoryForExportToIntegration: (connectionName: string) => `Tutte le spese devono essere categorizzate per poterle esportare su ${connectionName}.`,
             subtitle: 'Ottieni una panoramica migliore di dove viene speso il denaro. Usa le nostre categorie predefinite oppure aggiungi le tue.',
             emptyCategories: {
-                title: 'Nessuna categoria ancora',
+                title: 'Non hai creato alcuna categoria',
                 subtitle: 'Aggiungi una categoria per organizzare le tue spese.',
-                subtitleWithAccounting: (accountingPageURL: string, canManage = true) =>
-                    `<muted-text><centered-text>Le tue categorie sono attualmente importate da una connessione contabile.${canManage ? ` Vai alla sezione <a href="${accountingPageURL}">contabilità</a> per apportare modifiche.` : ''}</centered-text></muted-text>`,
+                subtitleWithAccounting: (accountingPageURL: string) =>
+                    `<muted-text><centered-text>Le tue categorie sono attualmente importate da una connessione contabile. Vai alla sezione <a href="${accountingPageURL}">contabilità</a> per apportare modifiche.</centered-text></muted-text>`,
             },
             updateFailureMessage: 'Si è verificato un errore durante l’aggiornamento della categoria, riprova per favore',
             createFailureMessage: 'Si è verificato un errore durante la creazione della categoria, riprova per favore',
@@ -5721,9 +5142,6 @@ _Per istruzioni più dettagliate, [visita il nostro sito di assistenza](${CONST.
             travel: {
                 title: 'Viaggi',
                 subtitle: 'Prenota, gestisci e riconcilia tutti i viaggi di lavoro.',
-                disableTravelTitle: 'Disattiva prima la fatturazione viaggi',
-                disableTravelPrompt: 'La fatturazione Viaggi è abilitata per questo spazio di lavoro. Disattivala prima di poter disabilitare Viaggi.',
-                disableTravelButton: 'Vai alle impostazioni Viaggio',
                 getStarted: {
                     title: 'Inizia con Expensify Travel',
                     subtitle: 'Ci servono solo ancora alcune informazioni sulla tua attività, poi sarai pronto al decollo.',
@@ -5735,15 +5153,9 @@ _Per istruzioni più dettagliate, [visita il nostro sito di assistenza](${CONST.
                     ctaText: 'Richiesta inviata',
                 },
                 bookOrManageYourTrip: {
-                    title: 'Prenotazione di viaggio',
-                    subtitle: 'Complimenti! Ora sei pronto per prenotare e gestire i viaggi in questo spazio di lavoro.',
-                    ctaText: 'Gestisci viaggi',
-                },
-                settings: {
-                    autoAddTripName: {
-                        title: 'Aggiungi nomi di viaggi alle spese',
-                        subtitle: 'Aggiungi automaticamente i nomi dei viaggi alle descrizioni delle spese per i viaggi prenotati in Expensify.',
-                    },
+                    title: 'Prenota o gestisci il tuo viaggio',
+                    subtitle: 'Usa Expensify Travel per ottenere le migliori offerte di viaggio e gestire tutte le spese di lavoro in un unico posto.',
+                    ctaText: 'Prenota o gestisci',
                 },
                 travelInvoicing: {
                     travelBookingSection: {
@@ -5751,59 +5163,30 @@ _Per istruzioni più dettagliate, [visita il nostro sito di assistenza](${CONST.
                         subtitle: 'Complimenti! Ora sei prontə per prenotare e gestire i viaggi in questo spazio di lavoro.',
                         manageTravelLabel: 'Gestisci viaggi',
                     },
-                    travelInvoicingSection: {
-                        title: 'Fatturazione viaggi',
+                    centralInvoicingSection: {
+                        title: 'Fatturazione centralizzata',
                         subtitle: 'Centralizza tutte le spese di viaggio in una fattura mensile invece di pagare al momento dell’acquisto.',
                         learnHow: 'Scopri come.',
                         subsections: {
                             currentTravelSpendLabel: 'Spesa di viaggio attuale',
-                            currentTravelSpendPaymentQueued: (amount: string) => `Il pagamento di ${amount} è in coda e verrà elaborato a breve.`,
                             currentTravelSpendCta: 'Paga saldo',
                             currentTravelLimitLabel: 'Limite di viaggio attuale',
                             settlementAccountLabel: 'Conto di regolamento',
                             settlementFrequencyLabel: 'Frequenza di regolamento',
                             settlementFrequencyDescription:
                                 'Con quale frequenza Expensify preleverà dal tuo conto bancario aziendale per saldare le recenti transazioni di Expensify Travel.',
-                            monthlySpendLimitLabel: 'Limite di spesa mensile per membro',
-                            monthlySpendLimitDescription: "L'importo massimo che ciascun membro può spendere in viaggi al mese.",
-                            reduceLimitTitle: 'Ridurre il limite di spesa per i viaggi?',
-                            reduceLimitWarning:
-                                'Se riduci il limite, i membri che hanno già speso più di questo importo non potranno effettuare nuove prenotazioni di viaggio fino al mese prossimo.',
-                            provisioningError:
-                                'Non siamo riusciti a configurare alcuni membri del tuo spazio di lavoro per la fatturazione di viaggio. Riprova più tardi oppure contatta Concierge per assistenza.',
                         },
                     },
-                    disableModal: {
-                        title: 'Disattivare la fatturazione viaggi?',
-                        body: 'Le prossime prenotazioni di hotel e autonoleggio potrebbero dover essere rifatte con un diverso metodo di pagamento per evitare la cancellazione.',
-                        confirm: 'Disattiva',
-                    },
-                    outstandingBalanceModal: {
-                        title: 'Impossibile disattivare la fatturazione viaggi',
-                        body: 'Hai ancora un saldo di viaggio in sospeso. Paga prima il tuo saldo.',
-                        confirm: 'Capito',
-                    },
-                    payBalanceModal: {
-                        title: (amount: string) => `Pagare il saldo di ${amount}?`,
-                        body: 'Il pagamento verrà messo in coda ed elaborato a breve. Questa azione non può essere annullata una volta avviata.',
-                    },
-                    exportToPDF: 'Esporta in PDF',
-                    exportToCSV: 'Esporta in CSV',
-                    selectDateRangeError: 'Seleziona un intervallo di date da esportare',
-                    invalidDateRangeError: 'La data di inizio deve essere precedente alla data di fine',
-                    enabled: 'Fatturazione Viaggi abilitata!',
-                    enabledDescription: 'Tutte le spese di viaggio in questo spazio di lavoro saranno ora centralizzate in una fattura mensile.',
                 },
-                personalDetailsDescription: 'Per prenotare il viaggio, inserisci il tuo nome legale così come appare sul tuo documento d’identità rilasciato dal governo.',
             },
             expensifyCard: {
                 title: 'Carta Expensify',
                 subtitle: 'Ottieni informazioni dettagliate e controllo sulle spese.',
-                disableCardTitle: 'Disattiva Carta Expensify',
-                disableCardPrompt: 'Non puoi disattivare la Carta Expensify perché è già in uso. Contatta Concierge per i prossimi passi.',
+                disableCardTitle: 'Disattiva Expensify Card',
+                disableCardPrompt: 'Non puoi disattivare la Expensify Card perché è già in uso. Contatta Concierge per i prossimi passaggi.',
                 disableCardButton: 'Chatta con Concierge',
                 feed: {
-                    title: 'Ottieni la Carta Expensify',
+                    title: 'Ottieni la Expensify Card',
                     subTitle: 'Ottimizza le spese aziendali e risparmia fino al 50% sulla tua fattura Expensify, oltre a:',
                     features: {
                         cashBack: 'Cashback su ogni acquisto negli USA',
@@ -5827,7 +5210,7 @@ _Per istruzioni più dettagliate, [visita il nostro sito di assistenza](${CONST.
                 },
                 bankConnectionError: 'Problema di connessione bancaria',
                 connectWithPlaid: 'collega tramite Plaid',
-                connectWithExpensifyCard: 'prova la Carta Expensify.',
+                connectWithExpensifyCard: 'prova la Expensify Card.',
                 bankConnectionDescription: `Prova ad aggiungere di nuovo le tue carte. Altrimenti, puoi`,
                 disableCardTitle: 'Disattiva carte aziendali',
                 disableCardPrompt: 'Non puoi disattivare le carte aziendali perché questa funzionalità è in uso. Contatta Concierge per sapere come procedere.',
@@ -5848,11 +5231,8 @@ _Per istruzioni più dettagliate, [visita il nostro sito di assistenza](${CONST.
                 updateCard: 'Aggiorna carta',
                 unassignCard: 'Rimuovi carta',
                 unassign: 'Rimuovi assegnazione',
-                unassignCardDescription: 'La rimozione dell’assegnazione di questa carta eliminerà tutte le transazioni non inviate.',
+                unassignCardDescription: 'La rimozione dell’assegnazione di questa carta eliminerà tutte le transazioni nei report in bozza dall’account del titolare della carta.',
                 assignCard: 'Assegna carta',
-                removeCard: 'Rimuovi carta',
-                remove: 'Rimuovi',
-                removeCardDescription: 'La rimozione di questa carta eliminerà tutte le transazioni non inviate.',
                 cardFeedName: 'Nome feed carta',
                 cardFeedNameDescription: 'Dai al feed della carta un nome univoco, così puoi distinguerlo dagli altri.',
                 cardFeedTransaction: 'Elimina transazioni',
@@ -5883,9 +5263,9 @@ _Per istruzioni più dettagliate, [visita il nostro sito di assistenza](${CONST.
                 noAccountsFound: 'Nessun account trovato',
                 defaultCard: 'Carta predefinita',
                 downgradeTitle: `Impossibile eseguire il downgrade dello spazio di lavoro`,
-                downgradeSubTitle: `Questo spazio di lavoro non può essere declassato perché sono collegati più flussi di carte (escluse le Carte Expensify). Per procedere, <a href="#">mantieni un solo flusso di carte</a>.`,
+                downgradeSubTitle: `Questo spazio di lavoro non può essere declassato perché sono collegati più flussi di carte (escluse le Expensify Card). Per continuare, <a href="#">mantieni un solo flusso di carte</a>.`,
                 noAccountsFoundDescription: (connection: string) => `Aggiungi l’account in ${connection} e sincronizza nuovamente la connessione`,
-                expensifyCardBannerTitle: 'Ottieni la Carta Expensify',
+                expensifyCardBannerTitle: 'Ottieni la Expensify Card',
                 expensifyCardBannerSubtitle:
                     'Goditi il cashback su ogni acquisto negli Stati Uniti, fino al 50% di sconto sulla tua fattura Expensify, carte virtuali illimitate e molto altro ancora.',
                 expensifyCardBannerLearnMoreButton: 'Scopri di più',
@@ -5896,7 +5276,7 @@ _Per istruzioni più dettagliate, [visita il nostro sito di assistenza](${CONST.
                 title: 'Flussi di lavoro',
                 subtitle: 'Configura come le spese vengono approvate e pagate.',
                 disableApprovalPrompt:
-                    'Le Carte Expensify di questo spazio di lavoro al momento si basano sulle approvazioni per definire i loro Smart Limits. Modifica i tipi di limite di tutte le Carte Expensify con Smart Limits prima di disattivare le approvazioni.',
+                    'Le Expensify Card di questo spazio di lavoro attualmente si basano sulle approvazioni per definire i loro Smart Limit. Modifica i tipi di limite di tutte le Expensify Card con Smart Limit prima di disattivare le approvazioni.',
             },
             invoices: {
                 title: 'Fatture',
@@ -5941,8 +5321,8 @@ _Per istruzioni più dettagliate, [visita il nostro sito di assistenza](${CONST.
             workflowWarningModal: {
                 featureEnabledTitle: 'Non così in fretta...',
                 featureEnabledText:
-                    'Le Carte Expensify in questo spazio di lavoro si basano sui flussi di approvazione per definire i loro Limiti Smart.\n\nModifica i tipi di limite di tutte le carte con Limiti Smart prima di disattivare i flussi di lavoro.',
-                confirmText: 'Vai a Carte Expensify',
+                    'Le Expensify Card in questo spazio di lavoro si basano sui flussi di approvazione per definire i loro Smart Limit.\n\nModifica i tipi di limite di tutte le carte con Smart Limit prima di disattivare i flussi di lavoro.',
+                confirmText: 'Vai a Expensify Cards',
             },
             rules: {
                 title: 'Regole',
@@ -5953,7 +5333,6 @@ _Per istruzioni più dettagliate, [visita il nostro sito di assistenza](${CONST.
                 subtitle: 'Imposta una tariffa oraria fatturabile per il rilevamento del tempo.',
                 defaultHourlyRate: 'Tariffa oraria predefinita',
             },
-            hrWarningModal: {disconnectText: ({integration}: {integration: string}) => `Per disattivare HR, scollega prima ${integration} da questo workspace.`},
         },
         reports: {
             reportsCustomTitleExamples: 'Esempi:',
@@ -5975,7 +5354,10 @@ _Per istruzioni più dettagliate, [visita il nostro sito di assistenza](${CONST.
             findReportField: 'Trova campo report',
             deleteConfirmation: 'Sei sicuro di voler eliminare questo campo del report?',
             deleteFieldsConfirmation: 'Sei sicuro di voler eliminare questi campi del resoconto?',
-            emptyReportFields: {title: 'Nessun campo di report ancora', subtitle: 'Aggiungi un campo personalizzato (testo, data o menu a discesa) che appare nei report.'},
+            emptyReportFields: {
+                title: 'Non hai creato nessun campo di rendiconto',
+                subtitle: 'Aggiungi un campo personalizzato (testo, data o menu a discesa) che appare nei report.',
+            },
             subtitle: 'I campi del report si applicano a tutte le spese e possono essere utili quando desideri richiedere informazioni aggiuntive.',
             disableReportFields: 'Disattiva campi del report',
             disableReportFieldsConfirmation: 'Sei sicuro? I campi di testo e data verranno eliminati e gli elenchi verranno disattivati.',
@@ -5999,7 +5381,10 @@ _Per istruzioni più dettagliate, [visita il nostro sito di assistenza](${CONST.
             disableValues: 'Disabilita valori',
             enableValue: 'Abilita valore',
             enableValues: 'Abilita valori',
-            emptyReportFieldsValues: {title: 'Nessun valore in elenco ancora', subtitle: 'Aggiungi valori personalizzati da visualizzare nei report.'},
+            emptyReportFieldsValues: {
+                title: 'Non hai creato alcun valore elenco',
+                subtitle: 'Aggiungi valori personalizzati da visualizzare nei report.',
+            },
             deleteValuePrompt: "Sei sicuro di voler eliminare questo valore dell'elenco?",
             deleteValuesPrompt: "Sei sicuro di voler eliminare questi valori dell'elenco?",
             listValueRequiredError: 'Inserisci il nome di un valore dell’elenco',
@@ -6011,33 +5396,9 @@ _Per istruzioni più dettagliate, [visita il nostro sito di assistenza](${CONST.
             reportFieldNameRequiredError: 'Inserisci un nome per il campo del report',
             reportFieldTypeRequiredError: 'Scegli un tipo di campo del report',
             circularReferenceError: 'Questo campo non può fare riferimento a se stesso. Aggiorna per favore.',
-            unsupportedFormulaValueError: ({value}: UnsupportedFormulaValueErrorParams) => `Campo formula ${value} non riconosciuto`,
             reportFieldInitialValueRequiredError: 'Scegli un valore iniziale per il campo del resoconto',
             genericFailureMessage: 'Si è verificato un errore durante l’aggiornamento del campo del report. Riprova.',
         },
-        invoiceFields: {
-            subtitle: 'I campi della fattura possono essere utili quando vuoi includere informazioni aggiuntive.',
-            importedFromAccountingSoftware: 'I campi della fattura riportati di seguito sono importati dal tuo',
-            disableInvoiceFields: 'Disattiva i campi della fattura',
-            disableInvoiceFieldsConfirmation: 'Sei sicuro? I campi della fattura verranno disattivati nelle fatture.',
-            delete: 'Elimina campo della fattura',
-            deleteConfirmation: 'Sei sicuro di voler eliminare questo campo della fattura?',
-            findInvoiceField: 'Trova campo della fattura',
-            nameInputSubtitle: 'Scegli un nome per il campo della fattura.',
-            typeInputSubtitle: 'Scegli il tipo di campo della fattura da utilizzare.',
-            initialValueInputSubtitle: 'Inserisci un valore iniziale da mostrare nel campo della fattura.',
-            listValuesInputSubtitle: 'Questi valori appariranno nel menu a discesa del campo della fattura. I valori abilitati possono essere selezionati dai membri.',
-            listInputSubtitle: 'Questi valori appariranno nell’elenco del campo della fattura. I valori abilitati possono essere selezionati dai membri.',
-            emptyInvoiceFieldsValues: {
-                title: 'Nessun valore elenco ancora',
-                subtitle: 'Aggiungi valori personalizzati da mostrare sulle fatture.',
-            },
-            existingInvoiceFieldNameError: 'Esiste già un campo della fattura con questo nome',
-            invoiceFieldNameRequiredError: 'Inserisci un nome per il campo della fattura',
-            invoiceFieldTypeRequiredError: 'Scegli un tipo di campo della fattura',
-            invoiceFieldInitialValueRequiredError: 'Scegli un valore iniziale per il campo della fattura',
-            addField: 'Aggiungi campo',
-        },
         tags: {
             tagName: 'Nome tag',
             requiresTag: 'I membri devono etichettare tutte le spese',
@@ -6055,14 +5416,14 @@ _Per istruzioni più dettagliate, [visita il nostro sito di assistenza](${CONST.
             editTags: 'Modifica tag',
             findTag: 'Trova tag',
             subtitle: 'I tag aggiungono modi più dettagliati per classificare i costi.',
-            subtitleWithDependentTags: (importSpreadsheetLink: string, canReimport = true) =>
-                `<muted-text>I tag aggiungono modi più dettagliati per classificare i costi. Stai usando i <a href="${CONST.IMPORT_TAGS_EXPENSIFY_URL_DEPENDENT_TAGS}">tag dipendenti</a>.${canReimport ? ` Puoi <a href="${importSpreadsheetLink}">importare nuovamente un foglio di calcolo</a> per aggiornare i tuoi tag.` : ''}</muted-text>`,
+            dependentMultiLevelTagsSubtitle: (importSpreadsheetLink: string) =>
+                `<muted-text>Stai usando i <a href="${CONST.IMPORT_TAGS_EXPENSIFY_URL_DEPENDENT_TAGS}">tag dipendenti</a>. Puoi <a href="${importSpreadsheetLink}">importare nuovamente un foglio di calcolo</a> per aggiornare i tuoi tag.</muted-text>`,
             emptyTags: {
-                title: 'Nessun tag ancora',
+                title: 'Non hai creato alcun tag',
                 subtitle: 'Aggiungi un tag per tenere traccia di progetti, sedi, reparti e altro ancora.',
                 subtitleHTML: `<muted-text><centered-text>Aggiungi tag per tenere traccia di progetti, sedi, reparti e altro ancora. <a href="${CONST.IMPORT_TAGS_EXPENSIFY_URL}">Scopri di più</a> sulla formattazione dei file dei tag da importare.</centered-text></muted-text>`,
-                subtitleWithAccounting: (accountingPageURL: string, canManage = true) =>
-                    `<muted-text><centered-text>I tuoi tag vengono attualmente importati da una connessione di contabilità.${canManage ? ` Vai alla sezione <a href="${accountingPageURL}">Contabilità</a> per apportare qualsiasi modifica.` : ''}</centered-text></muted-text>`,
+                subtitleWithAccounting: (accountingPageURL: string) =>
+                    `<muted-text><centered-text>I tuoi tag vengono attualmente importati da una connessione di contabilità. Vai alla sezione <a href="${accountingPageURL}">Contabilità</a> per apportare qualsiasi modifica.</centered-text></muted-text>`,
             },
             deleteTag: 'Elimina tag',
             deleteTags: 'Elimina tag',
@@ -6148,7 +5509,7 @@ _Per istruzioni più dettagliate, [visita il nostro sito di assistenza](${CONST.
                 updateTaxClaimableFailureMessage: 'La parte recuperabile deve essere inferiore all’importo della tariffa chilometrica',
             },
             deleteTaxConfirmation: 'Sei sicuro di voler eliminare questa imposta?',
-            deleteMultipleTaxConfirmation: (taxAmount: number) => `Sei sicuro di voler eliminare ${taxAmount} imposte?`,
+            deleteMultipleTaxConfirmation: ({taxAmount}: TaxAmountParams) => `Sei sicuro di voler eliminare ${taxAmount} imposte?`,
             actions: {
                 delete: 'Elimina tariffa',
                 deleteMultiple: 'Elimina tariffe',
@@ -6176,46 +5537,10 @@ _Per istruzioni più dettagliate, [visita il nostro sito di assistenza](${CONST.
             reimbursementAccount: 'conto di rimborso',
             welcomeNote: 'Inizia a usare il mio nuovo workspace',
             delayedSubmission: 'invio posticipato',
-            merchantRules: 'Regole del commerciante',
-            merchantRulesCount: () => ({
-                one: '1 regola del commerciante',
-                other: (count: number) => `${count} regole del commerciante`,
-            }),
             confirmTitle: ({newWorkspaceName, totalMembers}: {newWorkspaceName?: string; totalMembers?: number}) =>
                 `Stai per creare e condividere ${newWorkspaceName ?? ''} con ${totalMembers ?? 0} membri dello spazio di lavoro originale.`,
             error: 'Si è verificato un errore durante la duplicazione del tuo nuovo workspace. Riprova.',
         },
-        copyPolicySettings: {
-            title: 'Copia impostazioni',
-            error: 'Si è verificato un errore durante la copia delle impostazioni dello spazio di lavoro. Riprova.',
-            selectWorkspaces: {
-                title: 'Seleziona gli spazi di lavoro',
-                description: 'Scegli gli spazi di lavoro a cui vuoi copiare le impostazioni, poi seleziona le impostazioni che desideri copiare.',
-                searchPlaceholder: 'Cerca spazio di lavoro',
-            },
-            selectSettings: {
-                title: 'Seleziona le funzionalità da copiare',
-                description: 'Seleziona le impostazioni da sovrascrivere nei tuoi workspace esistenti.',
-                accountingMismatch: ({part}: {part: string}) =>
-                    `Puoi copiare ${part} solo se tutti gli spazi di lavoro usano lo stesso sistema di contabilità e la stessa connessione aziendale.`,
-            },
-            confirmSettings: {
-                title: 'Assicuriamoci che sia tutto corretto.',
-                description: ({workspaceName}: {workspaceName: string}) => `Copieremo le seguenti impostazioni da <strong>${workspaceName}</strong> agli spazi di lavoro che hai specificato`,
-            },
-            confirmWorkflows: {
-                continue: 'Continua senza membri',
-                description: 'Copiare Flussi di lavoro senza Membri non copierà i flussi di lavoro di approvazione. Le impostazioni di invio e pagamento verranno comunque copiate.',
-            },
-            progress: {
-                copyInProgressTitle: 'Copia in corso...',
-                copyInProgressDescription: 'Puoi aspettare che il processo finisca oppure Concierge può avvisarti quando è terminato.',
-                letMeKnowPrompt: 'Fammi sapere quando hai finito',
-                conciergeNotificationTitle: 'Concierge ti farà sapere',
-                conciergeNotificationDescription: 'Quando il processo sarà completato, Concierge ti invierà un messaggio.',
-                copyCompleted: 'Le impostazioni dello spazio di lavoro sono state copiate.',
-            },
-        },
         emptyWorkspace: {
             title: 'Non hai nessuna area di lavoro',
             subtitle: 'Tieni traccia delle ricevute, rimborsa le spese, gestisci i viaggi, invia le fatture e altro ancora.',
@@ -6230,7 +5555,7 @@ _Per istruzioni più dettagliate, [visita il nostro sito di assistenza](${CONST.
         },
         new: {
             newWorkspace: 'Nuovo spazio di lavoro',
-            getTheExpensifyCardAndMore: 'Ottieni la Carta Expensify e altro ancora',
+            getTheExpensifyCardAndMore: 'Ottieni la Expensify Card e altro ancora',
             confirmWorkspace: 'Conferma spazio di lavoro',
             myGroupWorkspace: ({workspaceNumber}: {workspaceNumber?: number}) => `Il mio spazio di lavoro di gruppo${workspaceNumber ? ` ${workspaceNumber}` : ''}`,
             workspaceName: (userName: string, workspaceNumber?: number) => `Workspace di ${userName}${workspaceNumber ? ` ${workspaceNumber}` : ''}`,
@@ -6273,12 +5598,12 @@ _Per istruzioni più dettagliate, [visita il nostro sito di assistenza](${CONST.
                 genericRemove: 'Si è verificato un problema durante la rimozione di quel membro dello spazio di lavoro',
             },
             addedWithPrimary: 'Alcuni membri sono stati aggiunti con i loro accessi principali.',
-            invitedBySecondaryLogin: (secondaryLogin: string) => `Aggiunto dall’accesso secondario ${secondaryLogin}.`,
-            workspaceMembersCount: (count: number) => `Totale membri dello spazio di lavoro: ${count}`,
+            invitedBySecondaryLogin: ({secondaryLogin}: SecondaryLoginParams) => `Aggiunto dall’accesso secondario ${secondaryLogin}.`,
+            workspaceMembersCount: ({count}: WorkspaceMembersCountParams) => `Totale membri dello spazio di lavoro: ${count}`,
             importMembers: 'Importa membri',
-            removeMemberPromptApprover: (approver: string, workspaceOwner: string) =>
+            removeMemberPromptApprover: ({approver, workspaceOwner}: {approver: string; workspaceOwner: string}) =>
                 `Se rimuovi ${approver} da questo workspace, lo sostituiremo nel flusso di approvazione con ${workspaceOwner}, il proprietario del workspace.`,
-            removeMemberPromptPendingApproval: (memberName: string) =>
+            removeMemberPromptPendingApproval: ({memberName}: {memberName: string}) =>
                 `${memberName} ha note spese in sospeso da approvare. Chiedi loro di approvarle o di prendere il controllo delle loro note spese prima di rimuoverli dallo spazio di lavoro.`,
             removeMemberPromptReimburser: ({memberName}: {memberName: string}) =>
                 `Non puoi rimuovere ${memberName} da questo workspace. Imposta un nuovo rimborsatore in Flussi di lavoro > Effettua o tieni traccia dei pagamenti, quindi riprova.`,
@@ -6288,20 +5613,10 @@ _Per istruzioni più dettagliate, [visita il nostro sito di assistenza](${CONST.
                 `Se rimuovi ${memberName} da questo spazio di lavoro, lo sostituiremo come referente tecnico con ${workspaceOwner}, il proprietario dello spazio di lavoro.`,
             cannotRemoveUserDueToReport: ({memberName}: {memberName: string}) =>
                 `${memberName} ha un rapporto in sospeso su cui deve intervenire. Chiedi loro di completare l’azione richiesta prima di rimuoverlə dallo spazio di lavoro.`,
-            allMembers: 'Tutti i membri',
-            admins: 'Amministratori workspace',
-            cardAdmins: 'Amministratori carte',
-            approvers: 'Approvatori',
-            auditors: 'Revisori',
-            emptyRoleFilter: {title: 'Nessun membro corrisponde a questo filtro', subtitle: 'Invita un membro o modifica il filtro qui sopra.'},
-            configureHRSync: (providerName: string) => `Configura la sincronizzazione di ${providerName}.`,
-            syncWithHR: (providerName: string) => `Sincronizza con ${providerName}`,
-            makeCardAdmin: () => ({one: 'Rendi amministratore della carta', other: 'Rendi amministratori carta'}),
         },
         card: {
             getStartedIssuing: 'Inizia emettendo la tua prima carta virtuale o fisica.',
             issueCard: 'Emetti carta',
-            chooseRule: 'Scegli una regola',
             issueNewCard: {
                 whoNeedsCard: 'Chi ha bisogno di una carta?',
                 inviteNewMember: 'Invita nuovo membro',
@@ -6343,27 +5658,22 @@ _Per istruzioni più dettagliate, [visita il nostro sito di assistenza](${CONST.
                 enterValidDate: 'Inserisci una data valida',
                 expirationDate: 'Data di scadenza',
                 limitAmount: 'Importo del limite',
-                setCardRules: 'Imposta regole carta',
-                addSpendRule: 'Aggiungi regola di spesa',
-                addExpirationDate: 'Aggiungi data di scadenza',
-                addExpirationDateDescription: 'Se non viene impostata una data specifica, la carta scadrà in base alla data di scadenza già presente sulla carta',
+                setExpiryOptions: 'Imposta opzioni di scadenza',
+                setExpiryDate: 'Imposta data di scadenza',
+                setExpiryDateDescription: 'La carta scadrà come indicato sulla carta',
                 amount: 'Importo',
-                copyExisting: 'Copia esistente',
-                createNew: 'Crea nuovo',
-                spendRulesEmptyStateTitle: 'Nessuna regola tra cui scegliere',
-                spendRulesEmptyStateSubtitle: 'Ancuna nessuna regola. Puoi crearne una dalla schermata precedente.',
             },
             deactivateCardModal: {
                 deactivate: 'Disattiva',
                 deactivateCard: 'Disattiva carta',
                 deactivateConfirmation: 'La disattivazione di questa carta rifiuterà tutte le transazioni future e non può essere annullata.',
             },
-            searchRules: 'Trova regola di spesa',
         },
         accounting: {
             settings: 'impostazioni',
             title: 'Connessioni',
-            subtitle: 'Collega il tuo software di contabilità per una sincronizzazione automatica.',
+            subtitle:
+                'Connetti il tuo sistema contabile per codificare le transazioni con il tuo piano dei conti, abbinare automaticamente i pagamenti e mantenere le tue finanze sincronizzate.',
             qbo: 'QuickBooks Online',
             qbd: 'QuickBooks Desktop',
             xero: 'Xero',
@@ -6372,7 +5682,7 @@ _Per istruzioni più dettagliate, [visita il nostro sito di assistenza](${CONST.
             sap: 'SAP',
             oracle: 'Oracle',
             microsoftDynamics: 'Microsoft Dynamics',
-            talkYourOnboardingSpecialist: 'Chatta con il tuo account executive.',
+            talkYourOnboardingSpecialist: 'Chatta con il tuo specialista di configurazione.',
             talkYourAccountManager: 'Chatta con il tuo account manager.',
             talkToConcierge: 'Chatta con Concierge.',
             needAnotherAccounting: 'Ti serve un altro software di contabilità?',
@@ -6447,8 +5757,6 @@ _Per istruzioni più dettagliate, [visita il nostro sito di assistenza](${CONST.
             connectPrompt: ({connectionName}: ConnectionNameParams) =>
                 `Sei sicuro di voler collegare ${CONST.POLICY.CONNECTIONS.NAME_USER_FRIENDLY[connectionName] ?? 'questa integrazione contabile'}? Questo rimuoverà tutte le connessioni contabili esistenti.`,
             enterCredentials: 'Inserisci le tue credenziali',
-            reconnect: 'Riconnetti',
-            updateCredentials: 'Aggiorna credenziali',
             claimOffer: {
                 badgeText: 'Offerta disponibile!',
                 xero: {
@@ -6591,26 +5899,6 @@ _Per istruzioni più dettagliate, [visita il nostro sito di assistenza](${CONST.
                             return 'Importazione delle dimensioni Sage Intacct';
                         case 'intacctImportTitle':
                             return 'Importazione dei dati Sage Intacct';
-                        case 'financialForceSyncTitle':
-                            return 'Sincronizzazione dei dati Certinia';
-                        case 'financialForceSyncStep':
-                            return 'Sincronizzazione della connessione Certinia';
-                        case 'financialForceSyncCategories':
-                            return 'Importazione delle categorie';
-                        case 'financialForceSyncTags':
-                            return 'Importazione dei tag';
-                        case 'financialForceSyncVendors':
-                            return 'Importazione dei fornitori';
-                        case 'financialForceSyncContacts':
-                            return 'Importazione dei contatti';
-                        case 'financialForceSyncCompanies':
-                            return 'Importazione delle aziende';
-                        case 'financialForceSyncUsers':
-                            return 'Importazione degli utenti';
-                        case 'financialForceSyncDimensions':
-                            return 'Importazione delle dimensioni';
-                        case 'financialForceMarkAsReimbursed':
-                            return 'Contrassegno dei report come rimborsati';
                         default: {
                             return `Traduzione mancante per lo stato: ${stage}`;
                         }
@@ -6633,18 +5921,14 @@ _Per istruzioni più dettagliate, [visita il nostro sito di assistenza](${CONST.
             reconciliationAccount: 'Conto di riconciliazione',
             continuousReconciliation: 'Riconciliazione continua',
             saveHoursOnReconciliation:
-                'Risparmia ore di riconciliazione a ogni periodo contabile lasciando che Expensify riconcili in modo continuo gli estratti conto e i regolamenti della Carta Expensify per tuo conto.',
+                'Risparmia ore nel riconciliare ogni periodo contabile grazie a Expensify, che riconcilia in modo continuo per tuo conto gli estratti conto e i regolamenti della Expensify Card.',
             enableContinuousReconciliation: (accountingAdvancedSettingsLink: string, connectionName: string) =>
                 `<muted-text-label>Per abilitare la Riconciliazione continua, abilita la <a href="${accountingAdvancedSettingsLink}">sincronizzazione automatica</a> per ${connectionName}.</muted-text-label>`,
             chooseReconciliationAccount: {
-                chooseBankAccount: 'Scegli il conto bancario con cui verranno riconciliati i pagamenti della tua Carta Expensify.',
-                settlementAccountReconciliation: (settlementAccountUrl: string, lastFourPAN: string) =>
-                    `Assicurati che questo conto corrisponda al tuo <a href="${settlementAccountUrl}">conto di regolamento della Carta Expensify</a> (con finale ${lastFourPAN}) affinché la Riconciliazione continua funzioni correttamente.`,
-                chooseTravelInvoicingBankAccount: 'Scegli il conto bancario su cui verranno riconciliati i pagamenti della fatturazione di viaggio.',
-                travelInvoicingSettlementAccountReconciliation: (lastFourPAN: string) =>
-                    `Assicurati che questo conto corrisponda al tuo conto di regolamento per la fatturazione dei viaggi (che termina con ${lastFourPAN}) in modo che la Riconciliazione continua funzioni correttamente.`,
+                chooseBankAccount: 'Scegli il conto bancario con cui verranno riconciliati i pagamenti della tua Expensify Card.',
+                settlementAccountReconciliation: ({settlementAccountUrl, lastFourPAN}: SettlementAccountReconciliationParams) =>
+                    `Assicurati che questo conto corrisponda al tuo <a href="${settlementAccountUrl}">conto di regolamento della carta Expensify</a> (che termina con ${lastFourPAN}) affinché la Riconciliazione Continua funzioni correttamente.`,
             },
-            syncTravelInvoicingSettlements: 'Sincronizza le liquidazioni delle fatture di viaggio',
         },
         export: {
             notReadyHeading: 'Non pronto per l’esportazione',
@@ -6723,13 +6007,7 @@ _Per istruzioni più dettagliate, [visita il nostro sito di assistenza](${CONST.
             errors: {
                 rateNameRequired: 'Il nome della tariffa è obbligatorio',
                 existingRateName: 'Esiste già una tariffa distanza con questo nome',
-                nameRequired: 'Il nome è obbligatorio',
-                startDateMustBeBeforeEndDate: 'La data di inizio deve essere precedente alla data di fine',
-                amountRequired: "L'importo è obbligatorio",
             },
-            amountPerUnit: (unit: string) => `Importo per ${unit}`,
-            startDate: 'Data di inizio',
-            endDate: 'Data di fine',
         },
         editor: {
             descriptionInputLabel: 'Descrizione',
@@ -6772,7 +6050,7 @@ _Per istruzioni più dettagliate, [visita il nostro sito di assistenza](${CONST.
             updateToUSD: 'Aggiorna a USD',
             updateWorkspaceCurrency: 'Aggiorna la valuta dello spazio di lavoro',
             workspaceCurrencyNotSupported: 'Valuta dello spazio di lavoro non supportata',
-            yourWorkspace: `La tua area di lavoro è impostata su una valuta non supportata. Visualizza l’<a href="${CONST.ENABLE_GLOBAL_REIMBURSEMENT_HELP_URL}">elenco delle valute supportate</a>.`,
+            yourWorkspace: `La tua area di lavoro è impostata su una valuta non supportata. Visualizza l’<a href="${CONST.CONNECT_A_BUSINESS_BANK_ACCOUNT_HELP_URL}">elenco delle valute supportate</a>.`,
             chooseAnExisting: 'Scegli un conto bancario esistente per pagare le spese oppure aggiungine uno nuovo.',
         },
         changeOwner: {
@@ -6809,7 +6087,7 @@ Se vuoi assumere la fatturazione per l'intero abbonamento, chiedi loro di aggiun
             hasFailedSettlementsTitle: 'Impossibile trasferire la proprietà',
             hasFailedSettlementsButtonText: 'Ho capito',
             hasFailedSettlementsText: (email: string) =>
-                `Non puoi subentrare nella fatturazione perché ${email} ha una regolazione in sospeso della Carta Expensify. Chiedi loro di contattare concierge@expensify.com per risolvere il problema. Dopodiché potrai subentrare nella fatturazione di questo spazio di lavoro.`,
+                `Non puoi assumere la fatturazione perché ${email} ha una regolazione in sospeso della Expensify Card. Chiedi a questa persona di contattare concierge@expensify.com per risolvere il problema. Dopodiché, potrai assumere la fatturazione per questo spazio di lavoro.`,
             failedToClearBalanceTitle: 'Impossibile azzerare il saldo',
             failedToClearBalanceButtonText: 'OK',
             failedToClearBalanceText: 'Non è stato possibile azzerare il saldo. Riprova più tardi.',
@@ -6838,12 +6116,6 @@ Vuoi davvero esportarli di nuovo?`,
                 onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
                     `<muted-text>I campi del report sono disponibili solo con il piano Control, a partire da <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `per utente al mese.` : `per membro attivo al mese.`}</muted-text>`,
             },
-            invoiceFields: {
-                title: 'Campi fattura',
-                description: `I campi fattura ti consentono di includere dettagli aggiuntivi a livello di fattura.`,
-                onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
-                    `<muted-text>I campi fattura sono disponibili solo con il piano Control, a partire da <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `per utente al mese.` : `per membro attivo al mese.`}</muted-text>`,
-            },
             [CONST.POLICY.CONNECTIONS.NAME.NETSUITE]: {
                 title: 'NetSuite',
                 description: `Approfitta della sincronizzazione automatica e riduci le registrazioni manuali con l’integrazione Expensify + NetSuite. Ottieni approfondimenti finanziari dettagliati e in tempo reale grazie al supporto di segmenti nativi e personalizzati, inclusa la mappatura di progetti e clienti.`,
@@ -6862,12 +6134,6 @@ Vuoi davvero esportarli di nuovo?`,
                 onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
                     `<muted-text>La nostra integrazione con QuickBooks Desktop è disponibile solo con il piano Control, a partire da <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `per utente al mese.` : `per membro attivo al mese.`}</muted-text>`,
             },
-            [CONST.POLICY.CONNECTIONS.NAME.CERTINIA]: {
-                title: 'Certinia',
-                description: `Approfitta della sincronizzazione automatizzata e riduci le registrazioni manuali con l’integrazione Expensify + Certinia. Allinea dimensioni di codifica delle spese e sincronizzazione fiscale alla tua configurazione Certinia per una maggiore visibilità finanziaria.`,
-                onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
-                    `<muted-text>La nostra integrazione con Certinia è disponibile solo con il piano Control, a partire da <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `per utente al mese.` : `per membro attivo al mese.`}</muted-text>`,
-            },
             [CONST.UPGRADE_FEATURE_INTRO_MAPPING.approvals.id]: {
                 title: 'Approvazioni avanzate',
                 description: `Se desideri aggiungere altri livelli di approvazione al processo – o semplicemente assicurarti che le spese più elevate ricevano un ulteriore controllo – ci pensiamo noi. Le approvazioni avanzate ti aiutano a impostare i controlli giusti a ogni livello, così mantieni la spesa del tuo team sotto controllo.`,
@@ -6945,7 +6211,7 @@ Richiedi dettagli sulle spese come ricevute e descrizioni, imposta limiti e valo
                 onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
                     `<muted-text>Le tariffe chilometriche sono disponibili con il piano Collect, a partire da <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `per utente al mese.` : `per membro attivo al mese.`}</muted-text>`,
             },
-            controlPolicyRoles: {
+            auditor: {
                 title: 'Revisore',
                 description: 'I revisori ottengono accesso in sola lettura a tutti i report per garantire completa visibilità e monitoraggio della conformità.',
                 onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
@@ -6962,12 +6228,13 @@ Richiedi dettagli sulle spese come ricevute e descrizioni, imposta limiti e valo
                 perActiveMember: 'per membro attivo al mese.',
                 perMember: 'per utente al mese.',
             },
-            note: (subscriptionLink: string) => `<muted-text><a href="${subscriptionLink}">Scopri di più</a> sui nostri piani e prezzi.</muted-text>`,
+            note: ({subscriptionLink}: WorkspaceUpgradeNoteParams) =>
+                `<muted-text>Effettua l’upgrade per accedere a questa funzione oppure <a href="${subscriptionLink}">scopri di più</a> sui nostri piani e prezzi.</muted-text>`,
             upgradeToUnlock: 'Sblocca questa funzionalità',
             completed: {
                 headline: `Hai aggiornato il tuo spazio di lavoro!`,
-                successMessage: (policyName: string, planName: string, subscriptionLink: string) =>
-                    `<centered-text>Hai effettuato l'upgrade di ${policyName} al piano ${planName}! <a href="${subscriptionLink}">Visualizza il tuo abbonamento</a> per maggiori dettagli.</centered-text>`,
+                successMessage: ({policyName, subscriptionLink}: UpgradeSuccessMessageParams) =>
+                    `<centered-text>Hai effettuato l'upgrade di ${policyName} al piano Control! <a href="${subscriptionLink}">Visualizza il tuo abbonamento</a> per maggiori dettagli.</centered-text>`,
                 categorizeMessage: `Hai eseguito l’upgrade al piano Collect. Ora puoi categorizzare le tue spese!`,
                 travelMessage: `Hai eseguito correttamente l’upgrade al piano Collect. Ora puoi iniziare a prenotare e gestire i viaggi!`,
                 distanceRateMessage: `Hai eseguito correttamente l’upgrade al piano Collect. Ora puoi modificare il rimborso chilometrico!`,
@@ -6990,88 +6257,25 @@ Richiedi dettagli sulle spese come ricevute e descrizioni, imposta limiti e valo
                 upgradeWorkspaceWarning: `Impossibile eseguire l'upgrade dello spazio di lavoro`,
                 upgradeWorkspaceWarningForRestrictedPolicyCreationPrompt: 'La tua azienda ha limitato la creazione degli spazi di lavoro. Contatta un amministratore per assistenza.',
             },
-            hr: {
-                title: 'Integrazioni HR',
-                description:
-                    'Collega il tuo provider HR per sincronizzare automaticamente i dipendenti e gestire i flussi di approvazione. Mantieni l’organigramma del tuo team e la struttura dei report sempre aggiornati senza lavoro manuale.',
-                onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
-                    `<muted-text>Le integrazioni HR sono disponibili solo con il piano Control, a partire da <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `per membro al mese.` : `per membro attivo al mese.`}</muted-text>`,
-            },
-            approvalSubmit: {
-                title: 'Approvazioni',
-                description: 'Configura centralmente a chi tutti i membri inviano le note spese abilitando le approvazioni.',
-                onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
-                    `<muted-text>Le approvazioni sono disponibili nei piani Collect e Control, a partire da <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `per membro al mese.` : `per membro attivo al mese.`}</muted-text>`,
-            },
-            companyCardSubmit: {
-                title: 'Carte aziendali',
-                description: `Porta la tua carta aziendale in Expensify per ottenere importazione automatica, categorizzazione automatica, supporto per regole personalizzabili e riconciliazione integrata.`,
-                onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
-                    `<muted-text>L'importazione della carta aziendale è disponibile con i piani Collect e Control, a partire da <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `per membro al mese.` : `per membro attivo al mese.`}</muted-text>`,
-            },
-            travelSubmit: {
-                title: 'Expensify Travel',
-                description:
-                    'Prenota in tutto il mondo voli, hotel, auto e treni scontati direttamente da Expensify, con reportistica per il duty of care e gestione integrata delle note spese.',
-                onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
-                    `<muted-text>Expensify Travel è disponibile con i piani Collect e Control, a partire da <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `per membro al mese.` : `per membro attivo al mese.`}</muted-text>`,
-            },
-            roles: {
-                title: 'Ruoli',
-                description: 'Assegna ruoli diversi ai vari membri per aumentare o ridurre visibilità e controllo secondo le esigenze.',
-                onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
-                    `<muted-text>I ruoli sono disponibili nei piani Collect e Control, a partire da <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `per membro al mese.` : `per membro attivo al mese.`}</muted-text>`,
-            },
-            payments: {
-                title: 'Pagamenti',
-                description: 'Rimborsa i dipendenti direttamente dal conto bancario aziendale.',
-                onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
-                    `<muted-text>I pagamenti sono disponibili nei piani Collect e Control, a partire da <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `per membro al mese.` : `per membro attivo al mese.`}</muted-text>`,
-            },
-            accounting: {
-                title: 'Contabilità',
-                description:
-                    'Sincronizza categorie, tag, aliquote fiscali e altro dal tuo sistema contabile a Expensify ed esporta anche note spese e transazioni con carta, senza bisogno di digitare nulla (né di rischiare errori di battitura)!',
-                onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
-                    `<muted-text>La contabilità è disponibile con i piani Collect e Control, a partire da <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `per membro al mese.` : `per membro attivo al mese.`}</muted-text>`,
-            },
-            expensifyCard: {
-                title: 'Carta Expensify',
-                description:
-                    'Emetti carte aziendali (incluse carte virtuali) direttamente dal tuo conto bancario per ottenere il controllo in tempo reale delle spese con una connessione infallibile e fino al 2% di cashback!',
-                onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
-                    `<muted-text>La Expensify Card è disponibile con i piani Collect e Control, a partire da <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `per membro al mese.` : `per membro attivo al mese.`}</muted-text>`,
-                upgradeButton: 'Aggiorna e abilita',
-            },
-            invoicing: {
-                title: 'Fatturazione',
-                description:
-                    'Crea, invia e monitora fatture professionali, tutto all’interno di Expensify. Ricevi i pagamenti più velocemente con pagamenti integrati e visibilità in tempo reale.',
-                onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
-                    `<muted-text>La fatturazione è disponibile nei piani Collect e Control, a partire da <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `per membro al mese.` : `per membro attivo al mese.`}</muted-text>`,
-            },
         },
         downgrade: {
             commonFeatures: {
-                title: 'Passa a Collect',
-                note: 'Perderai l’accesso alle seguenti funzionalità',
+                title: 'Passa al piano Collect',
+                note: 'Se esegui il downgrade, perderai l’accesso a queste funzionalità e ad altre ancora:',
                 benefits: {
-                    confirm: 'Dovrai cambiare il “Tipo di piano” di ogni spazio di lavoro in “Collect” per poter ottenere la tariffa Collect.',
-                    benefit1: 'NetSuite, Sage Intacct, QuickBooks Desktop, Oracle, Microsoft Dynamics',
-                    benefit2: 'Workday, Certinia',
-                    benefit3: 'SSO/SAML',
-                    benefit4: 'Regole intelligenti per le spese, diarie, approvazioni multilivello, report personalizzati e budget',
+                    note: 'Per un confronto completo dei nostri piani, consulta la nostra',
+                    pricingPage: 'pagina prezzi',
+                    confirm: 'Sei sicuro di voler eseguire il downgrade e rimuovere le tue configurazioni?',
+                    warning: 'Questa operazione non può essere annullata.',
+                    benefit1: 'Connessioni contabilità (eccetto QuickBooks Online e Xero)',
+                    benefit2: 'Regole spesa intelligenti',
+                    benefit3: 'Flussi di approvazione multilivello',
+                    benefit4: 'Controlli di sicurezza avanzati',
                     headsUp: 'Attenzione!',
                     multiWorkspaceNote:
                         'Dovrai effettuare il downgrade di tutti i tuoi spazi di lavoro prima del primo pagamento mensile per iniziare un abbonamento alla tariffa Collect. Fai clic',
                     selectStep: '> seleziona ogni spazio di lavoro > cambia il tipo di piano in',
-                    benefit1Label: 'Integrazioni ERP',
-                    benefit2Label: 'Integrazioni HR',
-                    benefit3Label: 'Sicurezza',
-                    benefit4Label: 'Avanzate',
-                    important: 'IMPORTANTE:',
                 },
-                noteAndMore: 'e altro:',
             },
             completed: {
                 headline: 'Il tuo spazio di lavoro è stato declassato',
@@ -7091,7 +6295,7 @@ Richiedi dettagli sulle spese come ricevute e descrizioni, imposta limiti e valo
         restrictedAction: {
             restricted: 'Limitato',
             actionsAreCurrentlyRestricted: (workspaceName: string) => `Le azioni nello spazio di lavoro ${workspaceName} sono attualmente limitate`,
-            workspaceOwnerWillNeedToAddOrUpdatePaymentCard: (workspaceOwnerName: string) =>
+            workspaceOwnerWillNeedToAddOrUpdatePaymentCard: ({workspaceOwnerName}: WorkspaceOwnerWillNeedToAddOrUpdatePaymentCardParams) =>
                 `Il/La proprietario/a dello spazio di lavoro, ${workspaceOwnerName}, deve aggiungere o aggiornare la carta di pagamento registrata per sbloccare la nuova attività dello spazio di lavoro.`,
             youWillNeedToAddOrUpdatePaymentCard: 'Dovrai aggiungere o aggiornare la carta di pagamento registrata per sbloccare le nuove attività dello spazio di lavoro.',
             addPaymentCardToUnlock: 'Aggiungi una carta di pagamento per sbloccare!',
@@ -7144,18 +6348,16 @@ Richiedi dettagli sulle spese come ricevute e descrizioni, imposta limiti e valo
                 eReceiptsHint: `Le eReceipt vengono create automaticamente [per la maggior parte delle transazioni con carta in USD](${CONST.DEEP_DIVE_ERECEIPTS}).`,
                 attendeeTracking: 'Monitoraggio partecipanti',
                 attendeeTrackingHint: 'Tieni traccia del costo per persona per ogni spesa.',
-                prohibitedDefaultDescription: 'Contrassegna le ricevute con queste voci di riga per una revisione manuale.',
+                prohibitedDefaultDescription:
+                    'Contrassegna tutte le ricevute in cui compaiono alcolici, gioco d’azzardo o altri articoli soggetti a restrizioni. Le spese con ricevute che includono queste voci richiederanno una revisione manuale.',
                 prohibitedExpenses: 'Spese vietate',
                 alcohol: 'Alcol',
                 hotelIncidentals: 'Spese accessorie dell’hotel',
                 gambling: 'Gioco d’azzardo',
                 tobacco: 'Tabacco',
                 adultEntertainment: 'Intrattenimento per adulti',
-                giftCard: 'Acquisto di carte regalo',
-                handwrittenReceipt: 'Ricevute scritte a mano',
                 requireCompanyCard: 'Richiedi le carte aziendali per tutti gli acquisti',
                 requireCompanyCardDescription: 'Contrassegna tutte le spese in contanti, inclusi chilometraggio e indennità giornaliere.',
-                requireCompanyCardDisabledTooltip: 'Abilita Carte aziendali (in Altre funzionalità) per sbloccare.',
             },
             expenseReportRules: {
                 title: 'Avanzate',
@@ -7164,8 +6366,8 @@ Richiedi dettagli sulle spese come ricevute e descrizioni, imposta limiti e valo
                 preventSelfApprovalsSubtitle: 'Impedisci ai membri dello spazio di lavoro di approvare i propri report spese.',
                 autoApproveCompliantReportsTitle: 'Approva automaticamente i report conformi',
                 autoApproveCompliantReportsSubtitle: 'Configura quali note spese sono idonee per l’approvazione automatica.',
-                autoApproveReportsUnderTitle: 'Approva automaticamente i report con tutte le spese inferiori a',
-                autoApproveReportsUnderDescription: 'Le note spese completamente conformi in cui tutte le spese sono inferiori a questo importo verranno approvate automaticamente.',
+                autoApproveReportsUnderTitle: 'Approva automaticamente i report inferiori a',
+                autoApproveReportsUnderDescription: 'Le note spese completamente conformi inferiori a questo importo verranno approvate automaticamente.',
                 randomReportAuditTitle: 'Revisione casuale dei report',
                 randomReportAuditDescription: 'Richiedi che alcuni report siano approvati manualmente, anche se idonei per l’approvazione automatica.',
                 autoPayApprovedReportsTitle: 'Pagare automaticamente i resoconti approvati',
@@ -7178,11 +6380,6 @@ Richiedi dettagli sulle spese come ricevute e descrizioni, imposta limiti e valo
                 enableFeatureSubtitle: (featureName: string, moreFeaturesLink?: string) =>
                     `Vai su [altre funzionalità](${moreFeaturesLink}) e abilita ${featureName} per sbloccare questa funzione.`,
             },
-            agentsPromoBanner: {
-                title: 'Non vedi la regola che ti serve? Aggiungi un agente',
-                subtitle: 'Aggiungi regole complesse e riduci le approvazioni manuali con agenti personalizzati.',
-                cta: 'Prova ora',
-            },
             merchantRules: {
                 title: 'Esercente',
                 subtitle: 'Imposta le regole per l’esercente in modo che le spese arrivino già codificate correttamente e richiedano meno correzioni.',
@@ -7210,10 +6407,9 @@ Richiedi dettagli sulle spese come ricevute e descrizioni, imposta limiti e valo
                 matchTypeContains: 'Contiene',
                 matchTypeExact: 'Corrisponde esattamente',
                 duplicateRuleTitle: "Una regola simile per l'esercente esiste già",
-                duplicateRulePrompt: (merchantName: string) => `La regola esistente per "${merchantName}" avrà la priorità su questa. Salvare comunque?`,
+                duplicateRulePrompt: (merchantName: string) => `Vuoi salvare una nuova regola per «${merchantName}» anche se ne hai già una esistente?`,
                 saveAnyway: 'Salva comunque',
                 applyToExistingUnsubmittedExpenses: 'Applica alle spese esistenti non inviate',
-                findRule: 'Trova regola esercente',
             },
             categoryRules: {
                 title: 'Regole di categoria',
@@ -7252,131 +6448,12 @@ Richiedi dettagli sulle spese come ricevute e descrizioni, imposta limiti e valo
                     always: 'Richiedi sempre ricevute dettagliate',
                 },
                 defaultTaxRate: 'Aliquota fiscale predefinita',
-                enableWorkflows: (moreFeaturesLink: string) =>
+                enableWorkflows: ({moreFeaturesLink}: RulesEnableWorkflowsParams) =>
                     `Vai su [Altre funzionalità](${moreFeaturesLink}) e abilita i flussi di lavoro, quindi aggiungi le approvazioni per sbloccare questa funzionalità.`,
             },
             customRules: {
                 title: 'Politica di spesa',
                 cardSubtitle: 'Qui trovi il regolamento spese del tuo team, così tutti sono allineati su cosa è coperto.',
-                policyDocument: 'Documento di politica',
-                policyText: 'Testo della politica',
-            },
-            spendRules: {
-                title: 'Spesa',
-                subtitle: 'Approva o rifiuta le transazioni della Carta Expensify in tempo reale.',
-                defaultRuleDescription: 'Tutte le carte',
-                block: 'Blocca',
-                defaultRuleTitle: 'Categorie: servizi per adulti, sportelli bancomat, gioco d’azzardo, trasferimenti di denaro',
-                builtInProtectionModal: {
-                    title: 'Le Carte Expensify offrono sempre una protezione integrata',
-                    description: `Expensify rifiuta sempre questi addebiti:
-
-  • Servizi per adulti
-  • Bancomat
-  • Gioco d’azzardo
-  • Trasferimenti di denaro
-
-Aggiungi altre regole di spesa per proteggere il flusso di cassa aziendale.`,
-                },
-                addSpendRule: 'Aggiungi regola di spesa',
-                cardPageTitle: 'Carta',
-                cardsSectionTitle: 'Carte',
-                chooseCards: 'Scegli le carte',
-                saveRule: 'Salva regola',
-                allow: 'Consenti',
-                spendRuleSectionTitle: 'Regola di spesa',
-                restrictionType: 'Tipo di restrizione',
-                restrictionTypeHelpAllow: 'Le spese vengono approvate se corrispondono a qualsiasi venditore o categoria e non superano un importo massimo.',
-                restrictionTypeHelpBlock: 'Le transazioni vengono rifiutate se corrispondono a un esercente o a una categoria, oppure se superano un importo massimo.',
-                addMerchant: 'Aggiungi esercente',
-                merchantContains: 'Il commerciante contiene',
-                merchantExactlyMatches: 'Il commerciante corrisponde esattamente',
-                noBlockedMerchants: 'Nessun esercente bloccato',
-                addMerchantToBlockSpend: 'Aggiungi un esercente da bloccare',
-                noAllowedMerchants: 'Nessun esercente consentito',
-                addMerchantToAllowSpend: 'Aggiungi un esercente per consentire la spesa',
-                matchType: 'Tipo di corrispondenza',
-                matchTypeContains: 'Contiene',
-                matchTypeExact: 'Corrisponde esattamente',
-                spendCategory: 'Categoria di spesa',
-                maxAmount: 'Importo massimo',
-                maxAmountHelp: 'Qualsiasi addebito superiore a questo importo verrà rifiutato, indipendentemente dalle restrizioni sul commerciante e sulla categoria di spesa.',
-                currencyMismatchTitle: 'Valuta non corrispondente',
-                currencyMismatchPrompt: 'Per impostare un importo massimo, seleziona carte che si regolano nella stessa valuta.',
-                reviewSelectedCards: 'Controlla le carte selezionate',
-                summaryMoreCount: ({summary, count}: {summary: string; count: number}) => (count > 0 ? `${summary}, +${count} altri` : summary),
-                confirmErrorApplyAtLeastOneSpendRuleToOneCard: 'Applica almeno una regola di spesa a una carta',
-                confirmErrorCardRequired: 'Il campo Carta è obbligatorio',
-                confirmErrorApplyAtLeastOneSpendRule: 'Applica almeno una regola di spesa',
-                categories: 'Categorie',
-                merchants: 'Esercenti',
-                noAvailableCards: 'Tutte le carte hanno già una regola',
-                noAvailableCardsSubtitle: 'Modifica una regola carta esistente per apportare modifiche',
-                noCardsIssuedTitle: 'Nessuna Carta Expensify emessa',
-                noCardsIssuedSubtitle: 'Emetti Carte Expensify per creare regole di spesa',
-                max: 'Massimo',
-                categoryOptions: {
-                    [CONST.SPEND_RULES.CATEGORIES.AIRLINES]: 'Compagnie aeree',
-                    [CONST.SPEND_RULES.CATEGORIES.ALCOHOL_AND_BARS]: 'Alcol e bar',
-                    [CONST.SPEND_RULES.CATEGORIES.AMAZON_AND_BOOKSTORES]: 'Amazon e librerie',
-                    [CONST.SPEND_RULES.CATEGORIES.AUTOMOTIVE]: 'Automotive',
-                    [CONST.SPEND_RULES.CATEGORIES.CAR_RENTALS]: 'Noleggio auto',
-                    [CONST.SPEND_RULES.CATEGORIES.DINING]: 'Ristoranti',
-                    [CONST.SPEND_RULES.CATEGORIES.FUEL_AND_GAS]: 'Carburante e gas',
-                    [CONST.SPEND_RULES.CATEGORIES.GOVERNMENT_AND_NON_PROFITS]: 'Pubblica amministrazione e non profit',
-                    [CONST.SPEND_RULES.CATEGORIES.GROCERIES]: 'Spesa supermercato',
-                    [CONST.SPEND_RULES.CATEGORIES.GYMS_AND_FITNESS]: 'Palestre e fitness',
-                    [CONST.SPEND_RULES.CATEGORIES.HEALTHCARE]: 'Sanità',
-                    [CONST.SPEND_RULES.CATEGORIES.HOTELS]: 'Hotel',
-                    [CONST.SPEND_RULES.CATEGORIES.INTERNET_AND_PHONE]: 'Internet e telefono',
-                    [CONST.SPEND_RULES.CATEGORIES.OFFICE_SUPPLIES]: "Materiale d'ufficio",
-                    [CONST.SPEND_RULES.CATEGORIES.PARKING_AND_TOLLS]: 'Parcheggi e pedaggi',
-                    [CONST.SPEND_RULES.CATEGORIES.PROFESSIONAL_SERVICES]: 'Servizi professionali',
-                    [CONST.SPEND_RULES.CATEGORIES.RETAIL]: 'Vendita al dettaglio',
-                    [CONST.SPEND_RULES.CATEGORIES.SHIPPING_AND_DELIVERY]: 'Spedizione e consegna',
-                    [CONST.SPEND_RULES.CATEGORIES.SOFTWARE]: 'Software',
-                    [CONST.SPEND_RULES.CATEGORIES.TRANSIT_AND_RIDESHARE]: 'Trasporti e ride sharing',
-                    [CONST.SPEND_RULES.CATEGORIES.TRAVEL_AGENCIES]: 'Agenzie di viaggio',
-                },
-                editRuleTitle: 'Modifica regola',
-                deleteRule: 'Elimina regola',
-                deleteRuleConfirmation: 'Sei sicuro di voler eliminare questa regola?',
-                summaryMerchants: ({
-                    merchants,
-                    hiddenCount,
-                    shownCount,
-                    action,
-                }: {
-                    merchants: string;
-                    hiddenCount: number;
-                    shownCount: number;
-                    action: ValueOf<typeof CONST.SPEND_RULES.ACTION>;
-                }) =>
-                    `${action === CONST.SPEND_RULES.ACTION.BLOCK ? 'Bloccato' : 'Consentito'} ${shownCount > 1 ? 'esercenti' : 'esercente'}: ${merchants}${hiddenCount > 0 ? `, +${hiddenCount} in più` : ''}`,
-                summaryCategories: ({
-                    categories,
-                    hiddenCount,
-                    shownCount,
-                    action,
-                }: {
-                    categories: string;
-                    hiddenCount: number;
-                    shownCount: number;
-                    action: ValueOf<typeof CONST.SPEND_RULES.ACTION>;
-                }) =>
-                    `${action === CONST.SPEND_RULES.ACTION.BLOCK ? 'Bloccato' : 'Consentito'} ${shownCount > 1 ? 'categorie' : 'categoria'}: ${categories}${hiddenCount > 0 ? `, +${hiddenCount} in più` : ''}`,
-            },
-            aiRules: {
-                title: 'Regole IA',
-                subtitle: 'Descrivi regole flessibili che vengono eseguite quando ne hai bisogno',
-                addRule: 'Aggiungi regola IA',
-                findRule: 'Trova regola IA',
-                addRuleTitle: 'Aggiungi regola',
-                editRuleTitle: 'Modifica regola',
-                deleteRule: 'Elimina regola',
-                deleteRuleConfirmation: 'Sei sicuro di voler eliminare questa regola?',
-                describeRuleTitle: 'Descrivi la tua regola',
-                describeRuleSubtitle: 'Descrivi la tua regola e Concierge la creerà',
             },
         },
         planTypePage: {
@@ -7389,105 +6466,15 @@ Aggiungi altre regole di spesa per proteggere il flusso di cassa aziendale.`,
                     label: 'Controllo',
                     description: 'Per le organizzazioni con requisiti avanzati.',
                 },
-                submit2026: {
-                    label: 'Invia',
-                    description: 'Per i dipendenti che desiderano inviare le spese al proprio datore di lavoro.',
-                },
             },
-            description: 'Scegli il piano più adatto a te.',
-            subscriptionLink: 'Scopri di più',
+            description: 'Scegli il piano più adatto a te. Per un elenco dettagliato di funzionalità e prezzi, consulta la nostra',
+            subscriptionLink: 'pagina di aiuto su tipi di piano e prezzi',
             lockedPlanDescription: ({count, annualSubscriptionEndDate}: WorkspaceLockedPlanTypeParams) => ({
                 one: `Ti sei impegnato per 1 membro attivo nel piano Control fino al termine dell’abbonamento annuale, il ${annualSubscriptionEndDate}. Puoi passare all’abbonamento a consumo e effettuare il downgrade al piano Collect a partire dal ${annualSubscriptionEndDate} disattivando il rinnovo automatico in`,
                 other: `Ti sei impegnato per ${count} membri attivi nel piano Control fino alla fine dell’abbonamento annuale, il ${annualSubscriptionEndDate}. Puoi passare all’abbonamento a consumo e effettuare il downgrade al piano Collect a partire dal ${annualSubscriptionEndDate} disattivando il rinnovo automatico in`,
             }),
             subscriptions: 'Abbonamenti',
         },
-        hr: {
-            title: 'Risorse umane',
-            connections: 'Connessioni',
-            connectionsSubtitle:
-                'Collega il tuo sistema HR per sincronizzare i dati dei dipendenti, abbinare automaticamente i rimborsi alle persone giuste e mantenere le spese del tuo team accurate senza lavoro manuale.',
-            subtitle: 'Collega gli strumenti HR e mantieni sincronizzate le approvazioni dei dipendenti.',
-            connect: 'Connetti',
-            syncNow: 'Sincronizza ora',
-            disconnect: 'Disconnetti',
-            disconnectTitle: (providerName: string) => `Disconnetti ${providerName}`,
-            disconnectPrompt: (providerName: string) => `Sei sicuro di voler disconnettere ${providerName}?`,
-            alreadyConnectedTitle: 'Impossibile connettersi a più piattaforme HR',
-            alreadyConnectedPrompt: 'Devi disconnettere la tua attuale piattaforma HR prima di collegarne un’altra.',
-            lastSync: (relativeDate: string) => `Ultima sincronizzazione ${relativeDate}`,
-            syncError: (providerName: string) => `Impossibile connettersi a ${providerName}`,
-            connectionDescription: (providerName: string) => `Collega ${providerName} per mantenere sincronizzate le approvazioni dei dipendenti con il tuo spazio di lavoro.`,
-            approvalMode: 'Modalità di approvazione',
-            providerApprovalMode: (providerName: string) => `Modalità di approvazione ${providerName}`,
-            finalApprover: 'Approvatore finale',
-            providerFinalApprover: (providerName: string) => `Approvatore finale ${providerName}`,
-            notSet: 'Non impostato',
-            approvalModeDescription: (providerName: string) => `I membri e i responsabili sono configurati per la sincronizzazione con ${providerName}.`,
-            approvalModeWarningTitle: 'Cambiare modalità di approvazione?',
-            approvalModeWarningPrompt: (providerName: string, helpSiteURL: string) =>
-                `Sei sicuro di voler cambiare la modalità di approvazione per questo spazio di lavoro? Scopri di più sulle diverse modalità di flusso di lavoro abilitate per ${providerName} nel nostro <a href="${helpSiteURL}">sito di assistenza</a>.`,
-            approvalModeWarningConfirm: 'Cambia modalità di approvazione',
-            approvalModes: {
-                basic: {label: 'Approvazione di base', description: 'Tutti gli utenti inviano a una singola persona per l’elaborazione e l’approvazione.'},
-                manager: {
-                    label: 'Approvazione del responsabile',
-                    description: (providerName: string) => `I dipendenti inviano i report al proprio responsabile diretto configurato in ${providerName}.`,
-                },
-                custom: {label: 'Approvazione personalizzata', description: 'Imposterò manualmente i flussi di approvazione in Expensify.'},
-            },
-            syncStageName: ({stage}: SyncStageNameConnectionsParams) => {
-                switch (stage) {
-                    case 'gustoSyncTitle':
-                        return 'Sincronizzazione dei dipendenti Gusto';
-                    case 'gustoSyncLoadData':
-                        return 'Caricamento dei dati da Gusto';
-                    case 'gustoSyncProvisioning':
-                        return 'Provisioning dei dipendenti nella policy';
-                    case 'zenefitsSyncTitle':
-                        return 'Sincronizzazione dipendenti TriNet';
-                    case 'zenefitsSyncLoadData':
-                        return 'Caricamento dei dati da TriNet';
-                    case 'zenefitsSyncProvisioning':
-                        return 'Provisioning dei dipendenti nella policy';
-                    case 'jobDone':
-                        return 'In attesa del caricamento dei dati importati';
-                    default: {
-                        return `Traduzione mancante per la fase: ${stage}`;
-                    }
-                }
-            },
-            syncResults: {
-                title: (provider: string) => `Sincronizzazione ${provider} completata`,
-                successTitle: (provider: string) => `Connessione ${provider} sincronizzata correttamente!`,
-                added: 'Aggiunto',
-                removed: 'Rimosso',
-                skipped: 'Saltato',
-                employeeCount: () => ({
-                    one: '1 dipendente',
-                    other: (count: number) => `${count} dipendenti`,
-                }),
-            },
-            gusto: {
-                title: 'Gusto',
-            },
-            zenefits: {
-                title: 'TriNet',
-            },
-            syncingModalTitle: 'La tua connessione è in sincronizzazione',
-            syncingModalDescription: "La prima connessione può richiedere un po' di tempo. Ti verrà notificato qualsiasi errore.",
-            syncing: 'Sincronizzazione dipendenti',
-            mergeHR: {
-                completeSetup: 'Completa configurazione',
-                setupIncomplete: (setupLink: string | undefined) =>
-                    `<muted-text-label>Connesso. ${setupLink ? `<a href="${setupLink}">Completa la configurazione</a>` : 'Completa configurazione'} per importare i dipendenti.</muted-text-label>`,
-                groups: {title: 'Gruppi', description: 'Scegli i gruppi di dipendenti che vuoi sincronizzare con questo spazio di lavoro'},
-            },
-        },
-        emptyDomain: {
-            title: 'Migliora la tua sicurezza con i domini',
-            subtitle: 'Richiedi ai membri del tuo dominio di accedere tramite accesso Single Sign-On, limita la creazione di space di lavoro e altro ancora.',
-        },
     },
     getAssistancePage: {
         title: 'Ottieni assistenza',
@@ -7515,7 +6502,6 @@ Aggiungi altre regole di spesa per proteggere il flusso di cassa aziendale.`,
             symbols: 'Simboli',
             flags: 'Segnalazioni',
         },
-        emojiNotSelected: 'Emoji non selezionata',
     },
     newRoomPage: {
         newRoom: 'Nuova stanza',
@@ -7528,7 +6514,7 @@ Aggiungi altre regole di spesa per proteggere il flusso di cassa aziendale.`,
         public_announceDescription: 'Chiunque può trovare questa stanza',
         createRoom: 'Crea stanza',
         roomAlreadyExistsError: 'Esiste già una stanza con questo nome',
-        roomNameReservedError: (reservedName: string) => `${reservedName} è una stanza predefinita in tutti gli spazi di lavoro. Scegli un altro nome.`,
+        roomNameReservedError: ({reservedName}: RoomNameReservedErrorParams) => `${reservedName} è una stanza predefinita in tutti gli spazi di lavoro. Scegli un altro nome.`,
         roomNameInvalidError: 'I nomi delle stanze possono includere solo lettere minuscole, numeri e trattini',
         pleaseEnterRoomName: 'Inserisci un nome per la stanza',
         pleaseSelectWorkspace: 'Seleziona uno spazio di lavoro',
@@ -7536,7 +6522,7 @@ Aggiungi altre regole di spesa per proteggere il flusso di cassa aziendale.`,
             const actor = actorName ? `${actorName} ` : '';
             return isExpenseReport ? `${actor}rinominato in "${newName}" (in precedenza "${oldName}")` : `${actor} ha rinominato questa stanza in «${newName}» (in precedenza «${oldName}»)`;
         },
-        roomRenamedTo: (newName: string) => `Stanza rinominata in ${newName}`,
+        roomRenamedTo: ({newName}: RoomRenamedToParams) => `Stanza rinominata in ${newName}`,
         social: 'sociale',
         selectAWorkspace: 'Seleziona uno spazio di lavoro',
         growlMessageOnRenameError: 'Impossibile rinominare la stanza dello spazio di lavoro. Controlla la connessione e riprova.',
@@ -7578,14 +6564,14 @@ Aggiungi altre regole di spesa per proteggere il flusso di cassa aziendale.`,
             `ha aggiunto ${approverName} (${approverEmail}) come approvatore per il campo ${field} «${name}»`,
         deleteApprovalRule: (approverEmail: string, approverName: string, field: string, name: string) =>
             `ha rimosso ${approverName} (${approverEmail}) come approvatore per il campo ${field} "${name}"`,
-        updateApprovalRule: (field: string, name: string, newApproverEmail: string, newApproverName: string | undefined, oldApproverEmail: string, oldApproverName: string | undefined) => {
+        updateApprovalRule: ({field, name, newApproverEmail, newApproverName, oldApproverEmail, oldApproverName}: UpdatedPolicyApprovalRuleParams) => {
             const formatApprover = (displayName?: string, email?: string) => (displayName ? `${displayName} (${email})` : email);
             return `ha modificato l’approvatore per il campo ${field} «${name}» in ${formatApprover(newApproverName, newApproverEmail)} (in precedenza ${formatApprover(oldApproverName, oldApproverEmail)})`;
         },
-        addCategory: (categoryName: string) => `ha aggiunto la categoria "${categoryName}"`,
-        deleteCategory: (categoryName: string) => `ha rimosso la categoria "${categoryName}"`,
-        updateCategory: (categoryName: string, oldValue: boolean) => `${oldValue ? 'disattivato' : 'abilitato'} la categoria "${categoryName}"`,
-        updateCategoryPayrollCode: (categoryName: string, newValue?: string, oldValue?: string) => {
+        addCategory: ({categoryName}: UpdatedPolicyCategoryParams) => `ha aggiunto la categoria "${categoryName}"`,
+        deleteCategory: ({categoryName}: UpdatedPolicyCategoryParams) => `ha rimosso la categoria "${categoryName}"`,
+        updateCategory: ({oldValue, categoryName}: UpdatedPolicyCategoryParams) => `${oldValue ? 'disattivato' : 'abilitato'} la categoria "${categoryName}"`,
+        updateCategoryPayrollCode: ({oldValue, categoryName, newValue}: UpdatedPolicyCategoryGLCodeParams) => {
             if (!oldValue) {
                 return `ha aggiunto il codice paghe "${newValue}" alla categoria "${categoryName}"`;
             }
@@ -7594,7 +6580,7 @@ Aggiungi altre regole di spesa per proteggere il flusso di cassa aziendale.`,
             }
             return `ha modificato il codice paghe della categoria "${categoryName}" in “${newValue}” (precedentemente “${oldValue}”)`;
         },
-        updateCategoryGLCode: (categoryName: string, newValue?: string, oldValue?: string) => {
+        updateCategoryGLCode: ({oldValue, categoryName, newValue}: UpdatedPolicyCategoryGLCodeParams) => {
             if (!oldValue) {
                 return `ha aggiunto il codice GL "${newValue}" alla categoria "${categoryName}"`;
             }
@@ -7603,10 +6589,10 @@ Aggiungi altre regole di spesa per proteggere il flusso di cassa aziendale.`,
             }
             return `ha modificato il codice GL della categoria “${categoryName}” in “${newValue}” (in precedenza “${oldValue}”)`;
         },
-        updateAreCommentsRequired: (categoryName: string, oldValue: boolean) => {
+        updateAreCommentsRequired: ({oldValue, categoryName}: UpdatedPolicyCategoryParams) => {
             return `ha modificato la descrizione della categoria "${categoryName}" in ${!oldValue ? 'obbligatorio' : 'non obbligatorio'} (in precedenza ${!oldValue ? 'non obbligatorio' : 'obbligatorio'})`;
         },
-        updateCategoryMaxExpenseAmount: (categoryName: string, newAmount?: string, oldAmount?: string) => {
+        updateCategoryMaxExpenseAmount: ({categoryName, oldAmount, newAmount}: UpdatedPolicyCategoryMaxExpenseAmountParams) => {
             if (newAmount && !oldAmount) {
                 return `ha aggiunto un importo massimo di ${newAmount} alla categoria "${categoryName}"`;
             }
@@ -7615,26 +6601,26 @@ Aggiungi altre regole di spesa per proteggere il flusso di cassa aziendale.`,
             }
             return `ha modificato l’importo massimo della categoria "${categoryName}" in ${newAmount} (precedentemente ${oldAmount})`;
         },
-        updateCategoryExpenseLimitType: (categoryName: string, newValue: string, oldValue?: string) => {
+        updateCategoryExpenseLimitType: ({categoryName, oldValue, newValue}: UpdatedPolicyCategoryExpenseLimitTypeParams) => {
             if (!oldValue) {
                 return `ha aggiunto un tipo di limite di ${newValue} alla categoria "${categoryName}"`;
             }
             return `ha modificato il tipo di limite della categoria "${categoryName}" in ${newValue} (precedentemente ${oldValue})`;
         },
-        updateCategoryMaxAmountNoReceipt: (categoryName: string, newValue: string, oldValue?: string) => {
+        updateCategoryMaxAmountNoReceipt: ({categoryName, oldValue, newValue}: UpdatedPolicyCategoryMaxAmountNoReceiptParams) => {
             if (!oldValue) {
                 return `ha aggiornato la categoria "${categoryName}" modificando Ricevute in ${newValue}`;
             }
             return `ha modificato la categoria "${categoryName}" in ${newValue} (precedentemente ${oldValue})`;
         },
-        updateCategoryMaxAmountNoItemizedReceipt: (categoryName: string, oldValue: string | undefined, newValue: string) => {
+        updateCategoryMaxAmountNoItemizedReceipt: ({categoryName, oldValue, newValue}: UpdatedPolicyCategoryMaxAmountNoReceiptParams) => {
             if (!oldValue) {
                 return `ha aggiornato la categoria "${categoryName}" modificando Ricevute dettagliate in ${newValue}`;
             }
             return `ha modificato le ricevute con voce di dettaglio della categoria "${categoryName}" in ${newValue} (in precedenza ${oldValue})`;
         },
-        setCategoryName: (oldName: string, newName: string) => `ha rinominato la categoria "${oldName}" in "${newName}"`,
-        updatedDescriptionHint: (categoryName: string, newValue?: string, oldValue?: string) => {
+        setCategoryName: ({oldName, newName}: UpdatedPolicyCategoryNameParams) => `ha rinominato la categoria "${oldName}" in "${newName}"`,
+        updatedDescriptionHint: ({categoryName, oldValue, newValue}: UpdatedPolicyCategoryDescriptionHintTypeParams) => {
             if (!newValue) {
                 return `ha rimosso il suggerimento di descrizione "${oldValue}" dalla categoria "${categoryName}"`;
             }
@@ -7642,42 +6628,43 @@ Aggiungi altre regole di spesa per proteggere il flusso di cassa aziendale.`,
                 ? `ha aggiunto il suggerimento di descrizione "${newValue}" alla categoria "${categoryName}"`
                 : `ha modificato il suggerimento della descrizione della categoria "${categoryName}" in “${newValue}” (in precedenza “${oldValue}”)`;
         },
-        updateTagListName: (oldName: string, newName: string) => `ha modificato il nome dell’elenco di tag in "${newName}" (in precedenza "${oldName}")`,
-        addTag: (tagListName: string, tagName?: string) => `ha aggiunto l’etichetta "${tagName}" all’elenco "${tagListName}"`,
-        updateTagName: (tagListName: string, newName: string, oldName: string) => `ha aggiornato l'elenco dei tag "${tagListName}" cambiando il tag "${oldName}" in "${newName}"`,
-        updateTagEnabled: (tagListName: string, tagName?: string, enabled?: boolean) => `${enabled ? 'abilitato' : 'disabilitato'} il tag "${tagName}" nella lista "${tagListName}"`,
-        deleteTag: (tagListName: string, tagName?: string) => `ha rimosso il tag "${tagName}" dall'elenco "${tagListName}"`,
-        deleteMultipleTags: (count?: string, tagListName?: string) => `rimosse le etichette "${count}" dall’elenco "${tagListName}"`,
-        updateTag: (tagListName: string, newValue: string, tagName: string, updatedField: string, oldValue?: string) => {
+        updateTagListName: ({oldName, newName}: UpdatedPolicyCategoryNameParams) => `ha modificato il nome dell’elenco di tag in "${newName}" (in precedenza "${oldName}")`,
+        addTag: ({tagListName, tagName}: UpdatedPolicyTagParams) => `ha aggiunto l’etichetta "${tagName}" all’elenco "${tagListName}"`,
+        updateTagName: ({tagListName, newName, oldName}: UpdatedPolicyTagNameParams) => `ha aggiornato l'elenco dei tag "${tagListName}" cambiando il tag "${oldName}" in "${newName}"`,
+        updateTagEnabled: ({tagListName, tagName, enabled}: UpdatedPolicyTagParams) => `${enabled ? 'abilitato' : 'disabilitato'} il tag "${tagName}" nella lista "${tagListName}"`,
+        deleteTag: ({tagListName, tagName}: UpdatedPolicyTagParams) => `ha rimosso il tag "${tagName}" dall'elenco "${tagListName}"`,
+        deleteMultipleTags: ({count, tagListName}: UpdatedPolicyTagParams) => `rimosse le etichette "${count}" dall’elenco "${tagListName}"`,
+        updateTag: ({tagListName, newValue, tagName, updatedField, oldValue}: UpdatedPolicyTagFieldParams) => {
             if (oldValue) {
                 return `ha aggiornato l’etichetta "${tagName}" nell’elenco "${tagListName}" cambiando ${updatedField} in "${newValue}" (precedentemente "${oldValue}")`;
             }
             return `ha aggiornato il tag "${tagName}" nell'elenco "${tagListName}" aggiungendo un ${updatedField} di "${newValue}"`;
         },
-        updateCustomUnit: (customUnitName: string, newValue: string, oldValue: string, updatedField: string) =>
+        updateCustomUnit: ({customUnitName, newValue, oldValue, updatedField}: UpdatePolicyCustomUnitParams) =>
             `ha modificato ${customUnitName} ${updatedField} in "${newValue}" (precedentemente "${oldValue}")`,
-        updateCustomUnitTaxEnabled: (newValue: boolean) => `${newValue ? 'abilitato' : 'disabilitato'} monitoraggio delle tasse sulle tariffe chilometriche`,
-        addCustomUnitRate: (customUnitName: string, rateName: string) => `ha aggiunto la tariffa ${customUnitName} "${rateName}"`,
-        updatedCustomUnitRate: (customUnitName: string, customUnitRateName: string, updatedField: string, newValue: string, oldValue: string) =>
+        updateCustomUnitTaxEnabled: ({newValue}: UpdatePolicyCustomUnitTaxEnabledParams) => `${newValue ? 'abilitato' : 'disabilitato'} monitoraggio delle tasse sulle tariffe chilometriche`,
+        addCustomUnitRate: ({customUnitName, rateName}: AddOrDeletePolicyCustomUnitRateParams) => `ha aggiunto una nuova tariffa ${customUnitName} "${rateName}"`,
+        updatedCustomUnitRate: ({customUnitName, customUnitRateName, newValue, oldValue, updatedField}: UpdatedPolicyCustomUnitRateParams) =>
             `ha modificato il valore di ${customUnitName} ${updatedField} "${customUnitRateName}" in "${newValue}" (in precedenza "${oldValue}")`,
-        updatedCustomUnitTaxRateExternalID: (customUnitRateName: string, newValue: string, newTaxPercentage: string, oldTaxPercentage?: string, oldValue?: string) => {
+        updatedCustomUnitTaxRateExternalID: ({customUnitRateName, newValue, newTaxPercentage, oldTaxPercentage, oldValue}: UpdatedPolicyCustomUnitTaxRateExternalIDParams) => {
             if (oldTaxPercentage && oldValue) {
                 return `ha modificato l’aliquota fiscale sulla tariffa distanza "${customUnitRateName}" in "${newValue} (${newTaxPercentage})" (precedentemente "${oldValue} (${oldTaxPercentage})")`;
             }
             return `ha aggiunto l’aliquota fiscale "${newValue} (${newTaxPercentage})" alla tariffa distanza "${customUnitRateName}"`;
         },
-        updatedCustomUnitTaxClaimablePercentage: (customUnitRateName: string, newValue: number, oldValue?: number) => {
+        updatedCustomUnitTaxClaimablePercentage: ({customUnitRateName, newValue, oldValue}: UpdatedPolicyCustomUnitTaxClaimablePercentageParams) => {
             if (oldValue) {
                 return `ha modificato la parte di imposta recuperabile sulla tariffa distanza "${customUnitRateName}" a "${newValue}" (in precedenza "${oldValue}")`;
             }
             return `ha aggiunto una parte di imposta rimborsabile di "${newValue}" alla tariffa distanza "${customUnitRateName}"`;
         },
-        updatedCustomUnitRateName: (customUnitName: string, oldValue: string, newValue: string) => `ha rinominato la tariffa ${customUnitName} da "${oldValue}" a "${newValue}"`,
-        updatedCustomUnitRateEnabled: (customUnitName: string, customUnitRateName: string, newValue: boolean) => {
+        updatedCustomUnitRateEnabled: ({customUnitName, customUnitRateName, newValue}: UpdatedPolicyCustomUnitRateEnabledParams) => {
             return `${newValue ? 'abilitato' : 'disattivato'} la tariffa ${customUnitName} "${customUnitRateName}"`;
         },
-        deleteCustomUnitRate: (customUnitName: string, rateName: string) => `ha rimosso la tariffa "${rateName}" per l'unità personalizzata "${customUnitName}"`,
-        updateReportFieldDefaultValue: (defaultValue?: string, fieldName?: string) => `imposta il valore predefinito del campo report "${fieldName}" su "${defaultValue}"`,
+        deleteCustomUnitRate: ({customUnitName, rateName}: AddOrDeletePolicyCustomUnitRateParams) => `ha rimosso la tariffa "${rateName}" per l'unità personalizzata "${customUnitName}"`,
+        addedReportField: ({fieldType, fieldName}: AddedOrDeletedPolicyReportFieldParams) => `aggiunto il campo di report ${fieldType} "${fieldName}"`,
+        updateReportFieldDefaultValue: ({defaultValue, fieldName}: UpdatedPolicyReportFieldDefaultValueParams) =>
+            `imposta il valore predefinito del campo report "${fieldName}" su "${defaultValue}"`,
         addedReportFieldOption: (fieldName: string, optionName: string) => `ha aggiunto l’opzione «${optionName}» al campo del rendiconto «${fieldName}»`,
         removedReportFieldOption: (fieldName: string, optionName: string) => `ha rimosso l’opzione «${optionName}» dal campo del report «${fieldName}»`,
         updateReportFieldOptionDisabled: (fieldName: string, optionName: string, optionEnabled: boolean) =>
@@ -7689,20 +6676,23 @@ Aggiungi altre regole di spesa per proteggere il flusso di cassa aziendale.`,
             return `${allEnabled ? 'abilitato' : 'disattivato'} l’opzione “${optionName}” per il campo del report “${fieldName}”, rendendo tutte le opzioni ${allEnabled ? 'abilitato' : 'disattivato'}`;
         },
         deleteReportField: ({fieldType, fieldName}: {fieldType: string; fieldName?: string}) => `ha rimosso il campo del report ${fieldType} "${fieldName}"`,
-        preventSelfApproval: (oldValue: string, newValue: string) =>
+        preventSelfApproval: ({oldValue, newValue}: UpdatedPolicyPreventSelfApprovalParams) =>
             `aggiornato "Impedisci auto-approvazione" a "${newValue === 'true' ? 'Abilitato' : 'Disattivato'}" (precedentemente "${oldValue === 'true' ? 'Abilitato' : 'Disattivato'}")`,
-        updateMonthlyOffset: (oldValue: string, newValue: string) => {
+        updateMonthlyOffset: ({oldValue, newValue}: UpdatedPolicyFieldWithNewAndOldValueParams) => {
             if (!oldValue) {
                 return `imposta la data di invio del report mensile su "${newValue}"`;
             }
             return `ha aggiornato la data di invio del report mensile a "${newValue}" (in precedenza "${oldValue}")`;
         },
-        updateDefaultBillable: (oldValue: string, newValue: string) => `aggiornato "Ribillare le spese ai clienti" a "${newValue}" (precedentemente "${oldValue}")`,
-        updateDefaultReimbursable: (oldValue: string, newValue: string) => `aggiornato "Impostazione predefinita spese in contanti" a "${newValue}" (in precedenza "${oldValue}")`,
-        updateDefaultTitleEnforced: (value: boolean) => `ha attivato "Applica i titoli predefiniti dei report" ${value ? 'attivo' : 'disattivato'}`,
-        changedCustomReportNameFormula: (oldValue: string, newValue: string) => `ha modificato la formula del nome del report personalizzato in "${newValue}" (in precedenza "${oldValue}")`,
+        updateDefaultBillable: ({oldValue, newValue}: UpdatedPolicyFieldWithNewAndOldValueParams) =>
+            `aggiornato "Ribillare le spese ai clienti" a "${newValue}" (precedentemente "${oldValue}")`,
+        updateDefaultReimbursable: ({oldValue, newValue}: UpdatedPolicyFieldWithNewAndOldValueParams) =>
+            `aggiornato "Impostazione predefinita spese in contanti" a "${newValue}" (in precedenza "${oldValue}")`,
+        updateDefaultTitleEnforced: ({value}: UpdatedPolicyFieldWithValueParams) => `ha attivato "Applica i titoli predefiniti dei report" ${value ? 'attivo' : 'disattivato'}`,
+        changedCustomReportNameFormula: ({newValue, oldValue}: UpdatedPolicyFieldWithNewAndOldValueParams) =>
+            `ha modificato la formula del nome del report personalizzato in "${newValue}" (in precedenza "${oldValue}")`,
         renamedWorkspaceNameAction: (oldName: string, newName: string) => `ha aggiornato il nome di questo spazio di lavoro in "${newName}" (in precedenza "${oldName}")`,
-        updateWorkspaceDescription: (newDescription: string, oldDescription: string) =>
+        updateWorkspaceDescription: ({newDescription, oldDescription}: UpdatedPolicyDescriptionParams) =>
             !oldDescription
                 ? `imposta la descrizione di questo spazio di lavoro su "${newDescription}"`
                 : `ha aggiornato la descrizione di questo spazio di lavoro in "${newDescription}" (in precedenza "${oldDescription}")`,
@@ -7722,47 +6712,45 @@ Aggiungi altre regole di spesa per proteggere il flusso di cassa aziendale.`,
         },
         demotedFromWorkspace: (policyName: string, oldRole: string) =>
             `ha aggiornato il tuo ruolo in ${policyName} da ${oldRole} a utente. Sei stato rimosso da tutte le chat delle note spese dei richiedenti, tranne che dalla tua.`,
-        updatedWorkspaceCurrencyAction: (oldCurrency: string, newCurrency: string) => `ha aggiornato la valuta predefinita in ${newCurrency} (precedentemente ${oldCurrency})`,
-        updatedWorkspaceFrequencyAction: (oldFrequency: string, newFrequency: string) =>
+        updatedWorkspaceCurrencyAction: ({oldCurrency, newCurrency}: UpdatedPolicyCurrencyParams) => `ha aggiornato la valuta predefinita in ${newCurrency} (precedentemente ${oldCurrency})`,
+        updatedWorkspaceFrequencyAction: ({oldFrequency, newFrequency}: UpdatedPolicyFrequencyParams) =>
             `ha aggiornato la frequenza di creazione automatica dei report a "${newFrequency}" (in precedenza "${oldFrequency}")`,
         updateApprovalMode: ({newValue, oldValue}: ChangeFieldParams) => `ha aggiornato la modalità di approvazione in "${newValue}" (in precedenza "${oldValue}")`,
         upgradedWorkspace: 'ha aggiornato questo spazio di lavoro al piano Control',
         forcedCorporateUpgrade: `Questo spazio di lavoro è stato aggiornato al piano Control. Fai clic <a href="${CONST.COLLECT_UPGRADE_HELP_URL}">qui</a> per maggiori informazioni.`,
         downgradedWorkspace: 'ha effettuato il downgrade di questo spazio di lavoro al piano Collect',
-        updatedAuditRate: (oldAuditRate: number, newAuditRate: number) =>
+        updatedAuditRate: ({oldAuditRate, newAuditRate}: UpdatedPolicyAuditRateParams) =>
             `ha modificato la percentuale di report indirizzati casualmente per l’approvazione manuale a ${Math.round(newAuditRate * 100)}% (in precedenza ${Math.round(oldAuditRate * 100)}%)`,
-        updatedManualApprovalThreshold: (oldLimit: string, newLimit: string) =>
+        updatedManualApprovalThreshold: ({oldLimit, newLimit}: UpdatedPolicyManualApprovalThresholdParams) =>
             `ha modificato il limite di approvazione manuale per tutte le spese a ${newLimit} (in precedenza ${oldLimit})`,
         updatedFeatureEnabled: ({enabled, featureName}: {enabled: boolean; featureName: string}) => {
             switch (featureName) {
                 case 'categories':
-                    return `${enabled ? 'attivato' : 'disattivato'} categorie`;
+                    return `${enabled ? 'abilitato' : 'disattivato'} categorie`;
                 case 'tags':
-                    return `tag ${enabled ? 'attivato' : 'disattivato'}`;
+                    return `tag ${enabled ? 'abilitato' : 'disattivato'}`;
                 case 'workflows':
-                    return `Flussi di lavoro ${enabled ? 'attivato' : 'disattivato'}`;
+                    return `Workflow ${enabled ? 'abilitato' : 'disattivato'}`;
                 case 'distance rates':
-                    return `tariffe distanza ${enabled ? 'attivato' : 'disattivato'}`;
+                    return `Tariffe chilometriche ${enabled ? 'abilitato' : 'disattivato'}`;
                 case 'accounting':
-                    return `${enabled ? 'attivato' : 'disattivato'} contabilità`;
+                    return `Contabilità ${enabled ? 'abilitato' : 'disattivato'}`;
                 case 'Expensify Cards':
-                    return `${enabled ? 'attivato' : 'disattivato'} Carte Expensify`;
-                case 'travel invoicing':
-                    return `fatturazione viaggi ${enabled ? 'attivato' : 'disattivato'}`;
+                    return `${enabled ? 'abilitato' : 'disattivato'} Carte Expensify`;
                 case 'company cards':
-                    return `${enabled ? 'attivato' : 'disattivato'} carte aziendali`;
+                    return `${enabled ? 'abilitato' : 'disattivato'} carte aziendali`;
                 case 'invoicing':
-                    return `fatturazione ${enabled ? 'attivato' : 'disattivato'}`;
+                    return `Fatturazione ${enabled ? 'abilitato' : 'disattivato'}`;
                 case 'per diem':
-                    return `${enabled ? 'attivato' : 'disattivato'} diaria`;
+                    return `${enabled ? 'abilitato' : 'disattivato'} diaria`;
                 case 'receipt partners':
-                    return `partner ricevute ${enabled ? 'attivato' : 'disattivato'}`;
+                    return `partner di ricevute ${enabled ? 'abilitato' : 'disattivato'}`;
                 case 'rules':
-                    return `${enabled ? 'attivato' : 'disattivato'} regole`;
+                    return `${enabled ? 'abilitato' : 'disattivato'} regole`;
                 case 'tax tracking':
-                    return `${enabled ? 'attivato' : 'disattivato'} monitoraggio delle imposte`;
+                    return `monitoraggio fiscale ${enabled ? 'abilitato' : 'disattivato'}`;
                 default:
-                    return `${enabled ? 'attivato' : 'disattivato'} ${featureName}`;
+                    return `${enabled ? 'abilitato' : 'disattivato'} ${featureName}`;
             }
         },
         updatedAttendeeTracking: ({enabled}: {enabled: boolean}) => `tracciamento partecipanti ${enabled ? 'abilitato' : 'disattivato'}`,
@@ -7831,18 +6819,14 @@ Aggiungi altre regole di spesa per proteggere il flusso di cassa aziendale.`,
             oldValue
                 ? `ha modificato il sito web dell’azienda in fattura in "${newValue}" (precedentemente "${oldValue}")`
                 : `imposta il sito web dell’azienda della fattura su "${newValue}"`,
-        changedReimburser: (newReimburser: string, previousReimburser?: string) =>
+        changedReimburser: ({newReimburser, previousReimburser}: UpdatedPolicyReimburserParams) =>
             previousReimburser
                 ? `ha modificato il pagatore autorizzato in "${newReimburser}" (in precedenza "${previousReimburser}")`
                 : `ha modificato il pagatore autorizzato in "${newReimburser}"`,
-        updateReimbursementEnabled: (enabled: boolean) => `Rimborsi ${enabled ? 'abilitato' : 'disattivato'}`,
-        updateCustomTaxName: (oldName: string, newName: string) => `ha cambiato il nome dell'imposta personalizzata in "${newName}" (precedentemente "${oldName}")`,
-        updateCurrencyDefaultTax: (oldName: string, newName: string) =>
-            `ha modificato l'aliquota fiscale predefinita della valuta dello spazio di lavoro in "${newName}" (in precedenza "${oldName}")`,
-        updateForeignCurrencyDefaultTax: (oldName: string, newName: string) => `ha modificato l'aliquota fiscale predefinita per valuta estera in "${newName}" (in precedenza "${oldName}")`,
-        addTax: (taxName: string) => `ha aggiunto l’imposta “${taxName}”`,
-        deleteTax: (taxName: string) => `ha rimosso l'imposta "${taxName}"`,
-        updateTax: (oldValue?: string | boolean | number, taxName?: string, updatedField?: string, newValue?: string | boolean | number) => {
+        updateReimbursementEnabled: ({enabled}: UpdatedPolicyReimbursementEnabledParams) => `Rimborsi ${enabled ? 'abilitato' : 'disattivato'}`,
+        addTax: ({taxName}: UpdatedPolicyTaxParams) => `ha aggiunto l’imposta “${taxName}”`,
+        deleteTax: ({taxName}: UpdatedPolicyTaxParams) => `ha rimosso l'imposta "${taxName}"`,
+        updateTax: ({oldValue, taxName, updatedField, newValue}: UpdatedPolicyTaxParams) => {
             if (!updatedField) {
                 return '';
             }
@@ -7864,32 +6848,31 @@ Aggiungi altre regole di spesa per proteggere il flusso di cassa aziendale.`,
                 }
             }
         },
-        setReceiptRequiredAmount: (newValue: string) => `imposta l’importo richiesto per la ricevuta su "${newValue}"`,
-        changedReceiptRequiredAmount: (oldValue: string, newValue: string) => `ha modificato l’importo richiesto per la ricevuta in "${newValue}" (in precedenza "${oldValue}")`,
-        removedReceiptRequiredAmount: (oldValue: string) => `ha rimosso l’importo richiesto per la ricevuta (in precedenza «${oldValue}»)`,
-        setItemizedReceiptRequiredAmount: (newValue: string) => `imposta l’importo richiesto per la ricevuta con voci singole su "${newValue}"`,
-        changedItemizedReceiptRequiredAmount: (oldValue: string, newValue: string) =>
-            `ha modificato l’importo richiesto per la ricevuta con voci a "${newValue}" (in precedenza "${oldValue}")`,
-        removedItemizedReceiptRequiredAmount: (oldValue: string) => `ha rimosso l’importo richiesto per la ricevuta dettagliata (precedentemente "${oldValue}")`,
-        setMaxExpenseAmount: (newValue: string) => `imposta l’importo massimo della spesa su "${newValue}"`,
-        changedMaxExpenseAmount: (oldValue: string, newValue: string) => `ha modificato l'importo massimo della spesa a "${newValue}" (precedentemente "${oldValue}")`,
-        removedMaxExpenseAmount: (oldValue: string) => `importo massimo spesa rimosso (precedentemente "${oldValue}")`,
-        setMaxExpenseAge: (newValue: string) => `imposta età massima della spesa a "${newValue}" giorni`,
-        changedMaxExpenseAge: (oldValue: string, newValue: string) => `età massima della spesa cambiata a "${newValue}" giorni (in precedenza "${oldValue}")`,
-        removedMaxExpenseAge: (oldValue: string) => `età massima spesa rimossa (precedentemente "${oldValue}" giorni)`,
-        updateCategories: (count: number) => `categorie aggiornate: ${count}`,
-        updateTagList: (tagListName: string) => `tag aggiornati nell’elenco "${tagListName}"`,
-        updateTagListRequired: (tagListsName: string, isRequired: boolean) => `ha modificato l’elenco tag "${tagListsName}" in ${isRequired ? 'obbligatorio' : 'non obbligatorio'}`,
+        setReceiptRequiredAmount: ({newValue}: UpdatedPolicyFieldWithNewAndOldValueParams) => `imposta l’importo richiesto per la ricevuta su "${newValue}"`,
+        changedReceiptRequiredAmount: ({oldValue, newValue}: UpdatedPolicyFieldWithNewAndOldValueParams) =>
+            `ha modificato l’importo richiesto per la ricevuta in "${newValue}" (in precedenza "${oldValue}")`,
+        removedReceiptRequiredAmount: ({oldValue}: UpdatedPolicyFieldWithNewAndOldValueParams) => `ha rimosso l’importo richiesto per la ricevuta (in precedenza «${oldValue}»)`,
+        setMaxExpenseAmount: ({newValue}: UpdatedPolicyFieldWithNewAndOldValueParams) => `imposta l’importo massimo della spesa su "${newValue}"`,
+        changedMaxExpenseAmount: ({oldValue, newValue}: UpdatedPolicyFieldWithNewAndOldValueParams) =>
+            `ha modificato l'importo massimo della spesa a "${newValue}" (precedentemente "${oldValue}")`,
+        removedMaxExpenseAmount: ({oldValue}: UpdatedPolicyFieldWithNewAndOldValueParams) => `importo massimo spesa rimosso (precedentemente "${oldValue}")`,
+        setMaxExpenseAge: ({newValue}: UpdatedPolicyFieldWithNewAndOldValueParams) => `imposta età massima della spesa a "${newValue}" giorni`,
+        changedMaxExpenseAge: ({oldValue, newValue}: UpdatedPolicyFieldWithNewAndOldValueParams) => `età massima della spesa cambiata a "${newValue}" giorni (in precedenza "${oldValue}")`,
+        removedMaxExpenseAge: ({oldValue}: UpdatedPolicyFieldWithNewAndOldValueParams) => `età massima spesa rimossa (precedentemente "${oldValue}" giorni)`,
+        updateCategories: ({count}: UpdatedPolicyCategoriesParams) => `categorie aggiornate: ${count}`,
+        updateTagList: ({tagListName}: UpdatedPolicyTagListParams) => `tag aggiornati nell’elenco "${tagListName}"`,
+        updateTagListRequired: ({tagListsName, isRequired}: UpdatedPolicyTagListRequiredParams) =>
+            `ha modificato l’elenco tag "${tagListsName}" in ${isRequired ? 'obbligatorio' : 'non obbligatorio'}`,
         importTags: 'tag importati da un foglio di calcolo',
         deletedAllTags: 'ha eliminato tutti i tag',
-        updateCustomUnitDefaultCategory: (customUnitName: string, newValue?: string, oldValue?: string) =>
+        updateCustomUnitDefaultCategory: ({customUnitName, newValue, oldValue}: UpdatePolicyCustomUnitDefaultCategoryParams) =>
             `ha cambiato la categoria predefinita di ${customUnitName} in "${newValue}" ${oldValue ? `(precedentemente "${oldValue}")` : ''}`,
-        importCustomUnitRates: (customUnitName: string) => `tariffe importate per l'unità personalizzata "${customUnitName}"`,
-        updateCustomUnitSubRate: (customUnitName: string, customUnitRateName: string, customUnitSubRateName: string, oldValue: string, newValue: string, updatedField: string) =>
+        importCustomUnitRates: ({customUnitName}: ImportPolicyCustomUnitRatesParams) => `tariffe importate per l'unità personalizzata "${customUnitName}"`,
+        updateCustomUnitSubRate: ({customUnitName, customUnitRateName, customUnitSubRateName, oldValue, newValue, updatedField}: UpdatedPolicyCustomUnitSubRateParams) =>
             `ha modificato l’aliquota di "${customUnitName}", tariffa "${customUnitRateName}", sotto-tariffa "${customUnitSubRateName}" ${updatedField} in "${newValue}" (precedentemente "${oldValue}")`,
-        removedCustomUnitSubRate: (customUnitName: string, customUnitRateName: string, removedSubRateName: string) =>
+        removedCustomUnitSubRate: ({customUnitName, customUnitRateName, removedSubRateName}: RemovedPolicyCustomUnitSubRateParams) =>
             `rimossa tariffa "${customUnitName}" tariffa "${customUnitRateName}" sottotariffa "${removedSubRateName}"`,
-        addBudget: (frequency: string, entityName: string, entityType: string, shared?: string, individual?: string, notificationThreshold?: number) => {
+        addBudget: ({frequency, entityName, entityType, shared, individual, notificationThreshold}: AddBudgetParams) => {
             const thresholdSuffix = typeof notificationThreshold === 'number' ? `con soglia di notifica pari al "${notificationThreshold}%"` : '';
             if (typeof shared !== 'undefined' && typeof individual !== 'undefined') {
                 return `aggiunto ${frequency} budget individuale di "${individual}" e ${frequency} budget condiviso di "${shared}"${thresholdSuffix} a ${entityType} "${entityName}"`;
@@ -7899,18 +6882,18 @@ Aggiungi altre regole di spesa per proteggere il flusso di cassa aziendale.`,
             }
             return `ha aggiunto un budget condiviso ${frequency} di "${shared}"${thresholdSuffix} a ${entityType} "${entityName}"`;
         },
-        updateBudget: (
-            entityType: string,
-            entityName: string,
-            oldFrequency?: string,
-            newFrequency?: string,
-            oldIndividual?: string,
-            newIndividual?: string,
-            oldShared?: string,
-            newShared?: string,
-            oldNotificationThreshold?: number,
-            newNotificationThreshold?: number,
-        ) => {
+        updateBudget: ({
+            entityType,
+            entityName,
+            oldFrequency,
+            newFrequency,
+            oldIndividual,
+            newIndividual,
+            oldShared,
+            newShared,
+            oldNotificationThreshold,
+            newNotificationThreshold,
+        }: UpdatedBudgetParams) => {
             const frequencyChanged = !!(newFrequency && oldFrequency !== newFrequency);
             const sharedChanged = !!(newShared && oldShared !== newShared);
             const individualChanged = !!(newIndividual && oldIndividual !== newIndividual);
@@ -7945,7 +6928,7 @@ Aggiungi altre regole di spesa per proteggere il flusso di cassa aziendale.`,
             }
             return `budget aggiornato per ${entityType} «${entityName}»: ${changesList.join('; ')}`;
         },
-        deleteBudget: (entityType: string, entityName: string, frequency?: string, individual?: string, shared?: string, notificationThreshold?: number) => {
+        deleteBudget: ({entityType, entityName, frequency, individual, shared, notificationThreshold}: DeleteBudgetParams) => {
             const thresholdSuffix = typeof notificationThreshold === 'number' ? `con soglia di notifica pari al "${notificationThreshold}%"` : '';
             if (shared && individual) {
                 return `ha rimosso ${frequency} il budget condiviso di "${shared}" e il budget individuale di "${individual}"${thresholdSuffix} da ${entityType} "${entityName}"`;
@@ -7958,129 +6941,48 @@ Aggiungi altre regole di spesa per proteggere il flusso di cassa aziendale.`,
             }
             return `ha rimosso il budget da ${entityType} «${entityName}»`;
         },
-        updatedTimeEnabled: (enabled?: boolean) => {
+        updatedTimeEnabled: ({enabled}: UpdatedPolicyTimeEnabledParams) => {
             return `${enabled ? 'abilitato' : 'disabilitato'} monitoraggio del tempo`;
         },
-        updatedTimeRate: (newRate?: string, oldRate?: string) => {
+        updatedTimeRate: ({newRate, oldRate}: UpdatedPolicyTimeRateParams) => {
             return `ha modificato la tariffa oraria in "${newRate}" (in precedenza "${oldRate}")`;
         },
         addedProhibitedExpense: ({prohibitedExpense}: {prohibitedExpense: string}) => `ha aggiunto "${prohibitedExpense}" alle spese vietate`,
         removedProhibitedExpense: ({prohibitedExpense}: {prohibitedExpense: string}) => `ha rimosso "${prohibitedExpense}" dalle spese vietate`,
-        updatedReimbursementChoice: (newReimbursementChoice: string, oldReimbursementChoice: string) =>
+        updatedReimbursementChoice: ({newReimbursementChoice, oldReimbursementChoice}: UpdatedPolicyReimbursementChoiceParams) =>
             `ha cambiato il metodo di rimborso in "${newReimbursementChoice}" (in precedenza "${oldReimbursementChoice}")`,
         setAutoJoin: ({enabled}: {enabled: boolean}) => `${enabled ? 'abilitato' : 'disabilitato'} pre-approvazione delle richieste di adesione allo spazio di lavoro`,
-        updatedDefaultTitle: (newDefaultTitle: string, oldDefaultTitle: string) =>
+        updatedDefaultTitle: ({newDefaultTitle, oldDefaultTitle}: UpdatedPolicyDefaultTitleParams) =>
             `ha modificato la formula del nome del report personalizzato in "${newDefaultTitle}" (in precedenza "${oldDefaultTitle}")`,
-        updatedOwnership: (oldOwnerEmail: string, oldOwnerName: string, policyName: string) => `ha assunto la proprietà di ${policyName} da ${oldOwnerName} (${oldOwnerEmail})`,
-        updatedAutoHarvesting: (enabled: boolean) => `Invio pianificato ${enabled ? 'abilitato' : 'disabilitato'}`,
-        updatedIndividualBudgetNotification: (
-            budgetAmount: string,
-            budgetFrequency: string,
-            budgetName: string,
-            budgetTypeForNotificationMessage: string,
-            thresholdPercentage: number,
-            totalSpend: number,
-            unsubmittedSpend: number,
-            awaitingApprovalSpend: number,
-            approvedReimbursedClosedSpend: number,
-            summaryLink?: string,
-            userEmail?: string,
-        ) =>
+        updatedOwnership: ({oldOwnerEmail, oldOwnerName, policyName}: UpdatedPolicyOwnershipParams) => `ha assunto la proprietà di ${policyName} da ${oldOwnerName} (${oldOwnerEmail})`,
+        updatedAutoHarvesting: ({enabled}: UpdatedPolicyAutoHarvestingParams) => `Invio pianificato ${enabled ? 'abilitato' : 'disabilitato'}`,
+        updatedIndividualBudgetNotification: ({
+            budgetAmount,
+            budgetFrequency,
+            budgetName,
+            budgetTypeForNotificationMessage,
+            summaryLink,
+            thresholdPercentage,
+            totalSpend,
+            unsubmittedSpend,
+            userEmail,
+            awaitingApprovalSpend,
+            approvedReimbursedClosedSpend,
+        }: UpdatedPolicyBudgetNotificationParams) =>
             `Attenzione! Questo spazio di lavoro ha un budget ${budgetFrequency} di “${budgetAmount}” per il/la ${budgetTypeForNotificationMessage} “${budgetName}”. ${userEmail} è attualmente a ${approvedReimbursedClosedSpend}, che supera il ${thresholdPercentage}% del budget. Ci sono anche ${awaitingApprovalSpend} in attesa di approvazione e ${unsubmittedSpend} non ancora inviati, per un totale di ${totalSpend}.${summaryLink ? `<a href="${summaryLink}">Ecco un report</a> con tutte quelle spese per i tuoi archivi!` : ''}`,
-        updatedSharedBudgetNotification: (
-            budgetAmount: string,
-            budgetFrequency: string,
-            budgetName: string,
-            budgetTypeForNotificationMessage: string,
-            summaryLink: string | undefined,
-            thresholdPercentage: number,
-            totalSpend: number,
-            unsubmittedSpend: number,
-            awaitingApprovalSpend: number,
-            approvedReimbursedClosedSpend: number,
-        ) =>
+        updatedSharedBudgetNotification: ({
+            budgetAmount,
+            budgetFrequency,
+            budgetName,
+            budgetTypeForNotificationMessage,
+            summaryLink,
+            thresholdPercentage,
+            totalSpend,
+            unsubmittedSpend,
+            awaitingApprovalSpend,
+            approvedReimbursedClosedSpend,
+        }: UpdatedPolicyBudgetNotificationParams) =>
             `Attenzione! Questo spazio di lavoro ha un budget ${budgetFrequency} di "${budgetAmount}" per il ${budgetTypeForNotificationMessage} "${budgetName}". Al momento sei a ${approvedReimbursedClosedSpend}, che supera il ${thresholdPercentage}% del budget. Ci sono anche ${awaitingApprovalSpend} in attesa di approvazione e ${unsubmittedSpend} non ancora inviati, per un totale di ${totalSpend}. ${summaryLink ? `<a href="${summaryLink}">Ecco un resoconto</a> con tutte quelle spese per i tuoi archivi!` : ''}`,
-        addedCardFeed: (feedName: string) => `ha aggiunto il feed della carta "${feedName}"`,
-        removedCardFeed: (feedName: string) => `ha rimosso il feed carta "${feedName}"`,
-        renamedCardFeed: (newName: string, oldName: string) => `ha rinominato il feed della carta in "${newName}" (precedentemente "${oldName}")`,
-        assignedCompanyCard: (email: string, feedName: string, cardLastFour: string) =>
-            `ha assegnato ${email} ${feedName ? `"${feedName}" ` : ''}carta aziendale terminante in ${cardLastFour}`,
-        unassignedCompanyCard: (email: string, feedName: string, cardLastFour: string) =>
-            `carta aziendale ${feedName ? `"${feedName}" ` : ''}non assegnata ${email} che termina con ${cardLastFour}`,
-        updatedCardFeedLiability: (feedName: string, enabled: boolean) =>
-            `${enabled ? 'abilitato' : 'disabilitato'} titolari di carta per eliminare le transazioni della carta per il flusso di carte "${feedName}"`,
-        updatedCardFeedStatementPeriod: (feedName: string, newValue?: string, previousValue?: string) =>
-            `ha modificato il giorno di fine periodo dell’estratto conto del flusso carta "${feedName}"${newValue ? ` a "${newValue}"` : ''}${previousValue ? ` (in precedenza "${previousValue}")` : ''}`,
-        addedReportField: (fieldType: string, fieldName?: string, defaultValue?: string) =>
-            `aggiunto campo di report ${fieldType} "${fieldName}"${defaultValue ? ` con valore predefinito "${defaultValue}"` : ''}`,
-        updatedMccGroupCategory: ({mccGroupName, oldCategory, newCategory}: {mccGroupName: string; oldCategory: string; newCategory: string}) =>
-            `ha modificato la categoria di spesa predefinita per "${mccGroupName}" in "${newCategory}" (precedentemente "${oldCategory}")`,
-        updatedRequireCompanyCards: ({enabled}: {enabled: boolean}) => `${enabled ? 'abilitato' : 'disabilitato'} il requisito per gli acquisti con carta aziendale`,
-        expensifyCardRule: {
-            actionVerb: {block: 'bloccato', allow: 'consentito'},
-            amountOperator: {over: 'terminato', under: 'sotto'},
-            amountFilter: ({operator, amount}: {operator: string; amount: string}) => `importi ${operator} ${amount}`,
-            theCard: 'la carta',
-            multipleCards: ({count}: {count: number}) => ({
-                one: '1 carta',
-                other: `${count} carte`,
-            }),
-            addRule: ({verb, filters, cards}: {verb: string; filters: string; cards: string}) => {
-                let text = verb;
-                if (filters !== '') {
-                    text += ` ${filters}`;
-                }
-                text += ` su ${cards}`;
-                return text;
-            },
-            removeRule: ({cards}: {cards: string}) => `regola di spesa rimossa da ${cards}`,
-            restrictionVerb: {block: 'blocca', allow: 'consenti solo'},
-            update: {
-                modeChange: ({fromAction, toAction, cards}: {fromAction: string; toAction: string; cards: string}) =>
-                    `ha modificato la regola di spesa da ${fromAction} a ${toAction} su ${cards}`,
-                appliedToAdditionalCards: ({count}: {count: number}) => ({
-                    one: 'ha applicato la regola di spesa a 1 altra carta',
-                    other: `ha applicato la regola di spesa ad altre ${count} carte`,
-                }),
-                phraseVerb: {added: 'aggiunto', removed: 'rimosso', changed: 'modificato', set: 'imposta', applied: 'applicata'},
-                bodyMerchant: ({adjective, value}: {adjective: string; value: string}) => (adjective !== '' ? `${adjective} esercente '${value}'` : `esercente '${value}'`),
-                bodyMerchantChange: ({adjective, oldValue, newValue}: {adjective: string; oldValue: string; newValue: string}) =>
-                    adjective !== '' ? `commerciante ${adjective} da '${oldValue}' a '${newValue}'` : `esercente da '${oldValue}' a '${newValue}'`,
-                bodySpendCategory: ({adjective, value}: {adjective: string; value: string}) =>
-                    adjective !== '' ? `Categoria di spesa ${adjective} '${value}'` : `categoria di spesa '${value}'`,
-                bodySpendCategoryChange: ({adjective, oldValue, newValue}: {adjective: string; oldValue: string; newValue: string}) =>
-                    adjective !== '' ? `categoria di spesa ${adjective} da '${oldValue}' a '${newValue}'` : `categoria di spesa da '${oldValue}' a '${newValue}'`,
-                bodyMaxAmount: 'importo massimo',
-                bodyMaxAmountSet: ({value}: {value: string}) => `importo massimo a ${value}`,
-                bodyMaxAmountChange: ({oldValue, newValue}: {oldValue: string; newValue: string}) => `importo massimo da ${oldValue} a ${newValue}`,
-                bodyAppliedToAdditionalCards: ({count}: {count: number}) => ({
-                    one: 'regola di spesa per 1 carta aggiuntiva',
-                    other: `regola di spesa per ${count} carte aggiuntive`,
-                }),
-                bodyRemovedFromCards: ({cards}: {cards: string}) => `regola di spesa da ${cards}`,
-                composeOnCards: ({content, cards}: {content: string; cards: string}) => `${content} su ${cards}`,
-                composeFromCards: ({content, cards}: {content: string; cards: string}) => `${content} da ${cards}`,
-            },
-        },
-        addCustomUnitRateWithAmount: (rateName: string, rateValue: string) => `ha aggiunto la tariffa "${rateName}" di ${rateValue}`,
-        addCustomUnitRateWithAmountAndStartDate: (rateName: string, rateValue: string, startDate: string) => `ha aggiunto l’aliquota "${rateName}" di ${rateValue}, valida dal ${startDate}`,
-        addCustomUnitRateWithAmountAndEndDate: (rateName: string, rateValue: string, endDate: string) => `ha aggiunto la tariffa "${rateName}" di ${rateValue}, valida fino al ${endDate}`,
-        addCustomUnitRateWithAmountAndDates: (rateName: string, rateValue: string, startDate: string, endDate: string) =>
-            `ha aggiunto la tariffa "${rateName}" di ${rateValue}, valida dal ${startDate} al ${endDate}`,
-        updatedCustomUnitRateStartDate: (rateName: string, newDate: string, oldDate?: string) =>
-            oldDate
-                ? `aggiornata la data di inizio della tariffa "${rateName}" a ${newDate} (in precedenza ${oldDate})`
-                : `imposta la data di inizio della tariffa "${rateName}" su ${newDate}`,
-        updatedCustomUnitRateEndDate: (rateName: string, newDate: string, oldDate?: string) =>
-            oldDate
-                ? `ha aggiornato la data di fine della tariffa "${rateName}" a ${newDate} (in precedenza ${oldDate})`
-                : `imposta la data di fine della tariffa "${rateName}" al ${newDate}`,
-        updatedCustomUnitRateStartAndEndDate: (rateName: string, newStartDate: string, newEndDate: string, oldStartDate?: string, oldEndDate?: string) =>
-            oldStartDate && oldEndDate
-                ? `ha aggiornato la data di inizio e fine della tariffa "${rateName}" in ${newStartDate} - ${newEndDate} (in precedenza ${oldStartDate} - ${oldEndDate})`
-                : `imposta data di inizio e fine della tariffa "${rateName}" su ${newStartDate} - ${newEndDate}`,
-        removedCustomUnitRateStartDate: (rateName: string, oldDate: string) => `rimossa la data di inizio dalla tariffa "${rateName}" (in precedenza ${oldDate})`,
-        removedCustomUnitRateEndDate: (rateName: string, oldDate: string) => `data di fine rimossa dalla tariffa "${rateName}" (precedentemente ${oldDate})`,
     },
     roomMembersPage: {
         memberNotFound: 'Membro non trovato.',
@@ -8112,7 +7014,7 @@ Aggiungi altre regole di spesa per proteggere il flusso di cassa aziendale.`,
         completed: 'Completato',
         action: 'Completa',
         messages: {
-            created: (title: string) => `attività per ${title}`,
+            created: ({title}: TaskCreatedActionParams) => `attività per ${title}`,
             completed: 'segnato come completato',
             canceled: 'attività eliminata',
             reopened: 'contrassegnato come incompleto',
@@ -8126,7 +7028,7 @@ Aggiungi altre regole di spesa per proteggere il flusso di cassa aziendale.`,
         deleteConfirmation: 'Sei sicuro di voler eliminare questa attività?',
     },
     statementPage: {
-        title: (year: number | string, monthName: string) => `Estratto conto di ${monthName} ${year}`,
+        title: ({year, monthName}: StatementTitleParams) => `Estratto conto di ${monthName} ${year}`,
     },
     keyboardShortcutsPage: {
         title: 'Scorciatoie da tastiera',
@@ -8139,8 +7041,6 @@ Aggiungi altre regole di spesa per proteggere il flusso di cassa aziendale.`,
             newChat: 'Nuova schermata chat',
             copy: 'Copia commento',
             openDebug: 'Apri la finestra delle preferenze di test',
-            expenseReportSearch: 'Cerca i report spese',
-            goToWorkspace: 'Vai allo spazio di lavoro del report corrente',
         },
     },
     guides: {
@@ -8150,8 +7050,6 @@ Aggiungi altre regole di spesa per proteggere il flusso di cassa aziendale.`,
     search: {
         resultsAreLimited: 'I risultati di ricerca sono limitati.',
         viewResults: 'Visualizza risultati',
-        applyFilters: 'Applica i filtri',
-        appliedFilters: 'Filtri applicati',
         resetFilters: 'Reimposta filtri',
         searchResults: {
             emptyResults: {
@@ -8159,23 +7057,28 @@ Aggiungi altre regole di spesa per proteggere il flusso di cassa aziendale.`,
                 subtitle: `Prova a modificare i criteri di ricerca o a creare qualcosa con il pulsante +.`,
             },
             emptyExpenseResults: {
-                title: 'Ancuna nessuna spesa',
+                title: 'Non hai ancora creato alcuna spesa',
                 subtitle: 'Crea una spesa o prova una demo di Expensify per saperne di più.',
                 subtitleWithOnlyCreateButton: 'Usa il pulsante verde qui sotto per creare una spesa.',
             },
             emptyReportResults: {
-                title: 'Nessun report ancora',
+                title: 'Non hai ancora creato alcun rapporto',
                 subtitle: 'Crea un report o fai un giro di prova con Expensify per saperne di più.',
                 subtitleWithOnlyCreateButton: 'Usa il pulsante verde qui sotto per creare un report.',
             },
             emptyInvoiceResults: {
-                title: 'Nessuna fattura ancora',
+                title: dedent(`
+                    Non hai ancora creato
+                    alcuna fattura
+                `),
                 subtitle: 'Invia una fattura o fai un giro di prova con Expensify per saperne di più.',
                 subtitleWithOnlyCreateButton: 'Usa il pulsante verde qui sotto per inviare una fattura.',
-                subtitleCannotSend: 'Hai bisogno di uno spazio di lavoro con Invoices abilitato per inviare fatture.',
-                subtitleCannotSendWithTestDrive: 'Hai bisogno di uno spazio di lavoro con Invoices abilitato per inviare fatture. Fai un giro di prova con Expensify per saperne di più.',
             },
-            emptyTripResults: {title: 'Ancun viaggio ancora', subtitle: 'Inizia prenotando il tuo primo viaggio qui sotto.', buttonText: 'Prenota un viaggio'},
+            emptyTripResults: {
+                title: 'Nessun viaggio da visualizzare',
+                subtitle: 'Inizia prenotando il tuo primo viaggio qui sotto.',
+                buttonText: 'Prenota un viaggio',
+            },
             emptySubmitResults: {
                 title: 'Nessuna spesa da inviare',
                 subtitle: 'Tutto a posto. Goditi il tuo giro d’onore!',
@@ -8203,31 +7106,30 @@ Aggiungi altre regole di spesa per proteggere il flusso di cassa aziendale.`,
             },
         },
         columns: 'Colonne',
-        editColumns: 'Modifica colonne',
         resetColumns: 'Reimposta colonne',
         groupColumns: 'Raggruppa colonne',
         expenseColumns: 'Colonne spese',
-        saveView: 'Salva vista',
+        statements: 'Estratti conto',
+        unapprovedCash: 'Contanti non approvati',
+        unapprovedCard: 'Carta non approvata',
+        reconciliation: 'Riconciliazione',
+        topSpenders: 'Maggiori spendaccioni',
+        saveSearch: 'Salva ricerca',
         deleteSavedSearch: 'Elimina ricerca salvata',
         deleteSavedSearchConfirm: 'Sei sicuro di voler eliminare questa ricerca?',
         searchName: 'Cerca nome',
         savedSearchesMenuItemTitle: 'Salvato',
-        urlCopied: 'URL copiato',
+        topCategories: 'Categorie principali',
+        topMerchants: 'Commercianti principali',
         groupedExpenses: 'spese raggruppate',
         bulkActions: {
-            editMultiple: 'Modifica multipli',
-            editMultipleTitle: 'Modifica più spese',
-            editMultipleDescription: 'Le modifiche verranno applicate a tutte le spese selezionate e sovrascriveranno qualsiasi valore impostato in precedenza.',
             approve: 'Approva',
             pay: 'Paga',
             delete: 'Elimina',
             hold: 'Metti in attesa',
             unhold: 'Rimuovi blocco',
             reject: 'Rifiuta',
-            duplicateExpense: ({count}: {count: number}) => `Duplica ${count === 1 ? 'spesa' : 'spese'}`,
             noOptionsAvailable: 'Nessuna opzione disponibile per il gruppo di spese selezionato.',
-            undelete: 'Ripristina',
-            duplicateReport: ({count}: {count: number}) => `Duplica ${count === 1 ? 'report' : 'report'}`,
         },
         filtersHeader: 'Filtri',
         filters: {
@@ -8235,14 +7137,11 @@ Aggiungi altre regole di spesa per proteggere il flusso di cassa aziendale.`,
                 before: (date?: string) => `Prima di ${date ?? ''}`,
                 after: (date?: string) => `Dopo ${date ?? ''}`,
                 on: (date?: string) => `Su ${date ?? ''}`,
-                customDate: 'Data personalizzata',
-                customRange: 'Intervallo personalizzato',
                 presets: {
                     [CONST.SEARCH.DATE_PRESETS.NEVER]: 'Mai',
                     [CONST.SEARCH.DATE_PRESETS.LAST_MONTH]: 'Il mese scorso',
                     [CONST.SEARCH.DATE_PRESETS.THIS_MONTH]: 'Questo mese',
                     [CONST.SEARCH.DATE_PRESETS.YEAR_TO_DATE]: 'Da inizio anno',
-                    [CONST.SEARCH.DATE_PRESETS.LAST_12_MONTHS]: 'Ultimi 12 mesi',
                     [CONST.SEARCH.DATE_PRESETS.LAST_STATEMENT]: 'Ultimo estratto conto',
                 },
             },
@@ -8254,15 +7153,10 @@ Aggiungi altre regole di spesa per proteggere il flusso di cassa aziendale.`,
             currency: 'Valuta',
             completed: 'Completato',
             amount: {
-                lessThan: (amount?: string) => `Meno di ${amount ?? ''}`,
-                greaterThan: (amount?: string) => `Maggiore di ${amount ?? ''}`,
-                between: (greaterThan?: string, lessThan?: string) => {
-                    if (greaterThan && lessThan) {
-                        return `Tra ${greaterThan} e ${lessThan}`;
-                    }
-                    return 'Tra';
-                },
-                equalTo: (amount?: string) => `Uguale a ${amount ?? ''}`,
+                lessThan: ({amount}: OptionalParam<RequestAmountParams> = {}) => `Meno di ${amount ?? ''}`,
+                greaterThan: ({amount}: OptionalParam<RequestAmountParams> = {}) => `Maggiore di ${amount ?? ''}`,
+                between: (greaterThan: string, lessThan: string) => `Tra ${greaterThan} e ${lessThan}`,
+                equalTo: ({amount}: OptionalParam<RequestAmountParams> = {}) => `Uguale a ${amount ?? ''}`,
             },
             card: {
                 expensify: 'Expensify',
@@ -8272,9 +7166,8 @@ Aggiungi altre regole di spesa per proteggere il flusso di cassa aziendale.`,
                 cardFeedName: ({cardFeedBankName, cardFeedLabel}: {cardFeedBankName: string; cardFeedLabel?: string}) =>
                     `Tutti ${cardFeedBankName}${cardFeedLabel ? ` - ${cardFeedLabel}` : ''}`,
                 cardFeedNameCSV: ({cardFeedLabel}: {cardFeedLabel?: string}) => `Tutte le carte CSV importate${cardFeedLabel ? ` - ${cardFeedLabel}` : ''}`,
-                travelInvoicing: 'Fatturazione viaggi',
             },
-            reportField: (name: string, value: string) => `${name} è ${value}`,
+            reportField: ({name, value}: OptionalParam<ReportFieldParams>) => `${name} è ${value}`,
             current: 'Attuale',
             past: 'Passato',
             submitted: 'Inviato',
@@ -8286,10 +7179,6 @@ Aggiungi altre regole di spesa per proteggere il flusso di cassa aziendale.`,
             billable: 'Fatturabile',
             reimbursable: 'Rimborsabile',
             purchaseCurrency: 'Valuta di acquisto',
-            sortOrder: {
-                [CONST.SEARCH.SORT_ORDER.ASC]: 'In ordine crescente',
-                [CONST.SEARCH.SORT_ORDER.DESC]: 'In discesa',
-            },
             groupBy: {
                 [CONST.SEARCH.GROUP_BY.FROM]: 'Da',
                 [CONST.SEARCH.GROUP_BY.CARD]: 'Carta',
@@ -8306,7 +7195,6 @@ Aggiungi altre regole di spesa per proteggere il flusso di cassa aziendale.`,
             withdrawalType: {
                 [CONST.SEARCH.WITHDRAWAL_TYPE.EXPENSIFY_CARD]: 'Carta Expensify',
                 [CONST.SEARCH.WITHDRAWAL_TYPE.REIMBURSEMENT]: 'Rimborso',
-                [CONST.SEARCH.WITHDRAWAL_TYPE.CENTRAL_TRAVEL_INVOICING]: 'Fatturazione viaggi',
             },
             is: 'È',
             action: {
@@ -8316,20 +7204,13 @@ Aggiungi altre regole di spesa per proteggere il flusso di cassa aziendale.`,
                 [CONST.SEARCH.ACTION_FILTERS.EXPORT]: 'Esporta',
             },
         },
-        display: {
-            label: 'Visualizza',
-            sortBy: 'Ordina per',
-            sortOrder: 'Ordine di visualizzazione',
-            groupBy: 'Raggruppa per',
-            limitResults: 'Limita i risultati',
-        },
         has: 'Ha',
+        groupBy: 'Raggruppa per',
         view: {
             label: 'Visualizza',
             table: 'Tabella',
             bar: 'Bar',
             line: 'Linea',
-            pie: 'Torta',
         },
         chartTitles: {
             [CONST.SEARCH.GROUP_BY.FROM]: 'Da',
@@ -8354,22 +7235,9 @@ Aggiungi altre regole di spesa per proteggere il flusso di cassa aziendale.`,
         withdrawalType: 'Tipo di prelievo',
         recentSearches: 'Ricerche recenti',
         recentChats: 'Chat recenti',
-        serverResults: 'Risultati di ricerca',
         searchIn: 'Cerca in',
-        askConcierge: (message: string) => `Chiedi a Concierge “${message}”`,
-        searchPlaceholder: 'Cerca qualcosa...',
+        searchPlaceholder: 'Cerca qualcosa',
         suggestions: 'Suggerimenti',
-        suggestionsAvailable: (
-            {
-                count,
-            }: {
-                count: number;
-            },
-            query = '',
-        ) => ({
-            one: `Suggerimenti disponibili${query ? ` per ${query}` : ''}. ${count} risultato.`,
-            other: (resultCount: number) => `Suggerimenti disponibili${query ? ` per ${query}` : ''}. ${resultCount} risultati.`,
-        }),
         exportSearchResults: {
             title: 'Crea esportazione',
             description: 'Wow, sono davvero tanti elementi! Li raggrupperemo e Concierge ti invierà un file a breve.',
@@ -8377,30 +7245,7 @@ Aggiungi altre regole di spesa per proteggere il flusso di cassa aziendale.`,
         exportedTo: 'Esportato in',
         exportAll: {
             selectAllMatchingItems: 'Seleziona tutti gli elementi corrispondenti',
-            allMatchingItemsSelected: 'Tutti gli elementi corrispondenti selezionati',
-            selectAllOnThisPage: 'Seleziona tutto in questa pagina',
-        },
-        errors: {
-            pleaseSelectDatesForBothFromAndTo: 'Seleziona le date per Da e A',
-        },
-        spendOverTime: 'Spesa nel tempo',
-        tabs: {
-            expenseReports: 'Note spese',
-            reports: 'Report',
-            expenses: 'Spese',
-            submit: 'Bozze',
-            approve: 'Richiede approvazione',
-            pay: 'Pronto per pagare',
-            accounting: 'Contabilità',
-            export: 'In attesa di esportazione',
-            unapprovedCash: 'Ratei e risconti in contanti',
-            unapprovedCard: 'Ratei carta',
-            statements: 'Estratti conto carta',
-            reconciliation: 'Riconciliazione bancaria',
-            insights: 'Analisi',
-            topSpenders: 'Maggiori spendaccioni',
-            topCategories: 'Categorie principali',
-            topMerchants: 'Principali esercenti',
+            allMatchingItemsSelected: 'Tutti gli elementi corrispondenti sono stati selezionati',
         },
     },
     genericErrorPage: {
@@ -8457,6 +7302,7 @@ Aggiungi altre regole di spesa per proteggere il flusso di cassa aziendale.`,
             emptyReportConfirmationTitle: 'Hai già un report vuoto',
             emptyReportConfirmationPrompt: ({workspaceName}: {workspaceName: string}) =>
                 `Sei sicuro di voler creare un altro report in ${workspaceName}? Puoi accedere ai tuoi report vuoti in`,
+            emptyReportConfirmationPromptLink: 'Report',
             emptyReportConfirmationDontShowAgain: 'Non mostrarmelo più',
             genericWorkspaceName: 'questo spazio di lavoro',
         },
@@ -8494,7 +7340,6 @@ Aggiungi altre regole di spesa per proteggere il flusso di cassa aziendale.`,
                     reimburseableLink: 'spese vive',
                     nonReimbursableLink: 'spese con carta aziendale',
                     pending: (label: string) => `ha iniziato a esportare questo resoconto su ${label}...`,
-                    travelCardLink: 'spese con carta di viaggio',
                 },
                 integrationsMessage: (errorMessage: string, label: string, linkText?: string, linkURL?: string) =>
                     `esportazione di questo report su ${label} non riuscita ("${errorMessage}${linkText ? `<a href="${linkURL}">${linkText}</a>` : ''}")`,
@@ -8503,8 +7348,7 @@ Aggiungi altre regole di spesa per proteggere il flusso di cassa aziendale.`,
                 markedReimbursed: (amount: string, currency: string) => `pagato ${currency}${amount} altrove`,
                 markedReimbursedFromIntegration: ({amount, currency}: MarkReimbursedFromIntegrationParams) => `pagato ${currency}${amount} tramite integrazione`,
                 outdatedBankAccount: `impossibile elaborare il pagamento a causa di un problema con il conto bancario del pagatore`,
-                reimbursementACHBounceDefault: `impossibile elaborare il pagamento a causa di un numero di instradamento/conto errato o di un conto chiuso`,
-                reimbursementACHBounceWithReason: ({returnReason}: {returnReason: string}) => `impossibile elaborare il pagamento: ${returnReason}`,
+                reimbursementACHBounce: `impossibile elaborare il pagamento a causa di un problema con il conto bancario`,
                 reimbursementACHCancelled: `ha annullato il pagamento`,
                 reimbursementAccountChanged: `impossibile elaborare il pagamento, poiché il pagatore ha cambiato conto bancario`,
                 reimbursementDelayed: `ha elaborato il pagamento ma è in ritardo di 1-2 giorni lavorativi in più`,
@@ -8512,22 +7356,17 @@ Aggiungi altre regole di spesa per proteggere il flusso di cassa aziendale.`,
                 selectedForRandomAuditMarkdown: `selezionato in modo casuale per la revisione`,
                 share: ({to}: ShareParams) => `ha invitato il membro ${to}`,
                 unshare: ({to}: UnshareParams) => `ha rimosso il membro ${to}`,
-                stripePaid: (amount: string, currency: string) => `ha pagato ${currency}${amount}`,
+                stripePaid: ({amount, currency}: StripePaidParams) => `ha pagato ${currency}${amount}`,
                 takeControl: `ha preso il controllo`,
                 integrationSyncFailed: (label: string, errorMessage: string, workspaceAccountingLink?: string) =>
                     `si è verificato un problema di sincronizzazione con ${label}${errorMessage ? ` ("${errorMessage}")` : ''}. Risolvi il problema nelle <a href="${workspaceAccountingLink}">impostazioni dello spazio di lavoro</a>.`,
-                integrationSyncFailedRecurrence: ({count}: {count: number}) => `(Ripetuto ${count} volte.)`,
                 companyCardConnectionBroken: ({feedName, workspaceCompanyCardRoute}: {feedName: string; workspaceCompanyCardRoute: string}) =>
                     `La connessione ${feedName} è interrotta. Per ripristinare le importazioni della carta, <a href='${workspaceCompanyCardRoute}'>accedi alla tua banca</a>.`,
                 plaidBalanceFailure: ({maskedAccountNumber, walletRoute}: {maskedAccountNumber: string; walletRoute: string}) =>
-                    `la connessione Plaid al conto bancario della tua azienda non funziona. Per favore, <a href='${walletRoute}'>ricollega il conto bancario ${maskedAccountNumber}</a> così puoi continuare a usare le tue Carte Expensify.`,
-                addEmployee: (email: string, role: string, didJoinPolicy?: boolean) => {
-                    const translatedRole = String(translations.workspace.common.roleName(role)).toLowerCase();
-                    const article = role === CONST.POLICY.ROLE.AUDITOR ? 'un' : 'a';
-                    return didJoinPolicy ? `${email} si è unito tramite il link di invito dello spazio di lavoro` : `ha aggiunto ${email} come ${article} ${translatedRole}`;
-                },
+                    `la connessione Plaid al conto bancario della tua azienda non funziona. Per favore, <a href='${walletRoute}'>ricollega il tuo conto bancario ${maskedAccountNumber}</a> per continuare a usare le tue Expensify Card.`,
+                addEmployee: (email: string, role: string) => `aggiunto ${email} come ${role === 'member' ? 'a' : 'un'} ${role}`,
                 updateRole: ({email, currentRole, newRole}: UpdateRoleParams) => `ha aggiornato il ruolo di ${email} a ${newRole} (in precedenza ${currentRole})`,
-                updatedCustomField1: (email: string, newValue: string, previousValue: string) => {
+                updatedCustomField1: ({email, previousValue, newValue}: UpdatedCustomFieldParams) => {
                     if (!newValue) {
                         return `rimossa la campo personalizzato 1 di ${email} (in precedenza “${previousValue}”)`;
                     }
@@ -8535,7 +7374,7 @@ Aggiungi altre regole di spesa per proteggere il flusso di cassa aziendale.`,
                         ? `ha aggiunto "${newValue}" al campo personalizzato 1 di ${email}`
                         : `ha modificato il campo personalizzato 1 di ${email} in "${newValue}" (precedentemente "${previousValue}")`;
                 },
-                updatedCustomField2: (email: string, newValue: string, previousValue: string) => {
+                updatedCustomField2: ({email, previousValue, newValue}: UpdatedCustomFieldParams) => {
                     if (!newValue) {
                         return `rimossa la sezione personalizzata 2 di ${email} (in precedenza “${previousValue}”)`;
                     }
@@ -8549,12 +7388,8 @@ Aggiungi altre regole di spesa per proteggere il flusso di cassa aziendale.`,
                 addedConnection: ({connectionName}: ConnectionNameParams) => `collegato a ${CONST.POLICY.CONNECTIONS.NAME_USER_FRIENDLY[connectionName]}`,
                 leftTheChat: 'ha lasciato la chat',
                 settlementAccountLocked: ({maskedBankAccountNumber}: OriginalMessageSettlementAccountLocked, linkURL: string) =>
-                    `il conto bancario aziendale ${maskedBankAccountNumber} è stato bloccato automaticamente a causa di un problema con il rimborso o con il regolamento della Carta Expensify. Risolvi il problema nelle <a href="${linkURL}">impostazioni dello spazio di lavoro</a>.`,
+                    `il conto bancario aziendale ${maskedBankAccountNumber} è stato bloccato automaticamente a causa di un problema con il Rimborso o con il regolamento della Expensify Card. Risolvi il problema nelle <a href="${linkURL}">impostazioni dello spazio di lavoro</a>.`,
                 leftTheChatWithName: (nameOrEmail: string) => `${nameOrEmail ? `${nameOrEmail}: ` : ''} ha lasciato la chat`,
-                actionableCard3DSTransactionApproval: (amount: string, merchant: string | undefined) => {
-                    const amountAndMerchantText = [amount, merchant].filter((s) => !!s?.length).join(' ');
-                    return `Apri l'app mobile di Expensify per esaminare la tua transazione di${amountAndMerchantText ? ` ${amountAndMerchantText}` : ''}`;
-                },
             },
             error: {
                 invalidCredentials: 'Credenziali non valide, controlla la configurazione della tua connessione.',
@@ -8564,23 +7399,6 @@ Aggiungi altre regole di spesa per proteggere il flusso di cassa aziendale.`,
     chronos: {
         oooEventSummaryFullDay: (summary: string, dayCount: number, date: string) => `${summary} per ${dayCount} ${dayCount === 1 ? 'giorno' : 'giorni'} fino al ${date}`,
         oooEventSummaryPartialDay: (summary: string, timePeriod: string, date: string) => `${summary} dal ${timePeriod} del ${date}`,
-        startTimer: 'Avvia timer',
-        stopTimer: (duration: string) => `Ferma timer (${duration})`,
-        scheduleOOO: 'Pianifica OOO',
-        scheduleOOOTitle: 'Programma assenza dall’ufficio',
-        date: 'Data',
-        time: 'Ora (formato 24 ore)',
-        durationAmount: 'Durata',
-        durationUnit: 'Unità',
-        reason: 'Motivo',
-        workingPercentage: 'Percentuale lavorativa',
-        dateRequired: 'La data è obbligatoria.',
-        invalidTimeFormat: 'Inserisci un orario valido nel formato 24 ore (ad es. 14:30).',
-        enterANumber: 'Inserisci un numero.',
-        hour: 'ore',
-        day: 'giorni',
-        week: 'settimane',
-        month: 'mesi',
     },
     footer: {
         features: 'Funzionalità',
@@ -8623,24 +7441,8 @@ Aggiungi altre regole di spesa per proteggere il flusso di cassa aziendale.`,
         workspaceName: 'Nome workspace',
         chatUserDisplayNames: 'Nomi visualizzati dei membri della chat',
         scrollToNewestMessages: 'Scorri ai messaggi più recenti',
-        scrollToActionBadgeTarget: "Scorri all'azione che richiede attenzione",
         preStyledText: 'Testo preformattato',
         viewAttachment: 'Visualizza allegato',
-        contextMenuAvailable: 'Menu contestuale disponibile. Premi Shift+F10 per aprirlo.',
-        contextMenuAvailableMacOS: 'Menu contestuale disponibile. Premi VO-Shift-M per aprirlo.',
-        contextMenuAvailableNative: 'Menu contestuale disponibile. Tocca due volte e tieni premuto per aprirlo.',
-        selectAllFeatures: 'Seleziona tutte le funzionalità',
-        selectAllTransactions: 'Seleziona tutte le transazioni',
-        selectAllItems: 'Seleziona tutti gli elementi',
-        openActionsMenu: 'Apri menu azioni',
-        selectAllCategories: 'Seleziona tutte le categorie',
-        selectAllDistanceRates: 'Seleziona tutte le tariffe chilometriche',
-        selectAllTags: 'Seleziona tutti i tag',
-        selectAllTaxes: 'Seleziona tutte le imposte',
-        selectAllPerDiemRates: 'Seleziona tutte le tariffe giornaliere',
-        selectAllMembers: 'Seleziona tutti i membri',
-        selectAllValues: 'Seleziona tutti i valori',
-        selectAllRules: 'Seleziona tutte le regole',
     },
     parentReportAction: {
         deletedReport: 'Report eliminato',
@@ -8659,7 +7461,6 @@ Aggiungi altre regole di spesa per proteggere il flusso di cassa aziendale.`,
         parentNavigationSummary: ({reportName, workspaceName}: ParentNavigationSummaryParams) => `Da ${reportName}${workspaceName ? `in ${workspaceName}` : ''}`,
     },
     qrCodes: {
-        qrCode: 'Codice QR',
         copy: 'Copia URL',
         copied: 'Copiato!',
     },
@@ -8706,11 +7507,6 @@ Aggiungi altre regole di spesa per proteggere il flusso di cassa aziendale.`,
             'Unisciti a Expensify.org per eliminare le ingiustizie in tutto il mondo. L’attuale campagna “Teachers Unite” supporta gli insegnanti ovunque, dividendo i costi delle forniture scolastiche essenziali.',
         iKnowATeacher: 'Conosco un insegnante',
         iAmATeacher: 'Sono un insegnante',
-        personalKarma: {
-            title: 'Attiva il Karma personale',
-            description: 'Dona 1 $ a Expensify.org per ogni 500 $ che spendi ogni mese',
-            stopDonationsPrompt: 'Sei sicuro di voler smettere di donare a Expensify.org?',
-        },
         getInTouch: 'Eccellente! Condividi le loro informazioni così possiamo metterci in contatto con loro.',
         introSchoolPrincipal: 'Introduzione al dirigente scolastico',
         schoolPrincipalVerifyExpense:
@@ -8733,11 +7529,6 @@ Aggiungi altre regole di spesa per proteggere il flusso di cassa aziendale.`,
         notActivated: 'Non attivato',
         outOfPocket: 'Rimborsabile',
         companySpend: 'Non rimborsabile',
-        personalCard: 'Carta personale',
-        companyCard: 'Carta aziendale',
-        expensifyCard: 'Carta Expensify',
-        travelInvoicing: 'Fatturazione viaggi',
-        travelCard: 'Carta Viaggio',
     },
     distance: {
         addStop: 'Aggiungi fermata',
@@ -8761,18 +7552,14 @@ Aggiungi altre regole di spesa per proteggere il flusso di cassa aziendale.`,
             endReading: 'Fine lettura',
             saveForLater: 'Salva per dopo',
             totalDistance: 'Distanza totale',
+            startTitle: 'Foto iniziale del contachilometri',
+            endTitle: 'Foto del contachilometri finale',
             startMessageWeb: 'Aggiungi una foto del contachilometri all’<strong>inizio</strong> del tuo viaggio. Trascina qui un file oppure scegli un file da caricare.',
             endMessageWeb: 'Aggiungi una foto del contachilometri scattata alla <strong>fine</strong> del viaggio. Trascina qui un file oppure scegli un file da caricare.',
-            startTitle: 'Foto iniziale del contachilometri',
-            endTitle: 'Foto contachilometri finale',
-            deleteOdometerPhoto: 'Elimina foto del contachilometri',
-            deleteOdometerPhotoConfirmation: 'Sei sicuro di voler eliminare questa foto del contachilometri?',
-            cameraAccessRequired: 'Per scattare foto è necessario l’accesso alla fotocamera.',
-            snapPhotoStart: "<muted-text-label>Scatta una foto del contachilometri all'<strong>inizio</strong> del viaggio.</muted-text-label>",
-            snapPhotoEnd: '<muted-text-label>Scatta una foto del contachilometri alla <strong>fine</strong> del viaggio.</muted-text-label>',
         },
     },
     gps: {
+        disclaimer: 'Usa il GPS per creare una spesa dal tuo viaggio. Tocca Avvia qui sotto per iniziare il tracciamento.',
         error: {
             failedToStart: 'Impossibile avviare il tracciamento della posizione.',
             failedToGetPermissions: 'Impossibile ottenere le autorizzazioni di posizione richieste.',
@@ -8781,9 +7568,13 @@ Aggiungi altre regole di spesa per proteggere il flusso di cassa aziendale.`,
         stopped: 'Interrotto',
         start: 'Avvia',
         stop: 'Interrompi',
-        save: 'Salva',
-        resume: 'Riprendi',
         discard: 'Scarta',
+        stopGpsTrackingModal: {
+            title: 'Interrompi tracciamento GPS',
+            prompt: 'Sei sicuro? Questo terminerà il percorso in corso.',
+            cancel: 'Riprendi monitoraggio',
+            confirm: 'Interrompi tracciamento GPS',
+        },
         discardDistanceTrackingModal: {
             title: 'Annulla rilevamento distanza',
             prompt: 'Sei sicuro? Questo eliminerà il tuo percorso attuale e non potrà essere annullato.',
@@ -8831,18 +7622,12 @@ Aggiungi altre regole di spesa per proteggere il flusso di cassa aziendale.`,
             prompt: 'Sei sicuro di voler interrompere il tracciamento GPS e passare a Expensify Classic?',
             confirm: 'Interrompi e cambia',
         },
-        switchAccountWarningTripInProgress: {
-            title: 'Monitoraggio GPS in corso',
-            prompt: 'Sei sicuro di voler interrompere il tracciamento GPS e cambiare account?',
-            confirm: 'Interrompi e cambia',
-        },
         locationServicesRequiredModal: {
             title: 'Accesso alla posizione richiesto',
             confirm: 'Apri impostazioni',
             prompt: 'Consenti l’accesso alla posizione nelle impostazioni del dispositivo per iniziare il tracciamento della distanza GPS.',
         },
-        gpsFloatingPillText: 'Tracciamento GPS in corso...',
-        liveActivity: {subtitle: 'Rilevamento distanza', button: 'Visualizza avanzamento', lockScreenBadgeText: 'Distanza', lockScreenTrackingText: 'Tracciamento in corso...'},
+        fabGpsTripExplained: 'Vai alla schermata GPS (azione flottante)',
     },
     reportCardLostOrDamaged: {
         screenTitle: 'Pagella smarrita o danneggiata',
@@ -8870,13 +7655,11 @@ Aggiungi altre regole di spesa per proteggere il flusso di cassa aziendale.`,
         [CONST.REFERRAL_PROGRAM.CONTENT_TYPES.START_CHAT]: {
             buttonText: 'Avvia una chat, <success><strong>presenta un amico</strong></success>.',
             header: 'Avvia una chat, invita un amico',
-            closeAccessibilityLabel: 'Chiudi, avvia una chat, invita un amico, banner',
             body: 'Vuoi che anche i tuoi amici usino Expensify? Inizia una chat con loro e ci occuperemo noi del resto.',
         },
         [CONST.REFERRAL_PROGRAM.CONTENT_TYPES.SUBMIT_EXPENSE]: {
             buttonText: 'Invia una nota spese, <success><strong>presenta il tuo team</strong></success>.',
             header: 'Invia una spesa, invita il tuo team',
-            closeAccessibilityLabel: 'Chiudi, invia una spesa, invita il tuo team, banner',
             body: 'Vuoi che anche il tuo team usi Expensify? Invia loro una spesa e noi ci occuperemo del resto.',
         },
         [CONST.REFERRAL_PROGRAM.CONTENT_TYPES.REFER_FRIEND]: {
@@ -8892,27 +7675,26 @@ Aggiungi altre regole di spesa per proteggere il flusso di cassa aziendale.`,
     },
     systemChatFooterMessage: {
         [CONST.INTRO_CHOICES.MANAGE_TEAM]: ({adminReportName, href}: {adminReportName: string; href: string}) =>
-            `Chatta con il tuo account executive in <a href="${href}">${adminReportName}</a> per avere aiuto`,
-        default: `Invia un messaggio a <concierge-link>${CONST.CONCIERGE_CHAT_NAME}</concierge-link> per ricevere aiuto con la configurazione`,
+            `Chatta con il tuo specialista di configurazione in <a href="${href}">${adminReportName}</a> per ricevere assistenza`,
+        default: `Invia un messaggio a <concierge-link>${CONST.CONCIERGE_CHAT_NAME}</concierge-link> per ricevere assistenza con la configurazione`,
     },
     violations: {
         allTagLevelsRequired: 'Tutti i tag obbligatori',
         autoReportedRejectedExpense: 'Questa spesa è stata rifiutata.',
         billableExpense: 'Addebitabile non più valido',
-        cashExpenseWithNoReceipt: (formattedLimit?: string) => `Ricevuta obbligatoria${formattedLimit ? `oltre ${formattedLimit}` : ''}`,
+        cashExpenseWithNoReceipt: ({formattedLimit}: ViolationsCashExpenseWithNoReceiptParams = {}) => `Ricevuta obbligatoria${formattedLimit ? `oltre ${formattedLimit}` : ''}`,
         categoryOutOfPolicy: 'Categoria non più valida',
-        conversionSurcharge: (surcharge: number) => `Applicato un sovrapprezzo di conversione del ${surcharge}%`,
+        conversionSurcharge: ({surcharge}: ViolationsConversionSurchargeParams) => `Applicato un sovrapprezzo di conversione del ${surcharge}%`,
         customUnitOutOfPolicy: 'Tariffa non valida per questo spazio di lavoro',
         duplicatedTransaction: 'Duplice potenziale',
         fieldRequired: 'I campi del report sono obbligatori',
         futureDate: 'Data futura non consentita',
-        inactiveVendor: 'Fornitore non più valido',
-        invoiceMarkup: (invoiceMarkup: number) => `Maggiorato del ${invoiceMarkup}%`,
-        maxAge: (maxAge: number) => `Data precedente a ${maxAge} giorni`,
+        invoiceMarkup: ({invoiceMarkup}: ViolationsInvoiceMarkupParams) => `Maggiorato del ${invoiceMarkup}%`,
+        maxAge: ({maxAge}: ViolationsMaxAgeParams) => `Data precedente a ${maxAge} giorni`,
         missingCategory: 'Categoria mancante',
         missingComment: 'Descrizione obbligatoria per la categoria selezionata',
         missingAttendees: 'Per questa categoria sono richiesti più partecipanti',
-        missingTag: (tagName?: string) => `Manca ${tagName ?? 'etichetta'}`,
+        missingTag: ({tagName}: ViolationsMissingTagParams = {}) => `Manca ${tagName ?? 'etichetta'}`,
         modifiedAmount: ({type, displayPercentVariance}: ViolationsModifiedAmountParams) => {
             switch (type) {
                 case 'distance':
@@ -8927,17 +7709,15 @@ Aggiungi altre regole di spesa per proteggere il flusso di cassa aziendale.`,
             }
         },
         modifiedDate: 'Data diversa dalla ricevuta scansionata',
-        increasedDistance: ({formattedRouteDistance}: ViolationsIncreasedDistanceParams) =>
-            formattedRouteDistance ? `La distanza supera il percorso calcolato di ${formattedRouteDistance}` : 'La distanza supera il percorso calcolato',
         nonExpensiworksExpense: 'Spesa non-Expensiworks',
-        overAutoApprovalLimit: (formattedLimit: string) => `La spesa supera il limite di approvazione automatica di ${formattedLimit}`,
-        overCategoryLimit: (formattedLimit: string) => `Importo superiore al limite di categoria di ${formattedLimit}/persona`,
-        overLimit: (formattedLimit: string) => `Importo oltre il limite di ${formattedLimit}/persona`,
-        overTripLimit: (formattedLimit: string) => `Importo oltre il limite di ${formattedLimit}/viaggio`,
-        overLimitAttendee: (formattedLimit: string) => `Importo oltre il limite di ${formattedLimit}/persona`,
-        perDayLimit: (formattedLimit: string) => `Importo oltre il limite giornaliero di categoria di ${formattedLimit}/persona`,
+        overAutoApprovalLimit: ({formattedLimit}: ViolationsOverLimitParams) => `La spesa supera il limite di approvazione automatica di ${formattedLimit}`,
+        overCategoryLimit: ({formattedLimit}: ViolationsOverCategoryLimitParams) => `Importo superiore al limite di categoria di ${formattedLimit}/persona`,
+        overLimit: ({formattedLimit}: ViolationsOverLimitParams) => `Importo oltre il limite di ${formattedLimit}/persona`,
+        overTripLimit: ({formattedLimit}: ViolationsOverLimitParams) => `Importo oltre il limite di ${formattedLimit}/viaggio`,
+        overLimitAttendee: ({formattedLimit}: ViolationsOverLimitParams) => `Importo oltre il limite di ${formattedLimit}/persona`,
+        perDayLimit: ({formattedLimit}: ViolationsPerDayLimitParams) => `Importo oltre il limite giornaliero di categoria di ${formattedLimit}/persona`,
         receiptNotSmartScanned: 'Dettagli di ricevuta e spesa aggiunti manualmente.',
-        receiptRequired: (formattedLimit?: string, category?: string) => {
+        receiptRequired: ({formattedLimit, category}: ViolationsReceiptRequiredParams) => {
             if (formattedLimit && category) {
                 return `Ricevuta richiesta oltre il limite di categoria di ${formattedLimit}`;
             }
@@ -8949,8 +7729,8 @@ Aggiungi altre regole di spesa per proteggere il flusso di cassa aziendale.`,
             }
             return 'Ricevuta obbligatoria';
         },
-        itemizedReceiptRequired: (formattedLimit?: string) => `Ricevuta dettagliata richiesta${formattedLimit ? `oltre ${formattedLimit}` : ''}`,
-        prohibitedExpense: (prohibitedExpenseTypes: string | string[]) => {
+        itemizedReceiptRequired: ({formattedLimit}: {formattedLimit?: string}) => `Ricevuta dettagliata richiesta${formattedLimit ? `oltre ${formattedLimit}` : ''}`,
+        prohibitedExpense: ({prohibitedExpenseTypes}: ViolationsProhibitedExpenseParams) => {
             const preMessage = 'Spesa vietata:';
             const getProhibitedExpenseTypeText = (prohibitedExpenseType: string) => {
                 switch (prohibitedExpenseType) {
@@ -8964,10 +7744,6 @@ Aggiungi altre regole di spesa per proteggere il flusso di cassa aziendale.`,
                         return `intrattenimento per adulti`;
                     case 'hotelIncidentals':
                         return `spese accessorie dell’hotel`;
-                    case 'giftCard':
-                        return `acquisto di carte regalo`;
-                    case 'handwrittenReceipt':
-                        return `ricevute scritte a mano`;
                     default:
                         return `${prohibitedExpenseType}`;
                 }
@@ -8983,37 +7759,19 @@ Aggiungi altre regole di spesa per proteggere il flusso di cassa aziendale.`,
             }
             return `${preMessage} ${types.map(getProhibitedExpenseTypeText).join(', ')}`;
         },
-        customRules: (message: string) => message,
+        customRules: ({message}: ViolationsCustomRulesParams) => message,
         reviewRequired: 'Revisione richiesta',
-        rter: (
-            brokenBankConnection: boolean,
-            isAdmin: boolean,
-            isTransactionOlderThan7Days: boolean,
-            member?: string,
-            rterType?: ValueOf<typeof CONST.RTER_VIOLATION_TYPES>,
-            companyCardPageURL?: string,
-            connectionLink?: string,
-            isPersonalCard?: boolean,
-            isMarkAsCash?: boolean,
-        ) => {
+        rter: ({brokenBankConnection, isAdmin, isTransactionOlderThan7Days, member, rterType, companyCardPageURL}: ViolationsRterParams) => {
             if (rterType === CONST.RTER_VIOLATION_TYPES.BROKEN_CARD_CONNECTION_530) {
-                return 'Impossibile abbinare automaticamente la ricevuta a causa di un problema di connessione bancaria.';
-            }
-            if (isPersonalCard && (rterType === CONST.RTER_VIOLATION_TYPES.BROKEN_CARD_CONNECTION || brokenBankConnection)) {
-                if (!connectionLink) {
-                    return 'Impossibile abbinare automaticamente la ricevuta a causa di un problema di connessione bancaria.';
-                }
-                return isMarkAsCash
-                    ? `Impossibile abbinare automaticamente la ricevuta a causa di un problema di connessione della carta. Contrassegna come contanti per ignorare oppure <a href="${connectionLink}">sistema la carta</a> per abbinare la ricevuta.`
-                    : `Impossibile abbinare automaticamente la ricevuta a causa di un problema di connessione con la carta. <a href="${connectionLink}">Correggi la carta</a> per abbinarla alla ricevuta.`;
+                return 'Impossibile abbinare automaticamente la ricevuta a causa di un collegamento bancario interrotto';
             }
             if (brokenBankConnection || rterType === CONST.RTER_VIOLATION_TYPES.BROKEN_CARD_CONNECTION) {
                 return isAdmin
                     ? `Connessione bancaria interrotta. <a href="${companyCardPageURL}">Riconnetti per abbinare la ricevuta</a>`
-                    : 'Connessione bancaria interrotta. Chiedi a un amministratore di riconnetterla per abbinare la ricevuta.';
+                    : 'Collegamento bancario interrotto. Chiedi a un amministratore di ricollegarlo per abbinare la ricevuta.';
             }
             if (!isTransactionOlderThan7Days) {
-                return isAdmin ? `Chiedi a ${member} di contrassegnarla come contante oppure attendi 7 giorni e riprova` : 'In attesa di abbinamento con la transazione della carta.';
+                return isAdmin ? `Chiedi a ${member} di contrassegnarla come contante oppure attendi 7 giorni e riprova` : 'In attesa di unione con la transazione della carta.';
             }
             return '';
         },
@@ -9022,21 +7780,12 @@ Aggiungi altre regole di spesa per proteggere il flusso di cassa aziendale.`,
             `<muted-text-label>Ricevuta in sospeso a causa di un collegamento bancario interrotto. Risolvi il problema in <a href="${workspaceCompanyCardRoute}">Carte aziendali</a>.</muted-text-label>`,
         memberBrokenConnectionError: 'Ricevuta in sospeso a causa di un collegamento bancario interrotto. Chiedi a un amministratore dello spazio di lavoro di risolvere il problema.',
         markAsCashToIgnore: 'Segna come contante da ignorare e richiedi il pagamento.',
-        smartscanFailed: ({canEdit = true, missingFields = []}: {canEdit?: boolean; missingFields?: string[]}) => {
-            if (missingFields.length > 0) {
-                const fieldNames: Record<string, string> = {merchant: 'esercente', date: 'data', amount: 'importo'};
-                const translated = missingFields.map((f) => fieldNames[f] ?? f);
-                const fieldList = translated.join(translated.length > 2 ? ', ' : ' e ');
-                const verb = translated.length === 1 ? 'mancante' : 'mancanti';
-                return `Scansione della ricevuta non riuscita — ${fieldList} ${verb}.${canEdit ? ' Inserisci i dettagli manualmente.' : ''}`;
-            }
-            return `Scansione della ricevuta non riuscita.${canEdit ? 'Inserisci i dettagli manualmente.' : ''}`;
-        },
+        smartscanFailed: ({canEdit = true}) => `Scansione della ricevuta non riuscita.${canEdit ? 'Inserisci i dettagli manualmente.' : ''}`,
         receiptGeneratedWithAI: 'Ricevuta potenzialmente generata dall’IA',
-        someTagLevelsRequired: (tagName?: string) => `Manca ${tagName ?? 'Etichetta'}`,
-        tagOutOfPolicy: (tagName?: string) => `${tagName ?? 'Etichetta'} non è più valido`,
+        someTagLevelsRequired: ({tagName}: ViolationsTagOutOfPolicyParams = {}) => `Manca ${tagName ?? 'Etichetta'}`,
+        tagOutOfPolicy: ({tagName}: ViolationsTagOutOfPolicyParams = {}) => `${tagName ?? 'Etichetta'} non è più valido`,
         taxAmountChanged: 'L’importo dell’imposta è stato modificato',
-        taxOutOfPolicy: (taxName?: string) => `${taxName ?? 'Imposta'} non è più valido`,
+        taxOutOfPolicy: ({taxName}: ViolationsTaxOutOfPolicyParams = {}) => `${taxName ?? 'Imposta'} non è più valido`,
         taxRateChanged: 'L’aliquota fiscale è stata modificata',
         taxRequired: 'Aliquota fiscale mancante',
         none: 'Nessuno',
@@ -9056,7 +7805,7 @@ Aggiungi altre regole di spesa per proteggere il flusso di cassa aziendale.`,
         noRoute: 'Seleziona un indirizzo valido',
     },
     reportViolations: {
-        [CONST.REPORT_VIOLATIONS.FIELD_REQUIRED]: (fieldName: string) => `${fieldName} è obbligatorio`,
+        [CONST.REPORT_VIOLATIONS.FIELD_REQUIRED]: ({fieldName}: RequiredFieldParams) => `${fieldName} è obbligatorio`,
         reportContainsExpensesWithViolations: 'Il report contiene spese con violazioni.',
     },
     violationDismissal: {
@@ -9113,7 +7862,6 @@ Aggiungi altre regole di spesa per proteggere il flusso di cassa aziendale.`,
         bookACallTextBottom:
             'Saremmo felici di fare una chiamata con te per capirne il motivo. Puoi prenotare una chiamata con uno dei nostri senior product manager per discutere delle tue esigenze.',
         takeMeToExpensifyClassic: 'Portami a Expensify Classic',
-        goBackJustOnce: 'Torna solo per questa volta',
     },
     listBoundary: {
         errorMessage: 'Si è verificato un errore durante il caricamento di altri messaggi',
@@ -9187,7 +7935,7 @@ Aggiungi altre regole di spesa per proteggere il flusso di cassa aziendale.`,
                 subtitle: 'Come prossimo passo, <a href="#">completa la tua checklist di configurazione</a> così il tuo team può iniziare a registrare le spese.',
             },
             trialStarted: {
-                title: (numOfDays: number) => `Prova: ${numOfDays} ${numOfDays === 1 ? 'giorno' : 'giorni'} rimanenti!`,
+                title: ({numOfDays}: TrialStartedTitleParams) => `Prova: ${numOfDays} ${numOfDays === 1 ? 'giorno' : 'giorni'} rimanenti!`,
                 subtitle: 'Aggiungi una carta di pagamento per continuare a usare tutte le tue funzionalità preferite.',
             },
             trialEnded: {
@@ -9225,15 +7973,15 @@ Aggiungi altre regole di spesa per proteggere il flusso di cassa aziendale.`,
             title: 'Il tuo piano',
             exploreAllPlans: 'Esplora tutti i piani',
             customPricing: 'Prezzi personalizzati',
-            asLowAs: (price: string) => `a partire da ${price} per membro attivo/mese`,
-            pricePerMemberMonth: (price: string) => `${price} per membro/mese`,
-            pricePerMemberPerMonth: (price: string) => `${price} per membro al mese`,
+            asLowAs: ({price}: YourPlanPriceValueParams) => `a partire da ${price} per membro attivo/mese`,
+            pricePerMemberMonth: ({price}: YourPlanPriceValueParams) => `${price} per membro/mese`,
+            pricePerMemberPerMonth: ({price}: YourPlanPriceValueParams) => `${price} per membro al mese`,
             perMemberMonth: 'per membro/mese',
             collect: {
                 title: 'Riscuoti',
                 description: 'Il piano per piccole imprese che ti offre note spese, viaggi e chat.',
-                priceAnnual: ({lower, upper}: YourPlanPriceParams) => `Da ${lower} membro/attivo con la Carta Expensify, ${upper} membro/attivo senza la Carta Expensify.`,
-                pricePayPerUse: ({lower, upper}: YourPlanPriceParams) => `Da ${lower} membro/attivo con la Carta Expensify, ${upper} membro/attivo senza la Carta Expensify.`,
+                priceAnnual: ({lower, upper}: YourPlanPriceParams) => `Da ${lower}/membro attivo con Expensify Card, ${upper}/membro attivo senza Expensify Card.`,
+                pricePayPerUse: ({lower, upper}: YourPlanPriceParams) => `Da ${lower}/membro attivo con Expensify Card, ${upper}/membro attivo senza Expensify Card.`,
                 benefit1: 'Scansione ricevute',
                 benefit2: 'Rimborsi',
                 benefit3: 'Gestione carte aziendali',
@@ -9246,8 +7994,8 @@ Aggiungi altre regole di spesa per proteggere il flusso di cassa aziendale.`,
             control: {
                 title: 'Controllo',
                 description: 'Spese, viaggi e chat per le aziende più grandi.',
-                priceAnnual: ({lower, upper}: YourPlanPriceParams) => `Da ${lower} membro/attivo con la Carta Expensify, ${upper} membro/attivo senza la Carta Expensify.`,
-                pricePayPerUse: ({lower, upper}: YourPlanPriceParams) => `Da ${lower} membro/attivo con la Carta Expensify, ${upper} membro/attivo senza la Carta Expensify.`,
+                priceAnnual: ({lower, upper}: YourPlanPriceParams) => `Da ${lower}/membro attivo con Expensify Card, ${upper}/membro attivo senza Expensify Card.`,
+                pricePayPerUse: ({lower, upper}: YourPlanPriceParams) => `Da ${lower}/membro attivo con Expensify Card, ${upper}/membro attivo senza Expensify Card.`,
                 benefit1: 'Tutto ciò che è incluso nel piano Collect',
                 benefit2: 'Flussi di approvazione multilivello',
                 benefit3: 'Regole personalizzate per le spese',
@@ -9261,8 +8009,8 @@ Aggiungi altre regole di spesa per proteggere il flusso di cassa aziendale.`,
             downgrade: 'Passa a Collect',
             upgrade: 'Passa a Control',
             addMembers: 'Aggiungi membri',
-            saveWithExpensifyTitle: 'Risparmia con la Carta Expensify',
-            saveWithExpensifyDescription: 'Usa il nostro calcolatore di risparmio per vedere come il cash back della Carta Expensify può ridurre la tua fattura Expensify.',
+            saveWithExpensifyTitle: 'Risparmia con la Expensify Card',
+            saveWithExpensifyDescription: 'Usa il nostro calcolatore di risparmio per vedere come il cashback della Expensify Card può ridurre la tua fattura Expensify.',
             saveWithExpensifyButton: 'Scopri di più',
         },
         compareModal: {
@@ -9272,7 +8020,6 @@ Aggiungi altre regole di spesa per proteggere il flusso di cassa aziendale.`,
         details: {
             title: 'Dettagli dell’abbonamento',
             annual: 'Abbonamento annuale',
-            creditBalance: 'Saldo del credito',
             taxExempt: 'Richiedi esenzione fiscale',
             taxExemptEnabled: 'Esente da imposte',
             taxExemptStatus: 'Stato di esenzione fiscale',
@@ -9290,10 +8037,10 @@ Aggiungi altre regole di spesa per proteggere il flusso di cassa aziendale.`,
             note: 'Nota: un membro attivo è chiunque abbia creato, modificato, inviato, approvato, rimborsato o esportato dati di spesa associati allo spazio di lavoro della tua azienda.',
             confirmDetails: 'Conferma i dettagli del tuo nuovo abbonamento annuale:',
             subscriptionSize: 'Dimensione abbonamento',
-            activeMembers: (size: number) => `${size} membri attivi/mese`,
+            activeMembers: ({size}: SubscriptionSizeParams) => `${size} membri attivi/mese`,
             subscriptionRenews: 'Rinnovo abbonamento',
             youCantDowngrade: 'Non puoi effettuare il downgrade durante l’abbonamento annuale.',
-            youAlreadyCommitted: (size: number, date: string) =>
+            youAlreadyCommitted: ({size, date}: SubscriptionCommitmentParams) =>
                 `Hai già sottoscritto un abbonamento annuale per ${size} membri attivi al mese fino al ${date}. Puoi passare a un abbonamento a consumo il ${date} disattivando il rinnovo automatico.`,
             error: {
                 size: 'Inserisci una dimensione di abbonamento valida',
@@ -9306,50 +8053,37 @@ Aggiungi altre regole di spesa per proteggere il flusso di cassa aziendale.`,
             security: 'Expensify è conforme allo standard PCI-DSS, utilizza la crittografia a livello bancario e si avvale di un’infrastruttura ridondante per proteggere i tuoi dati.',
             learnMoreAboutSecurity: 'Scopri di più sulla nostra sicurezza.',
         },
-        expensifyCode: {
-            title: 'Codice Expensify',
-            discountCode: 'Codice sconto',
-            enterCode: 'Inserisci un codice Expensify da applicare al tuo abbonamento.',
-            discountMessage: (promoDiscount: string, validBillingCycles: string) =>
-                `Riceverai uno sconto del ${promoDiscount}% sui tuoi prossimi ${validBillingCycles ? `${validBillingCycles} ` : ''}addebiti di fatturazione.`,
-            apply: 'Applica',
-            error: {
-                invalid: 'Questo codice non è valido',
-            },
-        },
         subscriptionSettings: {
             title: 'Impostazioni abbonamento',
-            summary: (subscriptionType: string, subscriptionSize: string, expensifyCode: string, autoRenew: string, autoIncrease: string) =>
-                `Tipo di abbonamento: ${subscriptionType}, Dimensione abbonamento: ${subscriptionSize}${expensifyCode ? `, Codice Expensify: ${expensifyCode}` : ''}, Rinnovo automatico: ${autoRenew}, Aumento automatico dei posti annuali: ${autoIncrease}`,
+            summary: ({subscriptionType, subscriptionSize, autoRenew, autoIncrease}: SubscriptionSettingsSummaryParams) =>
+                `Tipo di abbonamento: ${subscriptionType}, Dimensione abbonamento: ${subscriptionSize}, Rinnovo automatico: ${autoRenew}, Aumento automatico dei posti annuali: ${autoIncrease}`,
             none: 'nessuno',
             on: 'attivo',
             off: 'disattivato',
             annual: 'Annuale',
             autoRenew: 'Rinnovo automatico',
             autoIncrease: 'Aumento automatico dei posti annuali',
-            saveUpTo: (amountWithCurrency: string) => `Risparmia fino a ${amountWithCurrency}/mese per ogni membro attivo`,
+            saveUpTo: ({amountWithCurrency}: SubscriptionSettingsSaveUpToParams) => `Risparmia fino a ${amountWithCurrency}/mese per ogni membro attivo`,
             automaticallyIncrease:
                 'Aumenta automaticamente i posti annuali per accogliere i membri attivi che superano le dimensioni del tuo abbonamento. Nota: questo prolungherà la data di fine del tuo abbonamento annuale.',
             disableAutoRenew: 'Disattiva rinnovo automatico',
             helpUsImprove: 'Aiutaci a migliorare Expensify',
             whatsMainReason: 'Qual è il motivo principale per cui stai disattivando il rinnovo automatico?',
-            renewsOn: (date: string) => `Si rinnova il ${date}.`,
-            pricingConfiguration: 'Il prezzo dipende dalla configurazione. Per il prezzo più basso, scegli un abbonamento annuale e richiedi la Carta Expensify.',
-            learnMore: (hasAdminsRoom: boolean) =>
+            renewsOn: ({date}: SubscriptionSettingsRenewsOnParams) => `Si rinnova il ${date}.`,
+            pricingConfiguration: 'Il prezzo dipende dalla configurazione. Per ottenere il prezzo più basso, scegli un abbonamento annuale e richiedi la Expensify Card.',
+            learnMore: ({hasAdminsRoom}: SubscriptionSettingsLearnMoreParams) =>
                 `<muted-text>Scopri di più sulla nostra <a href="${CONST.PRICING}">pagina dei prezzi</a> oppure chatta con il nostro team nel tuo ${hasAdminsRoom ? `<a href="adminsRoom">Stanza #admins.</a>` : 'Stanza #admins.'}</muted-text>`,
             estimatedPrice: 'Prezzo stimato',
-            changesBasedOn: "Questo cambia in base all'utilizzo della tua Carta Expensify e alle opzioni di abbonamento qui sotto.",
-            collectBillingDescription: 'Gli spazi di lavoro Collect vengono fatturati mensilmente per membro, senza impegno annuale.',
-            pricing: 'Prezzi',
+            changesBasedOn: 'Questo cambia in base all’utilizzo della tua Expensify Card e alle opzioni di abbonamento qui sotto.',
         },
-        cancelSubscription: {
-            title: 'Annulla abbonamento',
-            subtitle: 'Qual è il motivo principale per cui vuoi annullare il tuo abbonamento?',
+        requestEarlyCancellation: {
+            title: 'Richiedi annullamento anticipato',
+            subtitle: 'Qual è il motivo principale per cui stai richiedendo l’annullamento anticipato?',
             subscriptionCanceled: {
                 title: 'Abbonamento annullato',
                 subtitle: 'Il tuo abbonamento annuale è stato annullato.',
                 info: 'Se vuoi continuare a usare il tuo workspace (o i tuoi workspace) con pagamento a consumo, è tutto pronto.',
-                preventFutureActivity: (workspacesListRoute: string) =>
+                preventFutureActivity: ({workspacesListRoute}: WorkspacesListRouteParams) =>
                     `Se desideri evitare attività e addebiti futuri, devi <a href="${workspacesListRoute}">eliminare il tuo spazio di lavoro (o i tuoi spazi di lavoro)</a>. Tieni presente che, quando elimini il tuo spazio di lavoro (o i tuoi spazi di lavoro), ti verrà addebitata qualsiasi attività in sospeso sostenuta durante il mese di calendario in corso.`,
             },
             requestSubmitted: {
@@ -9357,7 +8091,7 @@ Aggiungi altre regole di spesa per proteggere il flusso di cassa aziendale.`,
                 subtitle:
                     'Grazie per averci informato che sei interessato/a a disdire il tuo abbonamento. Stiamo esaminando la tua richiesta e ti contatteremo presto tramite la tua chat con <concierge-link>Concierge</concierge-link>.',
             },
-            acknowledgement: `Richiedendo la cancellazione, riconosco e accetto che Expensify non ha alcun obbligo di concedere tale richiesta ai sensi dei <a href=${CONST.OLD_DOT_PUBLIC_URLS.TERMS_URL}>Termini di servizio</a> di Expensify o di altri contratti di servizio applicabili tra me ed Expensify e che Expensify mantiene esclusiva discrezionalità in merito alla concessione di qualsiasi tale richiesta.`,
+            acknowledgement: `Richiedendo la cancellazione anticipata, riconosco e accetto che Expensify non ha alcun obbligo di concedere tale richiesta ai sensi dei <a href=${CONST.OLD_DOT_PUBLIC_URLS.TERMS_URL}>Termini di servizio</a> di Expensify o di altri contratti di servizio applicabili tra me ed Expensify e che Expensify mantiene esclusiva discrezionalità in merito alla concessione di qualsiasi tale richiesta.`,
         },
     },
     feedbackSurvey: {
@@ -9376,14 +8110,11 @@ Aggiungi altre regole di spesa per proteggere il flusso di cassa aziendale.`,
     },
     delegate: {
         switchAccount: 'Cambia account:',
-        switch: 'Cambia',
-        copilot: 'Copilot',
         copilotDelegatedAccess: 'Copilot: Accesso delegato',
         copilotDelegatedAccessDescription: 'Consenti agli altri membri di accedere al tuo account.',
-        learnMoreAboutDelegatedAccess: "Scopri di più sull'accesso delegato",
-        addCopilot: 'Aggiungi un copilota',
+        addCopilot: 'Aggiungi copilota',
         membersCanAccessYourAccount: 'Questi membri possono accedere al tuo account:',
-        youCanAccessTheseAccounts: 'Puoi accedere a questi account:',
+        youCanAccessTheseAccounts: 'Puoi accedere a questi account tramite il selettore di account:',
         role: ({role}: OptionalParam<DelegateRoleParams> = {}) => {
             switch (role) {
                 case CONST.DELEGATE_ROLE.ALL:
@@ -9502,7 +8233,6 @@ Aggiungi altre regole di spesa per proteggere il flusso di cassa aziendale.`,
             theresWasAProblemDuringAWorkspaceConnectionSync: 'Si è verificato un problema durante la sincronizzazione della connessione dello spazio di lavoro',
             theresAProblemWithYourWallet: 'Si è verificato un problema con il tuo portafoglio',
             theresAProblemWithYourWalletTerms: 'C’è un problema con i termini del tuo portafoglio',
-            aBankAccountIsLocked: 'Un conto bancario è bloccato',
         },
     },
     emptySearchView: {
@@ -9523,10 +8253,15 @@ Aggiungi altre regole di spesa per proteggere il flusso di cassa aziendale.`,
         conciergeLHNGBR: '<tooltip>Inizia <strong>qui!</strong></tooltip>',
         saveSearchTooltip: '<tooltip><strong>Rinomina qui le ricerche salvate</strong>!</tooltip>',
         accountSwitcher: '<tooltip>Accedi ai tuoi <strong>account Copilot</strong> qui</tooltip>',
+        scanTestTooltip: {
+            main: '<tooltip><strong>Scansiona la nostra ricevuta di prova</strong> per vedere come funziona!</tooltip>',
+            manager: '<tooltip>Scegli il nostro <strong>test manager</strong> per provarlo!</tooltip>',
+            confirmation: '<tooltip>Ora, <strong>invia la tua nota spese</strong> e guarda la\nmagia che accade!</tooltip>',
+            tryItOut: 'Provalo',
+        },
         outstandingFilter: '<tooltip>Filtra per le spese\nche <strong>necessitano di approvazione</strong></tooltip>',
         scanTestDriveTooltip: '<tooltip>Invia questa ricevuta per\n<strong>completare il test drive!</strong></tooltip>',
         gpsTooltip: '<tooltip>Tracciamento GPS in corso! Quando hai finito, interrompi il tracciamento qui sotto.</tooltip>',
-        hasFilterNegation: '<tooltip>Cerca le spese senza ricevute usando <strong>-has:receipt</strong>.</tooltip>',
     },
     discardChangesConfirmation: {
         title: 'Scartare le modifiche?',
@@ -9542,7 +8277,7 @@ Aggiungi altre regole di spesa per proteggere il flusso di cassa aziendale.`,
         confirmation: {
             title: 'Conferma chiamata',
             description: 'Assicurati che i dettagli qui sotto ti sembrino corretti. Una volta confermata la chiamata, ti invieremo un invito con maggiori informazioni.',
-            setupSpecialist: 'Il tuo account executive',
+            setupSpecialist: 'Il tuo/La tua specialista di configurazione',
             meetingLength: 'Durata riunione',
             dateTime: 'Data e ora',
             minutes: '30 minuti',
@@ -9590,20 +8325,6 @@ Ecco una *ricevuta di prova* per mostrarti come funziona:`,
         exportInProgress: 'Esportazione in corso',
         conciergeWillSend: 'Concierge ti invierà il file a breve.',
     },
-    exportDownload: {
-        preparingTitle: 'Preparing download...',
-        preparingBody: 'You can either wait for the download to finish or Concierge can send it to you via chat.',
-        sendFromConcierge: "Send me the file when it's ready",
-        conciergeTitle: 'You bet!',
-        conciergeBody: 'Concierge will send you a message when the file is ready.',
-        goToConcierge: 'Go to Concierge',
-        dismiss: 'Dismiss',
-        readyTitle: 'Your file is ready!',
-        readyBody: "If it didn't automatically download, use the button below.",
-        downloadFile: 'Download file',
-        failedTitle: 'Export failed',
-        close: 'Close',
-    },
     domain: {
         notVerified: 'Non verificato',
         retry: 'Riprova',
@@ -9637,7 +8358,7 @@ Ecco una *ricevuta di prova* per mostrarti come funziona:`,
         goToDomain: 'Vai al dominio',
         samlLogin: {
             title: 'Accesso SAML',
-            subtitle: `<muted-text>Configura l’accesso dei membri con <a href="${CONST.SAML_HELP_URL}">accesso Single Sign-On (SSO) SAML</a>.</muted-text>`,
+            subtitle: `<muted-text>Configura l’accesso dei membri con <a href="${CONST.SAML_HELP_URL}">accesso Single Sign-On (SSO) SAML.</a></muted-text>`,
             enableSamlLogin: 'Abilita accesso SAML',
             allowMembers: 'Consenti ai membri di accedere con SAML.',
             requireSamlLogin: 'Richiedi accesso SAML',
@@ -9647,8 +8368,6 @@ Ecco una *ricevuta di prova* per mostrarti come funziona:`,
             disableSamlRequired: 'Disattiva richiesta SAML',
             oktaWarningPrompt: 'Sei sicuro? Questo disabiliterà anche Okta SCIM.',
             requireWithEmptyMetadataError: 'Aggiungi qui sotto i metadati del provider di identità per abilitare',
-            pleaseDisableTwoFactorAuth: (twoFactorAuthSettingsUrl: string) =>
-                `<muted-text>Disattiva <a href="${twoFactorAuthSettingsUrl}">l’obbligo dell’autenticazione a due fattori</a> per abilitare l’accesso SAML.</muted-text>`,
         },
         samlConfigurationDetails: {
             title: 'Dettagli configurazione SAML',
@@ -9697,6 +8416,7 @@ Ecco una *ricevuta di prova* per mostrarti come funziona:`,
             primaryContact: 'Contatto principale',
             addPrimaryContact: 'Aggiungi contatto principale',
             setPrimaryContactError: 'Impossibile impostare il contatto principale. Riprova più tardi.',
+            settings: 'Impostazioni',
             consolidatedDomainBilling: 'Fatturazione dominio consolidata',
             consolidatedDomainBillingDescription: (domainName: string) =>
                 `<comment><muted-text-label>Se abilitata, la persona di contatto principale pagherà tutti gli spazi di lavoro di proprietà dei membri di <strong>${domainName}</strong> e riceverà tutte le ricevute di fatturazione.</muted-text-label></comment>`,
@@ -9713,110 +8433,25 @@ Ecco una *ricevuta di prova* per mostrarti come funziona:`,
             resetDomain: 'Reimposta dominio',
             resetDomainExplanation: ({domainName}: {domainName?: string}) => `Digita <strong>${domainName}</strong> per confermare il ripristino del dominio.`,
             enterDomainName: 'Inserisci qui il tuo nome di dominio',
-            resetDomainInfo: `Questa azione è <strong>definitiva</strong> e i seguenti dati verranno eliminati: <br/> <bullet-list><bullet-item>Connessioni alle carte aziendali e tutte le spese non rendicontate da tali carte</bullet-item><bullet-item>Impostazioni SAML e dei gruppi</bullet-item><bullet-item>Dati di viaggio e accesso a Expensify Travel</bullet-item></bullet-list> Tutti gli account, gli spazi di lavoro, i report, le spese e gli altri dati rimarranno. <br/><br/>Nota: puoi rimuovere questo dominio dall’elenco dei tuoi domini eliminando l’email associata dalle tue <a href="#">modalità di contatto</a>.`,
+            resetDomainInfo: `Questa azione è <strong>definitiva</strong> e i seguenti dati verranno eliminati: <br/> <ul><li>Connessioni alle carte aziendali e tutte le spese non rendicontate di tali carte</li> <li>Impostazioni SAML e di gruppo</li> </ul> Tutti gli account, gli spazi di lavoro, i report, le spese e gli altri dati rimarranno. <br/><br/>Nota: puoi rimuovere questo dominio dall’elenco dei tuoi domini eliminando l’email associata dalle tue <a href="#">modalità di contatto</a>.`,
         },
         domainMembers: 'Membri del dominio',
         members: {
             title: 'Membri',
             findMember: 'Trova membro',
             addMember: 'Aggiungi membro',
-            allMembers: 'Tutti i membri',
             email: 'Indirizzo email',
-            closeAccount: () => ({
-                one: 'Chiudi account',
-                other: 'Chiudi account',
-            }),
+            closeAccount: 'Chiudi account',
             closeAccountPrompt: 'Sei sicuro? Questa azione è permanente.',
-            forceCloseAccount: () => ({
-                one: 'Forza chiusura account',
-                other: 'Forza chiusura account',
-            }),
-            safeCloseAccount: () => ({
-                one: 'Chiudi il conto in sicurezza',
-                other: 'Chiudi i conti in sicurezza',
-            }),
-            closeAccountInfo: () => ({
-                one: 'Consigliamo di chiudere l’account in modo sicuro per evitare problemi in caso di: <bullet-list><bullet-item>Approvazioni in sospeso</bullet-item><bullet-item>Rimborsi attivi</bullet-item><bullet-item>Nessun metodo di accesso alternativo</bullet-item></bullet-list>In caso contrario, puoi ignorare le precauzioni di sicurezza sopra indicate e forzare la chiusura dell’account selezionato.',
-                other: 'Consigliamo di chiudere gli account in modo sicuro per evitare problemi in caso di: <bullet-list><bullet-item>Approvazioni in sospeso</bullet-item><bullet-item>Rimborsi attivi</bullet-item><bullet-item>Nessun metodo di accesso alternativo</bullet-item></bullet-list>In caso contrario, puoi ignorare le precauzioni di sicurezza sopra indicate e forzare la chiusura degli account selezionati.',
-            }),
+            forceCloseAccount: 'Forza chiusura account',
+            safeCloseAccount: 'Chiudi il conto in sicurezza',
+            closeAccountInfo:
+                'Consigliamo di chiudere l’account in modo sicuro per evitare problemi in caso di: <ul><li>Approvazioni in sospeso</li><li>Rimborsi attivi</li><li>Nessun metodo di accesso alternativo</li></ul>In caso contrario, puoi ignorare le precauzioni di sicurezza sopra indicate e forzare la chiusura dell’account selezionato.',
             error: {
                 removeMember: 'Impossibile rimuovere questo utente. Riprova.',
                 addMember: 'Impossibile aggiungere questo membro. Riprova.',
-                vacationDelegate: 'Impossibile impostare questo utente come delegato per le ferie. Riprova.',
-                moveMember: 'Impossibile spostare questo membro. Riprova.',
-                moveMemberNotPolicyAdmin:
-                    'Impossibile spostare il membro nel gruppo di dominio. Devi essere Amministratore di Criteri per il Criterio Preferito impostato nel gruppo di dominio in cui stai cercando di spostare questo utente.',
-            },
-            cannotSetVacationDelegateForMember: (email: string) => `Non puoi impostare un delegato per le vacanze per ${email} perché al momento è il delegato per i seguenti membri:`,
-            reportSuspiciousActivityPrompt: (email: string) =>
-                `Sei sicuro? Questo bloccherà l’account di <strong>${email}</strong>. <br /><br /> Il nostro team esaminerà quindi l’account e rimuoverà qualsiasi accesso non autorizzato. Per riottenere l’accesso, dovranno collaborare con Concierge.`,
-            reportSuspiciousActivityConfirmationPrompt: 'Esamineremo l’account per verificare che sia sicuro sbloccarlo e ti contatteremo tramite Concierge per qualsiasi domanda.',
-            emptyMembers: {title: 'Nessun membro in questo gruppo', subtitle: 'Aggiungi un membro o prova a cambiare il filtro qui sopra.'},
-            moveToGroup: 'Sposta nel gruppo',
-            chooseWhereToMove: ({count}: {count: number}) => `Scegli dove spostare ${count} ${count === 1 ? 'membro' : 'membri'}.`,
-            domainGroup: 'Gruppo di domini',
-            chooseWhereToMoveName: ({name}: {name: string}) => `Scegli dove spostare ${name}.`,
-            membersFeatureList: {
-                subtitle: ({domainName}: {domainName: string}) =>
-                    `<muted-text>Verifica il tuo dominio per avere un maggiore controllo sui membri di <strong>${domainName}</strong> in Expensify.</muted-text>`,
-                controlPolicyCreation: 'Limita la creazione di workspace',
-                enableSamlSso: 'Abilita SSO SAML',
-                enforce2FA: 'Imponi 2FA',
             },
         },
-        common: {
-            settings: 'Impostazioni',
-            forceTwoFactorAuth: 'Imponi l’autenticazione a due fattori',
-            forceTwoFactorAuthSAMLEnabledDescription: (samlPageUrl: string) =>
-                `<muted-text>Disabilita <a href="${samlPageUrl}">SAML</a> per imporre l’autenticazione a due fattori.</muted-text>`,
-            forceTwoFactorAuthDescription: `<muted-text>Richiedi l’autenticazione a due fattori per tutti i membri di questo dominio. Ai membri del dominio verrà chiesto di configurare l’autenticazione a due fattori sul proprio account quando effettuano l’accesso.</muted-text>`,
-            forceTwoFactorAuthError: 'Impossibile modificare l’impostazione “Forza l’autenticazione a due fattori”. Riprova più tardi.',
-            resetTwoFactorAuth: 'Reimposta l’autenticazione a due fattori',
-            error: 'Impossibile salvare questa modifica. Riprova.',
-        },
-        groups: {
-            title: 'Gruppi',
-            memberCount: () => ({one: '1 membro', other: (count: number) => `${count} membri`}),
-            defaultGroup: 'Gruppo predefinito per i nuovi membri',
-            defaultGroupPrompt: (currentName: string, newName: string) =>
-                `Sei sicuro di voler impostare ${newName} come gruppo predefinito? I nuovi membri verranno invitati a questo gruppo invece del precedente gruppo predefinito (${currentName}). `,
-            makeDefault: 'Imposta come predefinito',
-            neverMind: 'Lascia perdere',
-            createGroupError: 'Impossibile creare questo gruppo. Riprova.',
-            permissions: 'Autorizzazioni del gruppo',
-            createNewGroupButton: 'Nuovo gruppo',
-            createGroupSubmitButton: 'Crea gruppo',
-            expensifyCardPreferredWorkspace: 'Workspace preferito per Expensify Card',
-            expensifyCardPreferredWorkspaceDescription:
-                "Tutte le transazioni Expensify Card verranno create nell'area di lavoro preferita Expensify Card anziché nell'area di lavoro preferita.",
-            strictlyEnforceWorkspaceRules: 'Applica rigorosamente le regole dello spazio di lavoro',
-            strictlyEnforceWorkspaceRulesDescription: 'Tutte le regole dello spazio di lavoro devono essere soddisfatte prima di inviare un rapporto. Non sono consentite eccezioni manuali.',
-            restrictExpenseWorkspaceCreation: 'Limita la creazione/rimozione dell’area di lavoro spese',
-            restrictExpenseWorkspaceCreationDescription:
-                'Impedisci ai membri di poter creare un’area di lavoro spese o di rimuoversi da un’area di lavoro spese. Questo è utile per impedire alle persone di utilizzare Expensify per inviare report destinati a un uso al di fuori del tuo dominio, se combinato con un’applicazione rigorosa dell’area di lavoro.',
-            deleteGroup: 'Elimina gruppo',
-            deleteGroupDangerConfirmationModal: 'Elimina gruppo',
-            deleteGroupDangerConfirmationModalDescription: (defaultGroupName: string) =>
-                `Sei sicuro? Questo riassegnerà tutti i membri al gruppo predefinito (${defaultGroupName}) e non potrà essere annullato.`,
-            deleteGroupError: 'Impossibile eliminare questo gruppo. Riprova.',
-            preferredWorkspace: 'Spazio di lavoro preferito',
-            preferredWorkspaceDescription: (enabled: boolean) =>
-                `Tutti i nuovi report e le spese verranno creati ${enabled ? 'nello spazio di lavoro preferito selezionato' : 'in questo spazio di lavoro'}.`,
-            preferredWorkspaceSelectDescription: 'Tutte le nuove spese e i report verranno creati in questo spazio di lavoro.',
-            noWorkspacesMessage: 'Non ci sono spazi di lavoro su questo dominio. È necessario uno spazio di lavoro per abilitare questa restrizione.',
-            restrictDefaultLoginSelection: 'Limita la selezione di accesso predefinita',
-            restrictDefaultLoginSelectionDescription: 'Impedisce ai membri di modificare l’email di accesso al di fuori del dominio aziendale per eludere le restrizioni delle policy.',
-            expensifyCardPreferredWorkspaceDisabledMessage:
-                'Per abilitare questa impostazione, abilita prima uno spazio di lavoro preferito e configura le Expensify Card per il tuo dominio.',
-            findGroup: 'Trova gruppo',
-        },
-    },
-    proactiveAppReview: {
-        title: 'Ti piace il nuovo Expensify?',
-        description: 'Facci sapere così possiamo aiutarti a rendere ancora migliore la tua esperienza di gestione delle spese.',
-        positiveButton: 'Sì!',
-        negativeButton: 'Non proprio',
-    },
-    monthPickerPage: {month: 'Mese', selectMonth: 'Seleziona un mese'},
+    },
 };
 export default translations;
diff --git a/src/languages/ja.ts b/src/languages/ja.ts
index b06df1610df3..f341ce2106eb 100644
--- a/src/languages/ja.ts
+++ b/src/languages/ja.ts
@@ -11,52 +11,189 @@
  */
 import {CONST as COMMON_CONST} from 'expensify-common';
 import startCase from 'lodash/startCase';
-import type {ValueOf} from 'type-fest';
 import type {OnboardingTask} from '@libs/actions/Welcome/OnboardingFlow';
 import StringUtils from '@libs/StringUtils';
 import dedent from '@libs/StringUtils/dedent';
 import CONST from '@src/CONST';
 import type {Country} from '@src/CONST';
 import type OriginalMessage from '@src/types/onyx/OriginalMessage';
-import type {OriginalMessageSettlementAccountLocked, PersonalRulesModifiedFields, PolicyRulesModifiedFields} from '@src/types/onyx/OriginalMessage';
+import type {OriginalMessageSettlementAccountLocked, PolicyRulesModifiedFields} from '@src/types/onyx/OriginalMessage';
+import ObjectUtils from '@src/types/utils/ObjectUtils';
 import type en from './en';
 import type {
+    AddBudgetParams,
+    AddedOrDeletedPolicyReportFieldParams,
+    AddOrDeletePolicyCustomUnitRateParams,
     ChangeFieldParams,
-    ConciergeBrokenCardConnectionParams,
     ConnectionNameParams,
+    CreatedReportForUnapprovedTransactionsParams,
     DelegateRoleParams,
     DeleteActionParams,
+    DeleteBudgetParams,
     DeleteConfirmationParams,
     EditActionParams,
     ExportAgainModalDescriptionParams,
     ExportIntegrationSelectedParams,
+    ImportPolicyCustomUnitRatesParams,
     IntacctMappingTitleParams,
     InvalidPropertyParams,
     InvalidValueParams,
     MarkReimbursedFromIntegrationParams,
     MissingPropertyParams,
     MovedFromPersonalSpaceParams,
+    MultifactorAuthenticationTranslationParams,
+    NextStepParams,
     NotAllowedExtensionParams,
     OptionalParam,
     PaidElsewhereParams,
     ParentNavigationSummaryParams,
     RemovedFromApprovalWorkflowParams,
+    RemovedPolicyCustomUnitSubRateParams,
     ReportArchiveReasonsClosedParams,
     ReportArchiveReasonsInvoiceReceiverPolicyDeletedParams,
     ReportArchiveReasonsMergedParams,
     ReportArchiveReasonsRemovedFromPolicyParams,
+    ReportFieldParams,
+    ReportPolicyNameParams,
+    RequestAmountParams,
+    RequiredFieldParams,
     ResolutionConstraintsParams,
+    ReviewParams,
+    RoleNamesParams,
+    RoomNameReservedErrorParams,
+    RoomRenamedToParams,
+    RoutedDueToDEWParams,
+    RulesEnableWorkflowsParams,
+    SecondaryLoginParams,
+    SetTheDistanceMerchantParams,
+    SetTheRequestParams,
+    SettledAfterAddedBankAccountParams,
+    SettleExpensifyCardParams,
+    SettlementAccountInfoParams,
+    SettlementAccountReconciliationParams,
+    SettlementDateParams,
     ShareParams,
+    SignerInfoMessageParams,
+    SignUpNewFaceCodeParams,
     SizeExceededParams,
+    SplitAmountParams,
+    SplitDateRangeParams,
+    SplitExpenseEditTitleParams,
+    SplitExpenseSubtitleParams,
+    StatementTitleParams,
     StepCounterParams,
+    StripePaidParams,
+    SubmitsToParams,
+    SubmittedToVacationDelegateParams,
+    SubmittedWithMemoParams,
+    SubscriptionCommitmentParams,
+    SubscriptionSettingsLearnMoreParams,
+    SubscriptionSettingsRenewsOnParams,
+    SubscriptionSettingsSaveUpToParams,
+    SubscriptionSettingsSummaryParams,
+    SubscriptionSizeParams,
     SyncStageNameConnectionsParams,
+    TaskCreatedActionParams,
+    TaxAmountParams,
+    TermsParams,
+    ThreadRequestReportNameParams,
+    ThreadSentMoneyReportNameParams,
+    ToggleImportTitleParams,
+    TotalAmountGreaterOrLessThanOriginalParams,
+    ToValidateLoginParams,
+    TransferParams,
+    TravelTypeParams,
+    TrialStartedTitleParams,
+    UnapproveWithIntegrationWarningParams,
     UnshareParams,
-    UnsupportedFormulaValueErrorParams,
+    UntilTimeParams,
+    UpdatedBudgetParams,
+    UpdatedCustomFieldParams,
+    UpdatedPolicyApprovalRuleParams,
+    UpdatedPolicyAuditRateParams,
+    UpdatedPolicyAutoHarvestingParams,
+    UpdatedPolicyBudgetNotificationParams,
+    UpdatedPolicyCategoriesParams,
+    UpdatedPolicyCategoryDescriptionHintTypeParams,
+    UpdatedPolicyCategoryExpenseLimitTypeParams,
+    UpdatedPolicyCategoryGLCodeParams,
+    UpdatedPolicyCategoryMaxAmountNoReceiptParams,
+    UpdatedPolicyCategoryMaxExpenseAmountParams,
+    UpdatedPolicyCategoryNameParams,
+    UpdatedPolicyCategoryParams,
+    UpdatedPolicyCurrencyParams,
+    UpdatedPolicyCustomUnitRateEnabledParams,
+    UpdatedPolicyCustomUnitRateParams,
+    UpdatedPolicyCustomUnitSubRateParams,
+    UpdatedPolicyCustomUnitTaxClaimablePercentageParams,
+    UpdatedPolicyCustomUnitTaxRateExternalIDParams,
+    UpdatedPolicyDefaultTitleParams,
+    UpdatedPolicyDescriptionParams,
+    UpdatedPolicyFieldWithNewAndOldValueParams,
+    UpdatedPolicyFieldWithValueParams,
+    UpdatedPolicyFrequencyParams,
+    UpdatedPolicyManualApprovalThresholdParams,
+    UpdatedPolicyOwnershipParams,
+    UpdatedPolicyPreventSelfApprovalParams,
+    UpdatedPolicyReimbursementChoiceParams,
+    UpdatedPolicyReimbursementEnabledParams,
+    UpdatedPolicyReimburserParams,
+    UpdatedPolicyReportFieldDefaultValueParams,
+    UpdatedPolicyTagFieldParams,
+    UpdatedPolicyTagListParams,
+    UpdatedPolicyTagListRequiredParams,
+    UpdatedPolicyTagNameParams,
+    UpdatedPolicyTagParams,
+    UpdatedPolicyTaxParams,
+    UpdatedPolicyTimeEnabledParams,
+    UpdatedPolicyTimeRateParams,
+    UpdatedTheDistanceMerchantParams,
+    UpdatedTheRequestParams,
+    UpdatePolicyCustomUnitDefaultCategoryParams,
+    UpdatePolicyCustomUnitParams,
+    UpdatePolicyCustomUnitTaxEnabledParams,
     UpdateRoleParams,
-    ViolationsIncreasedDistanceParams,
+    UpgradeSuccessMessageParams,
+    UsePlusButtonParams,
+    UserIsAlreadyMemberParams,
+    UserSplitParams,
+    VacationDelegateParams,
+    ViolationsCashExpenseWithNoReceiptParams,
+    ViolationsConversionSurchargeParams,
+    ViolationsCustomRulesParams,
+    ViolationsInvoiceMarkupParams,
+    ViolationsMaxAgeParams,
+    ViolationsMissingTagParams,
     ViolationsModifiedAmountParams,
+    ViolationsOverCategoryLimitParams,
+    ViolationsOverLimitParams,
+    ViolationsPerDayLimitParams,
+    ViolationsProhibitedExpenseParams,
+    ViolationsReceiptRequiredParams,
+    ViolationsRterParams,
+    ViolationsTagOutOfPolicyParams,
+    ViolationsTaxOutOfPolicyParams,
+    WaitingOnBankAccountParams,
+    WalletAgreementParams,
+    WalletProgramParams,
+    WelcomeEnterMagicCodeParams,
+    WelcomeToRoomParams,
+    WeSentYouMagicSignInLinkParams,
+    WorkEmailMergingBlockedParams,
+    WorkEmailResendCodeParams,
+    WorkflowSettingsParam,
     WorkspaceLockedPlanTypeParams,
+    WorkspaceMemberList,
+    WorkspaceMembersCountParams,
+    WorkspaceOwnerWillNeedToAddOrUpdatePaymentCardParams,
+    WorkspaceRouteParams,
+    WorkspaceShareNoteParams,
+    WorkspacesListRouteParams,
+    WorkspaceUpgradeNoteParams,
+    WorkspaceYouMayJoin,
     YourPlanPriceParams,
+    YourPlanPriceValueParams,
+    ZipCodeExampleFormatParams,
 } from './params';
 import type {TranslationDeepObject} from './types';
 
@@ -90,10 +227,8 @@ const translations: TranslationDeepObject<typeof en> = {
         optional: '任意',
         new: '新規',
         newFeature: '新機能',
-        beta: 'ベータ',
         search: '検索',
         reports: 'レポート',
-        spend: '支出',
         find: '検索',
         searchWithThreeDots: '検索…',
         next: '次へ',
@@ -118,14 +253,6 @@ const translations: TranslationDeepObject<typeof en> = {
         workspaces: 'ワークスペース',
         home: 'ホーム',
         inbox: '受信トレイ',
-        yourReviewIsRequired: '確認が必要です',
-        actionBadge: {
-            submit: '送信',
-            approve: '承認する',
-            pay: '支払う',
-            fix: '修正',
-            task: 'タスク',
-        },
         success: '成功しました',
         group: 'グループ',
         profile: 'プロフィール',
@@ -135,7 +262,7 @@ const translations: TranslationDeepObject<typeof en> = {
         wallet: 'ウォレット',
         preferences: '設定',
         view: '表示',
-        review: (amount?: string) => `レビュー${amount ? ` ${amount}` : ''}`,
+        review: (reviewParams?: ReviewParams) => `レビュー${reviewParams?.amount ? ` ${reviewParams?.amount}` : ''}`,
         not: 'いいえ',
         signIn: 'サインイン',
         signInWithGoogle: 'Googleでログイン',
@@ -146,7 +273,6 @@ const translations: TranslationDeepObject<typeof en> = {
         lastName: '姓',
         scanning: 'スキャン中',
         analyzing: '分析中…',
-        thinking: 'Concierge が考えています...',
         addCardTermsOfService: 'Expensify 利用規約',
         perPerson: '1人あたり',
         phone: '電話',
@@ -208,12 +334,10 @@ const translations: TranslationDeepObject<typeof en> = {
         admin: '管理者',
         owner: 'オーナー',
         dateFormat: 'YYYY-MM-DD',
-        calendarOpened: 'カレンダーが開きました',
         send: '送信',
         na: '該当なし',
         noResultsFound: '結果が見つかりません',
         noResultsFoundMatching: (searchString: string) => `"${searchString}" に一致する結果は見つかりませんでした`,
-        suggestionsAvailableFor: (searchString: string) => (searchString ? `「${searchString}」の候補が利用可能です。` : '候補が利用可能です。'),
         recentDestinations: '最近の宛先',
         timePrefix: 'それは',
         conjunctionFor: '〜用',
@@ -224,7 +348,6 @@ const translations: TranslationDeepObject<typeof en> = {
         conjunctionTo: '宛先',
         genericErrorMessage: 'おっと…問題が発生したため、リクエストを完了できませんでした。時間をおいてもう一度お試しください。',
         percentage: 'パーセンテージ',
-        progressBarLabel: 'オンボーディング進捗',
         converted: '変換済み',
         error: {
             invalidAmount: '金額が無効です',
@@ -263,7 +386,6 @@ const translations: TranslationDeepObject<typeof en> = {
         reset: 'リセット',
         done: '完了',
         more: 'その他',
-        other: 'その他',
         debitCard: 'デビットカード',
         bankAccount: '銀行口座',
         personalBankAccount: '個人銀行口座',
@@ -289,7 +411,7 @@ const translations: TranslationDeepObject<typeof en> = {
         verify: '確認',
         yesContinue: 'はい、続行',
         websiteExample: '例：https://www.expensify.com',
-        zipCodeExampleFormat: (zipSampleFormat: string) => (zipSampleFormat ? `例：${zipSampleFormat}` : ''),
+        zipCodeExampleFormat: ({zipSampleFormat}: ZipCodeExampleFormatParams) => (zipSampleFormat ? `例：${zipSampleFormat}` : ''),
         description: '説明',
         title: 'タイトル',
         assignee: '担当者',
@@ -300,8 +422,6 @@ const translations: TranslationDeepObject<typeof en> = {
         per: 'あたり',
         mi: 'マイル',
         km: 'キロメートル',
-        milesAbbreviated: 'マイル',
-        kilometersAbbreviated: 'キロ',
         copied: 'コピーしました！',
         someone: '誰か',
         total: '合計',
@@ -310,7 +430,6 @@ const translations: TranslationDeepObject<typeof en> = {
         letsStart: `はじめましょう`,
         showMore: 'さらに表示',
         showLess: '表示を減らす',
-        plusMore: ({count}: {count: number}) => `+${count}件`,
         merchant: '加盟店',
         change: '変更',
         category: 'カテゴリ',
@@ -334,11 +453,8 @@ const translations: TranslationDeepObject<typeof en> = {
         selectCurrency: '通貨を選択',
         selectSymbolOrCurrency: '記号または通貨を選択',
         card: 'カード',
-        mcc: 'MCC',
-        categoryGLCode: 'カテゴリGLコード',
         whyDoWeAskForThis: 'なぜこの情報が必要なのですか？',
         required: '必須',
-        automatic: '自動',
         showing: '表示中',
         of: 'の',
         default: 'デフォルト',
@@ -346,7 +462,6 @@ const translations: TranslationDeepObject<typeof en> = {
         member: 'メンバー',
         auditor: '監査人',
         role: '役割',
-        roleCannotBeChanged: (workflowsLinkPage: string) => `このメンバーはこのワークスペースの<a href="${workflowsLinkPage}">支払者</a>であるため、役割を変更できません。`,
         currency: '通貨',
         groupCurrency: 'グループ通貨',
         rate: '評価',
@@ -384,7 +499,6 @@ const translations: TranslationDeepObject<typeof en> = {
         reportID: 'レポートID',
         longReportID: '長いレポートID',
         withdrawalID: '出金ID',
-        withdrawalStatus: '出金ステータス',
         bankAccounts: '銀行口座',
         chooseFile: 'ファイルを選択',
         chooseFiles: 'ファイルを選択',
@@ -418,21 +532,19 @@ const translations: TranslationDeepObject<typeof en> = {
         validate: '検証',
         downloadAsPDF: 'PDFとしてダウンロード',
         downloadAsCSV: 'CSVとしてダウンロード',
-        print: '印刷',
         help: 'ヘルプ',
-        collapsed: '折りたたみ',
-        expanded: '展開',
         expenseReport: '経費精算書',
-        rateOutOfPolicy: 'ポリシー外の料率',
+        expenseReports: '経費レポート',
+        rateOutOfPolicy: 'ポリシー対象外のレート',
         leaveWorkspace: 'ワークスペースから退出',
         leaveWorkspaceConfirmation: 'このワークスペースを退出すると、そこへ経費を提出できなくなります。',
         leaveWorkspaceConfirmationAuditor: 'このワークスペースを退出すると、そのレポートや設定を表示できなくなります。',
         leaveWorkspaceConfirmationAdmin: 'このワークスペースを退出すると、その設定を管理できなくなります。',
-        leaveWorkspaceConfirmationApprover: (workspaceOwner: string) =>
+        leaveWorkspaceConfirmationApprover: ({workspaceOwner}: {workspaceOwner: string}) =>
             `このワークスペースを退出すると、あなたの承認ワークフロー上での役割はワークスペースのオーナーである${workspaceOwner}に引き継がれます。`,
-        leaveWorkspaceConfirmationExporter: (workspaceOwner: string) =>
+        leaveWorkspaceConfirmationExporter: ({workspaceOwner}: {workspaceOwner: string}) =>
             `このワークスペースを退出すると、優先エクスポーターとしてあなたの代わりにワークスペースのオーナーである${workspaceOwner}が設定されます。`,
-        leaveWorkspaceConfirmationTechContact: (workspaceOwner: string) =>
+        leaveWorkspaceConfirmationTechContact: ({workspaceOwner}: {workspaceOwner: string}) =>
             `このワークスペースを退出すると、あなたに代わってワークスペースのオーナーである${workspaceOwner}が技術連絡先になります。`,
         leaveWorkspaceReimburser:
             '支払担当者であるため、このワークスペースを退出することはできません。［ワークスペース］＞［支払いの作成または追跡］で新しい支払担当者を設定してから、もう一度お試しください。',
@@ -441,6 +553,9 @@ const translations: TranslationDeepObject<typeof en> = {
         comments: 'コメント',
         sharedIn: '共有元',
         unreported: '未報告',
+        explore: '探索',
+        insights: 'インサイト',
+        todo: 'To-do',
         invoice: '請求書',
         expense: '経費',
         chat: 'チャット',
@@ -451,15 +566,12 @@ const translations: TranslationDeepObject<typeof en> = {
         on: 'オン',
         before: '前',
         after: '後',
-        range: '範囲',
         reschedule: '予定を変更',
         general: '一般',
         workspacesTabTitle: 'ワークスペース',
         headsUp: 'ご注意ください！',
         submitTo: '提出先',
         forwardTo: '転送先',
-        approvalLimit: '承認限度額',
-        overLimitForwardTo: '限度額超過時の転送先',
         merge: 'マージ',
         none: 'なし',
         unstableInternetConnection: 'インターネット接続が不安定です。ネットワークを確認して、もう一度お試しください。',
@@ -480,47 +592,19 @@ const translations: TranslationDeepObject<typeof en> = {
         exchangeRate: '為替レート',
         reimbursableTotal: '精算対象合計',
         nonReimbursableTotal: '未払い対象外の合計',
-        opensInNewTab: '新しいタブで開きます',
         locked: 'ロックされています',
         month: '月',
         week: '週',
         year: '年',
         quarter: '四半期',
-        vacationDelegate: '休暇代理人',
-        expensifyLogo: 'Expensifyロゴ',
-        concierge: {greeting: 'こんにちは、どのようにお手伝いできますか？', showHistory: '履歴を表示'},
-        duplicateReport: 'レポートを複製',
-        approver: '承認者',
-        goToConcierge: 'Conciergeへ移動',
-        allSet: 'すべて完了！',
-        enterDigitLabel: ({digitIndex, totalDigits}: {digitIndex: number; totalDigits: number}) => `${totalDigits}桁中${digitIndex}桁目を入力`,
-        copyOfReportName: (reportName: string) => `${reportName} のコピー`,
-        previousMonth: '前月',
-        nextMonth: '来月',
-        previousYear: '前年',
-        nextYear: '来年',
-        avatar: 'アバター',
-        editor: '編集者',
-        restrictions: '制限',
-    },
-    socials: {
-        podcast: 'ポッドキャストでフォロー',
-        twitter: 'Twitterでフォロー',
-        instagram: 'Instagramでフォロー',
-        facebook: 'Facebookでフォロー',
-        linkedin: 'LinkedInでフォロー',
-    },
-    concierge: {
-        collapseReasoning: '推論を折りたたむ',
-        expandReasoning: '推論を展開',
-        enableNotifications: {
-            prompt: 'Conciergeから返信があったときに通知を受け取りますか？',
-            cta: '通知',
-        },
     },
     supportalNoAccess: {
         title: 'ちょっと待ってください',
-        descriptionWithCommand: (command?: string) =>
+        descriptionWithCommand: ({
+            command,
+        }: {
+            command?: string;
+        } = {}) =>
             `サポートとしてログインしている場合、この操作を行う権限がありません（コマンド: ${command ?? ''}）。Success がこの操作を行えるようにすべきだと思われる場合は、Slack で会話を開始してください。`,
     },
     lockedAccount: {
@@ -556,7 +640,7 @@ const translations: TranslationDeepObject<typeof en> = {
         chooseDocument: 'ファイルを選択',
         attachmentTooLarge: '添付ファイルが大きすぎます',
         sizeExceeded: '添付ファイルのサイズが24MBの上限を超えています',
-        sizeExceededWithLimit: (maxUploadSizeInMB: number) => `添付ファイルのサイズが上限の ${maxUploadSizeInMB} MB を超えています`,
+        sizeExceededWithLimit: ({maxUploadSizeInMB}: SizeExceededParams) => `添付ファイルのサイズが上限の ${maxUploadSizeInMB} MB を超えています`,
         attachmentTooSmall: '添付ファイルが小さすぎます',
         sizeNotMet: '添付ファイルのサイズは240バイトより大きくする必要があります',
         wrongFileType: '無効なファイル形式',
@@ -567,9 +651,9 @@ const translations: TranslationDeepObject<typeof en> = {
         attachmentImageTooLarge: 'この画像は大きすぎるため、アップロード前にプレビューできません。',
         imageDimensionsTooLarge: '画像のサイズが大きすぎて処理できません。小さい画像を使用してください。',
         tooManyFiles: (fileLimit: number) => `一度にアップロードできるファイルは最大${fileLimit}件までです。`,
-        sizeExceededWithValue: (maxUploadSizeInMB: number) => `ファイルが ${maxUploadSizeInMB} MB を超えています。もう一度お試しください。`,
+        sizeExceededWithValue: ({maxUploadSizeInMB}: SizeExceededParams) => `ファイルが ${maxUploadSizeInMB} MB を超えています。もう一度お試しください。`,
         someFilesCantBeUploaded: '一部のファイルをアップロードできません',
-        sizeLimitExceeded: (maxUploadSizeInMB: number) => `ファイルサイズは${maxUploadSizeInMB}MB以下である必要があります。これより大きいファイルはアップロードされません。`,
+        sizeLimitExceeded: ({maxUploadSizeInMB}: SizeExceededParams) => `ファイルサイズは${maxUploadSizeInMB}MB以下である必要があります。これより大きいファイルはアップロードされません。`,
         maxFileLimitExceeded: '一度にアップロードできるレシートは最大30枚です。超過分はアップロードされません。',
         unsupportedFileType: (fileType: string) => `${fileType} ファイルはサポートされていません。サポートされているファイルタイプのみアップロードされます。`,
         learnMoreAboutSupportedFiles: '対応している形式の詳細を確認する',
@@ -609,46 +693,17 @@ const translations: TranslationDeepObject<typeof en> = {
         signIn: 'もう一度サインインしてください。',
     },
     multifactorAuthentication: {
-        reviewTransaction: {
-            reviewTransaction: '取引を確認',
-            pleaseReview: 'この取引を確認してください',
-            requiresYourReview: 'Expensifyカードの取引が、以下の内容であなたの確認を必要としています。',
-            transactionDetails: '取引の詳細',
-            deny: '拒否',
-            approve: '承認',
-            denyTransaction: '取引を却下',
-            transactionDenied: '取引が拒否されました',
-            transactionApproved: '取引が承認されました！',
-            areYouSureToDeny: 'よろしいですか？この画面を閉じると、その取引は拒否されます。',
-            youCanTryAgainAtMerchantOrReachOut:
-                '加盟店でもう一度お試しください。もしこの取引に心当たりがない場合は、不正の可能性がありますので、<concierge-link>Concierge に連絡してください</concierge-link>。',
-            youNeedToTryAgainAtMerchant: 'この取引は未認証のため、拒否されました。再度加盟店でお試しください。',
-            goBackToTheMerchant: '取引を続行するには、加盟店のサイトに戻ってください。',
-            attemptedTransaction: '試行された取引',
-            transactionFailed: '取引に失敗しました',
-            transactionCouldNotBeCompleted: '取引を完了できませんでした。加盟店で再度お試しください。',
-            transactionCouldNotBeCompletedReachOut:
-                '取引を完了できませんでした。心当たりのない取引の場合は、不正の可能性がありますので、<concierge-link>Conciergeに連絡してください</concierge-link>。',
-            reviewFailed: 'レビューに失敗しました',
-            alreadyReviewedSubtitle:
-                'この取引はすでに確認済みです。問題がある場合は、<transaction-history-link>取引履歴</transaction-history-link>をご確認いただくか、<concierge-link>Concierge</concierge-link>までご連絡ください。',
-        },
         biometricsTest: {
             biometricsTest: '生体認証テスト',
             authenticationSuccessful: '認証に成功しました',
-            successfullyAuthenticatedUsing: (authType?: string) => `${authType} を使用して正常に認証されました。`,
-            troubleshootBiometricsStatus: ({status}: {status?: string}) => `生体認証（${status}）`,
+            successfullyAuthenticatedUsing: ({authType}: MultifactorAuthenticationTranslationParams) => `${authType} を使用して正常に認証されました。`,
+            troubleshootBiometricsStatus: ({registered}: MultifactorAuthenticationTranslationParams) => `生体認証（${registered ? '登録済み' : '未登録'}）`,
             yourAttemptWasUnsuccessful: '認証を試みましたが、成功しませんでした。',
             youCouldNotBeAuthenticated: '認証できませんでした',
             areYouSureToReject: '本当に終了しますか？この画面を閉じると、認証の試行は拒否されます。',
             rejectAuthentication: '認証を拒否',
             test: 'テスト',
             biometricsAuthentication: '生体認証',
-            authType: {unknown: '不明', none: 'なし', credentials: '資格情報', biometrics: '生体認証', faceId: 'Face ID', touchId: 'Touch ID', opticId: 'Optic ID', passkey: 'Passkey'},
-            statusNeverRegistered: '未登録',
-            statusNotRegistered: '未登録',
-            statusRegisteredThisDevice: '登録済み',
-            statusRegisteredOtherDevice: () => ({one: '別のデバイスが登録されました', other: '登録済みの他のデバイス'}),
         },
         pleaseEnableInSystemSettings: {
             start: '顔認証/指紋認証を有効にするか、デバイスのパスコードを設定してください',
@@ -661,41 +716,26 @@ const translations: TranslationDeepObject<typeof en> = {
         letsVerifyItsYou: 'ご本人確認を行いましょう',
         nowLetsAuthenticateYou: 'では、ご本人確認を行いましょう…',
         letsAuthenticateYou: '認証を行っています…',
-        verifyYourself: {biometrics: '顔または指紋で本人確認を行ってください', passkeys: 'パスキーで本人確認を行います'},
+        verifyYourself: {
+            biometrics: '顔または指紋で本人確認を行ってください',
+        },
         enableQuickVerification: {
             biometrics: '顔や指紋を使って、素早く安全に認証できます。パスワードやコードは不要です。',
-            passkeys: 'パスキーを使って、素早く安全に認証できるようにします。パスワードやコードは不要です。',
         },
         revoke: {
-            title: '顔／指紋 & パスキー',
-            explanation: '1 台以上の端末で顔／指紋またはパスキー認証が有効になっています。アクセスを取り消すと、その端末で次回認証する際にマジックコードが必要になります。',
-            confirmationPrompt: '本当によろしいですか？そのデバイスで次回の認証を行うには、マジックコードが必要になります。',
+            remove: '削除',
+            title: '顔認証／指紋認証とパスキー',
+            explanation: '1 つ以上のデバイスで顔／指紋またはパスキーによる認証が有効になっています。アクセスを取り消すと、次回どのデバイスで認証する場合もマジックコードが必要になります。',
+            confirmationPrompt: '本当に実行しますか？次回以降、どのデバイスでも認証にはマジックコードが必要になります。',
             cta: 'アクセスを取り消す',
-            noDevices: '顔認証・指紋認証またはパスキー認証に登録されているデバイスがありません。デバイスを登録すると、そのアクセス権をここで取り消すことができるようになります。',
+            noDevices: '顔認証／指紋認証またはパスキー認証用に登録されているデバイスがありません。デバイスを登録すると、そのアクセスをここで取り消せるようになります。',
             dismiss: '了解しました',
             error: 'リクエストに失敗しました。後でもう一度お試しください。',
-            revoke: '取り消す',
-            confirmationPromptAll: '本当に実行してよろしいですか？今後どの端末でも、次回の認証にはマジックコードが必要になります。',
-            ctaAll: 'すべて取り消す',
-            thisDevice: 'このデバイス',
-            otherDevices: (otherDeviceCount?: number) => {
-                const numberWords = ['1', '二', '三', '四', '五', '六', '七', '8', '9'];
-                const displayCount = otherDeviceCount !== undefined && otherDeviceCount >= 1 && otherDeviceCount <= 9 ? numberWords.at(otherDeviceCount - 1) : `${otherDeviceCount}`;
-                return `その他${displayCount}件の${otherDeviceCount === 1 ? 'デバイス' : 'デバイス'}`;
-            },
-            confirmationPromptThisDevice: '本当によろしいですか？このデバイスで次回の認証を行うには、マジックコードが必要になります。',
-            confirmationPromptMultiple: 'よろしいですか？その端末で次回の認証を行うには、マジックコードが必要になります。',
         },
         unsupportedDevice: {
             unsupportedDevice: '未対応のデバイス',
-            pleaseDownloadMobileApp: `この操作はお使いのデバイスではサポートされていません。<a href="${CONST.APP_DOWNLOAD_LINKS.IOS}">App Store</a> または <a href="${CONST.APP_DOWNLOAD_LINKS.ANDROID}">Google Playストア</a> からExpensifyアプリをダウンロードして、もう一度お試しください。`,
-            pleaseUseWebApp: `この操作はお使いのデバイスではサポートされていません。<a href="${CONST.NEW_EXPENSIFY_URL}">Expensifyウェブアプリ</a>をご利用のうえ、もう一度お試しください。`,
+            pleaseDownloadMobileApp: `<centered-text><muted-text> この操作はお使いのデバイスではサポートされていません。<a href="${CONST.APP_DOWNLOAD_LINKS.IOS}">App Store</a> または <a href="${CONST.APP_DOWNLOAD_LINKS.ANDROID}">Google Playストア</a> からExpensifyアプリをダウンロードして、もう一度お試しください。</muted-text></centered-text>`,
         },
-        verificationFailed: '認証に失敗しました',
-        setPin: {didNotShipCard: 'カードを発送できませんでした。もう一度お試しください。'},
-        revealPin: {couldNotReveal: 'PIN を表示できませんでした。もう一度お試しください。'},
-        changePin: {didNotChange: 'お客様の暗証番号は変更されていません。もう一度お試しください。'},
-        revealCardDetail: {couldNotReveal: 'カード情報を表示できませんでした。もう一度お試しください。'},
     },
     validateCodeModal: {
         successfulSignInTitle: dedent(`
@@ -732,7 +772,11 @@ const translations: TranslationDeepObject<typeof en> = {
         nameEmailOrPhoneNumber: '名前、メールアドレス、または電話番号',
         findMember: 'メンバーを検索',
         searchForSomeone: '誰かを検索',
-        userSelected: (username: string) => `${username} 選択された`,
+    },
+    customApprovalWorkflow: {
+        title: 'カスタム承認ワークフロー',
+        description: 'このワークスペースでは、あなたの会社がカスタム承認ワークフローを使用しています。Expensify Classic でこの操作を行ってください',
+        goToExpensifyClassic: 'Expensify Classic に切り替える',
     },
     emptyList: {
         [CONST.IOU.TYPE.CREATE]: {
@@ -754,8 +798,8 @@ const translations: TranslationDeepObject<typeof en> = {
         phrase2: 'お金のことは、話せば早い。チャットと支払いがひとつになった今、そのやり取りもかんたんです。',
         phrase3: 'あなたが要点を伝える速さで、支払いもあなたのもとに届きます。',
         enterPassword: 'パスワードを入力してください',
-        welcomeNewFace: (login: string) => `${login} さん、ここで新しい顔にお会いできるのはいつでもうれしいです！`,
-        welcomeEnterMagicCode: (login: string) => `${login} に送信されたマジックコードを入力してください。1～2分以内に届きます。`,
+        welcomeNewFace: ({login}: SignUpNewFaceCodeParams) => `${login} さん、ここで新しい顔にお会いできるのはいつでもうれしいです！`,
+        welcomeEnterMagicCode: ({login}: WelcomeEnterMagicCodeParams) => `${login} に送信されたマジックコードを入力してください。1～2分以内に届きます。`,
     },
     login: {
         hero: {
@@ -783,9 +827,6 @@ const translations: TranslationDeepObject<typeof en> = {
         emoji: '絵文字',
         collapse: '折りたたむ',
         expand: '展開',
-        askConciergeToUpdate: '「経費を更新」と入力してみてください…',
-        askConciergeToCorrect: '「経費を修正」と入力してみてください…',
-        askConciergeForHelp: 'Concierge AI にヘルプを依頼…',
     },
     reportActionContextMenu: {
         copyMessage: 'メッセージをコピー',
@@ -849,9 +890,9 @@ const translations: TranslationDeepObject<typeof en> = {
         askMeAnything: '何でも聞いてください！',
         sayHello: '挨拶しよう！',
         yourSpace: 'あなたのスペース',
-        welcomeToRoom: (roomName: string) => `${roomName} へようこそ！`,
-        usePlusButton: (additionalText: string) => `+ ボタンを使って経費を${additionalText}します。`,
-        askConcierge: 'Concierge は、質問にお答えしたり、経費を更新したり、さまざまなことができます。',
+        welcomeToRoom: ({roomName}: WelcomeToRoomParams) => `${roomName} へようこそ！`,
+        usePlusButton: ({additionalText}: UsePlusButtonParams) => `+ ボタンを使って経費を${additionalText}します。`,
+        askConcierge: '何でも聞いてください！',
         conciergeSupport: 'あなた専用のAIエージェント',
         create: '作成',
         iouTypes: {
@@ -863,17 +904,12 @@ const translations: TranslationDeepObject<typeof en> = {
         },
     },
     adminOnlyCanPost: 'このルームでメッセージを送信できるのは管理者のみです。',
-    readOnlyConversation: 'この会話は読み取り専用です。',
     reportAction: {
         asCopilot: '共同操縦者として',
-        assistedBy: (agentName: string) => `${agentName}がアシスト`,
-        humanSupportAgent: 'サポート担当者',
         harvestCreatedExpenseReport: (reportUrl: string, reportName: string) =>
             `選択した頻度で提出できなかった、<a href="${reportUrl}">${reportName}</a> のすべての経費を保持するためにこのレポートを作成しました`,
-        createdReportForUnapprovedTransactions: (reportUrl: string, reportName: string, reportID: string, isReportDeleted: boolean) =>
-            isReportDeleted
-                ? `削除されたレポート #${reportID} に保留されていた経費のためにこのレポートを作成しました`
-                : `<a href="${reportUrl}">${reportName}</a> の保留中経費すべてに対してこのレポートを作成しました`,
+        createdReportForUnapprovedTransactions: ({reportUrl, reportName}: CreatedReportForUnapprovedTransactionsParams) =>
+            `<a href="${reportUrl}">${reportName}</a> から保留中の経費を対象としてこのレポートを作成しました`,
     },
     mentionSuggestions: {
         hereAlternateText: 'この会話の全員に通知',
@@ -912,6 +948,7 @@ const translations: TranslationDeepObject<typeof en> = {
         buttonFind: '何かを検索…',
         buttonMySettings: '自分の設定',
         fabNewChat: 'チャットを開始',
+        fabNewChatExplained: 'アクションメニューを開く',
         fabScanReceiptExplained: 'レシートをスキャン',
         chatPinned: 'チャットをピン留めしました',
         draftedMessage: '作成中のメッセージ',
@@ -919,41 +956,40 @@ const translations: TranslationDeepObject<typeof en> = {
         listOfChats: 'チャット一覧',
         saveTheWorld: '世界を救う',
         tooltip: 'ここから始めましょう！',
+        redirectToExpensifyClassicModal: {
+            title: '近日公開予定',
+            description: 'お客様の環境に合わせて New Expensify の細かな部分をいくつか調整しているところです。その間は、Expensify Classic をご利用ください。',
+        },
     },
     homePage: {
         forYou: 'あなた向け',
         timeSensitiveSection: {
             title: '時間に敏感',
-            addShippingAddress: {title: '配送先住所が必要です', subtitle: 'Expensify カードを受け取る住所を入力してください。', cta: '住所を追加'},
-            addPaymentCard: {title: 'Expensify を引き続きご利用いただくには、支払いカードを追加してください', subtitle: 'アカウント ＞ サブスクリプション', cta: '追加'},
-            activateCard: {title: 'Expensify カードを有効化する', subtitle: 'カードを認証して支出を始めましょう。', cta: '有効化'},
-            reviewCardFraud: {
-                title: 'Expensify カードの不正利用の可能性を確認する',
-                titleWithDetails: ({amount, merchant}: {amount: string; merchant: string}) => `${merchant} での不正の可能性がある ${amount} を確認`,
-                subtitle: 'Expensify カード',
-                cta: '確認',
+            cta: '申請',
+            offer50off: {
+                title: '初年度が50％オフ！',
+                subtitle: ({formattedTime}: {formattedTime: string}) => `残り${formattedTime}`,
+            },
+            offer25off: {
+                title: '初年度が25％オフになります！',
+                subtitle: ({days}: {days: number}) => `残り ${days} ${days === 1 ? '日' : '日数'} 日`,
+            },
+            addShippingAddress: {
+                title: '配送先住所が必要です',
+                subtitle: 'Expensify Card を受け取る住所を入力してください。',
+                cta: '住所を追加',
+            },
+            activateCard: {
+                title: 'Expensify Card を有効化する',
+                subtitle: 'カードを認証して支出を始めましょう。',
+                cta: '有効化',
             },
             ctaFix: '修正',
             fixCompanyCardConnection: {
                 title: ({feedName}: {feedName: string}) => (feedName ? `${feedName} 会社カード接続を修正` : '法人クレジットカードの接続を修正'),
-                defaultSubtitle: 'ワークスペース',
-                subtitle: ({policyName}: {policyName: string}) => `${policyName} > 会社カード`,
+                subtitle: 'ワークスペース > 会社カード',
             },
-            fixPolicyConnection: {
-                title: ({integrationName}: {integrationName: string}) => `${integrationName} 接続を修正`,
-                defaultSubtitle: 'ワークスペース',
-                subtitle: ({policyName}: {policyName: string}) => `${policyName} > 会計`,
-            },
-            fixPersonalCardConnection: {title: ({cardName}: {cardName?: string}) => (cardName ? `${cardName}個人カードの接続を修正` : '個人カードの連携を修正'), subtitle: 'ウォレット'},
-            validateAccount: {title: 'アカウントを認証してください', subtitle: 'アカウント', cta: '検証する'},
-            fixFailedBilling: {title: '登録されているカードから請求できませんでした', subtitle: 'サブスクリプション'},
-            unlockBankAccount: {
-                workspaceTitle: 'ビジネス用銀行口座がロックされました',
-                personalTitle: 'あなたの銀行口座はロックされています',
-                workspaceSubtitle: ({policyName}: {policyName: string}) => policyName,
-                personalSubtitle: 'ウォレット',
-            },
-            enterSignerInfo: {title: '署名者情報が必要です', subtitle: ({bankAccountLastFour}: {bankAccountLastFour: string}) => `銀行口座 ${bankAccountLastFour}`},
+            fixAccountingConnection: {title: ({integrationName}: {integrationName: string}) => `${integrationName} 接続を修正`, subtitle: 'ワークスペース > 会計'},
         },
         announcements: 'お知らせ',
         discoverSection: {
@@ -969,78 +1005,12 @@ const translations: TranslationDeepObject<typeof en> = {
             export: ({count}: {count: number}) => `${count} 件の ${count === 1 ? 'レポート' : 'レポート'} をエクスポート`,
             begin: '開始',
             emptyStateMessages: {
-                thumbsUpStarsTitle: '完了しました！',
-                thumbsUpStarsDescription: 'この調子です！新しいタスクをお楽しみに。',
-                smallRocketTitle: 'すべて確認済みです',
-                smallRocketDescription: '今後の To-do がここに表示されます。',
-                cowboyHatTitle: '完了しました！',
-                cowboyHatDescription: 'すべてのタスクが片付きました。次のタスクにご注目ください。',
-                trophy1Title: '表示するものがありません',
-                trophy1Description: 'やりました！次の To-do にご注目ください。',
-                palmTreeTitle: 'すべて確認済みです',
-                palmTreeDescription: 'ひと息つく時間ですが、今後のタスクをお楽しみに。',
-                fishbowlBlueTitle: '完了しました！',
-                fishbowlBlueDescription: '今後のタスクがここに表示されます。',
-                targetTitle: 'すべて確認済みです',
-                targetDescription: '目標どおりですね。次のタスクをまた確認してください！',
-                chairTitle: '表示するものがありません',
-                chairDescription: 'ゆっくりおくつろぎください。今後のやることリストはこちらに表示します。',
-                broomTitle: '完了しました！',
-                broomDescription: 'タスクは順調です。新しい To-do をお楽しみに。',
-                houseTitle: 'すべて確認済みです',
-                houseDescription: 'ここが今後のやることのホームベースです。',
-                conciergeBotTitle: '表示するものがありません',
-                conciergeBotDescription: 'ピッピッ、ブッブッ。次のタスクをまた確認してください！',
-                checkboxTextTitle: 'すべて確認済みです',
-                checkboxTextDescription: 'ここで今後のやることにチェックを付けましょう。',
-                flashTitle: '完了しました！',
-                flashDescription: '今後のタスクをここでサッと表示します。',
-                sunglassesTitle: '表示するものがありません',
-                sunglassesDescription: 'ひと休みするときですが、次の予定をお楽しみに！',
-                f1FlagsTitle: 'すべて確認済みです',
-                f1FlagsDescription: 'すべての未処理の To-do が完了しました。',
-            },
-        },
-        upcomingTravel: '今後の出張',
-        upcomingTravelSection: {
-            flightTo: ({destination}: {destination: string}) => `${destination} 行きのフライト`,
-            trainTo: ({destination}: {destination: string}) => `${destination} 行きの電車`,
-            hotelIn: ({destination}: {destination: string}) => `${destination}のホテル`,
-            carRentalIn: ({destination}: {destination: string}) => `${destination}でのレンタカー`,
-            inOneWeek: '1週間後',
-            inDays: () => ({one: '1日後', other: (count: number) => `${count}日後`}),
-            today: '今日',
-        },
-        freeTrialSection: {
-            title: ({days}: {days: number}) => `無料トライアル：あと ${days} ${days === 1 ? '日' : '日数'} 日！`,
-            offer50Body: '初年度が50％オフになります',
-            offer25Body: '初年度が25％オフになります',
-            addCardBody: '支払いカードを追加',
-            ctaClaim: '申請',
-            ctaAdd: 'カードを追加',
-            timeRemaining: ({formattedTime}: {formattedTime: string}) => `残り時間：${formattedTime}`,
-            timeRemainingDays: () => ({
-                one: '残り時間：1日',
-                other: (pluralCount: number) => `残り時間：${pluralCount}日`,
-            }),
-        },
-        gettingStartedSection: {
-            title: 'はじめに',
-            createWorkspace: 'ワークスペースを作成',
-            connectAccounting: ({integrationName}: {integrationName: string}) => `${integrationName}に接続する`,
-            connectAccountingDefault: '会計ソフトに接続',
-            customizeCategories: '会計カテゴリをカスタマイズする',
-            linkCompanyCards: '会社カードを連携',
-            setupRules: '支出ルールを設定',
-            inviteAccountant: '会計士を招待',
-        },
-        yourSpend: {
-            title: 'あなたの支出',
-            awaitingApproval: '承認待ち',
-            repaidLast30Days: '過去30日間に返済済み',
-            recentTransactions: ({lastFour}: {lastFour: string}) => `最近の取引 • ${lastFour}`,
+                nicelyDone: 'よくできました',
+                keepAnEyeOut: '次に何が起こるか楽しみにしていてください！',
+                allCaughtUp: 'すべて確認済みです',
+                upcomingTodos: '今後のTo-doはここに表示されます。',
+            },
         },
-        seeMore: ({count}: {count: number}) => `さらに${count}件表示`,
     },
     allSettingsScreen: {
         subscription: 'サブスクリプション',
@@ -1069,20 +1039,7 @@ const translations: TranslationDeepObject<typeof en> = {
         singleFieldMultipleColumns: (fieldName: string) => `おっと！1 つのフィールド（「${fieldName}」）を複数の列に割り当てています。確認してもう一度お試しください。`,
         emptyMappedField: (fieldName: string) => `おっと！フィールド（「${fieldName}」）に1つ以上の空の値が含まれています。確認してもう一度お試しください。`,
         importSuccessfulTitle: 'インポートに成功しました',
-        importCategoriesSuccessfulDescription: ({added, updated}: {added: number; updated: number}) => {
-            if (!added && !updated) {
-                return 'カテゴリーは追加も更新もされていません。';
-            }
-            if (added && updated) {
-                return `${added}件のカテゴリーを追加し、${updated}件のカテゴリーを更新しました。`;
-            }
-            if (added) {
-                return added === 1 ? 'カテゴリーを1件追加しました。' : `${added}件のカテゴリーを追加しました。`;
-            }
-            return updated === 1 ? 'カテゴリーを1件更新しました。' : `${updated}件のカテゴリーを更新しました。`;
-        },
-        importCompanyCardTransactionsSuccessfulDescription: ({transactions}: {transactions: number}) =>
-            transactions > 1 ? `${transactions} 件の取引が追加されました。` : '1 件の取引が追加されました。',
+        importCategoriesSuccessfulDescription: ({categories}: {categories: number}) => (categories > 1 ? `${categories} 個のカテゴリーを追加しました。` : 'カテゴリが1件追加されました。'),
         importMembersSuccessfulDescription: ({added, updated}: {added: number; updated: number}) => {
             if (!added && !updated) {
                 return 'メンバーは追加も更新もされていません。';
@@ -1114,7 +1071,6 @@ const translations: TranslationDeepObject<typeof en> = {
             other: (count: number) =>
                 `このアップロードで追加される${count}人の新しいワークスペースメンバーについて、以下の内容を確認してください。既存のメンバーには、ロールの更新や招待メッセージは送信されません。`,
         }),
-        importCompanyCardTransactionsPendingMessage: '新しいカードや取引が表示されるまでに少し時間がかかる場合があります。しばらくお待ちください。',
     },
     receipt: {
         upload: '領収書をアップロード',
@@ -1146,9 +1102,7 @@ const translations: TranslationDeepObject<typeof en> = {
         deleteReceipt: '領収書を削除',
         deleteConfirmation: 'この領収書を削除してもよろしいですか？',
         addReceipt: '領収書を追加',
-        addAdditionalReceipt: 'レシートを追加',
         scanFailed: 'このレシートは、店舗名、日付、または金額が不足しているためスキャンできませんでした。',
-        crop: 'トリミング',
         addAReceipt: {
             phrase1: '領収書を追加',
             phrase2: 'または、ここにファイルをドラッグ＆ドロップしてください',
@@ -1168,7 +1122,6 @@ const translations: TranslationDeepObject<typeof en> = {
         noLongerHaveReportAccess: '以前のクイック操作の宛先にはアクセスできなくなりました。下から新しい宛先を選択してください。',
         updateDestination: '送信先を更新',
         createReport: 'レポートを作成',
-        createTimeExpense: '時間経費を作成',
     },
     iou: {
         amount: '金額',
@@ -1188,18 +1141,18 @@ const translations: TranslationDeepObject<typeof en> = {
         split: '分割',
         splitExpense: '経費を分割',
         splitDates: '日付を分割',
-        splitDateRange: (startDate: string, endDate: string, count: number) => `${startDate} から ${endDate}（${count} 日間）`,
-        splitExpenseSubtitle: (amount: string, merchant: string) => `${merchant}からの${amount}`,
+        splitDateRange: ({startDate, endDate, count}: SplitDateRangeParams) => `${startDate} から ${endDate}（${count} 日間）`,
+        splitExpenseSubtitle: ({amount, merchant}: SplitExpenseSubtitleParams) => `${merchant}からの${amount}`,
         splitByPercentage: 'パーセンテージで分割',
         splitByDate: '日付ごとに分割',
         addSplit: '分割を追加',
         makeSplitsEven: '分割を均等にする',
         editSplits: '按分割を編集',
-        totalAmountGreaterThanOriginal: (amount: string) => `合計金額が元の経費よりも${amount}多くなっています。`,
-        totalAmountLessThanOriginal: (amount: string) => `合計金額は元の経費より${amount}少なくなっています。`,
+        totalAmountGreaterThanOriginal: ({amount}: TotalAmountGreaterOrLessThanOriginalParams) => `合計金額が元の経費よりも${amount}多くなっています。`,
+        totalAmountLessThanOriginal: ({amount}: TotalAmountGreaterOrLessThanOriginalParams) => `合計金額は元の経費より${amount}少なくなっています。`,
         splitExpenseZeroAmount: '続行する前に有効な金額を入力してください。',
         splitExpenseOneMoreSplit: '分割が追加されていません。保存するには少なくとも 1 件追加してください。',
-        splitExpenseEditTitle: (amount: string, merchant: string) => `${merchant} の ${amount} を編集`,
+        splitExpenseEditTitle: ({amount, merchant}: SplitExpenseEditTitleParams) => `${merchant} の ${amount} を編集`,
         removeSplit: '分割を削除',
         splitExpenseCannotBeEditedModalTitle: 'この経費は編集できません',
         splitExpenseCannotBeEditedModalDescription: '承認済みまたは支払済みの経費は編集できません',
@@ -1230,12 +1183,9 @@ const translations: TranslationDeepObject<typeof en> = {
         deleteReceipt: '領収書を削除',
         findExpense: '経費を検索',
         deletedTransaction: (amount: string, merchant: string) => `経費を削除しました（${merchant} に ${amount}）`,
-        movedFromReport: (reportName: string) => `${reportName} から経費を移動しました`,
-        movedFromReportNoName: '経費を移動しました',
-        movedTransactionTo: (reportUrl: string, reportName: string) => `この経費を<a href="${reportUrl}">${reportName}</a>に移動しました`,
-        movedTransactionToAnotherReport: 'この経費を別のレポートに移動しました',
-        movedTransactionFrom: (reportUrl: string, reportName: string) => `この経費を<a href="${reportUrl}">${reportName}</a>から移動しました`,
-        movedTransactionFromAnotherReport: 'この経費を別のレポートから移動しました',
+        movedFromReport: (reportName: string) => `経費${reportName ? `${reportName} から` : ''}を移動しました`,
+        movedTransactionTo: (reportUrl: string, reportName?: string) => `この経費を移動しました${reportName ? `<a href="${reportUrl}">${reportName}</a>へ` : ''}`,
+        movedTransactionFrom: (reportUrl: string, reportName?: string) => `この経費を移動しました${reportName ? `<a href="${reportUrl}">${reportName}</a> から` : ''}`,
         unreportedTransaction: (reportUrl: string) => `この経費をあなたの<a href="${reportUrl}">個人スペース</a>に移動しました`,
         movedAction: (shouldHideMovedReportUrl: boolean, movedReportUrl: string, newParentReportUrl: string, toPolicyName: string) => {
             if (shouldHideMovedReportUrl) {
@@ -1247,10 +1197,7 @@ const translations: TranslationDeepObject<typeof en> = {
         pendingMatch: '保留中の照合',
         pendingMatchWithCreditCardDescription: 'レシートはカード取引との照合待ちです。現金としてマークしてキャンセルします。',
         markAsCash: '現金としてマーク',
-        pendingMatchSubmitTitle: 'レポートを提出',
-        pendingMatchSubmitDescription: '一部の経費がクレジットカード取引との照合待ちです。現金としてマークしますか？',
         routePending: 'ルート保留中…',
-        automaticallyEnterExpenseDetails: 'Concierge が詳細を入力します。',
         receiptScanning: () => ({
             one: 'レシートをスキャンしています…',
             other: 'レシートをスキャンしています…',
@@ -1277,7 +1224,7 @@ const translations: TranslationDeepObject<typeof en> = {
         receiptStatusTitle: 'スキャン中…',
         receiptStatusText: 'スキャン中のレシートは、あなただけが見ることができます。後でまた確認するか、今すぐ詳細を入力してください。',
         receiptScanningFailed: 'レシートのスキャンに失敗しました。詳細を手入力してください。',
-        allTransactionsPendingNextStep: 'すべての取引が保留中です。数日後に処理が完了するまで、このレポートを提出することはできません。',
+        transactionPendingDescription: '取引は保留中です。記帳されるまで数日かかる場合があります。',
         companyInfo: '会社情報',
         companyInfoDescription: '最初の請求書を送信する前に、いくつか追加の情報が必要です。',
         yourCompanyName: '会社名',
@@ -1312,18 +1259,20 @@ const translations: TranslationDeepObject<typeof en> = {
         settledElsewhere: '他で支払い済み',
         individual: '個人',
         business: 'ビジネス',
-        settlePersonal: (formattedAmount?: string) => (formattedAmount ? `個人として${formattedAmount}を支払う` : `個人アカウントで支払う`),
-        settleWallet: (formattedAmount?: string) => (formattedAmount ? `ウォレットで ${formattedAmount} を支払う` : `ウォレットで支払う`),
-        settlePayment: (formattedAmount: string) => `${formattedAmount} を支払う`,
-        settleBusiness: (formattedAmount?: string) => (formattedAmount ? `${formattedAmount} をビジネスとして支払う` : `ビジネスアカウントで支払う`),
-        payElsewhere: (formattedAmount?: string) => (formattedAmount ? `${formattedAmount} を支払済みにする` : `支払い済みにする`),
-        confirmPaymentReceivedModalTitle: '支払いを受領したことを確認',
-        receivedPayment: '支払い受領済み',
-        receivedPaymentConfirmation: 'Expensify以外で支払いを受け取っている場合のみ続行してください。',
-        confirmReceivedPayment: 'はい、支払いを受け取りました。',
+        settleExpensify: ({formattedAmount}: SettleExpensifyCardParams) => (formattedAmount ? `Expensifyで${formattedAmount}を支払う` : `Expensify で支払う`),
+        settlePersonal: ({formattedAmount}: SettleExpensifyCardParams) => (formattedAmount ? `個人として${formattedAmount}を支払う` : `個人アカウントで支払う`),
+        settleWallet: ({formattedAmount}: SettleExpensifyCardParams) => (formattedAmount ? `ウォレットで ${formattedAmount} を支払う` : `ウォレットで支払う`),
+        settlePayment: ({formattedAmount}: SettleExpensifyCardParams) => `${formattedAmount} を支払う`,
+        settleBusiness: ({formattedAmount}: SettleExpensifyCardParams) => (formattedAmount ? `${formattedAmount} をビジネスとして支払う` : `ビジネスアカウントで支払う`),
+        payElsewhere: ({formattedAmount}: SettleExpensifyCardParams) => (formattedAmount ? `${formattedAmount} を支払済みにする` : `支払い済みにする`),
         settleInvoicePersonal: (amount?: string, last4Digits?: string) => (amount ? `個人アカウント（下4桁 ${last4Digits}）で ${amount} を支払いました` : `個人アカウントで支払い済み`),
         settleInvoiceBusiness: (amount?: string, last4Digits?: string) => (amount ? `ビジネス口座（末尾${last4Digits}）で${amount}を支払いました` : `ビジネスアカウントで支払済み`),
-        payWithPolicy: (policyName: string, formattedAmount?: string) => (formattedAmount ? `${policyName}で${formattedAmount}を支払う` : `${policyName}で支払う`),
+        payWithPolicy: ({
+            formattedAmount,
+            policyName,
+        }: SettleExpensifyCardParams & {
+            policyName: string;
+        }) => (formattedAmount ? `${policyName}で${formattedAmount}を支払う` : `${policyName}で支払う`),
         businessBankAccount: (amount?: string, last4Digits?: string) => (amount ? `銀行口座（末尾${last4Digits}）で${amount}を支払いました` : `銀行口座（下4桁 ${last4Digits}）で支払い済み`),
         automaticallyPaidWithBusinessBankAccount: (amount?: string, last4Digits?: string) =>
             `<a href="${CONST.CONFIGURE_EXPENSE_REPORT_RULES_HELP_URL}">ワークスペースルール</a>に従い、銀行口座（下4桁 ${last4Digits}）で${amount ? `${amount} ` : ''}を支払いました`,
@@ -1332,16 +1281,16 @@ const translations: TranslationDeepObject<typeof en> = {
         nextStep: '次のステップ',
         finished: '完了',
         flip: '反転',
-        sendInvoice: (amount: string) => `${amount} の請求書を送信`,
+        sendInvoice: ({amount}: RequestAmountParams) => `${amount} の請求書を送信`,
         expenseAmount: (formattedAmount: string, comment?: string) => `${formattedAmount}${comment ? `${comment}用` : ''}`,
-        submitted: (memo?: string) => `送信済み${memo ? `、メモ: ${memo}` : ''}`,
+        submitted: ({memo}: SubmittedWithMemoParams) => `送信済み${memo ? `、メモ: ${memo}` : ''}`,
         automaticallySubmitted: `<a href="${CONST.SELECT_WORKFLOWS_HELP_URL}">提出の延期</a> 経由で提出されました`,
         queuedToSubmitViaDEW: 'カスタム承認ワークフローで提出待ち',
         queuedToApproveViaDEW: 'カスタム承認ワークフローで承認待ちに設定されました',
         trackedAmount: (formattedAmount: string, comment?: string) => `追跡中 ${formattedAmount}${comment ? `${comment}用` : ''}`,
-        splitAmount: (amount: string) => `${amount} を分割`,
-        didSplitAmount: (formattedAmount: string, comment?: string) => `${formattedAmount}${comment ? `${comment}用` : ''} を分割`,
-        yourSplit: (amount: string) => `あなたの分担額 ${amount}`,
+        splitAmount: ({amount}: SplitAmountParams) => `${amount} を分割`,
+        didSplitAmount: (formattedAmount: string, comment: string) => `${formattedAmount}${comment ? `${comment}用` : ''} を分割`,
+        yourSplit: ({amount}: UserSplitParams) => `あなたの分担額 ${amount}`,
         payerOwesAmount: (amount: number | string, payer: string, comment?: string) => `${payer} は ${amount}${comment ? `${comment}用` : ''} を支払う必要があります`,
         payerOwes: (payer: string) => `${payer} の負担額：`,
         payerPaidAmount: (amount: number | string, payer?: string) => `${payer ? `${payer} ` : ''}が${amount}を支払いました`,
@@ -1357,70 +1306,33 @@ const translations: TranslationDeepObject<typeof en> = {
         approvedMessage: `承認済み`,
         unapproved: `未承認`,
         automaticallyForwarded: `<a href="${CONST.CONFIGURE_EXPENSE_REPORT_RULES_HELP_URL}">ワークスペースルール</a>により承認済み`,
-        forwarded: (memo?: string) => `承認済み${memo ? `、メモ: ${memo}` : ''}`,
-        rejectedThisReport: '却下しました',
-        waitingOnBankAccount: (submitterDisplayName: string) => `支払いを開始しましたが、${submitterDisplayName}が銀行口座を追加するのを待っています。`,
+        forwarded: `承認済み`,
+        rejectedThisReport: 'このレポートを却下しました',
+        waitingOnBankAccount: ({submitterDisplayName}: WaitingOnBankAccountParams) => `支払いを開始しましたが、${submitterDisplayName}が銀行口座を追加するのを待っています。`,
         adminCanceledRequest: '支払いをキャンセルしました',
         canceledRequest: (amount: string, submitterDisplayName: string) =>
             `${submitterDisplayName} が30日以内に Expensify Wallet を有効化しなかったため、${amount} の支払いをキャンセルしました`,
-        settledAfterAddedBankAccount: (submitterDisplayName: string, amount: string) => `${submitterDisplayName} が銀行口座を追加しました。${amount} の支払いが行われました。`,
+        settledAfterAddedBankAccount: ({submitterDisplayName, amount}: SettledAfterAddedBankAccountParams) =>
+            `${submitterDisplayName} が銀行口座を追加しました。${amount} の支払いが行われました。`,
         paidElsewhere: ({payer, comment}: PaidElsewhereParams = {}) => `${payer ? `${payer} ` : ''}支払い済みにしました${comment ? `、「${comment}」と言っています` : ''}`,
         paidWithExpensify: (payer?: string) => `${payer ? `${payer} ` : ''}ウォレットで支払い済み`,
         automaticallyPaidWithExpensify: (payer?: string) =>
             `${payer ? `${payer} ` : ''}は<a href="${CONST.CONFIGURE_EXPENSE_REPORT_RULES_HELP_URL}">ワークスペースルール</a>経由でExpensifyにより支払われました`,
-        reimbursedThisReport: 'このレポートを精算しました',
-        paidThisBill: 'この請求書を支払いました',
-        reimbursedOnBehalfOf: (actor: string) => `${actor}に代わって`,
-        reimbursedFromBankAccount: (debitBankAccount: string) => `末尾が ${debitBankAccount} の銀行口座から`,
-        reimbursedSubmitterAddedBankAccount: (submitter: string) => `${submitter} さんが銀行口座を追加し、レポートの保留を解除しました。払い戻しを開始しました。`,
-        reimbursedWithFastACH: ({
-            isCurrentUser,
-            submitterLogin,
-            creditBankAccount,
-            expectedDate,
-        }: {
-            isCurrentUser: boolean;
-            submitterLogin: string;
-            creditBankAccount: string;
-            expectedDate: string;
-        }) =>
-            isCurrentUser
-                ? `. ${creditBankAccount ? `預金口座（末尾番号 ${creditBankAccount}）` : 'アカウント'} にお金を送金中です。払い戻しは ${expectedDate} に完了する見込みです。`
-                : `. ${submitterLogin} さんへの${creditBankAccount ? `預金口座（末尾番号 ${creditBankAccount}）` : 'アカウント'}への送金中です。払い戻しの完了予定日は ${expectedDate} です。`,
-        reimbursedWithCheck: '小切手で',
-        reimbursedWithStripeConnect: ({
-            isCurrentUser,
-            submitterLogin,
-            creditBankAccount,
-            isCard,
-        }: {
-            isCurrentUser: boolean;
-            submitterLogin: string;
-            creditBankAccount: string;
-            isCard: boolean;
-        }) => {
-            const paymentMethod = isCard ? 'カード' : '銀行口座';
-            return isCurrentUser
-                ? `. ${paymentMethod}で支払われた資金が、お客様の${creditBankAccount ? `預金口座（末尾番号 ${creditBankAccount}）` : 'アカウント'}に向けて送金中です。最大で10営業日かかる場合があります。`
-                : `. ${submitterLogin} さんの ${creditBankAccount ? `預金口座（末尾番号 ${creditBankAccount}）` : 'アカウント'} へ送金中です（${paymentMethod} で支払われます）。最大 10 営業日かかる場合があります。`;
-        },
-        reimbursedWithACH: ({creditBankAccount, expectedDate}: {creditBankAccount?: string; expectedDate?: string}) =>
-            `直接入金（ACH）で${creditBankAccount ? `${creditBankAccount}で終わる銀行口座へ。` : '. '}${expectedDate ? `払戻しは${expectedDate}までに完了する見込みです。` : '通常、営業日で4～5日かかります。'}`,
         noReimbursableExpenses: 'このレポートには無効な金額が含まれています',
         pendingConversionMessage: 'オンラインに戻ると合計が更新されます',
         changedTheExpense: '経費を変更しました',
-        setTheRequest: (valueName: string, newValueToDisplay: string) => `${valueName} を ${newValueToDisplay} に`,
-        setTheDistanceMerchant: (translatedChangedField: string, newMerchant: string, newAmountToDisplay: string) =>
+        setTheRequest: ({valueName, newValueToDisplay}: SetTheRequestParams) => `${valueName} を ${newValueToDisplay} に`,
+        setTheDistanceMerchant: ({translatedChangedField, newMerchant, newAmountToDisplay}: SetTheDistanceMerchantParams) =>
             `${translatedChangedField} を ${newMerchant} に設定し、その結果金額が ${newAmountToDisplay} に設定されました`,
         removedTheRequest: (valueName: string, oldValueToDisplay: string) => `${valueName}（以前は${oldValueToDisplay}）`,
-        updatedTheRequest: (valueName: string, newValueToDisplay: string, oldValueToDisplay: string) => `${valueName} を ${newValueToDisplay} に（以前は ${oldValueToDisplay}）`,
-        updatedTheDistanceMerchant: (translatedChangedField: string, newMerchant: string, oldMerchant: string, newAmountToDisplay: string, oldAmountToDisplay: string) =>
+        updatedTheRequest: ({valueName, newValueToDisplay, oldValueToDisplay}: UpdatedTheRequestParams) => `${valueName} を ${newValueToDisplay} に（以前は ${oldValueToDisplay}）`,
+        updatedTheDistanceMerchant: ({translatedChangedField, newMerchant, oldMerchant, newAmountToDisplay, oldAmountToDisplay}: UpdatedTheDistanceMerchantParams) =>
             `${translatedChangedField} を ${newMerchant}（以前は ${oldMerchant}）に変更したため、金額が ${newAmountToDisplay}（以前は ${oldAmountToDisplay}）に更新されました`,
         basedOnAI: '過去のアクティビティに基づく',
         basedOnMCC: ({rulesLink}: {rulesLink: string}) => (rulesLink ? `<a href="${rulesLink}">ワークスペースルール</a>に基づく` : 'ワークスペースのルールに基づく'),
-        threadExpenseReportName: (formattedAmount: string, comment?: string) => `${formattedAmount} ${comment ? `${comment} 用` : '経費'}`,
+        threadExpenseReportName: ({formattedAmount, comment}: ThreadRequestReportNameParams) => `${formattedAmount} ${comment ? `${comment} 用` : '経費'}`,
         invoiceReportName: ({linkedReportID}: OriginalMessage<typeof CONST.REPORT.ACTIONS.TYPE.REPORT_PREVIEW>) => `請求書レポート #${linkedReportID}`,
-        threadPaySomeoneReportName: (formattedAmount: string, comment?: string) => `${formattedAmount} を送信済み${comment ? `${comment}用` : ''}`,
+        threadPaySomeoneReportName: ({formattedAmount, comment}: ThreadSentMoneyReportNameParams) => `${formattedAmount} を送信済み${comment ? `${comment}用` : ''}`,
         movedFromPersonalSpace: ({workspaceName, reportName}: MovedFromPersonalSpaceParams) => `経費を個人スペースから${workspaceName ?? `${reportName}とチャット`}に移動しました`,
         movedToPersonalSpace: '経費を個人スペースに移動しました',
         error: {
@@ -1428,14 +1340,10 @@ const translations: TranslationDeepObject<typeof en> = {
             invalidTagLength: 'タグ名が255文字を超えています。短くするか、別のタグを選択してください。',
             invalidAmount: '続行する前に有効な金額を入力してください',
             invalidDistance: '続行する前に有効な距離を入力してください',
-            invalidReadings: '続行する前に開始値と終了値の両方を入力してください',
+            invalidReadings: '開始値と終了値の両方を入力してください',
             negativeDistanceNotAllowed: '終了値は開始値より大きくなければなりません',
-            distanceAmountTooLarge: '合計金額が大きすぎます。距離を減らすか、レートを下げてください。',
-            distanceAmountTooLargeReduceDistance: '合計金額が大きすぎます。距離を減らしてください。',
-            distanceAmountTooLargeReduceRate: '合計金額が大きすぎます。レートを下げてください。',
-            odometerReadingTooLarge: (formattedMax: string) => `オドメーターの読み取り値は${formattedMax}を超えることはできません。`,
             invalidIntegerAmount: '続行する前にドルの整数金額を入力してください',
-            invalidTaxAmount: (amount: string) => `最大税額は${amount}です`,
+            invalidTaxAmount: ({amount}: RequestAmountParams) => `最大税額は${amount}です`,
             invalidSplit: '分割した金額の合計は合計金額と一致している必要があります',
             invalidSplitParticipants: '少なくとも2人の参加者に対して、0より大きい金額を入力してください',
             invalidSplitYourself: '分割する金額は 0 以外の数値を入力してください',
@@ -1449,8 +1357,6 @@ const translations: TranslationDeepObject<typeof en> = {
             receiptFailureMessage:
                 '<rbr>領収書のアップロード中にエラーが発生しました。後で再度お試しいただくために、<a href="download">領収書を保存</a>してから、時間をおいて<a href="retry">もう一度お試しください</a>。</rbr>',
             receiptFailureMessageShort: 'レシートのアップロード中にエラーが発生しました。',
-            receiptUploadFailedMessage: 'レシートのアップロードに失敗しました。レシートを保存するか、経費を削除して失うかを選択してください。',
-            saveReceipt: '領収書を保存',
             genericDeleteFailureMessage: 'この経費の削除中に予期しないエラーが発生しました。しばらくしてからもう一度お試しください。',
             genericEditFailureMessage: 'この経費の編集中に予期しないエラーが発生しました。後でもう一度お試しください。',
             genericSmartscanFailureMessage: '取引に未入力の項目があります',
@@ -1467,14 +1373,10 @@ const translations: TranslationDeepObject<typeof en> = {
             endDateSameAsStartDate: '終了日は開始日と同じにはできません',
             manySplitsProvided: `分割できる最大数は${CONST.IOU.SPLITS_LIMIT}件です。`,
             dateRangeExceedsMaxDays: `日付範囲は${CONST.IOU.SPLITS_LIMIT}日を超えることはできません。`,
-            unableToSubmitReport: 'レポートを送信できません',
-            allTransactionsPendingDescription: 'すべての取引が保留中のため、このレポートは提出できません。反映されるまでに数日かかる場合があります。',
-            stitchOdometerImagesFailed: '走行距離計の画像を結合できませんでした。後でもう一度お試しください。',
-            failedToSaveOdometerDraft: 'オドメーターの下書きを保存できませんでした。もう一度お試しください。',
         },
         dismissReceiptError: 'エラーを閉じる',
         dismissReceiptErrorConfirmation: 'ご注意ください！このエラーを閉じると、アップロード済みのレシートが完全に削除されます。本当に続行しますか？',
-        waitingOnEnabledWallet: (submitterDisplayName: string) => `清算を開始しました。${submitterDisplayName} がウォレットを有効にするまで、支払いは保留されます。`,
+        waitingOnEnabledWallet: ({submitterDisplayName}: WaitingOnBankAccountParams) => `清算を開始しました。${submitterDisplayName} がウォレットを有効にするまで、支払いは保留されます。`,
         enableWallet: 'ウォレットを有効にする',
         hold: '保留',
         unhold: '保留を解除',
@@ -1486,20 +1388,16 @@ const translations: TranslationDeepObject<typeof en> = {
         heldExpense: 'この経費を保留しました',
         unheldExpense: 'この経費の保留を解除しました',
         moveUnreportedExpense: '未報告の経費を移動',
-        addExistingExpense: '既存の経費を追加',
-        selectExistingExpense: 'レポートに追加する経費を少なくとも1件選択してください。',
-        emptyStateExistingExpenseTitle: '既存の経費はありません',
-        emptyStateExistingExpenseSubtitle: '既存の経費がありません。下から新しく作成してみてください。',
-        addExistingExpenseConfirm: 'レポートに追加',
+        addUnreportedExpense: '未報告の経費を追加',
+        selectUnreportedExpense: 'レポートに追加する経費を少なくとも1件選択してください。',
+        emptyStateUnreportedExpenseTitle: '未報告の経費はありません',
+        emptyStateUnreportedExpenseSubtitle: '未報告の経費はありません。下から新しく作成してみてください。',
+        addUnreportedExpenseConfirm: 'レポートに追加',
         newReport: '新しいレポート',
         explainHold: () => ({
             one: 'この経費を保留している理由を説明してください。',
             other: 'これらの経費を保留している理由を説明してください。',
         }),
-        explainHoldApprover: () => ({
-            one: 'この経費を承認する前に必要なことを説明してください。',
-            other: 'これらの経費を承認する前に必要なことを説明してください。',
-        }),
         retracted: '取り消し済み',
         retract: '撤回',
         reopened: '再開しました',
@@ -1512,12 +1410,9 @@ const translations: TranslationDeepObject<typeof en> = {
         expenseOnHold: 'この経費は保留されています。今後の手順についてコメントを確認してください。',
         expensesOnHold: 'すべての経費が保留になっています。次のステップについてはコメントを確認してください。',
         expenseDuplicate: 'この経費は別の経費と詳細がよく似ています。続行するには重複しているものを確認してください。',
-        someDuplicatesArePaid: 'これらの重複の一部は、すでに承認または支払い済みです。',
+        someDuplicatesArePaid: 'これらの重複のうち、いくつかはすでに承認または支払い済みです。',
         reviewDuplicates: '重複を確認',
         keepAll: 'すべて保持',
-        keepSelected: '選択したものを保持',
-        noDuplicatesTitle: '準備完了！',
-        noDuplicatesDescription: '確認が必要な重複取引はありません。',
         confirmApprove: '承認金額を確認',
         confirmApprovalAmount: '準拠している経費のみを承認するか、レポート全体を承認します。',
         confirmApprovalAllHoldAmount: () => ({
@@ -1551,7 +1446,7 @@ const translations: TranslationDeepObject<typeof en> = {
         unapprove: '承認を取り消す',
         unapproveReport: 'レポートの承認を取り消す',
         headsUp: 'ご注意ください！',
-        unapproveWithIntegrationWarning: (accountingIntegration: string) =>
+        unapproveWithIntegrationWarning: ({accountingIntegration}: UnapproveWithIntegrationWarningParams) =>
             `このレポートはすでに ${accountingIntegration} にエクスポートされています。変更するとデータの不整合が発生する可能性があります。本当にこのレポートの承認を取り消しますか？`,
         reimbursable: '経費精算対象',
         nonReimbursable: '精算対象外',
@@ -1560,7 +1455,6 @@ const translations: TranslationDeepObject<typeof en> = {
         bookingArchived: 'この予約はアーカイブされています',
         bookingArchivedDescription: 'この予約は旅行日が過ぎたためアーカイブされています。必要に応じて、最終金額の経費を追加してください。',
         attendees: '参加者',
-        totalPerAttendee: '参加者ごと',
         whoIsYourAccountant: 'あなたの会計士は誰ですか？',
         paymentComplete: '支払いが完了しました',
         time: '時間',
@@ -1587,7 +1481,7 @@ const translations: TranslationDeepObject<typeof en> = {
         }),
         dates: '日付',
         rates: '料金',
-        submitsTo: (name: string) => `${name} に提出`,
+        submitsTo: ({name}: SubmitsToParams) => `${name} に提出`,
         reject: {
             educationalTitle: '保留しますか、それとも却下しますか？',
             educationalText: '経費を承認または支払う準備ができていない場合は、保留にするか却下できます。',
@@ -1596,7 +1490,7 @@ const translations: TranslationDeepObject<typeof en> = {
             heldExpenseLeftBehindTitle: '保留中の経費は、レポート全体を承認してもそのまま残ります。',
             rejectExpenseTitle: '承認や支払いを行う予定のない経費を却下します。',
             reasonPageTitle: '経費を却下',
-            reasonPageDescription: 'この経費を承認しない理由を説明してください。',
+            reasonPageDescription: 'この経費を却下する理由を説明してください。',
             rejectReason: '却下理由',
             markAsResolved: '解決済みにする',
             rejectedStatus: 'この経費は却下されました。問題を修正して解決済みにすると、再提出できるようになります。',
@@ -1605,26 +1499,13 @@ const translations: TranslationDeepObject<typeof en> = {
                 markedAsResolved: '却下理由を解決済みにしました',
             },
         },
-        rejectReport: {
-            title: 'レポートを却下',
-            description: 'このレポートを承認しない理由を説明してください:',
-            rejectReason: '却理由',
-            selectTarget: 'このレポートを差し戻して再確認してもらうメンバーを選択してください：',
-            lastApprover: '最終承認者',
-            submitter: '申請者',
-            rejectedReportMessage: 'このレポートは却下されました。',
-            rejectedNextStep: 'このレポートは却下されました。問題を修正し、手動で再提出していただくのをお待ちしています。',
-            selectMemberError: 'このレポートを差し戻すメンバーを選択してください。',
-            couldNotReject: 'レポートを拒否できませんでした。もう一度お試しください。',
-        },
-        moveExpenses: 'レポートに移動',
+        moveExpenses: () => ({one: '経費を移動', other: '経費を移動'}),
         moveExpensesError: '日当経費は、ワークスペースごとに日当レートが異なる場合があるため、他のワークスペースのレポートに移動することはできません。',
         changeApprover: {
             title: '承認者を変更',
-            header: (workflowSettingLink: string) =>
+            header: ({workflowSettingLink}: WorkflowSettingsParam) =>
                 `このレポートの承認者を変更する方法を選択してください。（すべてのレポートで恒久的に変更するには、<a href="${workflowSettingLink}">ワークスペース設定</a>を更新してください。）`,
             changedApproverMessage: (managerID: number) => `承認者を <mention-user accountID="${managerID}"/> に変更しました`,
-            reassignedApproverMessage: (managerID: number) => `ワークフローの更新により承認者を <mention-user accountID="${managerID}"/> に再割り当てしました`,
             actions: {
                 addApprover: '承認者を追加',
                 addApproverSubtitle: '既存のワークフローに追加の承認者を追加します。',
@@ -1633,12 +1514,10 @@ const translations: TranslationDeepObject<typeof en> = {
             },
             addApprover: {
                 subtitle: '残りの承認ワークフローへ回付する前に、このレポートの追加承認者を選択してください。',
-                bulkSubtitle: '残りの承認ワークフローに回す前に、これらのレポートの追加承認者を選択してください。',
             },
-            bulkSubtitle: 'これらのレポートの承認者を変更する方法を選択してください。',
         },
         chooseWorkspace: 'ワークスペースを選択',
-        routedDueToDEW: (to: string, reason?: string) => `レポートは ${to}${reason ? ` ${reason} のため` : ''} に回覧されました`,
+        routedDueToDEW: ({to}: RoutedDueToDEWParams) => `カスタム承認ワークフローにより、レポートは${to}に回付されました`,
         timeTracking: {
             hoursAt: (hours: number, rate: string) => `${hours} ${hours === 1 ? '時間' : '時間'} @ ${rate} / 時間`,
             hrs: '時間',
@@ -1646,33 +1525,34 @@ const translations: TranslationDeepObject<typeof en> = {
             ratePreview: (rate: string) => `${rate} / 時間`,
             amountTooLargeError: '合計金額が大きすぎます。時間を減らすか、レートを下げてください。',
         },
-        correctRateError: 'レートのエラーを修正して、もう一度お試しください。',
-        AskToExplain: `・<a href="${CONST.CONCIERGE_EXPLAIN_LINK_PATH}">説明<sparkles-icon/></a>`,
-        duplicateNonDefaultWorkspacePerDiemError: 'ワークスペースごとに日当レートが異なる場合があるため、日当経費をワークスペース間で複製することはできません。',
-        rulesModifiedFields: {
-            reimbursable: (value: boolean) => (value ? '経費を「精算対象」に指定しました' : '経費を「精算対象外」にマークしました'),
-            billable: (value: boolean) => (value ? '経費を「請求可能」に設定しました' : '経費を「請求不可」としてマークしました'),
-            tax: (value: string, isFirst: boolean) => (isFirst ? `税率を「${value}」に設定する` : `税率を「${value}」に`),
-            reportName: (value: string) => `この経費をレポート「${value}」に移動しました`,
-            common: (key: keyof PolicyRulesModifiedFields | keyof PersonalRulesModifiedFields, value: string, isFirst: boolean) => {
-                const field = translations.common[key].toLowerCase();
-                return isFirst ? `${field} を「${value}」に設定する` : `${field} から「${value}」へ`;
-            },
-            formatPersonalRules: (fragments: string, route: string) => `${fragments} (<a href="${route}">個人経費ルール</a> 経由)`,
-            formatPolicyRules: (fragments: string, route: string) => `${fragments} (<a href="${route}">ワークスペースルール</a> 経由)`,
-        },
-        failedToAutoSubmitViaDEW: (reason: string) => `<a href="${CONST.SELECT_WORKFLOWS_HELP_URL}">提出を遅らせる</a>を使ったレポートの送信に失敗しました。${reason}`,
-        failedToSubmitViaDEW: (reason: string) => `レポートの送信に失敗しました。${reason}`,
-        failedToAutoApproveViaDEW: (reason: string) => `<a href="${CONST.CONFIGURE_EXPENSE_REPORT_RULES_HELP_URL}">ワークスペースルール</a>で承認に失敗しました。${reason}`,
-        failedToApproveViaDEW: (reason: string) => `承認に失敗しました。${reason}`,
-        cannotDuplicateDistanceExpense: '距離精算はワークスペースごとにレートが異なる可能性があるため、ワークスペース間で複製することはできません。',
-        taxDisabledAlert: {
-            title: '税が無効です',
-            prompt: '経費の詳細を編集したり、この経費から税金を削除したりするには、ワークスペースで税金の追跡を有効にしてください。',
-            confirmText: '税を削除',
-        },
-        bulkDuplicateLimit: `一度に複製できる経費は最大で ${CONST.SEARCH.BULK_DUPLICATE_LIMIT} 件です。経費の数を減らして、もう一度お試しください。`,
-        deleted: '削除済み',
+        correctDistanceRateError: '距離レートのエラーを修正して、もう一度お試しください。',
+        AskToExplain: `. <a href="${CONST.CONCIERGE_EXPLAIN_LINK_PATH}"><strong>説明</strong></a> &#x2728;`,
+        policyRulesModifiedFields: (policyRulesModifiedFields: PolicyRulesModifiedFields, policyRulesRoute: string, formatList: (list: string[]) => string) => {
+            const entries = ObjectUtils.typedEntries(policyRulesModifiedFields);
+            const fragments = entries.map(([key, value], i) => {
+                const isFirst = i === 0;
+                if (key === 'reimbursable') {
+                    return value ? '経費を「精算対象」としてマークしました' : '経費を「非精算」としてマークしました';
+                }
+                if (key === 'billable') {
+                    return value ? '経費を「請求可能」に設定しました' : '経費を「請求不可」としてマークしました';
+                }
+                if (key === 'tax') {
+                    const taxEntry = value as PolicyRulesModifiedFields['tax'];
+                    const taxRateName = taxEntry?.field_id_TAX.name ?? '';
+                    if (isFirst) {
+                        return `税率を「${taxRateName}」に設定する`;
+                    }
+                    return `税率を「${taxRateName}」に`;
+                }
+                const updatedValue = value as string | boolean;
+                if (isFirst) {
+                    return `${translations.common[key].toLowerCase()} を「${updatedValue}」に設定する`;
+                }
+                return `${translations.common[key].toLowerCase()} から「${updatedValue}」へ`;
+            });
+            return `${formatList(fragments)}（<a href="${policyRulesRoute}">ワークスペースルール</a>経由）`;
+        },
     },
     transactionMerge: {
         listPage: {
@@ -1745,185 +1625,110 @@ const translations: TranslationDeepObject<typeof en> = {
     },
     nextStep: {
         message: {
-            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_TO_ADD_TRANSACTIONS]: (
-                actor: string,
-                actorType: ValueOf<typeof CONST.NEXT_STEP.ACTOR_TYPE>,
-                _eta?: string,
-                _etaType?: ValueOf<typeof CONST.NEXT_STEP.ETA_TYPE>,
-            ) => {
+            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_TO_ADD_TRANSACTIONS]: ({actor, actorType}: NextStepParams) => {
                 switch (actorType) {
                     case CONST.NEXT_STEP.ACTOR_TYPE.CURRENT_USER:
-                        return `経費を追加するのを<strong>あなた</strong>が行うのを待機しています。`;
+                        return `経費が追加されるのを<strong>あなた</strong>の操作で待っています。`;
                     case CONST.NEXT_STEP.ACTOR_TYPE.OTHER_USER:
                         return `<strong>${actor}</strong> が経費を追加するのを待っています。`;
                     case CONST.NEXT_STEP.ACTOR_TYPE.UNSPECIFIED_ADMIN:
                         return `管理者が経費を追加するのを待機しています。`;
                 }
             },
-            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_TO_SUBMIT]: (
-                actor: string,
-                actorType: ValueOf<typeof CONST.NEXT_STEP.ACTOR_TYPE>,
-                _eta?: string,
-                _etaType?: ValueOf<typeof CONST.NEXT_STEP.ETA_TYPE>,
-            ) => {
+            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_TO_SUBMIT]: ({actor, actorType}: NextStepParams) => {
                 switch (actorType) {
                     case CONST.NEXT_STEP.ACTOR_TYPE.CURRENT_USER:
-                        return `経費の申請を<strong>あなた</strong>が行うのを待っています。`;
+                        return `経費の提出を<strong>あなた</strong>が行うのを待っています。`;
                     case CONST.NEXT_STEP.ACTOR_TYPE.OTHER_USER:
-                        return `<strong>${actor}</strong> が経費を提出するのを待機しています。`;
+                        return `<strong>${actor}</strong> が経費を提出するのを待っています。`;
                     case CONST.NEXT_STEP.ACTOR_TYPE.UNSPECIFIED_ADMIN:
-                        return `管理者が経費を送信するのを待っています。`;
+                        return `管理者が経費精算を提出するのを待機しています。`;
                 }
             },
-            [CONST.NEXT_STEP.MESSAGE_KEY.NO_FURTHER_ACTION]: (
-                _actor: string,
-                _actorType: ValueOf<typeof CONST.NEXT_STEP.ACTOR_TYPE>,
-                _eta?: string,
-                _etaType?: ValueOf<typeof CONST.NEXT_STEP.ETA_TYPE>,
-            ) => `これ以上の対応は不要です。`,
-            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_FOR_SUBMITTER_ACCOUNT]: (
-                actor: string,
-                actorType: ValueOf<typeof CONST.NEXT_STEP.ACTOR_TYPE>,
-                _eta?: string,
-                _etaType?: ValueOf<typeof CONST.NEXT_STEP.ETA_TYPE>,
-            ) => {
+            [CONST.NEXT_STEP.MESSAGE_KEY.NO_FURTHER_ACTION]: (_: NextStepParams) => `これ以上の操作は必要ありません。`,
+            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_FOR_SUBMITTER_ACCOUNT]: ({actor, actorType}: NextStepParams) => {
                 switch (actorType) {
                     case CONST.NEXT_STEP.ACTOR_TYPE.CURRENT_USER:
-                        return `銀行口座の追加を<strong>お待ちしています</strong>。`;
+                        return `銀行口座の追加を<strong>あなた</strong>が行うのを待っています。`;
                     case CONST.NEXT_STEP.ACTOR_TYPE.OTHER_USER:
                         return `<strong>${actor}</strong> が銀行口座を追加するのを待っています。`;
                     case CONST.NEXT_STEP.ACTOR_TYPE.UNSPECIFIED_ADMIN:
                         return `管理者が銀行口座を追加するのを待っています。`;
                 }
             },
-            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_FOR_AUTOMATIC_SUBMIT]: (
-                actor: string,
-                actorType: ValueOf<typeof CONST.NEXT_STEP.ACTOR_TYPE>,
-                eta?: string,
-                etaType?: ValueOf<typeof CONST.NEXT_STEP.ETA_TYPE>,
-            ) => {
+            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_FOR_AUTOMATIC_SUBMIT]: ({actor, actorType, eta, etaType}: NextStepParams) => {
                 let formattedETA = '';
                 if (eta) {
-                    formattedETA = etaType === CONST.NEXT_STEP.ETA_TYPE.DATE_TIME ? `毎月${eta}日に` : ` ${eta}`;
+                    formattedETA = etaType === CONST.NEXT_STEP.ETA_TYPE.DATE_TIME ? `${eta}に` : ` ${eta}`;
                 }
                 switch (actorType) {
                     case CONST.NEXT_STEP.ACTOR_TYPE.CURRENT_USER:
-                        return `<strong>あなたの</strong>経費が自動送信されるまでお待ちください${formattedETA}。`;
+                        return `<strong>あなた</strong>の経費が自動送信されるまでお待ちください${formattedETA}。`;
                     case CONST.NEXT_STEP.ACTOR_TYPE.OTHER_USER:
-                        return `<strong>${actor}</strong>さんの経費が自動で提出されるのを待機しています${formattedETA}。`;
+                        return `<strong>${actor}</strong>の経費が自動送信されるのを待機しています${formattedETA}。`;
                     case CONST.NEXT_STEP.ACTOR_TYPE.UNSPECIFIED_ADMIN:
-                        return `管理者の経費が自動送信されるのを待機しています${formattedETA}。`;
+                        return `管理者の経費精算が自動的に提出されるのを待機中${formattedETA}。`;
                 }
             },
-            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_TO_FIX_ISSUES]: (
-                actor: string,
-                actorType: ValueOf<typeof CONST.NEXT_STEP.ACTOR_TYPE>,
-                _eta?: string,
-                _etaType?: ValueOf<typeof CONST.NEXT_STEP.ETA_TYPE>,
-            ) => {
+            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_TO_FIX_ISSUES]: ({actor, actorType}: NextStepParams) => {
                 switch (actorType) {
                     case CONST.NEXT_STEP.ACTOR_TYPE.CURRENT_USER:
-                        return `問題の修正を<strong>あなた</strong>が行うのを待っています。`;
+                        return `問題を解決してくれるのを<strong>あなた</strong>を待っています。`;
                     case CONST.NEXT_STEP.ACTOR_TYPE.OTHER_USER:
-                        return `<strong>${actor}</strong>が問題を修正するのを待っています。`;
+                        return `<strong>${actor}</strong> が問題を修正するのを待っています。`;
                     case CONST.NEXT_STEP.ACTOR_TYPE.UNSPECIFIED_ADMIN:
-                        return `管理者が問題を修正するのを待機しています。`;
+                        return `管理者が問題を修正するのを待っています。`;
                 }
             },
-            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_TO_APPROVE]: (
-                actor: string,
-                actorType: ValueOf<typeof CONST.NEXT_STEP.ACTOR_TYPE>,
-                _eta?: string,
-                _etaType?: ValueOf<typeof CONST.NEXT_STEP.ETA_TYPE>,
-            ) => {
+            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_TO_APPROVE]: ({actor, actorType}: NextStepParams) => {
                 switch (actorType) {
                     case CONST.NEXT_STEP.ACTOR_TYPE.CURRENT_USER:
                         return `経費の承認を<strong>あなた</strong>が行うのを待っています。`;
                     case CONST.NEXT_STEP.ACTOR_TYPE.OTHER_USER:
-                        return `<strong>${actor}</strong>による経費の承認を待っています。`;
+                        return `<strong>${actor}</strong> が経費を承認するのを待っています。`;
                     case CONST.NEXT_STEP.ACTOR_TYPE.UNSPECIFIED_ADMIN:
-                        return `管理者が経費を承認するのを待っています。`;
+                        return `管理者の経費承認を待機中です。`;
                 }
             },
-            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_TO_EXPORT]: (
-                actor: string,
-                actorType: ValueOf<typeof CONST.NEXT_STEP.ACTOR_TYPE>,
-                _eta?: string,
-                _etaType?: ValueOf<typeof CONST.NEXT_STEP.ETA_TYPE>,
-            ) => {
+            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_TO_EXPORT]: ({actor, actorType}: NextStepParams) => {
                 switch (actorType) {
                     case CONST.NEXT_STEP.ACTOR_TYPE.CURRENT_USER:
                         return `このレポートのエクスポートを<strong>あなた</strong>が行うのを待っています。`;
                     case CONST.NEXT_STEP.ACTOR_TYPE.OTHER_USER:
-                        return `<strong>${actor}</strong> がこのレポートをエクスポートするのを待っています。`;
+                        return `このレポートをエクスポートするために<strong>${actor}</strong>を待機しています。`;
                     case CONST.NEXT_STEP.ACTOR_TYPE.UNSPECIFIED_ADMIN:
                         return `管理者がこのレポートをエクスポートするのを待機しています。`;
                 }
             },
-            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_TO_PAY]: (
-                actor: string,
-                actorType: ValueOf<typeof CONST.NEXT_STEP.ACTOR_TYPE>,
-                _eta?: string,
-                _etaType?: ValueOf<typeof CONST.NEXT_STEP.ETA_TYPE>,
-            ) => {
+            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_TO_PAY]: ({actor, actorType}: NextStepParams) => {
                 switch (actorType) {
                     case CONST.NEXT_STEP.ACTOR_TYPE.CURRENT_USER:
-                        return `精算の支払いを<strong>あなた</strong>が行うのを待っています。`;
+                        return `経費の支払いを<strong>あなた</strong>が行うのを待っています。`;
                     case CONST.NEXT_STEP.ACTOR_TYPE.OTHER_USER:
                         return `<strong>${actor}</strong> が経費を支払うのを待っています。`;
                     case CONST.NEXT_STEP.ACTOR_TYPE.UNSPECIFIED_ADMIN:
-                        return `管理者が経費を支払うのを待っています。`;
+                        return `管理者が経費を支払うのを待機中です。`;
                 }
             },
-            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_FOR_POLICY_BANK_ACCOUNT]: (
-                actor: string,
-                actorType: ValueOf<typeof CONST.NEXT_STEP.ACTOR_TYPE>,
-                _eta?: string,
-                _etaType?: ValueOf<typeof CONST.NEXT_STEP.ETA_TYPE>,
-            ) => {
+            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_FOR_POLICY_BANK_ACCOUNT]: ({actor, actorType}: NextStepParams) => {
                 switch (actorType) {
                     case CONST.NEXT_STEP.ACTOR_TYPE.CURRENT_USER:
-                        return `ビジネス銀行口座の設定が完了するのを<strong>お客様</strong>の操作待ちです。`;
+                        return `ビジネス銀行口座の設定が完了するのを<strong>あなた</strong>が終えるのを待っています。`;
                     case CONST.NEXT_STEP.ACTOR_TYPE.OTHER_USER:
                         return `<strong>${actor}</strong> がビジネス銀行口座の設定を完了するのを待っています。`;
                     case CONST.NEXT_STEP.ACTOR_TYPE.UNSPECIFIED_ADMIN:
-                        return `管理者がビジネス銀行口座の設定を完了するのを待っています。`;
+                        return `管理者がビジネス用銀行口座の設定を完了するのを待っています。`;
                 }
             },
-            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_FOR_PAYMENT]: (
-                _actor: string,
-                _actorType: ValueOf<typeof CONST.NEXT_STEP.ACTOR_TYPE>,
-                eta?: string,
-                etaType?: ValueOf<typeof CONST.NEXT_STEP.ETA_TYPE>,
-            ) => {
+            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_FOR_PAYMENT]: ({eta, etaType}: NextStepParams) => {
                 let formattedETA = '';
                 if (eta) {
-                    formattedETA = etaType === CONST.NEXT_STEP.ETA_TYPE.DATE_TIME ? `${eta}までに` : ` ${eta}`;
+                    formattedETA = etaType === CONST.NEXT_STEP.ETA_TYPE.DATE_TIME ? `${eta} まで` : ` ${eta}`;
                 }
                 return `支払いの完了を待機しています${formattedETA}。`;
             },
-            [CONST.NEXT_STEP.MESSAGE_KEY.SUBMITTING_TO_SELF]: (
-                _actor: string,
-                _actorType: ValueOf<typeof CONST.NEXT_STEP.ACTOR_TYPE>,
-                _eta?: string,
-                _etaType?: ValueOf<typeof CONST.NEXT_STEP.ETA_TYPE>,
-            ) =>
-                `おっと！<strong>ご自身</strong>に提出しようとしているようです。ご自分のレポートを承認することは、ワークスペースの設定により<strong>禁止</strong>されています。別の相手にこのレポートを提出するか、提出先の担当者を変更してもらうよう管理者に連絡してください。`,
-            [CONST.NEXT_STEP.MESSAGE_KEY.REJECTED_REPORT]: (
-                actor: string,
-                actorType: ValueOf<typeof CONST.NEXT_STEP.ACTOR_TYPE>,
-                _eta?: string,
-                _etaType?: ValueOf<typeof CONST.NEXT_STEP.ETA_TYPE>,
-            ) => {
-                switch (actorType) {
-                    case CONST.NEXT_STEP.ACTOR_TYPE.CURRENT_USER:
-                        return `このレポートは却下されました。問題を修正して手動で再提出していただくのを<strong>お待ちしています</strong>。`;
-                    case CONST.NEXT_STEP.ACTOR_TYPE.OTHER_USER:
-                        return `このレポートは却下されました。問題を修正して手動で再提出するのを<strong>${actor}</strong>さんを待っています。`;
-                    case CONST.NEXT_STEP.ACTOR_TYPE.UNSPECIFIED_ADMIN:
-                        return `このレポートは却下されました。管理者が問題を修正して手動で再提出するのを待っています。`;
-                }
-            },
+            [CONST.NEXT_STEP.MESSAGE_KEY.SUBMITTING_TO_SELF]: (_: NextStepParams) =>
+                `おっと！<strong>自分自身</strong>に提出しようとしているようです。ご利用のワークスペースでは、自分のレポートを承認することは<strong>禁止</strong>されています。別の人にこのレポートを提出するか、提出先の変更について管理者に連絡してください。`,
         },
         eta: {
             [CONST.NEXT_STEP.ETA_KEY.SHORTLY]: 'まもなく',
@@ -1949,8 +1754,6 @@ const translations: TranslationDeepObject<typeof en> = {
         offline: 'オフライン',
         syncing: '同期中',
         profileAvatar: 'プロフィールアバター',
-        customInstructions: 'カスタム指示',
-        copilotIntoAccount: 'アカウントにCopilot',
         publicSection: {
             title: '公開',
             subtitle: 'これらの詳細はあなたの公開プロフィールに表示され、誰でも閲覧できます。',
@@ -1959,16 +1762,12 @@ const translations: TranslationDeepObject<typeof en> = {
             title: '非公開',
             subtitle: 'これらの詳細は、旅行や支払いのために使用されます。あなたの公開プロフィールに表示されることは決してありません。',
         },
-        aiPromptSection: {
-            title: 'AIプロンプト',
-            subtitle: 'カスタム指示を作成',
-            prompt: 'プロンプト',
-            editPrompt: 'プロンプトを編集',
-            promptCannotBeEmpty: 'プロンプトを入力してください',
-            saved: '保存しました',
-        },
     },
-    securityPage: {title: 'セキュリティ', subtitle: 'アカウントを安全に保ちます。', goToSecurity: 'セキュリティページに戻る'},
+    securityPage: {
+        title: 'セキュリティオプション',
+        subtitle: 'アカウントを安全に保つために、2要素認証を有効にしてください。',
+        goToSecurity: 'セキュリティページに戻る',
+    },
     shareCodePage: {
         title: 'あなたのコード',
         subtitle: '自分のQRコードや紹介リンクを共有して、メンバーをExpensifyに招待しましょう。',
@@ -2005,7 +1804,6 @@ const translations: TranslationDeepObject<typeof en> = {
         },
         newContactMethod: '新しい連絡方法',
         goBackContactMethods: '連絡方法に戻る',
-        yourDefaultContactMethodRestrictedSwitch: 'これは現在のデフォルトの連絡方法です。会社により、これを削除または変更することは制限されています。',
     },
     pronouns: {
         coCos: '会社 / コスト',
@@ -2065,6 +1863,8 @@ const translations: TranslationDeepObject<typeof en> = {
         },
         troubleshoot: {
             clearCacheAndRestart: 'キャッシュをクリアして再起動',
+            viewConsole: 'デバッグコンソールを表示',
+            debugConsole: 'デバッグコンソール',
             description:
                 '<muted-text>以下のツールを使用して、Expensify のご利用状況のトラブルシューティングに役立ててください。問題が発生した場合は、<concierge-link>バグを報告</concierge-link>してください。</muted-text>',
             confirmResetDescription: '送信されていない下書きメッセージはすべて失われますが、その他のデータは安全です。',
@@ -2096,46 +1896,35 @@ const translations: TranslationDeepObject<typeof en> = {
             invalidateWithDelay: '遅延して無効化',
             leftHandNavCache: '左側ナビキャッシュ',
             clearleftHandNavCache: 'クリア',
+            recordTroubleshootData: 'トラブルシュートデータを記録',
             softKillTheApp: 'アプリをソフトキルする',
             kill: '終了',
             sentryDebug: 'Sentry デバッグ',
-            sentrySendDescription: 'Sentry にデータを送信',
             sentryDebugDescription: 'Sentry リクエストをコンソールに記録',
             sentryHighlightedSpanOps: '強調表示されたスパン名',
             sentryHighlightedSpanOpsPlaceholder: 'ui.interaction.click、ナビゲーション、ui.load',
-            showBranchNameInTitle: 'ブラウザのタイトルにブランチ名を表示',
+        },
+        debugConsole: {
+            saveLog: 'ログを保存',
+            shareLog: 'ログを共有',
+            enterCommand: 'コマンドを入力',
+            execute: '実行',
+            noLogsAvailable: 'ログはありません',
+            logSizeTooLarge: (size: number) => `ログサイズが上限の ${size} MB を超えています。"ログを保存" を使用してログファイルをダウンロードしてください。`,
+            logs: 'ログ',
+            viewConsole: 'コンソールを表示',
         },
         security: 'セキュリティ',
         signOut: 'サインアウト',
         restoreStashed: '保存済みログインを復元',
         signOutConfirmationText: 'サインアウトすると、オフライン中の変更内容はすべて失われます。',
         versionLetter: 'v',
-        readTheTermsAndPrivacy: `<a href="${CONST.OLD_DOT_PUBLIC_URLS.TERMS_URL}">利用規約</a>と<a href="${CONST.OLD_DOT_PUBLIC_URLS.PRIVACY_URL}">プライバシーポリシー</a>をお読みください。`,
+        readTheTermsAndPrivacy: `<muted-text-micro><a href="${CONST.OLD_DOT_PUBLIC_URLS.TERMS_URL}">利用規約</a>と<a href="${CONST.OLD_DOT_PUBLIC_URLS.PRIVACY_URL}">プライバシー</a>をお読みください。</muted-text-micro>`,
         help: 'ヘルプ',
         whatIsNew: '新機能',
         accountSettings: 'アカウント設定',
         account: 'アカウント',
         general: '一般',
-        helpPage: {
-            title: 'ヘルプとサポート',
-            description: '24時間いつでもサポートします。',
-            helpSite: 'ヘルプサイト',
-            helpSiteDescription: '記事、チュートリアルなど',
-            conciergeChat: 'Concierge',
-            conciergeChatDescription: 'あなたのパーソナルAIエージェント',
-            accountManager: 'アカウントマネージャー',
-            yourAccountManager: 'お客様のアカウントマネージャー',
-            accountManagerDescription: '質問してサポートを受ける',
-            partnerManager: 'パートナーマネージャー',
-            yourPartnerManager: 'パートナーマネージャー',
-            partnerManagerDescription: 'パートナーシップを最大限に活かし、紹介を促進しましょう',
-            guideDescription: 'お客様のアカウント担当者',
-            approvedPartnerTeamTitle: '承認済みパートナーチームをご紹介します',
-            approvedPartnerTeamDescription: '御社の成長支援、クライアントの迅速なオンボーディング、そして必要なときにいつでも受けられる専門的なサポートに特化した専任チームです。',
-            accountExecutive: 'アカウントエグゼクティブ',
-            accountExecutiveDescription: 'クライアントの導入を成功させる',
-            moreResources: 'その他のリソース',
-        },
     },
     closeAccountPage: {
         closeAccount: 'アカウントを閉じる',
@@ -2209,12 +1998,10 @@ const translations: TranslationDeepObject<typeof en> = {
         lockAccount: 'アカウントをロック',
         unlockAccount: 'アカウントのロック解除',
         compromisedDescription:
-            'アカウントにおかしな点がありますか？報告すると、すぐにアカウントがロックされ、新しい Expensify カードの取引がブロックされ、アカウントの変更もできなくなります。',
-        domainAdminsDescription: 'ドメイン管理者向け：これにより、ドメイン全体のすべての Expensify カードの利用と管理者による操作も一時停止されます。',
+            'アカウントにおかしな点がありますか？報告すると、アカウントが即座にロックされ、新しい Expensify Card での取引がブロックされ、アカウントの変更もできなくなります。',
+        domainAdminsDescription: 'ドメイン管理者向け：これにより、ドメイン内のすべての Expensify Card のアクティビティと管理者の操作も一時停止されます。',
         areYouSure: 'Expensify アカウントをロックしてもよろしいですか？',
         onceLocked: 'ロックされると、解除リクエストとセキュリティ審査が完了するまでアカウントは制限されます',
-        unlockTitle: 'リクエストを受け付けました',
-        unlockDescription: 'アカウントが安全にロック解除できることを確認するために審査し、質問がある場合はConciergeを通じてご連絡します。',
     },
     failedToLockAccountPage: {
         failedToLockAccount: 'アカウントのロックに失敗しました',
@@ -2227,34 +2014,27 @@ const translations: TranslationDeepObject<typeof en> = {
         chatToConciergeToUnlock: 'セキュリティに関する懸念を解決し、アカウントのロックを解除するには、Concierge とチャットしてください。',
         chatWithConcierge: 'Conciergeとチャット',
     },
-    deviceManagementPage: {
-        title: 'デバイス管理',
-        description:
-            'Expensify アカウントでログインしているすべてのデバイスを管理できます。<a href="https://help.expensify.com/articles/new-expensify/settings/Manage-Logged-in-Devices">詳しくはこちら</a>.',
-        revoke: '取り消す',
-        unknownDevice: '不明なデバイス',
-    },
     twoFactorAuth: {
         headerTitle: '2要素認証',
         twoFactorAuthEnabled: '2要素認証が有効になりました',
         whatIsTwoFactorAuth: '2要素認証（2FA）は、アカウントを安全に保つのに役立ちます。ログインする際、お好みの認証アプリで生成されたコードを入力する必要があります。',
         disableTwoFactorAuth: '2 要素認証を無効にする',
         explainProcessToRemove: '2要素認証（2FA）を無効にするには、認証アプリから有効なコードを入力してください。',
-        explainProcessToRemoveWithRecovery: '2要素認証（2FA）を無効にするには、有効な復旧コードを入力してください。',
+        explainProcessToRemoveWithRecovery: '2 要素認証（2FA）を無効にするには、有効なリカバリーコードを入力してください。',
         disabled: '二要素認証は現在無効になっています',
         noAuthenticatorApp: '今後、Expensify にログインする際に認証アプリは不要になります。',
         stepCodes: 'リカバリーコード',
-        keepCodesSafe: 'これらのコードを安全に保管してください。',
+        keepCodesSafe: 'これらのリカバリーコードを安全に保管してください！',
         codesLoseAccess: dedent(`
-            認証アプリへのアクセスを失い、これらのコードもお持ちでない場合は、アカウントにログインできなくなります。<br><br>
-            <strong>注意</strong>：2FA を有効にすると、他のすべてのセッションからログアウトされます。
+            認証アプリへのアクセスを失い、これらのコードも持っていない場合は、アカウントにアクセスできなくなります。
+
+            注: 二要素認証を設定すると、他のすべてのアクティブなセッションからログアウトされます。
         `),
         errorStepCodes: '続行する前にコードをコピーまたはダウンロードしてください',
         stepVerify: '確認',
         scanCode: '次の端末でQRコードをスキャンしてください:',
         authenticatorApp: '認証アプリ',
         addKey: 'または、この秘密キーを認証アプリに追加してください:',
-        secretKey: '秘密キー',
         enterCode: '次に、認証アプリで生成された6桁のコードを入力してください。',
         stepSuccess: '完了',
         enabled: '2要素認証が有効になりました',
@@ -2270,14 +2050,6 @@ const translations: TranslationDeepObject<typeof en> = {
         twoFactorAuthIsRequiredCompany: 'あなたの会社では、2 要素認証が必須です。',
         twoFactorAuthCannotDisable: '2要素認証を無効にできません',
         twoFactorAuthRequired: 'Xero 連携には二要素認証（2FA）が必須で、無効にすることはできません。',
-        replaceDevice: 'デバイスを交換',
-        replaceDeviceTitle: '2 要素認証デバイスを変更',
-        verifyOldDeviceTitle: '古い端末を確認',
-        verifyOldDeviceDescription: '現在使用している認証アプリに表示されている6桁のコードを入力して、アクセスできることを確認してください。',
-        verifyNewDeviceTitle: '新しいデバイスを設定',
-        verifyNewDeviceDescription: '新しいデバイスでQRコードをスキャンし、表示されたコードを入力して設定を完了してください。',
-        downloadCodes: 'コードをダウンロード',
-        copyCodes: 'コードをコピー',
     },
     recoveryCodeForm: {
         error: {
@@ -2365,39 +2137,6 @@ const translations: TranslationDeepObject<typeof en> = {
             password: 'Expensify のパスワードを入力してください',
         },
     },
-    personalCard: {
-        addPersonalCard: '個人カードを追加',
-        addCompanyCard: '会社カードを追加',
-        lookingForCompanyCards: '会社カードを追加する必要がありますか？',
-        lookingForCompanyCardsDescription: '世界中の10,000以上の銀行から自分のカードを追加できます。',
-        personalCardAdded: '個人カードが追加されました！',
-        personalCardAddedDescription: 'おめでとうございます。カードからの取引のインポートを開始します。',
-        isPersonalCard: 'これは個人カードですか？',
-        thisIsPersonalCard: 'これは個人カードです。',
-        thisIsCompanyCard: 'これは会社カードです。',
-        askAdmin: '管理者にお問い合わせください。',
-        warningDescription: ({isAdmin}: {isAdmin?: boolean}) =>
-            `その場合、問題ありません。ただし、<strong>会社</strong>カードの場合は、${isAdmin ? 'ワークスペースから割り当ててください。' : '管理者にワークスペースから割り当ててもらってください。'}`,
-        bankConnectionError: '銀行情報の接続に関する問題',
-        bankConnectionDescription: 'カードの追加を再度お試しください。または、',
-        connectWithPlaid: 'Plaid で接続できます。',
-        fixCard: 'カードを修正',
-        brokenConnection: 'カード接続が切断されています。',
-        conciergeBrokenConnection: ({cardName, connectionLink}: ConciergeBrokenCardConnectionParams) =>
-            connectionLink
-                ? `${cardName}カードとの接続が切れています。カードを修正するには、<a href="${connectionLink}">銀行にログイン</a>してください。`
-                : `${cardName}カードとの接続が切れています。カードを修正するには、銀行にログインしてください。`,
-        addAdditionalCards: '他のカードを追加',
-        upgradeDescription: 'さらにカードを追加しますか？ワークスペースを作成して、個人カードを追加するか、会社カードをチーム全体に割り当てることができます。',
-        onlyAvailableOnPlan: ({formattedPrice}: {formattedPrice: string}) =>
-            `<muted-text>Collect プランで利用可能で、1 メンバーあたり月額 <strong>${formattedPrice}</strong> です。</muted-text>`,
-        note: (subscriptionLink: string) =>
-            `<muted-text>この機能にアクセスするにはワークスペースを作成するか、<a href="${subscriptionLink}">プランと料金</a>の詳細をご確認ください。</muted-text>`,
-        workspaceCreated: 'ワークスペースが作成されました',
-        newWorkspace: 'ワークスペースを作成しました！',
-        successMessage: ({subscriptionLink}: {subscriptionLink: string}) =>
-            `<centered-text>追加のカードを追加する準備ができました。<a href="${subscriptionLink}">サブスクリプションを表示</a>して詳細をご確認ください。</centered-text>`,
-    },
     walletPage: {
         balance: '残高',
         paymentMethodsTitle: '支払方法',
@@ -2424,9 +2163,8 @@ const translations: TranslationDeepObject<typeof en> = {
         enableWallet: 'ウォレットを有効にする',
         addBankAccountToSendAndReceive: '支払いや入金を行うには銀行口座を追加してください。',
         addDebitOrCreditCard: 'デビットカードまたはクレジットカードを追加',
-        cardInactive: '非アクティブ',
-        assignedCards: 'カード',
-        assignedCardsDescription: '割り当てられたカードの取引は自動的に同期されます。',
+        assignedCards: '割り当て済みカード',
+        assignedCardsDescription: 'これらのカードからの取引は自動的に同期されます。',
         expensifyCard: 'Expensify カード',
         walletActivationPending: 'お客様の情報を確認しています。数分後にもう一度ご確認ください。',
         walletActivationFailed: '申し訳ありませんが、現在はウォレットを有効にできません。詳しいサポートについてはConciergeにチャットでお問い合わせください。',
@@ -2449,13 +2187,8 @@ const translations: TranslationDeepObject<typeof en> = {
         unshareBankAccount: '銀行口座の共有を解除',
         unshareBankAccountDescription: '以下の全員がこの銀行口座にアクセスできます。いつでもアクセス権を削除できます。進行中の支払いはそのまま完了します。',
         unshareBankAccountWarning: ({admin}: {admin?: string | null}) => `${admin} はこのビジネス銀行口座へのアクセス権を失います。処理中の支払いは引き続き完了します。`,
-        reachOutForHelp: 'Expensify カードで使用されています。共有を解除する必要がある場合は、<concierge-link>Concierge にお問い合わせください</concierge-link>。',
+        reachOutForHelp: 'そのレポートは Expensify Card と一緒に使用されています。共有を解除する必要がある場合は、<concierge-link>Concierge に連絡してください</concierge-link>。',
         unshareErrorModalTitle: '銀行口座の共有を解除できません',
-        travelCVV: {
-            title: 'トラベルCVV',
-            subtitle: '出張を予約するときにこれを使用してください',
-            description: 'このカードをExpensify Travelでの予約に使用してください。チェックアウト時には「Travel Card」と表示されます。',
-        },
         chaseAccountNumberDifferent: '口座番号が異なるのはなぜですか？',
     },
     cardPage: {
@@ -2464,15 +2197,15 @@ const translations: TranslationDeepObject<typeof en> = {
         availableSpend: '残りの上限',
         smartLimit: {
             name: 'スマート上限',
-            title: (formattedLimit: string) => `このカードでは最大で${formattedLimit}まで使用でき、提出した経費が承認されると、その限度額はリセットされます。`,
+            title: ({formattedLimit}: ViolationsOverLimitParams) => `このカードでは最大で${formattedLimit}まで使用でき、提出した経費が承認されると、その限度額はリセットされます。`,
         },
         fixedLimit: {
             name: '固定上限',
-            title: (formattedLimit: string) => `このカードでは最大で${formattedLimit}まで利用できます。その後、自動的に無効になります。`,
+            title: ({formattedLimit}: ViolationsOverLimitParams) => `このカードでは最大で${formattedLimit}まで利用できます。その後、自動的に無効になります。`,
         },
         monthlyLimit: {
             name: '月ごとの上限',
-            title: (formattedLimit: string) => `このカードでは月あたり最大 ${formattedLimit} まで利用できます。利用限度額は毎月、暦月の1日目にリセットされます。`,
+            title: ({formattedLimit}: ViolationsOverLimitParams) => `このカードでは月あたり最大 ${formattedLimit} まで利用できます。利用限度額は毎月、暦月の1日目にリセットされます。`,
         },
         virtualCardNumber: 'バーチャルカード番号',
         travelCardCvv: 'トラベルカードのCVV',
@@ -2493,17 +2226,16 @@ const translations: TranslationDeepObject<typeof en> = {
             expiration: '有効期限',
             cvv: 'CVV',
             address: '住所',
-            reveal: '表示',
             revealDetails: '詳細を表示',
             revealCvv: 'CVV を表示',
             copyCardNumber: 'カード番号をコピー',
-            copyCvv: 'CVV をコピー',
             updateAddress: '住所を更新',
         },
         cardAddedToWallet: ({platform}: {platform: 'Google' | 'Apple'}) => `${platform}ウォレットに追加しました`,
         cardDetailsLoadingFailure: 'カード詳細の読み込み中にエラーが発生しました。インターネット接続を確認して、もう一度お試しください。',
         validateCardTitle: 'ご本人確認を行います',
         enterMagicCode: (contactMethod: string) => `カード情報を表示するには、${contactMethod} に送信されたマジックコードを入力してください。1～2分以内に届きます。`,
+        missingPrivateDetails: ({missingDetailsLink}: {missingDetailsLink: string}) => `<a href="${missingDetailsLink}">個人情報を追加</a>してから、もう一度お試しください。`,
         unexpectedError: 'Expensifyカードの詳細を取得中にエラーが発生しました。もう一度お試しください。',
         cardFraudAlert: {
             confirmButtonText: 'はい、そうです',
@@ -2524,42 +2256,6 @@ const translations: TranslationDeepObject<typeof en> = {
 
 ${date} の ${merchant} への ${amount}`,
         },
-        setYourPin: 'PIN を設定.',
-        confirmYourPin: 'PIN を確認してください.',
-        changeYourPin: 'カードの新しい暗証番号を入力してください。',
-        confirmYourChangedPin: '新しい暗証番号を確認してください。',
-        pinMustBeFourDigits: 'PIN は 4 桁で入力してください。',
-        invalidPin: 'より安全な暗証番号を選択してください。',
-        pinMismatch: 'PIN が一致しません。もう一度お試しください。',
-        revealPin: 'PIN を表示',
-        hidePin: 'PIN を非表示',
-        pin: 'PIN',
-        changePin: 'PIN を変更',
-        pinChanged: 'PIN を変更しました！',
-        pinChangedHeader: 'PIN を変更しました',
-        pinChangedDescription: 'これで暗証番号をすぐにご利用いただけます。',
-        changePinAtATM: 'PIN は任意の ATM で変更できます',
-        changePinAtATMDescription: 'これはお住まいの地域では必須です。ご不明な点がある場合は<concierge-link>Concierge に連絡</concierge-link>してください。',
-        freezeCard: 'カードを一時停止',
-        unfreeze: '再開',
-        unfreezeCard: 'カードの一時停止を解除',
-        askToUnfreeze: '一時停止解除を依頼',
-        freezeDescription: '一時停止したカードは購入や取引に使用できません。いつでも再開できます。',
-        unfreezeDescription: 'このカードの一時停止を解除すると、購入と取引が再び可能になります。カードが安全に使用できると確信できる場合にのみ続行してください。',
-        frozen: '凍結中',
-        youFroze: ({date}: {date: string}) => `${date}にこのカードを一時停止しました。`,
-        frozenBy: ({person, date}: {person: string; date: string}) => `${person}が${date}にこのカードを一時停止しました。`,
-        frozenByAdminPrefix: ({date}: {date: string}) => `${date}にこのカードを一時停止したのは`,
-        frozenByAdminNeedsUnfreezePrefix: 'このカードは',
-        frozenByAdminNeedsUnfreezeSuffix: 'によって一時停止されました。解除するには管理者に連絡してください。',
-        frozenByAdminNeedsUnfreeze: ({person}: {person: string}) => `このカードは${person}によって一時停止されました。解除するには管理者に連絡してください。`,
-        spendRules: '支出ルール',
-        editSpendRules: '支出ルールを編集',
-        cardUnblocked: 'カードのブロックを解除しました！',
-        cardUnblockedDescription: '次回お買い物をされる際に、カードをリーダーに挿入するよう求められる場合があります。',
-        pinBlocked: '暗証番号の誤入力が続いたため、カードをブロックしました。',
-        unblock: 'ブロック解除',
-        unblockCard: 'カードのブロックを解除',
     },
     workflowsPage: {
         workflowTitle: '支出',
@@ -2571,14 +2267,9 @@ ${date} の ${merchant} への ${amount}`,
         addApprovalsTitle: '承認',
         accessibilityLabel: ({members, approvers}: {members: string; approvers: string}) => `${members} の経費で、承認者は ${approvers} です`,
         addApprovalButton: '承認ワークフローを追加',
-        editWorkflowAction: '編集',
-        addAgentAction: 'エージェントを追加',
-        findWorkflow: 'ワークフローを検索',
         addApprovalTip: 'より詳細なワークフローが存在する場合を除き、このデフォルトのワークフローがすべてのメンバーに適用されます。',
         approver: '承認者',
         addApprovalsDescription: '支払いを承認する前に、追加の承認を必須にする。',
-        automateApprovalsWithAgentsTitle: '代理を使って承認を自動化する',
-        automateApprovalsWithAgentsSubtitle: '承認を自動化するには、以下のエージェントをワークフローに追加してください。',
         makeOrTrackPaymentsTitle: '支払',
         makeOrTrackPaymentsDescription: 'Expensifyでの支払いに対する承認済み支払者を追加するか、他の場所で行われた支払いを記録します。',
         customApprovalWorkflowEnabled:
@@ -2623,15 +2314,7 @@ ${date} の ${merchant} への ${amount}`,
             title: '表示できるメンバーがいません',
             expensesFromSubtitle: 'すべてのワークスペースメンバーは、すでに既存の承認ワークフローに所属しています。',
             approverSubtitle: 'すべての承認者は、既存のワークフローに属しています。',
-            bulkApproverSubtitle: '選択されたレポートの条件に一致する承認者がいません。',
         },
-        configureViaHR: ({provider}: {provider: string}) => `${provider} で設定する。`,
-        hrApprovalWorkflowLockedPrompt: ({provider}: {provider: string}) =>
-            `承認は${provider}連携によって管理されています。承認ワークフローを更新するには、${provider}接続設定に移動してください。`,
-        goToHRSettings: ({provider}: {provider: string}) => `${provider}設定に移動`,
-        approverFromProvider: ({provider}: {provider: string}) => `${provider}から`,
-        finalApprover: '最終承認者',
-        manager: 'マネージャー',
     },
     workflowsDelayedSubmissionPage: {
         autoReportingFrequencyErrorMessage: '提出頻度を変更できませんでした。もう一度お試しいただくか、サポートまでご連絡ください。',
@@ -2651,9 +2334,6 @@ ${date} の ${merchant} への ${amount}`,
     workflowsExpensesFromPage: {
         title: '経費（開始日）',
         header: '次のメンバーが経費を提出したとき：',
-        memberAlreadyInWorkflowTitle: 'メンバーはすでにワークフローに属しています',
-        memberAlreadyInWorkflowPrompt: ({memberName, approverName}: {memberName: string; approverName: string}) =>
-            `${memberName}はすでに${approverName}に提出する承認ワークフローに属しています。ここに追加すると、このワークフローに移動します。`,
     },
     workflowsApproverPage: {
         genericErrorMessage: '承認者を変更できませんでした。もう一度お試しいただくか、サポートにお問い合わせください。',
@@ -2683,16 +2363,6 @@ ${date} の ${merchant} への ${amount}`,
         admins: '管理者',
         payer: '支払者',
         paymentAccount: '支払口座',
-        shareBankAccount: {
-            shareTitle: '銀行口座へのアクセスを共有しますか？',
-            shareDescription: ({admin}: {admin: string}) => `${admin}を支払人にするには、銀行口座へのアクセスを${admin}と共有する必要があります。`,
-            validationTitle: '銀行口座の検証待ち',
-            validationDescription: ({admin}: {admin: string}) =>
-                `<a href="#">この銀行口座を検証</a>する必要があります。検証が完了すると、銀行口座へのアクセス権を${admin}と共有して、支払人にすることができます。`,
-            errorTitle: '支払人を変更できません',
-            errorDescription: ({admin, owner}: {admin: string; owner: string}) =>
-                `${admin} はこの銀行口座へのアクセス権がないため、支払人に指定できません。銀行口座を共有する必要がある場合は、<a href="#">${owner} とチャットしてください。</a>`,
-        },
     },
     reportFraudPage: {
         title: 'バーチャルカードの不正利用を報告',
@@ -2703,7 +2373,6 @@ ${date} の ${merchant} への ${amount}`,
     reportFraudConfirmationPage: {
         title: 'カード不正利用を報告済み',
         description: '既存のカードは永久に無効化しました。カードの詳細画面に戻ると、新しいバーチャルカードが利用可能になっています。',
-        descriptionCardNotReplaced: 'カードは完全に無効化されました。新しいカードを発行するには管理者に連絡してください。',
         buttonText: '了解しました、ありがとうございます！',
     },
     activateCardPage: {
@@ -2713,7 +2382,7 @@ ${date} の ${merchant} への ${amount}`,
         error: {
             thatDidNotMatch: 'カードの下4桁が一致しませんでした。もう一度お試しください。',
             throttled:
-                'Expensify カードの下4桁の入力に複数回連続で失敗しました。番号が正しいと確信される場合は、問題解決のために Concierge へご連絡ください。それ以外の場合は、時間をおいてからもう一度お試しください。',
+                'Expensify Card の下4桁の入力ミスが多すぎます。番号が正しいと確信できる場合は、問題解決のため Concierge へお問い合わせください。それ以外の場合は、時間をおいてから再度お試しください。',
         },
     },
     getPhysicalCard: {
@@ -2738,7 +2407,7 @@ ${date} の ${merchant} への ${amount}`,
         shipCard: 'カードを発送',
     },
     transferAmountPage: {
-        transfer: (amount: string) => `振替${amount ? ` ${amount}` : ''}`,
+        transfer: ({amount}: TransferParams) => `振替${amount ? ` ${amount}` : ''}`,
         instant: '即時（デビットカード）',
         instantSummary: (rate: string, minAmount: string) => `${rate}%の手数料（最低${minAmount}）`,
         ach: '1〜3営業日（銀行口座）',
@@ -2765,46 +2434,14 @@ ${date} の ${merchant} への ${amount}`,
         defaultPaymentMethod: 'デフォルト',
         bankAccountLastFour: (lastFour: string) => `銀行口座・${lastFour}`,
     },
-    agentsPage: {
-        title: '担当者',
-        subtitle: 'ワークフローを処理するエージェントを作成しましょう。手作業を省いて、1日の時間を何時間も取り戻せます。',
-        newAgent: '新しいエージェント',
-        emptyAgents: {title: 'エージェントは作成されていません', subtitle: '手作業はやめて、代わりにエージェントに指示を出して、時間を大幅に節約しましょう。'},
-        error: {
-            genericAdd: 'このエージェントの追加中に問題が発生しました',
-            genericUpdate: 'このエージェントの更新中に問題が発生しました',
-            updateName: 'このエージェント名の更新中に問題が発生しました',
-            updatePrompt: 'このエージェントの指示を更新する際に問題が発生しました',
-            updateAvatar: 'このエージェントのアバターを更新する際に問題が発生しました',
-        },
-    },
-    addAgentPage: {
-        title: '新しいエージェント',
-        agentName: 'エージェント名',
-        instructions: 'カスタム指示を作成',
-        createAgent: 'エージェントを作成',
-        editAvatar: 'アバターを切り替え',
-        defaultAgentName: (displayName: string) => `${displayName} さんの代理人`,
-        defaultPrompt:
-            'ギャンブル、映画、またはその他明らかにビジネス目的ではない理由による経費は却下します。\n\nチップの金額が明確にわかるレシート画像を必ず添付するよう、ユーザーにリマインドします。\n\n同じユーザーの過去のレポートと非常によく似ている場合は、そのレポートを承認します。\n\n出張費が500ドルを超えるレポートは却下します。',
-    },
-    editAgentPage: {
-        title: 'エージェントを編集',
-        agentName: '担当者名',
-        instructions: 'カスタム手順を作成',
-        chatWithAgent: 'エージェントとチャット',
-        copilotIntoAccount: 'アカウントにコパイロット',
-        deleteAgent: 'エージェントを削除',
-        deleteAgentTitle: 'エージェントを削除しますか？',
-        deleteAgentMessage: 'このエージェントを削除してもよろしいですか？この操作は元に戻せません。',
-    },
-    editAgentAvatarPage: {title: 'アバターを編集'},
-    editAgentNamePage: {title: '担当者名'},
-    editAgentPromptPage: {title: 'カスタム手順を作成', error: {emptyPrompt: 'エージェントへの指示を入力してください。'}},
     expenseRulesPage: {
         title: '経費ルール',
+        subtitle: 'これらのルールはあなたの経費に適用されます。ワークスペースに提出した場合は、そのワークスペースのルールがこれらより優先されることがあります。',
         findRule: 'ルールを検索',
-        emptyRules: {title: 'まだルールがありません', subtitle: '経費レポートを自動化するルールを追加する'},
+        emptyRules: {
+            title: 'まだルールを作成していません',
+            subtitle: '経費レポートを自動化するルールを追加する',
+        },
         changes: {
             billableUpdate: (value: boolean) => `経費 ${value ? '請求可能' : '請求対象外'} を更新`,
             categoryUpdate: (value: string) => `カテゴリを「${value}」に更新`,
@@ -2845,7 +2482,6 @@ ${date} の ${merchant} への ${amount}`,
             deleteSinglePrompt: 'このルールを削除してもよろしいですか？',
             deleteMultiplePrompt: 'これらのルールを削除してもよろしいですか？',
         },
-        subtitle: 'これらのルールはあなたの経費に適用されます。',
     },
     preferencesPage: {
         appSection: {
@@ -2873,12 +2509,11 @@ ${date} の ${merchant} への ${amount}`,
         },
     },
     reportDetailsPage: {
-        inWorkspace: (policyName: string) => `${policyName} 内`,
+        inWorkspace: ({policyName}: ReportPolicyNameParams) => `${policyName} 内`,
         generatingPDF: 'PDFを生成',
         waitForPDF: 'PDF を作成しています。しばらくお待ちください。',
         errorPDF: 'PDF の生成中にエラーが発生しました',
         successPDF: 'PDFが作成されました！自動的にダウンロードされない場合は、下のボタンを使用してください。',
-        goToRoom: 'ルームに移動',
     },
     reportDescriptionPage: {
         roomDescription: '部屋の説明',
@@ -2888,7 +2523,7 @@ ${date} の ${merchant} への ${amount}`,
     groupChat: {
         lastMemberTitle: 'ご注意ください！',
         lastMemberWarning: 'ここにいる最後のメンバーのため、退出するとこのチャットには誰もアクセスできなくなります。本当に退出してもよろしいですか？',
-        defaultReportName: (displayName: string) => `${displayName}のグループチャット`,
+        defaultReportName: ({displayName}: ReportArchiveReasonsClosedParams) => `${displayName}のグループチャット`,
     },
     languagePage: {
         language: '言語',
@@ -2907,25 +2542,19 @@ ${date} の ${merchant} への ${amount}`,
                 label: 'デバイスの設定を使用',
             },
         },
-        highContrastMode: 'ハイコントラストモード',
-        enableHighContrast: 'ハイコントラストを有効にする',
-        disableHighContrast: 'ハイコントラストを無効にする',
         chooseThemeBelowOrSync: '以下からテーマを選択するか、デバイスの設定と同期してください。',
     },
     termsOfUse: {
         terms: `<muted-text-xs>ログインすると、<a href="${CONST.OLD_DOT_PUBLIC_URLS.TERMS_URL}">利用規約</a>および<a href="${CONST.OLD_DOT_PUBLIC_URLS.PRIVACY_URL}">プライバシーポリシー</a>に同意したものとみなされます。</muted-text-xs>`,
-        license: `資金移動サービスは、その<a href="${CONST.OLD_DOT_PUBLIC_URLS.LICENSES_URL}">認可</a>に基づき、${CONST.WALLET.PROGRAM_ISSUERS.EXPENSIFY_PAYMENTS}（NMLS ID:2017010）によって提供されています。`,
+        license: `<muted-text-xs>資金移動サービスは、その<a href="${CONST.OLD_DOT_PUBLIC_URLS.LICENSES_URL}">ライセンス</a>に基づき、${CONST.WALLET.PROGRAM_ISSUERS.EXPENSIFY_PAYMENTS}（NMLS ID:2017010）によって提供されています。</muted-text-xs>`,
     },
     validateCodeForm: {
         magicCodeNotReceived: 'マジックコードを受け取っていませんか？',
-        avoidScamsMessage: '<strong>詐欺に注意してください。コードを他人と共有しないでください。</strong> 当社スタッフがこのコードを電話・SMS・メールでお尋ねすることは決してありません。',
         enterAuthenticatorCode: '認証コードを入力してください',
         enterRecoveryCode: 'リカバリーコードを入力してください',
         requiredWhen2FAEnabled: '2要素認証が有効な場合は必須',
         requestNewCode: ({timeRemaining}: {timeRemaining: string}) => `<a>${timeRemaining}</a> 後に新しいコードをリクエストする`,
         requestNewCodeAfterErrorOccurred: '新しいコードをリクエスト',
-        timeRemainingAnnouncement: ({timeRemaining}) => `残り時間: ${timeRemaining}秒`,
-        timeExpiredAnnouncement: '時間切れです',
         error: {
             pleaseFillMagicCode: 'マジックコードを入力してください',
             incorrectMagicCode: '魔法コードが間違っているか無効です。もう一度お試しいただくか、新しいコードをリクエストしてください。',
@@ -2956,8 +2585,6 @@ ${date} の ${merchant} への ${amount}`,
         phoneOrEmail: '電話番号またはメールアドレス',
         error: {
             invalidFormatEmailLogin: '入力されたメールアドレスが無効です。形式を修正して、もう一度お試しください。',
-            agentSignInBlocked:
-                'エージェントアカウントには直接サインインすることはできません。エージェントを利用するには、ご自身のアカウントでサインインし、Copilot 経由でアクセスしてください。',
         },
         cannotGetAccountDetails: 'アカウントの詳細を取得できませんでした。もう一度サインインしてください。',
         loginForm: 'ログインフォーム',
@@ -2975,41 +2602,30 @@ ${date} の ${merchant} への ${amount}`,
         },
         getStarted: 'はじめる',
         whatsYourName: 'あなたの名前は何ですか？',
-        peopleYouMayKnow: 'あなたのチームが Expensify を利用しているか確認する',
-        workspaceYouMayJoin: (domain: string, email: string) => `${email} に送信されたコードを入力して、${domain} の誰かが参加できるワークスペースを持っているか確認します。`,
+        peopleYouMayKnow: '知り合いがすでにここに参加しています！一緒に参加するには、メールアドレスを確認してください。',
+        workspaceYouMayJoin: ({domain, email}: WorkspaceYouMayJoin) => `${domain} のユーザーがすでにワークスペースを作成しています。${email} に送信されたマジックコードを入力してください。`,
         joinAWorkspace: 'ワークスペースに参加',
-        listOfWorkspaces: '参加できるワークスペースの一覧です。',
-        skipForNow: '今はスキップ',
-        workspaceMemberList: (employeeCount: number, policyOwner: string) => `${employeeCount}人のメンバー${employeeCount > 1 ? 's' : ''}・${policyOwner}`,
+        listOfWorkspaces: '参加できるワークスペースの一覧です。今参加しなくても、後からいつでも参加できます。',
+        workspaceMemberList: ({employeeCount, policyOwner}: WorkspaceMemberList) => `${employeeCount}人のメンバー${employeeCount > 1 ? 's' : ''}・${policyOwner}`,
         whereYouWork: '勤務先はどこですか？',
         errorSelection: '次に進むオプションを選択してください',
         purpose: {
             title: '今日は何をしたいですか？',
             errorContinue: '続行を押してセットアップを完了してください',
             errorBackButton: 'アプリを使い始めるには、セットアップの質問にすべて回答してください',
-            [CONST.ONBOARDING_CHOICES.EMPLOYER]: '雇用主に経費を提出する',
+            [CONST.ONBOARDING_CHOICES.EMPLOYER]: '雇用主から立替金の精算を受ける',
             [CONST.ONBOARDING_CHOICES.MANAGE_TEAM]: 'チームの経費を管理',
-            [CONST.ONBOARDING_CHOICES.TRACK_BUSINESS]: 'ビジネスの経費を記録',
-            [CONST.ONBOARDING_CHOICES.TRACK_PERSONAL]: '個人の支出を管理',
+            [CONST.ONBOARDING_CHOICES.PERSONAL_SPEND]: '経費を記録・予算管理',
+            [CONST.ONBOARDING_CHOICES.CHAT_SPLIT]: '友だちとチャットして精算しよう',
             [CONST.ONBOARDING_CHOICES.LOOKING_AROUND]: 'その他',
         },
-        personalTrackGoal: {
-            title: '何を管理したいですか？',
-            [CONST.ONBOARDING_PERSONAL_TRACK_GOALS.INVESTMENT_TRACKING]: '投資用不動産の費用',
-            [CONST.ONBOARDING_PERSONAL_TRACK_GOALS.HOUSEHOLD_TRACKING]: '家計費',
-            [CONST.ONBOARDING_PERSONAL_TRACK_GOALS.SIDEPROJECT_TRACKING]: 'サイドプロジェクト経費',
-            [CONST.ONBOARDING_PERSONAL_TRACK_GOALS.SOMETHING_ELSE]: 'その他',
-            somethingElsePlaceholder: '何を記録しますか？',
-        },
         employees: {
             title: '従業員は何人いますか？',
-            [CONST.ONBOARDING_COMPANY_SIZE.MICRO_SMALL]: '1～4名の従業員',
-            [CONST.ONBOARDING_COMPANY_SIZE.MICRO_MEDIUM]: '5～10人の従業員',
             [CONST.ONBOARDING_COMPANY_SIZE.MICRO]: '従業員数 1～10 人',
-            [CONST.ONBOARDING_COMPANY_SIZE.SMALL]: '11～50名の従業員',
-            [CONST.ONBOARDING_COMPANY_SIZE.MEDIUM_SMALL]: '51～100人の従業員',
+            [CONST.ONBOARDING_COMPANY_SIZE.SMALL]: '従業員数 11～50 人',
+            [CONST.ONBOARDING_COMPANY_SIZE.MEDIUM_SMALL]: '従業員数 51～100 人',
             [CONST.ONBOARDING_COMPANY_SIZE.MEDIUM]: '101～1,000人の従業員',
-            [CONST.ONBOARDING_COMPANY_SIZE.LARGE]: '1,000人超の従業員',
+            [CONST.ONBOARDING_COMPANY_SIZE.LARGE]: '1,000人を超える従業員',
         },
         accounting: {
             title: '会計ソフトを利用していますか？',
@@ -3035,19 +2651,16 @@ ${date} の ${merchant} への ${amount}`,
         },
         workEmailValidation: {
             title: '勤務先メールを確認してください',
-            magicCodeSent: (workEmail: string | undefined) => `${workEmail} に送信されたマジックコードを入力してください。1～2分以内に届きます。`,
+            magicCodeSent: ({workEmail}: WorkEmailResendCodeParams) => `${workEmail} に送信されたマジックコードを入力してください。1～2分以内に届きます。`,
         },
         workEmailValidationError: {
             publicEmail: 'プライベートドメインの有効な勤務先メールアドレスを入力してください（例：mitch@company.com）',
-            sameAsSignupEmail: 'サインアップ時に使用したものとは別のメールアドレスを入力してください',
             offline: 'オフラインのため、勤務先のメールアドレスを追加できませんでした',
         },
         mergeBlockScreen: {
             title: '勤務用メールアドレスを追加できませんでした',
-            subtitle: (workEmail: string | undefined) =>
+            subtitle: ({workEmail}: WorkEmailMergingBlockedParams) =>
                 `${workEmail} を追加できませんでした。後で「設定」からもう一度お試しいただくか、ガイダンスについて Concierge にチャットでお問い合わせください。`,
-            workAccountClosedSubtitle:
-                'このメールアドレスに関連付けられている業務用アカウントは停止されています。再有効化するには会社の管理者にご連絡いただくか、別のメールアドレスでサインアップしてください。',
         },
         tasks: {
             testDriveAdminTask: {
@@ -3078,7 +2691,7 @@ ${date} の ${merchant} への ${amount}`,
             },
             createTestDriveAdminWorkspaceTask: {
                 title: ({workspaceConfirmationLink}) => `ワークスペースを[作成](${workspaceConfirmationLink})`,
-                description: 'ワークスペースを作成し、アカウントエグゼクティブのサポートを受けながら設定を行いましょう。',
+                description: 'ワークスペースを作成し、導入スペシャリストのサポートを受けながら設定を行いましょう！',
             },
             createWorkspaceTask: {
                 title: ({workspaceSettingsLink}) => `[ワークスペースを作成](${workspaceSettingsLink})`,
@@ -3094,13 +2707,13 @@ ${date} の ${merchant} への ${amount}`,
                 title: ({workspaceCategoriesLink}) => `[カテゴリ](${workspaceCategoriesLink})を設定`,
                 description: ({workspaceCategoriesLink}) =>
                     dedent(`
-                        経費をかんたんにレポートできるよう、チームが仕訳に使う*カテゴリを設定*しましょう。
+                        経費を簡単にレポートできるようにするため、チームが仕訳できるよう*カテゴリを設定*しましょう。
 
                         1. *ワークスペース*をクリックします。
                         2. 自分のワークスペースを選択します。
                         3. *カテゴリ*をクリックします。
                         4. 不要なカテゴリを無効にします。
-                        5. 右上から独自のカテゴリを追加します。
+                        5. 右上で独自のカテゴリを追加します。
 
                         [ワークスペースのカテゴリ設定に移動](${workspaceCategoriesLink})。
                     `),
@@ -3110,7 +2723,7 @@ ${date} の ${merchant} への ${amount}`,
                 description: dedent(`
                     金額を入力するかレシートをスキャンして、*経費を提出*しましょう。
 
-                    1. *+* ボタンをクリックします。
+                    1. ${CONST.CUSTOM_EMOJIS.GLOBAL_CREATE} ボタンをクリックします。
                     2. *経費を作成* を選択します。
                     3. 金額を入力するか、レシートをスキャンします。
                     4. 上司のメールアドレスまたは電話番号を追加します。
@@ -3124,7 +2737,7 @@ ${date} の ${merchant} への ${amount}`,
                 description: dedent(`
                     金額を入力するか、領収書をスキャンして*経費を提出*します。
 
-                    1. *+* ボタンをクリックします。
+                    1. ${CONST.CUSTOM_EMOJIS.GLOBAL_CREATE} ボタンをクリックします。
                     2. *経費を作成* を選択します。
                     3. 金額を入力するか、領収書をスキャンします。
                     4. 詳細を確認します。
@@ -3138,7 +2751,7 @@ ${date} の ${merchant} への ${amount}`,
                 description: dedent(`
                     領収書の有無にかかわらず、どの通貨でも*経費を記録*できます。
 
-                    1. *+* ボタンをクリックします。
+                    1. ${CONST.CUSTOM_EMOJIS.GLOBAL_CREATE} ボタンをクリックします。
                     2. *経費を作成* を選択します。
                     3. 金額を入力するか、領収書をスキャンします。
                     4. *個人*スペースを選択します。
@@ -3160,8 +2773,13 @@ ${integrationName === CONST.ONBOARDING_ACCOUNTING_MAPPING.other ? 'あなたの'
                         4. ${integrationName} を探します。
                         5.「*接続*」をクリックします。
 
-                        [経理画面に移動](${workspaceAccountingLink})。
-                    `),
+${
+    integrationName && CONST.connectionsVideoPaths[integrationName]
+        ? `[会計画面へ移動](${workspaceAccountingLink})。
+
+                        ![${integrationName} に接続](${CONST.CLOUDFRONT_URL}/${CONST.connectionsVideoPaths[integrationName]})`
+        : `[経理画面に移動](${workspaceAccountingLink})。`
+}`),
             },
             connectCorporateCardTask: {
                 title: ({corporateCardLink}) => `[法人カード](${corporateCardLink})を連携`,
@@ -3180,13 +2798,13 @@ ${integrationName === CONST.ONBOARDING_ACCOUNTING_MAPPING.other ? 'あなたの'
                 title: ({workspaceMembersLink}) => `[チームを招待する](${workspaceMembersLink})`,
                 description: ({workspaceMembersLink}) =>
                     dedent(`
-                        *チームを招待*して、今すぐ経費の記録を始めてもらいましょう。
+                        *チームを招待*して、今日から経費の記録を始めましょう。
 
                         1. *ワークスペース*をクリックします。
-                        2. ワークスペースを選択します。
+                        2. 自分のワークスペースを選択します。
                         3. *メンバー* > *メンバーを招待* をクリックします。
                         4. メールアドレスまたは電話番号を入力します。
-                        5. 必要に応じて、招待メッセージをカスタマイズしてください。
+                        5. 必要に応じて、招待メッセージを追加します。
 
                         [ワークスペースのメンバー画面へ移動](${workspaceMembersLink})。
                     `),
@@ -3203,14 +2821,14 @@ ${integrationName === CONST.ONBOARDING_ACCOUNTING_MAPPING.other ? 'あなたの'
                 title: ({workspaceTagsLink}) => `[tag](${workspaceTagsLink})を設定`,
                 description: ({workspaceMoreFeaturesLink}) =>
                     dedent(`
-                        タグを使って、プロジェクト、クライアント、所在地、部署などの追加経費情報を管理しましょう。タグを複数階層で使いたい場合は、Control プランにアップグレードできます。
+                        タグを使用して、プロジェクト、クライアント、所在地、部門などの経費の詳細を追加できます。タグを複数階層で使いたい場合は、Control プランにアップグレードできます。
 
-                        1. *Workspaces* をクリックします。
+                        1. 「ワークスペース」をクリックします。
                         2. ワークスペースを選択します。
-                        3. *More features* をクリックします。
-                        4. *Tags* を有効にします。
-                        5. ワークスペースエディタ内の *Tags* に移動します。
-                        6. *+ Add tag* をクリックして、独自のタグを作成します。
+                        3. 「その他の機能」をクリックします。
+                        4. 「タグ」を有効にします。
+                        5. ワークスペースエディタで「タグ」に移動します。
+                        6. 「+ タグを追加」をクリックして独自のタグを作成します。
 
                         [その他の機能に移動](${workspaceMoreFeaturesLink})。
 
@@ -3235,7 +2853,7 @@ ${integrationName === CONST.ONBOARDING_ACCOUNTING_MAPPING.other ? 'あなたの'
                 description: dedent(`
                     メールアドレスまたは電話番号を使って、誰とでも*チャットを開始*できます。
 
-                    1. *+* ボタンをクリックします。
+                    1. ${CONST.CUSTOM_EMOJIS.GLOBAL_CREATE} ボタンをクリックします。
                     2. *チャットを開始* を選択します。
                     3. メールアドレスまたは電話番号を入力します。
 
@@ -3249,7 +2867,7 @@ ${integrationName === CONST.ONBOARDING_ACCOUNTING_MAPPING.other ? 'あなたの'
                 description: dedent(`
                     1人または複数の人と*経費を分割*しましょう。
 
-                    1. *+* ボタンをクリックします。
+                    1. ${CONST.CUSTOM_EMOJIS.GLOBAL_CREATE} ボタンをクリックします。
                     2. *チャットを開始*を選択します。
                     3. メールアドレスまたは電話番号を入力します。
                     4. チャット画面でグレーの *+* ボタンをクリックし、*経費の分割*を選択します。
@@ -3273,7 +2891,7 @@ ${integrationName === CONST.ONBOARDING_ACCOUNTING_MAPPING.other ? 'あなたの'
                 description: dedent(`
                     レポートの作成方法は次のとおりです：
 
-                    1. *+* ボタンをクリックします。
+                    1. ${CONST.CUSTOM_EMOJIS.GLOBAL_CREATE} ボタンをクリックします。
                     2. 「レポートを作成」を選択します。
                     3. 「経費を追加」をクリックします。
                     4. 最初の経費を追加します。
@@ -3295,16 +2913,19 @@ ${integrationName === CONST.ONBOARDING_ACCOUNTING_MAPPING.other ? 'あなたの'
             onboardingManageTeamMessage: ({isOnboardingFlow = false}: {isOnboardingFlow?: boolean}) =>
                 isOnboardingFlow
                     ? dedent(`
-                        # 無料トライアルが開始されました！セットアップを始めましょう。
-                        👋 こんにちは、私はあなたの Expensify アカウントエグゼクティブです。すでにチームの領収書と経費を管理するためのワークスペースを作成済みです。30日間の無料トライアルを最大限に活用するために、以下の残りのセットアップ手順に沿って進めてください。
+                        # 無料トライアルが開始されました！さっそく設定を始めましょう。
+                        👋 こんにちは、私はあなたのExpensifyセットアップ担当です。すでにチームの領収書と経費を管理するためのワークスペースを作成しました。30日間の無料トライアルを最大限に活用するには、残りの設定ステップにしたがって進めてください！
                     `)
                     : dedent(`
-                        # 無料トライアルが開始しました！セットアップを始めましょう。
-                        👋 こんにちは、私はあなたの Expensify アカウントエグゼクティブです。ワークスペースを作成いただいたので、下記の手順に従って 30 日間の無料トライアルを最大限に活用しましょう！
+                        # 無料トライアルが開始されました！セットアップを始めましょう。
+                        👋 はじめまして。私は Expensify のセットアップ担当です。ワークスペースを作成したので、以下の手順に沿って 30 日間の無料トライアルを最大限に活用しましょう！
                     `),
-            onboardingTrackWorkspaceMessage: '30日間の無料トライアルを最大限に活用するために、以下の残りの手順に従ってください。',
+            onboardingTrackWorkspaceMessage:
+                '# セットアップを始めましょう\n👋 こんにちは、私はあなたのExpensifyセットアップ担当です。すでに領収書と経費を管理するためのワークスペースを作成してあります。30日間の無料トライアルを最大限に活用するために、残りのセットアップ手順に従って進めてください！',
             onboardingChatSplitMessage: '友だちとの割り勘は、メッセージを送るくらい簡単です。やり方はこちら。',
             onboardingAdminMessage: '管理者としてチームのワークスペースを管理し、自分の経費を提出する方法を学びましょう。',
+            onboardingLookingAroundMessage:
+                'Expensify は、経費精算、出張、法人カード管理でよく知られていますが、それだけにとどまりません。ご興味のあることを教えていただければ、始められるようお手伝いします。',
             onboardingTestDriveReceiverMessage: '*3か月無料でご利用いただけます！下から始めましょう。*',
         },
         workspace: {
@@ -3315,7 +2936,7 @@ ${integrationName === CONST.ONBOARDING_ACCOUNTING_MAPPING.other ? 'あなたの'
                 descriptionTwo: '経費を分類してタグ付けする',
                 descriptionThree: 'レポートを作成して共有',
             },
-            price: (price?: string) => `まずは30日間無料でお試しいただき、その後はわずか<strong>${price ?? '$5'}/ユーザー/月</strong>でアップグレードできます。`,
+            price: 'まずは30日間無料でお試しいただき、その後はわずか<strong>$5/ユーザー/月</strong>でアップグレードできます。',
             createWorkspace: 'ワークスペースを作成',
         },
         confirmWorkspace: {
@@ -3326,8 +2947,6 @@ ${integrationName === CONST.ONBOARDING_ACCOUNTING_MAPPING.other ? 'あなたの'
             title: 'メンバーを招待',
             subtitle: 'チームを追加するか、会計士を招待しましょう。人数が多いほど、もっと便利になります！',
         },
-        workEmail2FAError: 'このログインは、二要素認証（2FA）が有効になっている既存のアカウントです。',
-        singleSignOnError: 'このログインは、SSO／SAML が有効になっている既存のアカウントです。',
     },
     featureTraining: {
         doNotShowAgain: '今後このメッセージを表示しない',
@@ -3347,7 +2966,6 @@ ${integrationName === CONST.ONBOARDING_ACCOUNTING_MAPPING.other ? 'あなたの'
         enterPhoneNumber: '電話番号は何ですか？',
         personalDetails: '個人情報',
         privateDataMessage: 'これらの詳細は出張と支払いに使用されます。公開プロフィールに表示されることは決してありません。',
-        basicDetails: '基本情報',
         legalName: '法的氏名',
         legalFirstName: '法的な名',
         legalLastName: '法的な姓',
@@ -3356,18 +2974,19 @@ ${integrationName === CONST.ONBOARDING_ACCOUNTING_MAPPING.other ? 'あなたの'
             dateShouldBeBefore: (dateString: string) => `日付は${dateString}より前である必要があります`,
             dateShouldBeAfter: (dateString: string) => `日付は${dateString}より後の日付にしてください`,
             hasInvalidCharacter: '名前にはラテン文字のみ使用できます',
-            cannotIncludeCommaOrSemicolon: '名前にコンマまたはセミコロンを含めることはできません',
             incorrectZipFormat: (zipFormat?: string) => `郵便番号の形式が正しくありません${zipFormat ? `使用可能な形式：${zipFormat}` : ''}`,
             invalidPhoneNumber: `電話番号が有効であることを確認してください（例：${CONST.EXAMPLE_PHONE_NUMBER}）`,
         },
     },
     resendValidationForm: {
         linkHasBeenResent: 'リンクを再送信しました',
-        weSentYouMagicSignInLink: (login: string, loginType: string) => `${login} にマジックサインインリンクを送信しました。サインインするには ${loginType} を確認してください。`,
+        weSentYouMagicSignInLink: ({login, loginType}: WeSentYouMagicSignInLinkParams) =>
+            `${login} にマジックサインインリンクを送信しました。サインインするには ${loginType} を確認してください。`,
         resendLink: 'リンクを再送',
     },
     unlinkLoginForm: {
-        toValidateLogin: (primaryLogin: string, secondaryLogin: string) => `${secondaryLogin} を確認するには、${primaryLogin} のアカウント設定からマジックコードを再送してください。`,
+        toValidateLogin: ({primaryLogin, secondaryLogin}: ToValidateLoginParams) =>
+            `${secondaryLogin} を確認するには、${primaryLogin} のアカウント設定からマジックコードを再送してください。`,
         noLongerHaveAccess: (primaryLogin: string) => `${primaryLogin} にアクセスできなくなった場合は、アカウントの連携を解除してください。`,
         unlink: 'リンク解除',
         linkSent: 'リンクを送信しました！',
@@ -3424,12 +3043,14 @@ ${integrationName === CONST.ONBOARDING_ACCOUNTING_MAPPING.other ? 'あなたの'
     },
     welcomeSignUpForm: {
         join: '参加',
-        marketingSMSConsent: 'Expensifyからのマーケティングテキストの受信に同意します',
     },
     detailsPage: {
         localTime: '現地時間',
     },
-    newChatPage: {startGroup: 'グループを開始', addToGroup: 'グループに追加', addUserToGroup: (username: string) => `${username} をグループに追加`},
+    newChatPage: {
+        startGroup: 'グループを開始',
+        addToGroup: 'グループに追加',
+    },
     yearPickerPage: {
         year: '年',
         selectYear: '年を選択してください',
@@ -3472,18 +3093,17 @@ ${integrationName === CONST.ONBOARDING_ACCOUNTING_MAPPING.other ? 'あなたの'
             custom: 'カスタム',
         },
         untilTomorrow: '明日まで',
-        untilTime: (time: string) => `${time}まで`,
+        untilTime: ({time}: UntilTimeParams) => `${time}まで`,
         date: '日付',
         time: '時間',
         clearAfter: 'クリアまでの時間',
         whenClearStatus: 'ステータスをいつクリアしますか？',
+        vacationDelegate: '休暇代理人',
         setVacationDelegate: `休暇中に不在の間、あなたに代わってレポートを承認する代理人を設定しましょう。`,
-        cannotSetVacationDelegate: `現在、次のメンバーの代理人になっているため、休暇代理人を設定できません：`,
-        addVacationDelegate: '休暇代理人を追加',
         vacationDelegateError: '休暇の代理人を更新中にエラーが発生しました。',
-        asVacationDelegate: (nameOrEmail: string) => `${nameOrEmail} さんの休暇代理として`,
-        toAsVacationDelegate: (submittedToName: string, vacationDelegateName: string) => `${vacationDelegateName} の休暇代理人として ${submittedToName} に`,
-        vacationDelegateWarning: (nameOrEmail: string) =>
+        asVacationDelegate: ({nameOrEmail}: VacationDelegateParams) => `${nameOrEmail} さんの休暇代理として`,
+        toAsVacationDelegate: ({submittedToName, vacationDelegateName}: SubmittedToVacationDelegateParams) => `${vacationDelegateName} の休暇代理人として ${submittedToName} に`,
+        vacationDelegateWarning: ({nameOrEmail}: VacationDelegateParams) =>
             `${nameOrEmail} さんをあなたの休暇代理人に指定しようとしています。この人は、まだすべてのワークスペースに参加していません。続行すると、すべてのワークスペース管理者に、この人を追加するようメールが送信されます。`,
     },
     stepCounter: ({step, total, text}: StepCounterParams) => {
@@ -3512,35 +3132,23 @@ ${integrationName === CONST.ONBOARDING_ACCOUNTING_MAPPING.other ? 'あなたの'
         connectManually: '手動で接続',
         desktopConnection: '注意：Chase、Wells Fargo、Capital One、または Bank of America と接続するには、ブラウザでこの手続きを完了するためにこちらをクリックしてください。',
         yourDataIsSecure: 'お客様のデータは安全です',
-        toGetStarted: '銀行口座を追加して、経費の精算、Expensify カードの発行、請求書の入金管理、請求書の支払いをすべて一括で行いましょう。',
+        toGetStarted: '銀行口座を追加して、経費の精算、Expensifyカードの発行、請求書の回収、支払いをすべて一か所で行いましょう。',
         plaidBodyCopy: '従業員に、会社の経費を支払うのも立て替え精算を受けるのも、より簡単な方法を提供しましょう。',
         checkHelpLine: '口座のルーティング番号と口座番号は、その口座の小切手に記載されています。',
-        bankAccountPurposeTitle: '銀行口座で何をしたいですか？',
-        getReimbursed: '払い戻しを受ける',
-        getReimbursedDescription: '雇用主または他の人から',
-        makePayments: '支払いを行う',
-        makePaymentsDescription: '経費の支払いまたは Expensify カードの発行',
         hasPhoneLoginError: (contactMethodRoute: string) =>
             `銀行口座を連携するには、まず<a href="${contactMethodRoute}">メールアドレスをプライマリログインとして追加</a>してから、もう一度お試しください。電話番号はセカンダリログインとして追加できます。`,
         hasBeenThrottledError: '銀行口座の追加中にエラーが発生しました。数分待ってから、もう一度お試しください。',
-        hasCurrencyError: (workspaceRoute: string) =>
+        hasCurrencyError: ({workspaceRoute}: WorkspaceRouteParams) =>
             `おっと！ワークスペースの通貨がUSD以外に設定されているようです。続行するには、<a href="${workspaceRoute}">ワークスペース設定</a>で通貨をUSDに変更してから、もう一度お試しください。`,
         bbaAdded: 'ビジネス用銀行口座を追加しました！',
         bbaAddedDescription: '支払いに利用できる状態です。',
-        lockedBankAccount: 'ロックされた銀行口座',
-        unlockBankAccount: '銀行口座を解除する',
-        youCantPayThis: `このレポートは支払えません。<a href="${CONST.UNLOCK_BANK_ACCOUNT_HELP_URL}">ロックされた銀行口座</a>があるためです。下をタップすると、コンシェルジュが解除の手続きを案内します。`,
-        htmlUnlockMessage: (maskedAccountNumber: string) =>
-            `<h1>Expensify Business Bank Account ${maskedAccountNumber}</h1><p>銀行口座のロック解除リクエストを送信いただきありがとうございます。出金リクエストは、残高不足や銀行口座が口座振替に対応していない場合に拒否されることがあります。お客様のケースを確認し、問題解決のために追加情報が必要な場合はご連絡いたします。</p>`,
-        textUnlockMessage: (maskedAccountNumber: string) =>
-            `Expensify Business Bank Account ${maskedAccountNumber}\n銀行口座のロック解除リクエストを送信いただきありがとうございます。出金リクエストは、残高不足や銀行口座が口座振替に対応していない場合に拒否されることがあります。お客様のケースを確認し、問題解決のために追加情報が必要な場合はご連絡いたします。`,
         error: {
             youNeedToSelectAnOption: '続行するオプションを選択してください',
             noBankAccountAvailable: '申し訳ありませんが、利用可能な銀行口座がありません',
             noBankAccountSelected: 'アカウントを選択してください',
             taxID: '有効な納税者番号を入力してください',
             website: '有効なウェブサイトを入力してください',
-            zipCode: `有効なZIPコードを、次の形式で入力してください: ${COMMON_CONST.COUNTRY_ZIP_REGEX_DATA.US.samples}`,
+            zipCode: `有効なZIPコードを、次の形式で入力してください: ${CONST.COUNTRY_ZIP_REGEX_DATA.US.samples}`,
             phoneNumber: '有効な電話番号を入力してください',
             email: '有効なメールアドレスを入力してください',
             companyName: '有効な会社名を入力してください',
@@ -3566,7 +3174,7 @@ ${integrationName === CONST.ONBOARDING_ACCOUNTING_MAPPING.other ? 'あなたの'
             validationAmounts: '入力した検証用金額が正しくありません。銀行明細書をもう一度確認してから、再度お試しください。',
             fullName: '有効な氏名を入力してください',
             ownershipPercentage: '有効なパーセント数値を入力してください',
-            deletePaymentBankAccount: 'この銀行口座は Expensify カードの支払いに使用されているため、削除できません。この口座を削除したい場合は、Concierge までご連絡ください。',
+            deletePaymentBankAccount: 'この銀行口座は、Expensify Card の支払いに使用されているため削除できません。この口座をそれでも削除したい場合は、Concierge までご連絡ください。',
             sameDepositAndWithdrawalAccount: '入金口座と出金口座が同じです。',
         },
     },
@@ -3581,11 +3189,6 @@ ${integrationName === CONST.ONBOARDING_ACCOUNTING_MAPPING.other ? 'あなたの'
         confirmationStepHeader: '情報を確認してください。',
         confirmationStepSubHeader: '下記の詳細を再確認し、利用規約のチェックボックスをオンにして確定してください。',
         toGetStarted: '個人の銀行口座を追加して、経費精算の受け取りや請求書の支払い、Expensifyウォレットの有効化を行いましょう。',
-        updatePersonalInfo: '銀行口座を更新',
-        updatePersonalInfoFailure: '銀行口座情報を更新できませんでした。後でもう一度お試しください。',
-        updateSuccessTitle: '銀行口座が更新されました!',
-        updateSuccessHeader: '銀行口座が更新されました',
-        updateSuccessMessage: 'おめでとうございます。銀行口座の設定が完了し、精算の受け取りができるようになりました。',
     },
     addPersonalBankAccountPage: {
         enterPassword: 'Expensify のパスワードを入力',
@@ -3613,8 +3216,8 @@ ${integrationName === CONST.ONBOARDING_ACCOUNTING_MAPPING.other ? 'あなたの'
     messages: {
         errorMessageInvalidPhone: `かっこやハイフンを含まない有効な電話番号を入力してください。米国外の場合は、国番号を含めて入力してください（例：${CONST.EXAMPLE_PHONE_NUMBER}）。`,
         errorMessageInvalidEmail: '無効なメールアドレス',
-        userIsAlreadyMember: (login: string, name: string) => `${login} はすでに ${name} のメンバーです`,
-        userIsAlreadyAnAdmin: (login: string, name: string) => `${login} はすでに ${name} の管理者です`,
+        userIsAlreadyMember: ({login, name}: UserIsAlreadyMemberParams) => `${login} はすでに ${name} のメンバーです`,
+        userIsAlreadyAnAdmin: ({login, name}: UserIsAlreadyMemberParams) => `${login} はすでに ${name} の管理者です`,
     },
     onfidoStep: {
         acceptTerms: 'Expensifyウォレット有効化のリクエストを続行することで、お客様は次の内容を読み、理解し、同意したものとみなされます',
@@ -3660,7 +3263,7 @@ ${integrationName === CONST.ONBOARDING_ACCOUNTING_MAPPING.other ? 'あなたの'
         haveReadAndAgreePlain: '電子開示を受け取ることを読み理解し、同意します。',
         haveReadAndAgree: `<a href="${CONST.ELECTRONIC_DISCLOSURES_URL}">電子開示書面</a>を受け取ることを確認し、同意します。`,
         agreeToThePlain: 'プライバシーおよびウォレット規約に同意します。',
-        agreeToThe: (walletAgreementUrl: string) =>
+        agreeToThe: ({walletAgreementUrl}: WalletAgreementParams) =>
             `<a href="${CONST.OLD_DOT_PUBLIC_URLS.PRIVACY_URL}">プライバシーポリシー</a>および<a href="${walletAgreementUrl}">ウォレット利用規約</a>に同意します。`,
         enablePayments: '支払いを有効にする',
         monthlyFee: '月額料金',
@@ -3672,7 +3275,7 @@ ${integrationName === CONST.ONBOARDING_ACCOUNTING_MAPPING.other ? 'あなたの'
         checkTheBoxes: '以下のチェックボックスを選択してください。',
         agreeToTerms: '利用規約に同意すれば、すぐに始められます！',
         shortTermsForm: {
-            expensifyPaymentsAccount: (walletProgram: string) => `Expensifyウォレットは${walletProgram}によって発行されています。`,
+            expensifyPaymentsAccount: ({walletProgram}: WalletProgramParams) => `Expensifyウォレットは${walletProgram}によって発行されています。`,
             perPurchase: '購入ごと',
             atmWithdrawal: 'ATM引き出し',
             cashReload: '現金リロード',
@@ -3686,7 +3289,7 @@ ${integrationName === CONST.ONBOARDING_ACCOUNTING_MAPPING.other ? 'あなたの'
             generalInfo: `プリペイド口座に関する一般的な情報については、<a href="${CONST.CFPB_PREPAID_URL}">${CONST.TERMS.CFPB_PREPAID}</a>をご覧ください。`,
             conditionsDetails: `すべての手数料およびサービスの詳細と条件については、<a href="${CONST.FEES_URL}">${CONST.FEES_URL}</a> にアクセスするか、+1 833-400-0904 までお電話ください。`,
             electronicFundsWithdrawalInstant: '電子資金引き落とし（即時）',
-            electronicFundsInstantFeeMin: (amount: string) => `(最小 ${amount})`,
+            electronicFundsInstantFeeMin: ({amount}: TermsParams) => `(最小 ${amount})`,
         },
         longTermsForm: {
             listOfAllFees: 'すべてのExpensifyウォレット手数料の一覧',
@@ -3706,7 +3309,7 @@ ${integrationName === CONST.ONBOARDING_ACCOUNTING_MAPPING.other ? 'あなたの'
             electronicFundsInstantDetails: (percentage: string, amount: string) =>
                 '即時振込オプションを使用してExpensifyウォレットからリンク済みのデビットカードへ資金を振り替える場合、手数料が発生します。この振替は通常、数分以内に完了します。' +
                 `手数料は振込金額の${percentage}%（最低手数料は${amount}）です。`,
-            fdicInsuranceBancorp: (amount: string) =>
+            fdicInsuranceBancorp: ({amount}: TermsParams) =>
                 `お客さまの資金はFDIC保険の対象となります。お客さまの資金はFDIC保険の対象となる金融機関である${CONST.WALLET.PROGRAM_ISSUERS.BANCORP_BANK}に保管されるか、または同機関へ振替えられます。` +
                 `そこに移された資金は、特定の預金保険要件を満たし、かつカードが登録されている場合に限り、${CONST.WALLET.PROGRAM_ISSUERS.BANCORP_BANK} が破綻したときでも、FDIC により最大 ${amount} まで保険で保護されます。詳細は ${CONST.TERMS.FDIC_PREPAID} をご覧ください。`,
             contactExpensifyPayments: `${CONST.WALLET.PROGRAM_ISSUERS.EXPENSIFY_PAYMENTS} には、+1 833-400-0904 へのお電話、${CONST.EMAIL.CONCIERGE} へのメール、または ${CONST.NEW_EXPENSIFY_URL} へのサインインでお問い合わせください。`,
@@ -3715,7 +3318,7 @@ ${integrationName === CONST.ONBOARDING_ACCOUNTING_MAPPING.other ? 'あなたの'
             automated: '自動',
             liveAgent: 'ライブ担当者',
             instant: '即時',
-            electronicFundsInstantFeeMin: (amount: string) => `最小 ${amount}`,
+            electronicFundsInstantFeeMin: ({amount}: TermsParams) => `最小 ${amount}`,
         },
     },
     activateStep: {
@@ -3999,10 +3602,6 @@ ${integrationName === CONST.ONBOARDING_ACCOUNTING_MAPPING.other ? 'あなたの'
         youCanChange: 'ワークスペースの通貨は、次の場所で変更できます',
         findCountry: '国を検索',
         selectCountry: '国を選択',
-        error: {
-            connectToWorkspace: (workspaceRoute: string) =>
-                `この銀行口座はワークスペースにリンクする必要があります。<a href="${workspaceRoute}">ワークスペース</a>に移動し、ワークスペースを選択して、ワークフロー > 支払い > 銀行口座を追加 に進んでください。`,
-        },
     },
     bankInfoStep: {
         whatAreYour: 'あなたのビジネス用銀行口座の詳細を教えてください。',
@@ -4046,7 +3645,7 @@ ${integrationName === CONST.ONBOARDING_ACCOUNTING_MAPPING.other ? 'あなたの'
         pleaseUpload: 'ビジネスの取締役としての本人確認を行うため、以下に追加の書類をアップロードしてください。',
         enterSignerInfo: '署名者情報を入力',
         thisStep: 'このステップは完了しました',
-        isConnecting: (bankAccountLastFour: string | undefined, currency: string | undefined) =>
+        isConnecting: ({bankAccountLastFour, currency}: SignerInfoMessageParams) =>
             `は、従業員への支払いを${currency}で行うため、末尾が${bankAccountLastFour}の${currency}建てビジネス銀行口座をExpensifyに接続しようとしています。次のステップでは、取締役の署名者情報が必要です。`,
         error: {
             emailsMustBeDifferent: 'メールアドレスは異なる必要があります',
@@ -4058,7 +3657,7 @@ ${integrationName === CONST.ONBOARDING_ACCOUNTING_MAPPING.other ? 'あなたの'
         regulationRequiresUs: '法律により、事業の持分を25％超所有するすべての個人の本人確認を行うことが求められています。',
         iAmAuthorized: '私は、ビジネス支出のためにそのビジネス用銀行口座を使用する権限があります。',
         iCertify: '提供された情報が真実かつ正確であることを証明します。',
-        iAcceptTheTermsAndConditions: `私は<a href="https://www.corpay.com/cross-border/terms">利用規約と条件</a>に同意します。`,
+        iAcceptTheTermsAndConditions: `私は<a href="https://cross-border.corpay.com/tc/">利用規約と条件</a>に同意します。`,
         iAcceptTheTermsAndConditionsAccessibility: '利用規約に同意します。',
         accept: '承認して銀行口座を追加',
         iConsentToThePrivacyNotice: '私は<a href="https://payments.corpay.com/compliance">プライバシー通知</a>に同意します。',
@@ -4090,37 +3689,6 @@ ${integrationName === CONST.ONBOARDING_ACCOUNTING_MAPPING.other ? 'あなたの'
         weTake: 'お客様のセキュリティを重要視しています。アカウントをさらに強固に保護するため、今すぐ2要素認証（2FA）を設定してください。',
         secure: 'アカウントを保護する',
     },
-    documentsStep: {
-        beforeYouGo: '続行する前に、いくつかの情報を確認するための書類が必要です',
-        subheader: '確認',
-        verificationFailed: '確認に失敗したため、追加の書類で本人および事業の確認が必要です',
-        taxIDVerification: '納税者番号の確認',
-        taxIDVerificationDescription: dedent(`
-        以下のいずれかの書類をアップロードしてください：
-        • IRS TIN/EIN 割当通知書
-        • IRS TIN/EIN 申請確認書（通常「Congratulations! The EIN has been successfully assigned」と記載）
-        • 会社名と EIN が記載された IRS の免税通知書`),
-        nameChangeDocument: '名称変更書類',
-        nameChangeDocumentDescription: 'TIN/EIN 申請後に会社名が変更された場合、提供された納税者番号を確認するためにこの書類が必要です',
-        companyAddressVerification: '会社住所の確認',
-        companyAddressVerificationDescription: dedent(`
-        以下のいずれかの書類をアップロードしてください：
-        • 会社名と住所が記載された最近の公共料金請求書
-        • 会社名と住所が記載された銀行取引明細書
-        • 署名ページを含む現行の賃貸契約書（会社名と現住所が記載されたもの）
-        • 会社名と住所が記載された保険証書
-        • 会社名と住所が記載された TIN 割当書類`),
-        userAddressVerification: '住所確認',
-        userAddressVerificationDescription: dedent(`
-        以下のいずれかの書類をアップロードしてください：
-        • 有権者登録カード
-        • 運転免許証
-        • 銀行取引明細書
-        • 公共料金請求書`),
-        userDOBVerification: '生年月日の確認',
-        userDOBVerificationDescription: '米国発行の身分証明書をアップロードしてください',
-        finishViaChat: 'チャットで完了',
-    },
     reimbursementAccountLoadingAnimation: {
         oneMoment: '少々お待ちください',
         explanationLine: '現在、お客様の情報を確認しています。まもなく次のステップに進めるようになります。',
@@ -4258,15 +3826,15 @@ ${integrationName === CONST.ONBOARDING_ACCOUNTING_MAPPING.other ? 'あなたの'
             flightSeatChanged: (airlineCode: string) => `${airlineCode}便の座席指定が変更されました。`,
             flightSeatCancelled: (airlineCode: string) => `${airlineCode}便の座席指定が解除されました。`,
             paymentDeclined: '航空券の支払いに失敗しました。もう一度お試しください。',
-            bookingCancelledByTraveler: (type: string, id = '') => `${type}の予約（${id}）をキャンセルしました。`,
-            bookingCancelledByVendor: (type: string, id = '') => `業者があなたの${type}予約（${id}）をキャンセルしました。`,
-            bookingRebooked: (type: string, id = '') => `${type}の予約が再予約されました。新しい確認番号：${id}。`,
-            bookingUpdated: (type: string) => `${type}の予約が更新されました。旅程表で新しい詳細を確認してください。`,
+            bookingCancelledByTraveler: ({type, id = ''}: TravelTypeParams) => `${type}の予約（${id}）をキャンセルしました。`,
+            bookingCancelledByVendor: ({type, id = ''}: TravelTypeParams) => `業者があなたの${type}予約（${id}）をキャンセルしました。`,
+            bookingRebooked: ({type, id = ''}: TravelTypeParams) => `${type}の予約が再予約されました。新しい確認番号：${id}。`,
+            bookingUpdated: ({type}: TravelTypeParams) => `${type}の予約が更新されました。旅程表で新しい詳細を確認してください。`,
             railTicketRefund: (origin: string, destination: string, startDate: string) =>
                 `${origin} → ${destination} 行き（${startDate}）の鉄道チケットは払い戻しされました。クレジットが処理されます。`,
             railTicketExchange: (origin: string, destination: string, startDate: string) => `${startDate}の${origin}発${destination}行きの鉄道チケットは交換されました。`,
             railTicketUpdate: (origin: string, destination: string, startDate: string) => `${startDate} の ${origin} → ${destination} 行きの鉄道チケットが更新されました。`,
-            defaultUpdate: (type: string) => `${type}の予約が更新されました。`,
+            defaultUpdate: ({type}: TravelTypeParams) => `${type}の予約が更新されました。`,
         },
         flightTo: '行きのフライト',
         trainTo: '方面行き',
@@ -4283,13 +3851,13 @@ ${integrationName === CONST.ONBOARDING_ACCOUNTING_MAPPING.other ? 'あなたの'
             workflows: 'ワークフロー',
             workspace: 'ワークスペース',
             findWorkspace: 'ワークスペースを探す',
-            findRoom: 'ルームを探す',
             edit: 'ワークスペースを編集',
             enabled: '有効',
             disabled: '無効',
             everyone: '全員',
             delete: 'ワークスペースを削除',
             settings: '設定',
+            reimburse: '精算払い',
             categories: 'カテゴリ',
             tags: 'タグ',
             customField1: 'カスタムフィールド1',
@@ -4297,7 +3865,6 @@ ${integrationName === CONST.ONBOARDING_ACCOUNTING_MAPPING.other ? 'あなたの'
             customFieldHint: 'このメンバーのすべての支出に適用されるカスタムコードを追加します。',
             reports: 'レポート',
             reportFields: 'レポート項目',
-            invoiceFields: '請求書項目',
             reportTitle: 'レポートタイトル',
             reportField: 'レポート項目',
             taxes: '税金',
@@ -4326,9 +3893,6 @@ ${integrationName === CONST.ONBOARDING_ACCOUNTING_MAPPING.other ? 'あなたの'
             defaultNote: `${CONST.EMAIL.RECEIPTS} に送信されたレシートは、このワークスペースに表示されます。`,
             deleteConfirmation: 'このワークスペースを削除してもよろしいですか？',
             deleteWithCardsConfirmation: 'このワークスペースを削除してもよろしいですか？ すべてのカードフィードと割り当て済みカードが削除されます。',
-            deleteOpenExpensifyCardsError: 'あなたの会社にはまだ有効なExpensifyカードがあります。',
-            outstandingBalanceWarning: '最後のワークスペースを削除する前に精算する必要がある未払残高があります。支払いを解決するには、サブスクリプション設定に移動してください。',
-            settleBalance: 'サブスクリプションに移動',
             unavailable: '利用できないワークスペース',
             memberNotFound: 'メンバーが見つかりません。ワークスペースに新しいメンバーを招待するには、上の招待ボタンを使用してください。',
             notAuthorized: `このページへのアクセス権がありません。このワークスペースに参加しようとしている場合は、ワークスペースのオーナーに依頼してメンバーとして追加してもらってください。別のご用件ですか？${CONST.EMAIL.CONCIERGE} までご連絡ください。`,
@@ -4339,11 +3903,8 @@ ${integrationName === CONST.ONBOARDING_ACCOUNTING_MAPPING.other ? 'あなたの'
             clearFilter: 'フィルターをクリア',
             workspaceName: 'ワークスペース名',
             workspaceOwner: 'オーナー',
-            keepMeAsAdmin: '管理者のままにする',
             workspaceType: 'ワークスペースの種類',
             workspaceAvatar: 'ワークスペースのアバター',
-            clientID: 'クライアントID',
-            clientIDInputHint: 'クライアントの一意の識別子を入力してください',
             mustBeOnlineToViewMembers: 'このワークスペースのメンバーを表示するには、オンライン接続が必要です。',
             moreFeatures: 'その他の機能',
             requested: 'リクエスト済み',
@@ -4362,7 +3923,7 @@ ${integrationName === CONST.ONBOARDING_ACCOUNTING_MAPPING.other ? 'あなたの'
             appliedOnExport: 'Expensify にはインポートされず、エクスポート時に適用されます',
             shareNote: {
                 header: 'ワークスペースを他のメンバーと共有する',
-                content: (adminsRoomLink: string) =>
+                content: ({adminsRoomLink}: WorkspaceShareNoteParams) =>
                     `このQRコードを共有するか、以下のリンクをコピーしてメンバーがあなたのワークスペースへのアクセスを簡単にリクエストできるようにしましょう。ワークスペースへの参加リクエストはすべて、あなたが確認できるように<a href="${adminsRoomLink}">${CONST.REPORT.WORKSPACE_CHAT_ROOMS.ADMINS}</a>ルームに表示されます。`,
             },
             connectTo: ({connectionName}: ConnectionNameParams) => `${CONST.POLICY.CONNECTIONS.NAME_USER_FRIENDLY[connectionName]} に接続`,
@@ -4377,21 +3938,12 @@ ${integrationName === CONST.ONBOARDING_ACCOUNTING_MAPPING.other ? 'あなたの'
             memberAlternateText: 'レポートを提出して承認します。',
             adminAlternateText: 'レポートとワークスペースの設定を管理します。',
             auditorAlternateText: 'レポートを表示してコメントします。',
-            roleName: (role?: string) => {
+            roleName: ({role}: OptionalParam<RoleNamesParams> = {}) => {
                 switch (role) {
                     case CONST.POLICY.ROLE.ADMIN:
-                        return 'ワークスペース管理者';
+                        return '管理者';
                     case CONST.POLICY.ROLE.AUDITOR:
                         return '監査人';
-                    case CONST.POLICY.ROLE.EDITOR:
-                        return '編集者';
-                        return '監査担当者';
-                    case CONST.POLICY.ROLE.CARD_ADMIN:
-                        return 'カード管理者';
-                    case CONST.POLICY.ROLE.PEOPLE_ADMIN:
-                        return 'メンバー管理';
-                    case CONST.POLICY.ROLE.PAYMENTS_ADMIN:
-                        return '支払い管理者';
                     case CONST.POLICY.ROLE.USER:
                         return 'メンバー';
                     default:
@@ -4413,7 +3965,7 @@ ${integrationName === CONST.ONBOARDING_ACCOUNTING_MAPPING.other ? 'あなたの'
             defaultCategory: 'デフォルトカテゴリ',
             viewTransactions: '取引を表示',
             policyExpenseChatName: (displayName: string) => `${displayName} さんの経費`,
-            deepDiveExpensifyCard: `<muted-text-label>Expensify カードの取引は、<a href="${CONST.DEEP_DIVE_EXPENSIFY_CARD}">当社の連携機能</a>で作成される「Expensify カード負債勘定」に自動的にエクスポートされます。</muted-text-label>`,
+            deepDiveExpensifyCard: `<muted-text-label>Expensify Card の取引は、<a href="${CONST.DEEP_DIVE_EXPENSIFY_CARD}">当社のインテグレーション</a>によって作成される「Expensify Card 負債勘定」に自動的にエクスポートされます。</muted-text-label>`,
             reimbursementChoice: {
                 [CONST.POLICY.REIMBURSEMENT_CHOICES.REIMBURSEMENT_YES]: 'ダイレクト',
                 [CONST.POLICY.REIMBURSEMENT_CHOICES.REIMBURSEMENT_NO]: 'なし',
@@ -4422,21 +3974,6 @@ ${integrationName === CONST.ONBOARDING_ACCOUNTING_MAPPING.other ? 'あなたの'
             budgetFrequency: {monthly: '毎月', yearly: '年次'},
             budgetFrequencyUnit: {monthly: '月', yearly: '年'},
             budgetTypeForNotificationMessage: {tag: 'タグ', category: 'カテゴリ'},
-            travelInvoicing: '出張請求費用を次の形式でエクスポート',
-            travelInvoicingVendor: '出張ベンダー',
-            travelInvoicingPayableAccount: '旅費未払金勘定',
-            hr: '人事',
-            rooms: 'ルーム',
-            findDomain: 'ドメインを検索',
-            cardAdminAlternateText: 'ワークスペースカードを管理します。',
-            peopleAdminAlternateText: 'メンバーと承認ワークフローを管理します。',
-            paymentsAdminAlternateText: 'ワークフローの支払いを管理します。',
-            readOnlyActionTitle: 'ちょっと待ってください…',
-            readOnlyActionPrompt: 'このワークスペースでのあなたのロールは、これらの設定を表示できますが、編集することはできません。',
-        },
-        createdForClient: {
-            title: 'クライアントのワークスペースを作成しました！',
-            description: '素晴らしいニュースです 🎉。セットアップにサポートが必要な場合はお問い合わせください。',
         },
         receiptPartners: {
             uber: {
@@ -4499,7 +4036,7 @@ ${integrationName === CONST.ONBOARDING_ACCOUNTING_MAPPING.other ? 'あなたの'
             exportDescription: 'Expensify のデータを QuickBooks Desktop へエクスポートする方法を設定します。',
             date: 'エクスポート日',
             exportInvoices: '請求書のエクスポート先',
-            exportExpensifyCard: 'Expensify カードの取引を次の形式でエクスポートします',
+            exportExpensifyCard: 'Expensifyカードの取引を次の形式でエクスポートする',
             account: 'アカウント',
             accountDescription: '仕訳を記帳する場所を選択してください。',
             accountsPayable: '買掛金',
@@ -4619,7 +4156,7 @@ ${integrationName === CONST.ONBOARDING_ACCOUNTING_MAPPING.other ? 'あなたの'
             exportDescription: 'Expensify のデータを QuickBooks Online へエクスポートする方法を設定します。',
             date: 'エクスポート日',
             exportInvoices: '請求書のエクスポート先',
-            exportExpensifyCard: 'Expensify カードの取引を次の形式でエクスポートします',
+            exportExpensifyCard: 'Expensifyカードの取引を次の形式でエクスポートする',
             exportDate: {
                 label: 'エクスポート日',
                 description: 'レポートをQuickBooks Onlineにエクスポートする際に、この日付を使用します。',
@@ -4657,9 +4194,8 @@ ${integrationName === CONST.ONBOARDING_ACCOUNTING_MAPPING.other ? 'あなたの'
             notConfigured: '未設定',
             bankAccountDescription: '小切手の送金元を選択してください。',
             creditCardAccount: 'クレジットカード口座',
-            travelInvoicingDescription: '旅費は、以下で指定した QuickBooks Online アカウントにクレジットカード請求としてエクスポートされます。',
             companyCardsLocationEnabledDescription:
-                'QuickBooks Online では、ロケーションをタグとして取り込んでいる場合、ベンダー請求書のエクスポートでロケーションをサポートしていません。現在このワークスペースではロケーションがタグとして取り込まれているため、このエクスポートオプションは利用できません。',
+                'QuickBooks Online は仕入先請求書のエクスポートでロケーションをサポートしていません。ワークスペースでロケーションが有効になっているため、このエクスポートオプションは使用できません。',
             outOfPocketTaxEnabledDescription:
                 'QuickBooks Online は仕訳のエクスポートで税金に対応していません。ワークスペースで税金が有効になっているため、このエクスポートオプションは利用できません。',
             outOfPocketTaxEnabledError: '税金が有効になっている場合、仕訳は利用できません。別のエクスポートオプションを選択してください。',
@@ -4748,7 +4284,6 @@ ${integrationName === CONST.ONBOARDING_ACCOUNTING_MAPPING.other ? 'あなたの'
             purchaseBill: '仕入請求書',
             exportDeepDiveCompanyCard: 'エクスポートされた経費は、以下のXero銀行口座に銀行取引として記帳され、取引日付は銀行取引明細書の日付と一致します。',
             bankTransactions: '銀行取引',
-            travelInvoicingDescription: '旅費は、以下で指定したXeroアカウントに銀行取引としてエクスポートされます。',
             xeroBankAccount: 'Xero 銀行口座',
             xeroBankAccountDescription: '経費を銀行取引として計上する先を選択してください。',
             exportExpensesDescription: 'レポートは、以下で選択された日付とステータスで仕入請求書としてエクスポートされます。',
@@ -4843,7 +4378,6 @@ ${integrationName === CONST.ONBOARDING_ACCOUNTING_MAPPING.other ? 'あなたの'
                     [CONST.SAGE_INTACCT_NON_REIMBURSABLE_EXPENSE_TYPE.VENDOR_BILL]: '仕入先請求書',
                 },
             },
-            travelInvoicingDescription: '旅費は、以下で指定した Sage Intacct アカウントにクレジットカード請求としてエクスポートされます。',
             creditCardAccount: 'クレジットカード口座',
             defaultVendor: 'デフォルトのベンダー',
             defaultVendorDescription: (isReimbursable: boolean) =>
@@ -4875,64 +4409,6 @@ ${integrationName === CONST.ONBOARDING_ACCOUNTING_MAPPING.other ? 'あなたの'
                 },
             },
         },
-        certinia: {
-            title: 'Certinia',
-            titleFFA: 'Certinia (FFA)',
-            autoSyncDescription: 'Expensify は毎日自動的に Certinia と同期します。',
-            syncReimbursedReportsDescription: 'このオプションを有効にすると、FFA で買掛請求書が支払われるたびに、関連する Expensify レポートが自動的に精算済みとしてマークされます。',
-            exportDescription: 'Expensify のデータを Certinia へエクスポートする方法を設定します。',
-            payableInvoices: '支払対象の請求書',
-            exportStatus: {
-                label: '買掛請求書のステータス',
-                values: {
-                    [CONST.CERTINIA_EXPORT_STATUS.APPROVED]: '完了',
-                    [CONST.CERTINIA_EXPORT_STATUS.IN_PROGRESS]: '進行中',
-                    [CONST.CERTINIA_EXPORT_STATUS.SUBMITTED]: '送信済み',
-                },
-            },
-            exportDate: {
-                label: '支払予定請求書日',
-                values: {
-                    [CONST.CERTINIA_EXPORT_DATE.LAST_EXPENSE]: '最終経費日',
-                    [CONST.CERTINIA_EXPORT_DATE.REPORT_SUBMITTED]: 'レポート提出日',
-                    [CONST.CERTINIA_EXPORT_DATE.REPORT_EXPORTED]: 'エクスポート日',
-                },
-            },
-            exportReimbursable: {label: '精算対象経費の書き出し形式', helperText: '払い戻し対象としてマークされた経費は、従業員宛ての未払請求書としてエクスポートされます。'},
-            exportNonReimbursable: {label: '未払い精算の対象外経費を次の形式でエクスポートする'},
-            noVendorsFound: 'ベンダーが見つかりませんでした',
-            noVendorsFoundDescription: 'Certinia にベンダーを追加した後に、もう一度接続の同期を行ってください。',
-            prerequisites: {
-                title: '接続する前に',
-                installBundle: 'FFA 接続用',
-                installBundleDescription: ({href, version}: {href: string; version: string}) =>
-                    `このリンクをクリックして、Salesforce に Expensify バンドルをインストールしてください：<a href="${href}">FFA Expensify バンドルをインストール（バージョン ${version}）</a>`,
-                installBundleConfirm: 'バンドルをインストールしました',
-                setupContacts: 'ユーザーと連絡先を設定',
-                setupContactsBullet1:
-                    'Certinia に、まだ存在しない場合は自分用のユーザーと連絡先の両方を作成し、メールアドレスが Expensify のプライマリメールと一致していることを確認します。',
-                setupContactsBullet2:
-                    '経費精算書を提出する従業員ごと、および各承認者ごとに連絡先を作成してください。各連絡先のメールアドレスが、その従業員の Expensify アカウントに登録されているメールアドレスと一致していることを確認してください。',
-                setupContactsBullet3: '各連絡先／リソースごとにユーザーの権限を設定します。',
-                setupContactsConfirm: 'ユーザーと連絡先を設定しました',
-                oauth: 'Salesforce からログイン',
-                oauthDescription: '設定を完了するには、Salesforce と Certinia を通じてサインインする必要があります。\n\n続行するには、下のボタンを使用してください。',
-                connectButton: 'Certinia に接続',
-            },
-            import: {
-                chartOfAccounts: '勘定科目表',
-                chartOfAccountsDescription: '勘定科目表は、カテゴリとして Expensify にインポートされます。',
-                dimensionMapping: ({n}: {n: number}) => `ディメンション ${n}`,
-                dimensions: {dimension1: 'ディメンション 1', dimension2: 'ディメンション 2', dimension3: 'ディメンション 3', dimension4: 'ディメンション4'},
-                doNotMap: 'マッピングしない',
-                doNotMapSubtitle: '従業員リソースをデフォルトで使用する',
-                mappingTypes: {
-                    [CONST.CERTINIA_MAPPING_VALUE.DEFAULT]: 'マッピングしない',
-                    [CONST.CERTINIA_MAPPING_VALUE.TAG]: 'タグとしてインポート済み',
-                    [CONST.CERTINIA_MAPPING_VALUE.REPORT_FIELD]: 'レポートフィールドとしてインポートしました',
-                },
-            },
-        },
         netsuite: {
             subsidiary: '子会社',
             subsidiarySelectDescription: 'データをインポートしたいNetSuiteの子会社を選択してください。',
@@ -4947,8 +4423,8 @@ ${integrationName === CONST.ONBOARDING_ACCOUNTING_MAPPING.other ? 'あなたの'
             journalPostingPreference: {
                 label: '仕訳の記帳設定',
                 values: {
-                    [CONST.NETSUITE_JOURNAL_POSTING_PREFERENCE.JOURNALS_POSTING_INDIVIDUAL_LINE]: '各経費につき1件の入力',
-                    [CONST.NETSUITE_JOURNAL_POSTING_PREFERENCE.JOURNALS_POSTING_TOTAL_LINE]: '各レポートごとの単一の明細エントリ',
+                    [CONST.NETSUITE_JOURNAL_POSTING_PREFERENCE.JOURNALS_POSTING_INDIVIDUAL_LINE]: '各レポートごとの単一の項目別エントリ',
+                    [CONST.NETSUITE_JOURNAL_POSTING_PREFERENCE.JOURNALS_POSTING_TOTAL_LINE]: '各経費につき1件の入力',
                 },
             },
             invoiceItem: {
@@ -5014,7 +4490,6 @@ ${integrationName === CONST.ONBOARDING_ACCOUNTING_MAPPING.other ? 'あなたの'
 
                             各カードごとに特定の取引先を設定したい場合は、*設定 > ドメイン > 会社カード* に移動してください。
                         `),
-                        travelDescription: '出張費は、以下で指定された NetSuite アカウントに仕訳としてエクスポートされます。',
                     },
                 },
                 expenseReportDestinationConfirmDescription:
@@ -5155,7 +4630,7 @@ ${integrationName === CONST.ONBOARDING_ACCOUNTING_MAPPING.other ? 'あなたの'
                 importCustomFields: {
                     chooseOptionBelow: '以下からオプションを選択:',
                     label: (importedTypes: string[]) => `${importedTypes.join('と')}としてインポートされました`,
-                    requiredFieldError: (fieldName: string) => `${fieldName}を入力してください`,
+                    requiredFieldError: ({fieldName}: RequiredFieldParams) => `${fieldName}を入力してください`,
                     customSegments: {
                         title: 'カスタムセグメント／レコード',
                         addText: 'カスタムセグメント／レコードを追加',
@@ -5229,7 +4704,7 @@ _より詳細な手順については、[ヘルプサイトをご覧ください
                             customRecordMappingTitle: 'このカスタムレコードを Expensify ではどのように表示しますか？',
                         },
                         errors: {
-                            uniqueFieldError: (fieldName: string) => `この ${fieldName?.toLowerCase()} を持つカスタムセグメント／レコードはすでに存在します`,
+                            uniqueFieldError: ({fieldName}: RequiredFieldParams) => `この ${fieldName?.toLowerCase()} を持つカスタムセグメント／レコードはすでに存在します`,
                         },
                     },
                     customLists: {
@@ -5296,7 +4771,7 @@ _詳しい手順については、[ヘルプサイトをご覧ください](${CO
             employeeDefaultDescription: 'Sage Intacct に部門が設定されている場合は、その従業員の既定の部門が経費に適用されます。',
             displayedAsTagDescription: '部署は、従業員のレポート上の各経費ごとに選択できるようになります。',
             displayedAsReportFieldDescription: '部門の選択は、従業員のレポート内のすべての経費に適用されます。',
-            toggleImportTitle: (mappingTitle: string) => `Expensify で Sage Intacct の <strong>${mappingTitle}</strong> をどのように処理するか選択してください。`,
+            toggleImportTitle: ({mappingTitle}: ToggleImportTitleParams) => `Expensify で Sage Intacct の <strong>${mappingTitle}</strong> をどのように処理するか選択してください。`,
             expenseTypes: '経費の種類',
             expenseTypesDescription: 'Sage Intacct の経費タイプは、Expensify にはカテゴリとしてインポートされます。',
             accountTypesDescription: 'Sage Intacctの勘定科目表は、Expensifyにカテゴリとしてインポートされます。',
@@ -5336,14 +4811,10 @@ _詳しい手順については、[ヘルプサイトをご覧ください](${CO
             free: '無料',
             control: 'コントロール',
             collect: '回収',
-            submit: '提出',
         },
         companyCards: {
             addCards: 'カードを追加',
             selectCards: 'カードを選択',
-            fromOtherWorkspaces: '他のワークスペースから',
-            addWorkEmail: 'あなたの勤務用メールアドレスを追加',
-            addWorkEmailDescription: '他のワークスペースの既存フィードを使用するには、勤務用メールアドレスを追加してください。',
             error: {
                 workspaceFeedsCouldNotBeLoadedTitle: 'カードフィードを読み込めませんでした',
                 workspaceFeedsCouldNotBeLoadedMessage: 'ワークスペースカードフィードの読み込み中にエラーが発生しました。もう一度お試しいただくか、管理者にお問い合わせください。',
@@ -5353,11 +4824,6 @@ _詳しい手順については、[ヘルプサイトをご覧ください](${CO
             },
             addNewCard: {
                 other: 'その他',
-                fileImport: 'ファイルから取引をインポート',
-                createFileFeedHelpText: `<muted-text>会社カードの経費をインポートするには、この<a href="${CONST.COMPANY_CARDS_CREATE_FILE_FEED_HELP_URL}">ヘルプガイド</a>に従ってください。</muted-text>`,
-                companyCardLayoutName: '法人カードレイアウト名',
-                cardLayoutNameRequired: '法人カードレイアウト名は必須です',
-                useAdvancedFields: '詳細フィールドを使用（非推奨）',
                 cardProviders: {
                     gl1025: 'American Express コーポレートカード',
                     cdf: 'Mastercard コマーシャルカード',
@@ -5435,26 +4901,6 @@ _詳しい手順については、[ヘルプサイトをご覧ください](${CO
                     confirmText: '問題を報告',
                     cancelText: 'スキップ',
                 },
-                csvColumns: {
-                    cardNumber: 'カード番号',
-                    postedDate: '日付',
-                    merchant: '加盟店',
-                    amount: '金額',
-                    currency: '通貨',
-                    ignore: '無視',
-                    originalTransactionDate: '元の取引日',
-                    originalAmount: '元の金額',
-                    originalCurrency: '元の通貨',
-                    comment: 'コメント',
-                    category: 'カテゴリ',
-                    tag: 'タグ',
-                },
-                csvErrors: {
-                    requiredColumns: (missingColumns: string) => `各属性に列を割り当ててください：${missingColumns}`,
-                    duplicateColumns: (duplicateColumn: string) => `おっと！1 つのフィールド（"${duplicateColumn}"）を複数の列にマッピングしています。確認して、もう一度お試しください。`,
-                },
-                fileImportDescription: '銀行からフィードを送信できない場合の手動オプションです。',
-                duplicateFeedModal: {title: 'カードフィードはすでに接続されています', prompt: '同じカードフィードを同じワークスペースに二重に追加することはできません。'},
             },
             statementCloseDate: {
                 [CONST.COMPANY_CARDS.STATEMENT_CLOSE_DATE.LAST_DAY_OF_MONTH]: '月末最終日',
@@ -5473,7 +4919,7 @@ _詳しい手順については、[ヘルプサイトをご覧ください](${CO
             chooseCard: 'カードを選択',
             chooseCardFor: (assignee: string) =>
                 `<strong>${assignee}</strong> に割り当てるカードを選択してください。お探しのカードが見つかりませんか？<concierge-link>お知らせください。</concierge-link>`,
-            noActiveCards: 'このフィードに有効なカードはありません',
+            noActiveCards: 'このフィードには有効なカードがありません',
             somethingMightBeBroken:
                 '<muted-text><centered-text>もしくは不具合が発生している可能性があります。いずれにせよ、ご不明な点があれば、<concierge-link>Concierge にお問い合わせください</concierge-link>。</centered-text></muted-text>',
             chooseTransactionStartDate: '取引の開始日を選択',
@@ -5505,11 +4951,9 @@ _詳しい手順については、[ヘルプサイトをご覧ください](${CO
                 flipAmountSign: '金額の符号を反転',
                 importButton: '取引をインポート',
             },
-            deletedCard: '削除されたカード',
-            assignNewCards: {title: '新しいカードを割り当てる', description: '銀行から割り当て可能な最新のカードを取得します'},
         },
         expensifyCard: {
-            issueAndManageCards: 'Expensify カードを発行して管理する',
+            issueAndManageCards: 'Expensifyカードの発行と管理',
             getStartedIssuing: 'まずは最初のバーチャルカードまたは物理カードを発行しましょう。',
             verificationInProgress: '確認を進めています…',
             verifyingTheDetails: 'いくつかの詳細を確認しています。Expensify カードを発行できる準備が整いましたら、Concierge からお知らせします。',
@@ -5524,8 +4968,8 @@ _詳しい手順については、[ヘルプサイトをご覧ください](${CO
             lastFour: '下4桁',
             limit: '上限',
             currentBalance: '現在の残高',
-            currentBalanceDescription: '現在残高は、前回の精算日以降に発生し記帳されたすべての Expensify カード取引の合計です。',
-            balanceWillBeSettledOn: (settlementDate: string) => `残高は${settlementDate}に精算されます`,
+            currentBalanceDescription: '現在残高は、前回の清算日以降に発生した、すべての記帳済み Expensify Card 取引の合計です。',
+            balanceWillBeSettledOn: ({settlementDate}: SettlementDateParams) => `残高は${settlementDate}に精算されます`,
             settleBalance: '残高を清算',
             cardLimit: 'カード上限',
             remainingLimit: '残りの上限',
@@ -5533,27 +4977,26 @@ _詳しい手順については、[ヘルプサイトをご覧ください](${CO
             remainingLimitDescription:
                 '残りの限度額を算出する際には、お客様としてのご利用期間、登録時にご提供いただいた事業関連情報、およびビジネス用銀行口座の利用可能残高など、複数の要素を考慮します。残りの限度額は日々変動する可能性があります。',
             earnedCashback: 'キャッシュバック',
-            earnedCashbackDescription: 'キャッシュバック残高は、ワークスペース内で決済済みの月間 Expensify カード利用額に基づいています。',
+            earnedCashbackDescription: 'キャッシュバック残高は、ワークスペース全体での毎月の清算済みExpensifyカード利用額に基づいています。',
             issueNewCard: '新しいカードを発行',
             finishSetup: 'セットアップを完了',
             chooseBankAccount: '銀行口座を選択',
-            chooseExistingBank: '既存のビジネス銀行口座を選んで Expensify カードの残高を支払うか、新しい銀行口座を追加してください',
+            chooseExistingBank: '既存のビジネス銀行口座を選んでExpensifyカードの残高を支払うか、新しい銀行口座を追加してください',
             accountEndingIn: '末尾が…の口座',
             addNewBankAccount: '新しい銀行口座を追加',
             settlementAccount: '決済口座',
-            settlementAccountDescription: 'Expensify カードの残高を支払う口座を選択してください。',
-            settlementAccountInfo: (reconciliationAccountSettingsLink: string, accountNumber: string) =>
+            settlementAccountDescription: 'Expensifyカードの残高を支払う口座を選択してください。',
+            settlementAccountInfo: ({reconciliationAccountSettingsLink, accountNumber}: SettlementAccountInfoParams) =>
                 `継続照合が正しく機能するように、この口座が<a href="${reconciliationAccountSettingsLink}">照合用口座</a>（${accountNumber}）と一致していることを確認してください。`,
             settlementFrequency: '清算頻度',
-            settlementFrequencyDescription: 'Expensify カードの残高を支払う頻度を選択してください。',
+            settlementFrequencyDescription: 'Expensify Card の残高を支払う頻度を選択してください。',
             settlementFrequencyInfo: '月次清算に切り替えるには、Plaid を通じて銀行口座を連携し、直近90日間の残高履歴がプラスである必要があります。',
-            applyCashbackToBill: 'キャッシュバックを Expensify 請求書に適用する',
-            applyCashbackToBillDescription: 'Expensify カードのキャッシュバックは、Expensify 請求書の支払いに使用されます。',
             frequency: {
                 daily: '毎日',
                 monthly: '毎月',
             },
             cardDetails: 'カード情報',
+            cardPending: ({name}: {name: string}) => `カードは現在保留中で、${name} さんのアカウントが認証され次第、発行されます。`,
             virtual: 'バーチャル',
             physical: '物理',
             deactivate: 'カードを無効化',
@@ -5569,28 +5012,24 @@ _詳しい手順については、[ヘルプサイトをご覧ください](${CO
             changeCardMonthlyLimitTypeWarning: (limit: number | string) =>
                 `このカードの限度額タイプを「月次」に変更すると、すでに月間限度額 ${limit} に達しているため、新しい取引は拒否されます。`,
             addShippingDetails: '配送先の詳細を追加',
-            issuedCard: (assignee: string) => `${assignee} に Expensify カードを発行しました。カードは 2〜3 営業日以内に到着します。`,
-            issuedCardNoShippingDetails: (assignee: string) => `${assignee} に Expensify カードを発行しました。配送先の詳細が確認され次第、カードを発送します。`,
-            issuedCardVirtual: (assignee: string, link: string) => `${assignee} にバーチャル Expensify カードを発行しました！${link} はすぐにご利用いただけます。`,
-            addedShippingDetails: (assignee: string) => `${assignee} さんが配送先情報を追加しました。Expensify カードは営業日2～3日で届きます。`,
-            replacedCard: (assignee: string) => `${assignee} さんが Expensify カードを再発行しました。新しいカードは 2〜3 営業日以内に到着します。`,
-            replacedVirtualCard: (assignee: string, link: string) => `${assignee} はバーチャル Expensify カードを再発行しました！${link} はすぐにご利用いただけます。`,
+            issuedCard: (assignee: string) => `${assignee} に Expensify カードを発行しました！カードは 2～3 営業日以内に到着します。`,
+            issuedCardNoShippingDetails: (assignee: string) => `${assignee}にExpensify Cardを発行しました！配送先の詳細が確認され次第、カードを発送します。`,
+            issuedCardVirtual: (assignee: string, link: string) => `${assignee} にバーチャル Expensify Card を発行しました！${link} はすぐに使用できます。`,
+            addedShippingDetails: (assignee: string) => `${assignee} が配送先の詳細を追加しました。Expensify Card は 2～3 営業日で届きます。`,
+            replacedCard: (assignee: string) => `${assignee} は Expensify Card を再発行しました。新しいカードは 2〜3 営業日で到着します。`,
+            replacedVirtualCard: (assignee: string, link: string) => `${assignee}さんがバーチャル Expensify Card を再発行しました！${link}はすぐにご利用いただけます。`,
             card: 'カード',
             replacementCard: '再発行カード',
             verifyingHeader: '確認中',
             bankAccountVerifiedHeader: '銀行口座が確認されました',
             verifyingBankAccount: '銀行口座を確認しています…',
-            verifyingBankAccountDescription: 'このアカウントで Expensify カードを発行できるか確認しています。しばらくお待ちください。',
+            verifyingBankAccountDescription: 'このアカウントでExpensifyカードを発行できるか確認しています。しばらくお待ちください。',
             bankAccountVerified: '銀行口座が認証されました！',
-            bankAccountVerifiedDescription: 'ワークスペースのメンバーに Expensify カードを発行できるようになりました。',
+            bankAccountVerifiedDescription: 'ワークスペースのメンバーに Expensify Card を発行できるようになりました。',
             oneMoreStep: 'あともう一歩…',
             oneMoreStepDescription: '銀行口座を手動で確認する必要があるようです。指示が表示されていますので、Concierge 画面に進んでください。',
             gotIt: '了解しました',
             goToConcierge: 'Concierge へ移動',
-            exportAsCSV: 'CSVでエクスポート',
-            csvColumnType: 'タイプ',
-            csvColumnLimitType: '限度タイプ',
-            csvColumnLimit: '限度額',
         },
         categories: {
             deleteCategories: 'カテゴリを削除',
@@ -5609,10 +5048,10 @@ _詳しい手順については、[ヘルプサイトをご覧ください](${CO
             needCategoryForExportToIntegration: (connectionName: string) => `${connectionName} にエクスポートするには、すべての経費にカテゴリを指定する必要があります。`,
             subtitle: 'お金がどこで使われているかを、より分かりやすく把握しましょう。デフォルトのカテゴリを使うか、自分用のカテゴリを追加できます。',
             emptyCategories: {
-                title: 'カテゴリはまだありません',
+                title: 'カテゴリがまだ作成されていません',
                 subtitle: '支出を整理するカテゴリを追加してください。',
-                subtitleWithAccounting: (accountingPageURL: string, canManage = true) =>
-                    `<muted-text><centered-text>現在、お客様のカテゴリは会計連携からインポートされています。${canManage ? `変更するには、<a href="${accountingPageURL}">会計</a>に移動してください。` : ''}</centered-text></muted-text>`,
+                subtitleWithAccounting: (accountingPageURL: string) =>
+                    `<muted-text><centered-text>現在、お客様のカテゴリは会計連携からインポートされています。変更するには、<a href="${accountingPageURL}">会計</a>に移動してください。</centered-text></muted-text>`,
             },
             updateFailureMessage: 'カテゴリの更新中にエラーが発生しました。もう一度お試しください。',
             createFailureMessage: 'カテゴリの作成中にエラーが発生しました。もう一度お試しください。',
@@ -5667,9 +5106,6 @@ _詳しい手順については、[ヘルプサイトをご覧ください](${CO
             travel: {
                 title: '出張',
                 subtitle: '出張の予約、管理、精算をすべて一元管理。',
-                disableTravelTitle: '先に Travel Invoicing をオフにしてください',
-                disableTravelPrompt: 'このワークスペースでは旅行請求書作成が有効になっています。Travel を無効にする前にオフにしてください。',
-                disableTravelButton: '出張設定に移動します',
                 getStarted: {
                     title: 'Expensify Travel を使い始める',
                     subtitle: 'ビジネスについてあと少しだけ情報を教えてください。準備が整い次第、すぐに開始できます。',
@@ -5680,61 +5116,40 @@ _詳しい手順については、[ヘルプサイトをご覧ください](${CO
                     subtitle: '現在、Expensify Travel の有効化リクエストを確認中です。準備が整い次第、お知らせしますのでご安心ください。',
                     ctaText: 'リクエストを送信しました',
                 },
-                bookOrManageYourTrip: {title: '出張予約', subtitle: 'おめでとうございます！このワークスペースで旅行の予約と管理を行う準備が整いました。', ctaText: '出張を管理'},
-                settings: {autoAddTripName: {title: '経費に出張名を追加', subtitle: 'Expensifyで予約した出張について、経費の説明に出張名を自動的に追加します。'}},
+                bookOrManageYourTrip: {
+                    title: '出張を予約または管理',
+                    subtitle: 'Expensify Travel を使って、最高の旅行プランを入手し、すべてのビジネス経費を一括管理しましょう。',
+                    ctaText: '予約または管理',
+                },
                 travelInvoicing: {
                     travelBookingSection: {
                         title: '出張予約',
                         subtitle: 'おめでとうございます！このワークスペースで旅行の予約と管理を行う準備ができました。',
                         manageTravelLabel: '出張を管理',
                     },
-                    travelInvoicingSection: {
-                        title: '出張請求書作成',
+                    centralInvoicingSection: {
+                        title: '集中請求',
                         subtitle: '購入時に支払うのではなく、すべての出張費を月次請求書に集約しましょう。',
                         learnHow: '詳しく見る',
                         subsections: {
                             currentTravelSpendLabel: '現在の出張費支出',
-                            currentTravelSpendPaymentQueued: (amount: string) => `${amount} の支払いはキューに登録されており、まもなく処理されます。`,
                             currentTravelSpendCta: '残高を支払う',
                             currentTravelLimitLabel: '現在の出張上限',
                             settlementAccountLabel: '決済口座',
                             settlementFrequencyLabel: '清算頻度',
                             settlementFrequencyDescription: 'Expensify が直近の Expensify Travel 取引を精算するために、あなたのビジネス銀行口座から資金を引き落とす頻度。',
-                            monthlySpendLimitLabel: 'メンバーごとの月間支出上限',
-                            monthlySpendLimitDescription: '各メンバーが1か月に出張に使える最大金額。',
-                            reduceLimitTitle: '出張支出上限を引き下げますか？',
-                            reduceLimitWarning: 'この上限を引き下げると、すでにこの金額を超えて支出しているメンバーは、翌月まで新しい出張予約ができなくなります。',
-                            provisioningError:
-                                'ワークスペース内の一部メンバーを旅行請求用にプロビジョニングできませんでした。時間をおいてもう一度お試しいただくか、サポートが必要な場合は Concierge までご連絡ください。',
                         },
                     },
-                    disableModal: {
-                        title: '旅費請求書発行をオフにしますか？',
-                        body: '今後のホテルおよびレンタカーの予約は、キャンセルを避けるために別のお支払い方法で再予約する必要がある場合があります。',
-                        confirm: 'オフにする',
-                    },
-                    outstandingBalanceModal: {title: 'トラベル請求書作成をオフにできません', body: '未清算の出張残高があります。先に残高を精算してください。', confirm: '了解しました'},
-                    payBalanceModal: {
-                        title: (amount: string) => `残高 ${amount} を支払いますか？`,
-                        body: '支払いはキューに追加され、その後まもなく処理されます。この操作は一度開始すると元に戻すことはできません。',
-                    },
-                    exportToPDF: 'PDF にエクスポート',
-                    exportToCSV: 'CSV にエクスポート',
-                    selectDateRangeError: 'エクスポートする日付範囲を選択してください',
-                    invalidDateRangeError: '開始日は終了日より前でなければなりません',
-                    enabled: '出張請求書機能が有効になりました！',
-                    enabledDescription: 'このワークスペースのすべての出張費は、今後、月次請求書で一元管理されます。',
                 },
-                personalDetailsDescription: '旅行を予約するために、政府発行の身分証明書に記載されているとおりの正式な氏名を入力してください。',
             },
             expensifyCard: {
                 title: 'Expensify カード',
                 subtitle: '支出を把握し、コントロールしましょう。',
-                disableCardTitle: 'Expensify カードを無効にする',
-                disableCardPrompt: 'Expensify カードはすでに使用中のため、無効にすることはできません。今後の対応については Concierge までお問い合わせください。',
+                disableCardTitle: 'Expensifyカードを無効にする',
+                disableCardPrompt: 'このExpensifyカードはすでに使用中のため、無効にすることはできません。次の手順についてはConciergeにお問い合わせください。',
                 disableCardButton: 'Conciergeとチャット',
                 feed: {
-                    title: 'Expensify カードを入手する',
+                    title: 'Expensifyカードを入手',
                     subTitle: '経費精算を効率化してExpensifyの請求額を最大50％節約し、さらに以下の特典も利用できます。',
                     features: {
                         cashBack: '米国内でのすべての購入にキャッシュバック',
@@ -5758,7 +5173,7 @@ _詳しい手順については、[ヘルプサイトをご覧ください](${CO
                 },
                 bankConnectionError: '銀行接続の問題',
                 connectWithPlaid: 'Plaid 経由で接続',
-                connectWithExpensifyCard: 'Expensify カードをお試しください。',
+                connectWithExpensifyCard: 'Expensify Card をお試しください。',
                 bankConnectionDescription: `もう一度カードの追加をお試しください。それでも解決しない場合は、次の方法をお試しください。`,
                 disableCardTitle: '法人カードを無効化',
                 disableCardPrompt: 'この機能が使用中のため、会社カードは無効にできません。今後の対応についてはConciergeにお問い合わせください。',
@@ -5779,10 +5194,7 @@ _詳しい手順については、[ヘルプサイトをご覧ください](${CO
                 updateCard: 'カードを更新',
                 unassignCard: 'カードの割り当てを解除',
                 unassign: '割り当てを解除',
-                unassignCardDescription: 'このカードの割り当てを解除すると、未送信の取引はすべて削除されます。',
-                removeCard: 'カードを削除',
-                remove: '削除',
-                removeCardDescription: 'このカードを削除すると、未送信のすべての取引が削除されます。',
+                unassignCardDescription: 'このカードの割り当てを解除すると、ドラフトレポート上のすべての取引がカード所有者のアカウントから削除されます。',
                 assignCard: 'カードを割り当てる',
                 cardFeedName: 'カードフィード名',
                 cardFeedNameDescription: '他のカードフィードと区別できるように、一意の名前を付けてください。',
@@ -5814,9 +5226,9 @@ _詳しい手順については、[ヘルプサイトをご覧ください](${CO
                 noAccountsFound: 'アカウントが見つかりません',
                 defaultCard: 'デフォルトカード',
                 downgradeTitle: `ワークスペースをダウングレードできません`,
-                downgradeSubTitle: `このワークスペースには複数のカードフィード（Expensify カードを除く）が接続されているため、ダウングレードできません。続行するには、<a href="#">カードフィードを1つだけ残す</a>ようにしてください。`,
+                downgradeSubTitle: `このワークスペースには複数のカードフィード（Expensify Card を除く）が接続されているため、ダウングレードできません。続行するには、<a href="#">カードフィードを 1 つのみにしてください</a>。`,
                 noAccountsFoundDescription: (connection: string) => `${connection} にアカウントを追加して、もう一度接続を同期してください`,
-                expensifyCardBannerTitle: 'Expensify カードを入手する',
+                expensifyCardBannerTitle: 'Expensifyカードを入手',
                 expensifyCardBannerSubtitle:
                     '米国内でのあらゆるご利用でキャッシュバックを獲得し、Expensify の請求額を最大 50% 割引、無制限のバーチャルカードなど、さらに多くの特典をご利用いただけます。',
                 expensifyCardBannerLearnMoreButton: '詳細はこちら',
@@ -5827,7 +5239,7 @@ _詳しい手順については、[ヘルプサイトをご覧ください](${CO
                 title: 'ワークフロー',
                 subtitle: '支出の承認と支払い方法を設定します。',
                 disableApprovalPrompt:
-                    'このワークスペースの Expensify カードは現在、Smart Limits を設定するために承認フローに依存しています。承認を無効にする前に、Smart Limits が設定されている Expensify カードの上限タイプを変更してください。',
+                    'このワークスペースの Expensify Card は現在、Smart Limit を設定するために承認に依存しています。承認を無効にする前に、Smart Limit が設定されている Expensify Card の制限タイプをすべて変更してください。',
             },
             invoices: {
                 title: '請求書',
@@ -5872,7 +5284,7 @@ _詳しい手順については、[ヘルプサイトをご覧ください](${CO
             workflowWarningModal: {
                 featureEnabledTitle: 'ちょっと待ってください…',
                 featureEnabledText:
-                    'このワークスペースの Expensify カードは、Smart Limit を設定するために承認ワークフローに依存しています。\n\nワークフローを無効にする前に、Smart Limit が設定されているカードの上限タイプを変更してください。',
+                    'このワークスペース内の Expensify カードは、Smart Limit を設定するために承認ワークフローに依存しています。\n\nワークフローを無効にする前に、Smart Limit が設定されているカードの限度額タイプを変更してください。',
                 confirmText: 'Expensify カードに移動',
             },
             rules: {
@@ -5884,7 +5296,6 @@ _詳しい手順については、[ヘルプサイトをご覧ください](${CO
                 subtitle: '時間追跡用の請求可能な時間単価を設定します。',
                 defaultHourlyRate: 'デフォルトの時給率',
             },
-            hrWarningModal: {disconnectText: ({integration}: {integration: string}) => `HR を無効にするには、まずこのワークスペースから ${integration} を切断してください。`},
         },
         reports: {
             reportsCustomTitleExamples: '例:',
@@ -5906,7 +5317,10 @@ _詳しい手順については、[ヘルプサイトをご覧ください](${CO
             findReportField: 'レポート項目を検索',
             deleteConfirmation: 'このレポートフィールドを削除してもよろしいですか？',
             deleteFieldsConfirmation: 'これらのレポートフィールドを削除してもよろしいですか？',
-            emptyReportFields: {title: 'レポート項目はまだありません', subtitle: 'レポートに表示されるカスタムフィールド（テキスト、日付、またはドロップダウン）を追加する。'},
+            emptyReportFields: {
+                title: 'レポート項目がまだ作成されていません',
+                subtitle: 'レポートに表示されるカスタムフィールド（テキスト、日付、またはドロップダウン）を追加する。',
+            },
             subtitle: 'レポートフィールドはすべての支出に適用され、追加情報の入力を促したい場合に便利です。',
             disableReportFields: 'レポート項目を無効にする',
             disableReportFieldsConfirmation: '本当に実行しますか？テキストと日付フィールドは削除され、リストは無効になります。',
@@ -5930,7 +5344,10 @@ _詳しい手順については、[ヘルプサイトをご覧ください](${CO
             disableValues: '値を無効にする',
             enableValue: '値を有効にする',
             enableValues: '値を有効化',
-            emptyReportFieldsValues: {title: 'まだリストの値がありません', subtitle: 'レポートに表示するカスタム値を追加します。'},
+            emptyReportFieldsValues: {
+                title: 'リスト値がまだ作成されていません',
+                subtitle: 'レポートに表示するカスタム値を追加します。',
+            },
             deleteValuePrompt: 'このリスト値を削除してもよろしいですか？',
             deleteValuesPrompt: 'これらのリスト値を削除してもよろしいですか？',
             listValueRequiredError: 'リスト値の名前を入力してください',
@@ -5942,33 +5359,9 @@ _詳しい手順については、[ヘルプサイトをご覧ください](${CO
             reportFieldNameRequiredError: 'レポート項目名を入力してください',
             reportFieldTypeRequiredError: 'レポートフィールドの種類を選択してください',
             circularReferenceError: 'このフィールドを自分自身に参照することはできません。更新してください。',
-            unsupportedFormulaValueError: ({value}: UnsupportedFormulaValueErrorParams) => `数式フィールド ${value} が認識されません`,
             reportFieldInitialValueRequiredError: 'レポート項目の初期値を選択してください',
             genericFailureMessage: 'レポートフィールドの更新中にエラーが発生しました。もう一度お試しください。',
         },
-        invoiceFields: {
-            subtitle: '追加情報を含めたい場合、請求書フィールドが役立ちます。',
-            importedFromAccountingSoftware: '以下の請求書フィールドは、次からインポートされます',
-            disableInvoiceFields: '請求書フィールドを無効にする',
-            disableInvoiceFieldsConfirmation: 'よろしいですか？請求書フィールドは請求書で無効になります。',
-            delete: '請求書フィールドを削除',
-            deleteConfirmation: 'この請求書フィールドを削除してもよろしいですか？',
-            findInvoiceField: '請求書フィールドを検索',
-            nameInputSubtitle: '請求書フィールドの名前を選択してください。',
-            typeInputSubtitle: '使用する請求書フィールドの種類を選択してください。',
-            initialValueInputSubtitle: '請求書フィールドに表示する開始値を入力してください。',
-            listValuesInputSubtitle: 'これらの値は請求書フィールドのドロップダウンに表示されます。有効な値はメンバーが選択できます。',
-            listInputSubtitle: 'これらの値は請求書フィールドのリストに表示されます。有効な値はメンバーが選択できます。',
-            emptyInvoiceFieldsValues: {
-                title: 'リスト値はまだありません',
-                subtitle: '請求書に表示するカスタム値を追加します。',
-            },
-            existingInvoiceFieldNameError: 'この名前の請求書フィールドは既に存在します',
-            invoiceFieldNameRequiredError: '請求書フィールド名を入力してください',
-            invoiceFieldTypeRequiredError: '請求書フィールドの種類を選択してください',
-            invoiceFieldInitialValueRequiredError: '請求書フィールドの初期値を選択してください',
-            addField: 'フィールドを追加',
-        },
         tags: {
             tagName: 'タグ名',
             requiresTag: 'メンバーはすべての経費にタグを付ける必要があります',
@@ -5986,14 +5379,14 @@ _詳しい手順については、[ヘルプサイトをご覧ください](${CO
             editTags: 'タグを編集',
             findTag: 'タグを検索',
             subtitle: 'タグを使うと、コストをより詳しく分類できます。',
-            subtitleWithDependentTags: (importSpreadsheetLink: string, canReimport = true) =>
-                `<muted-text>タグを使うと、コストをより詳しく分類できます。あなたは<a href="${CONST.IMPORT_TAGS_EXPENSIFY_URL_DEPENDENT_TAGS}">連動タグ</a>を使用しています。${canReimport ? `タグを更新するには、<a href="${importSpreadsheetLink}">スプレッドシートを再インポート</a>できます。` : ''}</muted-text>`,
+            dependentMultiLevelTagsSubtitle: (importSpreadsheetLink: string) =>
+                `<muted-text>あなたは<a href="${CONST.IMPORT_TAGS_EXPENSIFY_URL_DEPENDENT_TAGS}">連動タグ</a>を使用しています。タグを更新するには、<a href="${importSpreadsheetLink}">スプレッドシートを再インポート</a>できます。</muted-text>`,
             emptyTags: {
-                title: 'タグはまだありません',
+                title: 'タグがまだ作成されていません',
                 subtitle: 'タグを追加して、プロジェクト、所在地、部署などを追跡しましょう。',
                 subtitleHTML: `<muted-text><centered-text>タグを追加して、プロジェクト、所在地、部門などを追跡しましょう。インポート用のタグファイルの書式設定については、<a href="${CONST.IMPORT_TAGS_EXPENSIFY_URL}">詳しくはこちら</a>をご覧ください。</centered-text></muted-text>`,
-                subtitleWithAccounting: (accountingPageURL: string, canManage = true) =>
-                    `<muted-text><centered-text>現在、タグは会計連携からインポートされています。${canManage ? `変更するには<a href="${accountingPageURL}">会計</a>に移動してください。` : ''}</centered-text></muted-text>`,
+                subtitleWithAccounting: (accountingPageURL: string) =>
+                    `<muted-text><centered-text>現在、タグは会計連携からインポートされています。変更するには<a href="${accountingPageURL}">会計</a>に移動してください。</centered-text></muted-text>`,
             },
             deleteTag: 'タグを削除',
             deleteTags: 'タグを削除',
@@ -6079,7 +5472,7 @@ _詳しい手順については、[ヘルプサイトをご覧ください](${CO
                 updateTaxClaimableFailureMessage: '返金可能額は距離レート額より小さくなければなりません',
             },
             deleteTaxConfirmation: 'この税を削除してもよろしいですか？',
-            deleteMultipleTaxConfirmation: (taxAmount: number) => `${taxAmount} 件の税額を削除してもよろしいですか？`,
+            deleteMultipleTaxConfirmation: ({taxAmount}: TaxAmountParams) => `${taxAmount} 件の税額を削除してもよろしいですか？`,
             actions: {
                 delete: 'レートを削除',
                 deleteMultiple: 'レートを削除',
@@ -6107,45 +5500,10 @@ _詳しい手順については、[ヘルプサイトをご覧ください](${CO
             reimbursementAccount: '精算口座',
             welcomeNote: '私の新しいワークスペースを使い始めてください',
             delayedSubmission: '遅延提出',
-            merchantRules: '販売者ルール',
-            merchantRulesCount: () => ({
-                one: '1 販売者ルール',
-                other: (count: number) => `${count} 販売者ルール`,
-            }),
             confirmTitle: ({newWorkspaceName, totalMembers}: {newWorkspaceName?: string; totalMembers?: number}) =>
                 `元のワークスペースから ${totalMembers ?? 0} 人のメンバーと一緒に、${newWorkspaceName ?? ''} を作成して共有しようとしています。`,
             error: '新しいワークスペースの複製中にエラーが発生しました。もう一度お試しください。',
         },
-        copyPolicySettings: {
-            title: '設定をコピー',
-            error: 'ワークスペース設定のコピー中にエラーが発生しました。もう一度お試しください。',
-            selectWorkspaces: {
-                title: 'ワークスペースを選択',
-                description: '設定をコピーしたいワークスペースを選択し、その後、コピーしたい設定を選びます。',
-                searchPlaceholder: 'ワークスペースを検索',
-            },
-            selectSettings: {
-                title: 'コピーする機能を選択します',
-                description: '既存のワークスペースで上書きする設定を選択します。',
-                accountingMismatch: ({part}: {part: string}) => `すべてのワークスペースが同じ会計システムと会社接続を使用している場合にのみ、${part} をコピーできます。`,
-            },
-            confirmSettings: {
-                title: 'すべて正しく表示されているか確認しましょう。',
-                description: ({workspaceName}: {workspaceName: string}) => `次の設定を<strong>${workspaceName}</strong>から指定したワークスペースにコピーします`,
-            },
-            confirmWorkflows: {
-                continue: 'メンバーなしで続行',
-                description: 'メンバーなしでワークフローをコピーすると、承認ワークフローはコピーされません。提出と支払いの設定は引き続きコピーされます。',
-            },
-            progress: {
-                copyInProgressTitle: 'コピーを実行中です...',
-                copyInProgressDescription: '処理が完了するまで待つこともできますし、完了したら Concierge からお知らせすることもできます。',
-                letMeKnowPrompt: '完了したら教えてください',
-                conciergeNotificationTitle: 'Concierge からお知らせします',
-                conciergeNotificationDescription: '処理が完了すると、Concierge からメッセージが送信されます。',
-                copyCompleted: 'ワークスペースの設定がコピーされました。',
-            },
-        },
         emptyWorkspace: {
             title: 'ワークスペースがありません',
             subtitle: '領収書を管理し、経費を精算し、出張を管理し、請求書を送信するなど、さまざまなことができます。',
@@ -6160,7 +5518,7 @@ _詳しい手順については、[ヘルプサイトをご覧ください](${CO
         },
         new: {
             newWorkspace: '新しいワークスペース',
-            getTheExpensifyCardAndMore: 'Expensify カードなどを利用する',
+            getTheExpensifyCardAndMore: 'Expensifyカードなどを入手する',
             confirmWorkspace: 'ワークスペースを確認',
             myGroupWorkspace: ({workspaceNumber}: {workspaceNumber?: number}) => `マイ・グループワークスペース${workspaceNumber ? ` ${workspaceNumber}` : ''}`,
             workspaceName: (userName: string, workspaceNumber?: number) => `${userName} のワークスペース${workspaceNumber ? ` ${workspaceNumber}` : ''}`,
@@ -6203,12 +5561,12 @@ _詳しい手順については、[ヘルプサイトをご覧ください](${CO
                 genericRemove: 'そのワークスペースメンバーを削除する際に問題が発生しました',
             },
             addedWithPrimary: '一部のメンバーは、プライマリーログインで追加されました。',
-            invitedBySecondaryLogin: (secondaryLogin: string) => `セカンダリログイン${secondaryLogin}によって追加されました。`,
-            workspaceMembersCount: (count: number) => `ワークスペースメンバー合計：${count}`,
+            invitedBySecondaryLogin: ({secondaryLogin}: SecondaryLoginParams) => `セカンダリログイン${secondaryLogin}によって追加されました。`,
+            workspaceMembersCount: ({count}: WorkspaceMembersCountParams) => `ワークスペースメンバー合計：${count}`,
             importMembers: 'メンバーをインポート',
-            removeMemberPromptApprover: (approver: string, workspaceOwner: string) =>
+            removeMemberPromptApprover: ({approver, workspaceOwner}: {approver: string; workspaceOwner: string}) =>
                 `このワークスペースから${approver}を削除すると、承認ワークフロー内ではワークスペースのオーナーである${workspaceOwner}に置き換えられます。`,
-            removeMemberPromptPendingApproval: (memberName: string) =>
+            removeMemberPromptPendingApproval: ({memberName}: {memberName: string}) =>
                 `${memberName} には未承認の経費精算書があります。ワークスペースから削除する前に、承認してもらうか、その精算書の管理を引き継いでください。`,
             removeMemberPromptReimburser: ({memberName}: {memberName: string}) =>
                 `このワークスペースから${memberName}を削除することはできません。ワークフロー ＞ 支払いの作成または追跡 で新しい払い戻し担当者を設定してから、もう一度お試しください。`,
@@ -6218,20 +5576,10 @@ _詳しい手順については、[ヘルプサイトをご覧ください](${CO
                 `このワークスペースから${memberName}を削除すると、技術連絡先はワークスペースのオーナーである${workspaceOwner}に置き換えられます。`,
             cannotRemoveUserDueToReport: ({memberName}: {memberName: string}) =>
                 `${memberName} は、対応が必要な未処理のレポートがあります。ワークスペースから削除する前に、必要な対応を完了するよう依頼してください。`,
-            allMembers: 'すべてのメンバー',
-            admins: 'ワークスペース管理者',
-            cardAdmins: 'カード管理者',
-            approvers: '承認者',
-            auditors: '監査担当者',
-            emptyRoleFilter: {title: 'このフィルターに一致するメンバーはいません', subtitle: 'メンバーを招待するか、上のフィルターを変更してください。'},
-            configureHRSync: (providerName: string) => `${providerName} の同期を設定します。`,
-            syncWithHR: (providerName: string) => `${providerName}と同期`,
-            makeCardAdmin: () => ({one: 'カード管理者にする', other: 'カード管理者を作成'}),
         },
         card: {
             getStartedIssuing: 'まずは最初のバーチャルカードまたは物理カードを発行しましょう。',
             issueCard: 'カードを発行',
-            chooseRule: 'ルールを選択してください',
             issueNewCard: {
                 whoNeedsCard: '誰がカードを必要としていますか？',
                 inviteNewMember: '新しいメンバーを招待',
@@ -6273,27 +5621,21 @@ _詳しい手順については、[ヘルプサイトをご覧ください](${CO
                 enterValidDate: '有効な日付を入力してください',
                 expirationDate: '有効期限',
                 limitAmount: '制限額',
-                setCardRules: 'カードルールを設定',
-                addSpendRule: '支出ルールを追加',
-                addExpirationDate: '有効期限を追加',
-                addExpirationDateDescription: '特定の日付が設定されていない場合、カードは既存の有効期限に基づいて失効します',
+                setExpiryOptions: '有効期限オプションを設定',
+                setExpiryDate: '有効期限を設定',
+                setExpiryDateDescription: 'カードに記載されている通りにカードは期限切れになります',
                 amount: '金額',
-                copyExisting: '既存のものをコピー',
-                createNew: '新規作成',
-                spendRulesEmptyStateTitle: '選択できるルールがありません',
-                spendRulesEmptyStateSubtitle: 'まだルールがありません。前の画面から作成できます。',
             },
             deactivateCardModal: {
                 deactivate: '無効化',
                 deactivateCard: 'カードを無効化',
                 deactivateConfirmation: 'このカードを無効化すると今後のすべての取引が拒否され、元に戻すことはできません。',
             },
-            searchRules: '支出ルールを検索',
         },
         accounting: {
             settings: '設定',
             title: '接続',
-            subtitle: '会計ソフトを接続して、自動同期を行いましょう。',
+            subtitle: '会計システムに接続して勘定科目で取引を仕訳し、支払いを自動照合し、財務情報を常に同期させましょう。',
             qbo: 'QuickBooks Online',
             qbd: 'QuickBooks Desktop',
             xero: 'Xero',
@@ -6302,7 +5644,7 @@ _詳しい手順については、[ヘルプサイトをご覧ください](${CO
             sap: 'SAP',
             oracle: 'Oracle',
             microsoftDynamics: 'Microsoft Dynamics',
-            talkYourOnboardingSpecialist: 'アカウントエグゼクティブとチャットします。',
+            talkYourOnboardingSpecialist: 'セットアップ担当者とチャットする',
             talkYourAccountManager: 'アカウントマネージャーとチャットする',
             talkToConcierge: 'Conciergeとチャットする',
             needAnotherAccounting: 'ほかの会計ソフトが必要ですか？',
@@ -6376,8 +5718,6 @@ _詳しい手順については、[ヘルプサイトをご覧ください](${CO
             connectPrompt: ({connectionName}: ConnectionNameParams) =>
                 `${CONST.POLICY.CONNECTIONS.NAME_USER_FRIENDLY[connectionName] ?? 'この会計連携'} を接続してもよろしいですか？これにより、既存の会計連携はすべて削除されます。`,
             enterCredentials: '認証情報を入力してください',
-            reconnect: '再接続',
-            updateCredentials: '認証情報を更新',
             claimOffer: {
                 badgeText: 'オファーをご利用いただけます！',
                 xero: {
@@ -6521,26 +5861,6 @@ _詳しい手順については、[ヘルプサイトをご覧ください](${CO
                             return 'Sage Intacct ディメンションのインポート';
                         case 'intacctImportTitle':
                             return 'Sage Intacct データのインポート';
-                        case 'financialForceSyncTitle':
-                            return 'Certinia データを同期中';
-                        case 'financialForceSyncStep':
-                            return 'Certinia 接続を同期中';
-                        case 'financialForceSyncCategories':
-                            return 'カテゴリをインポート中';
-                        case 'financialForceSyncTags':
-                            return 'タグをインポート中';
-                        case 'financialForceSyncVendors':
-                            return 'ベンダーをインポート中';
-                        case 'financialForceSyncContacts':
-                            return '連絡先をインポート中';
-                        case 'financialForceSyncCompanies':
-                            return '会社をインポート中';
-                        case 'financialForceSyncUsers':
-                            return 'ユーザーをインポート中';
-                        case 'financialForceSyncDimensions':
-                            return 'ディメンションをインポート中';
-                        case 'financialForceMarkAsReimbursed':
-                            return 'レポートを払い戻し済みにマーク中';
                         default: {
                             return `ステージの翻訳が見つかりません: ${stage}`;
                         }
@@ -6562,18 +5882,14 @@ _詳しい手順については、[ヘルプサイトをご覧ください](${CO
             cardReconciliation: 'カード照合',
             reconciliationAccount: '照合勘定',
             continuousReconciliation: '継続的な照合',
-            saveHoursOnReconciliation: 'Expensify が Expensify カードの明細と清算を自動的に照合することで、会計期間ごとの消し込み作業にかかる時間を大幅に削減できます。',
+            saveHoursOnReconciliation: '会計期間ごとの照合作業を、Expensify が Expensify カードの利用明細と清算を自動的かつ継続的に照合して代行することで、数時間分削減できます。',
             enableContinuousReconciliation: (accountingAdvancedSettingsLink: string, connectionName: string) =>
                 `<muted-text-label>継続的な消込を有効にするには、${connectionName} の<a href="${accountingAdvancedSettingsLink}">自動同期</a>を有効にしてください。</muted-text-label>`,
             chooseReconciliationAccount: {
-                chooseBankAccount: 'Expensify カードの支払いを照合する銀行口座を選択してください。',
-                settlementAccountReconciliation: (settlementAccountUrl: string, lastFourPAN: string) =>
-                    `継続消込が正しく機能するように、この口座が、末尾が ${lastFourPAN} の<a href="${settlementAccountUrl}">Expensify カード精算口座</a>と一致していることを確認してください。`,
-                chooseTravelInvoicingBankAccount: '出張請求の支払いの消込に使用する銀行口座を選択してください。',
-                travelInvoicingSettlementAccountReconciliation: (lastFourPAN: string) =>
-                    `Continuous Reconciliation が正しく機能するように、この口座が、旅行の請求書決済用口座（末尾が ${lastFourPAN} の口座）と一致していることを確認してください。`,
+                chooseBankAccount: 'Expensify Card の支払いを照合する銀行口座を選択してください。',
+                settlementAccountReconciliation: ({settlementAccountUrl, lastFourPAN}: SettlementAccountReconciliationParams) =>
+                    `この口座が、継続照合が正しく機能するように、末尾が ${lastFourPAN} の<a href="${settlementAccountUrl}">Expensify Card 精算口座</a>と一致していることを確認してください。`,
             },
-            syncTravelInvoicingSettlements: '出張請求の精算を同期',
         },
         export: {
             notReadyHeading: 'エクスポートの準備ができていません',
@@ -6652,13 +5968,7 @@ _詳しい手順については、[ヘルプサイトをご覧ください](${CO
             errors: {
                 rateNameRequired: 'レート名は必須です',
                 existingRateName: 'この名前の距離レートはすでに存在します',
-                nameRequired: '名前は必須です',
-                startDateMustBeBeforeEndDate: '開始日は終了日より前でなければなりません',
-                amountRequired: '金額は必須です',
             },
-            amountPerUnit: (unit: string) => `${unit}あたりの金額`,
-            startDate: '開始日',
-            endDate: '終了日',
         },
         editor: {
             descriptionInputLabel: '説明',
@@ -6700,7 +6010,7 @@ _詳しい手順については、[ヘルプサイトをご覧ください](${CO
             updateToUSD: 'USD に更新',
             updateWorkspaceCurrency: 'ワークスペースの通貨を更新',
             workspaceCurrencyNotSupported: 'ワークスペースの通貨はサポートされていません',
-            yourWorkspace: `ご利用のワークスペースはサポートされていない通貨に設定されています。<a href="${CONST.ENABLE_GLOBAL_REIMBURSEMENT_HELP_URL}">サポートされている通貨の一覧</a>を表示します。`,
+            yourWorkspace: `ご利用のワークスペースはサポートされていない通貨に設定されています。<a href="${CONST.CONNECT_A_BUSINESS_BANK_ACCOUNT_HELP_URL}">サポートされている通貨の一覧</a>を表示します。`,
             chooseAnExisting: '既存の銀行口座を選択して経費を支払うか、新しい口座を追加してください。',
         },
         changeOwner: {
@@ -6737,7 +6047,7 @@ _詳しい手順については、[ヘルプサイトをご覧ください](${CO
             hasFailedSettlementsTitle: '所有権を譲渡できません',
             hasFailedSettlementsButtonText: '了解しました',
             hasFailedSettlementsText: (email: string) =>
-                `${email} に未払いの Expensify カードの清算があるため、請求の引き継ぎはできません。問題を解決するために、concierge@expensify.com まで連絡するよう依頼してください。その後、このワークスペースの請求を引き継ぐことができます。`,
+                `${email} に未払いの Expensify Card 精算があるため、請求を引き継ぐことはできません。問題を解決するために、concierge@expensify.com まで連絡するよう依頼してください。その後、このワークスペースの請求を引き継ぐことができます。`,
             failedToClearBalanceTitle: '残高のクリアに失敗しました',
             failedToClearBalanceButtonText: 'OK',
             failedToClearBalanceText: '残高を消去できませんでした。後でもう一度お試しください。',
@@ -6766,12 +6076,6 @@ ${reportName}
                 onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
                     `<muted-text>レポートフィールドは、<strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `メンバー1人あたり月額` : `アクティブメンバー1人あたり月額`}からのControlプランでのみ利用できます</muted-text>`,
             },
-            invoiceFields: {
-                title: '請求書項目',
-                description: `請求書フィールドを使うと、請求書レベルの追加情報を請求書に含めることができます。`,
-                onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
-                    `<muted-text>請求書フィールドは、<strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `メンバー1人あたり月額` : `アクティブメンバー1人あたり月額`}からのControlプランでのみ利用できます</muted-text>`,
-            },
             [CONST.POLICY.CONNECTIONS.NAME.NETSUITE]: {
                 title: 'NetSuite',
                 description: `Expensify と NetSuite の連携により、自動同期を活用して手入力を減らしましょう。プロジェクトや顧客のマッピングを含むネイティブおよびカスタムセグメントのサポートで、詳細かつリアルタイムな財務インサイトを得られます。`,
@@ -6790,12 +6094,6 @@ ${reportName}
                 onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
                     `<muted-text>QuickBooks Desktop 連携機能は、<strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `メンバー1人あたり月額` : `アクティブメンバー1人あたり月額`} からの Control プランでのみご利用いただけます</muted-text>`,
             },
-            [CONST.POLICY.CONNECTIONS.NAME.CERTINIA]: {
-                title: 'Certinia',
-                description: `Expensify と Certinia の連携で自動同期を活用し、手入力を減らしましょう。経費のコーディングディメンションと税務同期を Certinia の設定に合わせて、財務の可視性を高めます。`,
-                onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
-                    `<muted-text>Certinia 連携は Control プランでのみご利用いただけます。<strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `メンバー1人あたり月額` : `アクティブメンバー1人あたり月額`} からご利用いただけます。</muted-text>`,
-            },
             [CONST.UPGRADE_FEATURE_INTRO_MAPPING.approvals.id]: {
                 title: '高度な承認',
                 description: `承認フローにさらに多くの段階を追加したい場合や、高額な経費に必ず別の承認者の目を通したい場合も、ご安心ください。高度な承認機能により、あらゆるレベルで適切なチェック体制を整え、チームの支出をしっかり管理できます。`,
@@ -6872,7 +6170,7 @@ ${reportName}
                 onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
                     `<muted-text>距離レートはCollectプランで利用できます。<strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `メンバー1人あたり月額` : `アクティブメンバー1人あたり月額`}からご利用になれます</muted-text>`,
             },
-            controlPolicyRoles: {
+            auditor: {
                 title: '監査人',
                 description: '監査担当者は、可視性とコンプライアンス監視を徹底するため、すべてのレポートを閲覧専用で確認できます。',
                 onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
@@ -6888,12 +6186,13 @@ ${reportName}
                 perActiveMember: 'アクティブメンバー1人あたり月額',
                 perMember: 'メンバー1人あたり月額',
             },
-            note: (subscriptionLink: string) => `<muted-text>プランと料金については<a href="${subscriptionLink}">詳しく見る</a>をご覧ください。</muted-text>`,
+            note: ({subscriptionLink}: WorkspaceUpgradeNoteParams) =>
+                `<muted-text>この機能を利用するにはアップグレードするか、プランと料金の詳細は<a href="${subscriptionLink}">こちら</a>をご覧ください。</muted-text>`,
             upgradeToUnlock: 'この機能を有効にする',
             completed: {
                 headline: `ワークスペースをアップグレードしました！`,
-                successMessage: (policyName: string, planName: string, subscriptionLink: string) =>
-                    `<centered-text>${policyName}を${planName}プランにアップグレードしました！詳しくは<a href="${subscriptionLink}">サブスクリプションを表示</a>してください。</centered-text>`,
+                successMessage: ({policyName, subscriptionLink}: UpgradeSuccessMessageParams) =>
+                    `<centered-text>${policyName}をControlプランにアップグレードしました！詳しくは<a href="${subscriptionLink}">サブスクリプションを表示</a>してください。</centered-text>`,
                 categorizeMessage: `Collectプランへのアップグレードが完了しました。これで経費をカテゴリー分けできるようになりました！`,
                 travelMessage: `Collectプランへのアップグレードが完了しました。さっそく出張の予約や管理を始めましょう！`,
                 distanceRateMessage: `Collectプランへのアップグレードが完了しました。これで距離単価を変更できるようになりました！`,
@@ -6916,83 +6215,24 @@ ${reportName}
                 upgradeWorkspaceWarning: `ワークスペースをアップグレードできません`,
                 upgradeWorkspaceWarningForRestrictedPolicyCreationPrompt: 'あなたの会社ではワークスペースの作成が制限されています。管理者に連絡してサポートを受けてください。',
             },
-            hr: {
-                title: '人事連携',
-                description: '人事システムを連携して、従業員情報を自動で同期し、承認ワークフローを管理できます。チームの名簿とレポートラインを手作業なしで最新の状態に保てます。',
-                onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
-                    `<muted-text>人事システム連携は、<strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `メンバー1人あたり月額` : `アクティブメンバー1人あたり、1か月ごと。`}からのControlプランでのみご利用いただけます</muted-text>`,
-            },
-            approvalSubmit: {
-                title: '承認',
-                description: '承認機能を有効にして、全メンバーの提出先を一括設定しましょう。',
-                onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
-                    `<muted-text>承認機能は、Collect プランおよび Control プランで利用できます。料金は <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `メンバー1人あたり月額` : `アクティブメンバー1人あたり月額`} からです。</muted-text>`,
-            },
-            companyCardSubmit: {
-                title: '会社カード',
-                description: `お使いの会社カードをExpensifyに連携して、自動取込、自動分類、カスタマイズ可能なルール設定、そして統合された照合機能を利用しましょう。`,
-                onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
-                    `<muted-text>会社カードのインポートは、Collect プランと Control プランで利用できます。料金は <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `メンバー1人あたり月額` : `アクティブメンバー1人あたり月額`} からです。</muted-text>`,
-            },
-            travelSubmit: {
-                title: 'Expensify トラベル',
-                description: 'Expensify から世界中の割引航空券、ホテル、レンタカー、列車を予約し、デューティ・オブ・ケアレポートと経費管理を統合して利用できます。',
-                onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
-                    `<muted-text>Expensify Travel は Collect プランと Control プランで利用でき、<strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `メンバー1人あたり月額` : `アクティブメンバー1人あたり月額`} からご利用いただけます</muted-text>`,
-            },
-            roles: {
-                title: 'ロール',
-                description: 'メンバーごとに異なるロールを割り当て、必要に応じて閲覧権限や管理権限を増減させましょう。',
-                onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
-                    `<muted-text>ロールは、Collect および Control プランで利用できます。<strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `メンバー1人あたり月額` : `アクティブメンバー1人あたり月額`} からご利用いただけます</muted-text>`,
-            },
-            payments: {
-                title: '支払い',
-                description: '従業員への精算を、事業用銀行口座から直接行います。',
-                onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
-                    `<muted-text>支払い機能は、Collect プランおよび Control プランで利用できます。料金は <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `メンバー1人あたり月額` : `アクティブメンバー1人あたり月額`} からです</muted-text>`,
-            },
-            accounting: {
-                title: '会計',
-                description: '会計システムからExpensifyへカテゴリ、タグ、税率などを同期し、経費レポートやカード取引をエクスポートできます。手入力も、入力ミスの心配も不要です！',
-                onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
-                    `<muted-text>会計機能は Collect プランと Control プランでご利用いただけます。<strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `メンバー1人あたり月額` : `アクティブメンバー1人あたり月額`}からご利用可能です</muted-text>`,
-            },
-            expensifyCard: {
-                title: 'Expensify カード',
-                description:
-                    '自社の銀行口座から（バーチャルカードを含む）コーポレートカードを直接発行し、途切れない連携によるリアルタイムな支出管理と、最大2%のキャッシュバックを手に入れましょう！',
-                onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
-                    `<muted-text>Expensify Card は Collect プランと Control プランでご利用いただけます。料金は <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `メンバー1人あたり月額` : `アクティブメンバー1人あたり月額`} からです。</muted-text>`,
-                upgradeButton: 'アップグレードして有効化',
-            },
-            invoicing: {
-                title: '請求書発行',
-                description: 'Expensify 内でプロ仕様の請求書を作成・送信・追跡。統合された支払い機能とリアルタイムの可視性で、より早く入金を受けましょう。',
-                onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
-                    `<muted-text>請求書発行機能は、Collect プランと Control プランでご利用いただけます。<strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `メンバー1人あたり月額` : `アクティブメンバー1人あたり月額`}からご利用可能です。</muted-text>`,
-            },
         },
         downgrade: {
             commonFeatures: {
-                title: 'Collect にダウングレード',
-                note: '次の機能へのアクセス権がなくなります',
+                title: 'Collectプランにダウングレードする',
+                note: 'ダウングレードすると、これらの機能などへのアクセスができなくなります。',
                 benefits: {
-                    confirm: 'Collect レートを適用するには、すべてのワークスペースの「プランタイプ」を「Collect」に変更する必要があります。',
-                    benefit1: 'NetSuite、Sage Intacct、QuickBooks Desktop、Oracle、Microsoft Dynamics',
-                    benefit2: 'Workday、Certinia',
-                    benefit3: 'SSO/SAML',
-                    benefit4: 'スマート経費ルール、日当、マルチレベル承認、カスタムレポート、予算管理',
+                    note: '各プランを完全に比較するには、こちらのページをご確認ください',
+                    pricingPage: '料金ページ',
+                    confirm: 'ダウングレードして、設定を削除してもよろしいですか？',
+                    warning: 'この操作は元に戻せません。',
+                    benefit1: '会計連携（QuickBooks Online と Xero を除く）',
+                    benefit2: 'スマート経費ルール',
+                    benefit3: '多段階承認ワークフロー',
+                    benefit4: '強化されたセキュリティ管理',
                     headsUp: 'ご注意ください！',
                     multiWorkspaceNote: 'Collect料金でのサブスクリプションを開始するには、初回の月額支払いの前に、すべてのワークスペースをダウングレードする必要があります。クリック',
                     selectStep: '> 各ワークスペースを選択 > プランタイプを変更',
-                    benefit1Label: 'ERP 連携',
-                    benefit2Label: '人事連携',
-                    benefit3Label: 'セキュリティ',
-                    benefit4Label: '詳細設定',
-                    important: '重要:',
                 },
-                noteAndMore: 'など：',
             },
             completed: {
                 headline: 'ワークスペースがダウングレードされました',
@@ -7012,7 +6252,7 @@ ${reportName}
         restrictedAction: {
             restricted: '制限あり',
             actionsAreCurrentlyRestricted: (workspaceName: string) => `${workspaceName} ワークスペースでの操作は現在制限されています`,
-            workspaceOwnerWillNeedToAddOrUpdatePaymentCard: (workspaceOwnerName: string) =>
+            workspaceOwnerWillNeedToAddOrUpdatePaymentCard: ({workspaceOwnerName}: WorkspaceOwnerWillNeedToAddOrUpdatePaymentCardParams) =>
                 `ワークスペースオーナーである${workspaceOwnerName}が、ワークスペースの新しいアクティビティを有効にするために、登録済みの支払いカードを追加または更新する必要があります。`,
             youWillNeedToAddOrUpdatePaymentCard: '新しいワークスペースのアクティビティを有効にするには、登録済みの支払いカードを追加または更新する必要があります。',
             addPaymentCardToUnlock: 'ロック解除のために支払いカードを追加してください！',
@@ -7065,18 +6305,16 @@ ${reportName}
                 eReceiptsHint: `eReceiptsは[ほとんどの米ドル建てクレジット取引に対して自動作成されます](${CONST.DEEP_DIVE_ERECEIPTS})。`,
                 attendeeTracking: '出席者の追跡',
                 attendeeTrackingHint: '各経費について、1人あたりの費用を追跡します。',
-                prohibitedDefaultDescription: 'これらの明細項目を含むレシートにフラグを付けて、手動で確認します。',
+                prohibitedDefaultDescription:
+                    'アルコール、ギャンブル、その他の制限対象品目が含まれている領収書にフラグを付けてください。これらの品目が記載された領収書の経費は、手動での確認が必要になります。',
                 prohibitedExpenses: '禁止経費',
                 alcohol: 'アルコール',
                 hotelIncidentals: 'ホテル付帯費用',
                 gambling: 'ギャンブル',
                 tobacco: 'たばこ',
                 adultEntertainment: 'アダルトエンターテインメント',
-                giftCard: 'ギフトカード購入',
-                handwrittenReceipt: '手書きレシート',
                 requireCompanyCard: 'すべての購入に会社カードを必須にする',
                 requireCompanyCardDescription: 'マイレージや日当経費を含む、すべての現金支出にフラグを付ける。',
-                requireCompanyCardDisabledTooltip: 'ロック解除するには、「その他の機能」内の「会社カード」を有効にしてください。',
             },
             expenseReportRules: {
                 title: '詳細設定',
@@ -7085,8 +6323,8 @@ ${reportName}
                 preventSelfApprovalsSubtitle: 'ワークスペースメンバーが自分自身の経費レポートを承認できないようにする。',
                 autoApproveCompliantReportsTitle: 'コンプライアンス準拠レポートを自動承認',
                 autoApproveCompliantReportsSubtitle: '自動承認の対象とする経費レポートを設定します。',
-                autoApproveReportsUnderTitle: 'すべての経費がこの金額以下のレポートを自動承認',
-                autoApproveReportsUnderDescription: 'すべての経費がこの金額以下で完全準拠している経費精算書は、自動的に承認されます。',
+                autoApproveReportsUnderTitle: '自動承認するレポートの上限額',
+                autoApproveReportsUnderDescription: 'この金額以下で完全準拠している経費精算書は、自動的に承認されます。',
                 randomReportAuditTitle: 'ランダムレポート監査',
                 randomReportAuditDescription: '一部のレポートについては、自動承認の対象であっても手動承認を必須にする',
                 autoPayApprovedReportsTitle: '自動支払い対象の承認済みレポート',
@@ -7099,11 +6337,6 @@ ${reportName}
                 enableFeatureSubtitle: (featureName: string, moreFeaturesLink?: string) =>
                     `[その他の機能](${moreFeaturesLink})に移動し、${featureName} を有効にしてこの機能を利用できるようにしてください。`,
             },
-            agentsPromoBanner: {
-                title: '必要なルールが見つかりませんか？エージェントを追加してください',
-                subtitle: '複雑なルールを追加し、カスタムエージェントで手動承認を減らしましょう。',
-                cta: 'お試しください',
-            },
             merchantRules: {
                 title: '加盟店',
                 subtitle: '経費が正しくコード化され、後処理が最小限で済むように、取引先ルールを設定しましょう。',
@@ -7131,10 +6364,9 @@ ${reportName}
                 matchTypeContains: '含む',
                 matchTypeExact: '完全一致',
                 duplicateRuleTitle: '同様のマーチャントルールが既に存在します',
-                duplicateRulePrompt: (merchantName: string) => `「${merchantName}」に対する既存のルールが、このルールよりも優先されます。保存しますか？`,
+                duplicateRulePrompt: (merchantName: string) => `既にルールが存在しますが、「${merchantName}」用に新しいルールを保存しますか？`,
                 saveAnyway: 'とにかく保存',
                 applyToExistingUnsubmittedExpenses: '既存の未提出経費に適用',
-                findRule: '加盟店ルールを検索',
             },
             categoryRules: {
                 title: 'カテゴリルール',
@@ -7171,130 +6403,12 @@ ${reportName}
                     always: '常に明細付きの領収書を必須にする',
                 },
                 defaultTaxRate: 'デフォルト税率',
-                enableWorkflows: (moreFeaturesLink: string) => `[その他の機能](${moreFeaturesLink})に移動してワークフローを有効にし、承認を追加してこの機能を有効化してください。`,
+                enableWorkflows: ({moreFeaturesLink}: RulesEnableWorkflowsParams) =>
+                    `[その他の機能](${moreFeaturesLink})に移動してワークフローを有効にし、承認を追加してこの機能を有効化してください。`,
             },
             customRules: {
                 title: '経費ポリシー',
                 cardSubtitle: 'ここはチームの経費ポリシーが保存されている場所です。何が対象になるか、全員が同じ認識を持てます。',
-                policyDocument: 'ポリシー文書',
-                policyText: 'ポリシーテキスト',
-            },
-            spendRules: {
-                title: '支出',
-                subtitle: 'Expensify カードの取引をリアルタイムで承認または却下できます。',
-                defaultRuleDescription: 'すべてのカード',
-                block: 'ブロック',
-                defaultRuleTitle: 'カテゴリ：アダルトサービス、ATM、ギャンブル、送金',
-                builtInProtectionModal: {
-                    title: 'Expensify カードには、常に標準で保護機能があります',
-                    description: `Expensify は、次のような支払いを常に拒否します：
-
-  ・アダルトサービス
-  ・ATM
-  ・ギャンブル
-  ・送金
-
-会社のキャッシュフローを守るために、支出ルールをさらに追加しましょう。`,
-                },
-                addSpendRule: '支出ルールを追加',
-                cardPageTitle: 'カード',
-                cardsSectionTitle: 'カード',
-                chooseCards: 'カードを選択',
-                saveRule: 'ルールを保存',
-                allow: '許可',
-                spendRuleSectionTitle: '支出ルール',
-                restrictionType: '制限タイプ',
-                restrictionTypeHelpAllow: 'いずれかの加盟店またはカテゴリに一致し、上限金額を超えない場合、請求は承認されます。',
-                restrictionTypeHelpBlock: '加盟店またはカテゴリに一致するか、上限金額を超えた請求は拒否されます。',
-                addMerchant: '取引先を追加',
-                merchantContains: '加盟店に次を含む',
-                merchantExactlyMatches: '完全一致する加盟店',
-                noBlockedMerchants: 'ブロックされている加盟店はありません',
-                addMerchantToBlockSpend: '支出をブロックする加盟店を追加',
-                noAllowedMerchants: '許可された加盟店はありません',
-                addMerchantToAllowSpend: '支出を許可する加盟店を追加',
-                matchType: 'マッチタイプ',
-                matchTypeContains: '含む',
-                matchTypeExact: '完全一致',
-                spendCategory: '支出カテゴリ',
-                maxAmount: '最大金額',
-                maxAmountHelp: '加盟店や支出カテゴリの制限にかかわらず、この金額を超えるすべての支払いは拒否されます。',
-                currencyMismatchTitle: '通貨の不一致',
-                currencyMismatchPrompt: '上限金額を設定するには、同じ通貨で清算されるカードを選択してください。',
-                reviewSelectedCards: '選択したカードを確認',
-                summaryMoreCount: ({summary, count}: {summary: string; count: number}) => (count > 0 ? `${summary}、ほか+${count}件` : summary),
-                confirmErrorApplyAtLeastOneSpendRuleToOneCard: '少なくとも1つの支出ルールを1枚のカードに適用してください',
-                confirmErrorCardRequired: 'カードは必須項目です',
-                confirmErrorApplyAtLeastOneSpendRule: '少なくとも 1 つの支出ルールを適用してください',
-                categories: 'カテゴリ',
-                merchants: '加盟店',
-                noAvailableCards: 'すべてのカードにはすでにルールがあります',
-                noAvailableCardsSubtitle: '既存のカードルールを編集して変更します',
-                noCardsIssuedTitle: 'Expensify カードは発行されていません',
-                noCardsIssuedSubtitle: 'Expensify カードを発行して支出ルールを作成しましょう',
-                max: '最大',
-                categoryOptions: {
-                    [CONST.SPEND_RULES.CATEGORIES.AIRLINES]: '航空会社',
-                    [CONST.SPEND_RULES.CATEGORIES.ALCOHOL_AND_BARS]: '酒類とバー',
-                    [CONST.SPEND_RULES.CATEGORIES.AMAZON_AND_BOOKSTORES]: 'Amazon と書店',
-                    [CONST.SPEND_RULES.CATEGORIES.AUTOMOTIVE]: '自動車',
-                    [CONST.SPEND_RULES.CATEGORIES.CAR_RENTALS]: 'レンタカー',
-                    [CONST.SPEND_RULES.CATEGORIES.DINING]: '外食',
-                    [CONST.SPEND_RULES.CATEGORIES.FUEL_AND_GAS]: '燃料・ガス',
-                    [CONST.SPEND_RULES.CATEGORIES.GOVERNMENT_AND_NON_PROFITS]: '政府機関・非営利団体',
-                    [CONST.SPEND_RULES.CATEGORIES.GROCERIES]: '食料品',
-                    [CONST.SPEND_RULES.CATEGORIES.GYMS_AND_FITNESS]: 'ジム・フィットネス',
-                    [CONST.SPEND_RULES.CATEGORIES.HEALTHCARE]: '医療',
-                    [CONST.SPEND_RULES.CATEGORIES.HOTELS]: 'ホテル',
-                    [CONST.SPEND_RULES.CATEGORIES.INTERNET_AND_PHONE]: 'インターネットと電話',
-                    [CONST.SPEND_RULES.CATEGORIES.OFFICE_SUPPLIES]: '事務用品',
-                    [CONST.SPEND_RULES.CATEGORIES.PARKING_AND_TOLLS]: '駐車料金と通行料金',
-                    [CONST.SPEND_RULES.CATEGORIES.PROFESSIONAL_SERVICES]: 'プロフェッショナルサービス',
-                    [CONST.SPEND_RULES.CATEGORIES.RETAIL]: '小売業',
-                    [CONST.SPEND_RULES.CATEGORIES.SHIPPING_AND_DELIVERY]: '配送と配達',
-                    [CONST.SPEND_RULES.CATEGORIES.SOFTWARE]: 'ソフトウェア',
-                    [CONST.SPEND_RULES.CATEGORIES.TRANSIT_AND_RIDESHARE]: '交通機関とライドシェア',
-                    [CONST.SPEND_RULES.CATEGORIES.TRAVEL_AGENCIES]: '旅行代理店',
-                },
-                editRuleTitle: 'ルールを編集',
-                deleteRule: 'ルールを削除',
-                deleteRuleConfirmation: 'このルールを削除してもよろしいですか？',
-                summaryMerchants: ({
-                    merchants,
-                    hiddenCount,
-                    shownCount,
-                    action,
-                }: {
-                    merchants: string;
-                    hiddenCount: number;
-                    shownCount: number;
-                    action: ValueOf<typeof CONST.SPEND_RULES.ACTION>;
-                }) =>
-                    `${action === CONST.SPEND_RULES.ACTION.BLOCK ? 'ブロック済み' : '許可されています'} ${shownCount > 1 ? '加盟店' : '加盟店'}: ${merchants}${hiddenCount > 0 ? `、ほか +${hiddenCount} 件` : ''}`,
-                summaryCategories: ({
-                    categories,
-                    hiddenCount,
-                    shownCount,
-                    action,
-                }: {
-                    categories: string;
-                    hiddenCount: number;
-                    shownCount: number;
-                    action: ValueOf<typeof CONST.SPEND_RULES.ACTION>;
-                }) =>
-                    `${action === CONST.SPEND_RULES.ACTION.BLOCK ? 'ブロック済み' : '許可されています'} ${shownCount > 1 ? 'カテゴリ' : 'カテゴリ'}: ${categories}${hiddenCount > 0 ? `、ほか +${hiddenCount} 件` : ''}`,
-            },
-            aiRules: {
-                title: 'AI ルール',
-                subtitle: '必要なときに実行される柔軟なルールを記述します',
-                addRule: 'AI ルールを追加',
-                findRule: 'AI ルールを検索',
-                addRuleTitle: 'ルールを追加',
-                editRuleTitle: 'ルールを編集',
-                deleteRule: 'ルールを削除',
-                deleteRuleConfirmation: 'このルールを削除してもよろしいですか？',
-                describeRuleTitle: 'ルールの内容を記入してください',
-                describeRuleSubtitle: 'ルールの内容を入力すると、Concierge が自動作成します',
             },
         },
         planTypePage: {
@@ -7307,104 +6421,15 @@ ${reportName}
                     label: 'コントロール',
                     description: '高度な要件を持つ組織向け。',
                 },
-                submit2026: {
-                    label: '提出',
-                    description: '雇用主に経費を提出したい従業員向け。',
-                },
             },
-            description: '自分に合ったプランをお選びください。',
-            subscriptionLink: '詳しく見る',
+            description: '自分に合ったプランをお選びください。機能と料金の詳細な一覧は、こちらのページをご覧ください',
+            subscriptionLink: 'プランの種類と料金のヘルプページ',
             lockedPlanDescription: ({count, annualSubscriptionEndDate}: WorkspaceLockedPlanTypeParams) => ({
                 one: `${annualSubscriptionEndDate} までの年間サブスクリプション期間中、Control プランでアクティブメンバー 1 名を利用することに同意しています。${annualSubscriptionEndDate} 以降、 自動更新を無効にすることで、従量課金サブスクリプションに切り替え、Collect プランへダウングレードできます。`,
                 other: `あなたは、年間サブスクリプションが${annualSubscriptionEndDate}に終了するまで、Controlプランでアクティブメンバー${count}名を契約しています。${annualSubscriptionEndDate}以降は、自動更新を無効にすることで、従量課金制サブスクリプションに切り替え、Collectプランへダウングレードできます。その操作は、`,
             }),
             subscriptions: 'サブスクリプション',
         },
-        hr: {
-            title: '人事',
-            connections: '接続',
-            connectionsSubtitle: '人事システムと連携して従業員データを同期し、精算を自動で正しい担当者に紐づけることで、手作業なしでチームの経費を正確に管理できます。',
-            subtitle: '人事ツールを連携して、従業員の承認を常に同期させます。',
-            connect: '接続',
-            syncNow: '今すぐ同期',
-            disconnect: '切断',
-            disconnectTitle: (providerName: string) => `${providerName}を切断`,
-            disconnectPrompt: (providerName: string) => `${providerName}を切断してもよろしいですか？`,
-            alreadyConnectedTitle: '複数の人事プラットフォームには接続できません',
-            alreadyConnectedPrompt: '別の人事プラットフォームに接続する前に、現在の人事プラットフォームとの接続を解除する必要があります。',
-            lastSync: (relativeDate: string) => `最終同期: ${relativeDate}`,
-            syncError: (providerName: string) => `${providerName}に接続できません`,
-            connectionDescription: (providerName: string) => `${providerName}を接続して、従業員の承認をワークスペースと同期させましょう。`,
-            approvalMode: '承認モード',
-            providerApprovalMode: (providerName: string) => `${providerName} 承認モード`,
-            finalApprover: '最終承認者',
-            providerFinalApprover: (providerName: string) => `${providerName} 最終承認者`,
-            notSet: '未設定',
-            approvalModeDescription: (providerName: string) => `メンバーとマネージャーは ${providerName} と同期するように設定されています。`,
-            approvalModeWarningTitle: '承認モードを変更しますか？',
-            approvalModeWarningPrompt: (providerName: string, helpSiteURL: string) =>
-                `このワークスペースの承認モードを変更してもよろしいですか？${providerName} 対応の各ワークフローモードについては、<a href="${helpSiteURL}">ヘルプサイト</a>で詳しくご覧いただけます。`,
-            approvalModeWarningConfirm: '承認モードを変更',
-            approvalModes: {
-                basic: {label: '基本承認', description: 'すべてのユーザーは、処理と承認のために 1 人の担当者に提出します。'},
-                manager: {
-                    label: 'マネージャー承認',
-                    description: (providerName: string) => `従業員は、${providerName} で設定された直属のマネージャーにレポートを提出します。`,
-                },
-                custom: {label: 'カスタム承認', description: 'Expensify で承認ワークフローを手動で設定します。'},
-            },
-            syncStageName: ({stage}: SyncStageNameConnectionsParams) => {
-                switch (stage) {
-                    case 'gustoSyncTitle':
-                        return 'Gusto 従業員を同期中';
-                    case 'gustoSyncLoadData':
-                        return 'Gusto からデータを読み込んでいます';
-                    case 'gustoSyncProvisioning':
-                        return 'ポリシー内で従業員をプロビジョニングする';
-                    case 'zenefitsSyncTitle':
-                        return 'TriNet 従業員を同期しています';
-                    case 'zenefitsSyncLoadData':
-                        return 'TriNet からデータを読み込んでいます';
-                    case 'zenefitsSyncProvisioning':
-                        return 'ポリシー内で従業員をプロビジョニングする';
-                    case 'jobDone':
-                        return 'インポートしたデータの読み込みを待機しています';
-                    default: {
-                        return `ステージ「${stage}」の翻訳が見つかりません`;
-                    }
-                }
-            },
-            syncResults: {
-                title: (provider: string) => `${provider} の同期が完了しました`,
-                successTitle: (provider: string) => `${provider} との接続が正常に同期されました！`,
-                added: '追加済み',
-                removed: '削除済み',
-                skipped: 'スキップ済み',
-                employeeCount: () => ({
-                    one: '1 従業員',
-                    other: (count: number) => `${count} 従業員`,
-                }),
-            },
-            gusto: {
-                title: 'Gusto',
-            },
-            zenefits: {
-                title: 'TriNet',
-            },
-            syncingModalTitle: '接続を同期しています',
-            syncingModalDescription: '最初の接続には時間がかかる場合があります。エラーが発生した場合は通知されます。',
-            syncing: '従業員を同期しています',
-            mergeHR: {
-                completeSetup: '設定を完了',
-                setupIncomplete: (setupLink: string | undefined) =>
-                    `<muted-text-label>接続されました。従業員をインポートするには ${setupLink ? `<a href="${setupLink}">セットアップを完了</a>` : '設定を完了'} に接続してください。</muted-text-label>`,
-                groups: {title: 'グループ', description: 'このワークスペースと同期したい従業員グループを選択してください'},
-            },
-        },
-        emptyDomain: {
-            title: 'ドメインでセキュリティを強化しましょう',
-            subtitle: 'ドメインのメンバーにシングルサインオンでのログインを必須にし、ワークスペースの作成を制限するなどの管理ができます。',
-        },
     },
     getAssistancePage: {
         title: 'サポートを受ける',
@@ -7432,7 +6457,6 @@ ${reportName}
             symbols: '記号',
             flags: 'フラグ',
         },
-        emojiNotSelected: '絵文字が選択されていません',
     },
     newRoomPage: {
         newRoom: '新しいルーム',
@@ -7445,7 +6469,7 @@ ${reportName}
         public_announceDescription: '誰でもこのルームを見つけられます',
         createRoom: 'ルームを作成',
         roomAlreadyExistsError: 'この名前のルームはすでに存在します',
-        roomNameReservedError: (reservedName: string) => `${reservedName} はすべてのワークスペースで使われるデフォルトのルーム名です。別の名前を選択してください。`,
+        roomNameReservedError: ({reservedName}: RoomNameReservedErrorParams) => `${reservedName} はすべてのワークスペースで使われるデフォルトのルーム名です。別の名前を選択してください。`,
         roomNameInvalidError: 'ルーム名に使用できるのは、小文字のアルファベット、数字、ハイフンのみです',
         pleaseEnterRoomName: 'ルーム名を入力してください',
         pleaseSelectWorkspace: 'ワークスペースを選択してください',
@@ -7453,7 +6477,7 @@ ${reportName}
             const actor = actorName ? `${actorName} ` : '';
             return isExpenseReport ? `${actor}は"${oldName}"から"${newName}"に名前を変更しました` : `${actor}はこのルーム名を「${newName}」（以前は「${oldName}」）に変更しました`;
         },
-        roomRenamedTo: (newName: string) => `ルーム名が${newName}に変更されました`,
+        roomRenamedTo: ({newName}: RoomRenamedToParams) => `ルーム名が${newName}に変更されました`,
         social: 'ソーシャル',
         selectAWorkspace: 'ワークスペースを選択',
         growlMessageOnRenameError: 'ワークスペースルームの名前を変更できません。接続を確認して、もう一度お試しください。',
@@ -7494,14 +6518,14 @@ ${reportName}
         addApprovalRule: (approverEmail: string, approverName: string, field: string, name: string) => `${field}「${name}」の承認者として${approverName}（${approverEmail}）を追加しました`,
         deleteApprovalRule: (approverEmail: string, approverName: string, field: string, name: string) =>
             `${field}「${name}」の承認者として、${approverName}（${approverEmail}）を削除しました`,
-        updateApprovalRule: (field: string, name: string, newApproverEmail: string, newApproverName: string | undefined, oldApproverEmail: string, oldApproverName: string | undefined) => {
+        updateApprovalRule: ({field, name, newApproverEmail, newApproverName, oldApproverEmail, oldApproverName}: UpdatedPolicyApprovalRuleParams) => {
             const formatApprover = (displayName?: string, email?: string) => (displayName ? `${displayName} (${email})` : email);
             return `${field}「${name}」の承認者を${formatApprover(newApproverName, newApproverEmail)}（以前は${formatApprover(oldApproverName, oldApproverEmail)}）に変更しました`;
         },
-        addCategory: (categoryName: string) => `カテゴリ「${categoryName}」を追加しました`,
-        deleteCategory: (categoryName: string) => `カテゴリ「${categoryName}」を削除しました`,
-        updateCategory: (categoryName: string, oldValue: boolean) => `${oldValue ? '無効' : '有効'} カテゴリ「${categoryName}」`,
-        updateCategoryPayrollCode: (categoryName: string, newValue?: string, oldValue?: string) => {
+        addCategory: ({categoryName}: UpdatedPolicyCategoryParams) => `カテゴリ「${categoryName}」を追加しました`,
+        deleteCategory: ({categoryName}: UpdatedPolicyCategoryParams) => `カテゴリ「${categoryName}」を削除しました`,
+        updateCategory: ({oldValue, categoryName}: UpdatedPolicyCategoryParams) => `${oldValue ? '無効' : '有効'} カテゴリ「${categoryName}」`,
+        updateCategoryPayrollCode: ({oldValue, categoryName, newValue}: UpdatedPolicyCategoryGLCodeParams) => {
             if (!oldValue) {
                 return `カテゴリ「${categoryName}」に給与コード「${newValue}」を追加しました`;
             }
@@ -7510,7 +6534,7 @@ ${reportName}
             }
             return `「${categoryName}」カテゴリの給与コードを「${newValue}」に変更しました（以前は「${oldValue}」）`;
         },
-        updateCategoryGLCode: (categoryName: string, newValue?: string, oldValue?: string) => {
+        updateCategoryGLCode: ({oldValue, categoryName, newValue}: UpdatedPolicyCategoryGLCodeParams) => {
             if (!oldValue) {
                 return `カテゴリ「${categoryName}」にGLコード「${newValue}」を追加しました`;
             }
@@ -7519,10 +6543,10 @@ ${reportName}
             }
             return `「${categoryName}」カテゴリのGLコードを「${newValue}」に変更しました（以前は「${oldValue}」）`;
         },
-        updateAreCommentsRequired: (categoryName: string, oldValue: boolean) => {
+        updateAreCommentsRequired: ({oldValue, categoryName}: UpdatedPolicyCategoryParams) => {
             return `「${categoryName}」カテゴリーの説明を${!oldValue ? '必須' : '任意'}に変更しました（以前は${!oldValue ? '任意' : '必須'}）`;
         },
-        updateCategoryMaxExpenseAmount: (categoryName: string, newAmount?: string, oldAmount?: string) => {
+        updateCategoryMaxExpenseAmount: ({categoryName, oldAmount, newAmount}: UpdatedPolicyCategoryMaxExpenseAmountParams) => {
             if (newAmount && !oldAmount) {
                 return `カテゴリ「${categoryName}」に上限額 ${newAmount} を追加しました`;
             }
@@ -7531,26 +6555,26 @@ ${reportName}
             }
             return `「${categoryName}」カテゴリの上限金額を${newAmount}に変更しました（以前は${oldAmount}）`;
         },
-        updateCategoryExpenseLimitType: (categoryName: string, newValue: string, oldValue?: string) => {
+        updateCategoryExpenseLimitType: ({categoryName, oldValue, newValue}: UpdatedPolicyCategoryExpenseLimitTypeParams) => {
             if (!oldValue) {
                 return `カテゴリ「${categoryName}」に上限タイプ ${newValue} を追加しました`;
             }
             return `「${categoryName}」カテゴリーの上限タイプを${newValue}（以前は${oldValue}）に変更しました`;
         },
-        updateCategoryMaxAmountNoReceipt: (categoryName: string, newValue: string, oldValue?: string) => {
+        updateCategoryMaxAmountNoReceipt: ({categoryName, oldValue, newValue}: UpdatedPolicyCategoryMaxAmountNoReceiptParams) => {
             if (!oldValue) {
                 return `領収書を${newValue}に変更して、カテゴリ「${categoryName}」を更新しました`;
             }
             return `「${categoryName}」カテゴリを${newValue}に変更しました（以前は${oldValue}）`;
         },
-        updateCategoryMaxAmountNoItemizedReceipt: (categoryName: string, oldValue: string | undefined, newValue: string) => {
+        updateCategoryMaxAmountNoItemizedReceipt: ({categoryName, oldValue, newValue}: UpdatedPolicyCategoryMaxAmountNoReceiptParams) => {
             if (!oldValue) {
                 return `「${categoryName}」カテゴリーの「明細付きレシート」を${newValue}に変更して更新しました`;
             }
             return `「${categoryName}」カテゴリの明細付きレシートを${newValue}に変更しました（以前は${oldValue}）`;
         },
-        setCategoryName: (oldName: string, newName: string) => `カテゴリ名を「${oldName}」から「${newName}」に変更しました`,
-        updatedDescriptionHint: (categoryName: string, newValue?: string, oldValue?: string) => {
+        setCategoryName: ({oldName, newName}: UpdatedPolicyCategoryNameParams) => `カテゴリ名を「${oldName}」から「${newName}」に変更しました`,
+        updatedDescriptionHint: ({categoryName, oldValue, newValue}: UpdatedPolicyCategoryDescriptionHintTypeParams) => {
             if (!newValue) {
                 return `カテゴリ「${categoryName}」から説明のヒント「${oldValue}」を削除しました`;
             }
@@ -7558,42 +6582,43 @@ ${reportName}
                 ? `カテゴリ「${categoryName}」に説明のヒント「${newValue}」を追加しました`
                 : `「${categoryName}」カテゴリの説明のヒントを「${newValue}」（以前は「${oldValue}」）に変更しました`;
         },
-        updateTagListName: (oldName: string, newName: string) => `タグリスト名を「${newName}」（以前は「${oldName}」）に変更しました`,
-        addTag: (tagListName: string, tagName?: string) => `タグ「${tagName}」をリスト「${tagListName}」に追加しました`,
-        updateTagName: (tagListName: string, newName: string, oldName: string) => `タグリスト「${tagListName}」でタグ「${oldName}」を「${newName}」に変更して更新しました`,
-        updateTagEnabled: (tagListName: string, tagName?: string, enabled?: boolean) => `${enabled ? '有効' : '無効'} リスト「${tagListName}」のタグ「${tagName}」`,
-        deleteTag: (tagListName: string, tagName?: string) => `タグ「${tagName}」をリスト「${tagListName}」から削除しました`,
-        deleteMultipleTags: (count?: string, tagListName?: string) => `リスト「${tagListName}」からタグ「${count}」個を削除しました`,
-        updateTag: (tagListName: string, newValue: string, tagName: string, updatedField: string, oldValue?: string) => {
+        updateTagListName: ({oldName, newName}: UpdatedPolicyCategoryNameParams) => `タグリスト名を「${newName}」（以前は「${oldName}」）に変更しました`,
+        addTag: ({tagListName, tagName}: UpdatedPolicyTagParams) => `タグ「${tagName}」をリスト「${tagListName}」に追加しました`,
+        updateTagName: ({tagListName, newName, oldName}: UpdatedPolicyTagNameParams) => `タグリスト「${tagListName}」でタグ「${oldName}」を「${newName}」に変更して更新しました`,
+        updateTagEnabled: ({tagListName, tagName, enabled}: UpdatedPolicyTagParams) => `${enabled ? '有効' : '無効'} リスト「${tagListName}」のタグ「${tagName}」`,
+        deleteTag: ({tagListName, tagName}: UpdatedPolicyTagParams) => `タグ「${tagName}」をリスト「${tagListName}」から削除しました`,
+        deleteMultipleTags: ({count, tagListName}: UpdatedPolicyTagParams) => `リスト「${tagListName}」からタグ「${count}」個を削除しました`,
+        updateTag: ({tagListName, newValue, tagName, updatedField, oldValue}: UpdatedPolicyTagFieldParams) => {
             if (oldValue) {
                 return `${updatedField} を「${oldValue}」から「${newValue}」に変更して、リスト「${tagListName}」内のタグ「${tagName}」を更新しました`;
             }
             return `${updatedField}「${newValue}」を追加して、リスト「${tagListName}」上のタグ「${tagName}」を更新しました`;
         },
-        updateCustomUnit: (customUnitName: string, newValue: string, oldValue: string, updatedField: string) =>
+        updateCustomUnit: ({customUnitName, newValue, oldValue, updatedField}: UpdatePolicyCustomUnitParams) =>
             `${customUnitName} の${updatedField}を「${newValue}」（以前は「${oldValue}」）に変更しました`,
-        updateCustomUnitTaxEnabled: (newValue: boolean) => `${newValue ? '有効' : '無効'} 距離レートでの税金追跡`,
-        addCustomUnitRate: (customUnitName: string, rateName: string) => `${customUnitName}レート「${rateName}」を追加しました`,
-        updatedCustomUnitRate: (customUnitName: string, customUnitRateName: string, updatedField: string, newValue: string, oldValue: string) =>
+        updateCustomUnitTaxEnabled: ({newValue}: UpdatePolicyCustomUnitTaxEnabledParams) => `${newValue ? '有効' : '無効'} 距離レートでの税金追跡`,
+        addCustomUnitRate: ({customUnitName, rateName}: AddOrDeletePolicyCustomUnitRateParams) => `新しい${customUnitName}レート「${rateName}」を追加しました`,
+        updatedCustomUnitRate: ({customUnitName, customUnitRateName, newValue, oldValue, updatedField}: UpdatedPolicyCustomUnitRateParams) =>
             `${customUnitName} の ${updatedField}「${customUnitRateName}」のレートを「${newValue}」（以前は「${oldValue}」）に変更しました`,
-        updatedCustomUnitTaxRateExternalID: (customUnitRateName: string, newValue: string, newTaxPercentage: string, oldTaxPercentage?: string, oldValue?: string) => {
+        updatedCustomUnitTaxRateExternalID: ({customUnitRateName, newValue, newTaxPercentage, oldTaxPercentage, oldValue}: UpdatedPolicyCustomUnitTaxRateExternalIDParams) => {
             if (oldTaxPercentage && oldValue) {
                 return `距離レート「${customUnitRateName}」の税率を「${oldValue}（${oldTaxPercentage}）」から「${newValue}（${newTaxPercentage}）」に変更しました`;
             }
             return `距離レート「${customUnitRateName}」に税率「${newValue}（${newTaxPercentage}）」を追加しました`;
         },
-        updatedCustomUnitTaxClaimablePercentage: (customUnitRateName: string, newValue: number, oldValue?: number) => {
+        updatedCustomUnitTaxClaimablePercentage: ({customUnitRateName, newValue, oldValue}: UpdatedPolicyCustomUnitTaxClaimablePercentageParams) => {
             if (oldValue) {
                 return `距離レート「${customUnitRateName}」の税還付可能部分を「${newValue}」（以前は「${oldValue}」）に変更しました`;
             }
             return `距離単価「${customUnitRateName}」に対して、税金還付対象額「${newValue}」を追加しました`;
         },
-        updatedCustomUnitRateName: (customUnitName: string, oldValue: string, newValue: string) => `${customUnitName}のレート名を「${oldValue}」から「${newValue}」に変更しました`,
-        updatedCustomUnitRateEnabled: (customUnitName: string, customUnitRateName: string, newValue: boolean) => {
+        updatedCustomUnitRateEnabled: ({customUnitName, customUnitRateName, newValue}: UpdatedPolicyCustomUnitRateEnabledParams) => {
             return `${newValue ? '有効' : '無効'} の ${customUnitName} レート「${customUnitRateName}」`;
         },
-        deleteCustomUnitRate: (customUnitName: string, rateName: string) => `「${customUnitName}」レート「${rateName}」を削除しました`,
-        updateReportFieldDefaultValue: (defaultValue?: string, fieldName?: string) => `レポートフィールド「${fieldName}」のデフォルト値を「${defaultValue}」に設定する`,
+        deleteCustomUnitRate: ({customUnitName, rateName}: AddOrDeletePolicyCustomUnitRateParams) => `「${customUnitName}」レート「${rateName}」を削除しました`,
+        addedReportField: ({fieldType, fieldName}: AddedOrDeletedPolicyReportFieldParams) => `${fieldType}レポートフィールド「${fieldName}」を追加しました`,
+        updateReportFieldDefaultValue: ({defaultValue, fieldName}: UpdatedPolicyReportFieldDefaultValueParams) =>
+            `レポートフィールド「${fieldName}」のデフォルト値を「${defaultValue}」に設定する`,
         addedReportFieldOption: (fieldName: string, optionName: string) => `レポート項目「${fieldName}」にオプション「${optionName}」を追加しました`,
         removedReportFieldOption: (fieldName: string, optionName: string) => `レポートフィールド「${fieldName}」からオプション「${optionName}」を削除しました`,
         updateReportFieldOptionDisabled: (fieldName: string, optionName: string, optionEnabled: boolean) =>
@@ -7605,20 +6630,21 @@ ${reportName}
             return `レポート項目「${fieldName}」のオプション「${optionName}」を${allEnabled ? '有効' : '無効'}にし、すべてのオプションを${allEnabled ? '有効' : '無効'}にしました`;
         },
         deleteReportField: ({fieldType, fieldName}: {fieldType: string; fieldName?: string}) => `${fieldType}レポートフィールド「${fieldName}」を削除しました`,
-        preventSelfApproval: (oldValue: string, newValue: string) =>
+        preventSelfApproval: ({oldValue, newValue}: UpdatedPolicyPreventSelfApprovalParams) =>
             `「自分で承認を防止」を「${newValue === 'true' ? '有効' : '無効'}」（以前は「${oldValue === 'true' ? '有効' : '無効'}」）に更新しました`,
-        updateMonthlyOffset: (oldValue: string, newValue: string) => {
+        updateMonthlyOffset: ({oldValue, newValue}: UpdatedPolicyFieldWithNewAndOldValueParams) => {
             if (!oldValue) {
                 return `月次レポートの提出日を「${newValue}」に設定`;
             }
             return `月次レポートの提出日を「${newValue}」（以前は「${oldValue}」）に更新しました`;
         },
-        updateDefaultBillable: (oldValue: string, newValue: string) => `「クライアントへの経費再請求」を「${newValue}」に更新しました（以前は「${oldValue}」）`,
-        updateDefaultReimbursable: (oldValue: string, newValue: string) => `「現金経費のデフォルト」を「${newValue}」（以前は「${oldValue}」）に更新しました`,
-        updateDefaultTitleEnforced: (value: boolean) => `「デフォルトのレポートタイトルを適用」を有効にしました ${value ? 'オン' : 'オフ'}`,
-        changedCustomReportNameFormula: (oldValue: string, newValue: string) => `カスタムレポート名の数式を「${newValue}」に変更しました（以前は「${oldValue}」）`,
+        updateDefaultBillable: ({oldValue, newValue}: UpdatedPolicyFieldWithNewAndOldValueParams) => `「クライアントへの経費再請求」を「${newValue}」に更新しました（以前は「${oldValue}」）`,
+        updateDefaultReimbursable: ({oldValue, newValue}: UpdatedPolicyFieldWithNewAndOldValueParams) => `「現金経費のデフォルト」を「${newValue}」（以前は「${oldValue}」）に更新しました`,
+        updateDefaultTitleEnforced: ({value}: UpdatedPolicyFieldWithValueParams) => `「デフォルトのレポートタイトルを適用」を有効にしました ${value ? 'オン' : 'オフ'}`,
+        changedCustomReportNameFormula: ({newValue, oldValue}: UpdatedPolicyFieldWithNewAndOldValueParams) =>
+            `カスタムレポート名の数式を「${newValue}」に変更しました（以前は「${oldValue}」）`,
         renamedWorkspaceNameAction: (oldName: string, newName: string) => `このワークスペースの名前を「${newName}」（以前は「${oldName}」）に更新しました`,
-        updateWorkspaceDescription: (newDescription: string, oldDescription: string) =>
+        updateWorkspaceDescription: ({newDescription, oldDescription}: UpdatedPolicyDescriptionParams) =>
             !oldDescription ? `このワークスペースの説明を「${newDescription}」に設定する` : `このワークスペースの説明を「${newDescription}」（以前は「${oldDescription}」）に更新しました`,
         removedFromApprovalWorkflow: ({submittersNames}: RemovedFromApprovalWorkflowParams) => {
             let joinedNames = '';
@@ -7636,21 +6662,21 @@ ${reportName}
         },
         demotedFromWorkspace: (policyName: string, oldRole: string) =>
             `${policyName} でのあなたのロールを ${oldRole} からユーザーに更新しました。あなた自身のものを除き、すべての申請者経費チャットから削除されました。`,
-        updatedWorkspaceCurrencyAction: (oldCurrency: string, newCurrency: string) => `デフォルト通貨を${newCurrency}（以前は${oldCurrency}）に更新しました`,
-        updatedWorkspaceFrequencyAction: (oldFrequency: string, newFrequency: string) => `自動レポート頻度を「${newFrequency}」（以前は「${oldFrequency}」）に更新しました`,
+        updatedWorkspaceCurrencyAction: ({oldCurrency, newCurrency}: UpdatedPolicyCurrencyParams) => `デフォルト通貨を${newCurrency}（以前は${oldCurrency}）に更新しました`,
+        updatedWorkspaceFrequencyAction: ({oldFrequency, newFrequency}: UpdatedPolicyFrequencyParams) => `自動レポート頻度を「${newFrequency}」（以前は「${oldFrequency}」）に更新しました`,
         updateApprovalMode: ({newValue, oldValue}: ChangeFieldParams) => `承認モードを「${newValue}」（以前は「${oldValue}」）に更新しました`,
         upgradedWorkspace: 'このワークスペースを Control プランにアップグレードしました',
         forcedCorporateUpgrade: `このワークスペースは Control プランにアップグレードされました。詳しくは<a href="${CONST.COLLECT_UPGRADE_HELP_URL}">こちら</a>をクリックしてください。`,
         downgradedWorkspace: 'このワークスペースを Collect プランにダウングレードしました',
-        updatedAuditRate: (oldAuditRate: number, newAuditRate: number) =>
+        updatedAuditRate: ({oldAuditRate, newAuditRate}: UpdatedPolicyAuditRateParams) =>
             `手動承認にランダムに回付されるレポートの割合を${Math.round(newAuditRate * 100)}%（以前は${Math.round(oldAuditRate * 100)}%）に変更しました`,
-        updatedManualApprovalThreshold: (oldLimit: string, newLimit: string) => `すべての経費の手動承認上限を${newLimit}に変更しました（以前は${oldLimit}）`,
+        updatedManualApprovalThreshold: ({oldLimit, newLimit}: UpdatedPolicyManualApprovalThresholdParams) => `すべての経費の手動承認上限を${newLimit}に変更しました（以前は${oldLimit}）`,
         updatedFeatureEnabled: ({enabled, featureName}: {enabled: boolean; featureName: string}) => {
             switch (featureName) {
                 case 'categories':
                     return `${enabled ? '有効' : '無効'} 個のカテゴリー`;
                 case 'tags':
-                    return `${enabled ? '有効' : '無効'} 個のタグ`;
+                    return `${enabled ? '有効' : '無効'} 件のタグ`;
                 case 'workflows':
                     return `${enabled ? '有効' : '無効'} 個のワークフロー`;
                 case 'distance rates':
@@ -7658,21 +6684,19 @@ ${reportName}
                 case 'accounting':
                     return `${enabled ? '有効' : '無効'} 会計`;
                 case 'Expensify Cards':
-                    return `${enabled ? '有効' : '無効'} Expensify カード`;
-                case 'travel invoicing':
-                    return `${enabled ? '有効' : '無効'} トラベルインボイス`;
+                    return `${enabled ? '有効' : '無効'} Expensifyカード`;
                 case 'company cards':
-                    return `${enabled ? '有効' : '無効'} 件の会社カード`;
+                    return `${enabled ? '有効' : '無効'} 枚の法人カード`;
                 case 'invoicing':
                     return `${enabled ? '有効' : '無効'} の請求書作成`;
                 case 'per diem':
-                    return `${enabled ? '有効' : '無効'} 日当`;
+                    return `日当 ${enabled ? '有効' : '無効'}`;
                 case 'receipt partners':
-                    return `${enabled ? '有効' : '無効'} 件のレシートパートナー`;
+                    return `${enabled ? '有効' : '無効'} 件の領収書パートナー`;
                 case 'rules':
                     return `${enabled ? '有効' : '無効'} 個のルール`;
                 case 'tax tracking':
-                    return `${enabled ? '有効' : '無効'} の税金の追跡`;
+                    return `${enabled ? '有効' : '無効'} 税金追跡`;
                 default:
                     return `${enabled ? '有効' : '無効'} ${featureName}`;
             }
@@ -7741,15 +6765,12 @@ ${reportName}
             oldValue ? `請求書の会社名を「${newValue}」に変更しました（以前は「${oldValue}」）` : `請求書の会社名を「${newValue}」に設定する`,
         changedInvoiceCompanyWebsite: ({newValue, oldValue}: {newValue: string; oldValue?: string}) =>
             oldValue ? `請求書の会社ウェブサイトを「${newValue}」（以前は「${oldValue}」）に変更しました` : `請求書の会社ウェブサイトを「${newValue}」に設定しました`,
-        changedReimburser: (newReimburser: string, previousReimburser?: string) =>
+        changedReimburser: ({newReimburser, previousReimburser}: UpdatedPolicyReimburserParams) =>
             previousReimburser ? `認可された支払者を「${newReimburser}」（以前は「${previousReimburser}」）に変更しました` : `承認済み支払担当者を「${newReimburser}」に変更しました`,
-        updateReimbursementEnabled: (enabled: boolean) => `${enabled ? '有効' : '無効'}件の精算`,
-        updateCustomTaxName: (oldName: string, newName: string) => `カスタム税区分名を「${newName}」（以前は「${oldName}」）に変更しました`,
-        updateCurrencyDefaultTax: (oldName: string, newName: string) => `ワークスペースの通貨デフォルト税率を「${newName}」（以前は「${oldName}」）に変更しました`,
-        updateForeignCurrencyDefaultTax: (oldName: string, newName: string) => `外貨のデフォルト税率を「${newName}」に変更しました（以前は「${oldName}」）。`,
-        addTax: (taxName: string) => `税「${taxName}」を追加しました`,
-        deleteTax: (taxName: string) => `税金「${taxName}」を削除しました`,
-        updateTax: (oldValue?: string | boolean | number, taxName?: string, updatedField?: string, newValue?: string | boolean | number) => {
+        updateReimbursementEnabled: ({enabled}: UpdatedPolicyReimbursementEnabledParams) => `${enabled ? '有効' : '無効'}件の精算`,
+        addTax: ({taxName}: UpdatedPolicyTaxParams) => `税「${taxName}」を追加しました`,
+        deleteTax: ({taxName}: UpdatedPolicyTaxParams) => `税金「${taxName}」を削除しました`,
+        updateTax: ({oldValue, taxName, updatedField, newValue}: UpdatedPolicyTaxParams) => {
             if (!updatedField) {
                 return '';
             }
@@ -7771,31 +6792,29 @@ ${reportName}
                 }
             }
         },
-        setReceiptRequiredAmount: (newValue: string) => `必要な領収書金額を「${newValue}」に設定`,
-        changedReceiptRequiredAmount: (oldValue: string, newValue: string) => `領収書必須金額を「${newValue}」（以前は「${oldValue}」）に変更しました`,
-        removedReceiptRequiredAmount: (oldValue: string) => `必須領収書金額を削除しました（以前の値：「${oldValue}」）`,
-        setItemizedReceiptRequiredAmount: (newValue: string) => `明細付き領収書の必須金額を「${newValue}」に設定しました`,
-        changedItemizedReceiptRequiredAmount: (oldValue: string, newValue: string) => `品目別レシートの必須金額を「${newValue}」（以前は「${oldValue}」）に変更しました`,
-        removedItemizedReceiptRequiredAmount: (oldValue: string) => `品目別レシートの必須金額を削除しました（以前の値：「${oldValue}」）`,
-        setMaxExpenseAmount: (newValue: string) => `最大経費金額を「${newValue}」に設定`,
-        changedMaxExpenseAmount: (oldValue: string, newValue: string) => `上限経費額を「${newValue}」に変更しました（以前は「${oldValue}」）`,
-        removedMaxExpenseAmount: (oldValue: string) => `最大経費金額を削除しました（以前の値: 「${oldValue}」）`,
-        setMaxExpenseAge: (newValue: string) => `最大経費日数を「${newValue}」日に設定`,
-        changedMaxExpenseAge: (oldValue: string, newValue: string) => `最大経費期限を「${newValue}」日に変更しました（以前は「${oldValue}」日）`,
-        removedMaxExpenseAge: (oldValue: string) => `最大経費日数を削除（以前は「${oldValue}」日）`,
-        updateCategories: (count: number) => `${count} 個のカテゴリーを更新しました`,
-        updateTagList: (tagListName: string) => `リスト「${tagListName}」のタグを更新しました`,
-        updateTagListRequired: (tagListsName: string, isRequired: boolean) => `タグリスト「${tagListsName}」を${isRequired ? '必須' : '必須ではありません'}に変更しました`,
+        setReceiptRequiredAmount: ({newValue}: UpdatedPolicyFieldWithNewAndOldValueParams) => `必要な領収書金額を「${newValue}」に設定`,
+        changedReceiptRequiredAmount: ({oldValue, newValue}: UpdatedPolicyFieldWithNewAndOldValueParams) => `領収書必須金額を「${newValue}」（以前は「${oldValue}」）に変更しました`,
+        removedReceiptRequiredAmount: ({oldValue}: UpdatedPolicyFieldWithNewAndOldValueParams) => `必須領収書金額を削除しました（以前の値：「${oldValue}」）`,
+        setMaxExpenseAmount: ({newValue}: UpdatedPolicyFieldWithNewAndOldValueParams) => `最大経費金額を「${newValue}」に設定`,
+        changedMaxExpenseAmount: ({oldValue, newValue}: UpdatedPolicyFieldWithNewAndOldValueParams) => `上限経費額を「${newValue}」に変更しました（以前は「${oldValue}」）`,
+        removedMaxExpenseAmount: ({oldValue}: UpdatedPolicyFieldWithNewAndOldValueParams) => `最大経費金額を削除しました（以前の値: 「${oldValue}」）`,
+        setMaxExpenseAge: ({newValue}: UpdatedPolicyFieldWithNewAndOldValueParams) => `最大経費日数を「${newValue}」日に設定`,
+        changedMaxExpenseAge: ({oldValue, newValue}: UpdatedPolicyFieldWithNewAndOldValueParams) => `最大経費期限を「${newValue}」日に変更しました（以前は「${oldValue}」日）`,
+        removedMaxExpenseAge: ({oldValue}: UpdatedPolicyFieldWithNewAndOldValueParams) => `最大経費日数を削除（以前は「${oldValue}」日）`,
+        updateCategories: ({count}: UpdatedPolicyCategoriesParams) => `${count} 個のカテゴリーを更新しました`,
+        updateTagList: ({tagListName}: UpdatedPolicyTagListParams) => `リスト「${tagListName}」のタグを更新しました`,
+        updateTagListRequired: ({tagListsName, isRequired}: UpdatedPolicyTagListRequiredParams) =>
+            `タグリスト「${tagListsName}」を${isRequired ? '必須' : '必須ではありません'}に変更しました`,
         importTags: 'スプレッドシートからタグをインポートしました',
         deletedAllTags: 'すべてのタグを削除しました',
-        updateCustomUnitDefaultCategory: (customUnitName: string, newValue?: string, oldValue?: string) =>
+        updateCustomUnitDefaultCategory: ({customUnitName, newValue, oldValue}: UpdatePolicyCustomUnitDefaultCategoryParams) =>
             `${customUnitName}のデフォルトカテゴリを「${newValue}」に変更しました ${oldValue ? `（以前の値 "${oldValue}"）` : ''}`,
-        importCustomUnitRates: (customUnitName: string) => `カスタム単位「${customUnitName}」のレートをインポートしました`,
-        updateCustomUnitSubRate: (customUnitName: string, customUnitRateName: string, customUnitSubRateName: string, oldValue: string, newValue: string, updatedField: string) =>
+        importCustomUnitRates: ({customUnitName}: ImportPolicyCustomUnitRatesParams) => `カスタム単位「${customUnitName}」のレートをインポートしました`,
+        updateCustomUnitSubRate: ({customUnitName, customUnitRateName, customUnitSubRateName, oldValue, newValue, updatedField}: UpdatedPolicyCustomUnitSubRateParams) =>
             `「${customUnitName}」のレート「${customUnitRateName}」、サブレート「${customUnitSubRateName}」の${updatedField}を「${newValue}」（以前は「${oldValue}」）に変更しました`,
-        removedCustomUnitSubRate: (customUnitName: string, customUnitRateName: string, removedSubRateName: string) =>
+        removedCustomUnitSubRate: ({customUnitName, customUnitRateName, removedSubRateName}: RemovedPolicyCustomUnitSubRateParams) =>
             `「${customUnitName}」のレート「${customUnitRateName}」からサブレート「${removedSubRateName}」を削除しました`,
-        addBudget: (frequency: string, entityName: string, entityType: string, shared?: string, individual?: string, notificationThreshold?: number) => {
+        addBudget: ({frequency, entityName, entityType, shared, individual, notificationThreshold}: AddBudgetParams) => {
             const thresholdSuffix = typeof notificationThreshold === 'number' ? `通知しきい値「${notificationThreshold}%」で` : '';
             if (typeof shared !== 'undefined' && typeof individual !== 'undefined') {
                 return `${entityType}「${entityName}」に、個人予算「${individual}」を${frequency}件と、共有予算「${shared}」を${frequency}件${thresholdSuffix}追加しました`;
@@ -7805,18 +6824,18 @@ ${reportName}
             }
             return `${frequency}の共有予算「${shared}」${thresholdSuffix}を${entityType}「${entityName}」に追加しました`;
         },
-        updateBudget: (
-            entityType: string,
-            entityName: string,
-            oldFrequency?: string,
-            newFrequency?: string,
-            oldIndividual?: string,
-            newIndividual?: string,
-            oldShared?: string,
-            newShared?: string,
-            oldNotificationThreshold?: number,
-            newNotificationThreshold?: number,
-        ) => {
+        updateBudget: ({
+            entityType,
+            entityName,
+            oldFrequency,
+            newFrequency,
+            oldIndividual,
+            newIndividual,
+            oldShared,
+            newShared,
+            oldNotificationThreshold,
+            newNotificationThreshold,
+        }: UpdatedBudgetParams) => {
             const frequencyChanged = !!(newFrequency && oldFrequency !== newFrequency);
             const sharedChanged = !!(newShared && oldShared !== newShared);
             const individualChanged = !!(newIndividual && oldIndividual !== newIndividual);
@@ -7851,7 +6870,7 @@ ${reportName}
             }
             return `${entityType}「${entityName}」の予算を更新しました：${changesList.join('; ')}`;
         },
-        deleteBudget: (entityType: string, entityName: string, frequency?: string, individual?: string, shared?: string, notificationThreshold?: number) => {
+        deleteBudget: ({entityType, entityName, frequency, individual, shared, notificationThreshold}: DeleteBudgetParams) => {
             const thresholdSuffix = typeof notificationThreshold === 'number' ? `通知しきい値「${notificationThreshold}%」で` : '';
             if (shared && individual) {
                 return `${entityType}「${entityName}」から、共有予算（${frequency}）「${shared}」と個人予算「${individual}」${thresholdSuffix}を削除しました`;
@@ -7864,123 +6883,48 @@ ${reportName}
             }
             return `${entityType}「${entityName}」から予算を削除しました`;
         },
-        updatedTimeEnabled: (enabled?: boolean) => {
+        updatedTimeEnabled: ({enabled}: UpdatedPolicyTimeEnabledParams) => {
             return `${enabled ? '有効' : '無効'} 時間追跡`;
         },
-        updatedTimeRate: (newRate?: string, oldRate?: string) => {
+        updatedTimeRate: ({newRate, oldRate}: UpdatedPolicyTimeRateParams) => {
             return `時給を「${newRate}」（以前は「${oldRate}」）に変更しました`;
         },
         addedProhibitedExpense: ({prohibitedExpense}: {prohibitedExpense: string}) => `禁止経費に「${prohibitedExpense}」を追加しました`,
         removedProhibitedExpense: ({prohibitedExpense}: {prohibitedExpense: string}) => `禁止経費から「${prohibitedExpense}」を削除しました`,
-        updatedReimbursementChoice: (newReimbursementChoice: string, oldReimbursementChoice: string) =>
+        updatedReimbursementChoice: ({newReimbursementChoice, oldReimbursementChoice}: UpdatedPolicyReimbursementChoiceParams) =>
             `精算方法を「${newReimbursementChoice}」（以前は「${oldReimbursementChoice}」）に変更しました`,
         setAutoJoin: ({enabled}: {enabled: boolean}) => `${enabled ? '有効' : '無効'} ワークスペース参加リクエストの事前承認`,
-        updatedDefaultTitle: (newDefaultTitle: string, oldDefaultTitle: string) => `カスタムレポート名の数式を「${newDefaultTitle}」に変更しました（以前は「${oldDefaultTitle}」）`,
-        updatedOwnership: (oldOwnerEmail: string, oldOwnerName: string, policyName: string) => `${oldOwnerName}（${oldOwnerEmail}）から${policyName}の所有権を引き継ぎました`,
-        updatedAutoHarvesting: (enabled: boolean) => `${enabled ? '有効' : '無効'} の送信を予約しました`,
-        updatedIndividualBudgetNotification: (
-            budgetAmount: string,
-            budgetFrequency: string,
-            budgetName: string,
-            budgetTypeForNotificationMessage: string,
-            thresholdPercentage: number,
-            totalSpend: number,
-            unsubmittedSpend: number,
-            awaitingApprovalSpend: number,
-            approvedReimbursedClosedSpend: number,
-            summaryLink?: string,
-            userEmail?: string,
-        ) =>
+        updatedDefaultTitle: ({newDefaultTitle, oldDefaultTitle}: UpdatedPolicyDefaultTitleParams) =>
+            `カスタムレポート名の数式を「${newDefaultTitle}」に変更しました（以前は「${oldDefaultTitle}」）`,
+        updatedOwnership: ({oldOwnerEmail, oldOwnerName, policyName}: UpdatedPolicyOwnershipParams) => `${oldOwnerName}（${oldOwnerEmail}）から${policyName}の所有権を引き継ぎました`,
+        updatedAutoHarvesting: ({enabled}: UpdatedPolicyAutoHarvestingParams) => `${enabled ? '有効' : '無効'} の送信を予約しました`,
+        updatedIndividualBudgetNotification: ({
+            budgetAmount,
+            budgetFrequency,
+            budgetName,
+            budgetTypeForNotificationMessage,
+            summaryLink,
+            thresholdPercentage,
+            totalSpend,
+            unsubmittedSpend,
+            userEmail,
+            awaitingApprovalSpend,
+            approvedReimbursedClosedSpend,
+        }: UpdatedPolicyBudgetNotificationParams) =>
             `お知らせです！このワークスペースには、${budgetTypeForNotificationMessage}「${budgetName}」に対して、${budgetFrequency}あたり「${budgetAmount}」の予算が設定されています。${userEmail} は現在 ${approvedReimbursedClosedSpend} を利用しており、これは予算の ${thresholdPercentage}% を超えています。さらに承認待ちが ${awaitingApprovalSpend}、未申請が ${unsubmittedSpend} あり、合計で ${totalSpend} になります。${summaryLink ? `<a href="${summaryLink}">こちらがレポートです</a>。これらすべての経費の記録としてご利用ください！` : ''}`,
-        updatedSharedBudgetNotification: (
-            budgetAmount: string,
-            budgetFrequency: string,
-            budgetName: string,
-            budgetTypeForNotificationMessage: string,
-            summaryLink: string | undefined,
-            thresholdPercentage: number,
-            totalSpend: number,
-            unsubmittedSpend: number,
-            awaitingApprovalSpend: number,
-            approvedReimbursedClosedSpend: number,
-        ) =>
+        updatedSharedBudgetNotification: ({
+            budgetAmount,
+            budgetFrequency,
+            budgetName,
+            budgetTypeForNotificationMessage,
+            summaryLink,
+            thresholdPercentage,
+            totalSpend,
+            unsubmittedSpend,
+            awaitingApprovalSpend,
+            approvedReimbursedClosedSpend,
+        }: UpdatedPolicyBudgetNotificationParams) =>
             `お知らせです！このワークスペースには、${budgetTypeForNotificationMessage}「${budgetName}」に対して、${budgetFrequency}の予算額「${budgetAmount}」が設定されています。現在の金額は${approvedReimbursedClosedSpend}で、予算の${thresholdPercentage}%を超えています。さらに承認待ちの金額が${awaitingApprovalSpend}あり、まだ提出されていない金額が${unsubmittedSpend}あるため、合計は${totalSpend}になります。${summaryLink ? `<a href="${summaryLink}">こちらがレポートです</a>。これらすべての経費が記録用にまとめられています！` : ''}`,
-        addedCardFeed: (feedName: string) => `カードフィード「${feedName}」を追加しました`,
-        removedCardFeed: (feedName: string) => `カードフィード「${feedName}」を削除しました`,
-        renamedCardFeed: (newName: string, oldName: string) => `カードフィードの名前を「${newName}」に変更しました（以前は「${oldName}」）`,
-        assignedCompanyCard: (email: string, feedName: string, cardLastFour: string) =>
-            `${email} さんに下4桁が ${cardLastFour} の${feedName ? `「${feedName}」` : ''}会社カードを割り当てました`,
-        unassignedCompanyCard: (email: string, feedName: string, cardLastFour: string) => `${email} の未割り当て${feedName ? `「${feedName}」` : ''}会社カード（下4桁 ${cardLastFour}）`,
-        updatedCardFeedLiability: (feedName: string, enabled: boolean) => `カードフィード「${feedName}」のカード取引を削除できるカード保有者の数：${enabled ? '有効' : '無効'}`,
-        updatedCardFeedStatementPeriod: (feedName: string, newValue?: string, previousValue?: string) =>
-            `カード明細フィード「${feedName}」の利用明細期間の終了日を変更しました${newValue ? ` を「${newValue}」に` : ''}${previousValue ? ` （以前の値：「${previousValue}」）` : ''}`,
-        addedReportField: (fieldType: string, fieldName?: string, defaultValue?: string) =>
-            `${fieldType}レポートフィールド「${fieldName}」を追加しました${defaultValue ? ` デフォルト値「${defaultValue}」付き` : ''}`,
-        updatedMccGroupCategory: ({mccGroupName, oldCategory, newCategory}: {mccGroupName: string; oldCategory: string; newCategory: string}) =>
-            `「${mccGroupName}」のデフォルト支出カテゴリーを「${newCategory}」に変更しました（以前は「${oldCategory}」）`,
-        updatedRequireCompanyCards: ({enabled}: {enabled: boolean}) => `${enabled ? '有効' : '無効'} の法人カード購入要件`,
-        expensifyCardRule: {
-            actionVerb: {block: 'ブロック済み', allow: '許可済み'},
-            amountOperator: {
-                over: '以上',
-                under: '以下のいずれかの意味に応じてお使いください：  \n- 位置・場所：「〜の下」→「under」＝「〜の下」  \n- 条件・範囲：「〜のもとで／〜以下」→「under 18」＝「18歳未満」',
-            },
-            amountFilter: ({operator, amount}: {operator: string; amount: string}) => `金額が ${amount} を${operator}`,
-            theCard: 'カード',
-            multipleCards: ({count}: {count: number}) => ({
-                one: '1 枚のカード',
-                other: `${count} 枚のカード`,
-            }),
-            addRule: ({verb, filters, cards}: {verb: string; filters: string; cards: string}) => {
-                let text = verb;
-                if (filters !== '') {
-                    text += ` ${filters}`;
-                }
-                text += `（${cards}）で`;
-                return text;
-            },
-            removeRule: ({cards}: {cards: string}) => `${cards} から支出ルールを削除しました`,
-            restrictionVerb: {block: 'ブロック', allow: 'のみ許可'},
-            update: {
-                modeChange: ({fromAction, toAction, cards}: {fromAction: string; toAction: string; cards: string}) => `${cards} の利用ルールを ${fromAction} から ${toAction} に変更しました`,
-                appliedToAdditionalCards: ({count}: {count: number}) => ({
-                    one: '追加で 1 枚のカードに支出ルールを適用しました',
-                    other: `追加で ${count} 枚のカードに支出ルールを適用しました`,
-                }),
-                phraseVerb: {added: '追加しました', removed: '削除済み', changed: '変更しました', set: '設定', applied: '適用済み'},
-                bodyMerchant: ({adjective, value}: {adjective: string; value: string}) => (adjective !== '' ? `${adjective}なマーチャント「${value}」` : `加盟店「${value}」`),
-                bodyMerchantChange: ({adjective, oldValue, newValue}: {adjective: string; oldValue: string; newValue: string}) =>
-                    adjective !== '' ? `${oldValue} から ${newValue} へ${adjective}加盟店を変更しました` : `加盟店を「${oldValue}」から「${newValue}」に変更しました`,
-                bodySpendCategory: ({adjective, value}: {adjective: string; value: string}) => (adjective !== '' ? `${adjective}な支出カテゴリ「${value}」` : `支出カテゴリ「${value}」`),
-                bodySpendCategoryChange: ({adjective, oldValue, newValue}: {adjective: string; oldValue: string; newValue: string}) =>
-                    adjective !== '' ? `${adjective}支出カテゴリを「${oldValue}」から「${newValue}」に変更しました` : `支出カテゴリを「${oldValue}」から「${newValue}」に変更しました`,
-                bodyMaxAmount: '最大金額',
-                bodyMaxAmountSet: ({value}: {value: string}) => `最大金額を${value}に設定`,
-                bodyMaxAmountChange: ({oldValue, newValue}: {oldValue: string; newValue: string}) => `最大金額を${oldValue}から${newValue}に変更しました`,
-                bodyAppliedToAdditionalCards: ({count}: {count: number}) => ({
-                    one: '1枚の追加カードに支出ルールを適用します',
-                    other: `${count}枚の追加カードに支出ルールを適用します`,
-                }),
-                bodyRemovedFromCards: ({cards}: {cards: string}) => `${cards} からの支出ルール`,
-                composeOnCards: ({content, cards}: {content: string; cards: string}) => `${cards} 上の ${content}`,
-                composeFromCards: ({content, cards}: {content: string; cards: string}) => `${cards} からの ${content}`,
-            },
-        },
-        addCustomUnitRateWithAmount: (rateName: string, rateValue: string) => `「${rateName}」レート（${rateValue}）を追加しました`,
-        addCustomUnitRateWithAmountAndStartDate: (rateName: string, rateValue: string, startDate: string) => `${startDate}から有効な「${rateName}」レート（${rateValue}）を追加しました`,
-        addCustomUnitRateWithAmountAndEndDate: (rateName: string, rateValue: string, endDate: string) => `「${rateName}」レート（${rateValue}）を${endDate}まで有効として追加しました`,
-        addCustomUnitRateWithAmountAndDates: (rateName: string, rateValue: string, startDate: string, endDate: string) =>
-            `「${rateName}」レート（${rateValue}）を追加しました。有効期間：${startDate}〜${endDate}`,
-        updatedCustomUnitRateStartDate: (rateName: string, newDate: string, oldDate?: string) =>
-            oldDate ? `「${rateName}」レートの開始日を${newDate}に更新しました（以前は${oldDate}）` : `「${rateName}」レートの開始日を${newDate}に設定する`,
-        updatedCustomUnitRateEndDate: (rateName: string, newDate: string, oldDate?: string) =>
-            oldDate ? `「${rateName}」レートの終了日を${newDate}（以前は${oldDate}）に更新しました` : `「${rateName}」レートの終了日を${newDate}に設定します`,
-        updatedCustomUnitRateStartAndEndDate: (rateName: string, newStartDate: string, newEndDate: string, oldStartDate?: string, oldEndDate?: string) =>
-            oldStartDate && oldEndDate
-                ? `「${rateName}」レートの開始日と終了日を${newStartDate}〜${newEndDate}に更新しました（以前は${oldStartDate}〜${oldEndDate}）`
-                : `「${rateName}」レートの開始日と終了日を${newStartDate}〜${newEndDate}に設定しました`,
-        removedCustomUnitRateStartDate: (rateName: string, oldDate: string) => `「${rateName}」レートの開始日を削除しました（以前の開始日：${oldDate}）`,
-        removedCustomUnitRateEndDate: (rateName: string, oldDate: string) => `「${rateName}」レートの終了日を削除しました（以前は ${oldDate}）`,
     },
     roomMembersPage: {
         memberNotFound: 'メンバーが見つかりません。',
@@ -8012,7 +6956,7 @@ ${reportName}
         completed: '完了',
         action: '完了',
         messages: {
-            created: (title: string) => `${title} のタスク`,
+            created: ({title}: TaskCreatedActionParams) => `${title} のタスク`,
             completed: '完了としてマークしました',
             canceled: '削除されたタスク',
             reopened: '未完了としてマーク済み',
@@ -8026,7 +6970,7 @@ ${reportName}
         deleteConfirmation: 'このタスクを削除してもよろしいですか？',
     },
     statementPage: {
-        title: (year: number | string, monthName: string) => `${year}年${monthName}の明細書`,
+        title: ({year, monthName}: StatementTitleParams) => `${year}年${monthName}の明細書`,
     },
     keyboardShortcutsPage: {
         title: 'キーボードショートカット',
@@ -8039,8 +6983,6 @@ ${reportName}
             newChat: '新しいチャット画面',
             copy: 'コメントをコピー',
             openDebug: 'テスト設定ダイアログを開く',
-            expenseReportSearch: '経費レポートを検索',
-            goToWorkspace: '現在のレポートのワークスペースに移動',
         },
     },
     guides: {
@@ -8050,8 +6992,6 @@ ${reportName}
     search: {
         resultsAreLimited: '検索結果は制限されています。',
         viewResults: '結果を表示',
-        applyFilters: 'フィルターを適用する',
-        appliedFilters: '適用されたフィルター',
         resetFilters: 'フィルターをリセット',
         searchResults: {
             emptyResults: {
@@ -8059,23 +6999,27 @@ ${reportName}
                 subtitle: `検索条件を調整するか、＋ボタンを使って作成してみてください。`,
             },
             emptyExpenseResults: {
-                title: '経費はまだありません',
+                title: 'まだ経費を作成していません',
                 subtitle: '経費を作成するか、Expensify をお試し利用して詳細を確認しましょう。',
                 subtitleWithOnlyCreateButton: '下の緑色のボタンを使って経費を作成してください。',
             },
             emptyReportResults: {
-                title: 'レポートはまだありません',
+                title: 'まだレポートを作成していません',
                 subtitle: 'レポートを作成するか、Expensify を試用して詳細を確認しましょう。',
                 subtitleWithOnlyCreateButton: '下の緑色のボタンを使ってレポートを作成してください。',
             },
             emptyInvoiceResults: {
-                title: '請求書はまだありません',
+                title: dedent(`
+                    まだ請求書を作成していません
+                `),
                 subtitle: '請求書を送信するか、Expensify を試用してさらに詳しく知りましょう。',
                 subtitleWithOnlyCreateButton: '下の緑色のボタンを使って請求書を送信してください。',
-                subtitleCannotSend: '請求書を送信するには、Invoicesが有効なワークスペースが必要です。',
-                subtitleCannotSendWithTestDrive: '請求書を送信するには、Invoicesが有効なワークスペースが必要です。Expensify を試用してさらに詳しく知りましょう。',
             },
-            emptyTripResults: {title: 'まだ出張はありません', subtitle: 'まずは、下から最初の出張を予約しましょう。', buttonText: '出張を予約'},
+            emptyTripResults: {
+                title: '表示する出張はありません',
+                subtitle: 'まずは、下から最初の出張を予約しましょう。',
+                buttonText: '出張を予約',
+            },
             emptySubmitResults: {
                 title: '提出できる経費はありません',
                 subtitle: 'すべて完了しました。勝利の一周をしてきましょう！',
@@ -8103,31 +7047,30 @@ ${reportName}
             },
         },
         columns: '列',
-        editColumns: '列の編集',
         resetColumns: '列をリセット',
         groupColumns: '列をグループ化',
         expenseColumns: '経費列',
-        saveView: 'ビューを保存',
+        statements: 'ステートメント',
+        unapprovedCash: '未承認の現金',
+        unapprovedCard: '未承認のカード',
+        reconciliation: '照合',
+        topSpenders: '上位支出者',
+        saveSearch: '検索を保存',
         deleteSavedSearch: '保存した検索を削除',
         deleteSavedSearchConfirm: 'この検索を削除してもよろしいですか？',
         searchName: '名前を検索',
         savedSearchesMenuItemTitle: '保存済み',
-        urlCopied: 'URLをコピーしました',
+        topCategories: 'トップカテゴリ',
+        topMerchants: '上位加盟店',
         groupedExpenses: 'グループ化された経費',
         bulkActions: {
-            editMultiple: '複数を編集',
-            editMultipleTitle: '複数の経費を編集',
-            editMultipleDescription: '変更は選択されたすべての経費に適用され、以前に設定された値は上書きされます。',
             approve: '承認',
             pay: '支払う',
             delete: '削除',
             hold: '保留',
             unhold: '保留を解除',
             reject: '却下',
-            duplicateExpense: ({count}: {count: number}) => `${count === 1 ? '経費を複製' : '経費を一括複製'}`,
             noOptionsAvailable: '選択した経費グループには利用できるオプションがありません。',
-            undelete: '削除を取り消す',
-            duplicateReport: ({count}: {count: number}) => `${count === 1 ? 'レポート' : 'レポート'} を複製`,
         },
         filtersHeader: 'フィルター',
         filters: {
@@ -8135,14 +7078,11 @@ ${reportName}
                 before: (date?: string) => `${date ?? ''} より前`,
                 after: (date?: string) => `${date ?? ''} の後`,
                 on: (date?: string) => `${date ?? ''} に発生`,
-                customDate: 'カスタム日付',
-                customRange: 'カスタム範囲',
                 presets: {
                     [CONST.SEARCH.DATE_PRESETS.NEVER]: '決してない',
                     [CONST.SEARCH.DATE_PRESETS.LAST_MONTH]: '先月',
                     [CONST.SEARCH.DATE_PRESETS.THIS_MONTH]: '今月',
                     [CONST.SEARCH.DATE_PRESETS.YEAR_TO_DATE]: '年初来（累計）',
-                    [CONST.SEARCH.DATE_PRESETS.LAST_12_MONTHS]: '過去12か月',
                     [CONST.SEARCH.DATE_PRESETS.LAST_STATEMENT]: '最新明細書',
                 },
             },
@@ -8154,15 +7094,10 @@ ${reportName}
             currency: '通貨',
             completed: '完了',
             amount: {
-                lessThan: (amount?: string) => `${amount ?? ''} 未満`,
-                greaterThan: (amount?: string) => `${amount ?? ''}より大きい`,
-                between: (greaterThan?: string, lessThan?: string) => {
-                    if (greaterThan && lessThan) {
-                        return `${greaterThan} 以上 ${lessThan} 未満`;
-                    }
-                    return '間';
-                },
-                equalTo: (amount?: string) => `${amount ?? ''} に等しい`,
+                lessThan: ({amount}: OptionalParam<RequestAmountParams> = {}) => `${amount ?? ''} 未満`,
+                greaterThan: ({amount}: OptionalParam<RequestAmountParams> = {}) => `${amount ?? ''}より大きい`,
+                between: (greaterThan: string, lessThan: string) => `${greaterThan} 以上 ${lessThan} 未満`,
+                equalTo: ({amount}: OptionalParam<RequestAmountParams> = {}) => `${amount ?? ''} に等しい`,
             },
             card: {
                 expensify: 'Expensify',
@@ -8172,9 +7107,8 @@ ${reportName}
                 cardFeedName: ({cardFeedBankName, cardFeedLabel}: {cardFeedBankName: string; cardFeedLabel?: string}) =>
                     `すべての${cardFeedBankName}${cardFeedLabel ? ` - ${cardFeedLabel}` : ''}`,
                 cardFeedNameCSV: ({cardFeedLabel}: {cardFeedLabel?: string}) => `すべてのCSVインポート済みカード${cardFeedLabel ? ` - ${cardFeedLabel}` : ''}`,
-                travelInvoicing: '出張請求書作成',
             },
-            reportField: (name: string, value: string) => `${name} は ${value} です`,
+            reportField: ({name, value}: OptionalParam<ReportFieldParams>) => `${name} は ${value} です`,
             current: '現在',
             past: '過去',
             submitted: '送信済み',
@@ -8186,10 +7120,6 @@ ${reportName}
             billable: '請求可能',
             reimbursable: '払い戻し対象',
             purchaseCurrency: '購入通貨',
-            sortOrder: {
-                [CONST.SEARCH.SORT_ORDER.ASC]: '昇順',
-                [CONST.SEARCH.SORT_ORDER.DESC]: '降順',
-            },
             groupBy: {
                 [CONST.SEARCH.GROUP_BY.FROM]: '差出人',
                 [CONST.SEARCH.GROUP_BY.CARD]: 'カード',
@@ -8205,8 +7135,7 @@ ${reportName}
             feed: 'フィード',
             withdrawalType: {
                 [CONST.SEARCH.WITHDRAWAL_TYPE.EXPENSIFY_CARD]: 'Expensify カード',
-                [CONST.SEARCH.WITHDRAWAL_TYPE.REIMBURSEMENT]: '精算',
-                [CONST.SEARCH.WITHDRAWAL_TYPE.CENTRAL_TRAVEL_INVOICING]: '出張請求書作成',
+                [CONST.SEARCH.WITHDRAWAL_TYPE.REIMBURSEMENT]: '払い戻し',
             },
             is: 'は',
             action: {
@@ -8216,15 +7145,14 @@ ${reportName}
                 [CONST.SEARCH.ACTION_FILTERS.EXPORT]: 'エクスポート',
             },
         },
-        display: {
+        has: '持っている',
+        groupBy: 'グループ化基準',
+        view: {
             label: '表示',
-            sortBy: '並べ替え',
-            sortOrder: '並べ替え順',
-            groupBy: 'グループ化基準',
-            limitResults: '結果の絞り込み',
+            table: 'テーブル',
+            bar: 'バー',
+            line: '折れ線',
         },
-        has: '持っている',
-        view: {label: '表示', table: 'テーブル', bar: 'バー', line: '折れ線', pie: '円グラフ'},
         chartTitles: {
             [CONST.SEARCH.GROUP_BY.FROM]: '差出人',
             [CONST.SEARCH.GROUP_BY.CARD]: 'カード',
@@ -8248,49 +7176,17 @@ ${reportName}
         withdrawalType: '出金の種類',
         recentSearches: '最近の検索',
         recentChats: '最近のチャット',
-        serverResults: '検索結果',
         searchIn: '検索対象',
-        askConcierge: (message: string) => `Concierge に「${message}」と聞く`,
-        searchPlaceholder: '何かを検索...',
+        searchPlaceholder: '何かを検索',
         suggestions: '提案',
-        suggestionsAvailable: (
-            {
-                count,
-            }: {
-                count: number;
-            },
-            query = '',
-        ) => ({
-            one: `候補があります${query ? `: ${query}` : ''}。${count}件の結果。`,
-            other: (resultCount: number) => `候補があります${query ? `: ${query}` : ''}。${resultCount}件の結果。`,
-        }),
         exportSearchResults: {
             title: 'エクスポートを作成',
             description: 'おっと、アイテムがたくさんありますね！まとめて整理して、間もなくConciergeからファイルをお送りします。',
         },
         exportedTo: 'エクスポート先',
-        exportAll: {selectAllMatchingItems: '一致する項目をすべて選択', allMatchingItemsSelected: '一致する項目をすべて選択済み', selectAllOnThisPage: 'このページのすべてを選択'},
-        errors: {
-            pleaseSelectDatesForBothFromAndTo: '開始日と終了日の両方を選択してください',
-        },
-        spendOverTime: '時間経過による支出',
-        tabs: {
-            expenseReports: '経費精算書',
-            reports: 'レポート',
-            expenses: '経費',
-            submit: '下書き',
-            approve: '承認が必要',
-            pay: '支払いの準備完了',
-            accounting: '会計',
-            export: 'エクスポート待ち',
-            unapprovedCash: '現金発生主義',
-            unapprovedCard: 'カード発生額',
-            statements: 'カード明細',
-            reconciliation: '銀行照合',
-            insights: 'インサイト',
-            topSpenders: '上位の支出者',
-            topCategories: '上位カテゴリ',
-            topMerchants: '上位加盟店',
+        exportAll: {
+            selectAllMatchingItems: '一致する項目をすべて選択',
+            allMatchingItemsSelected: '一致する項目をすべて選択済み',
         },
     },
     genericErrorPage: {
@@ -8346,6 +7242,7 @@ ${reportName}
             chooseWorkspace: 'このレポート用のワークスペースを選択してください。',
             emptyReportConfirmationTitle: 'すでに空のレポートがあります',
             emptyReportConfirmationPrompt: ({workspaceName}: {workspaceName: string}) => `${workspaceName} で別のレポートを作成してもよろしいですか？空のレポートには次からアクセスできます`,
+            emptyReportConfirmationPromptLink: 'レポート',
             emptyReportConfirmationDontShowAgain: '今後このメッセージを表示しない',
             genericWorkspaceName: 'このワークスペース',
         },
@@ -8383,7 +7280,6 @@ ${reportName}
                     reimburseableLink: '立替経費',
                     nonReimbursableLink: '会社カード経費',
                     pending: (label: string) => `このレポートの${label}へのエクスポートを開始しました…`,
-                    travelCardLink: 'トラベルカード経費',
                 },
                 integrationsMessage: (errorMessage: string, label: string, linkText?: string, linkURL?: string) =>
                     `このレポートを${label}にエクスポートできませんでした（"${errorMessage}${linkText ? `<a href="${linkURL}">${linkText}</a>` : ''}"）`,
@@ -8392,8 +7288,7 @@ ${reportName}
                 markedReimbursed: (amount: string, currency: string) => `他の場所で${currency}${amount}を支払いました`,
                 markedReimbursedFromIntegration: ({amount, currency}: MarkReimbursedFromIntegrationParams) => `連携経由で${currency}${amount}を支払いました`,
                 outdatedBankAccount: `支払元の銀行口座に問題があるため、支払いを処理できませんでした`,
-                reimbursementACHBounceDefault: `ルーティング番号または口座番号の誤り、もしくは口座が閉鎖されているため、支払いを処理できませんでした`,
-                reimbursementACHBounceWithReason: ({returnReason}: {returnReason: string}) => `支払いを処理できませんでした：${returnReason}`,
+                reimbursementACHBounce: `銀行口座の問題により支払いを処理できませんでした`,
                 reimbursementACHCancelled: `支払いをキャンセルしました`,
                 reimbursementAccountChanged: `支払元が銀行口座を変更したため、支払いを処理できませんでした`,
                 reimbursementDelayed: `支払いは処理されましたが、あと1～2営業日遅れています`,
@@ -8401,22 +7296,17 @@ ${reportName}
                 selectedForRandomAuditMarkdown: `審査のために[randomly selected](https://help.expensify.com/articles/expensify-classic/reports/Set-a-random-report-audit-schedule)`,
                 share: ({to}: ShareParams) => `メンバーを${to}に招待しました`,
                 unshare: ({to}: UnshareParams) => `メンバー ${to} を削除しました`,
-                stripePaid: (amount: string, currency: string) => `支払い済み ${currency}${amount}`,
+                stripePaid: ({amount, currency}: StripePaidParams) => `支払い済み ${currency}${amount}`,
                 takeControl: `管理権限を取得しました`,
                 integrationSyncFailed: (label: string, errorMessage: string, workspaceAccountingLink?: string) =>
                     `${label}${errorMessage ? ` ("${errorMessage}")` : ''}との同期中に問題が発生しました。<a href="${workspaceAccountingLink}">ワークスペース設定</a>で問題を解決してください。`,
-                integrationSyncFailedRecurrence: ({count}: {count: number}) => `（${count} 回繰り返し）`,
                 companyCardConnectionBroken: ({feedName, workspaceCompanyCardRoute}: {feedName: string; workspaceCompanyCardRoute: string}) =>
                     `${feedName} との接続が切断されています。カードの取引明細の取込を再開するには、<a href='${workspaceCompanyCardRoute}'>銀行にログイン</a>してください。`,
                 plaidBalanceFailure: ({maskedAccountNumber, walletRoute}: {maskedAccountNumber: string; walletRoute: string}) =>
-                    `Plaid によるビジネス銀行口座との接続が切断されています。Expensify カードを引き続きご利用いただくために、<a href='${walletRoute}'>銀行口座 ${maskedAccountNumber} を再接続</a>してください。`,
-                addEmployee: (email: string, role: string, didJoinPolicy?: boolean) => {
-                    const translatedRole = String(translations.workspace.common.roleName(role)).toLowerCase();
-                    const article = role === CONST.POLICY.ROLE.AUDITOR ? '一つの' : 'a';
-                    return didJoinPolicy ? `${email} さんがワークスペースの招待リンクから参加しました` : `${email} を${article}${translatedRole}として追加しました`;
-                },
+                    `ビジネス用銀行口座へのPlaid接続が切断されました。Expensifyカードを引き続きご利用いただくために、<a href='${walletRoute}'>銀行口座 ${maskedAccountNumber} を再接続</a>してください。`,
+                addEmployee: (email: string, role: string) => `${email} を ${role === 'member' ? 'a' : 'ある'} ${role} として追加しました`,
                 updateRole: ({email, currentRole, newRole}: UpdateRoleParams) => `${email} のロールを ${currentRole} から ${newRole} に更新しました`,
-                updatedCustomField1: (email: string, newValue: string, previousValue: string) => {
+                updatedCustomField1: ({email, previousValue, newValue}: UpdatedCustomFieldParams) => {
                     if (!newValue) {
                         return `${email} のカスタムフィールド1を削除しました（以前の値：「${previousValue}」）`;
                     }
@@ -8424,7 +7314,7 @@ ${reportName}
                         ? `${email} のカスタムフィールド1に「${newValue}」を追加しました`
                         : `${email} のカスタムフィールド1を「${newValue}」（以前は「${previousValue}」）に変更しました`;
                 },
-                updatedCustomField2: (email: string, newValue: string, previousValue: string) => {
+                updatedCustomField2: ({email, previousValue, newValue}: UpdatedCustomFieldParams) => {
                     if (!newValue) {
                         return `${email} のカスタムフィールド2を削除しました（以前の値：「${previousValue}」）`;
                     }
@@ -8438,12 +7328,8 @@ ${reportName}
                 addedConnection: ({connectionName}: ConnectionNameParams) => `${CONST.POLICY.CONNECTIONS.NAME_USER_FRIENDLY[connectionName]} に接続済み`,
                 leftTheChat: 'チャットを退出しました',
                 settlementAccountLocked: ({maskedBankAccountNumber}: OriginalMessageSettlementAccountLocked, linkURL: string) =>
-                    `ビジネス銀行口座 ${maskedBankAccountNumber} は、払い戻しまたは Expensify カードの精算に問題が発生したため自動的にロックされました。問題を解決するには、<a href="${linkURL}">ワークスペース設定</a>で修正してください。`,
+                    `Reimbursement または Expensify Card の清算に問題が発生したため、ビジネス銀行口座 ${maskedBankAccountNumber} は自動的にロックされました。問題を解決するには、<a href="${linkURL}">ワークスペース設定</a>で修正してください。`,
                 leftTheChatWithName: (nameOrEmail: string) => `${nameOrEmail ? `${nameOrEmail}: ` : ''}がチャットから退出しました`,
-                actionableCard3DSTransactionApproval: (amount: string, merchant: string | undefined) => {
-                    const amountAndMerchantText = [amount, merchant].filter((s) => !!s?.length).join(' ');
-                    return `Expensify モバイルアプリを開いて、${amountAndMerchantText && `${amountAndMerchantText} `}の取引を確認してください`;
-                },
             },
             error: {
                 invalidCredentials: '認証情報が無効です。接続の設定を確認してください。',
@@ -8453,23 +7339,6 @@ ${reportName}
     chronos: {
         oooEventSummaryFullDay: (summary: string, dayCount: number, date: string) => `${summary}（${date} までの ${dayCount} ${dayCount === 1 ? '日' : '日数'} 分）`,
         oooEventSummaryPartialDay: (summary: string, timePeriod: string, date: string) => `${date}の${timePeriod}の${summary}`,
-        startTimer: 'タイマー開始',
-        stopTimer: (duration: string) => `タイマーを停止 (${duration})`,
-        scheduleOOO: '不在予定を設定',
-        scheduleOOOTitle: '不在予定を設定',
-        date: '日付',
-        time: '時間（24時間表記）',
-        durationAmount: '期間',
-        durationUnit: '単位',
-        reason: '理由',
-        workingPercentage: '稼働率',
-        dateRequired: '日付は必須です。',
-        invalidTimeFormat: '有効な24時間表記の時刻を入力してください（例: 14:30）。',
-        enterANumber: '数字を入力してください。',
-        hour: '時間',
-        day: '日数',
-        week: '週間',
-        month: 'か月',
     },
     footer: {
         features: '機能',
@@ -8512,24 +7381,8 @@ ${reportName}
         workspaceName: 'ワークスペース名',
         chatUserDisplayNames: 'チャットメンバー表示名',
         scrollToNewestMessages: '最新のメッセージまでスクロール',
-        scrollToActionBadgeTarget: '注意が必要なアクションまでスクロール',
         preStyledText: '事前にスタイル設定されたテキスト',
         viewAttachment: '添付ファイルを表示',
-        contextMenuAvailable: 'コンテキストメニューが利用可能です。Shift+F10 を押して開きます。',
-        contextMenuAvailableMacOS: 'コンテキストメニューが利用可能です。VO-Shift-M を押して開きます。',
-        contextMenuAvailableNative: 'コンテキストメニューが利用可能です。ダブルタップして長押しで開きます。',
-        selectAllFeatures: 'すべての機能を選択',
-        selectAllTransactions: 'すべての取引を選択',
-        selectAllItems: 'すべての項目を選択',
-        openActionsMenu: 'アクションメニューを開く',
-        selectAllCategories: 'すべてのカテゴリを選択',
-        selectAllDistanceRates: 'すべての距離レートを選択',
-        selectAllTags: 'すべてのタグを選択',
-        selectAllTaxes: 'すべての税を選択',
-        selectAllPerDiemRates: 'すべての日当レートを選択',
-        selectAllMembers: 'すべてのメンバーを選択',
-        selectAllValues: 'すべての値を選択',
-        selectAllRules: 'すべてのルールを選択',
     },
     parentReportAction: {
         deletedReport: '削除されたレポート',
@@ -8548,7 +7401,6 @@ ${reportName}
         parentNavigationSummary: ({reportName, workspaceName}: ParentNavigationSummaryParams) => `${reportName}${workspaceName ? `${workspaceName} の中` : ''} から`,
     },
     qrCodes: {
-        qrCode: 'QRコード',
         copy: 'URLをコピー',
         copied: 'コピーしました！',
     },
@@ -8595,11 +7447,6 @@ ${reportName}
             'Expensify.org に参加して、世界中の不公正の解消に取り組みましょう。現在実施中の「Teachers Unite」キャンペーンでは、必需の学用品の費用を分担することで、すべての教育者を支援しています。',
         iKnowATeacher: '私は先生を知っています',
         iAmATeacher: '私は教師です',
-        personalKarma: {
-            title: 'パーソナルカルマを有効にする',
-            description: '毎月の支出500ドルごとに1ドルを Expensify.org に寄付します',
-            stopDonationsPrompt: 'Expensify.org への寄付をやめてもよろしいですか？',
-        },
         getInTouch: '素晴らしいです！その方の情報を共有していただければ、こちらからご連絡いたします。',
         introSchoolPrincipal: '学校校長への紹介',
         schoolPrincipalVerifyExpense: 'Expensify.org は、低所得世帯の生徒がより良い学習体験を得られるよう、必要な学用品の費用を分担します。あなたの経費は、校長により確認されます。',
@@ -8621,11 +7468,6 @@ ${reportName}
         notActivated: '未有効化',
         outOfPocket: '返金可能',
         companySpend: '返金不可',
-        personalCard: '個人のカード',
-        companyCard: '会社カード',
-        expensifyCard: 'Expensify カード',
-        travelInvoicing: '出張請求書作成',
-        travelCard: 'トラベルカード',
     },
     distance: {
         addStop: '経由地を追加',
@@ -8649,18 +7491,14 @@ ${reportName}
             endReading: '読み終える',
             saveForLater: '後で保存',
             totalDistance: '合計距離',
+            startTitle: '走行距離計の開始写真',
+            endTitle: '走行距離計終了時の写真',
             startMessageWeb: '旅行の<strong>開始時</strong>のオドメーターの写真を追加してください。ここにファイルをドラッグするか、またはアップロードするファイルを選択してください。',
             endMessageWeb: '旅行の<strong>終了時</strong>の走行距離計の写真を追加してください。ここにファイルをドラッグするか、アップロードするファイルを選択してください。',
-            startTitle: '走行距離計の開始時の写真',
-            endTitle: '走行距離計（終了時）の写真',
-            deleteOdometerPhoto: '走行距離計の写真を削除',
-            deleteOdometerPhotoConfirmation: 'この走行距離計の写真を削除してもよろしいですか？',
-            cameraAccessRequired: '写真を撮影するにはカメラへのアクセス権限が必要です。',
-            snapPhotoStart: '<muted-text-label>移動を<strong>開始</strong>するときに、走行距離計の写真を撮影してください。</muted-text-label>',
-            snapPhotoEnd: '<muted-text-label>走行の<strong>終了時</strong>に、オドメーターの写真を撮影してください。</muted-text-label>',
         },
     },
     gps: {
+        disclaimer: 'GPSを使用して移動履歴から経費を作成しましょう。追跡を開始するには、下の「開始」をタップしてください。',
         error: {
             failedToStart: '位置情報の追跡を開始できませんでした。',
             failedToGetPermissions: '必要な位置情報の権限を取得できませんでした。',
@@ -8669,9 +7507,13 @@ ${reportName}
         stopped: '停止済み',
         start: '開始',
         stop: '停止',
-        save: '保存',
-        resume: '再開',
         discard: '破棄',
+        stopGpsTrackingModal: {
+            title: 'GPS追跡を停止',
+            prompt: '本当に終了してもよろしいですか？現在の進行状況が失われます。',
+            cancel: '追跡を再開',
+            confirm: 'GPS追跡を停止',
+        },
         discardDistanceTrackingModal: {
             title: '移動距離の追跡を破棄',
             prompt: '本当によろしいですか？現在の操作は破棄され、元に戻すことはできません。',
@@ -8719,14 +7561,12 @@ ${reportName}
             prompt: 'GPS追跡を停止して、Expensify Classic に切り替えてもよろしいですか？',
             confirm: '停止して切り替える',
         },
-        switchAccountWarningTripInProgress: {title: 'GPS トラッキングを実行中です', prompt: 'GPS 追跡を停止してアカウントを切り替えてもよろしいですか？', confirm: '停止して切り替える'},
         locationServicesRequiredModal: {
             title: '位置情報へのアクセスが必要です',
             confirm: '設定を開く',
             prompt: 'GPSで距離の追跡を開始するには、端末の設定で位置情報へのアクセスを許可してください。',
         },
-        gpsFloatingPillText: 'GPS 追跡を実行中です…',
-        liveActivity: {subtitle: '距離の記録', button: '進捗を表示', lockScreenBadgeText: '距離', lockScreenTrackingText: '追跡中…'},
+        fabGpsTripExplained: 'GPS画面へ移動（フローティングアクション）',
     },
     reportCardLostOrDamaged: {
         screenTitle: '成績表の紛失または破損',
@@ -8753,13 +7593,11 @@ ${reportName}
         [CONST.REFERRAL_PROGRAM.CONTENT_TYPES.START_CHAT]: {
             buttonText: 'チャットを開始して、<success><strong>友達を紹介しましょう</strong></success>。',
             header: 'チャットを開始、友達を紹介',
-            closeAccessibilityLabel: '閉じる、チャットを開始、友達を紹介、バナー',
             body: '友だちにもExpensifyを使ってほしいですか？チャットを開始するだけで、あとはお任せください。',
         },
         [CONST.REFERRAL_PROGRAM.CONTENT_TYPES.SUBMIT_EXPENSE]: {
             buttonText: '経費を申請し、<success><strong>チームを紹介しましょう</strong></success>。',
             header: '経費を提出し、チームを紹介する',
-            closeAccessibilityLabel: '閉じる、経費を提出、チームを紹介、バナー',
             body: 'あなたのチームにもExpensifyを使ってほしいですか？チームに経費精算を1件提出するだけで、あとは私たちにお任せください。',
         },
         [CONST.REFERRAL_PROGRAM.CONTENT_TYPES.REFER_FRIEND]: {
@@ -8775,27 +7613,26 @@ ${reportName}
     },
     systemChatFooterMessage: {
         [CONST.INTRO_CHOICES.MANAGE_TEAM]: ({adminReportName, href}: {adminReportName: string; href: string}) =>
-            `ヘルプが必要な場合は、<a href="${href}">${adminReportName}</a> でアカウント担当者とチャットしてください`,
-        default: `セットアップのサポートが必要な場合は、<concierge-link>${CONST.CONCIERGE_CHAT_NAME}</concierge-link> にメッセージを送信してください`,
+            `サポートが必要な場合は、<a href="${href}">${adminReportName}</a> で設定スペシャリストにチャットしてください`,
+        default: `セットアップについては、<concierge-link>${CONST.CONCIERGE_CHAT_NAME}</concierge-link> にメッセージを送ってサポートを受けてください`,
     },
     violations: {
         allTagLevelsRequired: 'すべてのタグが必須です',
         autoReportedRejectedExpense: 'この経費精算は却下されました。',
         billableExpense: '請求可能区分は無効になりました',
-        cashExpenseWithNoReceipt: (formattedLimit?: string) => `領収書が必要です${formattedLimit ? `${formattedLimit} を超過` : ''}`,
+        cashExpenseWithNoReceipt: ({formattedLimit}: ViolationsCashExpenseWithNoReceiptParams = {}) => `領収書が必要です${formattedLimit ? `${formattedLimit} を超過` : ''}`,
         categoryOutOfPolicy: 'カテゴリは無効です',
-        conversionSurcharge: (surcharge: number) => `${surcharge}% の換算手数料を適用しました`,
+        conversionSurcharge: ({surcharge}: ViolationsConversionSurchargeParams) => `${surcharge}% の換算手数料を適用しました`,
         customUnitOutOfPolicy: 'このワークスペースでは有効なレートではありません',
         duplicatedTransaction: '重複の可能性',
         fieldRequired: 'レポートの項目は必須です',
         futureDate: '将来の日付は使用できません',
-        inactiveVendor: 'ベンダーは無効です',
-        invoiceMarkup: (invoiceMarkup: number) => `${invoiceMarkup}%値上げ済み`,
-        maxAge: (maxAge: number) => `日付が${maxAge}日より前です`,
+        invoiceMarkup: ({invoiceMarkup}: ViolationsInvoiceMarkupParams) => `${invoiceMarkup}%値上げ済み`,
+        maxAge: ({maxAge}: ViolationsMaxAgeParams) => `日付が${maxAge}日より前です`,
         missingCategory: 'カテゴリが未選択です',
         missingComment: '選択したカテゴリには説明が必要です',
         missingAttendees: 'このカテゴリには複数の参加者が必要です',
-        missingTag: (tagName?: string) => `${tagName ?? 'タグ'} が見つかりません`,
+        missingTag: ({tagName}: ViolationsMissingTagParams = {}) => `${tagName ?? 'タグ'} が見つかりません`,
         modifiedAmount: ({type, displayPercentVariance}: ViolationsModifiedAmountParams) => {
             switch (type) {
                 case 'distance':
@@ -8810,17 +7647,15 @@ ${reportName}
             }
         },
         modifiedDate: '日付がスキャンしたレシートと異なります',
-        increasedDistance: ({formattedRouteDistance}: ViolationsIncreasedDistanceParams) =>
-            formattedRouteDistance ? `距離が計算されたルート距離（${formattedRouteDistance}）を超えています` : '距離が計算されたルートを超えています',
         nonExpensiworksExpense: 'Expensiworks 以外の経費',
-        overAutoApprovalLimit: (formattedLimit: string) => `経費が自動承認限度額 ${formattedLimit} を超えています`,
-        overCategoryLimit: (formattedLimit: string) => `1人あたりのカテゴリ上限 ${formattedLimit} を超えた金額`,
-        overLimit: (formattedLimit: string) => `1人あたりの上限額 ${formattedLimit} を超過した金額`,
-        overTripLimit: (formattedLimit: string) => `1回の出張あたりの上限${formattedLimit}超過額`,
-        overLimitAttendee: (formattedLimit: string) => `1人あたりの上限額 ${formattedLimit} を超過した金額`,
-        perDayLimit: (formattedLimit: string) => `1人あたりの1日上限額 ${formattedLimit} を超えたカテゴリ金額`,
+        overAutoApprovalLimit: ({formattedLimit}: ViolationsOverLimitParams) => `経費が自動承認限度額 ${formattedLimit} を超えています`,
+        overCategoryLimit: ({formattedLimit}: ViolationsOverCategoryLimitParams) => `1人あたりのカテゴリ上限 ${formattedLimit} を超えた金額`,
+        overLimit: ({formattedLimit}: ViolationsOverLimitParams) => `1人あたりの上限額 ${formattedLimit} を超過した金額`,
+        overTripLimit: ({formattedLimit}: ViolationsOverLimitParams) => `1回の出張あたりの上限${formattedLimit}超過額`,
+        overLimitAttendee: ({formattedLimit}: ViolationsOverLimitParams) => `1人あたりの上限額 ${formattedLimit} を超過した金額`,
+        perDayLimit: ({formattedLimit}: ViolationsPerDayLimitParams) => `1人あたりの1日上限額 ${formattedLimit} を超えたカテゴリ金額`,
         receiptNotSmartScanned: 'レシートと経費の詳細が手動で追加されました。',
-        receiptRequired: (formattedLimit?: string, category?: string) => {
+        receiptRequired: ({formattedLimit, category}: ViolationsReceiptRequiredParams) => {
             if (formattedLimit && category) {
                 return `レシートが必要です（カテゴリ上限 ${formattedLimit} を超過）`;
             }
@@ -8832,8 +7667,8 @@ ${reportName}
             }
             return '領収書が必要です';
         },
-        itemizedReceiptRequired: (formattedLimit?: string) => `項目別の領収書が必要です${formattedLimit ? `${formattedLimit} を超過` : ''}`,
-        prohibitedExpense: (prohibitedExpenseTypes: string | string[]) => {
+        itemizedReceiptRequired: ({formattedLimit}: {formattedLimit?: string}) => `項目別の領収書が必要です${formattedLimit ? `${formattedLimit} を超過` : ''}`,
+        prohibitedExpense: ({prohibitedExpenseTypes}: ViolationsProhibitedExpenseParams) => {
             const preMessage = '禁止経費：';
             const getProhibitedExpenseTypeText = (prohibitedExpenseType: string) => {
                 switch (prohibitedExpenseType) {
@@ -8847,10 +7682,6 @@ ${reportName}
                         return `アダルトエンターテインメント`;
                     case 'hotelIncidentals':
                         return `ホテル諸雑費`;
-                    case 'giftCard':
-                        return `ギフトカード購入`;
-                    case 'handwrittenReceipt':
-                        return `手書きレシート`;
                     default:
                         return `${prohibitedExpenseType}`;
                 }
@@ -8866,37 +7697,19 @@ ${reportName}
             }
             return `${preMessage} ${types.map(getProhibitedExpenseTypeText).join(', ')}`;
         },
-        customRules: (message: string) => message,
+        customRules: ({message}: ViolationsCustomRulesParams) => message,
         reviewRequired: '要レビュー',
-        rter: (
-            brokenBankConnection: boolean,
-            isAdmin: boolean,
-            isTransactionOlderThan7Days: boolean,
-            member?: string,
-            rterType?: ValueOf<typeof CONST.RTER_VIOLATION_TYPES>,
-            companyCardPageURL?: string,
-            connectionLink?: string,
-            isPersonalCard?: boolean,
-            isMarkAsCash?: boolean,
-        ) => {
+        rter: ({brokenBankConnection, isAdmin, isTransactionOlderThan7Days, member, rterType, companyCardPageURL}: ViolationsRterParams) => {
             if (rterType === CONST.RTER_VIOLATION_TYPES.BROKEN_CARD_CONNECTION_530) {
-                return '銀行連携の不具合により、領収書を自動照合できません。';
-            }
-            if (isPersonalCard && (rterType === CONST.RTER_VIOLATION_TYPES.BROKEN_CARD_CONNECTION || brokenBankConnection)) {
-                if (!connectionLink) {
-                    return '銀行連携の不具合により、領収書を自動照合できません。';
-                }
-                return isMarkAsCash
-                    ? `カード連携の不具合により領収書を自動照合できません。無視するには現金としてマークするか、<a href="${connectionLink}">カードを修正</a>して領収書と照合してください。`
-                    : `カード連携が壊れているため、領収書を自動照合できません。領収書を照合するには、<a href="${connectionLink}">カードの問題を解決</a>してください。`;
+                return '銀行連携の不具合によりレシートを自動照合できません';
             }
             if (brokenBankConnection || rterType === CONST.RTER_VIOLATION_TYPES.BROKEN_CARD_CONNECTION) {
                 return isAdmin
-                    ? `銀行連携が切断されました。<a href="${companyCardPageURL}">レシートと照合するために再接続</a>`
-                    : '銀行連携が切断されています。管理者に依頼して再接続し、領収書と照合してください。';
+                    ? `銀行接続が切断されました。<a href="${companyCardPageURL}">再接続してレシートと照合</a>`
+                    : '銀行連携が切断されています。管理者に依頼して再接続し、レシートとの照合を行ってください。';
             }
             if (!isTransactionOlderThan7Days) {
-                return isAdmin ? `${member} に現金としてマークするよう依頼するか、7日待ってから再試行してください` : 'カード取引との照合待ちです。';
+                return isAdmin ? `${member} に現金としてマークするよう依頼するか、7日待ってからもう一度お試しください` : 'カード取引との統合待ちです。';
             }
             return '';
         },
@@ -8905,20 +7718,12 @@ ${reportName}
             `<muted-text-label>銀行接続の不具合により領収書が保留されています。<a href="${workspaceCompanyCardRoute}">会社カード</a>で解決してください。</muted-text-label>`,
         memberBrokenConnectionError: '銀行連携の不具合により領収書が保留されています。ワークスペース管理者に対応を依頼してください。',
         markAsCashToIgnore: '現金としてマークして無視し、支払いをリクエストします。',
-        smartscanFailed: ({canEdit = true, missingFields = []}: {canEdit?: boolean; missingFields?: string[]}) => {
-            if (missingFields.length > 0) {
-                const fieldNames: Record<string, string> = {merchant: '加盟店', date: '日付', amount: '金額'};
-                const translated = missingFields.map((f) => fieldNames[f] ?? f);
-                const fieldList = translated.join('、');
-                return `レシートのスキャンに失敗しました — ${fieldList}が見つかりません。${canEdit ? '詳細を手動で入力してください。' : ''}`;
-            }
-            return `レシートのスキャンに失敗しました。${canEdit ? '詳細を手動で入力してください。' : ''}`;
-        },
+        smartscanFailed: ({canEdit = true}) => `レシートのスキャンに失敗しました。${canEdit ? '詳細を手動で入力してください。' : ''}`,
         receiptGeneratedWithAI: 'AI生成の可能性があるレシート',
-        someTagLevelsRequired: (tagName?: string) => `${tagName ?? 'タグ'} が見つかりません`,
-        tagOutOfPolicy: (tagName?: string) => `${tagName ?? 'タグ'} は無効になりました`,
+        someTagLevelsRequired: ({tagName}: ViolationsTagOutOfPolicyParams = {}) => `${tagName ?? 'タグ'} が見つかりません`,
+        tagOutOfPolicy: ({tagName}: ViolationsTagOutOfPolicyParams = {}) => `${tagName ?? 'タグ'} は無効になりました`,
         taxAmountChanged: '税額が変更されました',
-        taxOutOfPolicy: (taxName?: string) => `${taxName ?? '税金'} は有効期限切れです`,
+        taxOutOfPolicy: ({taxName}: ViolationsTaxOutOfPolicyParams = {}) => `${taxName ?? '税金'} は有効期限切れです`,
         taxRateChanged: '税率が変更されました',
         taxRequired: '税率が未設定です',
         none: 'なし',
@@ -8938,7 +7743,7 @@ ${reportName}
         noRoute: '有効な住所を選択してください',
     },
     reportViolations: {
-        [CONST.REPORT_VIOLATIONS.FIELD_REQUIRED]: (fieldName: string) => `${fieldName} は必須です`,
+        [CONST.REPORT_VIOLATIONS.FIELD_REQUIRED]: ({fieldName}: RequiredFieldParams) => `${fieldName} は必須です`,
         reportContainsExpensesWithViolations: 'レポートに違反のある経費が含まれています。',
     },
     violationDismissal: {
@@ -8994,7 +7799,6 @@ ${reportName}
         bookACallTextTop: 'Expensify Classic に切り替えると、次の機能が利用できなくなります：',
         bookACallTextBottom: 'ぜひお電話で理由をお聞かせください。お客様のニーズについて話し合うために、シニアプロダクトマネージャーとの通話を予約できます。',
         takeMeToExpensifyClassic: 'Expensify Classic に移動',
-        goBackJustOnce: '一度だけ戻る',
     },
     listBoundary: {
         errorMessage: 'さらにメッセージを読み込む際にエラーが発生しました',
@@ -9066,7 +7870,7 @@ ${reportName}
                 subtitle: '次のステップとして、チームが経費精算を開始できるように、<a href="#">セットアップチェックリストを完了してください</a>。',
             },
             trialStarted: {
-                title: (numOfDays: number) => `トライアル：残り ${numOfDays} ${numOfDays === 1 ? '日' : '日数'} 日！`,
+                title: ({numOfDays}: TrialStartedTitleParams) => `トライアル：残り ${numOfDays} ${numOfDays === 1 ? '日' : '日数'} 日！`,
                 subtitle: 'すべてのお気に入り機能を引き続き利用するには、支払い用カードを追加してください。',
             },
             trialEnded: {
@@ -9103,15 +7907,15 @@ ${reportName}
             title: 'あなたのプラン',
             exploreAllPlans: 'すべてのプランを表示',
             customPricing: 'カスタム料金',
-            asLowAs: (price: string) => `アクティブメンバー1人あたり月額${price}〜`,
-            pricePerMemberMonth: (price: string) => `メンバー1人あたり/月 ${price}`,
-            pricePerMemberPerMonth: (price: string) => `${price}（メンバー1人あたり／月）`,
+            asLowAs: ({price}: YourPlanPriceValueParams) => `アクティブメンバー1人あたり月額${price}〜`,
+            pricePerMemberMonth: ({price}: YourPlanPriceValueParams) => `メンバー1人あたり/月 ${price}`,
+            pricePerMemberPerMonth: ({price}: YourPlanPriceValueParams) => `${price}（メンバー1人あたり／月）`,
             perMemberMonth: 'メンバー1人あたり／月',
             collect: {
                 title: '回収',
                 description: '経費、出張、チャットがすべて使える小規模ビジネス向けプラン。',
-                priceAnnual: ({lower, upper}: YourPlanPriceParams) => `Expensify カードありのアクティブメンバーは ${lower}、Expensify カードなしのアクティブメンバーは ${upper} です。`,
-                pricePayPerUse: ({lower, upper}: YourPlanPriceParams) => `Expensify カードありのアクティブメンバーは ${lower}、Expensify カードなしのアクティブメンバーは ${upper} です。`,
+                priceAnnual: ({lower, upper}: YourPlanPriceParams) => `Expensify カードありのアクティブメンバーは ${lower}、Expensify カードなしのアクティブメンバーは ${upper} から。`,
+                pricePayPerUse: ({lower, upper}: YourPlanPriceParams) => `Expensify カードありのアクティブメンバーは ${lower}、Expensify カードなしのアクティブメンバーは ${upper} から。`,
                 benefit1: 'レシートのスキャン',
                 benefit2: '精算払い',
                 benefit3: 'コーポレートカード管理',
@@ -9124,8 +7928,8 @@ ${reportName}
             control: {
                 title: 'コントロール',
                 description: '大企業向けの経費精算、出張管理、チャット。',
-                priceAnnual: ({lower, upper}: YourPlanPriceParams) => `Expensify カードありのアクティブメンバーは ${lower}、Expensify カードなしのアクティブメンバーは ${upper} です。`,
-                pricePayPerUse: ({lower, upper}: YourPlanPriceParams) => `Expensify カードありのアクティブメンバーは ${lower}、Expensify カードなしのアクティブメンバーは ${upper} です。`,
+                priceAnnual: ({lower, upper}: YourPlanPriceParams) => `Expensify カードありのアクティブメンバーは ${lower}、Expensify カードなしのアクティブメンバーは ${upper} から。`,
+                pricePayPerUse: ({lower, upper}: YourPlanPriceParams) => `Expensify カードありのアクティブメンバーは ${lower}、Expensify カードなしのアクティブメンバーは ${upper} から。`,
                 benefit1: 'Collect プランのすべての内容',
                 benefit2: '多段階承認ワークフロー',
                 benefit3: 'カスタム経費ルール',
@@ -9139,8 +7943,8 @@ ${reportName}
             downgrade: 'Collect へダウングレード',
             upgrade: 'Control にアップグレード',
             addMembers: 'メンバーを追加',
-            saveWithExpensifyTitle: 'Expensify カードで節約しましょう',
-            saveWithExpensifyDescription: '節約計算ツールを使って、Expensify カードのキャッシュバックが Expensify の請求額をどれだけ減らせるか確認しましょう。',
+            saveWithExpensifyTitle: 'Expensify カードで節約',
+            saveWithExpensifyDescription: 'Expensify CardのキャッシュバックがExpensifyの請求額をどれだけ削減できるか、節約額計算ツールを使って確認しましょう。',
             saveWithExpensifyButton: '詳細はこちら',
         },
         compareModal: {
@@ -9150,7 +7954,6 @@ ${reportName}
         details: {
             title: 'サブスクリプションの詳細',
             annual: '年額サブスクリプション',
-            creditBalance: 'クレジット残高',
             taxExempt: '非課税扱いを申請',
             taxExemptEnabled: '非課税',
             taxExemptStatus: '非課税ステータス',
@@ -9168,10 +7971,10 @@ ${reportName}
             note: '注：アクティブメンバーとは、あなたの会社ワークスペースに紐づく経費データを作成、編集、提出、承認、精算、またはエクスポートしたことがあるすべてのユーザーを指します。',
             confirmDetails: '新しい年額サブスクリプションの詳細を確認してください。',
             subscriptionSize: 'サブスクリプションサイズ',
-            activeMembers: (size: number) => `${size} 名のアクティブメンバー／月`,
+            activeMembers: ({size}: SubscriptionSizeParams) => `${size} 名のアクティブメンバー／月`,
             subscriptionRenews: 'サブスクリプションの更新',
             youCantDowngrade: '年額サブスクリプションの期間中はダウングレードできません。',
-            youAlreadyCommitted: (size: number, date: string) =>
+            youAlreadyCommitted: ({size, date}: SubscriptionCommitmentParams) =>
                 `${date} まで、すでに月あたり ${size} 名のアクティブメンバーという年間サブスクリプションにコミットしています。自動更新を無効にすると、${date} に従量課金制のサブスクリプションへ切り替えることができます。`,
             error: {
                 size: '有効なサブスクリプション数を入力してください',
@@ -9181,52 +7984,39 @@ ${reportName}
         paymentCard: {
             addPaymentCard: '支払カードを追加',
             enterPaymentCardDetails: '支払いカードの詳細を入力してください',
-            security: 'Expensify は PCI-DSS に準拠し、銀行レベルの暗号化を使用し、お客様のデータを保護するために冗長化されたインフラストラクチャを活用しています。',
-            learnMoreAboutSecurity: '当社のセキュリティについて詳しく見る',
-        },
-        expensifyCode: {
-            title: 'Expensifyコード',
-            discountCode: '割引コード',
-            enterCode: 'サブスクリプションに適用するExpensifyコードを入力してください。',
-            discountMessage: (promoDiscount: string, validBillingCycles: string) =>
-                `次の${validBillingCycles ? `${validBillingCycles}回の` : ''}請求に対して${promoDiscount}%の割引が適用されます。`,
-            apply: '適用',
-            error: {
-                invalid: 'このコードは無効です',
-            },
+            security: 'Expensify は PCI-DSS に準拠し、銀行レベルの暗号化を使用し、冗長化されたインフラストラクチャでお客様のデータを保護しています。',
+            learnMoreAboutSecurity: 'セキュリティの詳細をご覧ください。',
         },
         subscriptionSettings: {
             title: 'サブスクリプション設定',
-            summary: (subscriptionType: string, subscriptionSize: string, expensifyCode: string, autoRenew: string, autoIncrease: string) =>
-                `サブスクリプションタイプ: ${subscriptionType}、サブスクリプション規模: ${subscriptionSize}${expensifyCode ? `、Expensifyコード: ${expensifyCode}` : ''}、自動更新: ${autoRenew}、年間席数の自動増加: ${autoIncrease}`,
+            summary: ({subscriptionType, subscriptionSize, autoRenew, autoIncrease}: SubscriptionSettingsSummaryParams) =>
+                `サブスクリプションタイプ: ${subscriptionType}、サブスクリプション規模: ${subscriptionSize}、自動更新: ${autoRenew}、年間席数の自動増加: ${autoIncrease}`,
             none: 'なし',
             on: 'オン',
             off: 'オフ',
             annual: '年額',
             autoRenew: '自動更新',
             autoIncrease: '年間席数を自動増加',
-            saveUpTo: (amountWithCurrency: string) => `アクティブメンバー1人あたり月額最大${amountWithCurrency}節約`,
+            saveUpTo: ({amountWithCurrency}: SubscriptionSettingsSaveUpToParams) => `アクティブメンバー1人あたり月額最大${amountWithCurrency}節約`,
             automaticallyIncrease: 'サブスクリプションの席数を超える有効メンバーが発生した場合に、年間席数を自動的に増やします。注：年間サブスクリプションの終了日は延長されます。',
             disableAutoRenew: '自動更新を無効にする',
             helpUsImprove: 'Expensify の改善にご協力ください',
             whatsMainReason: '自動更新を無効にする主な理由は何ですか？',
-            renewsOn: (date: string) => `更新日：${date}`,
-            pricingConfiguration: '料金は設定内容によって異なります。最もお得にご利用いただくには、年額プランを選択し、Expensify カードをお申し込みください。',
-            learnMore: (hasAdminsRoom: boolean) =>
+            renewsOn: ({date}: SubscriptionSettingsRenewsOnParams) => `更新日：${date}`,
+            pricingConfiguration: '料金は構成によって異なります。最も安くご利用いただくには、年額サブスクリプションを選択し、Expensify Card をご利用ください。',
+            learnMore: ({hasAdminsRoom}: SubscriptionSettingsLearnMoreParams) =>
                 `<muted-text>詳しくは<a href="${CONST.PRICING}">料金ページ</a>をご覧いただくか、${hasAdminsRoom ? `<a href="adminsRoom">#adminsルーム。</a>` : '#admins ルーム。'}で当社チームにチャットでお問い合わせください</muted-text>`,
             estimatedPrice: '概算価格',
-            changesBasedOn: 'これは、お客様の Expensify カードの利用状況と、以下のサブスクリプションオプションによって変わります。',
-            collectBillingDescription: 'Collect ワークスペースは、年間契約なしで、メンバーごとに毎月課金されます。',
-            pricing: '料金',
+            changesBasedOn: 'これは、Expensify Card の利用状況と、以下のサブスクリプションオプションに基づいて変動します。',
         },
-        cancelSubscription: {
-            title: 'サブスクリプションをキャンセル',
-            subtitle: 'サブスクリプションをキャンセルする主な理由を教えてください。',
+        requestEarlyCancellation: {
+            title: '早期解約をリクエスト',
+            subtitle: '早期解約を申請する主な理由を教えてください。',
             subscriptionCanceled: {
                 title: 'サブスクリプションを解約しました',
                 subtitle: '年間サブスクリプションは解約されました。',
                 info: 'ワークスペースを従量課金制で使い続けたい場合は、これで準備完了です。',
-                preventFutureActivity: (workspacesListRoute: string) =>
+                preventFutureActivity: ({workspacesListRoute}: WorkspacesListRouteParams) =>
                     `今後のアクティビティや請求を防ぎたい場合は、<a href="${workspacesListRoute}">ワークスペースを削除</a>する必要があります。ワークスペースを削除すると、当月中に発生した未精算のアクティビティについて請求が行われることにご注意ください。`,
             },
             requestSubmitted: {
@@ -9234,7 +8024,7 @@ ${reportName}
                 subtitle:
                     'サブスクリプションの解約をご希望とのこと、お知らせいただきありがとうございます。ご依頼の内容を確認し、まもなく<concierge-link>Concierge</concierge-link>とのチャットを通じてご連絡いたします。',
             },
-            acknowledgement: `解約を申請することにより、私は、Expensify の<a href=${CONST.OLD_DOT_PUBLIC_URLS.TERMS_URL}>利用規約</a>または私と Expensify 間のその他の適用されるサービス契約のいずれにおいても、Expensify は当該申請を承認する義務を負わず、また当該申請を承認するかどうかについての裁量が専ら Expensify にあることを認識し、これに同意します。`,
+            acknowledgement: `早期解約を申請することにより、私は、Expensify の<a href=${CONST.OLD_DOT_PUBLIC_URLS.TERMS_URL}>利用規約</a>または私と Expensify 間のその他の適用されるサービス契約のいずれにおいても、Expensify は当該申請を承認する義務を負わず、また当該申請を承認するかどうかについての裁量が専ら Expensify にあることを認識し、これに同意します。`,
         },
     },
     feedbackSurvey: {
@@ -9253,14 +8043,11 @@ ${reportName}
     },
     delegate: {
         switchAccount: 'アカウントを切り替え:',
-        switch: '切り替え',
-        copilot: 'Copilot',
         copilotDelegatedAccess: 'Copilot：代理アクセス',
         copilotDelegatedAccessDescription: '他のメンバーがあなたのアカウントにアクセスできるようにする',
-        learnMoreAboutDelegatedAccess: '代理アクセスの詳細',
         addCopilot: 'コパイロットを追加',
         membersCanAccessYourAccount: '次のメンバーがあなたのアカウントにアクセスできます:',
-        youCanAccessTheseAccounts: 'これらのアカウントにアクセスできます:',
+        youCanAccessTheseAccounts: 'これらのアカウントには、アカウント切り替え機能からアクセスできます。',
         role: ({role}: OptionalParam<DelegateRoleParams> = {}) => {
             switch (role) {
                 case CONST.DELEGATE_ROLE.ALL:
@@ -9378,7 +8165,6 @@ ${reportName}
             theresWasAProblemDuringAWorkspaceConnectionSync: 'ワークスペース接続の同期中に問題が発生しました',
             theresAProblemWithYourWallet: 'ウォレットに問題があります',
             theresAProblemWithYourWalletTerms: 'ウォレットの利用規約に問題があります',
-            aBankAccountIsLocked: '銀行口座がロックされています',
         },
     },
     emptySearchView: {
@@ -9399,10 +8185,15 @@ ${reportName}
         conciergeLHNGBR: '<tooltip>まずは<strong>こちらから！</strong></tooltip>',
         saveSearchTooltip: '<tooltip>保存済み検索の<strong>名前を変更</strong>しましょう！</tooltip>',
         accountSwitcher: '<tooltip>ここから<strong>Copilot アカウント</strong>にアクセスできます</tooltip>',
+        scanTestTooltip: {
+            main: '<tooltip><strong>テスト用レシートをスキャン</strong>して、どのように動作するか見てみましょう！</tooltip>',
+            manager: '<tooltip>お試しには<strong>テストマネージャー</strong>を選択してください！</tooltip>',
+            confirmation: '<tooltip>さあ、<strong>経費を提出</strong>して、何が起こるか見てみましょう！</tooltip>',
+            tryItOut: '試してみる',
+        },
         outstandingFilter: '<tooltip><strong>承認が必要な</strong>経費を絞り込む</tooltip>',
         scanTestDriveTooltip: '<tooltip>このレシートを送信して\n<strong>試用を完了しましょう！</strong></tooltip>',
         gpsTooltip: '<tooltip>GPS追跡を実行中です！完了したら、下で追跡を停止してください。</tooltip>',
-        hasFilterNegation: '<tooltip><strong>-has:receipt</strong> を使って、レシートのない経費を検索します。</tooltip>',
     },
     discardChangesConfirmation: {
         title: '変更を破棄しますか？',
@@ -9418,7 +8209,7 @@ ${reportName}
         confirmation: {
             title: '通話を確認',
             description: '以下の詳細をご確認ください。問題なければ通話を確定してください。確定後、詳細情報を記載した招待状をお送りします。',
-            setupSpecialist: 'お客様のアカウント担当者',
+            setupSpecialist: '設定スペシャリスト',
             meetingLength: '会議時間',
             dateTime: '日時',
             minutes: '30分',
@@ -9466,20 +8257,6 @@ ${reportName}
         exportInProgress: 'エクスポート処理中',
         conciergeWillSend: 'Conciergeがまもなくファイルを送信します。',
     },
-    exportDownload: {
-        preparingTitle: 'Preparing download...',
-        preparingBody: 'You can either wait for the download to finish or Concierge can send it to you via chat.',
-        sendFromConcierge: "Send me the file when it's ready",
-        conciergeTitle: 'You bet!',
-        conciergeBody: 'Concierge will send you a message when the file is ready.',
-        goToConcierge: 'Go to Concierge',
-        dismiss: 'Dismiss',
-        readyTitle: 'Your file is ready!',
-        readyBody: "If it didn't automatically download, use the button below.",
-        downloadFile: 'Download file',
-        failedTitle: 'Export failed',
-        close: 'Close',
-    },
     domain: {
         notVerified: '未確認',
         retry: '再試行',
@@ -9522,8 +8299,6 @@ ${reportName}
             disableSamlRequired: '必須なSAMLを無効にする',
             oktaWarningPrompt: 'よろしいですか？これにより Okta SCIM も無効になります。',
             requireWithEmptyMetadataError: '有効にするには、以下にアイデンティティプロバイダーのメタデータを追加してください',
-            pleaseDisableTwoFactorAuth: (twoFactorAuthSettingsUrl: string) =>
-                `<muted-text>SAML ログインを有効にするには、<a href="${twoFactorAuthSettingsUrl}">二要素認証の強制</a>を無効にしてください。</muted-text>`,
         },
         samlConfigurationDetails: {
             title: 'SAML 設定の詳細',
@@ -9572,6 +8347,7 @@ ${reportName}
             primaryContact: '主要連絡先',
             addPrimaryContact: '主な連絡先を追加',
             setPrimaryContactError: '主要連絡先を設定できませんでした。後でもう一度お試しください。',
+            settings: '設定',
             consolidatedDomainBilling: 'ドメイン一括請求',
             consolidatedDomainBillingDescription: (domainName: string) =>
                 `<comment><muted-text-label>有効にすると、主な連絡先は <strong>${domainName}</strong> メンバーが所有するすべてのワークスペースの支払いを行い、すべての請求書の受領書を受け取ります。</muted-text-label></comment>`,
@@ -9588,104 +8364,25 @@ ${reportName}
             resetDomain: 'ドメインをリセット',
             resetDomainExplanation: ({domainName}: {domainName?: string}) => `ドメインのリセットを確認するため、<strong>${domainName}</strong> と入力してください。`,
             enterDomainName: 'ここにドメイン名を入力してください',
-            resetDomainInfo: `この操作は<strong>完全に削除</strong>され、次のデータが消去されます。<br/> <bullet-list><bullet-item>会社カードの接続およびそれらのカードに紐づく未申報経費</bullet-item><bullet-item>SAML とグループ設定</bullet-item><bullet-item>旅行データおよび Expensify Travel へのアクセス</bullet-item></bullet-list> すべてのアカウント、ワークスペース、レポート、経費、およびその他のデータはそのまま残ります。<br/><br/>注：<a href="#">連絡方法</a>から関連付けられたメールアドレスを削除すると、このドメインをドメイン一覧から消去できます。`,
+            resetDomainInfo: `この操作は<strong>元に戻せません</strong>。次のデータが削除されます：<br/> <ul><li>会社カードの接続と、そのカードの未報告精算</li> <li>SAML およびグループ設定</li> </ul> すべてのアカウント、ワークスペース、レポート、経費、およびその他のデータは保持されます。<br/><br/>注：<a href="#">連絡方法</a>から関連付けられているメールアドレスを削除すると、このドメインをドメイン一覧から消去できます。`,
         },
         domainMembers: 'ドメインメンバー',
         members: {
             title: 'メンバー',
             findMember: 'メンバーを検索',
             addMember: 'メンバーを追加',
-            allMembers: 'すべてのメンバー',
             email: 'メールアドレス',
-            closeAccount: () => ({
-                one: 'アカウントを閉じる',
-                other: 'アカウントを閉じる',
-            }),
+            closeAccount: 'アカウントを閉じる',
             closeAccountPrompt: '本当によろしいですか？この操作は元に戻せません。',
-            forceCloseAccount: () => ({one: 'アカウントを強制的に閉鎖', other: 'アカウントを強制的に閉鎖'}),
-            safeCloseAccount: () => ({
-                one: 'アカウントを安全に閉じる',
-                other: 'アカウントを安全に閉じる',
-            }),
-            closeAccountInfo: () => ({
-                one: '保留中の承認、処理中の精算、代替ログイン方法がない場合などでもアカウントを閉鎖できるように、安全にアカウントを閉鎖することを推奨します: <bullet-list><bullet-item>保留中の承認</bullet-item><bullet-item>進行中の払い戻し</bullet-item><bullet-item>代替ログイン方法なし</bullet-item></bullet-list>それ以外の場合は、上記の安全上の注意を無視して、選択したアカウントを強制的に閉鎖できます。',
-                other: '保留中の承認、処理中の精算、代替ログイン方法がない場合などでもアカウントを閉鎖できるように、安全にアカウントを閉鎖することを推奨します: <bullet-list><bullet-item>保留中の承認</bullet-item><bullet-item>進行中の払い戻し</bullet-item><bullet-item>代替ログイン方法なし</bullet-item></bullet-list>それ以外の場合は、上記の安全上の注意を無視して、選択したアカウントを強制的に閉鎖できます。',
-            }),
+            forceCloseAccount: 'アカウントを強制的に閉鎖',
+            safeCloseAccount: 'アカウントを安全に閉じる',
+            closeAccountInfo:
+                '保留中の承認、処理中の精算、代替ログイン方法がない場合などでもアカウントを閉鎖できるように、安全にアカウントを閉鎖することを推奨します: <ul><li>保留中の承認</li><li>進行中の払い戻し</li><li>代替ログイン方法なし</li></ul>それ以外の場合は、上記の安全上の注意を無視して、選択したアカウントを強制的に閉鎖できます。',
             error: {
                 removeMember: 'このユーザーを削除できません。もう一度お試しください。',
                 addMember: 'このメンバーを追加できませんでした。もう一度お試しください。',
-                vacationDelegate: 'このユーザーを休暇代理人として設定できませんでした。もう一度お試しください。',
-                moveMember: 'このメンバーを移動できませんでした。もう一度お試しください。',
-                moveMemberNotPolicyAdmin:
-                    'メンバーをドメイングループに移動できません。このユーザーを移動しようとしているドメイングループに設定された優先ポリシーのポリシー管理者である必要があります。',
-            },
-            cannotSetVacationDelegateForMember: (email: string) => `${email} に休暇代理人を設定できません。現在、このユーザーは次のメンバーの代理人になっています。`,
-            reportSuspiciousActivityPrompt: (email: string) =>
-                `本当によろしいですか？これにより、<strong>${email}</strong> さんのアカウントがロックされます。<br /><br />その後、当社のチームがアカウントを確認し、不正アクセスを削除します。アクセスを回復するには、Concierge と連携して対応してもらう必要があります。`,
-            reportSuspiciousActivityConfirmationPrompt: 'アカウントが安全にロック解除できることを確認するために審査し、質問がある場合はConciergeを通じてご連絡します。',
-            emptyMembers: {title: 'このグループにはメンバーがいません', subtitle: 'メンバーを追加するか、上のフィルターを変更してみてください。'},
-            moveToGroup: 'グループへ移動',
-            chooseWhereToMove: ({count}: {count: number}) => `${count} ${count === 1 ? 'メンバー' : 'メンバー'} を移動する先を選択してください。`,
-            domainGroup: 'ドメイングループ',
-            chooseWhereToMoveName: ({name}: {name: string}) => `${name} をどこに移動するか選択してください。`,
-            membersFeatureList: {
-                subtitle: ({domainName}: {domainName: string}) =>
-                    `<muted-text>Expensify で <strong>${domainName}</strong> メンバーをより細かく管理できるように、ドメインを確認してください。</muted-text>`,
-                controlPolicyCreation: 'ワークスペースの作成を制限',
-                enableSamlSso: 'SAML SSO を有効にする',
-                enforce2FA: '2 要素認証を必須にする',
             },
         },
-        common: {
-            settings: '設定',
-            forceTwoFactorAuth: '2要素認証を必須にする',
-            forceTwoFactorAuthSAMLEnabledDescription: (samlPageUrl: string) =>
-                `<muted-text>2 要素認証を必須にするには、<a href="${samlPageUrl}">SAML</a> を無効にしてください。</muted-text>`,
-            forceTwoFactorAuthDescription: `<muted-text>このドメインのすべてのメンバーに二要素認証を必須にします。ドメインメンバーは、サインイン時に自分のアカウントで二要素認証を設定するよう求められます。</muted-text>`,
-            forceTwoFactorAuthError: '2要素認証の強制設定を変更できませんでした。後でもう一度お試しください。',
-            resetTwoFactorAuth: '2 要素認証をリセット',
-            error: 'この変更を保存できませんでした。もう一度お試しください。',
-        },
-        groups: {
-            title: 'グループ',
-            memberCount: () => ({one: 'メンバー 1 人', other: (count: number) => `${count}名のメンバー`}),
-            defaultGroup: '新しいメンバーのデフォルトグループ',
-            defaultGroupPrompt: (currentName: string, newName: string) =>
-                `本当に ${newName} をデフォルトグループに設定しますか？新しいメンバーは、以前のデフォルトグループ (${currentName}) ではなく、このグループに招待されます。`,
-            makeDefault: 'デフォルトに設定',
-            neverMind: 'やめておく',
-            createGroupError: 'このグループを作成できませんでした。もう一度お試しください。',
-            permissions: 'グループの権限',
-            createNewGroupButton: '新しいグループ',
-            createGroupSubmitButton: 'グループを作成',
-            expensifyCardPreferredWorkspace: 'Expensify Card の優先ワークスペース',
-            expensifyCardPreferredWorkspaceDescription: 'すべてのExpensify Cardトランザクションは、優先ワークスペースではなくExpensify Card優先ワークスペースで作成されます。',
-            strictlyEnforceWorkspaceRules: 'ワークスペースのルールを厳密に適用する',
-            strictlyEnforceWorkspaceRulesDescription: 'レポートを送信する前にすべてのワークスペースのルールを満たす必要があります。手動による例外は許可されていません。',
-            restrictExpenseWorkspaceCreation: '経費ワークスペースの作成／削除を制限する',
-            restrictExpenseWorkspaceCreationDescription:
-                'メンバーが経費ワークスペースを作成したり、経費ワークスペースから自分自身を削除したりできないようにします。これは、厳格なワークスペース適用と組み合わせることで、ドメイン外での使用を目的としたレポートの提出に Expensify が利用されるのを防ぐのに役立ちます。',
-            deleteGroup: 'グループを削除',
-            deleteGroupDangerConfirmationModal: 'グループを削除',
-            deleteGroupDangerConfirmationModalDescription: (defaultGroupName: string) =>
-                `本当によろしいですか？これにより、すべてのメンバーがデフォルトグループ（${defaultGroupName}）に再割り当てされ、元に戻すことはできません。`,
-            deleteGroupError: 'このグループを削除できませんでした。もう一度お試しください。',
-            preferredWorkspace: '優先ワークスペース',
-            preferredWorkspaceDescription: (enabled: boolean) => `すべての新しいレポートと経費は${enabled ? '選択された優先' : 'この'}ワークスペースに作成されます。`,
-            preferredWorkspaceSelectDescription: 'すべての新しい経費とレポートはこのワークスペースに作成されます。',
-            noWorkspacesMessage: 'このドメインにワークスペースがありません。この制限を有効にするにはワークスペースが必要です。',
-            restrictDefaultLoginSelection: 'デフォルトのログイン選択を制限する',
-            restrictDefaultLoginSelectionDescription: 'メンバーがポリシー制限を回避するために、ログイン用のメールアドレスを会社のドメイン以外に変更することを防ぎます。',
-            expensifyCardPreferredWorkspaceDisabledMessage: 'この設定を有効にするには、まず優先するワークスペースを有効にし、ドメインでExpensify Cardsを設定してください。',
-            findGroup: 'グループを検索',
-        },
-    },
-    proactiveAppReview: {
-        title: '新しい Expensify をお楽しみいただけていますか？',
-        description: '経費精算の体験をさらに良くできるよう、お知らせください。',
-        positiveButton: 'やった！',
-        negativeButton: 'そうでもありません',
-    },
-    monthPickerPage: {month: '月', selectMonth: '月を選択してください'},
+    },
 };
 export default translations;
diff --git a/src/languages/nl.ts b/src/languages/nl.ts
index fb4a758c1769..d30a82f499e2 100644
--- a/src/languages/nl.ts
+++ b/src/languages/nl.ts
@@ -11,52 +11,189 @@
  */
 import {CONST as COMMON_CONST} from 'expensify-common';
 import startCase from 'lodash/startCase';
-import type {ValueOf} from 'type-fest';
 import type {OnboardingTask} from '@libs/actions/Welcome/OnboardingFlow';
 import StringUtils from '@libs/StringUtils';
 import dedent from '@libs/StringUtils/dedent';
 import CONST from '@src/CONST';
 import type {Country} from '@src/CONST';
 import type OriginalMessage from '@src/types/onyx/OriginalMessage';
-import type {OriginalMessageSettlementAccountLocked, PersonalRulesModifiedFields, PolicyRulesModifiedFields} from '@src/types/onyx/OriginalMessage';
+import type {OriginalMessageSettlementAccountLocked, PolicyRulesModifiedFields} from '@src/types/onyx/OriginalMessage';
+import ObjectUtils from '@src/types/utils/ObjectUtils';
 import type en from './en';
 import type {
+    AddBudgetParams,
+    AddedOrDeletedPolicyReportFieldParams,
+    AddOrDeletePolicyCustomUnitRateParams,
     ChangeFieldParams,
-    ConciergeBrokenCardConnectionParams,
     ConnectionNameParams,
+    CreatedReportForUnapprovedTransactionsParams,
     DelegateRoleParams,
     DeleteActionParams,
+    DeleteBudgetParams,
     DeleteConfirmationParams,
     EditActionParams,
     ExportAgainModalDescriptionParams,
     ExportIntegrationSelectedParams,
+    ImportPolicyCustomUnitRatesParams,
     IntacctMappingTitleParams,
     InvalidPropertyParams,
     InvalidValueParams,
     MarkReimbursedFromIntegrationParams,
     MissingPropertyParams,
     MovedFromPersonalSpaceParams,
+    MultifactorAuthenticationTranslationParams,
+    NextStepParams,
     NotAllowedExtensionParams,
     OptionalParam,
     PaidElsewhereParams,
     ParentNavigationSummaryParams,
     RemovedFromApprovalWorkflowParams,
+    RemovedPolicyCustomUnitSubRateParams,
     ReportArchiveReasonsClosedParams,
     ReportArchiveReasonsInvoiceReceiverPolicyDeletedParams,
     ReportArchiveReasonsMergedParams,
     ReportArchiveReasonsRemovedFromPolicyParams,
+    ReportFieldParams,
+    ReportPolicyNameParams,
+    RequestAmountParams,
+    RequiredFieldParams,
     ResolutionConstraintsParams,
+    ReviewParams,
+    RoleNamesParams,
+    RoomNameReservedErrorParams,
+    RoomRenamedToParams,
+    RoutedDueToDEWParams,
+    RulesEnableWorkflowsParams,
+    SecondaryLoginParams,
+    SetTheDistanceMerchantParams,
+    SetTheRequestParams,
+    SettledAfterAddedBankAccountParams,
+    SettleExpensifyCardParams,
+    SettlementAccountInfoParams,
+    SettlementAccountReconciliationParams,
+    SettlementDateParams,
     ShareParams,
+    SignerInfoMessageParams,
+    SignUpNewFaceCodeParams,
     SizeExceededParams,
+    SplitAmountParams,
+    SplitDateRangeParams,
+    SplitExpenseEditTitleParams,
+    SplitExpenseSubtitleParams,
+    StatementTitleParams,
     StepCounterParams,
+    StripePaidParams,
+    SubmitsToParams,
+    SubmittedToVacationDelegateParams,
+    SubmittedWithMemoParams,
+    SubscriptionCommitmentParams,
+    SubscriptionSettingsLearnMoreParams,
+    SubscriptionSettingsRenewsOnParams,
+    SubscriptionSettingsSaveUpToParams,
+    SubscriptionSettingsSummaryParams,
+    SubscriptionSizeParams,
     SyncStageNameConnectionsParams,
+    TaskCreatedActionParams,
+    TaxAmountParams,
+    TermsParams,
+    ThreadRequestReportNameParams,
+    ThreadSentMoneyReportNameParams,
+    ToggleImportTitleParams,
+    TotalAmountGreaterOrLessThanOriginalParams,
+    ToValidateLoginParams,
+    TransferParams,
+    TravelTypeParams,
+    TrialStartedTitleParams,
+    UnapproveWithIntegrationWarningParams,
     UnshareParams,
-    UnsupportedFormulaValueErrorParams,
+    UntilTimeParams,
+    UpdatedBudgetParams,
+    UpdatedCustomFieldParams,
+    UpdatedPolicyApprovalRuleParams,
+    UpdatedPolicyAuditRateParams,
+    UpdatedPolicyAutoHarvestingParams,
+    UpdatedPolicyBudgetNotificationParams,
+    UpdatedPolicyCategoriesParams,
+    UpdatedPolicyCategoryDescriptionHintTypeParams,
+    UpdatedPolicyCategoryExpenseLimitTypeParams,
+    UpdatedPolicyCategoryGLCodeParams,
+    UpdatedPolicyCategoryMaxAmountNoReceiptParams,
+    UpdatedPolicyCategoryMaxExpenseAmountParams,
+    UpdatedPolicyCategoryNameParams,
+    UpdatedPolicyCategoryParams,
+    UpdatedPolicyCurrencyParams,
+    UpdatedPolicyCustomUnitRateEnabledParams,
+    UpdatedPolicyCustomUnitRateParams,
+    UpdatedPolicyCustomUnitSubRateParams,
+    UpdatedPolicyCustomUnitTaxClaimablePercentageParams,
+    UpdatedPolicyCustomUnitTaxRateExternalIDParams,
+    UpdatedPolicyDefaultTitleParams,
+    UpdatedPolicyDescriptionParams,
+    UpdatedPolicyFieldWithNewAndOldValueParams,
+    UpdatedPolicyFieldWithValueParams,
+    UpdatedPolicyFrequencyParams,
+    UpdatedPolicyManualApprovalThresholdParams,
+    UpdatedPolicyOwnershipParams,
+    UpdatedPolicyPreventSelfApprovalParams,
+    UpdatedPolicyReimbursementChoiceParams,
+    UpdatedPolicyReimbursementEnabledParams,
+    UpdatedPolicyReimburserParams,
+    UpdatedPolicyReportFieldDefaultValueParams,
+    UpdatedPolicyTagFieldParams,
+    UpdatedPolicyTagListParams,
+    UpdatedPolicyTagListRequiredParams,
+    UpdatedPolicyTagNameParams,
+    UpdatedPolicyTagParams,
+    UpdatedPolicyTaxParams,
+    UpdatedPolicyTimeEnabledParams,
+    UpdatedPolicyTimeRateParams,
+    UpdatedTheDistanceMerchantParams,
+    UpdatedTheRequestParams,
+    UpdatePolicyCustomUnitDefaultCategoryParams,
+    UpdatePolicyCustomUnitParams,
+    UpdatePolicyCustomUnitTaxEnabledParams,
     UpdateRoleParams,
-    ViolationsIncreasedDistanceParams,
+    UpgradeSuccessMessageParams,
+    UsePlusButtonParams,
+    UserIsAlreadyMemberParams,
+    UserSplitParams,
+    VacationDelegateParams,
+    ViolationsCashExpenseWithNoReceiptParams,
+    ViolationsConversionSurchargeParams,
+    ViolationsCustomRulesParams,
+    ViolationsInvoiceMarkupParams,
+    ViolationsMaxAgeParams,
+    ViolationsMissingTagParams,
     ViolationsModifiedAmountParams,
+    ViolationsOverCategoryLimitParams,
+    ViolationsOverLimitParams,
+    ViolationsPerDayLimitParams,
+    ViolationsProhibitedExpenseParams,
+    ViolationsReceiptRequiredParams,
+    ViolationsRterParams,
+    ViolationsTagOutOfPolicyParams,
+    ViolationsTaxOutOfPolicyParams,
+    WaitingOnBankAccountParams,
+    WalletAgreementParams,
+    WalletProgramParams,
+    WelcomeEnterMagicCodeParams,
+    WelcomeToRoomParams,
+    WeSentYouMagicSignInLinkParams,
+    WorkEmailMergingBlockedParams,
+    WorkEmailResendCodeParams,
+    WorkflowSettingsParam,
     WorkspaceLockedPlanTypeParams,
+    WorkspaceMemberList,
+    WorkspaceMembersCountParams,
+    WorkspaceOwnerWillNeedToAddOrUpdatePaymentCardParams,
+    WorkspaceRouteParams,
+    WorkspaceShareNoteParams,
+    WorkspacesListRouteParams,
+    WorkspaceUpgradeNoteParams,
+    WorkspaceYouMayJoin,
     YourPlanPriceParams,
+    YourPlanPriceValueParams,
+    ZipCodeExampleFormatParams,
 } from './params';
 import type {TranslationDeepObject} from './types';
 
@@ -90,10 +227,8 @@ const translations: TranslationDeepObject<typeof en> = {
         optional: 'Optioneel',
         new: 'Nieuw',
         newFeature: 'Nieuwe functie',
-        beta: 'Bèta',
         search: 'Zoeken',
         reports: 'Rapporten',
-        spend: 'Uitgaven',
         find: 'Zoeken',
         searchWithThreeDots: 'Zoeken...',
         next: 'Volgende',
@@ -118,14 +253,6 @@ const translations: TranslationDeepObject<typeof en> = {
         workspaces: 'Werkruimtes',
         home: 'Home',
         inbox: 'Inbox',
-        yourReviewIsRequired: 'Uw beoordeling is vereist',
-        actionBadge: {
-            submit: 'Verzenden',
-            approve: 'Goedkeuren',
-            pay: 'Betalen',
-            fix: 'Oplossen',
-            task: 'Taak',
-        },
         success: 'Gelukt',
         group: 'Groep',
         profile: 'Profiel',
@@ -135,7 +262,7 @@ const translations: TranslationDeepObject<typeof en> = {
         wallet: 'Wallet',
         preferences: 'Voorkeuren',
         view: 'Bekijken',
-        review: (amount?: string) => `Beoordelen${amount ? ` ${amount}` : ''}`,
+        review: (reviewParams?: ReviewParams) => `Beoordelen${reviewParams?.amount ? ` ${reviewParams?.amount}` : ''}`,
         not: 'Niet',
         signIn: 'Inloggen',
         signInWithGoogle: 'Aanmelden met Google',
@@ -146,7 +273,6 @@ const translations: TranslationDeepObject<typeof en> = {
         lastName: 'Achternaam',
         scanning: 'Scannen',
         analyzing: 'Analyseren...',
-        thinking: 'Concierge denkt na...',
         addCardTermsOfService: 'Expensify-servicevoorwaarden',
         perPerson: 'per persoon',
         phone: 'Telefoon',
@@ -208,12 +334,10 @@ const translations: TranslationDeepObject<typeof en> = {
         admin: 'Beheerder',
         owner: 'Eigenaar',
         dateFormat: 'JJJJ-MM-DD',
-        calendarOpened: 'kalender geopend',
         send: 'Verzenden',
         na: 'n.v.t.',
         noResultsFound: 'Geen resultaten gevonden',
         noResultsFoundMatching: (searchString: string) => `Geen resultaten gevonden voor "${searchString}"`,
-        suggestionsAvailableFor: (searchString: string) => (searchString ? `Suggesties beschikbaar voor "${searchString}".` : 'Suggesties beschikbaar.'),
         recentDestinations: 'Recente bestemmingen',
         timePrefix: 'Het is',
         conjunctionFor: 'voor',
@@ -224,7 +348,6 @@ const translations: TranslationDeepObject<typeof en> = {
         conjunctionTo: 'naar',
         genericErrorMessage: 'Oeps... er is iets misgegaan en je verzoek kon niet worden voltooid. Probeer het later opnieuw.',
         percentage: 'Percentage',
-        progressBarLabel: 'Voortgang onboarding',
         converted: 'Geconverteerd',
         error: {
             invalidAmount: 'Ongeldig bedrag',
@@ -263,7 +386,6 @@ const translations: TranslationDeepObject<typeof en> = {
         reset: 'Opnieuw instellen',
         done: 'Klaar',
         more: 'Meer',
-        other: 'Overig',
         debitCard: 'Debetkaart',
         bankAccount: 'Bankrekening',
         personalBankAccount: 'Persoonlijke bankrekening',
@@ -289,7 +411,7 @@ const translations: TranslationDeepObject<typeof en> = {
         verify: 'Verifiëren',
         yesContinue: 'Ja, ga door',
         websiteExample: 'bijv. https://www.expensify.com',
-        zipCodeExampleFormat: (zipSampleFormat: string) => (zipSampleFormat ? `bijv. ${zipSampleFormat}` : ''),
+        zipCodeExampleFormat: ({zipSampleFormat}: ZipCodeExampleFormatParams) => (zipSampleFormat ? `bijv. ${zipSampleFormat}` : ''),
         description: 'Beschrijving',
         title: 'Titel',
         assignee: 'Toegewezene',
@@ -300,8 +422,6 @@ const translations: TranslationDeepObject<typeof en> = {
         per: 'per',
         mi: 'mijl',
         km: 'kilometer',
-        milesAbbreviated: 'mi',
-        kilometersAbbreviated: 'km',
         copied: 'Gekopieerd!',
         someone: 'Iemand',
         total: 'Totaal',
@@ -310,7 +430,6 @@ const translations: TranslationDeepObject<typeof en> = {
         letsStart: `Laten we beginnen`,
         showMore: 'Meer weergeven',
         showLess: 'Toon minder',
-        plusMore: ({count}: {count: number}) => `+${count} meer`,
         merchant: 'Handelaar',
         change: 'Wijzigen',
         category: 'Categorie',
@@ -334,11 +453,8 @@ const translations: TranslationDeepObject<typeof en> = {
         selectCurrency: 'Selecteer een valuta',
         selectSymbolOrCurrency: 'Selecteer een symbool of valuta',
         card: 'Kaart',
-        mcc: 'MCC',
-        categoryGLCode: 'Categorie-grootboekcode',
         whyDoWeAskForThis: 'Waarom vragen we dit?',
         required: 'Vereist',
-        automatic: 'Automatisch',
         showing: 'Wordt weergegeven',
         of: 'of',
         default: 'Standaard',
@@ -346,7 +462,6 @@ const translations: TranslationDeepObject<typeof en> = {
         member: 'Lid',
         auditor: 'Auditor',
         role: 'Rol',
-        roleCannotBeChanged: (workflowsLinkPage: string) => `De rol kan niet worden gewijzigd omdat dit lid een <a href="${workflowsLinkPage}">betaler</a> is in deze werkruimte.`,
         currency: 'Valuta',
         groupCurrency: 'Groepsvaluta',
         rate: 'Beoordeling',
@@ -384,7 +499,6 @@ const translations: TranslationDeepObject<typeof en> = {
         reportID: 'Rapport-ID',
         longReportID: 'Lang rapport-ID',
         withdrawalID: 'Opname-ID',
-        withdrawalStatus: 'Opnamestatus',
         bankAccounts: 'Bankrekeningen',
         chooseFile: 'Bestand kiezen',
         chooseFiles: 'Bestanden kiezen',
@@ -418,21 +532,19 @@ const translations: TranslationDeepObject<typeof en> = {
         validate: 'Valideren',
         downloadAsPDF: 'Downloaden als PDF',
         downloadAsCSV: 'Downloaden als CSV',
-        print: 'Afdrukken',
         help: 'Help',
-        collapsed: 'Ingeklapt',
-        expanded: 'Uitgeklapt',
         expenseReport: 'Declaratie',
+        expenseReports: 'Declaraties',
         rateOutOfPolicy: 'Tarief buiten beleid',
         leaveWorkspace: 'Werkruimte verlaten',
         leaveWorkspaceConfirmation: 'Als je deze workspace verlaat, kun je er geen declaraties meer naartoe indienen.',
         leaveWorkspaceConfirmationAuditor: 'Als je deze workspace verlaat, kun je de bijbehorende rapporten en instellingen niet meer bekijken.',
         leaveWorkspaceConfirmationAdmin: 'Als je deze workspace verlaat, kun je de instellingen ervan niet meer beheren.',
-        leaveWorkspaceConfirmationApprover: (workspaceOwner: string) =>
+        leaveWorkspaceConfirmationApprover: ({workspaceOwner}: {workspaceOwner: string}) =>
             `Als je deze workspace verlaat, word je in de goedkeuringsworkflow vervangen door ${workspaceOwner}, de eigenaar van de workspace.`,
-        leaveWorkspaceConfirmationExporter: (workspaceOwner: string) =>
+        leaveWorkspaceConfirmationExporter: ({workspaceOwner}: {workspaceOwner: string}) =>
             `Als je deze workspace verlaat, word je als voorkeurs-exporteur vervangen door ${workspaceOwner}, de eigenaar van de workspace.`,
-        leaveWorkspaceConfirmationTechContact: (workspaceOwner: string) =>
+        leaveWorkspaceConfirmationTechContact: ({workspaceOwner}: {workspaceOwner: string}) =>
             `Als je deze workspace verlaat, word je als technisch contactpersoon vervangen door ${workspaceOwner}, de eigenaar van de workspace.`,
         leaveWorkspaceReimburser:
             'Je kunt deze workspace niet verlaten als terugbetaler. Stel een nieuwe terugbetaler in via Workspaces > Betalingen doen of volgen en probeer het dan opnieuw.',
@@ -441,6 +553,9 @@ const translations: TranslationDeepObject<typeof en> = {
         comments: 'Opmerkingen',
         sharedIn: 'Gedeeld in',
         unreported: 'Niet gerapporteerd',
+        explore: 'Ontdekken',
+        insights: 'Inzichten',
+        todo: 'To-do',
         invoice: 'Factuur',
         expense: 'Declaratie',
         chat: 'Chat',
@@ -451,15 +566,12 @@ const translations: TranslationDeepObject<typeof en> = {
         on: 'Aan',
         before: 'Vooraf',
         after: 'Na',
-        range: 'Bereik',
         reschedule: 'Opnieuw plannen',
         general: 'Algemeen',
         workspacesTabTitle: 'Werkruimtes',
         headsUp: 'Let op!',
         submitTo: 'Indienen bij',
         forwardTo: 'Doorsturen naar',
-        approvalLimit: 'Goedkeuringslimiet',
-        overLimitForwardTo: 'Doorsturen bij overschrijding limiet',
         merge: 'Samenvoegen',
         none: 'Geen',
         unstableInternetConnection: 'Onstabiele internetverbinding. Controleer je netwerk en probeer het opnieuw.',
@@ -476,7 +588,6 @@ const translations: TranslationDeepObject<typeof en> = {
         actionRequired: 'Actie vereist',
         duplicate: 'Dupliceren',
         duplicated: 'Gedupliceerd',
-        opensInNewTab: 'Opent in een nieuw tabblad',
         locked: 'Vergrendeld',
         duplicateExpense: 'Dubbele uitgave',
         exchangeRate: 'Wisselkoers',
@@ -486,38 +597,14 @@ const translations: TranslationDeepObject<typeof en> = {
         week: 'Week',
         year: 'Jaar',
         quarter: 'Kwartaal',
-        vacationDelegate: 'Vertegenwoordiger tijdens vakantie',
-        expensifyLogo: 'Expensify-logo',
-        concierge: {greeting: 'Hoi, waarmee kan ik je helpen?', showHistory: 'Geschiedenis weergeven'},
-        duplicateReport: 'Dubbel rapport',
-        approver: 'Fiatteur',
-        goToConcierge: 'Ga naar Concierge',
-        allSet: 'Helemaal klaar!',
-        enterDigitLabel: ({digitIndex, totalDigits}: {digitIndex: number; totalDigits: number}) => `voer cijfer ${digitIndex} van ${totalDigits} in`,
-        copyOfReportName: (reportName: string) => `Kopie van ${reportName}`,
-        previousMonth: 'Vorige maand',
-        nextMonth: 'Volgende maand',
-        previousYear: 'Vorig jaar',
-        nextYear: 'Volgend jaar',
-        avatar: 'Avatar',
-        editor: 'Editor',
-        restrictions: 'Beperkingen',
-    },
-    socials: {
-        podcast: 'Volg ons op Podcast',
-        twitter: 'Volg ons op Twitter',
-        instagram: 'Volg ons op Instagram',
-        facebook: 'Volg ons op Facebook',
-        linkedin: 'Volg ons op LinkedIn',
-    },
-    concierge: {
-        collapseReasoning: 'Redenering inklappen',
-        expandReasoning: 'Redenering uitklappen',
-        enableNotifications: {prompt: 'Wil je een melding krijgen wanneer Concierge reageert?', cta: 'Melden'},
     },
     supportalNoAccess: {
         title: 'Niet zo snel',
-        descriptionWithCommand: (command?: string) =>
+        descriptionWithCommand: ({
+            command,
+        }: {
+            command?: string;
+        } = {}) =>
             `Je bent niet gemachtigd om deze actie uit te voeren wanneer support is ingelogd (opdracht: ${command ?? ''}). Als je denkt dat Success deze actie zou moeten kunnen uitvoeren, start dan een gesprek in Slack.`,
     },
     lockedAccount: {
@@ -553,7 +640,7 @@ const translations: TranslationDeepObject<typeof en> = {
         chooseDocument: 'Bestand kiezen',
         attachmentTooLarge: 'Bijlage is te groot',
         sizeExceeded: 'Bijlage is groter dan de limiet van 24 MB',
-        sizeExceededWithLimit: (maxUploadSizeInMB: number) => `De bijlage is groter dan de limiet van ${maxUploadSizeInMB} MB`,
+        sizeExceededWithLimit: ({maxUploadSizeInMB}: SizeExceededParams) => `De bijlage is groter dan de limiet van ${maxUploadSizeInMB} MB`,
         attachmentTooSmall: 'Bijlage is te klein',
         sizeNotMet: 'Bijlagegrootte moet groter zijn dan 240 bytes',
         wrongFileType: 'Ongeldig bestandstype',
@@ -564,9 +651,9 @@ const translations: TranslationDeepObject<typeof en> = {
         attachmentImageTooLarge: 'Deze afbeelding is te groot om een voorbeeld te tonen vóór het uploaden.',
         imageDimensionsTooLarge: 'De afmetingen van de afbeelding zijn te groot om te verwerken. Gebruik een kleinere afbeelding.',
         tooManyFiles: (fileLimit: number) => `Je kunt maximaal ${fileLimit} bestanden tegelijk uploaden.`,
-        sizeExceededWithValue: (maxUploadSizeInMB: number) => `Bestanden zijn groter dan ${maxUploadSizeInMB} MB. Probeer het opnieuw.`,
+        sizeExceededWithValue: ({maxUploadSizeInMB}: SizeExceededParams) => `Bestanden zijn groter dan ${maxUploadSizeInMB} MB. Probeer het opnieuw.`,
         someFilesCantBeUploaded: 'Sommige bestanden kunnen niet worden geüpload',
-        sizeLimitExceeded: (maxUploadSizeInMB: number) => `Bestanden moeten kleiner zijn dan ${maxUploadSizeInMB} MB. Grotere bestanden worden niet geüpload.`,
+        sizeLimitExceeded: ({maxUploadSizeInMB}: SizeExceededParams) => `Bestanden moeten kleiner zijn dan ${maxUploadSizeInMB} MB. Grotere bestanden worden niet geüpload.`,
         maxFileLimitExceeded: 'Je kunt tot 30 bonnetjes tegelijk uploaden. Extra bonnetjes worden niet geüpload.',
         unsupportedFileType: (fileType: string) => `${fileType}-bestanden worden niet ondersteund. Alleen ondersteunde bestandstypen worden geüpload.`,
         learnMoreAboutSupportedFiles: 'Meer informatie over ondersteunde indelingen.',
@@ -606,55 +693,17 @@ const translations: TranslationDeepObject<typeof en> = {
         signIn: 'Meld je opnieuw aan.',
     },
     multifactorAuthentication: {
-        reviewTransaction: {
-            reviewTransaction: 'Transactie controleren',
-            pleaseReview: 'Controleer deze transactie alsjeblieft',
-            requiresYourReview: 'Er is een Expensify Card-transactie hieronder die je moet beoordelen.',
-            transactionDetails: 'Transactiegegevens',
-            deny: 'Weigeren',
-            approve: 'Goedkeuren',
-            denyTransaction: 'Transactie weigeren',
-            transactionDenied: 'Transactie geweigerd',
-            transactionApproved: 'Transactie goedgekeurd!',
-            areYouSureToDeny: 'Weet je het zeker? De transactie wordt geweigerd als je dit scherm sluit.',
-            youCanTryAgainAtMerchantOrReachOut:
-                'Je kunt het opnieuw proberen bij de winkelier. Als je deze transactie niet hebt geprobeerd uit te voeren, <concierge-link>neem dan contact op met Concierge</concierge-link> om mogelijke fraude te melden.',
-            youNeedToTryAgainAtMerchant: 'Deze transactie is niet geverifieerd, dus we hebben haar geweigerd. Je moet het opnieuw proberen bij de handelaar.',
-            goBackToTheMerchant: 'Ga terug naar de website van de verkoper om door te gaan met de transactie.',
-            attemptedTransaction: 'Poging tot transactie',
-            transactionFailed: 'Transactie mislukt',
-            transactionCouldNotBeCompleted: 'Je transactie kon niet worden voltooid. Probeer het alsjeblieft opnieuw bij de verkoper.',
-            transactionCouldNotBeCompletedReachOut:
-                'Je transactie kon niet worden voltooid. Als je deze transactie niet hebt geprobeerd uit te voeren, <concierge-link>neem dan contact op met Concierge</concierge-link> om mogelijke fraude te melden.',
-            reviewFailed: 'Beoordeling mislukt',
-            alreadyReviewedSubtitle:
-                'Je hebt deze transactie al gecontroleerd. Controleer je <transaction-history-link>transactiegeschiedenis</transaction-history-link> of neem contact op met <concierge-link>Concierge</concierge-link> om problemen te melden.',
-        },
         biometricsTest: {
             biometricsTest: 'Biometrische test',
-            authenticationSuccessful: 'Authenticatie geslaagd',
-            successfullyAuthenticatedUsing: (authType?: string) => `Je bent succesvol geauthenticeerd met ${authType}.`,
-            troubleshootBiometricsStatus: ({status}: {status?: string}) => `Biometrie (${status})`,
+            authenticationSuccessful: 'Verificatie geslaagd',
+            successfullyAuthenticatedUsing: ({authType}: MultifactorAuthenticationTranslationParams) => `Je bent succesvol geauthenticeerd met ${authType}.`,
+            troubleshootBiometricsStatus: ({registered}: MultifactorAuthenticationTranslationParams) => `Biometrie (${registered ? 'Geregistreerd' : 'Niet geregistreerd'})`,
             yourAttemptWasUnsuccessful: 'Je verificatiepoging is niet gelukt.',
             youCouldNotBeAuthenticated: 'Je kon niet worden geverifieerd',
             areYouSureToReject: 'Weet je het zeker? De authenticatiepoging wordt geweigerd als je dit scherm sluit.',
             rejectAuthentication: 'Authenticatie weigeren',
             test: 'Test',
             biometricsAuthentication: 'Biometrische verificatie',
-            authType: {
-                unknown: 'Onbekend',
-                none: 'Geen',
-                credentials: 'Inloggegevens',
-                biometrics: 'Biometrie',
-                faceId: 'Face ID',
-                touchId: 'Touch ID',
-                opticId: 'Optic ID',
-                passkey: 'Passkey',
-            },
-            statusNeverRegistered: 'Nooit geregistreerd',
-            statusNotRegistered: 'Niet geregistreerd',
-            statusRegisteredThisDevice: 'Geregistreerd',
-            statusRegisteredOtherDevice: () => ({one: 'Ander apparaat geregistreerd', other: 'Andere geregistreerde apparaten'}),
         },
         pleaseEnableInSystemSettings: {
             start: 'Schakel gezichts-/vingerafdrukverificatie in of stel een toesteltoegangscode in op uw',
@@ -667,42 +716,27 @@ const translations: TranslationDeepObject<typeof en> = {
         letsVerifyItsYou: 'Laten we controleren of jij het bent',
         nowLetsAuthenticateYou: 'Laten we je nu verifiëren...',
         letsAuthenticateYou: 'We gaan je authenticeren...',
-        verifyYourself: {biometrics: 'Verifieer jezelf met je gezicht of vingerafdruk', passkeys: 'Verifieer jezelf met een toegangssleutel'},
+        verifyYourself: {
+            biometrics: 'Verifieer jezelf met je gezicht of vingerafdruk',
+        },
         enableQuickVerification: {
             biometrics: 'Schakel snelle, veilige verificatie in met je gezicht of vingerafdruk. Geen wachtwoorden of codes nodig.',
-            passkeys: 'Schakel snelle, veilige verificatie in met een passkey. Geen wachtwoorden of codes nodig.',
         },
         revoke: {
+            remove: 'Verwijderen',
             title: 'Gezicht/vingerafdruk & passkeys',
             explanation:
-                'Gezichts-/vingerafdruk- of passkeys-verificatie is ingeschakeld op één of meer apparaten. Toegang intrekken betekent dat er op dat apparaat bij de volgende verificatie een magische code nodig is.',
-            confirmationPrompt: 'Weet je het zeker? Je hebt een magische code nodig voor de volgende verificatie op dat apparaat.',
+                'Gezichts-/vingerafdruk- of passkeys-verificatie is ingeschakeld op een of meer apparaten. Toegang intrekken betekent dat er een magische code nodig is voor de volgende verificatie op elk apparaat.',
+            confirmationPrompt: 'Weet je het zeker? Je hebt een magische code nodig voor de volgende verificatie op elk apparaat.',
             cta: 'Toegang intrekken',
-            noDevices: 'Je hebt geen apparaten geregistreerd voor gezichts-/vingerafdruk- of passkeys-verificatie. Als je er een registreert, kun je die toegang hier intrekken.',
+            noDevices: 'Je hebt geen apparaten geregistreerd voor gezichts-/vingerafdruk- of passkey-verificatie. Als je er een registreert, kun je die toegang hier intrekken.',
             dismiss: 'Begrepen',
             error: 'Aanvraag mislukt. Probeer het later opnieuw.',
-            revoke: 'Intrekken',
-            confirmationPromptAll: 'Weet je het zeker? Je hebt een magische code nodig voor de volgende verificatie op elk apparaat.',
-            ctaAll: 'Alles intrekken',
-            thisDevice: 'Dit apparaat',
-            otherDevices: (otherDeviceCount?: number) => {
-                const numberWords = ['Eén', 'Twee', 'Drie', 'Vier', 'Vijf', 'Zes', 'Zeven', 'Acht', 'Negen'];
-                const displayCount = otherDeviceCount !== undefined && otherDeviceCount >= 1 && otherDeviceCount <= 9 ? numberWords.at(otherDeviceCount - 1) : `${otherDeviceCount}`;
-                return `${displayCount} andere ${otherDeviceCount === 1 ? 'apparaat' : 'apparaten'}`;
-            },
-            confirmationPromptThisDevice: 'Weet je het zeker? Je hebt een magische code nodig voor de volgende verificatie op dit apparaat.',
-            confirmationPromptMultiple: 'Weet je het zeker? Je hebt een magische code nodig voor de volgende verificatie op die apparaten.',
         },
         unsupportedDevice: {
             unsupportedDevice: 'Niet-ondersteund apparaat',
-            pleaseDownloadMobileApp: `Deze actie wordt niet ondersteund op jouw apparaat. Download de Expensify-app uit de <a href="${CONST.APP_DOWNLOAD_LINKS.IOS}">App Store</a> of de <a href="${CONST.APP_DOWNLOAD_LINKS.ANDROID}">Google Play Store</a> en probeer het opnieuw.`,
-            pleaseUseWebApp: `Deze actie wordt niet ondersteund op jouw apparaat. Gebruik de <a href="${CONST.NEW_EXPENSIFY_URL}">Expensify-webapp</a> en probeer het opnieuw.`,
+            pleaseDownloadMobileApp: `<centered-text><muted-text> Deze actie wordt niet ondersteund op jouw apparaat. Download de Expensify-app uit de <a href="${CONST.APP_DOWNLOAD_LINKS.IOS}">App Store</a> of de <a href="${CONST.APP_DOWNLOAD_LINKS.ANDROID}">Google Play Store</a> en probeer het opnieuw.</muted-text></centered-text>`,
         },
-        verificationFailed: 'Verificatie mislukt',
-        setPin: {didNotShipCard: 'We hebben je kaart niet verzonden. Probeer het opnieuw.'},
-        revealPin: {couldNotReveal: 'We konden je pincode niet tonen. Probeer het opnieuw.'},
-        changePin: {didNotChange: 'We hebben je pincode niet gewijzigd. Probeer het opnieuw.'},
-        revealCardDetail: {couldNotReveal: 'We konden je kaartgegevens niet weergeven. Probeer het opnieuw.'},
     },
     validateCodeModal: {
         successfulSignInTitle: dedent(`
@@ -712,7 +746,7 @@ const translations: TranslationDeepObject<typeof en> = {
         successfulSignInDescription: 'Ga terug naar je oorspronkelijke tabblad om verder te gaan.',
         title: 'Hier is je magische code',
         description: dedent(`
-            Voer de code in op het apparaat
+            Voer de code in op het apparaat  
             waar deze oorspronkelijk is aangevraagd
         `),
         doNotShare: dedent(`
@@ -741,7 +775,11 @@ const translations: TranslationDeepObject<typeof en> = {
         nameEmailOrPhoneNumber: 'Naam, e-mail of telefoonnummer',
         findMember: 'Lid zoeken',
         searchForSomeone: 'Iemand zoeken',
-        userSelected: (username: string) => `${username} geselecteerd`,
+    },
+    customApprovalWorkflow: {
+        title: 'Aangepaste goedkeuringsworkflow',
+        description: 'Je bedrijf heeft een aangepast goedkeuringsproces in deze workspace. Voer deze actie uit in Expensify Classic',
+        goToExpensifyClassic: 'Overschakelen naar Expensify Classic',
     },
     emptyList: {
         [CONST.IOU.TYPE.CREATE]: {
@@ -763,8 +801,8 @@ const translations: TranslationDeepObject<typeof en> = {
         phrase2: 'Geld spreekt. En nu chatten en betalen op één plek samenkomen, is het ook nog eens eenvoudig.',
         phrase3: 'Je betalingen komen net zo snel bij je aan als jij je punt kunt maken.',
         enterPassword: 'Voer uw wachtwoord in',
-        welcomeNewFace: (login: string) => `${login}, het is altijd leuk om een nieuw gezicht hier te zien!`,
-        welcomeEnterMagicCode: (login: string) => `Voer de magische code in die naar ${login} is gestuurd. Deze zou binnen een tot twee minuten moeten aankomen.`,
+        welcomeNewFace: ({login}: SignUpNewFaceCodeParams) => `${login}, het is altijd leuk om een nieuw gezicht hier te zien!`,
+        welcomeEnterMagicCode: ({login}: WelcomeEnterMagicCodeParams) => `Voer de magische code in die naar ${login} is gestuurd. Deze zou binnen een tot twee minuten moeten aankomen.`,
     },
     login: {
         hero: {
@@ -792,9 +830,6 @@ const translations: TranslationDeepObject<typeof en> = {
         emoji: 'Emoji',
         collapse: 'Samenvouwen',
         expand: 'Uitklappen',
-        askConciergeToUpdate: 'Probeer „Een uitgave bijwerken”…',
-        askConciergeToCorrect: 'Probeer “Een uitgave corrigeren”…',
-        askConciergeForHelp: 'Vraag Concierge AI om hulp...',
     },
     reportActionContextMenu: {
         copyMessage: 'Bericht kopiëren',
@@ -858,9 +893,9 @@ const translations: TranslationDeepObject<typeof en> = {
         askMeAnything: 'Vraag me alles!',
         sayHello: 'Zeg hallo!',
         yourSpace: 'Jouw ruimte',
-        welcomeToRoom: (roomName: string) => `Welkom bij ${roomName}!`,
-        usePlusButton: (additionalText: string) => `Gebruik de +-knop om een uitgave te ${additionalText}.`,
-        askConcierge: 'Concierge kan vragen beantwoorden, uitgaven bijwerken en meer.',
+        welcomeToRoom: ({roomName}: WelcomeToRoomParams) => `Welkom bij ${roomName}!`,
+        usePlusButton: ({additionalText}: UsePlusButtonParams) => `Gebruik de +-knop om een uitgave te ${additionalText}.`,
+        askConcierge: 'Vraag me alles!',
         conciergeSupport: 'Jouw persoonlijke AI-agent',
         create: 'maken',
         iouTypes: {
@@ -872,17 +907,12 @@ const translations: TranslationDeepObject<typeof en> = {
         },
     },
     adminOnlyCanPost: 'Alleen beheerders kunnen berichten sturen in deze ruimte.',
-    readOnlyConversation: 'Deze conversatie is alleen-lezen.',
     reportAction: {
         asCopilot: 'als copiloot voor',
-        assistedBy: (agentName: string) => `bijgestaan door ${agentName}`,
-        humanSupportAgent: 'een menselijke medewerker',
         harvestCreatedExpenseReport: (reportUrl: string, reportName: string) =>
             `heeft dit rapport gemaakt om alle uitgaven van <a href="${reportUrl}">${reportName}</a> te bewaren die niet konden worden ingediend op de door jou gekozen frequentie`,
-        createdReportForUnapprovedTransactions: (reportUrl: string, reportName: string, reportID: string, isReportDeleted: boolean) =>
-            isReportDeleted
-                ? `heeft dit rapport gemaakt voor alle vastgehouden uitgaven uit verwijderd rapport nr. ${reportID}`
-                : `heeft dit rapport gemaakt voor alle vastgehouden uitgaven van <a href="${reportUrl}">${reportName}</a>`,
+        createdReportForUnapprovedTransactions: ({reportUrl, reportName}: CreatedReportForUnapprovedTransactionsParams) =>
+            `heeft dit rapport gemaakt voor uitgestelde uitgaven van <a href="${reportUrl}">${reportName}</a>`,
     },
     mentionSuggestions: {
         hereAlternateText: 'Laat iedereen in dit gesprek een melding krijgen',
@@ -921,6 +951,7 @@ const translations: TranslationDeepObject<typeof en> = {
         buttonFind: 'Zoek iets...',
         buttonMySettings: 'Mijn instellingen',
         fabNewChat: 'Chat starten',
+        fabNewChatExplained: 'Actiemenu openen',
         fabScanReceiptExplained: 'Bon scannen',
         chatPinned: 'Chat vastgezet',
         draftedMessage: 'Conceptbericht',
@@ -928,44 +959,41 @@ const translations: TranslationDeepObject<typeof en> = {
         listOfChats: 'Lijst met chats',
         saveTheWorld: 'Red de wereld',
         tooltip: 'Begin hier!',
+        redirectToExpensifyClassicModal: {
+            title: 'Binnenkort beschikbaar',
+            description:
+                'We zijn nog een paar onderdelen van New Expensify aan het finetunen om die op jouw specifieke instellingen af te stemmen. Ga in de tussentijd verder in Expensify Classic.',
+        },
     },
     homePage: {
         forYou: 'Voor jou',
         timeSensitiveSection: {
             title: 'Tijdgevoelig',
-            addShippingAddress: {title: 'We hebben je verzendadres nodig', subtitle: 'Geef een adres op om je Expensify Kaart te ontvangen.', cta: 'Adres toevoegen'},
-            addPaymentCard: {title: 'Voeg een betaalkaart toe om Expensify te blijven gebruiken', subtitle: 'Account > Abonnement', cta: 'Toevoegen'},
-            activateCard: {title: 'Activeer je Expensify Kaart', subtitle: 'Valideer je kaart en begin met uitgeven.', cta: 'Activeren'},
-            reviewCardFraud: {
-                title: 'Controleer mogelijk misbruik van je Expensify Kaart',
-                titleWithDetails: ({amount, merchant}: {amount: string; merchant: string}) => `Controleer ${amount} aan mogelijke fraude bij ${merchant}`,
-                subtitle: 'Expensify Kaart',
-                cta: 'Beoordelen',
+            cta: 'Declaratie',
+            offer50off: {
+                title: 'Krijg 50% korting op je eerste jaar!',
+                subtitle: ({formattedTime}: {formattedTime: string}) => `Nog ${formattedTime} resterend`,
             },
-            ctaFix: 'Repareren',
-            fixCompanyCardConnection: {
-                title: ({feedName}: {feedName: string}) => (feedName ? `Verbinding bedrijfskaart ${feedName} herstellen` : 'Verbinding van bedrijfskaart repareren'),
-                defaultSubtitle: 'Werkruimte',
-                subtitle: ({policyName}: {policyName: string}) => `${policyName} > Bedrijfspassen`,
+            offer25off: {
+                title: 'Krijg 25% korting op je eerste jaar!',
+                subtitle: ({days}: {days: number}) => `${days} ${days === 1 ? 'dag' : 'dagen'} resterend`,
             },
-            fixPolicyConnection: {
-                title: ({integrationName}: {integrationName: string}) => `Verbinding met ${integrationName} repareren`,
-                defaultSubtitle: 'Werkruimte',
-                subtitle: ({policyName}: {policyName: string}) => `${policyName} > Boekhouding`,
+            addShippingAddress: {
+                title: 'We hebben je verzendadres nodig',
+                subtitle: 'Voer een adres in om je Expensify Card te ontvangen.',
+                cta: 'Adres toevoegen',
             },
-            fixPersonalCardConnection: {
-                title: ({cardName}: {cardName?: string}) => (cardName ? `Verbinding van persoonlijke kaart ${cardName} herstellen` : 'Verbinding persoonlijke kaart herstellen'),
-                subtitle: 'Portemonnee',
+            activateCard: {
+                title: 'Activeer je Expensify Card',
+                subtitle: 'Valideer je kaart en begin met uitgeven.',
+                cta: 'Activeren',
             },
-            validateAccount: {title: 'Valideer je account', subtitle: 'Account', cta: 'Valideren'},
-            fixFailedBilling: {title: 'We konden je kaart in ons bestand niet belasten', subtitle: 'Abonnement'},
-            unlockBankAccount: {
-                workspaceTitle: 'Je zakelijke bankrekening is geblokkeerd',
-                personalTitle: 'Je bankrekening is vergrendeld',
-                workspaceSubtitle: ({policyName}: {policyName: string}) => policyName,
-                personalSubtitle: 'Portemonnee',
+            ctaFix: 'Repareren',
+            fixCompanyCardConnection: {
+                title: ({feedName}: {feedName: string}) => (feedName ? `Verbinding bedrijfskaart ${feedName} herstellen` : 'Verbinding van bedrijfskaart repareren'),
+                subtitle: 'Werkruimte > Bedrijfspassen',
             },
-            enterSignerInfo: {title: 'Ondertekenaargegevens vereist', subtitle: ({bankAccountLastFour}: {bankAccountLastFour: string}) => `Bankrekening ${bankAccountLastFour}`},
+            fixAccountingConnection: {title: ({integrationName}: {integrationName: string}) => `Verbinding met ${integrationName} repareren`, subtitle: 'Werkruimte > Boekhouding'},
         },
         announcements: 'Aankondigingen',
         discoverSection: {
@@ -981,78 +1009,12 @@ const translations: TranslationDeepObject<typeof en> = {
             export: ({count}: {count: number}) => `Exporteer ${count} ${count === 1 ? 'rapport' : 'rapporten'}`,
             begin: 'Begin',
             emptyStateMessages: {
-                thumbsUpStarsTitle: 'Je bent klaar!',
-                thumbsUpStarsDescription: 'Duim omhoog voor jou, houd je klaar voor meer taken.',
-                smallRocketTitle: 'Helemaal bij',
-                smallRocketDescription: 'Aankomende taken verschijnen hier.',
-                cowboyHatTitle: 'Je bent klaar!',
-                cowboyHatDescription: 'Alle taken zijn geregeld, houd de volgende in de gaten.',
-                trophy1Title: 'Niets om weer te geven',
-                trophy1Description: "Je hebt het gedaan! Houd de volgende to-do's in de gaten.",
-                palmTreeTitle: 'Helemaal bij',
-                palmTreeDescription: 'Tijd om te ontspannen, maar houd je klaar voor toekomstige taken.',
-                fishbowlBlueTitle: 'Je bent klaar!',
-                fishbowlBlueDescription: 'Toekomstige taken verschijnen hier.',
-                targetTitle: 'Helemaal bij',
-                targetDescription: 'Goed bezig, je blijft op koers. Kom terug voor meer taken!',
-                chairTitle: 'Niets om weer te geven',
-                chairDescription: "Ga maar ontspannen, we zetten aankomende to-do's hier neer.",
-                broomTitle: 'Je bent klaar!',
-                broomDescription: "Taken zijn afgerond, maar houd je klaar voor meer to-do's.",
-                houseTitle: 'Helemaal bij',
-                houseDescription: "Dit is je thuisbasis voor aankomende to-do's.",
-                conciergeBotTitle: 'Niets om weer te geven',
-                conciergeBotDescription: 'Biep boep biep boep, kom terug voor meer taken!',
-                checkboxTextTitle: 'Helemaal bij',
-                checkboxTextDescription: 'Vink hier je komende taken af.',
-                flashTitle: 'Je bent klaar!',
-                flashDescription: 'We laten je toekomstige taken hier zien.',
-                sunglassesTitle: 'Niets om weer te geven',
-                sunglassesDescription: 'Tijd om te relaxen, maar houd je klaar voor wat er komt!',
-                f1FlagsTitle: 'Helemaal bij',
-                f1FlagsDescription: "Je hebt alle openstaande to-do's afgerond.",
-            },
-        },
-        upcomingTravel: 'Aankomende reizen',
-        upcomingTravelSection: {
-            flightTo: ({destination}: {destination: string}) => `Vlucht naar ${destination}`,
-            trainTo: ({destination}: {destination: string}) => `Trein naar ${destination}`,
-            hotelIn: ({destination}: {destination: string}) => `Hotel in ${destination}`,
-            carRentalIn: ({destination}: {destination: string}) => `Autoverhuur in ${destination}`,
-            inOneWeek: 'Over 1 week',
-            inDays: () => ({one: 'Over 1 dag', other: (count: number) => `Over ${count} dagen`}),
-            today: 'Vandaag',
-        },
-        freeTrialSection: {
-            title: ({days}: {days: number}) => `Proefperiode: nog ${days} ${days === 1 ? 'dag' : 'dagen'}!`,
-            offer50Body: 'Krijg 50% korting op je eerste jaar',
-            offer25Body: 'Krijg 25% korting op je eerste jaar',
-            addCardBody: 'Betaalpas toevoegen',
-            ctaClaim: 'Declareren',
-            ctaAdd: 'Kaart toevoegen',
-            timeRemaining: ({formattedTime}: {formattedTime: string}) => `Resterende tijd: ${formattedTime}`,
-            timeRemainingDays: () => ({
-                one: 'Resterende tijd: 1 dag',
-                other: (pluralCount: number) => `Resterende tijd: ${pluralCount} dagen`,
-            }),
-        },
-        gettingStartedSection: {
-            title: 'Aan de slag',
-            createWorkspace: 'Maak een werkruimte',
-            connectAccounting: ({integrationName}: {integrationName: string}) => `Verbind met ${integrationName}`,
-            connectAccountingDefault: 'Verbind met boekhouding',
-            customizeCategories: 'Boekhoudcategorieën aanpassen',
-            linkCompanyCards: 'Bedrijfspassen koppelen',
-            setupRules: 'Uitgavenregels instellen',
-            inviteAccountant: 'Nodig je accountant uit',
-        },
-        yourSpend: {
-            title: 'Je uitgaven',
-            awaitingApproval: 'In afwachting van goedkeuring',
-            repaidLast30Days: 'Terugbetaald in de afgelopen 30 dagen',
-            recentTransactions: ({lastFour}: {lastFour: string}) => `Recente transacties • ${lastFour}`,
+                nicelyDone: 'Mooi gedaan',
+                keepAnEyeOut: 'Hou in de gaten wat er hierna komt!',
+                allCaughtUp: 'Je bent helemaal bij',
+                upcomingTodos: 'Aankomende taken verschijnen hier.',
+            },
         },
-        seeMore: ({count}: {count: number}) => `Bekijk nog ${count}`,
     },
     allSettingsScreen: {
         subscription: 'Abonnement',
@@ -1081,20 +1043,7 @@ const translations: TranslationDeepObject<typeof en> = {
         singleFieldMultipleColumns: (fieldName: string) => `Oeps! Je hebt één veld (‘${fieldName}’) aan meerdere kolommen gekoppeld. Controleer dit en probeer het opnieuw.`,
         emptyMappedField: (fieldName: string) => `Oeps! Het veld („${fieldName}”) bevat een of meer lege waarden. Controleer het en probeer het opnieuw.`,
         importSuccessfulTitle: 'Import geslaagd',
-        importCategoriesSuccessfulDescription: ({added, updated}: {added: number; updated: number}) => {
-            if (!added && !updated) {
-                return 'Er zijn geen categorieën toegevoegd of bijgewerkt.';
-            }
-            if (added && updated) {
-                return `${added} ${added === 1 ? 'categorie' : 'categorieën'} toegevoegd, ${updated} ${updated === 1 ? 'categorie' : 'categorieën'} bijgewerkt.`;
-            }
-            if (added) {
-                return added === 1 ? '1 categorie is toegevoegd.' : `${added} categorieën zijn toegevoegd.`;
-            }
-            return updated === 1 ? '1 categorie is bijgewerkt.' : `${updated} categorieën zijn bijgewerkt.`;
-        },
-        importCompanyCardTransactionsSuccessfulDescription: ({transactions}: {transactions: number}) =>
-            transactions > 1 ? `${transactions} transacties zijn toegevoegd.` : '1 transactie is toegevoegd.',
+        importCategoriesSuccessfulDescription: ({categories}: {categories: number}) => (categories > 1 ? `${categories} categorieën zijn toegevoegd.` : '1 categorie is toegevoegd.'),
         importMembersSuccessfulDescription: ({added, updated}: {added: number; updated: number}) => {
             if (!added && !updated) {
                 return 'Er zijn geen leden toegevoegd of bijgewerkt.';
@@ -1126,7 +1075,6 @@ const translations: TranslationDeepObject<typeof en> = {
             other: (count: number) =>
                 `Bevestig hieronder de gegevens voor de ${count} nieuwe werkruimteleden die als onderdeel van deze upload worden toegevoegd. Bestaande leden ontvangen geen rolupdates of uitnodigingsberichten.`,
         }),
-        importCompanyCardTransactionsPendingMessage: 'Nieuwe kaarten en transacties kunnen even duren voordat ze verschijnen, even geduld.',
     },
     receipt: {
         upload: 'Bon uploaden',
@@ -1158,9 +1106,7 @@ const translations: TranslationDeepObject<typeof en> = {
         deleteReceipt: 'Bon verwijderen',
         deleteConfirmation: 'Weet je zeker dat je deze bon wilt verwijderen?',
         addReceipt: 'Bon toevoegen',
-        addAdditionalReceipt: 'Voeg extra bon toe',
         scanFailed: 'De bon is niet gescand, omdat er een handelaar, datum of bedrag ontbreekt.',
-        crop: 'Bijsnijden',
         addAReceipt: {
             phrase1: 'Voeg een bon toe',
             phrase2: 'of sleep ze hier naartoe',
@@ -1180,7 +1126,6 @@ const translations: TranslationDeepObject<typeof en> = {
         noLongerHaveReportAccess: 'Je hebt geen toegang meer tot je vorige snelkoppelingsbestemming. Kies hieronder een nieuwe.',
         updateDestination: 'Bestemming bijwerken',
         createReport: 'Rapport maken',
-        createTimeExpense: 'Tijdkosten aanmaken',
     },
     iou: {
         amount: 'Bedrag',
@@ -1200,18 +1145,18 @@ const translations: TranslationDeepObject<typeof en> = {
         split: 'Splitsen',
         splitExpense: 'Uitgave splitsen',
         splitDates: 'Datums splitsen',
-        splitDateRange: (startDate: string, endDate: string, count: number) => `${startDate} tot ${endDate} (${count} dagen)`,
-        splitExpenseSubtitle: (amount: string, merchant: string) => `${amount} van ${merchant}`,
+        splitDateRange: ({startDate, endDate, count}: SplitDateRangeParams) => `${startDate} tot ${endDate} (${count} dagen)`,
+        splitExpenseSubtitle: ({amount, merchant}: SplitExpenseSubtitleParams) => `${amount} van ${merchant}`,
         splitByPercentage: 'Verdelen op percentage',
         splitByDate: 'Opsplitsen op datum',
         addSplit: 'Splits toevoegen',
         makeSplitsEven: 'Verdeel bedragen gelijk',
         editSplits: 'Splits bewerken',
-        totalAmountGreaterThanOriginal: (amount: string) => `Het totale bedrag is ${amount} hoger dan de oorspronkelijke uitgave.`,
-        totalAmountLessThanOriginal: (amount: string) => `Het totale bedrag is ${amount} minder dan de oorspronkelijke uitgave.`,
+        totalAmountGreaterThanOriginal: ({amount}: TotalAmountGreaterOrLessThanOriginalParams) => `Het totale bedrag is ${amount} hoger dan de oorspronkelijke uitgave.`,
+        totalAmountLessThanOriginal: ({amount}: TotalAmountGreaterOrLessThanOriginalParams) => `Het totale bedrag is ${amount} minder dan de oorspronkelijke uitgave.`,
         splitExpenseZeroAmount: 'Voer een geldig bedrag in voordat je verdergaat.',
         splitExpenseOneMoreSplit: 'Geen splitsingen toegevoegd. Voeg er minimaal één toe om op te slaan.',
-        splitExpenseEditTitle: (amount: string, merchant: string) => `${amount} voor ${merchant} bewerken`,
+        splitExpenseEditTitle: ({amount, merchant}: SplitExpenseEditTitleParams) => `${amount} voor ${merchant} bewerken`,
         removeSplit: 'Splits verwijderen',
         splitExpenseCannotBeEditedModalTitle: 'Deze uitgave kan niet worden bewerkt',
         splitExpenseCannotBeEditedModalDescription: 'Goedgekeurde of betaalde onkosten kunnen niet worden bewerkt',
@@ -1242,12 +1187,9 @@ const translations: TranslationDeepObject<typeof en> = {
         deleteReceipt: 'Bon verwijderen',
         findExpense: 'Uitgave zoeken',
         deletedTransaction: (amount: string, merchant: string) => `heeft een uitgave verwijderd (${amount} voor ${merchant})`,
-        movedFromReport: (reportName: string) => `heeft een uitgave verplaatst uit ${reportName}`,
-        movedFromReportNoName: 'heeft een uitgave verplaatst',
-        movedTransactionTo: (reportUrl: string, reportName: string) => `heeft deze uitgave verplaatst naar <a href="${reportUrl}">${reportName}</a>`,
-        movedTransactionToAnotherReport: 'heeft deze uitgave naar een ander rapport verplaatst',
-        movedTransactionFrom: (reportUrl: string, reportName: string) => `heeft deze uitgave verplaatst van <a href="${reportUrl}">${reportName}</a>`,
-        movedTransactionFromAnotherReport: 'heeft deze uitgave van een ander rapport verplaatst',
+        movedFromReport: (reportName: string) => `heeft een uitgave verplaatst${reportName ? `van ${reportName}` : ''}`,
+        movedTransactionTo: (reportUrl: string, reportName?: string) => `heeft deze uitgave verplaatst${reportName ? `naar <a href="${reportUrl}">${reportName}</a>` : ''}`,
+        movedTransactionFrom: (reportUrl: string, reportName?: string) => `heeft deze uitgave verplaatst${reportName ? `van <a href="${reportUrl}">${reportName}</a>` : ''}`,
         unreportedTransaction: (reportUrl: string) => `heeft deze uitgave verplaatst naar je <a href="${reportUrl}">persoonlijke ruimte</a>`,
         movedAction: (shouldHideMovedReportUrl: boolean, movedReportUrl: string, newParentReportUrl: string, toPolicyName: string) => {
             if (shouldHideMovedReportUrl) {
@@ -1259,10 +1201,7 @@ const translations: TranslationDeepObject<typeof en> = {
         pendingMatch: 'Overeenkomst in behandeling',
         pendingMatchWithCreditCardDescription: 'Bon wordt nog gekoppeld aan kaarttransactie. Markeer als contant om te annuleren.',
         markAsCash: 'Markeren als contant',
-        pendingMatchSubmitTitle: 'Rapport indienen',
-        pendingMatchSubmitDescription: 'Sommige uitgaven wachten op koppeling met een creditcardtransactie. Wilt u ze als contant markeren?',
         routePending: 'Routeren in behandeling...',
-        automaticallyEnterExpenseDetails: 'Concierge vult de gegevens voor je in.',
         receiptScanning: () => ({
             one: 'Bon wordt gescand...',
             other: 'Bonnetjes scannen...',
@@ -1289,7 +1228,7 @@ const translations: TranslationDeepObject<typeof en> = {
         receiptStatusTitle: 'Scannen…',
         receiptStatusText: 'Alleen jij kunt deze bon zien terwijl hij wordt gescand. Kom later terug of voer de gegevens nu in.',
         receiptScanningFailed: 'Bon scannen mislukt. Voer de gegevens handmatig in.',
-        allTransactionsPendingNextStep: 'Alle transacties zijn in behandeling. Je kunt dit rapport pas indienen als ze over een paar dagen zijn geboekt.',
+        transactionPendingDescription: 'Transactie in behandeling. Het kan een paar dagen duren voordat deze wordt verwerkt.',
         companyInfo: 'Bedrijfsgegevens',
         companyInfoDescription: 'We hebben nog een paar gegevens nodig voordat je je eerste factuur kunt versturen.',
         yourCompanyName: 'Naam van je bedrijf',
@@ -1324,18 +1263,20 @@ const translations: TranslationDeepObject<typeof en> = {
         settledElsewhere: 'Elders betaald',
         individual: 'Individueel',
         business: 'Zakelijk',
-        settlePersonal: (formattedAmount?: string) => (formattedAmount ? `Betaal ${formattedAmount} als individu` : `Betalen met persoonlijke rekening`),
-        settleWallet: (formattedAmount?: string) => (formattedAmount ? `Betaal ${formattedAmount} met wallet` : `Betalen met wallet`),
-        settlePayment: (formattedAmount: string) => `Betaal ${formattedAmount}`,
-        settleBusiness: (formattedAmount?: string) => (formattedAmount ? `Betaal ${formattedAmount} als bedrijf` : `Betalen met zakelijke rekening`),
-        payElsewhere: (formattedAmount?: string) => (formattedAmount ? `Markeer ${formattedAmount} als betaald` : `Markeren als betaald`),
-        confirmPaymentReceivedModalTitle: 'Ontvangst van betaling bevestigen',
-        receivedPayment: 'Betaling ontvangen',
-        receivedPaymentConfirmation: 'Ga alleen verder als je de betaling al buiten Expensify hebt ontvangen.',
-        confirmReceivedPayment: 'Ja, ik heb de betaling ontvangen.',
+        settleExpensify: ({formattedAmount}: SettleExpensifyCardParams) => (formattedAmount ? `Betaal ${formattedAmount} met Expensify` : `Betalen met Expensify`),
+        settlePersonal: ({formattedAmount}: SettleExpensifyCardParams) => (formattedAmount ? `Betaal ${formattedAmount} als individu` : `Betalen met persoonlijke rekening`),
+        settleWallet: ({formattedAmount}: SettleExpensifyCardParams) => (formattedAmount ? `Betaal ${formattedAmount} met wallet` : `Betalen met wallet`),
+        settlePayment: ({formattedAmount}: SettleExpensifyCardParams) => `Betaal ${formattedAmount}`,
+        settleBusiness: ({formattedAmount}: SettleExpensifyCardParams) => (formattedAmount ? `Betaal ${formattedAmount} als bedrijf` : `Betalen met zakelijke rekening`),
+        payElsewhere: ({formattedAmount}: SettleExpensifyCardParams) => (formattedAmount ? `Markeer ${formattedAmount} als betaald` : `Markeren als betaald`),
         settleInvoicePersonal: (amount?: string, last4Digits?: string) => (amount ? `heeft ${amount} betaald met persoonlijke rekening ${last4Digits}` : `Betaald met privérekening`),
         settleInvoiceBusiness: (amount?: string, last4Digits?: string) => (amount ? `heeft ${amount} betaald met zakelijke rekening ${last4Digits}` : `Betaald met zakelijke rekening`),
-        payWithPolicy: (policyName: string, formattedAmount?: string) => (formattedAmount ? `Betaal ${formattedAmount} via ${policyName}` : `Betaal via ${policyName}`),
+        payWithPolicy: ({
+            formattedAmount,
+            policyName,
+        }: SettleExpensifyCardParams & {
+            policyName: string;
+        }) => (formattedAmount ? `Betaal ${formattedAmount} via ${policyName}` : `Betaal via ${policyName}`),
         businessBankAccount: (amount?: string, last4Digits?: string) => (amount ? `heeft ${amount} betaald met bankrekening ${last4Digits}` : `betaald met bankrekening ${last4Digits}`),
         automaticallyPaidWithBusinessBankAccount: (amount?: string, last4Digits?: string) =>
             `betaald ${amount ? `${amount} ` : ''} met bankrekening ${last4Digits} via <a href="${CONST.CONFIGURE_EXPENSE_REPORT_RULES_HELP_URL}">werkruimteregels</a>`,
@@ -1344,16 +1285,16 @@ const translations: TranslationDeepObject<typeof en> = {
         nextStep: 'Volgende stappen',
         finished: 'Voltooid',
         flip: 'Omkeren',
-        sendInvoice: (amount: string) => `Verzend factuur van ${amount}`,
+        sendInvoice: ({amount}: RequestAmountParams) => `Verzend factuur van ${amount}`,
         expenseAmount: (formattedAmount: string, comment?: string) => `${formattedAmount}${comment ? `voor ${comment}` : ''}`,
-        submitted: (memo?: string) => `ingediend${memo ? `, met de omschrijving ${memo}` : ''}`,
+        submitted: ({memo}: SubmittedWithMemoParams) => `ingediend${memo ? `, met de omschrijving ${memo}` : ''}`,
         automaticallySubmitted: `ingediend via <a href="${CONST.SELECT_WORKFLOWS_HELP_URL}">uitgestelde indieningen</a>`,
         queuedToSubmitViaDEW: 'in wachtrij om via aangepast goedkeuringsproces in te dienen',
         queuedToApproveViaDEW: 'in de wachtrij gezet voor goedkeuring via aangepaste goedkeuringsworkflow',
         trackedAmount: (formattedAmount: string, comment?: string) => `volgt ${formattedAmount}${comment ? `voor ${comment}` : ''}`,
-        splitAmount: (amount: string) => `verdeel ${amount}`,
-        didSplitAmount: (formattedAmount: string, comment?: string) => `splitsen ${formattedAmount}${comment ? `voor ${comment}` : ''}`,
-        yourSplit: (amount: string) => `Jouw deel ${amount}`,
+        splitAmount: ({amount}: SplitAmountParams) => `verdeel ${amount}`,
+        didSplitAmount: (formattedAmount: string, comment: string) => `splitsen ${formattedAmount}${comment ? `voor ${comment}` : ''}`,
+        yourSplit: ({amount}: UserSplitParams) => `Jouw deel ${amount}`,
         payerOwesAmount: (amount: number | string, payer: string, comment?: string) => `${payer} is ${amount}${comment ? `voor ${comment}` : ''} verschuldigd`,
         payerOwes: (payer: string) => `${payer} is nog verschuldigd:`,
         payerPaidAmount: (amount: number | string, payer?: string) => `${payer ? `${payer} ` : ''}heeft ${amount} betaald`,
@@ -1369,70 +1310,33 @@ const translations: TranslationDeepObject<typeof en> = {
         approvedMessage: `goedgekeurd`,
         unapproved: `niet-goedgekeurd`,
         automaticallyForwarded: `goedgekeurd via <a href="${CONST.CONFIGURE_EXPENSE_REPORT_RULES_HELP_URL}">werkruimteregels</a>`,
-        forwarded: (memo?: string) => `goedgekeurd${memo ? `, met de omschrijving ${memo}` : ''}`,
-        rejectedThisReport: 'afgekeurd',
-        waitingOnBankAccount: (submitterDisplayName: string) => `is een betaling gestart, maar wacht tot ${submitterDisplayName} een bankrekening toevoegt.`,
+        forwarded: `goedgekeurd`,
+        rejectedThisReport: 'heeft dit rapport afgekeurd',
+        waitingOnBankAccount: ({submitterDisplayName}: WaitingOnBankAccountParams) => `is een betaling gestart, maar wacht tot ${submitterDisplayName} een bankrekening toevoegt.`,
         adminCanceledRequest: 'heeft de betaling geannuleerd',
         canceledRequest: (amount: string, submitterDisplayName: string) =>
             `heeft de betaling van ${amount} geannuleerd, omdat ${submitterDisplayName} hun Expensify Wallet niet binnen 30 dagen heeft geactiveerd`,
-        settledAfterAddedBankAccount: (submitterDisplayName: string, amount: string) => `${submitterDisplayName} heeft een bankrekening toegevoegd. De betaling van ${amount} is voltooid.`,
+        settledAfterAddedBankAccount: ({submitterDisplayName, amount}: SettledAfterAddedBankAccountParams) =>
+            `${submitterDisplayName} heeft een bankrekening toegevoegd. De betaling van ${amount} is voltooid.`,
         paidElsewhere: ({payer, comment}: PaidElsewhereParams = {}) => `${payer ? `${payer} ` : ''}gemarkeerd als betaald${comment ? `, met de opmerking: "${comment}"` : ''}`,
         paidWithExpensify: (payer?: string) => `${payer ? `${payer} ` : ''}betaald met wallet`,
         automaticallyPaidWithExpensify: (payer?: string) =>
             `${payer ? `${payer} ` : ''}betaald met Expensify via <a href="${CONST.CONFIGURE_EXPENSE_REPORT_RULES_HELP_URL}">werkruimteregels</a>`,
-        reimbursedThisReport: 'heeft dit rapport terugbetaald',
-        paidThisBill: 'heeft deze rekening betaald',
-        reimbursedOnBehalfOf: (actor: string) => `namens ${actor}`,
-        reimbursedFromBankAccount: (debitBankAccount: string) => `van de bankrekening die eindigt op ${debitBankAccount}`,
-        reimbursedSubmitterAddedBankAccount: (submitter: string) => `${submitter} heeft een bankrekening toegevoegd en het rapport van de wachtlijst gehaald. Terugbetaling is gestart`,
-        reimbursedWithFastACH: ({
-            isCurrentUser,
-            submitterLogin,
-            creditBankAccount,
-            expectedDate,
-        }: {
-            isCurrentUser: boolean;
-            submitterLogin: string;
-            creditBankAccount: string;
-            expectedDate: string;
-        }) =>
-            isCurrentUser
-                ? `. Geld is onderweg naar je ${creditBankAccount ? `bankrekening eindigend op ${creditBankAccount}` : 'rekening'}. Terugbetaling wordt naar verwachting afgerond op ${expectedDate}.`
-                : `. Geld is onderweg naar de bankrekening van ${submitterLogin}${creditBankAccount ? ` eindigend op ${creditBankAccount}` : ''}. Terugbetaling wordt naar verwachting afgerond op ${expectedDate}.`,
-        reimbursedWithCheck: ' via cheque.',
-        reimbursedWithStripeConnect: ({
-            isCurrentUser,
-            submitterLogin,
-            creditBankAccount,
-            isCard,
-        }: {
-            isCurrentUser: boolean;
-            submitterLogin: string;
-            creditBankAccount: string;
-            isCard: boolean;
-        }) => {
-            const paymentMethod = isCard ? 'kaart' : 'bankrekening';
-            return isCurrentUser
-                ? `. Het geld is onderweg naar je ${creditBankAccount ? `bankrekening eindigend op ${creditBankAccount}` : 'rekening'} (betaald via ${paymentMethod}). Dit kan tot 10 werkdagen duren.`
-                : `. Geld is onderweg naar de bankrekening van ${submitterLogin}${creditBankAccount ? ` eindigend op ${creditBankAccount}` : ''} (betaald via ${paymentMethod}). Dit kan tot 10 werkdagen duren.`;
-        },
-        reimbursedWithACH: ({creditBankAccount, expectedDate}: {creditBankAccount?: string; expectedDate?: string}) =>
-            ` met directe storting (ACH)${creditBankAccount ? ` naar de bankrekening die eindigt op ${creditBankAccount}.` : '. '}${expectedDate ? `De terugbetaling wordt naar verwachting voltooid op ${expectedDate}.` : 'Dit duurt meestal 4-5 werkdagen.'}`,
         noReimbursableExpenses: 'Dit rapport bevat een ongeldig bedrag',
         pendingConversionMessage: 'Totaal wordt bijgewerkt zodra je weer online bent',
         changedTheExpense: 'heeft de uitgave gewijzigd',
-        setTheRequest: (valueName: string, newValueToDisplay: string) => `de ${valueName} naar ${newValueToDisplay}`,
-        setTheDistanceMerchant: (translatedChangedField: string, newMerchant: string, newAmountToDisplay: string) =>
+        setTheRequest: ({valueName, newValueToDisplay}: SetTheRequestParams) => `de ${valueName} naar ${newValueToDisplay}`,
+        setTheDistanceMerchant: ({translatedChangedField, newMerchant, newAmountToDisplay}: SetTheDistanceMerchantParams) =>
             `stel ${translatedChangedField} in op ${newMerchant}, waarmee het bedrag is ingesteld op ${newAmountToDisplay}`,
         removedTheRequest: (valueName: string, oldValueToDisplay: string) => `de ${valueName} (voorheen ${oldValueToDisplay})`,
-        updatedTheRequest: (valueName: string, newValueToDisplay: string, oldValueToDisplay: string) => `de ${valueName} in ${newValueToDisplay} (voorheen ${oldValueToDisplay})`,
-        updatedTheDistanceMerchant: (translatedChangedField: string, newMerchant: string, oldMerchant: string, newAmountToDisplay: string, oldAmountToDisplay: string) =>
+        updatedTheRequest: ({valueName, newValueToDisplay, oldValueToDisplay}: UpdatedTheRequestParams) => `de ${valueName} in ${newValueToDisplay} (voorheen ${oldValueToDisplay})`,
+        updatedTheDistanceMerchant: ({translatedChangedField, newMerchant, oldMerchant, newAmountToDisplay, oldAmountToDisplay}: UpdatedTheDistanceMerchantParams) =>
             `heeft ${translatedChangedField} gewijzigd in ${newMerchant} (voorheen ${oldMerchant}), waardoor het bedrag is bijgewerkt naar ${newAmountToDisplay} (voorheen ${oldAmountToDisplay})`,
         basedOnAI: 'op basis van eerdere activiteit',
         basedOnMCC: ({rulesLink}: {rulesLink: string}) => (rulesLink ? `op basis van <a href="${rulesLink}">werkruimteregels</a>` : 'op basis van werkruimteregel'),
-        threadExpenseReportName: (formattedAmount: string, comment?: string) => `${formattedAmount} ${comment ? `voor ${comment}` : 'uitgave'}`,
+        threadExpenseReportName: ({formattedAmount, comment}: ThreadRequestReportNameParams) => `${formattedAmount} ${comment ? `voor ${comment}` : 'uitgave'}`,
         invoiceReportName: ({linkedReportID}: OriginalMessage<typeof CONST.REPORT.ACTIONS.TYPE.REPORT_PREVIEW>) => `Factuurrapport nr. ${linkedReportID}`,
-        threadPaySomeoneReportName: (formattedAmount: string, comment?: string) => `${formattedAmount} verzonden${comment ? `voor ${comment}` : ''}`,
+        threadPaySomeoneReportName: ({formattedAmount, comment}: ThreadSentMoneyReportNameParams) => `${formattedAmount} verzonden${comment ? `voor ${comment}` : ''}`,
         movedFromPersonalSpace: ({reportName, workspaceName}: MovedFromPersonalSpaceParams) =>
             `heeft uitgave verplaatst van persoonlijke ruimte naar ${workspaceName ?? `chat met ${reportName}`}`,
         movedToPersonalSpace: 'heeft uitgave verplaatst naar persoonlijke ruimte',
@@ -1441,14 +1345,10 @@ const translations: TranslationDeepObject<typeof en> = {
             invalidTagLength: 'De tagnaam is langer dan 255 tekens. Maak deze korter of kies een andere tag.',
             invalidAmount: 'Voer een geldig bedrag in voordat je doorgaat',
             invalidDistance: 'Voer een geldige afstand in voordat je verdergaat',
-            invalidReadings: 'Voer zowel de begin- als eindstanden in voordat je doorgaat',
+            invalidReadings: 'Voer zowel de begin- als eindstanden in',
             negativeDistanceNotAllowed: 'Eindstand moet hoger zijn dan beginstand',
-            distanceAmountTooLarge: 'Het totale bedrag is te hoog. Verlaag de afstand of verlaag het tarief.',
-            distanceAmountTooLargeReduceDistance: 'Het totale bedrag is te hoog. Verlaag de afstand.',
-            distanceAmountTooLargeReduceRate: 'Het totale bedrag is te hoog. Verlaag het tarief.',
-            odometerReadingTooLarge: (formattedMax: string) => `Kilometertellerstanden mogen niet hoger zijn dan ${formattedMax}.`,
             invalidIntegerAmount: 'Voer een volledig dollarbedrag in voordat je doorgaat',
-            invalidTaxAmount: (amount: string) => `Maximale belastingbedrag is ${amount}`,
+            invalidTaxAmount: ({amount}: RequestAmountParams) => `Maximale belastingbedrag is ${amount}`,
             invalidSplit: 'De som van de splitsingen moet gelijk zijn aan het totale bedrag',
             invalidSplitParticipants: 'Voer een bedrag groter dan nul in voor minstens twee deelnemers',
             invalidSplitYourself: 'Voer een ander bedrag dan nul in voor je verdeling',
@@ -1461,8 +1361,6 @@ const translations: TranslationDeepObject<typeof en> = {
             receiptDeleteFailureError: 'Onverwachte fout bij het verwijderen van deze bon. Probeer het later opnieuw.',
             receiptFailureMessage: '<rbr>Er is een fout opgetreden bij het uploaden van je bon. <a href="download">Sla de bon op</a> en <a href="retry">probeer het later opnieuw</a>.</rbr>',
             receiptFailureMessageShort: 'Er is een fout opgetreden bij het uploaden van je bon.',
-            receiptUploadFailedMessage: 'Uploaden van bon mislukt. Sla de bon op of verwijder de uitgave en verlies hem.',
-            saveReceipt: 'Bon opslaan',
             genericDeleteFailureMessage: 'Onverwachte fout bij het verwijderen van deze uitgave. Probeer het later opnieuw.',
             genericEditFailureMessage: 'Onverwachte fout bij het bewerken van deze uitgave. Probeer het later opnieuw.',
             genericSmartscanFailureMessage: 'Transactie mist velden',
@@ -1479,14 +1377,11 @@ const translations: TranslationDeepObject<typeof en> = {
             endDateSameAsStartDate: 'De einddatum mag niet gelijk zijn aan de startdatum',
             manySplitsProvided: `Het maximale aantal toegestane splitsingen is ${CONST.IOU.SPLITS_LIMIT}.`,
             dateRangeExceedsMaxDays: `Het datumbereik mag niet meer dan ${CONST.IOU.SPLITS_LIMIT} dagen zijn.`,
-            unableToSubmitReport: 'Rapport kan niet worden ingediend',
-            allTransactionsPendingDescription: 'Je kunt dit rapport niet indienen omdat alle transacties in behandeling zijn. Het kan een paar dagen duren voordat ze worden verwerkt.',
-            stitchOdometerImagesFailed: 'Odometerafbeeldingen combineren mislukt. Probeer het later opnieuw.',
-            failedToSaveOdometerDraft: 'De conceptkilometerstand kon niet worden opgeslagen. Probeer het opnieuw.',
         },
         dismissReceiptError: 'Foutmelding sluiten',
         dismissReceiptErrorConfirmation: 'Let op! Dit foutbericht negeren verwijdert je geüploade bon volledig. Weet je het zeker?',
-        waitingOnEnabledWallet: (submitterDisplayName: string) => `is begonnen met afrekenen. Betaling wordt vastgehouden totdat ${submitterDisplayName} hun wallet inschakelt.`,
+        waitingOnEnabledWallet: ({submitterDisplayName}: WaitingOnBankAccountParams) =>
+            `is begonnen met afrekenen. Betaling wordt vastgehouden totdat ${submitterDisplayName} hun wallet inschakelt.`,
         enableWallet: 'Portemonnee inschakelen',
         hold: 'Vasthouden',
         unhold: 'Blokkering opheffen',
@@ -1498,20 +1393,16 @@ const translations: TranslationDeepObject<typeof en> = {
         heldExpense: 'heeft deze uitgave vastgehouden',
         unheldExpense: 'heeft deze uitgave vrijgegeven',
         moveUnreportedExpense: 'Niet-gerapporteerde uitgave verplaatsen',
-        addExistingExpense: 'Bestaande uitgave toevoegen',
-        selectExistingExpense: 'Selecteer minimaal één uitgave om aan het rapport toe te voegen.',
-        emptyStateExistingExpenseTitle: 'Geen bestaande uitgaven',
-        emptyStateExistingExpenseSubtitle: 'Het lijkt erop dat je geen bestaande uitgaven hebt. Probeer er hieronder een aan te maken.',
-        addExistingExpenseConfirm: 'Aan rapport toevoegen',
+        addUnreportedExpense: 'Niet-gerapporteerde uitgave toevoegen',
+        selectUnreportedExpense: 'Selecteer minimaal één uitgave om aan het rapport toe te voegen.',
+        emptyStateUnreportedExpenseTitle: 'Geen niet-gerapporteerde uitgaven',
+        emptyStateUnreportedExpenseSubtitle: 'Het lijkt erop dat je geen niet-gerapporteerde uitgaven hebt. Probeer er hieronder een aan te maken.',
+        addUnreportedExpenseConfirm: 'Aan rapport toevoegen',
         newReport: 'Nieuw rapport',
         explainHold: () => ({
             one: 'Leg uit waarom je deze uitgave aanhoudt.',
             other: 'Leg uit waarom je deze uitgaven vasthoudt.',
         }),
-        explainHoldApprover: () => ({
-            one: 'Leg uit wat je nodig hebt voordat je deze uitgave goedkeurt.',
-            other: 'Leg uit wat je nodig hebt voordat je deze uitgaven goedkeurt.',
-        }),
         retracted: 'ingetrokken',
         retract: 'Intrekken',
         reopened: 'heropend',
@@ -1527,9 +1418,6 @@ const translations: TranslationDeepObject<typeof en> = {
         someDuplicatesArePaid: 'Sommige van deze duplicaten zijn al goedgekeurd of betaald.',
         reviewDuplicates: 'Dubbele items controleren',
         keepAll: 'Alles behouden',
-        keepSelected: 'Selectie behouden',
-        noDuplicatesTitle: 'Alles in orde!',
-        noDuplicatesDescription: 'Er zijn hier geen dubbele transacties om te beoordelen.',
         confirmApprove: 'Bevestig goedkeuringsbedrag',
         confirmApprovalAmount: 'Keur alleen conforme uitgaven goed, of keur het hele rapport goed.',
         confirmApprovalAllHoldAmount: () => ({
@@ -1563,7 +1451,7 @@ const translations: TranslationDeepObject<typeof en> = {
         unapprove: 'Intrekken goedkeuring',
         unapproveReport: 'Goedkeuring rapport intrekken',
         headsUp: 'Let op!',
-        unapproveWithIntegrationWarning: (accountingIntegration: string) =>
+        unapproveWithIntegrationWarning: ({accountingIntegration}: UnapproveWithIntegrationWarningParams) =>
             `Dit rapport is al geëxporteerd naar ${accountingIntegration}. Het wijzigen ervan kan leiden tot gegevensafwijkingen. Weet je zeker dat je dit rapport wilt afkeuren?`,
         reimbursable: 'vergoedbaar',
         nonReimbursable: 'niet-vergoedbaar',
@@ -1572,7 +1460,6 @@ const translations: TranslationDeepObject<typeof en> = {
         bookingArchived: 'Deze boeking is gearchiveerd',
         bookingArchivedDescription: 'Deze boeking is gearchiveerd omdat de reisdatum is verstreken. Voeg indien nodig een uitgave toe voor het eindbedrag.',
         attendees: 'Deelnemers',
-        totalPerAttendee: 'Per deelnemer',
         whoIsYourAccountant: 'Wie is jouw accountant?',
         paymentComplete: 'Betaling voltooid',
         time: 'Tijd',
@@ -1599,7 +1486,7 @@ const translations: TranslationDeepObject<typeof en> = {
         }),
         dates: 'Datums',
         rates: 'Tarieven',
-        submitsTo: (name: string) => `Dient in bij ${name}`,
+        submitsTo: ({name}: SubmitsToParams) => `Dient in bij ${name}`,
         reject: {
             educationalTitle: 'Moet je vasthouden of afwijzen?',
             educationalText: 'Als je nog niet klaar bent om een uitgave goed te keuren of te betalen, kun je deze in de wacht zetten of afwijzen.',
@@ -1608,7 +1495,7 @@ const translations: TranslationDeepObject<typeof en> = {
             heldExpenseLeftBehindTitle: 'Vaste uitgaven blijven achter wanneer je een volledig rapport goedkeurt.',
             rejectExpenseTitle: 'Wijs een uitgave af die je niet van plan bent goed te keuren of te betalen.',
             reasonPageTitle: 'Uitgave afwijzen',
-            reasonPageDescription: 'Leg uit waarom je deze uitgave niet zult goedkeuren.',
+            reasonPageDescription: 'Leg uit waarom je deze declaratie afwijst.',
             rejectReason: 'Reden van afwijzing',
             markAsResolved: 'Markeren als opgelost',
             rejectedStatus: 'Deze uitgave is afgewezen. We wachten tot jij de problemen oplost en als opgelost markeert, zodat je deze opnieuw kunt indienen.',
@@ -1617,26 +1504,13 @@ const translations: TranslationDeepObject<typeof en> = {
                 markedAsResolved: 'heeft de afwijsreden als opgelost gemarkeerd',
             },
         },
-        rejectReport: {
-            title: 'Rapport afwijzen',
-            description: 'Leg uit waarom je dit rapport niet goedkeurt:',
-            rejectReason: 'Reden van afwijzing',
-            selectTarget: 'Kies het lid naar wie je dit rapport wilt afkeuren voor beoordeling:',
-            lastApprover: 'Laatste fiatteur',
-            submitter: 'Indiener',
-            rejectedReportMessage: 'Dit rapport is afgewezen.',
-            rejectedNextStep: 'Dit rapport is afgekeurd. We wachten tot jij de problemen oplost en het handmatig opnieuw indient.',
-            selectMemberError: 'Selecteer een lid om dit rapport naar terug te sturen.',
-            couldNotReject: 'Het rapport kon niet worden afgewezen. Probeer het opnieuw.',
-        },
-        moveExpenses: 'Verplaatsen naar rapport',
+        moveExpenses: () => ({one: 'Kosten verplaatsen', other: 'Declaraties verplaatsen'}),
         moveExpensesError: 'Je kunt dagvergoedingdeclaraties niet naar rapporten in andere werkruimten verplaatsen, omdat de dagvergoedingsbedragen per werkruimte kunnen verschillen.',
         changeApprover: {
             title: 'Goedkeurder wijzigen',
-            header: (workflowSettingLink: string) =>
+            header: ({workflowSettingLink}: WorkflowSettingsParam) =>
                 `Kies een optie om de fiatteur voor dit rapport te wijzigen. (Werk je <a href="${workflowSettingLink}">werkruimteninstellingen</a> bij om dit permanent voor alle rapporten te wijzigen.)`,
             changedApproverMessage: (managerID: number) => `heeft de goedkeurder gewijzigd naar <mention-user accountID="${managerID}"/>`,
-            reassignedApproverMessage: (managerID: number) => `heeft de goedkeurder opnieuw toegewezen aan <mention-user accountID="${managerID}"/> via een workflow-update`,
             actions: {
                 addApprover: 'Goedkeurder toevoegen',
                 addApproverSubtitle: 'Voeg een extra fiatteur toe aan de bestaande workflow.',
@@ -1645,12 +1519,10 @@ const translations: TranslationDeepObject<typeof en> = {
             },
             addApprover: {
                 subtitle: 'Kies een extra fiatteur voor dit rapport voordat we het door de rest van de fiatteringsworkflow sturen.',
-                bulkSubtitle: 'Kies een extra fiatteur voor deze rapporten voordat we ze door de rest van de goedkeuringsworkflow sturen.',
             },
-            bulkSubtitle: 'Kies een optie om de fiatteur voor deze rapporten te wijzigen.',
         },
         chooseWorkspace: 'Kies een werkruimte',
-        routedDueToDEW: (to: string, reason?: string) => `rapport doorgestuurd naar ${to}${reason ? ` omdat ${reason}` : ''}`,
+        routedDueToDEW: ({to}: RoutedDueToDEWParams) => `rapport doorgestuurd naar ${to} vanwege aangepast goedkeuringsworkflow`,
         timeTracking: {
             hoursAt: (hours: number, rate: string) => `${hours} ${hours === 1 ? 'uur' : 'uren'} @ ${rate} / uur`,
             hrs: 'uur',
@@ -1658,33 +1530,34 @@ const translations: TranslationDeepObject<typeof en> = {
             ratePreview: (rate: string) => `${rate} / uur`,
             amountTooLargeError: 'Het totale bedrag is te hoog. Verlaag het aantal uren of verlaag het tarief.',
         },
-        correctRateError: 'Los de tarieffout op en probeer het opnieuw.',
-        AskToExplain: `. <a href="${CONST.CONCIERGE_EXPLAIN_LINK_PATH}">Uitleggen<sparkles-icon/></a>`,
-        duplicateNonDefaultWorkspacePerDiemError: 'Je kunt dagvergoedingen niet dupliceren tussen werkruimtes, omdat de tarieven per werkruimte kunnen verschillen.',
-        rulesModifiedFields: {
-            reimbursable: (value: boolean) => (value ? 'markeerde de uitgave als „terugbetaalbaar”' : 'heeft de uitgave als ‘niet-vergoedbaar’ gemarkeerd'),
-            billable: (value: boolean) => (value ? `heeft de uitgave gemarkeerd als ‘door te belasten’` : `heeft de uitgave gemarkeerd als ‘niet factureerbaar’`),
-            tax: (value: string, isFirst: boolean) => (isFirst ? `stel het belastingtarief in op „${value}”` : `belastingtarief naar „${value}”`),
-            reportName: (value: string) => `heeft deze uitgave verplaatst naar rapport „${value}”`,
-            common: (key: keyof PolicyRulesModifiedFields | keyof PersonalRulesModifiedFields, value: string, isFirst: boolean) => {
-                const field = translations.common[key].toLowerCase();
-                return isFirst ? `stel de ${field} in op "${value}"` : `${field} naar "${value}"`;
-            },
-            formatPersonalRules: (fragments: string, route: string) => `${fragments} via <a href="${route}">persoonlijke onkostregels</a>`,
-            formatPolicyRules: (fragments: string, route: string) => `${fragments} via <a href="${route}">werkruimte­regels</a>`,
-        },
-        failedToAutoSubmitViaDEW: (reason: string) => `rapport indienen via <a href="${CONST.SELECT_WORKFLOWS_HELP_URL}">indiening uitstellen</a> is mislukt. ${reason}`,
-        failedToSubmitViaDEW: (reason: string) => `het is niet gelukt om het rapport in te dienen. ${reason}`,
-        failedToAutoApproveViaDEW: (reason: string) => `goedkeuren via <a href="${CONST.CONFIGURE_EXPENSE_REPORT_RULES_HELP_URL}">werkruimte­regels</a> is mislukt. ${reason}`,
-        failedToApproveViaDEW: (reason: string) => `goedkeuren mislukt. ${reason}`,
-        cannotDuplicateDistanceExpense: 'Je kunt afstandsvergoedingen niet dupliceren tussen werkruimtes, omdat de tarieven per werkruimte kunnen verschillen.',
-        taxDisabledAlert: {
-            title: 'Belasting uitgeschakeld',
-            prompt: 'Schakel belastingregistratie in voor de workspace om de onkostendetails te bewerken of de belasting uit deze onkostendeclaratie te verwijderen.',
-            confirmText: 'Belasting verwijderen',
-        },
-        bulkDuplicateLimit: `Je kunt maximaal ${CONST.SEARCH.BULK_DUPLICATE_LIMIT} uitgaven tegelijk dupliceren. Selecteer minder uitgaven en probeer het opnieuw.`,
-        deleted: 'Verwijderd',
+        correctDistanceRateError: 'Los het foutieve afstandstarief op en probeer het opnieuw.',
+        AskToExplain: `. <a href="${CONST.CONCIERGE_EXPLAIN_LINK_PATH}"><strong>Uitleggen</strong></a> &#x2728;`,
+        policyRulesModifiedFields: (policyRulesModifiedFields: PolicyRulesModifiedFields, policyRulesRoute: string, formatList: (list: string[]) => string) => {
+            const entries = ObjectUtils.typedEntries(policyRulesModifiedFields);
+            const fragments = entries.map(([key, value], i) => {
+                const isFirst = i === 0;
+                if (key === 'reimbursable') {
+                    return value ? 'heeft de uitgave gemarkeerd als „vergoedbaar”' : 'markeerde de uitgave als ‘niet-terugbetaalbaar’';
+                }
+                if (key === 'billable') {
+                    return value ? 'heeft de uitgave gemarkeerd als ‘door te belasten’' : 'heeft de uitgave gemarkeerd als ‘niet factureerbaar’';
+                }
+                if (key === 'tax') {
+                    const taxEntry = value as PolicyRulesModifiedFields['tax'];
+                    const taxRateName = taxEntry?.field_id_TAX.name ?? '';
+                    if (isFirst) {
+                        return `stel het belastingtarief in op „${taxRateName}”`;
+                    }
+                    return `belastingtarief naar „${taxRateName}”`;
+                }
+                const updatedValue = value as string | boolean;
+                if (isFirst) {
+                    return `stel de ${translations.common[key].toLowerCase()} in op "${updatedValue}"`;
+                }
+                return `${translations.common[key].toLowerCase()} naar "${updatedValue}"`;
+            });
+            return `${formatList(fragments)} via <a href="${policyRulesRoute}">werkruimte­regels</a>`;
+        },
     },
     transactionMerge: {
         listPage: {
@@ -1757,112 +1630,72 @@ const translations: TranslationDeepObject<typeof en> = {
     },
     nextStep: {
         message: {
-            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_TO_ADD_TRANSACTIONS]: (
-                actor: string,
-                actorType: ValueOf<typeof CONST.NEXT_STEP.ACTOR_TYPE>,
-                _eta?: string,
-                _etaType?: ValueOf<typeof CONST.NEXT_STEP.ETA_TYPE>,
-            ) => {
+            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_TO_ADD_TRANSACTIONS]: ({actor, actorType}: NextStepParams) => {
                 switch (actorType) {
                     case CONST.NEXT_STEP.ACTOR_TYPE.CURRENT_USER:
-                        return `Wacht tot <strong>jij</strong> uitgaven toevoegt.`;
+                        return `We wachten op <strong>jou</strong> om onkosten toe te voegen.`;
                     case CONST.NEXT_STEP.ACTOR_TYPE.OTHER_USER:
-                        return `Wachten tot <strong>${actor}</strong> uitgaven toevoegt.`;
+                        return `Wachten tot <strong>${actor}</strong> onkosten toevoegt.`;
                     case CONST.NEXT_STEP.ACTOR_TYPE.UNSPECIFIED_ADMIN:
                         return `Wachten tot een beheerder uitgaven toevoegt.`;
                 }
             },
-            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_TO_SUBMIT]: (
-                actor: string,
-                actorType: ValueOf<typeof CONST.NEXT_STEP.ACTOR_TYPE>,
-                _eta?: string,
-                _etaType?: ValueOf<typeof CONST.NEXT_STEP.ETA_TYPE>,
-            ) => {
+            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_TO_SUBMIT]: ({actor, actorType}: NextStepParams) => {
                 switch (actorType) {
                     case CONST.NEXT_STEP.ACTOR_TYPE.CURRENT_USER:
-                        return `Er wordt gewacht tot <strong>jij</strong> declaraties indient.`;
+                        return `Aan het wachten tot <strong>jij</strong> onkosten indient.`;
                     case CONST.NEXT_STEP.ACTOR_TYPE.OTHER_USER:
-                        return `Wachten tot <strong>${actor}</strong> de onkosten indient.`;
+                        return `Wachten tot <strong>${actor}</strong> onkosten indient.`;
                     case CONST.NEXT_STEP.ACTOR_TYPE.UNSPECIFIED_ADMIN:
-                        return `Wachten tot een beheerder de onkosten indient.`;
+                        return `Wachten tot een beheerder onkosten indient.`;
                 }
             },
-            [CONST.NEXT_STEP.MESSAGE_KEY.NO_FURTHER_ACTION]: (
-                _actor: string,
-                _actorType: ValueOf<typeof CONST.NEXT_STEP.ACTOR_TYPE>,
-                _eta?: string,
-                _etaType?: ValueOf<typeof CONST.NEXT_STEP.ETA_TYPE>,
-            ) => `Geen verdere actie vereist!`,
-            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_FOR_SUBMITTER_ACCOUNT]: (
-                actor: string,
-                actorType: ValueOf<typeof CONST.NEXT_STEP.ACTOR_TYPE>,
-                _eta?: string,
-                _etaType?: ValueOf<typeof CONST.NEXT_STEP.ETA_TYPE>,
-            ) => {
+            [CONST.NEXT_STEP.MESSAGE_KEY.NO_FURTHER_ACTION]: (_: NextStepParams) => `Geen verdere actie vereist!`,
+            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_FOR_SUBMITTER_ACCOUNT]: ({actor, actorType}: NextStepParams) => {
                 switch (actorType) {
                     case CONST.NEXT_STEP.ACTOR_TYPE.CURRENT_USER:
-                        return `Er wordt gewacht tot <strong>jij</strong> een bankrekening toevoegt.`;
+                        return `Wachten tot <strong>jij</strong> een bankrekening toevoegt.`;
                     case CONST.NEXT_STEP.ACTOR_TYPE.OTHER_USER:
                         return `Wachten tot <strong>${actor}</strong> een bankrekening toevoegt.`;
                     case CONST.NEXT_STEP.ACTOR_TYPE.UNSPECIFIED_ADMIN:
                         return `Wachten tot een beheerder een bankrekening toevoegt.`;
                 }
             },
-            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_FOR_AUTOMATIC_SUBMIT]: (
-                actor: string,
-                actorType: ValueOf<typeof CONST.NEXT_STEP.ACTOR_TYPE>,
-                eta?: string,
-                etaType?: ValueOf<typeof CONST.NEXT_STEP.ETA_TYPE>,
-            ) => {
+            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_FOR_AUTOMATIC_SUBMIT]: ({actor, actorType, eta, etaType}: NextStepParams) => {
                 let formattedETA = '';
                 if (eta) {
-                    formattedETA = etaType === CONST.NEXT_STEP.ETA_TYPE.DATE_TIME ? `op de ${eta} van elke maand` : ` ${eta}`;
+                    formattedETA = etaType === CONST.NEXT_STEP.ETA_TYPE.DATE_TIME ? `op ${eta}` : ` ${eta}`;
                 }
                 switch (actorType) {
                     case CONST.NEXT_STEP.ACTOR_TYPE.CURRENT_USER:
-                        return `Wachten tot <strong>jouw</strong> uitgaven automatisch worden ingediend${formattedETA}.`;
+                        return `Wachten tot <strong>je</strong> declaraties automatisch worden ingediend${formattedETA}.`;
                     case CONST.NEXT_STEP.ACTOR_TYPE.OTHER_USER:
-                        return `Wachten tot de onkosten van <strong>${actor}</strong> automatisch worden ingediend${formattedETA}.`;
+                        return `Wachten tot de uitgaven van <strong>${actor}</strong> automatisch worden ingediend${formattedETA}.`;
                     case CONST.NEXT_STEP.ACTOR_TYPE.UNSPECIFIED_ADMIN:
-                        return `Wachten tot de onkostendeclaraties van een beheerder automatisch worden ingediend${formattedETA}.`;
+                        return `Wachten tot de onkosten van een beheerder automatisch worden ingediend${formattedETA}.`;
                 }
             },
-            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_TO_FIX_ISSUES]: (
-                actor: string,
-                actorType: ValueOf<typeof CONST.NEXT_STEP.ACTOR_TYPE>,
-                _eta?: string,
-                _etaType?: ValueOf<typeof CONST.NEXT_STEP.ETA_TYPE>,
-            ) => {
+            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_TO_FIX_ISSUES]: ({actor, actorType}: NextStepParams) => {
                 switch (actorType) {
                     case CONST.NEXT_STEP.ACTOR_TYPE.CURRENT_USER:
-                        return `We wachten op <strong>jou</strong> om de problemen op te lossen.`;
+                        return `Wacht tot <strong>jij</strong> de problemen oplost.`;
                     case CONST.NEXT_STEP.ACTOR_TYPE.OTHER_USER:
                         return `Wachten tot <strong>${actor}</strong> de problemen oplost.`;
                     case CONST.NEXT_STEP.ACTOR_TYPE.UNSPECIFIED_ADMIN:
                         return `Wachten tot een beheerder de problemen oplost.`;
                 }
             },
-            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_TO_APPROVE]: (
-                actor: string,
-                actorType: ValueOf<typeof CONST.NEXT_STEP.ACTOR_TYPE>,
-                _eta?: string,
-                _etaType?: ValueOf<typeof CONST.NEXT_STEP.ETA_TYPE>,
-            ) => {
+            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_TO_APPROVE]: ({actor, actorType}: NextStepParams) => {
                 switch (actorType) {
                     case CONST.NEXT_STEP.ACTOR_TYPE.CURRENT_USER:
-                        return `Wacht tot <strong>jij</strong> de onkosten goedkeurt.`;
+                        return `Wacht tot <strong>jij</strong> de declaraties goedkeurt.`;
                     case CONST.NEXT_STEP.ACTOR_TYPE.OTHER_USER:
-                        return `Wachten tot <strong>${actor}</strong> de uitgaven goedkeurt.`;
+                        return `Wachten tot <strong>${actor}</strong> de onkosten goedkeurt.`;
                     case CONST.NEXT_STEP.ACTOR_TYPE.UNSPECIFIED_ADMIN:
-                        return `Wachten op goedkeuring van uitgaven door een beheerder.`;
+                        return `Wachten op goedkeuring van de onkosten door een beheerder.`;
                 }
             },
-            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_TO_EXPORT]: (
-                actor: string,
-                actorType: ValueOf<typeof CONST.NEXT_STEP.ACTOR_TYPE>,
-                _eta?: string,
-                _etaType?: ValueOf<typeof CONST.NEXT_STEP.ETA_TYPE>,
-            ) => {
+            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_TO_EXPORT]: ({actor, actorType}: NextStepParams) => {
                 switch (actorType) {
                     case CONST.NEXT_STEP.ACTOR_TYPE.CURRENT_USER:
                         return `We wachten op <strong>jou</strong> om dit rapport te exporteren.`;
@@ -1872,70 +1705,35 @@ const translations: TranslationDeepObject<typeof en> = {
                         return `Wachten tot een beheerder dit rapport exporteert.`;
                 }
             },
-            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_TO_PAY]: (
-                actor: string,
-                actorType: ValueOf<typeof CONST.NEXT_STEP.ACTOR_TYPE>,
-                _eta?: string,
-                _etaType?: ValueOf<typeof CONST.NEXT_STEP.ETA_TYPE>,
-            ) => {
+            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_TO_PAY]: ({actor, actorType}: NextStepParams) => {
                 switch (actorType) {
                     case CONST.NEXT_STEP.ACTOR_TYPE.CURRENT_USER:
-                        return `Wacht tot <strong>jij</strong> onkosten betaalt.`;
+                        return `Wachten tot <strong>jij</strong> de onkosten betaalt.`;
                     case CONST.NEXT_STEP.ACTOR_TYPE.OTHER_USER:
-                        return `Wachten tot <strong>${actor}</strong> de declaraties betaalt.`;
+                        return `Wachten tot <strong>${actor}</strong> de onkosten betaalt.`;
                     case CONST.NEXT_STEP.ACTOR_TYPE.UNSPECIFIED_ADMIN:
                         return `Wachten tot een beheerder de onkosten betaalt.`;
                 }
             },
-            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_FOR_POLICY_BANK_ACCOUNT]: (
-                actor: string,
-                actorType: ValueOf<typeof CONST.NEXT_STEP.ACTOR_TYPE>,
-                _eta?: string,
-                _etaType?: ValueOf<typeof CONST.NEXT_STEP.ETA_TYPE>,
-            ) => {
+            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_FOR_POLICY_BANK_ACCOUNT]: ({actor, actorType}: NextStepParams) => {
                 switch (actorType) {
                     case CONST.NEXT_STEP.ACTOR_TYPE.CURRENT_USER:
-                        return `Wachten tot <strong>je</strong> klaar bent met het instellen van een zakelijke bankrekening.`;
+                        return `Wachten tot <strong>jij</strong> het instellen van een zakelijke bankrekening afrondt.`;
                     case CONST.NEXT_STEP.ACTOR_TYPE.OTHER_USER:
                         return `Wachten tot <strong>${actor}</strong> klaar is met het instellen van een zakelijke bankrekening.`;
                     case CONST.NEXT_STEP.ACTOR_TYPE.UNSPECIFIED_ADMIN:
-                        return `Wachten tot een beheerder klaar is met het instellen van een zakelijke bankrekening.`;
+                        return `Wachten tot een beheerder het instellen van een zakelijke bankrekening afrondt.`;
                 }
             },
-            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_FOR_PAYMENT]: (
-                _actor: string,
-                _actorType: ValueOf<typeof CONST.NEXT_STEP.ACTOR_TYPE>,
-                eta?: string,
-                etaType?: ValueOf<typeof CONST.NEXT_STEP.ETA_TYPE>,
-            ) => {
+            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_FOR_PAYMENT]: ({eta, etaType}: NextStepParams) => {
                 let formattedETA = '';
                 if (eta) {
-                    formattedETA = etaType === CONST.NEXT_STEP.ETA_TYPE.DATE_TIME ? `vóór ${eta}` : ` ${eta}`;
+                    formattedETA = etaType === CONST.NEXT_STEP.ETA_TYPE.DATE_TIME ? `voor ${eta}` : ` ${eta}`;
                 }
                 return `Wachten tot de betaling is voltooid${formattedETA}.`;
             },
-            [CONST.NEXT_STEP.MESSAGE_KEY.SUBMITTING_TO_SELF]: (
-                _actor: string,
-                _actorType: ValueOf<typeof CONST.NEXT_STEP.ACTOR_TYPE>,
-                _eta?: string,
-                _etaType?: ValueOf<typeof CONST.NEXT_STEP.ETA_TYPE>,
-            ) =>
-                `Oeps! Het lijkt erop dat je deze rapportage naar <strong>jezelf</strong> indient. Het goedkeuren van je eigen rapporten is <strong>verboden</strong> door je werkruimte. Dien dit rapport in bij iemand anders of neem contact op met je admin om de persoon te wijzigen bij wie je indient.`,
-            [CONST.NEXT_STEP.MESSAGE_KEY.REJECTED_REPORT]: (
-                actor: string,
-                actorType: ValueOf<typeof CONST.NEXT_STEP.ACTOR_TYPE>,
-                _eta?: string,
-                _etaType?: ValueOf<typeof CONST.NEXT_STEP.ETA_TYPE>,
-            ) => {
-                switch (actorType) {
-                    case CONST.NEXT_STEP.ACTOR_TYPE.CURRENT_USER:
-                        return `Dit rapport is afgewezen. We wachten op <strong>jou</strong> om de problemen op te lossen en het handmatig opnieuw in te dienen.`;
-                    case CONST.NEXT_STEP.ACTOR_TYPE.OTHER_USER:
-                        return `Dit rapport is afgewezen. Wachten op <strong>${actor}</strong> om de problemen op te lossen en het handmatig opnieuw in te dienen.`;
-                    case CONST.NEXT_STEP.ACTOR_TYPE.UNSPECIFIED_ADMIN:
-                        return `Dit rapport is afgewezen. Wacht tot een beheerder de problemen oplost en het handmatig opnieuw indient.`;
-                }
-            },
+            [CONST.NEXT_STEP.MESSAGE_KEY.SUBMITTING_TO_SELF]: (_: NextStepParams) =>
+                `Oeps! Het lijkt erop dat je deze rapportage naar <strong>jezelf</strong> indient. Het goedkeuren van je eigen rapporten is <strong>verboden</strong> binnen je workspace. Dien dit rapport in bij iemand anders of neem contact op met je beheerder om de persoon te wijzigen naar wie je indient.`,
         },
         eta: {
             [CONST.NEXT_STEP.ETA_KEY.SHORTLY]: 'binnenkort',
@@ -1961,8 +1759,6 @@ const translations: TranslationDeepObject<typeof en> = {
         offline: 'Offline',
         syncing: 'Synchroniseren',
         profileAvatar: 'Profielavatar',
-        customInstructions: 'Aangepaste instructies',
-        copilotIntoAccount: 'Copilot naar account',
         publicSection: {
             title: 'Openbaar',
             subtitle: 'Deze gegevens worden weergegeven op je openbare profiel. Iedereen kan ze zien.',
@@ -1971,16 +1767,12 @@ const translations: TranslationDeepObject<typeof en> = {
             title: 'Privé',
             subtitle: 'Deze gegevens worden gebruikt voor reizen en betalingen. Ze worden nooit getoond op je openbare profiel.',
         },
-        aiPromptSection: {
-            title: 'AI-prompt',
-            subtitle: 'Schrijf aangepaste instructies',
-            prompt: 'Prompt',
-            editPrompt: 'Prompt bewerken',
-            promptCannotBeEmpty: 'Prompt mag niet leeg zijn',
-            saved: 'Opgeslagen',
-        },
     },
-    securityPage: {title: 'Beveiliging', subtitle: 'Houd je account veilig.', goToSecurity: 'Ga terug naar de beveiligingspagina'},
+    securityPage: {
+        title: 'Beveiligingsopties',
+        subtitle: 'Schakel tweeledige verificatie in om je account veilig te houden.',
+        goToSecurity: 'Ga terug naar de beveiligingspagina',
+    },
     shareCodePage: {
         title: 'Uw code',
         subtitle: 'Nodig leden uit voor Expensify door je persoonlijke QR-code of verwijzingslink te delen.',
@@ -1995,7 +1787,7 @@ const translations: TranslationDeepObject<typeof en> = {
         featureRequiresValidate: 'Voor deze functie moet je je account verifiëren.',
         validateAccount: 'Valideer je account',
         helpText: ({email}: {email: string}) =>
-            `Voeg meer manieren toe om in te loggen en bonnetjes naar Expensify te sturen.<br/><br/>Voeg een e-mailadres toe om bonnetjes door te sturen naar <a href="mailto:${email}">${email}</a> of voeg een telefoonnummer toe om bonnetjes te sms'en naar 47777 (alleen voor Amerikaanse nummers).`,
+            `Voeg meer manieren toe om in te loggen en bonnetjes naar Expensify te sturen.<br/><br/>Voeg een e-mailadres toe om bonnetjes door te sturen naar <a href="mailto:${email}">${email}</a> of voeg een telefoonnummer toe om bonnetjes te sms’en naar 47777 (alleen voor Amerikaanse nummers).`,
         pleaseVerify: 'Verifieer deze contactmethode.',
         getInTouch: 'We gebruiken deze methode om contact met je op te nemen.',
         enterMagicCode: (contactMethod: string) => `Voer de magische code in die naar ${contactMethod} is verzonden. Deze zou binnen een minuut of twee moeten aankomen.`,
@@ -2018,7 +1810,6 @@ const translations: TranslationDeepObject<typeof en> = {
         },
         newContactMethod: 'Nieuwe contactmethode',
         goBackContactMethods: 'Ga terug naar contactmethoden',
-        yourDefaultContactMethodRestrictedSwitch: 'Dit is je huidige standaardcontactmethode. Je bedrijf heeft beperkt dat je deze kunt verwijderen of wijzigen.',
     },
     pronouns: {
         coCos: 'Co / Cos',
@@ -2078,6 +1869,8 @@ const translations: TranslationDeepObject<typeof en> = {
         },
         troubleshoot: {
             clearCacheAndRestart: 'Cache wissen en opnieuw starten',
+            viewConsole: 'Debugconsole bekijken',
+            debugConsole: 'Debugconsole',
             description:
                 '<muted-text>Gebruik de onderstaande tools om problemen met de Expensify-ervaring op te lossen. Als je problemen tegenkomt, <concierge-link>dien dan een bug in</concierge-link>.</muted-text>',
             confirmResetDescription: 'Alle niet-verzonden conceptberichten gaan verloren, maar de rest van je gegevens is veilig.',
@@ -2109,47 +1902,35 @@ const translations: TranslationDeepObject<typeof en> = {
             invalidateWithDelay: 'Ongeldig maken met vertraging',
             leftHandNavCache: 'Cache linkernavigatie',
             clearleftHandNavCache: 'Wissen',
+            recordTroubleshootData: 'Probleemopsporingsgegevens opnemen',
             softKillTheApp: 'App zacht afsluiten',
             kill: 'Doden',
             sentryDebug: 'Sentry-debug',
-            sentrySendDescription: 'Gegevens naar Sentry verzenden',
             sentryDebugDescription: 'Sentry-aanvragen naar console loggen',
             sentryHighlightedSpanOps: 'Gemarkeerde span-namen',
             sentryHighlightedSpanOpsPlaceholder: 'ui.interactie.klik, navigatie, ui.laden',
-            showBranchNameInTitle: 'Toon branchnaam in titel van browser',
+        },
+        debugConsole: {
+            saveLog: 'Log opslaan',
+            shareLog: 'Log delen',
+            enterCommand: 'Voer opdracht in',
+            execute: 'Uitvoeren',
+            noLogsAvailable: 'Geen logs beschikbaar',
+            logSizeTooLarge: (size: number) => `Loggrootte overschrijdt de limiet van ${size} MB. Gebruik alstublieft "Log opslaan" om het logbestand te downloaden.`,
+            logs: 'Logboeken',
+            viewConsole: 'Console bekijken',
         },
         security: 'Beveiliging',
         signOut: 'Afmelden',
         restoreStashed: 'Opgeslagen login herstellen',
         signOutConfirmationText: 'Je verliest alle offline wijzigingen als je je afmeldt.',
         versionLetter: 'v',
-        readTheTermsAndPrivacy: `Lees de <a href="${CONST.OLD_DOT_PUBLIC_URLS.TERMS_URL}">Servicevoorwaarden</a> en het <a href="${CONST.OLD_DOT_PUBLIC_URLS.PRIVACY_URL}">Privacybeleid</a>.`,
+        readTheTermsAndPrivacy: `<muted-text-micro>Lees de <a href="${CONST.OLD_DOT_PUBLIC_URLS.TERMS_URL}">servicevoorwaarden</a> en het <a href="${CONST.OLD_DOT_PUBLIC_URLS.PRIVACY_URL}">privacybeleid</a>.</muted-text-micro>`,
         help: 'Help',
         whatIsNew: 'Wat is er nieuw',
         accountSettings: 'Accountinstellingen',
         account: 'Account',
         general: 'Algemeen',
-        helpPage: {
-            title: 'Hulp en ondersteuning',
-            description: 'We zijn er 24/7 om je te helpen.',
-            helpSite: 'Hulpwebsite',
-            helpSiteDescription: 'Artikelen, handleidingen en meer',
-            conciergeChat: 'Concierge',
-            conciergeChatDescription: 'Je persoonlijke AI-agent',
-            accountManager: 'Accountmanager',
-            yourAccountManager: 'Je accountmanager',
-            accountManagerDescription: 'Stel vragen en krijg ondersteuning voor klanten',
-            partnerManager: 'Partner Manager',
-            yourPartnerManager: 'Twój opiekun partnerski',
-            partnerManagerDescription: 'Haal het maximale uit je partnership en stimuleer verwijzingen',
-            guideDescription: 'Je accountmanager',
-            approvedPartnerTeamTitle: 'Maak kennis met je Approved!-partnerteam',
-            approvedPartnerTeamDescription:
-                'Een toegewijd team dat zich richt op het laten groeien van je bedrijf, sneller onboarden van klanten en het bieden van deskundige ondersteuning wanneer je die nodig hebt.',
-            accountExecutive: 'Accountmanager',
-            accountExecutiveDescription: 'Klanten succesvol instellen',
-            moreResources: 'Meer bronnen',
-        },
     },
     closeAccountPage: {
         closeAccount: 'Account sluiten',
@@ -2223,12 +2004,10 @@ const translations: TranslationDeepObject<typeof en> = {
         lockAccount: 'Account vergrendelen',
         unlockAccount: 'Account ontgrendelen',
         compromisedDescription:
-            'Val je iets op aan je account? Als je dit meldt, wordt je account onmiddellijk vergrendeld, worden nieuwe Expensify Kaart-transacties geblokkeerd en worden wijzigingen aan je account voorkomen.',
-        domainAdminsDescription: 'Voor domeinbeheerders: dit pauzeert ook alle Expensify Kaart-activiteit en beheerdersacties in je domein(en).',
+            'Valt je iets op aan je account? Dit melden zal je account onmiddellijk vergrendelen, nieuwe Expensify Card-transacties blokkeren en alle accountwijzigingen voorkomen.',
+        domainAdminsDescription: 'Voor domeinbeheerders: Dit pauzeert ook alle Expensify Card-activiteit en beheerdersacties in je domein(en).',
         areYouSure: 'Weet je zeker dat je je Expensify-account wilt vergrendelen?',
         onceLocked: 'Zodra deze wordt vergrendeld, wordt je account beperkt in afwachting van een deblokkeringsverzoek en een beveiligingscontrole',
-        unlockTitle: 'We hebben je verzoek ontvangen',
-        unlockDescription: 'We beoordelen de account om te verifiëren dat het veilig is om deze te ontgrendelen en nemen via Concierge contact op als we vragen hebben.',
     },
     failedToLockAccountPage: {
         failedToLockAccount: 'Account vergrendelen mislukt',
@@ -2241,35 +2020,28 @@ const translations: TranslationDeepObject<typeof en> = {
         chatToConciergeToUnlock: 'Chat met Concierge om beveiligingsproblemen op te lossen en je account te ontgrendelen.',
         chatWithConcierge: 'Chatten met Concierge',
     },
-    deviceManagementPage: {
-        title: 'Apparaatbeheer',
-        description:
-            'Beheer alle apparaten waarop je bent ingelogd met je Expensify-account. <a href="https://help.expensify.com/articles/new-expensify/settings/Manage-Logged-in-Devices">Meer informatie</a>.',
-        revoke: 'Intrekken',
-        unknownDevice: 'Onbekend Apparaat',
-    },
     twoFactorAuth: {
         headerTitle: 'Tweeledige verificatie',
         twoFactorAuthEnabled: 'Authenticatie in twee stappen ingeschakeld',
         whatIsTwoFactorAuth:
             'Tweestapsverificatie (2FA) helpt je account veilig te houden. Bij het inloggen moet je een code invoeren die is gegenereerd door je voorkeursauthenticator-app.',
         disableTwoFactorAuth: 'Tweefactorauthenticatie uitschakelen',
-        explainProcessToRemove: 'Voer een geldige code uit je authenticatie-app in om twee-factor-authenticatie (2FA) uit te schakelen.',
-        explainProcessToRemoveWithRecovery: 'Voer een geldige herstelcode in om tweeledige verificatie (2FA) uit te schakelen.',
+        explainProcessToRemove: 'Voer een geldige code uit je authenticatie-app in om tweeledige verificatie (2FA) uit te schakelen.',
+        explainProcessToRemoveWithRecovery: 'Voer een geldige herstelcode in om twee-factor-authenticatie (2FA) uit te schakelen.',
         disabled: 'Tweeledige verificatie is nu uitgeschakeld',
         noAuthenticatorApp: 'Je hebt geen authenticator-app meer nodig om in te loggen bij Expensify.',
         stepCodes: 'Herstelcodes',
-        keepCodesSafe: 'Bewaar deze codes goed!',
+        keepCodesSafe: 'Bewaar deze herstercodes goed!',
         codesLoseAccess: dedent(`
-            Als je de toegang tot je authenticator-app kwijtraakt en deze codes niet hebt, word je uit je account afgesloten.<br><br>
-            <strong>Let op</strong>: Het inschakelen van 2FA logt je uit in alle andere sessies.
+            Als je de toegang tot je authenticator-app kwijtraakt en deze codes niet hebt, verlies je de toegang tot je account.
+
+            Let op: het instellen van tweeledige verificatie zal je uitloggen bij alle andere actieve sessies.
         `),
         errorStepCodes: 'Kopieer of download de codes voordat je verdergaat',
         stepVerify: 'Verifiëren',
         scanCode: 'Scan de QR-code met je',
         authenticatorApp: 'authenticator-app',
         addKey: 'Of voeg deze geheime sleutel toe aan je authenticator-app:',
-        secretKey: 'geheime sleutel',
         enterCode: 'Voer vervolgens de zescijferige code in die is gegenereerd door je authenticator-app.',
         stepSuccess: 'Voltooid',
         enabled: 'Authenticatie in twee stappen ingeschakeld',
@@ -2285,14 +2057,6 @@ const translations: TranslationDeepObject<typeof en> = {
         twoFactorAuthIsRequiredCompany: 'Je bedrijf vereist tweefactorauthenticatie.',
         twoFactorAuthCannotDisable: 'Kan 2FA niet uitschakelen',
         twoFactorAuthRequired: 'Tweestapsverificatie (2FA) is vereist voor je Xero-verbinding en kan niet worden uitgeschakeld.',
-        replaceDevice: 'Apparaat vervangen',
-        replaceDeviceTitle: 'Tweefactorauthenticatie-apparaat vervangen',
-        verifyOldDeviceTitle: 'Oud apparaat verifiëren',
-        verifyOldDeviceDescription: 'Voer de zescijferige code uit je huidige authenticator-app in om te bevestigen dat je daar toegang toe hebt.',
-        verifyNewDeviceTitle: 'Nieuw apparaat instellen',
-        verifyNewDeviceDescription: 'Scan de QR-code met je nieuwe apparaat en voer daarna de code in om de installatie te voltooien.',
-        downloadCodes: 'Codes downloaden',
-        copyCodes: 'Codes kopiëren',
     },
     recoveryCodeForm: {
         error: {
@@ -2380,39 +2144,6 @@ const translations: TranslationDeepObject<typeof en> = {
             password: 'Voer je Expensify-wachtwoord in',
         },
     },
-    personalCard: {
-        addPersonalCard: 'Persoonlijke kaart toevoegen',
-        addCompanyCard: 'Bedrijfskaart toevoegen',
-        lookingForCompanyCards: 'Bedrijfskaarten toevoegen?',
-        lookingForCompanyCardsDescription: 'Koppel je eigen kaarten van meer dan 10.000 banken wereldwijd.',
-        personalCardAdded: 'Persoonlijke kaart toegevoegd!',
-        personalCardAddedDescription: 'Gefeliciteerd, we beginnen met het importeren van transacties van uw kaart.',
-        isPersonalCard: 'Is dit een persoonlijke kaart?',
-        thisIsPersonalCard: 'Dit is een persoonlijke kaart',
-        thisIsCompanyCard: 'Dit is een bedrijfskaart',
-        askAdmin: 'Vraag uw beheerder',
-        warningDescription: ({isAdmin}: {isAdmin?: boolean}) =>
-            `Zo ja, prima! Maar als het een <strong>bedrijfs</strong>kaart is, ${isAdmin ? 'wijs deze dan toe vanuit je werkruimte.' : 'vraag je beheerder om deze vanuit de werkruimte aan je toe te wijzen.'}`,
-        bankConnectionError: 'Probleem met bankverbinding',
-        bankConnectionDescription: 'Probeer je kaarten opnieuw toe te voegen. Anders kun je',
-        connectWithPlaid: 'verbinden via Plaid.',
-        fixCard: 'Kaart herstellen',
-        brokenConnection: 'Je kaartkoppeling is verbroken.',
-        conciergeBrokenConnection: ({cardName, connectionLink}: ConciergeBrokenCardConnectionParams) =>
-            connectionLink
-                ? `Je verbinding met de kaart ${cardName} is verbroken. <a href="${connectionLink}">Log in bij je bank</a> om de kaart te herstellen.`
-                : `Je verbinding met de kaart ${cardName} is verbroken. Log in bij je bank om de kaart te herstellen.`,
-        addAdditionalCards: 'Extra kaarten toevoegen',
-        upgradeDescription: 'Meer kaarten toevoegen? Maak een werkruimte om extra persoonlijke kaarten toe te voegen of bedrijfskaarten aan het hele team toe te wijzen.',
-        onlyAvailableOnPlan: ({formattedPrice}: {formattedPrice: string}) =>
-            `<muted-text>Beschikbaar in het Collect-abonnement, <strong>${formattedPrice}</strong> per lid per maand.</muted-text>`,
-        note: (subscriptionLink: string) =>
-            `<muted-text>Maak een werkruimte om deze functie te gebruiken, of <a href="${subscriptionLink}">meer informatie</a> over onze abonnementen en prijzen.</muted-text>`,
-        workspaceCreated: 'Werkruimte aangemaakt',
-        newWorkspace: 'Je hebt een werkruimte aangemaakt!',
-        successMessage: ({subscriptionLink}: {subscriptionLink: string}) =>
-            `<centered-text>Je kunt nu extra kaarten toevoegen. <a href="${subscriptionLink}">Bekijk je abonnement</a> voor meer details.</centered-text>`,
-    },
     walletPage: {
         balance: 'Saldo',
         paymentMethodsTitle: 'Betaalmethoden',
@@ -2440,10 +2171,9 @@ const translations: TranslationDeepObject<typeof en> = {
         enableWallet: 'Portemonnee inschakelen',
         addBankAccountToSendAndReceive: 'Voeg een bankrekening toe om betalingen te doen of te ontvangen.',
         addDebitOrCreditCard: 'Debet- of creditcard toevoegen',
-        cardInactive: 'Inactief',
-        assignedCards: 'Kaarten',
-        assignedCardsDescription: 'Transacties van toegewezen kaarten worden automatisch gesynchroniseerd.',
-        expensifyCard: 'Expensify Kaart',
+        assignedCards: 'Toegewezen kaarten',
+        assignedCardsDescription: 'Transacties van deze kaarten worden automatisch gesynchroniseerd.',
+        expensifyCard: 'Expensify Card',
         walletActivationPending: 'We controleren je gegevens. Kom over een paar minuten terug!',
         walletActivationFailed: 'Helaas kan je wallet op dit moment niet worden ingeschakeld. Chat met Concierge voor verdere hulp.',
         addYourBankAccount: 'Bankrekening toevoegen',
@@ -2467,30 +2197,27 @@ const translations: TranslationDeepObject<typeof en> = {
             'Iedereen hieronder heeft toegang tot deze bankrekening. Je kunt de toegang op elk moment verwijderen. We zullen eventuele lopende betalingen nog steeds afronden.',
         unshareBankAccountWarning: ({admin}: {admin?: string | null}) =>
             `${admin} verliest de toegang tot deze zakelijke bankrekening. We verwerken nog steeds alle betalingen die al in behandeling zijn.`,
-        reachOutForHelp: 'Hij wordt gebruikt met de Expensify Kaart. <concierge-link>Neem contact op met Concierge</concierge-link> als je hem niet meer wilt delen.',
+        reachOutForHelp: 'Het wordt gebruikt met de Expensify Card. <concierge-link>Neem contact op met Concierge</concierge-link> als je het moet stoppen met delen.',
         unshareErrorModalTitle: 'Kan betaalrekening niet meer ontkoppelen',
-        travelCVV: {
-            title: 'Reis-CVV',
-            subtitle: 'Gebruik dit bij het boeken van reizen',
-            description: 'Gebruik deze kaart voor je Expensify Travel-boekingen. Hij wordt weergegeven als “Travel Card” bij het afrekenen.',
-        },
         chaseAccountNumberDifferent: 'Waarom is mijn rekeningnummer anders?',
     },
     cardPage: {
-        expensifyCard: 'Expensify Kaart',
+        expensifyCard: 'Expensify Card',
         expensifyTravelCard: 'Expensify Travel Card',
         availableSpend: 'Resterende limiet',
         smartLimit: {
             name: 'Slimme limiet',
-            title: (formattedLimit: string) => `Je kunt tot ${formattedLimit} uitgeven met deze kaart, en de limiet wordt opnieuw ingesteld zodra je ingediende uitgaven zijn goedgekeurd.`,
+            title: ({formattedLimit}: ViolationsOverLimitParams) =>
+                `Je kunt tot ${formattedLimit} uitgeven met deze kaart, en de limiet wordt opnieuw ingesteld zodra je ingediende uitgaven zijn goedgekeurd.`,
         },
         fixedLimit: {
             name: 'Vast limiet',
-            title: (formattedLimit: string) => `Je kunt tot ${formattedLimit} uitgeven met deze kaart, daarna wordt hij gedeactiveerd.`,
+            title: ({formattedLimit}: ViolationsOverLimitParams) => `Je kunt tot ${formattedLimit} uitgeven met deze kaart, daarna wordt hij gedeactiveerd.`,
         },
         monthlyLimit: {
             name: 'Maandlimiet',
-            title: (formattedLimit: string) => `Je kunt met deze kaart tot ${formattedLimit} per maand uitgeven. De limiet wordt op de 1e dag van elke kalendermaand opnieuw ingesteld.`,
+            title: ({formattedLimit}: ViolationsOverLimitParams) =>
+                `Je kunt met deze kaart tot ${formattedLimit} per maand uitgeven. De limiet wordt op de 1e dag van elke kalendermaand opnieuw ingesteld.`,
         },
         virtualCardNumber: 'Nummer van virtuele kaart',
         travelCardCvv: 'Reiskaart-CVV',
@@ -2511,11 +2238,9 @@ const translations: TranslationDeepObject<typeof en> = {
             expiration: 'Vervaldatum',
             cvv: 'CVV',
             address: 'Adres',
-            reveal: 'Weergeven',
             revealDetails: 'Details weergeven',
             revealCvv: 'CVV weergeven',
             copyCardNumber: 'Kaartnummer kopiëren',
-            copyCvv: 'CVV kopiëren',
             updateAddress: 'Adres bijwerken',
         },
         cardAddedToWallet: ({platform}: {platform: 'Google' | 'Apple'}) => `Toegevoegd aan ${platform}-wallet`,
@@ -2523,6 +2248,7 @@ const translations: TranslationDeepObject<typeof en> = {
         validateCardTitle: 'We willen zeker weten dat jij het bent',
         enterMagicCode: (contactMethod: string) =>
             `Voer de magische code in die naar ${contactMethod} is gestuurd om je kaartgegevens te bekijken. Deze zou binnen één à twee minuten moeten aankomen.`,
+        missingPrivateDetails: ({missingDetailsLink}: {missingDetailsLink: string}) => `<a href="${missingDetailsLink}">Voeg je persoonlijke gegevens toe</a> en probeer het daarna opnieuw.`,
         unexpectedError: 'Er is een fout opgetreden bij het ophalen van de gegevens van je Expensify-kaart. Probeer het opnieuw.',
         cardFraudAlert: {
             confirmButtonText: 'Ja, dat doe ik',
@@ -2544,42 +2270,6 @@ const translations: TranslationDeepObject<typeof en> = {
 
 ${amount} voor ${merchant} - ${date}`,
         },
-        setYourPin: 'Stel je pincode in.',
-        confirmYourPin: 'Bevestig je pincode.',
-        changeYourPin: 'Voer een nieuwe pincode in voor je kaart.',
-        confirmYourChangedPin: 'Bevestig je nieuwe pincode.',
-        pinMustBeFourDigits: 'Pincode moet precies 4 cijfers bevatten.',
-        invalidPin: 'Kies alsjeblieft een veiligere pincode.',
-        pinMismatch: 'Pincodes komen niet overeen. Probeer het opnieuw.',
-        revealPin: 'Pincode weergeven',
-        hidePin: 'Pincode verbergen',
-        pin: 'Pincode',
-        changePin: 'Pincode wijzigen',
-        pinChanged: 'Pincode gewijzigd!',
-        pinChangedHeader: 'Pincode gewijzigd',
-        pinChangedDescription: 'Je bent helemaal klaar om je pincode te gebruiken.',
-        changePinAtATM: 'Wijzig je pincode bij elke geldautomaat',
-        changePinAtATMDescription: 'Dit is vereist in jouw regio. <concierge-link>Neem contact op met Concierge</concierge-link> als je vragen hebt.',
-        freezeCard: 'Kaart blokkeren',
-        unfreeze: 'Deblokkeren',
-        unfreezeCard: 'Kaart deblokkeren',
-        askToUnfreeze: 'Vraag om deblokkering',
-        freezeDescription: 'Een geblokkeerde kaart kan niet worden gebruikt voor aankopen en transacties. Je kunt deze op elk moment deblokkeren.',
-        unfreezeDescription: 'Door deze kaart te deblokkeren worden aankopen en transacties weer toegestaan. Ga alleen verder als je zeker weet dat de kaart veilig is om te gebruiken.',
-        frozen: 'Geblokkeerd',
-        youFroze: ({date}: {date: string}) => `Je hebt deze kaart op ${date} geblokkeerd.`,
-        frozenBy: ({person, date}: {person: string; date: string}) => `${person} heeft deze kaart op ${date} geblokkeerd.`,
-        frozenByAdminPrefix: ({date}: {date: string}) => `Deze kaart is op ${date} bevroren door `,
-        frozenByAdminNeedsUnfreezePrefix: 'Deze kaart is bevroren door ',
-        frozenByAdminNeedsUnfreezeSuffix: '. Neem contact op met een beheerder om deze te deblokkeren.',
-        frozenByAdminNeedsUnfreeze: ({person}: {person: string}) => `Deze kaart is bevroren door ${person}. Neem contact op met een beheerder om deze te deblokkeren.`,
-        spendRules: 'Bestedingsregels',
-        editSpendRules: 'Uitgavenregels bewerken',
-        cardUnblocked: 'Kaart gedeblokkeerd!',
-        cardUnblockedDescription: 'Mogelijk wordt je de volgende keer dat je een aankoop doet gevraagd om je kaart in de lezer te steken.',
-        pinBlocked: 'Je kaart is geblokkeerd vanwege onjuiste pincode-invoer.',
-        unblock: 'Deblokkeren',
-        unblockCard: 'Kaart deblokkeren',
     },
     workflowsPage: {
         workflowTitle: 'Uitgaven',
@@ -2591,14 +2281,9 @@ ${amount} voor ${merchant} - ${date}`,
         addApprovalsTitle: 'Goedkeuringen',
         accessibilityLabel: ({members, approvers}: {members: string; approvers: string}) => `de uitgaven van ${members}, en de goedkeurder is ${approvers}`,
         addApprovalButton: 'Goedkeuringsworkflow toevoegen',
-        editWorkflowAction: 'Bewerken',
-        addAgentAction: 'Agent toevoegen',
-        findWorkflow: 'Workflow zoeken',
         addApprovalTip: 'Deze standaardworkflow is van toepassing op alle leden, tenzij er een specifiekere workflow bestaat.',
         approver: 'Fiatteur',
         addApprovalsDescription: 'Extra goedkeuring vereisen voordat je een betaling autoriseert.',
-        automateApprovalsWithAgentsTitle: 'Automatiseer goedkeuringen met agents',
-        automateApprovalsWithAgentsSubtitle: 'Voeg hieronder een agent toe aan de workflow om goedkeuringen te automatiseren.',
         makeOrTrackPaymentsTitle: 'Betalingen',
         makeOrTrackPaymentsDescription: 'Voeg een gemachtigde betaler toe voor betalingen die in Expensify worden gedaan of volg betalingen die elders zijn gedaan.',
         customApprovalWorkflowEnabled:
@@ -2643,15 +2328,7 @@ ${amount} voor ${merchant} - ${date}`,
             title: 'Geen leden om weer te geven',
             expensesFromSubtitle: 'Alle werkruimteleden behoren al tot een bestaande goedkeuringsworkflow.',
             approverSubtitle: 'Alle fiatteurs behoren tot een bestaand workflow.',
-            bulkApproverSubtitle: 'Geen goedkeurders komen overeen met de criteria voor de geselecteerde rapporten.',
         },
-        configureViaHR: ({provider}: {provider: string}) => `Configureren via ${provider}.`,
-        hrApprovalWorkflowLockedPrompt: ({provider}: {provider: string}) =>
-            `Goedkeuringen worden beheerd door je ${provider}-integratie. Ga naar je ${provider}-verbindingsinstellingen om je goedkeuringsworkflow bij te werken.`,
-        goToHRSettings: ({provider}: {provider: string}) => `Ga naar ${provider}-instellingen`,
-        approverFromProvider: ({provider}: {provider: string}) => `van ${provider}`,
-        finalApprover: 'Laatste fiatteur',
-        manager: 'Manager',
     },
     workflowsDelayedSubmissionPage: {
         autoReportingFrequencyErrorMessage: 'Indienfrequentie kon niet worden gewijzigd. Probeer het opnieuw of neem contact op met support.',
@@ -2671,9 +2348,6 @@ ${amount} voor ${merchant} - ${date}`,
     workflowsExpensesFromPage: {
         title: 'Uitgaven vanaf',
         header: 'Wanneer de volgende leden onkosten indienen:',
-        memberAlreadyInWorkflowTitle: 'Lid bevindt zich al in een workflow',
-        memberAlreadyInWorkflowPrompt: ({memberName, approverName}: {memberName: string; approverName: string}) =>
-            `${memberName} bevindt zich al in een goedkeuringsworkflow die indient bij ${approverName}. Door het lid hier toe te voegen, wordt het naar deze workflow verplaatst.`,
     },
     workflowsApproverPage: {
         genericErrorMessage: 'De fiatteur kon niet worden gewijzigd. Probeer het opnieuw of neem contact op met support.',
@@ -2704,16 +2378,6 @@ ${amount} voor ${merchant} - ${date}`,
         admins: 'Beheerders',
         payer: 'Betaler',
         paymentAccount: 'Betaalrekening',
-        shareBankAccount: {
-            shareTitle: 'Bankrekeningtoegang delen?',
-            shareDescription: ({admin}: {admin: string}) => `U moet bankrekeningtoegang delen met ${admin} om hem/haar de betaler te maken.`,
-            validationTitle: 'Bankrekening wacht op validatie',
-            validationDescription: ({admin}: {admin: string}) =>
-                `U moet deze bankrekening <a href="#">valideren</a>. Zodra dat is gedaan, kunt u de toegang tot de bankrekening delen met ${admin} om hem/haar de betaler te maken.`,
-            errorTitle: 'Betaler kan niet worden gewijzigd',
-            errorDescription: ({admin, owner}: {admin: string; owner: string}) =>
-                `${admin} heeft geen toegang tot deze bankrekening, dus je kunt hem/haar niet als betaler instellen. <a href="#">Chat met ${owner}</a> als de bankrekening gedeeld moet worden.`,
-        },
     },
     reportFraudPage: {
         title: 'Fraude met virtuele kaart melden',
@@ -2725,7 +2389,6 @@ ${amount} voor ${merchant} - ${date}`,
     reportFraudConfirmationPage: {
         title: 'Kaartfraude gemeld',
         description: 'We hebben je bestaande kaart permanent gedeactiveerd. Wanneer je teruggaat om je kaartgegevens te bekijken, heb je een nieuwe virtuele kaart beschikbaar.',
-        descriptionCardNotReplaced: 'Je kaart is permanent gedeactiveerd. Neem contact op met een beheerder om een nieuwe kaart uit te geven.',
         buttonText: 'Begrepen, dank je!',
     },
     activateCardPage: {
@@ -2735,7 +2398,7 @@ ${amount} voor ${merchant} - ${date}`,
         error: {
             thatDidNotMatch: 'Dat komt niet overeen met de laatste 4 cijfers van je kaart. Probeer het opnieuw.',
             throttled:
-                'Je hebt te vaak onjuist de laatste 4 cijfers van je Expensify Kaart ingevoerd. Als je zeker weet dat de cijfers kloppen, neem dan contact op met Concierge om dit op te lossen. Probeer het anders later opnieuw.',
+                'Je hebt te vaak de laatste 4 cijfers van je Expensify Card onjuist ingevoerd. Als je zeker weet dat de cijfers kloppen, neem dan contact op met Concierge om dit op te lossen. Probeer het anders later opnieuw.',
         },
     },
     getPhysicalCard: {
@@ -2760,7 +2423,7 @@ ${amount} voor ${merchant} - ${date}`,
         shipCard: 'Kaart verzenden',
     },
     transferAmountPage: {
-        transfer: (amount: string) => `Overboeken${amount ? ` ${amount}` : ''}`,
+        transfer: ({amount}: TransferParams) => `Overboeken${amount ? ` ${amount}` : ''}`,
         instant: 'Direct (betaalpas)',
         instantSummary: (rate: string, minAmount: string) => `${rate}% vergoeding (minimum ${minAmount})`,
         ach: '1-3 werkdagen (bankrekening)',
@@ -2787,46 +2450,14 @@ ${amount} voor ${merchant} - ${date}`,
         defaultPaymentMethod: 'Standaard',
         bankAccountLastFour: (lastFour: string) => `Bankrekening • ${lastFour}`,
     },
-    agentsPage: {
-        title: 'Agenten',
-        subtitle: 'Maak agents aan om je workflow af te handelen. Sla het handmatige werk over en krijg uren van je dag terug.',
-        newAgent: 'Nieuwe medewerker',
-        emptyAgents: {title: 'Geen agents aangemaakt', subtitle: 'Stop met dingen handmatig doen. Geef in plaats daarvan een opdracht aan een agent en bespaar jezelf veel tijd.'},
-        error: {
-            genericAdd: 'Er was een probleem bij het toevoegen van deze agent',
-            genericUpdate: 'Er is een probleem opgetreden bij het bijwerken van deze agent',
-            updateName: 'Er is een probleem opgetreden bij het bijwerken van de naam van deze agent',
-            updatePrompt: 'Er is een probleem opgetreden bij het bijwerken van de instructies van deze agent',
-            updateAvatar: 'Er is een probleem opgetreden bij het bijwerken van de avatar van deze agent',
-        },
-    },
-    addAgentPage: {
-        title: 'Nieuwe agent',
-        agentName: 'Naam medewerker',
-        instructions: 'Schrijf aangepaste instructies',
-        createAgent: 'Agent aanmaken',
-        editAvatar: 'Profielavatar wisselen',
-        defaultAgentName: (displayName: string) => `Agent van ${displayName}`,
-        defaultPrompt:
-            'Wijs declaraties af die zijn voor gokken, films of andere duidelijk niet-zakelijke redenen.\n\nHerinner de gebruiker eraan altijd een bonafbeelding toe te voegen waarop de fooi duidelijk is.\n\nKeur het verslag goed als het sterk lijkt op eerdere verslagen van dezelfde gebruiker.\n\nWijs verslagen af met meer dan $500 aan reiskosten.',
-    },
-    editAgentPage: {
-        title: 'Agent bewerken',
-        agentName: 'Naam medewerker',
-        instructions: 'Aangepaste instructies schrijven',
-        chatWithAgent: 'Chat met agent',
-        copilotIntoAccount: 'Copilot in account',
-        deleteAgent: 'Agent verwijderen',
-        deleteAgentTitle: 'Agent verwijderen?',
-        deleteAgentMessage: 'Weet je zeker dat je deze agent wilt verwijderen? Deze actie kan niet ongedaan worden gemaakt.',
-    },
-    editAgentAvatarPage: {title: 'Avatar bewerken'},
-    editAgentNamePage: {title: 'Naam medewerker'},
-    editAgentPromptPage: {title: 'Aangepaste instructies schrijven', error: {emptyPrompt: 'Voer instructies in voor je medewerker.'}},
     expenseRulesPage: {
         title: 'Declaratieregels',
+        subtitle: 'Deze regels zijn van toepassing op je uitgaven. Als je bij een werkruimte indient, kunnen de regels van die werkruimte deze overschrijven.',
         findRule: 'Regel zoeken',
-        emptyRules: {title: 'Nog geen regels', subtitle: 'Voeg een regel toe om onkostendeclaraties te automatiseren.'},
+        emptyRules: {
+            title: 'Je hebt nog geen regels gemaakt',
+            subtitle: 'Voeg een regel toe om onkostendeclaraties te automatiseren.',
+        },
         changes: {
             billableUpdate: (value: boolean) => `Declaratie ${value ? 'factureerbaar' : 'niet-factureerbaar'} bijwerken`,
             categoryUpdate: (value: string) => `Categorie bijwerken naar ‘${value}’`,
@@ -2867,7 +2498,6 @@ ${amount} voor ${merchant} - ${date}`,
             deleteSinglePrompt: 'Weet je zeker dat je deze regel wilt verwijderen?',
             deleteMultiplePrompt: 'Weet je zeker dat je deze regels wilt verwijderen?',
         },
-        subtitle: 'Deze regels zijn van toepassing op je uitgaven.',
     },
     preferencesPage: {
         appSection: {
@@ -2895,12 +2525,11 @@ ${amount} voor ${merchant} - ${date}`,
         },
     },
     reportDetailsPage: {
-        inWorkspace: (policyName: string) => `in ${policyName}`,
+        inWorkspace: ({policyName}: ReportPolicyNameParams) => `in ${policyName}`,
         generatingPDF: 'PDF genereren',
         waitForPDF: 'Even geduld terwijl we de pdf genereren.',
         errorPDF: 'Er is een fout opgetreden bij het genereren van je PDF',
         successPDF: 'Je PDF is gegenereerd! Als het niet automatisch is gedownload, gebruik dan de knop hieronder.',
-        goToRoom: 'Ga naar kamer',
     },
     reportDescriptionPage: {
         roomDescription: 'Kamerbeschrijving',
@@ -2910,7 +2539,7 @@ ${amount} voor ${merchant} - ${date}`,
     groupChat: {
         lastMemberTitle: 'Let op!',
         lastMemberWarning: 'Omdat jij de laatste persoon hier bent, wordt deze chat ontoegankelijk voor alle leden als je vertrekt. Weet je zeker dat je wilt vertrekken?',
-        defaultReportName: (displayName: string) => `Groepschat van ${displayName}`,
+        defaultReportName: ({displayName}: ReportArchiveReasonsClosedParams) => `Groepschat van ${displayName}`,
     },
     languagePage: {
         language: 'Taal',
@@ -2929,25 +2558,19 @@ ${amount} voor ${merchant} - ${date}`,
                 label: 'Apparaatinstellingen gebruiken',
             },
         },
-        highContrastMode: 'Hoog contrast',
-        enableHighContrast: 'Hoog contrast inschakelen',
-        disableHighContrast: 'Hoog contrast uitschakelen',
         chooseThemeBelowOrSync: 'Kies hieronder een thema, of synchroniseer met de instellingen van je apparaat.',
     },
     termsOfUse: {
         terms: `<muted-text-xs>Door in te loggen ga je akkoord met de <a href="${CONST.OLD_DOT_PUBLIC_URLS.TERMS_URL}">Servicevoorwaarden</a> en het <a href="${CONST.OLD_DOT_PUBLIC_URLS.PRIVACY_URL}">Privacybeleid</a>.</muted-text-xs>`,
-        license: `Geldtransfers worden verzorgd door ${CONST.WALLET.PROGRAM_ISSUERS.EXPENSIFY_PAYMENTS} (NMLS ID:2017010) volgens diens <a href="${CONST.OLD_DOT_PUBLIC_URLS.LICENSES_URL}">licenties</a>.`,
+        license: `<muted-text-xs>Geldtransmissie wordt verzorgd door ${CONST.WALLET.PROGRAM_ISSUERS.EXPENSIFY_PAYMENTS} (NMLS ID:2017010) overeenkomstig de <a href="${CONST.OLD_DOT_PUBLIC_URLS.LICENSES_URL}">licenties</a>.</muted-text-xs>`,
     },
     validateCodeForm: {
         magicCodeNotReceived: 'Geen magische code ontvangen?',
-        avoidScamsMessage: '<strong>Voorkom oplichting. Deel je code met niemand.</strong> Ons team zal je nooit bellen, sms’en of e-mailen om deze code te vragen.',
         enterAuthenticatorCode: 'Voer je authenticatiecode in',
         enterRecoveryCode: 'Voer uw herstelcode in',
         requiredWhen2FAEnabled: 'Vereist wanneer 2FA is ingeschakeld',
         requestNewCode: ({timeRemaining}: {timeRemaining: string}) => `Vraag een nieuwe code aan over <a>${timeRemaining}</a>`,
         requestNewCodeAfterErrorOccurred: 'Een nieuwe code aanvragen',
-        timeRemainingAnnouncement: ({timeRemaining}) => `Resterende tijd: ${timeRemaining} ${timeRemaining === 1 ? 'seconde' : 'seconden'}`,
-        timeExpiredAnnouncement: 'De tijd is verstreken',
         error: {
             pleaseFillMagicCode: 'Voer je magische code in',
             incorrectMagicCode: 'Onjuiste of ongeldige magische code. Probeer het opnieuw of vraag een nieuwe code aan.',
@@ -2978,7 +2601,6 @@ ${amount} voor ${merchant} - ${date}`,
         phoneOrEmail: 'Telefoon of e-mail',
         error: {
             invalidFormatEmailLogin: 'Het ingevoerde e-mailadres is ongeldig. Corrigeer de notatie en probeer het opnieuw.',
-            agentSignInBlocked: 'Je kunt niet rechtstreeks inloggen op agent-accounts. Log in met je eigen account en gebruik de agent via Copilot.',
         },
         cannotGetAccountDetails: 'Accountgegevens konden niet worden opgehaald. Probeer opnieuw in te loggen.',
         loginForm: 'Aanmeldformulier',
@@ -2996,41 +2618,29 @@ ${amount} voor ${merchant} - ${date}`,
         },
         getStarted: 'Aan de slag',
         whatsYourName: 'Hoe heet je?',
-        peopleYouMayKnow: 'Kijk of je team al in Expensify zit',
-        workspaceYouMayJoin: (domain: string, email: string) =>
-            `Voer de code in die is verzonden naar ${email} om te controleren of iemand van ${domain} een workspace heeft waar je lid van kunt worden.`,
+        peopleYouMayKnow: 'Mensen die je misschien kent zijn hier al! Verifieer je e-mailadres om je bij hen aan te sluiten.',
+        workspaceYouMayJoin: ({domain, email}: WorkspaceYouMayJoin) => `Iemand van ${domain} heeft al een workspace gemaakt. Voer de magische code in die is verzonden naar ${email}.`,
         joinAWorkspace: 'Lid worden van een workspace',
-        listOfWorkspaces: 'Hier is de lijst met werkruimtes waartoe je je kunt aansluiten.',
-        skipForNow: 'Voorlopig overslaan',
-        workspaceMemberList: (employeeCount: number, policyOwner: string) => `${employeeCount} lid${employeeCount > 1 ? 's' : ''} • ${policyOwner}`,
+        listOfWorkspaces: 'Hier is de lijst met werkruimtes waaraan je kunt deelnemen. Geen zorgen, je kunt je er altijd later nog bij aansluiten als je dat liever hebt.',
+        workspaceMemberList: ({employeeCount, policyOwner}: WorkspaceMemberList) => `${employeeCount} lid${employeeCount > 1 ? 's' : ''} • ${policyOwner}`,
         whereYouWork: 'Waar werk je?',
         errorSelection: 'Selecteer een optie om verder te gaan',
         purpose: {
             title: 'Wat wil je vandaag doen?',
             errorContinue: 'Druk op ‘Doorgaan’ om de installatie te voltooien',
             errorBackButton: 'Beantwoord eerst de instelvragen om de app te kunnen gebruiken',
-            [CONST.ONBOARDING_CHOICES.EMPLOYER]: 'Onkosten indienen bij mijn werkgever',
+            [CONST.ONBOARDING_CHOICES.EMPLOYER]: 'Door mijn werkgever laten terugbetalen',
             [CONST.ONBOARDING_CHOICES.MANAGE_TEAM]: 'De onkosten van mijn team beheren',
-            [CONST.ONBOARDING_CHOICES.TRACK_BUSINESS]: 'Zakelijke uitgaven bijhouden',
-            [CONST.ONBOARDING_CHOICES.TRACK_PERSONAL]: 'Mijn persoonlijke uitgaven organiseren',
+            [CONST.ONBOARDING_CHOICES.PERSONAL_SPEND]: 'Uitgaven bijhouden en budgetteren',
+            [CONST.ONBOARDING_CHOICES.CHAT_SPLIT]: 'Chat en deel uitgaven met vrienden',
             [CONST.ONBOARDING_CHOICES.LOOKING_AROUND]: 'Iets anders',
         },
-        personalTrackGoal: {
-            title: 'Wat wil je bijhouden?',
-            [CONST.ONBOARDING_PERSONAL_TRACK_GOALS.INVESTMENT_TRACKING]: 'Kosten voor een beleggingspand',
-            [CONST.ONBOARDING_PERSONAL_TRACK_GOALS.HOUSEHOLD_TRACKING]: 'Huishoudelijke uitgaven',
-            [CONST.ONBOARDING_PERSONAL_TRACK_GOALS.SIDEPROJECT_TRACKING]: 'Kosten voor nevenproject',
-            [CONST.ONBOARDING_PERSONAL_TRACK_GOALS.SOMETHING_ELSE]: 'Iets anders',
-            somethingElsePlaceholder: 'Wat volg je?',
-        },
         employees: {
-            title: 'Hoeveel medewerkers heb je?',
-            [CONST.ONBOARDING_COMPANY_SIZE.MICRO_SMALL]: '1-4 medewerkers',
-            [CONST.ONBOARDING_COMPANY_SIZE.MICRO_MEDIUM]: '5-10 medewerkers',
-            [CONST.ONBOARDING_COMPANY_SIZE.MICRO]: '1-10 medewerkers',
+            title: 'Hoeveel werknemers heb je?',
+            [CONST.ONBOARDING_COMPANY_SIZE.MICRO]: '1-10 werknemers',
             [CONST.ONBOARDING_COMPANY_SIZE.SMALL]: '11-50 medewerkers',
-            [CONST.ONBOARDING_COMPANY_SIZE.MEDIUM_SMALL]: '51-100 medewerkers',
-            [CONST.ONBOARDING_COMPANY_SIZE.MEDIUM]: '101-1.000 werknemers',
+            [CONST.ONBOARDING_COMPANY_SIZE.MEDIUM_SMALL]: '51-100 werknemers',
+            [CONST.ONBOARDING_COMPANY_SIZE.MEDIUM]: '101–1.000 werknemers',
             [CONST.ONBOARDING_COMPANY_SIZE.LARGE]: 'Meer dan 1.000 medewerkers',
         },
         accounting: {
@@ -3057,18 +2667,15 @@ ${amount} voor ${merchant} - ${date}`,
         },
         workEmailValidation: {
             title: 'Verifieer je werk-e-mailadres',
-            magicCodeSent: (workEmail: string | undefined) => `Voer de magische code in die is verzonden naar ${workEmail}. Deze zou binnen een of twee minuten moeten aankomen.`,
+            magicCodeSent: ({workEmail}: WorkEmailResendCodeParams) => `Voer de magische code in die is verzonden naar ${workEmail}. Deze zou binnen een of twee minuten moeten aankomen.`,
         },
         workEmailValidationError: {
             publicEmail: 'Voer een geldig zakelijk e-mailadres in van een privédomein, bijv. mitch@company.com',
-            sameAsSignupEmail: 'Voer een ander e-mailadres in dan het e-mailadres waarmee je je hebt aangemeld',
             offline: 'We konden je werk-e-mailadres niet toevoegen omdat je offline lijkt te zijn',
         },
         mergeBlockScreen: {
             title: 'Werkmail kon niet worden toegevoegd',
-            subtitle: (workEmail: string | undefined) => `We konden ${workEmail} niet toevoegen. Probeer het later opnieuw in Instellingen of chat met Concierge voor hulp.`,
-            workAccountClosedSubtitle:
-                'De zakelijke account die aan dit e-mailadres is gekoppeld, is gesloten. Neem contact op met de beheerder van je bedrijf om het opnieuw te activeren, of meld je aan met een ander e-mailadres.',
+            subtitle: ({workEmail}: WorkEmailMergingBlockedParams) => `We konden ${workEmail} niet toevoegen. Probeer het later opnieuw in Instellingen of chat met Concierge voor hulp.`,
         },
         tasks: {
             testDriveAdminTask: {
@@ -3099,7 +2706,7 @@ ${amount} voor ${merchant} - ${date}`,
             },
             createTestDriveAdminWorkspaceTask: {
                 title: ({workspaceConfirmationLink}) => `[Maak](${workspaceConfirmationLink}) een workspace`,
-                description: 'Maak een workspace aan en stel de instellingen in met hulp van je accountmanager!',
+                description: 'Maak een workspace aan en configureer de instellingen met hulp van je set-up specialist!',
             },
             createWorkspaceTask: {
                 title: ({workspaceSettingsLink}) => `Maak een [werkruimte](${workspaceSettingsLink})`,
@@ -3115,13 +2722,13 @@ ${amount} voor ${merchant} - ${date}`,
                 title: ({workspaceCategoriesLink}) => `[categorieën instellen](${workspaceCategoriesLink})`,
                 description: ({workspaceCategoriesLink}) =>
                     dedent(`
-                        *Stel categorieën in* zodat je team uitgaven kan coderen voor eenvoudige rapportage.
+                        *Stel categorieën in* zodat je team onkosten kan coderen voor eenvoudige rapportage.
 
                         1. Klik op *Workspaces*.
                         2. Selecteer je workspace.
                         3. Klik op *Categories*.
-                        4. Schakel alle categorieën uit die je niet nodig hebt.
-                        5. Voeg rechtsboven je eigen categorieën toe.
+                        4. Schakel categorieën uit die je niet nodig hebt.
+                        5. Voeg je eigen categorieën toe rechtsboven.
 
                         [Breng me naar de categorie-instellingen van de workspace](${workspaceCategoriesLink}).
                     `),
@@ -3131,7 +2738,7 @@ ${amount} voor ${merchant} - ${date}`,
                 description: dedent(`
                     *Dien een uitgave in* door een bedrag in te voeren of een bon te scannen.
 
-                    1. Klik op de knop *+*.
+                    1. Klik op de knop ${CONST.CUSTOM_EMOJIS.GLOBAL_CREATE}.
                     2. Kies *Uitgave maken*.
                     3. Voer een bedrag in of scan een bon.
                     4. Voeg het e-mailadres of telefoonnummer van je manager toe.
@@ -3145,7 +2752,7 @@ ${amount} voor ${merchant} - ${date}`,
                 description: dedent(`
                     *Dien een uitgave in* door een bedrag in te voeren of een bon te scannen.
 
-                    1. Klik op de knop *+*.
+                    1. Klik op de knop ${CONST.CUSTOM_EMOJIS.GLOBAL_CREATE}.
                     2. Kies *Uitgave maken*.
                     3. Voer een bedrag in of scan een bon.
                     4. Bevestig de details.
@@ -3159,7 +2766,7 @@ ${amount} voor ${merchant} - ${date}`,
                 description: dedent(`
                     *Volg een uitgave* in elke valuta, of je nu een bon hebt of niet.
 
-                    1. Klik op de knop *+*.
+                    1. Klik op de knop ${CONST.CUSTOM_EMOJIS.GLOBAL_CREATE}.
                     2. Kies *Uitgave maken*.
                     3. Voer een bedrag in of scan een bon.
                     4. Kies je *persoonlijke* ruimte.
@@ -3181,8 +2788,13 @@ ${amount} voor ${merchant} - ${date}`,
                         4. Zoek ${integrationName}.
                         5. Klik op *Connect*.
 
-                        [Breng me naar boekhouding](${workspaceAccountingLink}).
-                    `),
+${
+    integrationName && CONST.connectionsVideoPaths[integrationName]
+        ? `[Breng me naar de boekhouding](${workspaceAccountingLink}).
+
+                        ![Verbinden met ${integrationName}](${CONST.CLOUDFRONT_URL}/${CONST.connectionsVideoPaths[integrationName]})`
+        : `[Breng me naar boekhouding](${workspaceAccountingLink}).`
+}`),
             },
             connectCorporateCardTask: {
                 title: ({corporateCardLink}) => `Verbind [je zakelijke kaarten](${corporateCardLink})`,
@@ -3206,7 +2818,7 @@ ${amount} voor ${merchant} - ${date}`,
                         1. Klik op *Workspaces*.
                         2. Selecteer je workspace.
                         3. Klik op *Members* > *Invite member*.
-                        4. Voer e-mails of telefoonnummers in.
+                        4. Voer e-mailadressen of telefoonnummers in.
                         5. Voeg een aangepast uitnodigingsbericht toe als je wilt!
 
                         [Breng me naar workspaceleden](${workspaceMembersLink}).
@@ -3224,13 +2836,13 @@ ${amount} voor ${merchant} - ${date}`,
                 title: ({workspaceTagsLink}) => `[Tags](${workspaceTagsLink}) instellen`,
                 description: ({workspaceMoreFeaturesLink}) =>
                     dedent(`
-                        Gebruik labels om extra details aan uitgaven toe te voegen, zoals projecten, klanten, locaties en afdelingen. Als je meerdere niveaus van labels nodig hebt, kun je upgraden naar het Control-abonnement.
+                        Gebruik labels om extra details aan je uitgaven toe te voegen, zoals projecten, klanten, locaties en afdelingen. Als je meerdere niveaus van labels nodig hebt, kun je upgraden naar het Control-abonnement.
 
                         1. Klik op *Workspaces*.
                         2. Selecteer je workspace.
                         3. Klik op *More features*.
                         4. Schakel *Tags* in.
-                        5. Ga naar *Tags* in de workspace-editor.
+                        5. Ga in de workspace-editor naar *Tags*.
                         6. Klik op *+ Add tag* om je eigen labels te maken.
 
                         [Breng me naar more features](${workspaceMoreFeaturesLink}).
@@ -3256,7 +2868,7 @@ ${amount} voor ${merchant} - ${date}`,
                 description: dedent(`
                     *Start een chat* met iedereen via hun e-mailadres of telefoonnummer.
 
-                    1. Klik op de knop *+*.
+                    1. Klik op de knop ${CONST.CUSTOM_EMOJIS.GLOBAL_CREATE}.
                     2. Kies *Chat starten*.
                     3. Voer een e-mailadres of telefoonnummer in.
 
@@ -3270,7 +2882,7 @@ ${amount} voor ${merchant} - ${date}`,
                 description: dedent(`
                     *Kosten splitsen* met één of meer personen.
 
-                    1. Klik op de knop *+*.
+                    1. Klik op de knop ${CONST.CUSTOM_EMOJIS.GLOBAL_CREATE}.
                     2. Kies *Chat starten*.
                     3. Voer e-mailadressen of telefoonnummers in.
                     4. Klik in de chat op de grijze knop *+* > *Kosten splitsen*.
@@ -3294,7 +2906,7 @@ ${amount} voor ${merchant} - ${date}`,
                 description: dedent(`
                     Zo maak je een rapport:
 
-                    1. Klik op de knop *+*.
+                    1. Klik op de knop ${CONST.CUSTOM_EMOJIS.GLOBAL_CREATE}.
                     2. Kies *Rapport maken*.
                     3. Klik op *Uitgave toevoegen*.
                     4. Voeg je eerste uitgave toe.
@@ -3317,15 +2929,18 @@ ${amount} voor ${merchant} - ${date}`,
                 isOnboardingFlow
                     ? dedent(`
                         # Je gratis proefperiode is gestart! Laten we je account instellen.
-                        👋 Hoi, ik ben je Expensify accountmanager. Ik heb al een workspace aangemaakt om de bonnen en uitgaven van je team te beheren. Volg de resterende configuratiestappen hieronder om het meeste uit je 30 dagen gratis proefperiode te halen!
+                        👋 Hoi, ik ben je Expensify-configuratiespecialist. Ik heb al een workspace aangemaakt om de bonnetjes en uitgaven van je team te beheren. Volg gewoon de resterende configuratiestappen hieronder om het meeste uit je gratis proefperiode van 30 dagen te halen!
                     `)
                     : dedent(`
-                        # Je gratis proefperiode is begonnen! Laten we je account instellen.
-                        👋 Hoi, ik ben je Expensify accountmanager. Nu je een workspace hebt aangemaakt, haal alles uit je gratis proefperiode van 30 dagen door de onderstaande stappen te volgen!
+                        # Je gratis proefperiode is gestart! Laten we je account instellen.
+                        👋 Hallo, ik ben je Expensify-specialist voor de installatie. Nu je een workspace hebt aangemaakt, haal het meeste uit je gratis proefperiode van 30 dagen door de onderstaande stappen te volgen!
                     `),
-            onboardingTrackWorkspaceMessage: 'Haal het meeste uit je gratis proefperiode van 30 dagen door de volgende stappen te volgen:',
+            onboardingTrackWorkspaceMessage:
+                '# Laten we je instellen\n👋 Hoi, ik ben je Expensify-instellingsspecialist. Ik heb alvast een workspace aangemaakt om je bonnetjes en uitgaven te beheren. Volg de laatste onderstaande instellingsstappen om het meeste uit je gratis proefperiode van 30 dagen te halen!',
             onboardingChatSplitMessage: 'Rekeningen splitsen met vrienden is net zo makkelijk als het sturen van een bericht. Zo werkt het.',
             onboardingAdminMessage: 'Leer hoe je als beheerder de werkruimte van je team beheert en je eigen onkosten indient.',
+            onboardingLookingAroundMessage:
+                'Expensify staat vooral bekend om het beheer van uitgaven, reizen en zakelijke kaarten, maar we doen veel meer dan dat. Laat me weten waarin je geïnteresseerd bent, dan help ik je op weg.',
             onboardingTestDriveReceiverMessage: '*Je krijgt 3 maanden gratis! Ga hieronder aan de slag.*',
         },
         workspace: {
@@ -3336,7 +2951,7 @@ ${amount} voor ${merchant} - ${date}`,
                 descriptionTwo: 'Categoriseer en tag uitgaven',
                 descriptionThree: 'Rapporten maken en delen',
             },
-            price: (price?: string) => `Probeer het 30 dagen gratis, upgrade daarna voor slechts <strong>${price ?? '$5'}/gebruiker/maand</strong>.`,
+            price: 'Probeer het 30 dagen gratis, upgrade daarna voor slechts <strong>$5/gebruiker/maand</strong>.',
             createWorkspace: 'Werkruimte maken',
         },
         confirmWorkspace: {
@@ -3347,8 +2962,6 @@ ${amount} voor ${merchant} - ${date}`,
             title: 'Leden uitnodigen',
             subtitle: 'Voeg je team toe of nodig je accountant uit. Hoe meer zielen, hoe meer vreugd!',
         },
-        workEmail2FAError: 'Deze inlog is een bestaand account met Two-Factor Authentication (2FA) ingeschakeld.',
-        singleSignOnError: 'Deze login is een bestaand account met SSO/SAML ingeschakeld.',
     },
     featureTraining: {
         doNotShowAgain: 'Dit niet meer tonen',
@@ -3368,7 +2981,6 @@ ${amount} voor ${merchant} - ${date}`,
         enterPhoneNumber: 'Wat is je telefoonnummer?',
         personalDetails: 'Persoonlijke gegevens',
         privateDataMessage: 'Deze gegevens worden gebruikt voor reizen en betalingen. Ze worden nooit weergegeven op je openbare profiel.',
-        basicDetails: 'Basisgegevens',
         legalName: 'Wettelijke naam',
         legalFirstName: 'Juridische voornaam',
         legalLastName: 'Wettelijke achternaam',
@@ -3377,18 +2989,17 @@ ${amount} voor ${merchant} - ${date}`,
             dateShouldBeBefore: (dateString: string) => `Datum moet vóór ${dateString} zijn`,
             dateShouldBeAfter: (dateString: string) => `Datum moet na ${dateString} liggen`,
             hasInvalidCharacter: 'Naam mag alleen Latijnse letters bevatten',
-            cannotIncludeCommaOrSemicolon: 'Naam mag geen komma of puntkomma bevatten',
             incorrectZipFormat: (zipFormat?: string) => `Ongeldig postcodeformaat${zipFormat ? `Acceptabel formaat: ${zipFormat}` : ''}`,
             invalidPhoneNumber: `Zorg ervoor dat het telefoonnummer geldig is (bijv. ${CONST.EXAMPLE_PHONE_NUMBER})`,
         },
     },
     resendValidationForm: {
         linkHasBeenResent: 'Link is opnieuw verzonden',
-        weSentYouMagicSignInLink: (login: string, loginType: string) => `Ik heb een magische inloglink naar ${login} gestuurd. Controleer je ${loginType} om in te loggen.`,
+        weSentYouMagicSignInLink: ({login, loginType}: WeSentYouMagicSignInLinkParams) => `Ik heb een magische inloglink naar ${login} gestuurd. Controleer je ${loginType} om in te loggen.`,
         resendLink: 'Link opnieuw verzenden',
     },
     unlinkLoginForm: {
-        toValidateLogin: (primaryLogin: string, secondaryLogin: string) =>
+        toValidateLogin: ({primaryLogin, secondaryLogin}: ToValidateLoginParams) =>
             `Om ${secondaryLogin} te verifiëren, stuur de magische code opnieuw vanuit de Accountinstellingen van ${primaryLogin}.`,
         noLongerHaveAccess: (primaryLogin: string) => `Als je geen toegang meer hebt tot ${primaryLogin}, koppel dan je accounts los.`,
         unlink: 'Koppeling verbreken',
@@ -3446,12 +3057,14 @@ ${amount} voor ${merchant} - ${date}`,
     },
     welcomeSignUpForm: {
         join: 'Deelnemen',
-        marketingSMSConsent: 'Ik ga akkoord met het ontvangen van marketing-sms van Expensify',
     },
     detailsPage: {
         localTime: 'Lokale tijd',
     },
-    newChatPage: {startGroup: 'Groep starten', addToGroup: 'Aan groep toevoegen', addUserToGroup: (username: string) => `${username} aan groep toevoegen`},
+    newChatPage: {
+        startGroup: 'Groep starten',
+        addToGroup: 'Aan groep toevoegen',
+    },
     yearPickerPage: {
         year: 'Jaar',
         selectYear: 'Selecteer een jaar',
@@ -3494,18 +3107,18 @@ ${amount} voor ${merchant} - ${date}`,
             custom: 'Aangepast',
         },
         untilTomorrow: 'Tot morgen',
-        untilTime: (time: string) => `Tot ${time}`,
+        untilTime: ({time}: UntilTimeParams) => `Tot ${time}`,
         date: 'Datum',
         time: 'Tijd',
         clearAfter: 'Wissen na',
         whenClearStatus: 'Wanneer moeten we je status wissen?',
+        vacationDelegate: 'Vertegenwoordiger tijdens vakantie',
         setVacationDelegate: `Stel een vervangende fiatteur in om rapporten namens jou goed te keuren terwijl je afwezig bent.`,
-        cannotSetVacationDelegate: `Je kunt geen vakantiedelegaat instellen omdat je momenteel de delegaat bent voor de volgende leden:`,
-        addVacationDelegate: 'Vakantiedelegaat toevoegen',
         vacationDelegateError: 'Er is een fout opgetreden bij het bijwerken van je vervanger tijdens vakantie.',
-        asVacationDelegate: (nameOrEmail: string) => `als vakantiewaarnemer van ${nameOrEmail}`,
-        toAsVacationDelegate: (submittedToName: string, vacationDelegateName: string) => `aan ${submittedToName} als vakantieplaatsvervanger voor ${vacationDelegateName}`,
-        vacationDelegateWarning: (nameOrEmail: string) =>
+        asVacationDelegate: ({nameOrEmail}: VacationDelegateParams) => `als vakantiewaarnemer van ${nameOrEmail}`,
+        toAsVacationDelegate: ({submittedToName, vacationDelegateName}: SubmittedToVacationDelegateParams) =>
+            `aan ${submittedToName} als vakantieplaatsvervanger voor ${vacationDelegateName}`,
+        vacationDelegateWarning: ({nameOrEmail}: VacationDelegateParams) =>
             `Je wijst ${nameOrEmail} aan als jouw vervang(st)er tijdens afwezigheid. Diegene zit nog niet in al je werkruimtes. Als je doorgaat, wordt er een e-mail naar alle beheerders van je werkruimtes gestuurd om diegene toe te voegen.`,
     },
     stepCounter: ({step, total, text}: StepCounterParams) => {
@@ -3534,35 +3147,23 @@ ${amount} voor ${merchant} - ${date}`,
         connectManually: 'Handmatig verbinden',
         desktopConnection: 'Opmerking: om verbinding te maken met Chase, Wells Fargo, Capital One of Bank of America, klik hier om dit proces in een browser te voltooien.',
         yourDataIsSecure: 'Je gegevens zijn beveiligd',
-        toGetStarted: 'Voeg een bankrekening toe om onkosten terug te betalen, Expensify Kaarten uit te geven, facturen te innen en rekeningen te betalen – allemaal vanaf één plek.',
+        toGetStarted: 'Voeg een bankrekening toe om onkosten terug te betalen, Expensify Cards uit te geven, factuurbetalingen te innen en rekeningen te betalen – allemaal vanuit één plek.',
         plaidBodyCopy: 'Geef je medewerkers een eenvoudigere manier om bedrijfsuitgaven te betalen – en terugbetaald te worden.',
         checkHelpLine: 'Je bankcode en rekeningnummer staan op een cheque van de rekening.',
-        bankAccountPurposeTitle: 'Wat wil je doen met je bankrekening?',
-        getReimbursed: 'Vergoed worden',
-        getReimbursedDescription: 'Door werkgever of anderen',
-        makePayments: 'Betalingen doen',
-        makePaymentsDescription: 'Betaal uitgaven of geef Expensify Kaarten uit',
         hasPhoneLoginError: (contactMethodRoute: string) =>
             `Om een bankrekening te koppelen, <a href="${contactMethodRoute}">voeg eerst een e-mailadres toe als je primaire login</a> en probeer het daarna opnieuw. Je kunt je telefoonnummer toevoegen als secundaire login.`,
         hasBeenThrottledError: 'Er is een fout opgetreden bij het toevoegen van je bankrekening. Wacht een paar minuten en probeer het opnieuw.',
-        hasCurrencyError: (workspaceRoute: string) =>
+        hasCurrencyError: ({workspaceRoute}: WorkspaceRouteParams) =>
             `Oeps! Het lijkt erop dat de valuta van je workspace is ingesteld op een andere valuta dan USD. Ga naar <a href="${workspaceRoute}">de instellingen van je workspace</a>, stel deze in op USD en probeer het opnieuw.`,
         bbaAdded: 'Zakelijke bankrekening toegevoegd!',
         bbaAddedDescription: 'Het is klaar om voor betalingen te worden gebruikt.',
-        lockedBankAccount: 'Geblokkeerde bankrekening',
-        unlockBankAccount: 'Deblokkeer bankrekening',
-        youCantPayThis: `Je kunt dit rapport niet betalen omdat je een <a href="${CONST.UNLOCK_BANK_ACCOUNT_HELP_URL}">geblokkeerde bankrekening</a> hebt. Tik hieronder en de Concierge helpt je met de volgende stappen om deze te deblokkeren.`,
-        htmlUnlockMessage: (maskedAccountNumber: string) =>
-            `<h1>Expensify Business Bank Account ${maskedAccountNumber}</h1><p>Bedankt voor het indienen van een verzoek om je bankrekening te deblokkeren. Opnameverzoeken kunnen worden afgewezen vanwege onvoldoende saldo of als de bankrekening niet is geactiveerd voor automatische incasso. We zullen je zaak bekijken en contact met je opnemen als we aanvullende informatie nodig hebben om dit probleem op te lossen.</p>`,
-        textUnlockMessage: (maskedAccountNumber: string) =>
-            `Expensify Business Bank Account ${maskedAccountNumber}\nBedankt voor het indienen van een verzoek om je bankrekening te deblokkeren. Opnameverzoeken kunnen worden afgewezen vanwege onvoldoende saldo of als de bankrekening niet is geactiveerd voor automatische incasso. We zullen je zaak bekijken en contact met je opnemen als we aanvullende informatie nodig hebben om dit probleem op te lossen.`,
         error: {
             youNeedToSelectAnOption: 'Selecteer een optie om door te gaan',
             noBankAccountAvailable: 'Sorry, er is geen bankrekening beschikbaar',
             noBankAccountSelected: 'Kies een account',
             taxID: 'Voer een geldig btw-identificatienummer in',
             website: 'Voer een geldige website in',
-            zipCode: `Voer een geldige postcode in met het volgende formaat: ${COMMON_CONST.COUNTRY_ZIP_REGEX_DATA.US.samples}`,
+            zipCode: `Voer een geldige postcode in met het volgende formaat: ${CONST.COUNTRY_ZIP_REGEX_DATA.US.samples}`,
             phoneNumber: 'Voer een geldig telefoonnummer in',
             email: 'Voer een geldig e-mailadres in',
             companyName: 'Voer een geldige bedrijfsnaam in',
@@ -3589,7 +3190,7 @@ ${amount} voor ${merchant} - ${date}`,
             fullName: 'Voer een geldige volledige naam in',
             ownershipPercentage: 'Voer een geldig percentage in',
             deletePaymentBankAccount:
-                'Deze bankrekening kan niet worden verwijderd omdat hij wordt gebruikt voor betalingen met de Expensify Kaart. Als je deze rekening toch wilt verwijderen, neem dan contact op met Concierge.',
+                'Deze bankrekening kan niet worden verwijderd omdat deze wordt gebruikt voor Expensify Card-betalingen. Als je deze rekening toch wilt verwijderen, neem dan contact op met Concierge.',
             sameDepositAndWithdrawalAccount: 'De stortings- en opname­rekeningen zijn hetzelfde.',
         },
     },
@@ -3604,11 +3205,6 @@ ${amount} voor ${merchant} - ${date}`,
         confirmationStepHeader: 'Controleer je gegevens.',
         confirmationStepSubHeader: 'Controleer de onderstaande gegevens goed en vink het vakje met de voorwaarden aan om te bevestigen.',
         toGetStarted: 'Voeg een persoonlijke bankrekening toe om terugbetalingen te ontvangen, facturen te betalen of de Expensify Wallet in te schakelen.',
-        updatePersonalInfo: 'Bankrekening bijwerken',
-        updatePersonalInfoFailure: 'Kan de bankrekeninggegevens niet bijwerken. Probeer het later opnieuw.',
-        updateSuccessTitle: 'Bankrekening bijgewerkt!',
-        updateSuccessHeader: 'Bankrekening bijgewerkt',
-        updateSuccessMessage: 'Gefeliciteerd, je bankrekening is ingesteld en klaar om terugbetalingen te ontvangen.',
     },
     addPersonalBankAccountPage: {
         enterPassword: 'Voer Expensify-wachtwoord in',
@@ -3636,8 +3232,8 @@ ${amount} voor ${merchant} - ${date}`,
     messages: {
         errorMessageInvalidPhone: `Voer een geldig telefoonnummer in zonder haakjes of streepjes. Als je buiten de VS bent, voeg dan je landcode toe (bijv. ${CONST.EXAMPLE_PHONE_NUMBER}).`,
         errorMessageInvalidEmail: 'Ongeldig e-mailadres',
-        userIsAlreadyMember: (login: string, name: string) => `${login} is al lid van ${name}`,
-        userIsAlreadyAnAdmin: (login: string, name: string) => `${login} is al een beheerder van ${name}`,
+        userIsAlreadyMember: ({login, name}: UserIsAlreadyMemberParams) => `${login} is al lid van ${name}`,
+        userIsAlreadyAnAdmin: ({login, name}: UserIsAlreadyMemberParams) => `${login} is al een beheerder van ${name}`,
     },
     onfidoStep: {
         acceptTerms: 'Door verder te gaan met het verzoek om je Expensify Wallet te activeren, bevestig je dat je hebt gelezen, begrijpt en accepteert',
@@ -3683,7 +3279,7 @@ ${amount} voor ${merchant} - ${date}`,
         haveReadAndAgreePlain: 'Ik heb gelezen en ga ermee akkoord elektronische bekendmakingen te ontvangen.',
         haveReadAndAgree: `Ik heb gelezen en ga ermee akkoord om <a href="${CONST.ELECTRONIC_DISCLOSURES_URL}">elektronische openbaarmakingen</a> te ontvangen.`,
         agreeToThePlain: 'Ik ga akkoord met het privacy- en walletcontract.',
-        agreeToThe: (walletAgreementUrl: string) =>
+        agreeToThe: ({walletAgreementUrl}: WalletAgreementParams) =>
             `Ik ga akkoord met het <a href="${CONST.OLD_DOT_PUBLIC_URLS.PRIVACY_URL}">privacybeleid</a> en de <a href="${walletAgreementUrl}">walletovereenkomst</a>.`,
         enablePayments: 'Betalingen inschakelen',
         monthlyFee: 'Maandelijkse vergoeding',
@@ -3695,7 +3291,7 @@ ${amount} voor ${merchant} - ${date}`,
         checkTheBoxes: 'Vink de onderstaande vakjes aan.',
         agreeToTerms: 'Ga akkoord met de voorwaarden en je bent klaar om te beginnen!',
         shortTermsForm: {
-            expensifyPaymentsAccount: (walletProgram: string) => `De Expensify Wallet wordt uitgegeven door ${walletProgram}.`,
+            expensifyPaymentsAccount: ({walletProgram}: WalletProgramParams) => `De Expensify Wallet wordt uitgegeven door ${walletProgram}.`,
             perPurchase: 'Per aankoop',
             atmWithdrawal: 'Geldopname bij geldautomaat',
             cashReload: 'Cash-opwaardering',
@@ -3709,7 +3305,7 @@ ${amount} voor ${merchant} - ${date}`,
             generalInfo: `Ga voor algemene informatie over prepaidrekeningen naar <a href="${CONST.CFPB_PREPAID_URL}">${CONST.TERMS.CFPB_PREPAID}</a>.`,
             conditionsDetails: `Voor details en voorwaarden voor alle kosten en diensten, ga naar <a href="${CONST.FEES_URL}">${CONST.FEES_URL}</a> of bel +1 833-400-0904.`,
             electronicFundsWithdrawalInstant: 'Elektronische geldafschrijving (direct)',
-            electronicFundsInstantFeeMin: (amount: string) => `(min. ${amount})`,
+            electronicFundsInstantFeeMin: ({amount}: TermsParams) => `(min. ${amount})`,
         },
         longTermsForm: {
             listOfAllFees: 'Een lijst met alle Expensify Wallet-kosten',
@@ -3729,7 +3325,7 @@ ${amount} voor ${merchant} - ${date}`,
             electronicFundsInstantDetails: (percentage: string, amount: string) =>
                 'Er wordt een vergoeding in rekening gebracht om geld van je Expensify Wallet naar je gekoppelde betaalpas over te maken met de optie voor directe overboeking. Deze overboeking wordt meestal binnen enkele minuten voltooid.' +
                 `De vergoeding is ${percentage}% van het overboekingsbedrag (met een minimumvergoeding van ${amount}).`,
-            fdicInsuranceBancorp: (amount: string) =>
+            fdicInsuranceBancorp: ({amount}: TermsParams) =>
                 `Je geld komt in aanmerking voor FDIC-verzekering. Je geld wordt aangehouden bij of overgemaakt naar ${CONST.WALLET.PROGRAM_ISSUERS.BANCORP_BANK}, een instelling die verzekerd is door de FDIC.` +
                 `Daar zijn je tegoeden verzekerd tot ${amount} door de FDIC in het geval ${CONST.WALLET.PROGRAM_ISSUERS.BANCORP_BANK} failliet gaat, mits aan specifieke eisen voor depositoverzekering is voldaan en je kaart is geregistreerd. Zie ${CONST.TERMS.FDIC_PREPAID} voor details.`,
             contactExpensifyPayments: `Neem contact op met ${CONST.WALLET.PROGRAM_ISSUERS.EXPENSIFY_PAYMENTS} door te bellen naar +1 833-400-0904, een e-mail te sturen naar ${CONST.EMAIL.CONCIERGE} of meld je aan op ${CONST.NEW_EXPENSIFY_URL}.`,
@@ -3738,7 +3334,7 @@ ${amount} voor ${merchant} - ${date}`,
             automated: 'Geautomatiseerd',
             liveAgent: 'Live agent',
             instant: 'Direct',
-            electronicFundsInstantFeeMin: (amount: string) => `Min. ${amount}`,
+            electronicFundsInstantFeeMin: ({amount}: TermsParams) => `Min. ${amount}`,
         },
     },
     activateStep: {
@@ -4023,10 +3619,6 @@ ${amount} voor ${merchant} - ${date}`,
         youCanChange: 'Je kunt de valuta van je werkruimte wijzigen in je',
         findCountry: 'Land zoeken',
         selectCountry: 'Selecteer land',
-        error: {
-            connectToWorkspace: (workspaceRoute: string) =>
-                `Deze bankrekening moet worden gekoppeld aan een werkruimte. Ga naar <a href="${workspaceRoute}">Werkruimtes</a>, selecteer je werkruimte en navigeer vervolgens naar Workflows > Betalingen > Bankrekening toevoegen.`,
-        },
     },
     bankInfoStep: {
         whatAreYour: 'Wat zijn de gegevens van je zakelijke bankrekening?',
@@ -4070,7 +3662,7 @@ ${amount} voor ${merchant} - ${date}`,
         pleaseUpload: 'Upload hieronder extra documentatie om ons te helpen uw identiteit als directeur van het bedrijf te verifiëren.',
         enterSignerInfo: 'Voer ondertekenaargegevens in',
         thisStep: 'Deze stap is voltooid',
-        isConnecting: (bankAccountLastFour: string | undefined, currency: string | undefined) =>
+        isConnecting: ({bankAccountLastFour, currency}: SignerInfoMessageParams) =>
             `verbindt een zakelijke ${currency}-bankrekening die eindigt op ${bankAccountLastFour} met Expensify om werknemers in ${currency} te betalen. De volgende stap vereist ondertekenaarsgegevens van een directeur.`,
         error: {
             emailsMustBeDifferent: 'E-mails moeten verschillend zijn',
@@ -4082,7 +3674,7 @@ ${amount} voor ${merchant} - ${date}`,
         regulationRequiresUs: 'Volgens de regelgeving moeten we de identiteit verifiëren van elke persoon die meer dan 25% van het bedrijf bezit.',
         iAmAuthorized: 'Ik ben gemachtigd om de zakelijke bankrekening te gebruiken voor zakelijke uitgaven.',
         iCertify: 'Ik verklaar dat de verstrekte informatie waarheidsgetrouw en nauwkeurig is.',
-        iAcceptTheTermsAndConditions: `Ik ga akkoord met de <a href="https://www.corpay.com/cross-border/terms">algemene voorwaarden</a>.`,
+        iAcceptTheTermsAndConditions: `Ik ga akkoord met de <a href="https://cross-border.corpay.com/tc/">algemene voorwaarden</a>.`,
         iAcceptTheTermsAndConditionsAccessibility: 'Ik ga akkoord met de algemene voorwaarden.',
         accept: 'Accepteren en bankrekening toevoegen',
         iConsentToThePrivacyNotice: 'Ik ga akkoord met de <a href="https://payments.corpay.com/compliance">privacyverklaring</a>.',
@@ -4114,37 +3706,6 @@ ${amount} voor ${merchant} - ${date}`,
         weTake: 'We nemen je beveiliging serieus. Stel nu 2FA in om een extra beveiligingslaag aan je account toe te voegen.',
         secure: 'Beveilig je account',
     },
-    documentsStep: {
-        beforeYouGo: 'Voordat je verdergaat, hebben we enkele documenten nodig om bepaalde gegevens te verifiëren',
-        subheader: 'Verificatie',
-        verificationFailed: 'De verificatie is mislukt, daarom hebben we extra documenten nodig om jou en je bedrijf te verifiëren',
-        taxIDVerification: 'Belastingnummerverificatie',
-        taxIDVerificationDescription: dedent(`
-        Upload een van de volgende bestanden:
-        • IRS TIN/EIN-toewijzingsbrief
-        • IRS TIN/EIN-aanvraagbevestiging (bevat meestal "Congratulations! The EIN has been successfully assigned")
-        • IRS-belastingvrijstellingsbrief met bedrijfsnaam en EIN`),
-        nameChangeDocument: 'Document naamswijziging',
-        nameChangeDocumentDescription: 'Als de naam van je bedrijf is gewijzigd sinds de TIN/EIN-aanvraag, hebben we dit document nodig om het opgegeven belastingnummer te verifiëren',
-        companyAddressVerification: 'Verificatie van bedrijfsadres',
-        companyAddressVerificationDescription: dedent(`
-        Upload een van de volgende bestanden:
-        • Recente energierekening met bedrijfsnaam en adres
-        • Bankafschrift met bedrijfsnaam en adres
-        • Huidige huur- of leaseovereenkomst inclusief ondertekeningspagina met bedrijfsnaam en huidig adres
-        • Verzekeringsverklaring met bedrijfsnaam en adres
-        • TIN-toewijzingsdocument met bedrijfsnaam en adres`),
-        userAddressVerification: 'Adresverificatie',
-        userAddressVerificationDescription: dedent(`
-        Upload een van de volgende bestanden:
-        • Kiezersregistratiekaart
-        • Rijbewijs
-        • Bankafschrift
-        • Energierekening`),
-        userDOBVerification: 'Verificatie van geboortedatum',
-        userDOBVerificationDescription: 'Upload een in de VS uitgegeven identiteitsbewijs',
-        finishViaChat: 'Afronden via chat',
-    },
     reimbursementAccountLoadingAnimation: {
         oneMoment: 'Een ogenblik',
         explanationLine: 'We bekijken je gegevens. Je kunt binnenkort verdergaan met de volgende stappen.',
@@ -4282,15 +3843,15 @@ ${amount} voor ${merchant} - ${date}`,
             flightSeatChanged: (airlineCode: string) => `Uw stoeltoewijzing op vlucht ${airlineCode} is gewijzigd.`,
             flightSeatCancelled: (airlineCode: string) => `Je stoeltoewijzing op vlucht ${airlineCode} is verwijderd.`,
             paymentDeclined: 'De betaling voor je vluchtboeking is mislukt. Probeer het opnieuw.',
-            bookingCancelledByTraveler: (type: string, id = '') => `Je hebt je ${type}-reservering ${id} geannuleerd.`,
-            bookingCancelledByVendor: (type: string, id = '') => `De leverancier heeft je ${type}-reservering ${id} geannuleerd.`,
-            bookingRebooked: (type: string, id = '') => `Je ${type}-reservering is opnieuw geboekt. Nieuwe bevestiging nr.: ${id}.`,
-            bookingUpdated: (type: string) => `Je ${type}-boeking is bijgewerkt. Bekijk de nieuwe details in het reisschema.`,
+            bookingCancelledByTraveler: ({type, id = ''}: TravelTypeParams) => `Je hebt je ${type}-reservering ${id} geannuleerd.`,
+            bookingCancelledByVendor: ({type, id = ''}: TravelTypeParams) => `De leverancier heeft je ${type}-reservering ${id} geannuleerd.`,
+            bookingRebooked: ({type, id = ''}: TravelTypeParams) => `Je ${type}-reservering is opnieuw geboekt. Nieuwe bevestiging nr.: ${id}.`,
+            bookingUpdated: ({type}: TravelTypeParams) => `Je ${type}-boeking is bijgewerkt. Bekijk de nieuwe details in het reisschema.`,
             railTicketRefund: (origin: string, destination: string, startDate: string) =>
                 `Je treinkaartje voor ${origin} → ${destination} op ${startDate} is terugbetaald. Een tegoed wordt verwerkt.`,
             railTicketExchange: (origin: string, destination: string, startDate: string) => `Uw treinticket voor ${origin} → ${destination} op ${startDate} is omgewisseld.`,
             railTicketUpdate: (origin: string, destination: string, startDate: string) => `Je treinkaartje voor ${origin} → ${destination} op ${startDate} is bijgewerkt.`,
-            defaultUpdate: (type: string) => `Je ${type}reservering is bijgewerkt.`,
+            defaultUpdate: ({type}: TravelTypeParams) => `Je ${type}reservering is bijgewerkt.`,
         },
         flightTo: 'Vlucht naar',
         trainTo: 'Trein naar',
@@ -4301,19 +3862,19 @@ ${amount} voor ${merchant} - ${date}`,
     workspace: {
         common: {
             card: 'Kaarten',
-            expensifyCard: 'Expensify Kaart',
+            expensifyCard: 'Expensify Card',
             companyCards: 'Bedrijfskaarten',
             personalCards: 'Persoonlijke kaarten',
             workflows: 'Workflows',
             workspace: 'Werkruimte',
             findWorkspace: 'Werkruimte zoeken',
-            findRoom: 'Kamer zoeken',
             edit: 'Werkruimte bewerken',
             enabled: 'Ingeschakeld',
             disabled: 'Uitgeschakeld',
             everyone: 'Iedereen',
             delete: 'Werkruimte verwijderen',
             settings: 'Instellingen',
+            reimburse: 'Terugbetalingen',
             categories: 'Categorieën',
             tags: 'Tags',
             customField1: 'Aangepast veld 1',
@@ -4321,7 +3882,6 @@ ${amount} voor ${merchant} - ${date}`,
             customFieldHint: 'Voeg aangepaste codering toe die van toepassing is op alle uitgaven van dit lid.',
             reports: 'Rapporten',
             reportFields: 'Rapportvelden',
-            invoiceFields: 'Factuurvelden',
             reportTitle: 'Rapporttitel',
             reportField: 'Rapportveld',
             taxes: 'Belastingen',
@@ -4350,10 +3910,6 @@ ${amount} voor ${merchant} - ${date}`,
             defaultNote: `Bonnetjes die naar ${CONST.EMAIL.RECEIPTS} worden gestuurd, verschijnen in deze workspace.`,
             deleteConfirmation: 'Weet je zeker dat je deze werkruimte wilt verwijderen?',
             deleteWithCardsConfirmation: 'Weet je zeker dat je deze werkruimte wilt verwijderen? Hiermee worden alle kaartfeeds en toegewezen kaarten verwijderd.',
-            deleteOpenExpensifyCardsError: 'Uw bedrijf heeft nog actieve Expensify Cards.',
-            outstandingBalanceWarning:
-                'Je hebt een openstaand saldo dat moet worden vereffend voordat je je laatste werkruimte kunt verwijderen. Ga naar je abonnementsinstellingen om de betaling af te ronden.',
-            settleBalance: 'Ga naar abonnement',
             unavailable: 'Niet-beschikbare workspace',
             memberNotFound: 'Lid niet gevonden. Gebruik de uitnodigingsknop hierboven om een nieuw lid aan de werkruimte toe te voegen.',
             notAuthorized: `Je hebt geen toegang tot deze pagina. Als je wilt deelnemen aan deze werkruimte, vraag dan de eigenaar van de werkruimte om je als lid toe te voegen. Iets anders aan de hand? Neem contact op met ${CONST.EMAIL.CONCIERGE}.`,
@@ -4366,9 +3922,6 @@ ${amount} voor ${merchant} - ${date}`,
             workspaceOwner: 'Eigenaar',
             workspaceType: 'Werkruimtetype',
             workspaceAvatar: 'Workspace-avatar',
-            keepMeAsAdmin: 'Houd mij als beheerder',
-            clientID: 'Klant-ID',
-            clientIDInputHint: 'Voer de unieke identificatie van de klant in',
             mustBeOnlineToViewMembers: 'Je moet online zijn om de leden van deze workspace te bekijken.',
             moreFeatures: 'Meer functies',
             requested: 'Aangevraagd',
@@ -4387,7 +3940,7 @@ ${amount} voor ${merchant} - ${date}`,
             appliedOnExport: 'Niet geïmporteerd in Expensify, toegepast bij export',
             shareNote: {
                 header: 'Deel je werkruimte met andere leden',
-                content: (adminsRoomLink: string) =>
+                content: ({adminsRoomLink}: WorkspaceShareNoteParams) =>
                     `Deel deze QR-code of kopieer de link hieronder om het leden makkelijk te maken toegang tot je werkruimte aan te vragen. Alle verzoeken om lid te worden van de werkruimte verschijnen in de <a href="${adminsRoomLink}">${CONST.REPORT.WORKSPACE_CHAT_ROOMS.ADMINS}</a>-ruimte ter beoordeling.`,
             },
             connectTo: ({connectionName}: ConnectionNameParams) => `Verbind met ${CONST.POLICY.CONNECTIONS.NAME_USER_FRIENDLY[connectionName]}`,
@@ -4402,20 +3955,12 @@ ${amount} voor ${merchant} - ${date}`,
             memberAlternateText: 'Dien rapporten in en keur ze goed.',
             adminAlternateText: 'Beheer rapporten en werkruimte-instellingen.',
             auditorAlternateText: 'Rapporten bekijken en erop reageren.',
-            roleName: (role?: string) => {
+            roleName: ({role}: OptionalParam<RoleNamesParams> = {}) => {
                 switch (role) {
                     case CONST.POLICY.ROLE.ADMIN:
-                        return 'Beheerder van workspace';
+                        return 'Beheerder';
                     case CONST.POLICY.ROLE.AUDITOR:
                         return 'Auditor';
-                    case CONST.POLICY.ROLE.EDITOR:
-                        return 'Editor';
-                    case CONST.POLICY.ROLE.CARD_ADMIN:
-                        return 'Kaartbeheer';
-                    case CONST.POLICY.ROLE.PEOPLE_ADMIN:
-                        return 'Personenbeheer';
-                    case CONST.POLICY.ROLE.PAYMENTS_ADMIN:
-                        return 'Beheerder betalingen';
                     case CONST.POLICY.ROLE.USER:
                         return 'Lid';
                     default:
@@ -4445,22 +3990,7 @@ ${amount} voor ${merchant} - ${date}`,
             budgetFrequency: {monthly: 'maandelijks', yearly: 'jaarlijks'},
             budgetFrequencyUnit: {monthly: 'maand', yearly: 'jaar'},
             budgetTypeForNotificationMessage: {tag: 'tag', category: 'categorie'},
-            deepDiveExpensifyCard: `<muted-text-label>Transacties met de Expensify Kaart worden automatisch geëxporteerd naar een "Expensify Kaart Passivarekening" dat wordt aangemaakt via <a href="${CONST.DEEP_DIVE_EXPENSIFY_CARD}">onze integratie</a>.</muted-text-label>`,
-            travelInvoicing: 'Reisfacturatiekosten exporteren als',
-            travelInvoicingVendor: 'Reisaanbieder',
-            travelInvoicingPayableAccount: 'Reiscrediteurenrekening',
-            hr: 'HR',
-            rooms: 'Kamers',
-            findDomain: 'Domein zoeken',
-            cardAdminAlternateText: 'Werkruimtekaarten beheren.',
-            peopleAdminAlternateText: 'Beheer leden en goedkeuringsworkflows.',
-            paymentsAdminAlternateText: 'Workflowsbetalingen beheren.',
-            readOnlyActionTitle: 'Niet zo snel...',
-            readOnlyActionPrompt: 'Je rol in de workspace kan deze instellingen bekijken, maar niet bewerken.',
-        },
-        createdForClient: {
-            title: 'Je hebt een werkruimte voor je klant aangemaakt!',
-            description: 'Geweldig nieuws 🎉. Neem contact met ons op als ze hulp nodig hebben bij de configuratie.',
+            deepDiveExpensifyCard: `<muted-text-label>Expensify Card-transacties worden automatisch geëxporteerd naar een "Expensify Card Liability Account" dat wordt aangemaakt met <a href="${CONST.DEEP_DIVE_EXPENSIFY_CARD}">onze integratie</a>.</muted-text-label>`,
         },
         receiptPartners: {
             uber: {
@@ -4523,7 +4053,7 @@ ${amount} voor ${merchant} - ${date}`,
             exportDescription: 'Stel in hoe Expensify-gegevens worden geëxporteerd naar QuickBooks Desktop.',
             date: 'Exportdatum',
             exportInvoices: 'Facturen exporteren naar',
-            exportExpensifyCard: 'Exporteer Expensify Kaart-transacties als',
+            exportExpensifyCard: 'Exporteer Expensify Card-transacties als',
             account: 'Account',
             accountDescription: 'Kies waar journaalposten moeten worden geboekt.',
             accountsPayable: 'Crediteuren',
@@ -4643,7 +4173,7 @@ ${amount} voor ${merchant} - ${date}`,
             exportDescription: 'Configureren hoe Expensify-gegevens worden geëxporteerd naar QuickBooks Online.',
             date: 'Exportdatum',
             exportInvoices: 'Facturen exporteren naar',
-            exportExpensifyCard: 'Exporteer Expensify Kaart-transacties als',
+            exportExpensifyCard: 'Exporteer Expensify Card-transacties als',
             exportDate: {
                 label: 'Exportdatum',
                 description: 'Gebruik deze datum bij het exporteren van rapporten naar QuickBooks Online.',
@@ -4681,9 +4211,8 @@ ${amount} voor ${merchant} - ${date}`,
             notConfigured: 'Niet geconfigureerd',
             bankAccountDescription: 'Kies vanaf waar cheques worden verzonden.',
             creditCardAccount: 'Creditcardrekening',
-            travelInvoicingDescription: 'Reiskosten worden als creditcardkosten geëxporteerd naar het hieronder opgegeven QuickBooks Online-account.',
             companyCardsLocationEnabledDescription:
-                'QuickBooks Online ondersteunt geen locaties op leveranciersfactuur-exporten wanneer locaties als tags worden geïmporteerd. Omdat je in je werkruimte locaties als tags hebt geïmporteerd, is deze exportoptie niet beschikbaar.',
+                'QuickBooks Online ondersteunt geen locaties bij het exporteren van leveranciersfacturen. Omdat je locaties hebt ingeschakeld in je workspace, is deze exportoptie niet beschikbaar.',
             outOfPocketTaxEnabledDescription:
                 'QuickBooks Online ondersteunt geen belastingen op exports van journaalboekingen. Omdat je belastingen hebt ingeschakeld in je workspace, is deze exportoptie niet beschikbaar.',
             outOfPocketTaxEnabledError: 'Boekingen zijn niet beschikbaar wanneer belastingen zijn ingeschakeld. Kies een andere exportoptie.',
@@ -4777,7 +4306,6 @@ ${amount} voor ${merchant} - ${date}`,
             exportDeepDiveCompanyCard:
                 'Geëxporteerde uitgaven worden als banktransacties geboekt op de onderstaande Xero-bankrekening, en transactiedata komen overeen met de data op je bankafschrift.',
             bankTransactions: 'Banktransacties',
-            travelInvoicingDescription: 'Reiskosten worden als banktransacties geëxporteerd naar het hieronder opgegeven Xero-account.',
             xeroBankAccount: 'Xero-bankrekening',
             xeroBankAccountDescription: 'Kies waar onkosten als banktransacties worden geboekt.',
             exportExpensesDescription: 'Rapporten worden geëxporteerd als een inkoopfactuur met de datum en status die hieronder zijn geselecteerd.',
@@ -4872,7 +4400,6 @@ ${amount} voor ${merchant} - ${date}`,
                     [CONST.SAGE_INTACCT_NON_REIMBURSABLE_EXPENSE_TYPE.VENDOR_BILL]: 'Leveranciersfacturen',
                 },
             },
-            travelInvoicingDescription: 'Reiskosten worden als creditcardkosten geëxporteerd naar het hieronder opgegeven Sage Intacct-account.',
             creditCardAccount: 'Creditcardrekening',
             defaultVendor: 'Standaardleverancier',
             defaultVendorDescription: (isReimbursable: boolean) =>
@@ -4905,68 +4432,6 @@ ${amount} voor ${merchant} - ${date}`,
                 },
             },
         },
-        certinia: {
-            title: 'Certinia',
-            titleFFA: 'Certinia (FFA)',
-            autoSyncDescription: 'Expensify wordt elke dag automatisch met Certinia gesynchroniseerd.',
-            syncReimbursedReportsDescription:
-                'Als deze optie is ingeschakeld, wordt elke keer dat een te betalen factuur in FFA wordt betaald, het bijbehorende Expensify-rapport automatisch als terugbetaald gemarkeerd.',
-            exportDescription: 'Stel in hoe Expensify-gegevens worden geëxporteerd naar Certinia.',
-            payableInvoices: 'Te betalen facturen',
-            exportStatus: {
-                label: 'Status te betalen factuur',
-                values: {
-                    [CONST.CERTINIA_EXPORT_STATUS.APPROVED]: 'Voltooien',
-                    [CONST.CERTINIA_EXPORT_STATUS.IN_PROGRESS]: 'Bezig',
-                    [CONST.CERTINIA_EXPORT_STATUS.SUBMITTED]: 'Ingediend',
-                },
-            },
-            exportDate: {
-                label: 'Vervaldatum factuur',
-                values: {
-                    [CONST.CERTINIA_EXPORT_DATE.LAST_EXPENSE]: 'Datum van laatste uitgave',
-                    [CONST.CERTINIA_EXPORT_DATE.REPORT_SUBMITTED]: 'Indiendatum rapport',
-                    [CONST.CERTINIA_EXPORT_DATE.REPORT_EXPORTED]: 'Exportdatum',
-                },
-            },
-            exportReimbursable: {
-                label: 'Terugbetaalbare declaraties exporteren als',
-                helperText: 'Declarabele uitgaven worden geëxporteerd als te betalen facturen op naam van de werknemer.',
-            },
-            exportNonReimbursable: {label: 'Niet-declarabele uitgaven exporteren als'},
-            noVendorsFound: 'Geen leveranciers gevonden',
-            noVendorsFoundDescription: 'Synchroniseer de verbinding opnieuw nadat leveranciers zijn toegevoegd in Certinia.',
-            prerequisites: {
-                title: 'Voordat je verbinding maakt',
-                installBundle: 'Voor FFA-verbindingen',
-                installBundleDescription: ({href, version}: {href: string; version: string}) =>
-                    `Installeer de Expensify-bundel in Salesforce door op deze link te klikken: <a href="${href}">FFA Expensify-bundel installeren (versie ${version})</a>`,
-                installBundleConfirm: 'Ik heb de bundel geïnstalleerd',
-                setupContacts: 'Gebruiker en contacten instellen',
-                setupContactsBullet1:
-                    'Maak zowel een Gebruiker als een Contact voor jezelf aan in Certinia als deze nog niet bestaan en zorg ervoor dat het e‑mailadres overeenkomt met je primaire e‑mail in Expensify.',
-                setupContactsBullet2:
-                    'Maak contacten aan voor elke medewerker die declaraties gaat indienen en voor elke rapportgoedkeurder. Zorg ervoor dat het e-mailadres van elk contact overeenkomt met het e-mailadres van het Expensify-account van de medewerker.',
-                setupContactsBullet3: 'Stel per contact/bron machtigingen in voor je gebruiker.',
-                setupContactsConfirm: 'Ik heb de gebruiker en de contacten ingesteld',
-                oauth: 'Log in via Salesforce',
-                oauthDescription: 'Om de installatie te voltooien, moet je je aanmelden via Salesforce en Certinia.\n\nGebruik de knop hieronder om door te gaan.',
-                connectButton: 'Verbind met Certinia',
-            },
-            import: {
-                chartOfAccounts: 'Rekeningschema',
-                chartOfAccountsDescription: 'Het grootboekschema wordt in Expensify geïmporteerd als categorieën.',
-                dimensionMapping: ({n}: {n: number}) => `Dimensie ${n}`,
-                dimensions: {dimension1: 'Dimensie 1', dimension2: 'Dimensie 2', dimension3: 'Dimensie 3', dimension4: 'Dimensie 4'},
-                doNotMap: 'Niet toewijzen',
-                doNotMapSubtitle: 'Standaard werknemersbron gebruiken',
-                mappingTypes: {
-                    [CONST.CERTINIA_MAPPING_VALUE.DEFAULT]: 'Niet toewijzen',
-                    [CONST.CERTINIA_MAPPING_VALUE.TAG]: 'Geïmporteerd als labels',
-                    [CONST.CERTINIA_MAPPING_VALUE.REPORT_FIELD]: 'Geïmporteerd als rapportvelden',
-                },
-            },
-        },
         netsuite: {
             subsidiary: 'Dochteronderneming',
             subsidiarySelectDescription: 'Kies de dochteronderneming in NetSuite waaruit je gegevens wilt importeren.',
@@ -4981,8 +4446,8 @@ ${amount} voor ${merchant} - ${date}`,
             journalPostingPreference: {
                 label: 'Voorkeur voor het boeken van journaalposten',
                 values: {
-                    [CONST.NETSUITE_JOURNAL_POSTING_PREFERENCE.JOURNALS_POSTING_INDIVIDUAL_LINE]: 'Enkele boeking per uitgave',
-                    [CONST.NETSUITE_JOURNAL_POSTING_PREFERENCE.JOURNALS_POSTING_TOTAL_LINE]: 'Enkele, uitgesplitste boeking per rapport',
+                    [CONST.NETSUITE_JOURNAL_POSTING_PREFERENCE.JOURNALS_POSTING_INDIVIDUAL_LINE]: 'Enkele, uitgesplitste boeking voor elk rapport',
+                    [CONST.NETSUITE_JOURNAL_POSTING_PREFERENCE.JOURNALS_POSTING_TOTAL_LINE]: 'Eén boeking per uitgave',
                 },
             },
             invoiceItem: {
@@ -5048,7 +4513,6 @@ ${amount} voor ${merchant} - ${date}`,
 
                             Als je voor elke kaart een specifieke leverancier wilt instellen, ga dan naar *Instellingen > Domeinen > Bedrijfspassen*.
                         `),
-                        travelDescription: 'Reiskosten worden geëxporteerd als journaalposten naar de hieronder opgegeven NetSuite-rekening.',
                     },
                 },
                 expenseReportDestinationConfirmDescription:
@@ -5193,7 +4657,7 @@ ${amount} voor ${merchant} - ${date}`,
                 importCustomFields: {
                     chooseOptionBelow: 'Kies een optie hieronder:',
                     label: (importedTypes: string[]) => `Geïmporteerd als ${importedTypes.join('en')}`,
-                    requiredFieldError: (fieldName: string) => `Voer de ${fieldName} in`,
+                    requiredFieldError: ({fieldName}: RequiredFieldParams) => `Voer de ${fieldName} in`,
                     customSegments: {
                         title: 'Aangepaste segmenten/records',
                         addText: 'Aangepast segment/record toevoegen',
@@ -5267,7 +4731,7 @@ _Voor meer gedetailleerde instructies, [bezoek onze helpwebsite](${CONST.NETSUIT
                             customRecordMappingTitle: 'Hoe moet dit aangepaste record in Expensify worden weergegeven?',
                         },
                         errors: {
-                            uniqueFieldError: (fieldName: string) => `Er bestaat al een aangepast segment/record met deze ${fieldName?.toLowerCase()}`,
+                            uniqueFieldError: ({fieldName}: RequiredFieldParams) => `Er bestaat al een aangepast segment/record met deze ${fieldName?.toLowerCase()}`,
                         },
                     },
                     customLists: {
@@ -5334,7 +4798,7 @@ _Voor meer gedetailleerde instructies, [bezoek onze help-site](${CONST.NETSUITE_
             employeeDefaultDescription: 'De standaardafdeling van de werknemer wordt, indien aanwezig, toegepast op hun uitgaven in Sage Intacct.',
             displayedAsTagDescription: 'Afdeling kan worden geselecteerd voor elke afzonderlijke uitgave op het rapport van de werknemer.',
             displayedAsReportFieldDescription: 'Afdelingsselectie is van toepassing op alle uitgaven in het rapport van een medewerker.',
-            toggleImportTitle: (mappingTitle: string) => `Kies hoe je Sage Intacct-<strong>${mappingTitle}</strong> in Expensify wilt verwerken.`,
+            toggleImportTitle: ({mappingTitle}: ToggleImportTitleParams) => `Kies hoe je Sage Intacct-<strong>${mappingTitle}</strong> in Expensify wilt verwerken.`,
             expenseTypes: 'Onkostypen',
             expenseTypesDescription: 'Je uitgavensoorten uit Sage Intacct worden in Expensify geïmporteerd als categorieën.',
             accountTypesDescription: 'Uw Sage Intacct-rekeningschema wordt in Expensify geïmporteerd als categorieën.',
@@ -5374,14 +4838,10 @@ _Voor meer gedetailleerde instructies, [bezoek onze help-site](${CONST.NETSUITE_
             free: 'Gratis',
             control: 'Beheer',
             collect: 'Incasseren',
-            submit: 'Indienen',
         },
         companyCards: {
             addCards: 'Kaarten toevoegen',
             selectCards: 'Kaarten selecteren',
-            fromOtherWorkspaces: 'Uit andere workspaces',
-            addWorkEmail: 'Voeg je werkmail toe',
-            addWorkEmailDescription: 'Voeg je werkmail toe om bestaande feeds van andere workspaces te gebruiken.',
             error: {
                 workspaceFeedsCouldNotBeLoadedTitle: 'Kaartfeeds konden niet worden geladen',
                 workspaceFeedsCouldNotBeLoadedMessage: 'Er is een fout opgetreden bij het laden van workspacekaartfeeds. Probeer het opnieuw of neem contact op met je beheerder.',
@@ -5391,11 +4851,6 @@ _Voor meer gedetailleerde instructies, [bezoek onze help-site](${CONST.NETSUITE_
             },
             addNewCard: {
                 other: 'Anders',
-                fileImport: 'Transacties uit bestand importeren',
-                createFileFeedHelpText: `<muted-text>Volg deze <a href="${CONST.COMPANY_CARDS_CREATE_FILE_FEED_HELP_URL}">hulpgids</a> om de uitgaven op je bedrijfskaarten te importeren!</muted-text>`,
-                companyCardLayoutName: 'Naam van lay-out van bedrijfskaart',
-                cardLayoutNameRequired: 'De naam van de lay-out van de bedrijfskaart is verplicht',
-                useAdvancedFields: 'Geavanceerde velden gebruiken (niet aanbevolen)',
                 cardProviders: {
                     gl1025: 'American Express Corporate Cards',
                     cdf: 'Mastercard Zakelijke Kaarten',
@@ -5474,27 +4929,6 @@ _Voor meer gedetailleerde instructies, [bezoek onze help-site](${CONST.NETSUITE_
                     confirmText: 'Probleem melden',
                     cancelText: 'Overslaan',
                 },
-                csvColumns: {
-                    cardNumber: 'Kaartnummer',
-                    postedDate: 'Datum',
-                    merchant: 'Handelaar',
-                    amount: 'Bedrag',
-                    currency: 'Valuta',
-                    ignore: 'Negeren',
-                    originalTransactionDate: 'Oorspronkelijke transactiedatum',
-                    originalAmount: 'Oorspronkelijk bedrag',
-                    originalCurrency: 'Oorspronkelijke valuta',
-                    comment: 'Opmerking',
-                    category: 'Categorie',
-                    tag: 'Label',
-                },
-                csvErrors: {
-                    requiredColumns: (missingColumns: string) => `Wijs een kolom toe aan elk van de attributen: ${missingColumns}.`,
-                    duplicateColumns: (duplicateColumn: string) =>
-                        `Oeps! Je hebt één enkel veld (“${duplicateColumn}”) aan meerdere kolommen gekoppeld. Controleer dit en probeer het opnieuw.`,
-                },
-                fileImportDescription: 'Een handmatige optie als je bank geen feed kan versturen.',
-                duplicateFeedModal: {title: 'Kaartfeed al verbonden', prompt: 'Je kunt dezelfde kaartfeed niet twee keer aan dezelfde workspace toevoegen.'},
             },
             statementCloseDate: {
                 [CONST.COMPANY_CARDS.STATEMENT_CLOSE_DATE.LAST_DAY_OF_MONTH]: 'Laatste dag van de maand',
@@ -5546,14 +4980,12 @@ _Voor meer gedetailleerde instructies, [bezoek onze help-site](${CONST.NETSUITE_
                 flipAmountSign: 'Teken van bedrag omdraaien',
                 importButton: 'Transacties importeren',
             },
-            deletedCard: 'Verwijderde kaart',
-            assignNewCards: {title: 'Nieuwe kaarten toewijzen', description: 'Haal de nieuwste kaarten op om toe te wijzen vanuit je bank'},
         },
         expensifyCard: {
-            issueAndManageCards: 'Geef Expensify Kaarten uit en beheer ze',
+            issueAndManageCards: 'Expensify Cards uitgeven en beheren',
             getStartedIssuing: 'Begin met het uitgeven van je eerste virtuele of fysieke kaart.',
             verificationInProgress: 'Verificatie wordt uitgevoerd...',
-            verifyingTheDetails: 'We controleren een paar gegevens. Concierge laat je weten wanneer Expensify Kaarten klaar zijn om uit te geven.',
+            verifyingTheDetails: 'We controleren een paar gegevens. Concierge laat je weten wanneer Expensify Cards klaar zijn om uit te geven.',
             disclaimer:
                 'De Expensify Visa® Commercial Card wordt uitgegeven door The Bancorp Bank, N.A., lid FDIC, krachtens een licentie van Visa U.S.A. Inc. en kan niet bij alle handelaren worden gebruikt die Visa-kaarten accepteren. Apple® en het Apple‑logo® zijn handelsmerken van Apple Inc., geregistreerd in de VS en andere landen. App Store is een dienstmerk van Apple Inc. Google Play en het Google Play‑logo zijn handelsmerken van Google LLC.',
             euUkDisclaimer:
@@ -5565,8 +4997,8 @@ _Voor meer gedetailleerde instructies, [bezoek onze help-site](${CONST.NETSUITE_
             lastFour: 'Laatste 4',
             limit: 'Limiet',
             currentBalance: 'Huidige saldo',
-            currentBalanceDescription: 'Het huidige saldo is de som van alle geboekte Expensify Kaart-transacties die hebben plaatsgevonden sinds de laatste afwikkelingsdatum.',
-            balanceWillBeSettledOn: (settlementDate: string) => `Saldo wordt vereffend op ${settlementDate}`,
+            currentBalanceDescription: 'Het huidige saldo is de som van alle geboekte Expensify Card-transacties die hebben plaatsgevonden sinds de laatste afwikkelingsdatum.',
+            balanceWillBeSettledOn: ({settlementDate}: SettlementDateParams) => `Saldo wordt vereffend op ${settlementDate}`,
             settleBalance: 'Saldo vereffenen',
             cardLimit: 'Kaartlimiet',
             remainingLimit: 'Resterende limiet',
@@ -5574,27 +5006,26 @@ _Voor meer gedetailleerde instructies, [bezoek onze help-site](${CONST.NETSUITE_
             remainingLimitDescription:
                 'We houden rekening met een aantal factoren bij het berekenen van je resterende limiet: hoe lang je al klant bent, de zakelijke informatie die je tijdens het aanmelden hebt verstrekt en het beschikbare saldo op je zakelijke bankrekening. Je resterende limiet kan dagelijks schommelen.',
             earnedCashback: 'Cashback',
-            earnedCashbackDescription: 'Cashbacksaldo is gebaseerd op de maandelijks vereffende uitgaven met de Expensify Kaart in je werkruimte.',
+            earnedCashbackDescription: 'Cashbacksaldo is gebaseerd op de afgerekende maandelijkse uitgaven met de Expensify Card binnen je workspace.',
             issueNewCard: 'Nieuwe kaart uitgeven',
             finishSetup: 'Configuratie voltooien',
             chooseBankAccount: 'Kies bankrekening',
-            chooseExistingBank: 'Kies een bestaande zakelijke bankrekening om je saldo van de Expensify Kaart te betalen, of voeg een nieuwe bankrekening toe',
+            chooseExistingBank: 'Kies een bestaande zakelijke bankrekening om je saldo van je Expensify Card te betalen, of voeg een nieuwe bankrekening toe',
             accountEndingIn: 'Rekening eindigend op',
             addNewBankAccount: 'Nieuwe bankrekening toevoegen',
             settlementAccount: 'Verrekeningsrekening',
-            settlementAccountDescription: 'Kies een rekening om je saldo van de Expensify Kaart te betalen.',
-            settlementAccountInfo: (reconciliationAccountSettingsLink: string, accountNumber: string) =>
+            settlementAccountDescription: 'Kies een rekening om het saldo van je Expensify Card te betalen.',
+            settlementAccountInfo: ({reconciliationAccountSettingsLink, accountNumber}: SettlementAccountInfoParams) =>
                 `Zorg ervoor dat deze rekening overeenkomt met je <a href="${reconciliationAccountSettingsLink}">afstemmingsrekening</a> (${accountNumber}), zodat Continue Afstemming correct werkt.`,
             settlementFrequency: 'Uitbetalingsfrequentie',
-            settlementFrequencyDescription: 'Kies hoe vaak je het saldo van je Expensify Kaart betaalt.',
+            settlementFrequencyDescription: 'Kies hoe vaak je je Expensify Card‑saldo wilt betalen.',
             settlementFrequencyInfo: 'Als je wilt overschakelen naar maandelijkse afrekening, moet je je bankrekening koppelen via Plaid en een positieve saldohistorie van 90 dagen hebben.',
-            applyCashbackToBill: 'Cashback toepassen op mijn Expensify-factuur',
-            applyCashbackToBillDescription: 'De cashback van de Expensify Kaart wordt gebruikt voor het betalen van je Expensify-factuur.',
             frequency: {
                 daily: 'Dagelijks',
                 monthly: 'Maandelijks',
             },
             cardDetails: 'Kaartgegevens',
+            cardPending: ({name}: {name: string}) => `De kaart is momenteel in behandeling en wordt uitgegeven zodra het account van ${name} is gevalideerd.`,
             virtual: 'Virtueel',
             physical: 'Fysiek',
             deactivate: 'Kaart deactiveren',
@@ -5611,28 +5042,24 @@ _Voor meer gedetailleerde instructies, [bezoek onze help-site](${CONST.NETSUITE_
             changeCardMonthlyLimitTypeWarning: (limit: number | string) =>
                 `Als je het limiettype van deze kaart wijzigt naar Maandelijks, worden nieuwe transacties geweigerd omdat de maandelijkse limiet van ${limit} al is bereikt.`,
             addShippingDetails: 'Verzendgegevens toevoegen',
-            issuedCard: (assignee: string) => `heeft ${assignee} een Expensify Kaart uitgegeven! De kaart wordt binnen 2-3 werkdagen bezorgd.`,
-            issuedCardNoShippingDetails: (assignee: string) => `heeft ${assignee} een Expensify Kaart uitgegeven! De kaart wordt verstuurd zodra de verzendgegevens zijn bevestigd.`,
-            issuedCardVirtual: (assignee: string, link: string) => `heeft ${assignee} een virtuele Expensify Kaart uitgegeven! De ${link} kan meteen worden gebruikt.`,
-            addedShippingDetails: (assignee: string) => `${assignee} heeft verzendgegevens toegevoegd. Expensify Kaart komt over 2-3 werkdagen aan.`,
-            replacedCard: (assignee: string) => `${assignee} heeft hun Expensify Kaart vervangen. De nieuwe kaart arriveert binnen 2-3 werkdagen.`,
-            replacedVirtualCard: (assignee: string, link: string) => `${assignee} heeft zijn/haar virtuele Expensify Kaart vervangen! De ${link} kan meteen worden gebruikt.`,
+            issuedCard: (assignee: string) => `heeft een Expensify Card uitgegeven aan ${assignee}! De kaart wordt binnen 2-3 werkdagen bezorgd.`,
+            issuedCardNoShippingDetails: (assignee: string) => `heeft een Expensify Card uitgegeven aan ${assignee}! De kaart wordt verzonden zodra de verzendgegevens zijn bevestigd.`,
+            issuedCardVirtual: (assignee: string, link: string) => `heeft een virtuele Expensify Card uitgegeven aan ${assignee}! De ${link} kan meteen worden gebruikt.`,
+            addedShippingDetails: (assignee: string) => `${assignee} heeft verzendgegevens toegevoegd. Expensify Card wordt binnen 2-3 werkdagen bezorgd.`,
+            replacedCard: (assignee: string) => `${assignee} heeft hun Expensify Card vervangen. De nieuwe kaart wordt binnen 2-3 werkdagen bezorgd.`,
+            replacedVirtualCard: (assignee: string, link: string) => `${assignee} heeft hun virtuele Expensify Card vervangen! De ${link} kan meteen worden gebruikt.`,
             card: 'kaart',
             replacementCard: 'vervangende kaart',
             verifyingHeader: 'Bezig met verifiëren',
             bankAccountVerifiedHeader: 'Bankrekening geverifieerd',
             verifyingBankAccount: 'Bankrekening verifiëren...',
-            verifyingBankAccountDescription: 'Wacht even terwijl we bevestigen dat deze rekening gebruikt kan worden om Expensify Kaarten uit te geven.',
+            verifyingBankAccountDescription: 'Even geduld terwijl we bevestigen dat deze account kan worden gebruikt om Expensify Cards uit te geven.',
             bankAccountVerified: 'Bankrekening geverifieerd!',
-            bankAccountVerifiedDescription: 'Je kunt nu Expensify Kaarten uitgeven aan de leden van je werkruimte.',
+            bankAccountVerifiedDescription: 'Je kunt nu Expensify Cards uitgeven aan de leden van je werkruimte.',
             oneMoreStep: 'Nog één stap...',
             oneMoreStepDescription: 'Het lijkt erop dat we je bankrekening handmatig moeten verifiëren. Ga naar Concierge, waar de instructies voor je klaarstaan.',
             gotIt: 'Begrepen',
             goToConcierge: 'Ga naar Concierge',
-            exportAsCSV: 'Exporteren als CSV',
-            csvColumnType: 'Type',
-            csvColumnLimitType: 'Limiettype',
-            csvColumnLimit: 'Limiet',
         },
         categories: {
             deleteCategories: 'Categorieën verwijderen',
@@ -5651,10 +5078,10 @@ _Voor meer gedetailleerde instructies, [bezoek onze help-site](${CONST.NETSUITE_
             needCategoryForExportToIntegration: (connectionName: string) => `Alle onkosten moeten worden gecategoriseerd om te kunnen exporteren naar ${connectionName}.`,
             subtitle: 'Krijg beter inzicht in waar geld wordt uitgegeven. Gebruik onze standaardcategorieën of voeg je eigen categorieën toe.',
             emptyCategories: {
-                title: 'Nog geen categorieën',
+                title: 'Je hebt nog geen categorieën aangemaakt',
                 subtitle: 'Voeg een categorie toe om je uitgaven te organiseren.',
-                subtitleWithAccounting: (accountingPageURL: string, canManage = true) =>
-                    `<muted-text><centered-text>Je categorieën worden momenteel geïmporteerd vanuit een boekhoudkoppeling.${canManage ? ` Ga naar <a href="${accountingPageURL}">Boekhouding</a> om wijzigingen aan te brengen.` : ''}</centered-text></muted-text>`,
+                subtitleWithAccounting: (accountingPageURL: string) =>
+                    `<muted-text><centered-text>Je categorieën worden momenteel geïmporteerd vanuit een boekhoudkoppeling. Ga naar <a href="${accountingPageURL}">Boekhouding</a> om wijzigingen aan te brengen.</centered-text></muted-text>`,
             },
             updateFailureMessage: 'Er is een fout opgetreden bij het bijwerken van de categorie, probeer het opnieuw',
             createFailureMessage: 'Er is een fout opgetreden bij het aanmaken van de categorie, probeer het opnieuw.',
@@ -5709,9 +5136,6 @@ _Voor meer gedetailleerde instructies, [bezoek onze help-site](${CONST.NETSUITE_
             travel: {
                 title: 'Reizen',
                 subtitle: 'Boek, beheer en reconcilieer al je zakelijke reizen.',
-                disableTravelTitle: 'Schakel eerst Reisfacturatie uit',
-                disableTravelPrompt: 'Reisfacturatie is ingeschakeld voor deze workspace. Schakel dit uit voordat je Reis kunt uitschakelen.',
-                disableTravelButton: 'Ga naar Reisinstellingen',
                 getStarted: {
                     title: 'Aan de slag met Expensify Travel',
                     subtitle: 'We hebben nog maar een paar extra gegevens over je bedrijf nodig, dan ben je klaar voor vertrek.',
@@ -5723,12 +5147,9 @@ _Voor meer gedetailleerde instructies, [bezoek onze help-site](${CONST.NETSUITE_
                     ctaText: 'Verzoek verzonden',
                 },
                 bookOrManageYourTrip: {
-                    title: 'Boeking van reizen',
-                    subtitle: 'Gefeliciteerd! Je bent helemaal klaar om reizen in deze workspace te boeken en te beheren.',
-                    ctaText: 'Reizen beheren',
-                },
-                settings: {
-                    autoAddTripName: {title: 'Reisnamen aan uitgaven toevoegen', subtitle: 'Voeg automatisch reisnamen toe aan onkostomemo’s voor reizen die in Expensify zijn geboekt.'},
+                    title: 'Boek of beheer je reis',
+                    subtitle: 'Gebruik Expensify Travel om de beste reisaanbiedingen te krijgen en al je zakelijke uitgaven op één plek te beheren.',
+                    ctaText: 'Boeken of beheren',
                 },
                 travelInvoicing: {
                     travelBookingSection: {
@@ -5736,53 +5157,29 @@ _Voor meer gedetailleerde instructies, [bezoek onze help-site](${CONST.NETSUITE_
                         subtitle: 'Gefeliciteerd! Je bent helemaal klaar om reizen in deze workspace te boeken en te beheren.',
                         manageTravelLabel: 'Reizen beheren',
                     },
-                    travelInvoicingSection: {
-                        title: 'Reisfacturatie',
+                    centralInvoicingSection: {
+                        title: 'Gecentraliseerde facturatie',
                         subtitle: 'Centraliseer alle reiskosten op één maandelijkse factuur in plaats van bij aankoop te betalen.',
                         learnHow: 'Kom meer te weten.',
                         subsections: {
                             currentTravelSpendLabel: 'Huidige reiskosten',
-                            currentTravelSpendPaymentQueued: (amount: string) => `Betaling van ${amount} staat in de wachtrij en wordt binnenkort verwerkt.`,
                             currentTravelSpendCta: 'Saldo betalen',
                             currentTravelLimitLabel: 'Huidige reisl imiet',
                             settlementAccountLabel: 'Verrekeningsrekening',
                             settlementFrequencyLabel: 'Uitbetalingsfrequentie',
                             settlementFrequencyDescription: 'Hoe vaak Expensify geld van uw zakelijke bankrekening zal incasseren om recente Expensify Travel-transacties te vereffenen.',
-                            monthlySpendLimitLabel: 'Maandelijks bestedingslimiet per lid',
-                            monthlySpendLimitDescription: 'Het maximale bedrag dat elk lid per maand aan reizen kan besteden.',
-                            reduceLimitTitle: 'Reisbestedingslimiet verlagen?',
-                            reduceLimitWarning: 'Als u het limiet verlaagt, kunnen leden die dit bedrag al hebben overschreden geen nieuwe reisboekingen maken tot volgende maand.',
-                            provisioningError:
-                                'We konden voor sommige leden van je workspace geen toegang voor reisfacturatie instellen. Probeer het later opnieuw of neem contact op met Concierge voor hulp.',
                         },
                     },
-                    disableModal: {
-                        title: 'Reisfacturatie uitschakelen?',
-                        body: 'Toekomstige hotel en autoverhuurreserveringen moeten mogelijk opnieuw worden geboekt met een andere betaalmethode om annulering te voorkomen.',
-                        confirm: 'Uitschakelen',
-                    },
-                    outstandingBalanceModal: {title: 'Kan Reiskostenfacturatie niet uitschakelen', body: 'Je hebt nog een openstaand reissaldo. Betaal eerst je saldo.', confirm: 'Begrepen'},
-                    payBalanceModal: {
-                        title: (amount: string) => `Saldo van ${amount} betalen?`,
-                        body: 'De betaling wordt in de wachtrij gezet en kort daarna verwerkt. Deze actie kan niet ongedaan worden gemaakt zodra ze is gestart.',
-                    },
-                    exportToPDF: 'Exporteren naar PDF',
-                    exportToCSV: 'Exporteren naar CSV',
-                    selectDateRangeError: 'Selecteer een datumbereik om te exporteren',
-                    invalidDateRangeError: 'De begindatum moet vóór de einddatum liggen',
-                    enabled: 'Facturatie voor reizen ingeschakeld!',
-                    enabledDescription: 'Alle reiskosten in deze workspace worden nu gebundeld op één maandelijkse factuur.',
                 },
-                personalDetailsDescription: 'Om een reis te boeken, voer je wettelijke naam in zoals deze op je door de overheid uitgegeven identiteitsbewijs staat.',
             },
             expensifyCard: {
-                title: 'Expensify Kaart',
+                title: 'Expensify Card',
                 subtitle: 'Krijg inzicht en grip op uitgaven.',
-                disableCardTitle: 'Expensify Kaart uitschakelen',
-                disableCardPrompt: 'Je kunt de Expensify Kaart niet deactiveren omdat deze al in gebruik is. Neem contact op met Concierge voor de volgende stappen.',
+                disableCardTitle: 'Expensify Card uitschakelen',
+                disableCardPrompt: 'Je kunt de Expensify Card niet uitschakelen omdat deze al in gebruik is. Neem contact op met Concierge voor de volgende stappen.',
                 disableCardButton: 'Chatten met Concierge',
                 feed: {
-                    title: 'Vraag de Expensify Kaart aan',
+                    title: 'Vraag de Expensify-kaart aan',
                     subTitle: 'Stroomlijn je zakelijke uitgaven en bespaar tot 50% op je Expensify‑rekening, plus:',
                     features: {
                         cashBack: 'Cashback op elke aankoop in de VS',
@@ -5806,7 +5203,7 @@ _Voor meer gedetailleerde instructies, [bezoek onze help-site](${CONST.NETSUITE_
                 },
                 bankConnectionError: 'Probleem met bankverbinding',
                 connectWithPlaid: 'verbinden via Plaid',
-                connectWithExpensifyCard: 'probeer de Expensify Kaart.',
+                connectWithExpensifyCard: 'probeer de Expensify Card.',
                 bankConnectionDescription: `Probeer je kaarten opnieuw toe te voegen. Anders kun je`,
                 disableCardTitle: 'Bedrijfskaarten uitschakelen',
                 disableCardPrompt: 'Je kunt bedrijfskaarten niet uitschakelen omdat deze functie in gebruik is. Neem contact op met de Concierge voor de volgende stappen.',
@@ -5827,10 +5224,7 @@ _Voor meer gedetailleerde instructies, [bezoek onze help-site](${CONST.NETSUITE_
                 updateCard: 'Kaart bijwerken',
                 unassignCard: 'Kaart loskoppelen',
                 unassign: 'Toewijzen ongedaan maken',
-                unassignCardDescription: 'Het loskoppelen van deze kaart verwijdert alle niet-ingediende transacties.',
-                removeCard: 'Kaart verwijderen',
-                remove: 'Verwijderen',
-                removeCardDescription: 'Als je deze kaart verwijdert, worden alle niet-ingediende transacties verwijderd.',
+                unassignCardDescription: 'Deze kaart loskoppelen verwijdert alle transacties op conceptrapporten uit de rekening van de kaarthouder.',
                 assignCard: 'Kaart toewijzen',
                 cardFeedName: 'Naam van kaartfeed',
                 cardFeedNameDescription: 'Geef de kaartfeed een unieke naam zodat je deze kunt onderscheiden van de andere.',
@@ -5862,9 +5256,9 @@ _Voor meer gedetailleerde instructies, [bezoek onze help-site](${CONST.NETSUITE_
                 noAccountsFound: 'Geen accounts gevonden',
                 defaultCard: 'Standaardkaart',
                 downgradeTitle: `Kan werkruimte niet downgraden`,
-                downgradeSubTitle: `Deze workspace kan niet worden gedowngradet omdat meerdere kaartfeeds zijn verbonden (met uitzondering van Expensify Kaarten). <a href="#">Beperk het aantal kaartfeeds tot één</a> om door te gaan.`,
+                downgradeSubTitle: `Deze workspace kan niet worden gedowngraded omdat er meerdere kaartfeeds zijn verbonden (met uitzondering van Expensify Cards). <a href="#">Beperk het tot één kaartfeed</a> om door te gaan.`,
                 noAccountsFoundDescription: (connection: string) => `Voeg de rekening toe in ${connection} en synchroniseer de koppeling opnieuw`,
-                expensifyCardBannerTitle: 'Vraag de Expensify Kaart aan',
+                expensifyCardBannerTitle: 'Vraag de Expensify-kaart aan',
                 expensifyCardBannerSubtitle: 'Geniet van cashback op elke aankoop in de VS, tot 50% korting op je Expensify‑rekening, onbeperkte virtuele kaarten en nog veel meer.',
                 expensifyCardBannerLearnMoreButton: 'Meer informatie',
                 statementCloseDateTitle: 'Sluitingsdatum afschrift',
@@ -5874,7 +5268,7 @@ _Voor meer gedetailleerde instructies, [bezoek onze help-site](${CONST.NETSUITE_
                 title: 'Workflows',
                 subtitle: 'Configureer hoe uitgaven worden goedgekeurd en betaald.',
                 disableApprovalPrompt:
-                    'Expensify Kaarten van deze workspace zijn op dit moment afhankelijk van goedkeuring om hun Smart Limits te bepalen. Pas de limiettypen van alle Expensify Kaarten met Smart Limits aan voordat je goedkeuringen uitschakelt.',
+                    'Expensify Cards van deze workspace zijn momenteel afhankelijk van goedkeuring om hun Smart Limits te bepalen. Pas de limiettypen van alle Expensify Cards met Smart Limits aan voordat je goedkeuringen uitschakelt.',
             },
             invoices: {
                 title: 'Facturen',
@@ -5919,8 +5313,8 @@ _Voor meer gedetailleerde instructies, [bezoek onze help-site](${CONST.NETSUITE_
             workflowWarningModal: {
                 featureEnabledTitle: 'Niet zo snel...',
                 featureEnabledText:
-                    'Expensify Kaarten in deze workspace maken gebruik van goedkeuringsworkflows om hun Smart Limits te bepalen.\n\nWijzig het limiettype van alle kaarten met Smart Limits voordat je workflows uitschakelt.',
-                confirmText: 'Ga naar Expensify Kaarten',
+                    'Expensify Cards in deze workspace zijn afhankelijk van goedkeuringsworkflows om hun Smart Limits te bepalen.\n\nWijzig het type limiet van alle kaarten met Smart Limits voordat je workflows uitschakelt.',
+                confirmText: 'Ga naar Expensify Cards',
             },
             rules: {
                 title: 'Regels',
@@ -5931,7 +5325,6 @@ _Voor meer gedetailleerde instructies, [bezoek onze help-site](${CONST.NETSUITE_
                 subtitle: 'Stel een factureerbaar uurtarief in voor tijdregistratie.',
                 defaultHourlyRate: 'Standaard uurtarief',
             },
-            hrWarningModal: {disconnectText: ({integration}: {integration: string}) => `Om HR uit te schakelen, koppel eerst ${integration} los van deze workspace.`},
         },
         reports: {
             reportsCustomTitleExamples: 'Voorbeelden:',
@@ -5953,7 +5346,10 @@ _Voor meer gedetailleerde instructies, [bezoek onze help-site](${CONST.NETSUITE_
             findReportField: 'Rapportveld zoeken',
             deleteConfirmation: 'Weet je zeker dat je dit rapportveld wilt verwijderen?',
             deleteFieldsConfirmation: 'Weet je zeker dat je deze rapportvelden wilt verwijderen?',
-            emptyReportFields: {title: 'Nog geen rapportvelden', subtitle: 'Voeg een aangepast veld toe (tekst, datum of keuzemenu) dat op rapporten verschijnt.'},
+            emptyReportFields: {
+                title: 'Je hebt nog geen rapportvelden aangemaakt',
+                subtitle: 'Voeg een aangepast veld toe (tekst, datum of keuzemenu) dat op rapporten verschijnt.',
+            },
             subtitle: 'Rapportvelden zijn van toepassing op alle uitgaven en kunnen nuttig zijn wanneer je om extra informatie wilt vragen.',
             disableReportFields: 'Rapportvelden uitschakelen',
             disableReportFieldsConfirmation: 'Weet je het zeker? Tekst- en datumvelden worden verwijderd en lijsten worden uitgeschakeld.',
@@ -5977,7 +5373,10 @@ _Voor meer gedetailleerde instructies, [bezoek onze help-site](${CONST.NETSUITE_
             disableValues: 'Waarden uitschakelen',
             enableValue: 'Waarde inschakelen',
             enableValues: 'Waarden inschakelen',
-            emptyReportFieldsValues: {title: 'Nog geen lijstwaarden', subtitle: 'Voeg aangepaste waarden toe die op rapporten worden weergegeven.'},
+            emptyReportFieldsValues: {
+                title: 'Je hebt nog geen lijstwaarden gemaakt',
+                subtitle: 'Voeg aangepaste waarden toe die op rapporten worden weergegeven.',
+            },
             deleteValuePrompt: 'Weet je zeker dat je deze lijstwaarde wilt verwijderen?',
             deleteValuesPrompt: 'Weet je zeker dat je deze lijstwaarden wilt verwijderen?',
             listValueRequiredError: 'Voer een naam voor de lijstwaarde in',
@@ -5989,33 +5388,9 @@ _Voor meer gedetailleerde instructies, [bezoek onze help-site](${CONST.NETSUITE_
             reportFieldNameRequiredError: 'Voer een naam voor een rapportveld in',
             reportFieldTypeRequiredError: 'Kies een veldtype voor het rapport',
             circularReferenceError: 'Dit veld kan niet naar zichzelf verwijzen. Werk het alsjeblieft bij.',
-            unsupportedFormulaValueError: ({value}: UnsupportedFormulaValueErrorParams) => `Formuleveld ${value} niet herkend`,
             reportFieldInitialValueRequiredError: 'Kies een beginwaarde voor een rapportveld',
             genericFailureMessage: 'Er is een fout opgetreden bij het bijwerken van het rapportveld. Probeer het opnieuw.',
         },
-        invoiceFields: {
-            subtitle: 'Factuurvelden kunnen handig zijn als je extra informatie wilt toevoegen.',
-            importedFromAccountingSoftware: 'De onderstaande factuurvelden zijn geïmporteerd uit je',
-            disableInvoiceFields: 'Factuurvelden uitschakelen',
-            disableInvoiceFieldsConfirmation: 'Weet je het zeker? Factuurvelden worden uitgeschakeld op facturen.',
-            delete: 'Factuurveld verwijderen',
-            deleteConfirmation: 'Weet je zeker dat je dit factuurveld wilt verwijderen?',
-            findInvoiceField: 'Factuurveld zoeken',
-            nameInputSubtitle: 'Kies een naam voor het factuurveld.',
-            typeInputSubtitle: 'Kies welk type factuurveld je wilt gebruiken.',
-            initialValueInputSubtitle: 'Voer een beginwaarde in om in het factuurveld weer te geven.',
-            listValuesInputSubtitle: 'Deze waarden verschijnen in de vervolgkeuzelijst van je factuurveld. Ingeschakelde waarden kunnen door leden worden geselecteerd.',
-            listInputSubtitle: 'Deze waarden verschijnen in je factuurveldenlijst. Ingeschakelde waarden kunnen door leden worden geselecteerd.',
-            emptyInvoiceFieldsValues: {
-                title: 'Nog geen lijstwaarden',
-                subtitle: 'Voeg aangepaste waarden toe om op facturen te tonen.',
-            },
-            existingInvoiceFieldNameError: 'Er bestaat al een factuurveld met deze naam',
-            invoiceFieldNameRequiredError: 'Voer een naam voor een factuurveld in',
-            invoiceFieldTypeRequiredError: 'Kies een veldtype voor de factuur',
-            invoiceFieldInitialValueRequiredError: 'Kies een beginwaarde voor een factuurveld',
-            addField: 'Veld toevoegen',
-        },
         tags: {
             tagName: 'Tagnaam',
             requiresTag: 'Leden moeten alle uitgaven taggen',
@@ -6033,14 +5408,14 @@ _Voor meer gedetailleerde instructies, [bezoek onze help-site](${CONST.NETSUITE_
             editTags: 'Tags bewerken',
             findTag: 'Tag zoeken',
             subtitle: 'Labels bieden meer gedetailleerde manieren om kosten te classificeren.',
-            subtitleWithDependentTags: (importSpreadsheetLink: string, canReimport = true) =>
-                `<muted-text>Labels bieden meer gedetailleerde manieren om kosten te classificeren. Je gebruikt <a href="${CONST.IMPORT_TAGS_EXPENSIFY_URL_DEPENDENT_TAGS}">afhankelijke labels</a>.${canReimport ? ` Je kunt <a href="${importSpreadsheetLink}">een spreadsheet opnieuw importeren</a> om je labels bij te werken.` : ''}</muted-text>`,
+            dependentMultiLevelTagsSubtitle: (importSpreadsheetLink: string) =>
+                `<muted-text>Je gebruikt <a href="${CONST.IMPORT_TAGS_EXPENSIFY_URL_DEPENDENT_TAGS}">afhankelijke labels</a>. Je kunt <a href="${importSpreadsheetLink}">een spreadsheet opnieuw importeren</a> om je labels bij te werken.</muted-text>`,
             emptyTags: {
-                title: 'Nog geen tags',
+                title: 'Je hebt nog geen labels gemaakt',
                 subtitle: 'Voeg een tag toe om projecten, locaties, afdelingen en meer bij te houden.',
                 subtitleHTML: `<muted-text><centered-text>Voeg tags toe om projecten, locaties, afdelingen en meer bij te houden. <a href="${CONST.IMPORT_TAGS_EXPENSIFY_URL}">Meer informatie</a> over het formatteren van tagbestanden voor import.</centered-text></muted-text>`,
-                subtitleWithAccounting: (accountingPageURL: string, canManage = true) =>
-                    `<muted-text><centered-text>Je tags worden momenteel geïmporteerd via een boekhoudkoppeling.${canManage ? ` Ga naar <a href="${accountingPageURL}">Boekhouding</a> om wijzigingen aan te brengen.` : ''}</centered-text></muted-text>`,
+                subtitleWithAccounting: (accountingPageURL: string) =>
+                    `<muted-text><centered-text>Je tags worden momenteel geïmporteerd via een boekhoudkoppeling. Ga naar <a href="${accountingPageURL}">Boekhouding</a> om wijzigingen aan te brengen.</centered-text></muted-text>`,
             },
             deleteTag: 'Tag verwijderen',
             deleteTags: 'Labels verwijderen',
@@ -6126,7 +5501,7 @@ _Voor meer gedetailleerde instructies, [bezoek onze help-site](${CONST.NETSUITE_
                 updateTaxClaimableFailureMessage: 'Het terugvorderbare deel moet lager zijn dan het kilometertariefbedrag',
             },
             deleteTaxConfirmation: 'Weet je zeker dat je deze belasting wilt verwijderen?',
-            deleteMultipleTaxConfirmation: (taxAmount: number) => `Weet je zeker dat je ${taxAmount} belastingen wilt verwijderen?`,
+            deleteMultipleTaxConfirmation: ({taxAmount}: TaxAmountParams) => `Weet je zeker dat je ${taxAmount} belastingen wilt verwijderen?`,
             actions: {
                 delete: 'Tarief verwijderen',
                 deleteMultiple: 'Tarieven verwijderen',
@@ -6154,46 +5529,10 @@ _Voor meer gedetailleerde instructies, [bezoek onze help-site](${CONST.NETSUITE_
             reimbursementAccount: 'vergoedingsrekening',
             welcomeNote: 'Begin alsjeblieft mijn nieuwe werkruimte te gebruiken',
             delayedSubmission: 'vertraagde indiening',
-            merchantRules: 'Handelaarsregels',
-            merchantRulesCount: () => ({
-                one: '1 handelaarsregel',
-                other: (count: number) => `${count} handelaarsregels`,
-            }),
             confirmTitle: ({newWorkspaceName, totalMembers}: {newWorkspaceName?: string; totalMembers?: number}) =>
                 `Je staat op het punt ${newWorkspaceName ?? ''} te maken en te delen met ${totalMembers ?? 0} leden van de oorspronkelijke werkruimte.`,
             error: 'Er is een fout opgetreden bij het dupliceren van je nieuwe werkruimte. Probeer het opnieuw.',
         },
-        copyPolicySettings: {
-            title: 'Instellingen kopiëren',
-            error: 'Er is een fout opgetreden bij het kopiëren van de werkruimtainstellingen. Probeer het opnieuw.',
-            selectWorkspaces: {
-                title: 'Selecteer werkruimtes',
-                description: 'Kies de werkruimtes waarnaar je instellingen wilt kopiëren en selecteer daarna de instellingen die je wilt kopiëren.',
-                searchPlaceholder: 'Werkruimtes zoeken',
-            },
-            selectSettings: {
-                title: 'Selecteer functies om te kopiëren',
-                description: 'Selecteer de instellingen die je wilt overschrijven in je bestaande werkruimtes.',
-                accountingMismatch: ({part}: {part: string}) => `Je kunt ${part} alleen kopiëren als alle werkruimtes hetzelfde boekhoudsysteem en dezelfde bedrijfsverbinding gebruiken.`,
-            },
-            confirmSettings: {
-                title: 'Laten we controleren of alles er goed uitziet.',
-                description: ({workspaceName}: {workspaceName: string}) =>
-                    `We kopiëren de volgende instellingen van <strong>${workspaceName}</strong> naar de werkruimtes die je hebt opgegeven`,
-            },
-            confirmWorkflows: {
-                continue: 'Doorgaan zonder leden',
-                description: 'Workflows kopiëren zonder leden zal goedkeuringsworkflows niet kopiëren. Instellingen voor indienen en betalen worden nog steeds gekopieerd.',
-            },
-            progress: {
-                copyInProgressTitle: 'Kopie wordt gemaakt...',
-                copyInProgressDescription: 'Je kunt wachten tot het proces is voltooid, of Concierge kan je laten weten wanneer het klaar is.',
-                letMeKnowPrompt: 'Laat het me weten als het klaar is',
-                conciergeNotificationTitle: 'Concierge laat je het weten',
-                conciergeNotificationDescription: 'Wanneer het proces is afgerond, stuurt Concierge je een bericht.',
-                copyCompleted: 'Je werkruimte-instellingen zijn gekopieerd.',
-            },
-        },
         emptyWorkspace: {
             title: 'Je hebt geen werkruimtes',
             subtitle: 'Volg bonnen, vergoed uitgaven, beheer reizen, verstuur facturen en meer.',
@@ -6208,7 +5547,7 @@ _Voor meer gedetailleerde instructies, [bezoek onze help-site](${CONST.NETSUITE_
         },
         new: {
             newWorkspace: 'Nieuwe workspace',
-            getTheExpensifyCardAndMore: 'Krijg de Expensify Kaart en meer',
+            getTheExpensifyCardAndMore: 'Krijg de Expensify Card en meer',
             confirmWorkspace: 'Werkruimte bevestigen',
             myGroupWorkspace: ({workspaceNumber}: {workspaceNumber?: number}) => `Mijn groepswerkruimte${workspaceNumber ? ` ${workspaceNumber}` : ''}`,
             workspaceName: (userName: string, workspaceNumber?: number) => `Workspace van ${userName}${workspaceNumber ? ` ${workspaceNumber}` : ''}`,
@@ -6251,12 +5590,12 @@ _Voor meer gedetailleerde instructies, [bezoek onze help-site](${CONST.NETSUITE_
                 genericRemove: 'Er is een probleem opgetreden bij het verwijderen van dat werkpleklid',
             },
             addedWithPrimary: 'Sommige leden zijn toegevoegd met hun primaire login.',
-            invitedBySecondaryLogin: (secondaryLogin: string) => `Toegevoegd door secundair login ${secondaryLogin}.`,
-            workspaceMembersCount: (count: number) => `Totaal aantal werkruimteleden: ${count}`,
+            invitedBySecondaryLogin: ({secondaryLogin}: SecondaryLoginParams) => `Toegevoegd door secundair login ${secondaryLogin}.`,
+            workspaceMembersCount: ({count}: WorkspaceMembersCountParams) => `Totaal aantal werkruimteleden: ${count}`,
             importMembers: 'Leden importeren',
-            removeMemberPromptApprover: (approver: string, workspaceOwner: string) =>
+            removeMemberPromptApprover: ({approver, workspaceOwner}: {approver: string; workspaceOwner: string}) =>
                 `Als je ${approver} uit deze workspace verwijdert, vervangen we diegene in de goedkeuringsworkflow door ${workspaceOwner}, de eigenaar van de workspace.`,
-            removeMemberPromptPendingApproval: (memberName: string) =>
+            removeMemberPromptPendingApproval: ({memberName}: {memberName: string}) =>
                 `${memberName} heeft openstaande onkostendeclaraties om goed te keuren. Vraag hen deze goed te keuren, of neem de controle over hun declaraties voordat je hen uit de workspace verwijdert.`,
             removeMemberPromptReimburser: ({memberName}: {memberName: string}) =>
                 `Je kunt ${memberName} niet uit deze werkruimte verwijderen. Stel eerst een nieuwe terugbetaler in via Workflows > Betalingen doen of volgen en probeer het dan opnieuw.`,
@@ -6266,20 +5605,10 @@ _Voor meer gedetailleerde instructies, [bezoek onze help-site](${CONST.NETSUITE_
                 `Als je ${memberName} uit deze workspace verwijdert, vervangen we hen als technisch contactpersoon door ${workspaceOwner}, de eigenaar van de workspace.`,
             cannotRemoveUserDueToReport: ({memberName}: {memberName: string}) =>
                 `${memberName} heeft een openstaand rapport in verwerking waarop actie moet worden ondernomen. Vraag hen dit vereiste actiepunt af te ronden voordat je hen uit de workspace verwijdert.`,
-            allMembers: 'Alle leden',
-            admins: 'Werkruimtebeheerders',
-            cardAdmins: 'Kaartbeheerders',
-            approvers: 'Fiatteurs',
-            auditors: 'Accountants',
-            emptyRoleFilter: {title: 'Geen leden komen overeen met dit filter', subtitle: 'Nodig een lid uit of wijzig het filter hierboven.'},
-            configureHRSync: (providerName: string) => `Stel ${providerName}-synchronisatie in.`,
-            syncWithHR: (providerName: string) => `Synchroniseren met ${providerName}`,
-            makeCardAdmin: () => ({one: 'Kaartbeheerder maken', other: 'Maak kaartbeheerders'}),
         },
         card: {
             getStartedIssuing: 'Begin met het uitgeven van je eerste virtuele of fysieke kaart.',
             issueCard: 'Kaart uitgeven',
-            chooseRule: 'Kies een regel',
             issueNewCard: {
                 whoNeedsCard: 'Wie heeft er een kaart nodig?',
                 inviteNewMember: 'Nieuw lid uitnodigen',
@@ -6321,27 +5650,22 @@ _Voor meer gedetailleerde instructies, [bezoek onze help-site](${CONST.NETSUITE_
                 enterValidDate: 'Voer een geldige datum in',
                 expirationDate: 'Vervaldatum',
                 limitAmount: 'Limietbedrag',
-                setCardRules: 'Kaartregels instellen',
-                addSpendRule: 'Uitgavenregel toevoegen',
-                addExpirationDate: 'Vervaldatum toevoegen',
-                addExpirationDateDescription: 'Als er geen specifieke datum is ingesteld, verloopt de kaart op basis van de bestaande vervaldatum op de kaart',
+                setExpiryOptions: 'Vervalopties instellen',
+                setExpiryDate: 'Vervaldatum instellen',
+                setExpiryDateDescription: 'De kaart verloopt zoals vermeld op de kaart',
                 amount: 'Bedrag',
-                copyExisting: 'Bestaande kopiëren',
-                createNew: 'Nieuw maken',
-                spendRulesEmptyStateTitle: 'Geen regels om uit te kiezen',
-                spendRulesEmptyStateSubtitle: 'Nog geen regels. Je kunt er een aanmaken vanaf het vorige scherm.',
             },
             deactivateCardModal: {
                 deactivate: 'Deactiveren',
                 deactivateCard: 'Kaart deactiveren',
                 deactivateConfirmation: 'Als je deze kaart deactiveert, worden alle toekomstige transacties geweigerd en dit kan niet ongedaan worden gemaakt.',
             },
-            searchRules: 'Uitgavenregel zoeken',
         },
         accounting: {
             settings: 'instellingen',
             title: 'Verbindingen',
-            subtitle: 'Verbind je boekhoudsoftware voor een automatische synchronisatie.',
+            subtitle:
+                'Maak verbinding met je boekhoudsysteem om transacties te coderen met je grootboekrekeningen, betalingen automatisch te matchen en je financiën gesynchroniseerd te houden.',
             qbo: 'QuickBooks Online',
             qbd: 'QuickBooks Desktop',
             xero: 'Xero',
@@ -6350,7 +5674,7 @@ _Voor meer gedetailleerde instructies, [bezoek onze help-site](${CONST.NETSUITE_
             sap: 'SAP',
             oracle: 'Oracle',
             microsoftDynamics: 'Microsoft Dynamics',
-            talkYourOnboardingSpecialist: 'Chat met je accountmanager.',
+            talkYourOnboardingSpecialist: 'Chat met je installatiespecialist.',
             talkYourAccountManager: 'Chat met je accountmanager.',
             talkToConcierge: 'Chat met Concierge.',
             needAnotherAccounting: 'Nog een boekhoudprogramma nodig?',
@@ -6425,8 +5749,6 @@ _Voor meer gedetailleerde instructies, [bezoek onze help-site](${CONST.NETSUITE_
             connectPrompt: ({connectionName}: ConnectionNameParams) =>
                 `Weet je zeker dat je ${CONST.POLICY.CONNECTIONS.NAME_USER_FRIENDLY[connectionName] ?? 'deze boekhoudkoppeling'} wilt koppelen? Hierdoor worden alle bestaande boekhoudkundige koppelingen verwijderd.`,
             enterCredentials: 'Voer je inloggegevens in',
-            reconnect: 'Opnieuw verbinden',
-            updateCredentials: 'Inloggegevens bijwerken',
             claimOffer: {
                 badgeText: 'Aanbieding beschikbaar!',
                 xero: {
@@ -6569,26 +5891,6 @@ _Voor meer gedetailleerde instructies, [bezoek onze help-site](${CONST.NETSUITE_
                             return 'Sage Intacct-dimensies importeren';
                         case 'intacctImportTitle':
                             return 'Sage Intacct-gegevens importeren';
-                        case 'financialForceSyncTitle':
-                            return 'Certinia-gegevens synchroniseren';
-                        case 'financialForceSyncStep':
-                            return 'Certinia-verbinding synchroniseren';
-                        case 'financialForceSyncCategories':
-                            return 'Categorieen importeren';
-                        case 'financialForceSyncTags':
-                            return 'Tags importeren';
-                        case 'financialForceSyncVendors':
-                            return 'Leveranciers importeren';
-                        case 'financialForceSyncContacts':
-                            return 'Contacten importeren';
-                        case 'financialForceSyncCompanies':
-                            return 'Bedrijven importeren';
-                        case 'financialForceSyncUsers':
-                            return 'Gebruikers importeren';
-                        case 'financialForceSyncDimensions':
-                            return 'Dimensies importeren';
-                        case 'financialForceMarkAsReimbursed':
-                            return 'Rapporten als vergoed markeren';
                         default: {
                             return `Vertaling ontbreekt voor fase: ${stage}`;
                         }
@@ -6611,18 +5913,14 @@ _Voor meer gedetailleerde instructies, [bezoek onze help-site](${CONST.NETSUITE_
             reconciliationAccount: 'Rekening voor afstemming',
             continuousReconciliation: 'Continue reconciliëren',
             saveHoursOnReconciliation:
-                'Bespaar elke boekhoudperiode uren op de reconciliatie door Expensify doorlopend de afschriften en afwikkelingen van je Expensify Kaart voor je te laten afstemmen.',
+                'Bespaar elke boekhoudperiode uren op de afstemming door Expensify continu de Expensify Card‑afschriften en -afwikkelingen voor je te laten afstemmen.',
             enableContinuousReconciliation: (accountingAdvancedSettingsLink: string, connectionName: string) =>
                 `<muted-text-label>Schakel voor het inschakelen van Continuous Reconciliation de <a href="${accountingAdvancedSettingsLink}">automatische synchronisatie</a> in voor ${connectionName}.</muted-text-label>`,
             chooseReconciliationAccount: {
-                chooseBankAccount: 'Kies de bankrekening waarop de betalingen met je Expensify Kaart worden afgestemd.',
-                settlementAccountReconciliation: (settlementAccountUrl: string, lastFourPAN: string) =>
-                    `Zorg ervoor dat deze rekening overeenkomt met je <a href="${settlementAccountUrl}">Expensify Kaart-afwikkelingsrekening</a> (eindigend op ${lastFourPAN}), zodat Continue Afstemming goed werkt.`,
-                chooseTravelInvoicingBankAccount: 'Kies de bankrekening waarop de betalingen van je reiskostenfacturen worden afgeletterd.',
-                travelInvoicingSettlementAccountReconciliation: (lastFourPAN: string) =>
-                    `Zorg ervoor dat deze rekening overeenkomt met je afwikkelingsrekening voor reiskostenfacturatie (die eindigt op ${lastFourPAN}), zodat Continue Afstemming goed werkt.`,
+                chooseBankAccount: 'Kies de bankrekening waarop je betalingen met de Expensify Card worden afgestemd.',
+                settlementAccountReconciliation: ({settlementAccountUrl, lastFourPAN}: SettlementAccountReconciliationParams) =>
+                    `Zorg ervoor dat deze rekening overeenkomt met je <a href="${settlementAccountUrl}">Expensify Card-afwikkelingsrekening</a> (eindigend op ${lastFourPAN}), zodat Continue Afstemmen goed werkt.`,
             },
-            syncTravelInvoicingSettlements: 'Reisfactureringsafrekeningen synchroniseren',
         },
         export: {
             notReadyHeading: 'Niet klaar om te exporteren',
@@ -6702,13 +6000,7 @@ _Voor meer gedetailleerde instructies, [bezoek onze help-site](${CONST.NETSUITE_
             errors: {
                 rateNameRequired: 'Tariefnaam is verplicht',
                 existingRateName: 'Er bestaat al een afstandstarief met deze naam',
-                nameRequired: 'Naam is verplicht',
-                startDateMustBeBeforeEndDate: 'Begindatum moet vóór de einddatum liggen',
-                amountRequired: 'Bedrag is verplicht',
             },
-            amountPerUnit: (unit: string) => `Bedrag per ${unit}`,
-            startDate: 'Startdatum',
-            endDate: 'Einddatum',
         },
         editor: {
             descriptionInputLabel: 'Beschrijving',
@@ -6751,7 +6043,7 @@ _Voor meer gedetailleerde instructies, [bezoek onze help-site](${CONST.NETSUITE_
             updateToUSD: 'Bijwerken naar USD',
             updateWorkspaceCurrency: 'Werkruimtevaluta bijwerken',
             workspaceCurrencyNotSupported: 'Werkruimtevaluta wordt niet ondersteund',
-            yourWorkspace: `Je werkruimte is ingesteld op een niet-ondersteunde valuta. Bekijk de <a href="${CONST.ENABLE_GLOBAL_REIMBURSEMENT_HELP_URL}">lijst met ondersteunde valuta's</a>.`,
+            yourWorkspace: `Je werkruimte is ingesteld op een niet-ondersteunde valuta. Bekijk de <a href="${CONST.CONNECT_A_BUSINESS_BANK_ACCOUNT_HELP_URL}">lijst met ondersteunde valuta's</a>.`,
             chooseAnExisting: 'Kies een bestaande bankrekening om onkosten te betalen of voeg een nieuwe toe.',
         },
         changeOwner: {
@@ -6788,7 +6080,7 @@ Als je de facturering voor hun volledige abonnement wilt overnemen, laat hen je
             hasFailedSettlementsTitle: 'Kan eigendom niet overdragen',
             hasFailedSettlementsButtonText: 'Begrepen',
             hasFailedSettlementsText: (email: string) =>
-                `Je kunt de facturering niet overnemen omdat ${email} een achterstallige afrekening voor de Expensify Kaart heeft. Vraag hen om contact op te nemen met concierge@expensify.com om het probleem op te lossen. Daarna kun je de facturering voor deze werkruimte overnemen.`,
+                `Je kunt de facturering niet overnemen omdat ${email} een achterstallige Expensify Card‑afrekening heeft. Vraag hen om contact op te nemen met concierge@expensify.com om het probleem op te lossen. Daarna kun je de facturering voor deze werkruimte overnemen.`,
             failedToClearBalanceTitle: 'Saldo wissen mislukt',
             failedToClearBalanceButtonText: 'OK',
             failedToClearBalanceText: 'We konden het saldo niet wissen. Probeer het later opnieuw.',
@@ -6817,12 +6109,6 @@ Weet je zeker dat je ze opnieuw wilt exporteren?`,
                 onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
                     `<muted-text>Rapportvelden zijn alleen beschikbaar in het Control-abonnement, vanaf <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `per lid per maand.` : `per actieve deelnemer per maand.`}</muted-text>`,
             },
-            invoiceFields: {
-                title: 'Factuurvelden',
-                description: `Met factuurvelden kun je extra gegevens op factuurniveau toevoegen aan facturen.`,
-                onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
-                    `<muted-text>Factuurvelden zijn alleen beschikbaar in het Control-abonnement, vanaf <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `per lid per maand.` : `per actieve deelnemer per maand.`}</muted-text>`,
-            },
             [CONST.POLICY.CONNECTIONS.NAME.NETSUITE]: {
                 title: 'NetSuite',
                 description: `Profiteer van automatische synchronisatie en verminder handmatige invoer met de Expensify + NetSuite-integratie. Krijg diepgaande realtime financiële inzichten met ondersteuning voor native en aangepaste segmenten, inclusief project- en klanttoewijzing.`,
@@ -6841,12 +6127,6 @@ Weet je zeker dat je ze opnieuw wilt exporteren?`,
                 onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
                     `<muted-text>Onze QuickBooks Desktop-integratie is alleen beschikbaar in het Control-abonnement, vanaf <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `per lid per maand.` : `per actieve deelnemer per maand.`}</muted-text>`,
             },
-            [CONST.POLICY.CONNECTIONS.NAME.CERTINIA]: {
-                title: 'Certinia',
-                description: `Profiteer van automatische synchronisatie en verminder handmatige invoer met de Expensify + Certinia-integratie. Stem uitgavendimensies en belastingsynchronisatie af op je Certinia-configuratie voor helderder financieel inzicht.`,
-                onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
-                    `<muted-text>Onze Certinia-integratie is alleen beschikbaar in het Control-abonnement, vanaf <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `per lid per maand.` : `per actieve deelnemer per maand.`}</muted-text>`,
-            },
             [CONST.UPGRADE_FEATURE_INTRO_MAPPING.approvals.id]: {
                 title: 'Geavanceerde goedkeuringen',
                 description: `Als je extra lagen van goedkeuring wilt toevoegen – of gewoon zeker wilt weten dat de hoogste uitgaven een extra controle krijgen – dan ben je bij ons aan het juiste adres. Geavanceerde goedkeuringen helpen je om op elk niveau de juiste controles in te bouwen, zodat je de uitgaven van je team onder controle houdt.`,
@@ -6923,7 +6203,7 @@ Vereis onkostendetails zoals bonnen en beschrijvingen, stel limieten en standaar
                 onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
                     `<muted-text>Afstandstarieven zijn beschikbaar in het Collect-abonnement, vanaf <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `per lid per maand.` : `per actieve deelnemer per maand.`}</muted-text>`,
             },
-            controlPolicyRoles: {
+            auditor: {
                 title: 'Auditor',
                 description: 'Auditors krijgen alleen-lezen-toegang tot alle rapporten voor volledige transparantie en nalevingsbewaking.',
                 onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
@@ -6940,12 +6220,13 @@ Vereis onkostendetails zoals bonnen en beschrijvingen, stel limieten en standaar
                 perActiveMember: 'per actieve deelnemer per maand.',
                 perMember: 'per lid per maand.',
             },
-            note: (subscriptionLink: string) => `<muted-text><a href="${subscriptionLink}">Lees meer</a> over onze abonnementen en prijzen.</muted-text>`,
+            note: ({subscriptionLink}: WorkspaceUpgradeNoteParams) =>
+                `<muted-text>Upgrade om toegang te krijgen tot deze functie, of <a href="${subscriptionLink}">lees meer</a> over onze abonnementen en prijzen.</muted-text>`,
             upgradeToUnlock: 'Deze functie ontgrendelen',
             completed: {
                 headline: `Je hebt je workspace geüpgraded!`,
-                successMessage: (policyName: string, planName: string, subscriptionLink: string) =>
-                    `<centered-text>Je hebt ${policyName} succesvol geüpgraded naar het ${planName}-abonnement! <a href="${subscriptionLink}">Bekijk je abonnement</a> voor meer details.</centered-text>`,
+                successMessage: ({policyName, subscriptionLink}: UpgradeSuccessMessageParams) =>
+                    `<centered-text>Je hebt ${policyName} succesvol geüpgraded naar het Control-abonnement! <a href="${subscriptionLink}">Bekijk je abonnement</a> voor meer details.</centered-text>`,
                 categorizeMessage: `Je bent succesvol overgestapt naar het Collect-abonnement. Nu kun je je uitgaven categoriseren!`,
                 travelMessage: `Je bent succesvol geüpgraded naar het Collect-abonnement. Je kunt nu beginnen met het boeken en beheren van reizen!`,
                 distanceRateMessage: `Je bent succesvol geüpgraded naar het Collect-abonnement. Nu kun je het kilometertarief wijzigen!`,
@@ -6968,85 +6249,24 @@ Vereis onkostendetails zoals bonnen en beschrijvingen, stel limieten en standaar
                 upgradeWorkspaceWarning: `Kan werkruimte niet upgraden`,
                 upgradeWorkspaceWarningForRestrictedPolicyCreationPrompt: 'Je bedrijf heeft het aanmaken van werkruimtes beperkt. Neem contact op met een admin voor hulp.',
             },
-            hr: {
-                title: 'HR-integraties',
-                description:
-                    'Koppel je HR-provider om automatisch werknemers te synchroniseren en goedkeuringsworkflows te beheren. Houd je teamoverzicht en rapportagestructuur up-to-date zonder handmatig werk.',
-                onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
-                    `<muted-text>HR-integraties zijn alleen beschikbaar in het Control-abonnement, vanaf <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `per lid per maand.` : `per actief lid per maand.`}</muted-text>`,
-            },
-            approvalSubmit: {
-                title: 'Goedkeuringen',
-                description: 'Configureer centraal naar wie alle leden indienen door goedkeuringen in te schakelen.',
-                onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
-                    `<muted-text>Goedkeuringen zijn beschikbaar in de Collect- en Control-abonnementen, vanaf <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `per lid per maand.` : `per actieve deelnemer per maand.`}</muted-text>`,
-            },
-            companyCardSubmit: {
-                title: 'Bedrijfskaarten',
-                description: `Neem je eigen bedrijfskaart mee naar Expensify voor automatische import, automatische categorisatie, ondersteuning voor aangepaste regels en geïntegreerde afstemming.`,
-                onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
-                    `<muted-text>Bedrijfskaartimport is beschikbaar in de Collect- en Control-abonnementen, vanaf <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `per lid per maand.` : `per actieve deelnemer per maand.`}</muted-text>`,
-            },
-            travelSubmit: {
-                title: 'Expensify Travel',
-                description: 'Boek wereldwijd voordelige vluchten, hotels, auto’s en treinen vanuit Expensify, met duty-of-carerapportage en geïntegreerd onkostbeheer.',
-                onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
-                    `<muted-text>Expensify Travel is beschikbaar in de Collect- en Control-abonnementen, vanaf <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `per lid per maand.` : `per actieve deelnemer per maand.`}</muted-text>`,
-            },
-            roles: {
-                title: 'Rollen',
-                description: 'Wijs verschillende rollen toe aan verschillende leden om de zichtbaarheid en controle naar behoefte te verhogen of te verlagen.',
-                onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
-                    `<muted-text>Rollen zijn beschikbaar in de Collect- en Control-abonnementen, vanaf <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `per lid per maand.` : `per actieve deelnemer per maand.`}</muted-text>`,
-            },
-            payments: {
-                title: 'Betalingen',
-                description: 'Vergoed medewerkers rechtstreeks vanaf je zakelijke bankrekening.',
-                onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
-                    `<muted-text>Betalingen zijn beschikbaar in de abonnementen Collect en Control, vanaf <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `per lid per maand.` : `per actieve deelnemer per maand.`}</muted-text>`,
-            },
-            accounting: {
-                title: 'Boekhouding',
-                description:
-                    'Synchroniseer categorieën, labels, belastingtarieven en meer van je boekhoudsysteem naar Expensify, en exporteer onkostendeclaraties en kaarttransacties – zonder typwerk (of tikfouten)!',
-                onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
-                    `<muted-text>Boekhouding is beschikbaar in de Collect- en Control-abonnementen, vanaf <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `per lid per maand.` : `per actieve deelnemer per maand.`}</muted-text>`,
-            },
-            expensifyCard: {
-                title: 'Expensify Card',
-                description:
-                    'Geef bedrijfskaarten (inclusief virtuele kaarten) direct uit vanaf je eigen bankrekening voor realtime controle over uitgaven met een onbreekbare koppeling en tot 2% cashback!',
-                onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
-                    `<muted-text>De Expensify Card is beschikbaar bij de Collect- en Control-abonnementen, vanaf <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `per lid per maand.` : `per actieve deelnemer per maand.`}</muted-text>`,
-                upgradeButton: 'Upgrade en inschakelen',
-            },
-            invoicing: {
-                title: 'Facturatie',
-                description: 'Maak, verstuur en volg professionele facturen, allemaal in Expensify. Laat je sneller betalen met geïntegreerde betalingen en realtime inzicht.',
-                onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
-                    `<muted-text>Facturatie is beschikbaar in de Collect- en Control-abonnementen, vanaf <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `per lid per maand.` : `per actieve deelnemer per maand.`}</muted-text>`,
-            },
         },
         downgrade: {
             commonFeatures: {
-                title: 'Downgraden naar Collect',
-                note: 'Je verliest toegang tot de volgende functies',
+                title: 'Downgraden naar het Collect-abonnement',
+                note: 'Als je een downgrade uitvoert, verlies je de toegang tot deze functies en meer:',
                 benefits: {
-                    confirm: 'Je moet het “Plan type” van elke workspace wijzigen naar “Collect” om het Collect-tarief veilig te stellen.',
-                    benefit1: 'NetSuite, Sage Intacct, QuickBooks Desktop, Oracle, Microsoft Dynamics',
-                    benefit2: 'Workday, Certinia',
-                    benefit3: 'SSO/SAML',
-                    benefit4: 'Slimme onkostregels, dagvergoedingen, goedkeuring op meerdere niveaus, aangepaste rapportage en budgettering',
+                    note: 'Voor een volledig overzicht van onze abonnementen, bekijk onze',
+                    pricingPage: 'prijspagina',
+                    confirm: 'Weet je zeker dat je wilt downgraden en je configuraties wilt verwijderen?',
+                    warning: 'Dit kan niet ongedaan worden gemaakt.',
+                    benefit1: 'Boekhoudkoppelingen (behalve QuickBooks Online en Xero)',
+                    benefit2: 'Slimme uitgaveregels',
+                    benefit3: 'Meerlagige goedkeuringsworkflows',
+                    benefit4: 'Verbeterde beveiligingsinstellingen',
                     headsUp: 'Let op!',
                     multiWorkspaceNote: 'Je moet al je werkruimtes downgraden vóór je eerste maandelijkse betaling om een abonnement tegen het Collect-tarief te starten. Klik',
                     selectStep: '> selecteer elke werkruimte > wijzig het abonnementstype naar',
-                    benefit1Label: 'ERP-integraties',
-                    benefit2Label: 'HR-integraties',
-                    benefit3Label: 'Beveiliging',
-                    benefit4Label: 'Geavanceerd',
-                    important: 'BELANGRIJK:',
                 },
-                noteAndMore: 'en meer:',
             },
             completed: {
                 headline: 'Je werkruimte is gedowngraded',
@@ -7066,7 +6286,7 @@ Vereis onkostendetails zoals bonnen en beschrijvingen, stel limieten en standaar
         restrictedAction: {
             restricted: 'Beperkt',
             actionsAreCurrentlyRestricted: (workspaceName: string) => `Acties in de ${workspaceName}-werkruimte zijn momenteel beperkt`,
-            workspaceOwnerWillNeedToAddOrUpdatePaymentCard: (workspaceOwnerName: string) =>
+            workspaceOwnerWillNeedToAddOrUpdatePaymentCard: ({workspaceOwnerName}: WorkspaceOwnerWillNeedToAddOrUpdatePaymentCardParams) =>
                 `De eigenaar van de workspace, ${workspaceOwnerName}, moet de betaalkaart in het dossier toevoegen of bijwerken om nieuwe workspace-activiteit te ontgrendelen.`,
             youWillNeedToAddOrUpdatePaymentCard: 'Je moet de opgeslagen betaalkaart toevoegen of bijwerken om nieuwe werkruimte-activiteiten te ontgrendelen.',
             addPaymentCardToUnlock: 'Voeg een betaalkaart toe om te ontgrendelen!',
@@ -7120,18 +6340,16 @@ Vereis onkostendetails zoals bonnen en beschrijvingen, stel limieten en standaar
                 eReceiptsHint: `eReceipts worden automatisch aangemaakt [voor de meeste USD-credittransacties](${CONST.DEEP_DIVE_ERECEIPTS}).`,
                 attendeeTracking: 'Deelnemersregistratie',
                 attendeeTrackingHint: 'Houd de kosten per persoon bij voor elke uitgave.',
-                prohibitedDefaultDescription: 'Markeer bonnen met deze regels voor handmatige controle.',
+                prohibitedDefaultDescription:
+                    'Markeer alle bonnen waarop alcohol, gokken of andere verboden artikelen voorkomen. Declaraties met bonnen waarop deze posten voorkomen, moeten handmatig worden gecontroleerd.',
                 prohibitedExpenses: 'Verboden uitgaven',
                 alcohol: 'Alcohol',
                 hotelIncidentals: 'Hotelnevenkosten',
                 gambling: 'Gokken',
                 tobacco: 'Tabak',
                 adultEntertainment: 'Volwassenenentertainment',
-                giftCard: 'Cadeaukaartaankopen',
-                handwrittenReceipt: 'Handgeschreven bonnen',
                 requireCompanyCard: 'Verplicht bedrijfskaarten voor alle aankopen',
                 requireCompanyCardDescription: 'Markeer alle contante uitgaven, inclusief kilometer- en dagvergoedingen.',
-                requireCompanyCardDisabledTooltip: 'Schakel Bedrijfskaarten in (onder Meer functies) om te ontgrendelen.',
             },
             expenseReportRules: {
                 title: 'Geavanceerd',
@@ -7140,8 +6358,8 @@ Vereis onkostendetails zoals bonnen en beschrijvingen, stel limieten en standaar
                 preventSelfApprovalsSubtitle: 'Voorkom dat werkruimteleden hun eigen onkostendeclaraties goedkeuren.',
                 autoApproveCompliantReportsTitle: 'Rapporten die voldoen automatisch goedkeuren',
                 autoApproveCompliantReportsSubtitle: 'Configureren welke onkostendeclaraties in aanmerking komen voor automatische goedkeuring.',
-                autoApproveReportsUnderTitle: 'Rapporten automatisch goedkeuren als alle onkosten onder',
-                autoApproveReportsUnderDescription: 'Volledig conforme onkostendeclaraties waarvan alle onkosten onder dit bedrag liggen, worden automatisch goedgekeurd.',
+                autoApproveReportsUnderTitle: 'Rapporten automatisch goedkeuren onder',
+                autoApproveReportsUnderDescription: 'Volledig conforme onkostendeclaraties onder dit bedrag worden automatisch goedgekeurd.',
                 randomReportAuditTitle: 'Willekeurige rapportcontrole',
                 randomReportAuditDescription: 'Vereisen dat sommige rapporten handmatig worden goedgekeurd, zelfs als ze in aanmerking komen voor automatische goedkeuring.',
                 autoPayApprovedReportsTitle: 'Automatisch betalen van goedgekeurde rapporten',
@@ -7154,11 +6372,6 @@ Vereis onkostendetails zoals bonnen en beschrijvingen, stel limieten en standaar
                 enableFeatureSubtitle: (featureName: string, moreFeaturesLink?: string) =>
                     `Ga naar [meer functies](${moreFeaturesLink}) en schakel ${featureName} in om deze functie te ontgrendelen.`,
             },
-            agentsPromoBanner: {
-                title: 'Zie je de regel die je nodig hebt niet? Voeg een agent toe',
-                subtitle: 'Voeg complexe regels toe en verminder handmatige goedkeuringen met aangepaste agents.',
-                cta: 'Probeer het uit',
-            },
             merchantRules: {
                 title: 'Handelaar',
                 subtitle: 'Stel de leveranciersregels in zodat onkosten correct gecodeerd binnenkomen en er minder nabewerking nodig is.',
@@ -7186,10 +6399,9 @@ Vereis onkostendetails zoals bonnen en beschrijvingen, stel limieten en standaar
                 matchTypeContains: 'Bevat',
                 matchTypeExact: 'Komt exact overeen',
                 duplicateRuleTitle: 'Vergelijkbare handelaarregel bestaat al',
-                duplicateRulePrompt: (merchantName: string) => `Je bestaande regel voor ‘${merchantName}’ krijgt voorrang op deze regel. Toch opslaan?`,
+                duplicateRulePrompt: (merchantName: string) => `Wil je een nieuwe regel voor ‘${merchantName}’ opslaan, ook al heb je er al een bestaande?`,
                 saveAnyway: 'Toch opslaan',
                 applyToExistingUnsubmittedExpenses: 'Toepassen op bestaande niet-ingediende uitgaven',
-                findRule: 'Zoek handelsregel',
             },
             categoryRules: {
                 title: 'Categorisatieregels',
@@ -7227,130 +6439,12 @@ Vereis onkostendetails zoals bonnen en beschrijvingen, stel limieten en standaar
                     always: 'Altijd gespecificeerde bonnetjes vereisen',
                 },
                 defaultTaxRate: 'Standaardbelastingtarief',
-                enableWorkflows: (moreFeaturesLink: string) =>
+                enableWorkflows: ({moreFeaturesLink}: RulesEnableWorkflowsParams) =>
                     `Ga naar [Meer functies](${moreFeaturesLink}) en schakel workflows in, voeg daarna goedkeuringen toe om deze functie te ontgrendelen.`,
             },
             customRules: {
                 title: 'Declaratiebeleid',
                 cardSubtitle: 'Hier staat het declaratiebeleid van je team, zodat iedereen hetzelfde beeld heeft van wat er wordt vergoed.',
-                policyDocument: 'Beleidsdocument',
-                policyText: 'Beleidstekst',
-            },
-            spendRules: {
-                title: 'Uitgaven',
-                subtitle: 'Keur Expensify Kaart-transacties in realtime goed of af.',
-                defaultRuleDescription: 'Alle kaarten',
-                block: 'Blokkeren',
-                defaultRuleTitle: 'Categorieën: diensten voor volwassenen, geldautomaten, gokken, geldoverdrachten',
-                builtInProtectionModal: {
-                    title: 'Expensify Kaarten bieden altijd ingebouwde bescherming',
-                    description: `Expensify weigert deze uitgaven altijd:
-
-  • Services voor volwassenen
-  • Geldautomaten (ATM's)
-  • Gokken
-  • Geldoverschrijvingen
-er bestedingsregels toe om de kasstroom van het bedrijf te beschermen.`,
-                },
-                addSpendRule: 'Uitgaveregel toevoegen',
-                cardPageTitle: 'Kaart',
-                cardsSectionTitle: 'Kaarten',
-                chooseCards: 'Kaarten kiezen',
-                saveRule: 'Regel opslaan',
-                allow: 'Toestaan',
-                spendRuleSectionTitle: 'Bestedingsregel',
-                restrictionType: 'Restrictietype',
-                restrictionTypeHelpAllow: 'Kosten worden goedgekeurd als ze overeenkomen met een handelaar of categorie en een maximumbedrag niet overschrijden.',
-                restrictionTypeHelpBlock: 'Betalingen worden geweigerd als ze overeenkomen met een handelaar of categorie, of een maximumbedrag overschrijden.',
-                addMerchant: 'Handelaar toevoegen',
-                merchantContains: 'Handelaar bevat',
-                merchantExactlyMatches: 'Handelaar komt exact overeen',
-                noBlockedMerchants: 'Geen geblokkeerde handelaren',
-                addMerchantToBlockSpend: 'Voeg een handelaar toe om uitgaven te blokkeren',
-                noAllowedMerchants: 'Geen toegestane handelaren',
-                addMerchantToAllowSpend: 'Voeg een handelaar toe om uitgaven toe te staan',
-                matchType: 'Overeenkomsttype',
-                matchTypeContains: 'Bevat',
-                matchTypeExact: 'Komt exact overeen',
-                spendCategory: 'Uitgavencategorie',
-                maxAmount: 'Maximumbedrag',
-                maxAmountHelp: 'Elke betaling boven dit bedrag wordt geweigerd, ongeacht beperkingen voor handelaar en uitgavencategorie.',
-                currencyMismatchTitle: 'Valutamismatch',
-                currencyMismatchPrompt: 'Om een maximumbedrag in te stellen, selecteer je kaarten die in dezelfde valuta worden vereffend.',
-                reviewSelectedCards: 'Geselecteerde kaarten bekijken',
-                summaryMoreCount: ({summary, count}: {summary: string; count: number}) => (count > 0 ? `${summary}, +${count} meer` : summary),
-                confirmErrorApplyAtLeastOneSpendRuleToOneCard: 'Pas minstens één bestedingsregel toe op één kaart',
-                confirmErrorCardRequired: 'Kaart is een verplicht veld',
-                confirmErrorApplyAtLeastOneSpendRule: 'Pas minstens één bestedingsregel toe',
-                categories: 'Categorieën',
-                merchants: 'Handelaars',
-                noAvailableCards: 'Alle kaarten hebben al een regel',
-                noAvailableCardsSubtitle: 'Bewerk een bestaande kaartregel om wijzigingen aan te brengen',
-                noCardsIssuedTitle: 'Geen Expensify Kaarten uitgegeven',
-                noCardsIssuedSubtitle: 'Geef Expensify Kaarten uit om bestedingsregels te maken',
-                max: 'Max',
-                categoryOptions: {
-                    [CONST.SPEND_RULES.CATEGORIES.AIRLINES]: 'Luchtvaartmaatschappijen',
-                    [CONST.SPEND_RULES.CATEGORIES.ALCOHOL_AND_BARS]: 'Alcohol en bars',
-                    [CONST.SPEND_RULES.CATEGORIES.AMAZON_AND_BOOKSTORES]: 'Amazon en boekhandels',
-                    [CONST.SPEND_RULES.CATEGORIES.AUTOMOTIVE]: 'Auto-industrie',
-                    [CONST.SPEND_RULES.CATEGORIES.CAR_RENTALS]: 'Autoverhuur',
-                    [CONST.SPEND_RULES.CATEGORIES.DINING]: 'Eten en drinken',
-                    [CONST.SPEND_RULES.CATEGORIES.FUEL_AND_GAS]: 'Brandstof en gas',
-                    [CONST.SPEND_RULES.CATEGORIES.GOVERNMENT_AND_NON_PROFITS]: 'Overheid en non-profitorganisaties',
-                    [CONST.SPEND_RULES.CATEGORIES.GROCERIES]: 'Boodschappen',
-                    [CONST.SPEND_RULES.CATEGORIES.GYMS_AND_FITNESS]: 'Sportscholen en fitness',
-                    [CONST.SPEND_RULES.CATEGORIES.HEALTHCARE]: 'Gezondheidszorg',
-                    [CONST.SPEND_RULES.CATEGORIES.HOTELS]: 'Hotels',
-                    [CONST.SPEND_RULES.CATEGORIES.INTERNET_AND_PHONE]: 'Internet en telefoon',
-                    [CONST.SPEND_RULES.CATEGORIES.OFFICE_SUPPLIES]: 'Kantoorbenodigdheden',
-                    [CONST.SPEND_RULES.CATEGORIES.PARKING_AND_TOLLS]: 'Parkeren en tol',
-                    [CONST.SPEND_RULES.CATEGORIES.PROFESSIONAL_SERVICES]: 'Professionele diensten',
-                    [CONST.SPEND_RULES.CATEGORIES.RETAIL]: 'Detailhandel',
-                    [CONST.SPEND_RULES.CATEGORIES.SHIPPING_AND_DELIVERY]: 'Verzending en levering',
-                    [CONST.SPEND_RULES.CATEGORIES.SOFTWARE]: 'Software',
-                    [CONST.SPEND_RULES.CATEGORIES.TRANSIT_AND_RIDESHARE]: 'Openbaar vervoer en ritdiensten',
-                    [CONST.SPEND_RULES.CATEGORIES.TRAVEL_AGENCIES]: 'Reisbureaus',
-                },
-                editRuleTitle: 'Regel bewerken',
-                deleteRule: 'Regel verwijderen',
-                deleteRuleConfirmation: 'Weet je zeker dat je deze regel wilt verwijderen?',
-                summaryMerchants: ({
-                    merchants,
-                    hiddenCount,
-                    shownCount,
-                    action,
-                }: {
-                    merchants: string;
-                    hiddenCount: number;
-                    shownCount: number;
-                    action: ValueOf<typeof CONST.SPEND_RULES.ACTION>;
-                }) =>
-                    `${action === CONST.SPEND_RULES.ACTION.BLOCK ? 'Geblokkeerd' : 'Toegestaan'} ${shownCount > 1 ? 'handelaars' : 'handelaar'}: ${merchants}${hiddenCount > 0 ? `, +${hiddenCount} meer` : ''}`,
-                summaryCategories: ({
-                    categories,
-                    hiddenCount,
-                    shownCount,
-                    action,
-                }: {
-                    categories: string;
-                    hiddenCount: number;
-                    shownCount: number;
-                    action: ValueOf<typeof CONST.SPEND_RULES.ACTION>;
-                }) =>
-                    `${action === CONST.SPEND_RULES.ACTION.BLOCK ? 'Geblokkeerd' : 'Toegestaan'} ${shownCount > 1 ? 'categorieën' : 'categorie'}: ${categories}${hiddenCount > 0 ? `, +${hiddenCount} meer` : ''}`,
-            },
-            aiRules: {
-                title: 'AI-regels',
-                subtitle: 'Beschrijf flexibele regels die worden uitgevoerd wanneer je ze nodig hebt',
-                addRule: 'AI-regel toevoegen',
-                findRule: 'AI-regel zoeken',
-                addRuleTitle: 'Regel toevoegen',
-                editRuleTitle: 'Regel bewerken',
-                deleteRule: 'Regel verwijderen',
-                deleteRuleConfirmation: 'Weet je zeker dat je deze regel wilt verwijderen?',
-                describeRuleTitle: 'Beschrijf je regel',
-                describeRuleSubtitle: 'Beschrijf je regel en Concierge maakt hem voor je',
             },
         },
         planTypePage: {
@@ -7363,102 +6457,15 @@ er bestedingsregels toe om de kasstroom van het bedrijf te beschermen.`,
                     label: 'Beheer',
                     description: 'Voor organisaties met geavanceerde vereisten.',
                 },
-                submit2026: {
-                    label: 'Indienen',
-                    description: 'Voor werknemers die onkosten bij hun werkgever willen indienen.',
-                },
             },
-            description: 'Kies een abonnement dat bij je past.',
-            subscriptionLink: 'Meer informatie',
+            description: 'Kies een pakket dat bij je past. Voor een gedetailleerd overzicht van functies en prijzen, bekijk onze',
+            subscriptionLink: 'hulppagina voor abonnementstypen en prijzen',
             lockedPlanDescription: ({count, annualSubscriptionEndDate}: WorkspaceLockedPlanTypeParams) => ({
                 one: `Je hebt je vastgelegd op 1 actief lid in het Control-abonnement tot je jaarlijkse abonnement afloopt op ${annualSubscriptionEndDate}. Je kunt overstappen op een pay-per-use-abonnement en downgraden naar het Collect-abonnement vanaf ${annualSubscriptionEndDate} door automatisch verlengen uit te schakelen in`,
                 other: `Je hebt je vastgelegd op ${count} actieve leden op het Control-abonnement totdat je jaarlijkse abonnement eindigt op ${annualSubscriptionEndDate}. Je kunt overschakelen naar een betaling-per-gebruik-abonnement en downgraden naar het Collect-abonnement vanaf ${annualSubscriptionEndDate} door automatisch verlengen uit te schakelen in`,
             }),
             subscriptions: 'Abonnementen',
         },
-        hr: {
-            title: 'HR',
-            connections: 'Verbindingen',
-            connectionsSubtitle:
-                'Verbind met je HR-systeem om werknemersgegevens te synchroniseren, terugbetalingen automatisch aan de juiste personen te koppelen en de uitgaven van je team nauwkeurig te houden zonder handmatig werk.',
-            subtitle: 'Koppel HR-tools en houd goedkeuringen van medewerkers gesynchroniseerd.',
-            connect: 'Verbinden',
-            syncNow: 'Nu synchroniseren',
-            disconnect: 'Ontkoppelen',
-            disconnectTitle: (providerName: string) => `${providerName} ontkoppelen`,
-            disconnectPrompt: (providerName: string) => `Weet je zeker dat je ${providerName} wilt ontkoppelen?`,
-            alreadyConnectedTitle: 'Kan niet met meerdere HR-platformen verbinden',
-            alreadyConnectedPrompt: 'Je moet je huidige HR-platform loskoppelen voordat je een ander kunt verbinden.',
-            lastSync: (relativeDate: string) => `Laatst gesynchroniseerd ${relativeDate}`,
-            syncError: (providerName: string) => `Kan geen verbinding maken met ${providerName}`,
-            connectionDescription: (providerName: string) => `Verbind ${providerName} om goedkeuringen van werknemers gesynchroniseerd te houden met je werkruimte.`,
-            approvalMode: 'Goedkeuringsmodus',
-            providerApprovalMode: (providerName: string) => `${providerName}-goedkeuringsmodus`,
-            finalApprover: 'Eindgoedkeurder',
-            providerFinalApprover: (providerName: string) => `Laatste ${providerName}-fiatteur`,
-            notSet: 'Niet ingesteld',
-            approvalModeDescription: (providerName: string) => `Leden en managers zijn ingesteld om te synchroniseren met ${providerName}.`,
-            approvalModeWarningTitle: 'Goedkeuringsmodus wijzigen?',
-            approvalModeWarningPrompt: (providerName: string, helpSiteURL: string) =>
-                `Weet je zeker dat je de goedkeuringsmodus voor deze werkruimte wilt wijzigen? Lees meer over de verschillende ${providerName}-ondersteunde workflowmodi op onze <a href="${helpSiteURL}">help-site</a>.`,
-            approvalModeWarningConfirm: 'Goedkeuringsmodus wijzigen',
-            approvalModes: {
-                basic: {label: 'Basisgoedkeuring', description: 'Alle gebruikers dienen bij één persoon in voor verwerking en goedkeuring.'},
-                manager: {
-                    label: 'Managergoedkeuring',
-                    description: (providerName: string) => `Werknemers dienen rapporten in bij hun direct leidinggevende die is ingesteld in ${providerName}.`,
-                },
-                custom: {label: 'Aangepaste goedkeuring', description: 'Ik stel goedkeuringsworkflows handmatig in in Expensify.'},
-            },
-            syncStageName: ({stage}: SyncStageNameConnectionsParams) => {
-                switch (stage) {
-                    case 'gustoSyncTitle':
-                        return 'Gusto-medewerkers synchroniseren';
-                    case 'gustoSyncLoadData':
-                        return 'Gegevens laden van Gusto';
-                    case 'gustoSyncProvisioning':
-                        return 'Medewerkers toewijzen in beleid';
-                    case 'zenefitsSyncTitle':
-                        return 'TriNet-medewerkers synchroniseren';
-                    case 'zenefitsSyncLoadData':
-                        return 'Gegevens laden van TriNet';
-                    case 'zenefitsSyncProvisioning':
-                        return 'Medewerkers toewijzen in beleid';
-                    case 'jobDone':
-                        return 'Wachten tot geïmporteerde gegevens worden geladen';
-                    default: {
-                        return `Vertaling ontbreekt voor fase: ${stage}`;
-                    }
-                }
-            },
-            syncResults: {
-                title: (provider: string) => `Synchronisatie met ${provider} voltooid`,
-                successTitle: (provider: string) => `Je ${provider}-verbinding is succesvol gesynchroniseerd!`,
-                added: 'Toegevoegd',
-                removed: 'Verwijderd',
-                skipped: 'Overgeslagen',
-                employeeCount: () => ({
-                    one: '1 werknemer',
-                    other: (count: number) => `${count} medewerkers`,
-                }),
-            },
-            gusto: {
-                title: 'Gusto',
-            },
-            zenefits: {
-                title: 'TriNet',
-            },
-            syncingModalTitle: 'Je verbinding wordt gesynchroniseerd',
-            syncingModalDescription: 'De eerste verbinding kan even duren. Je krijgt een melding als er fouten optreden.',
-            syncing: 'Werknemers synchroniseren',
-            mergeHR: {
-                completeSetup: 'Configuratie voltooien',
-                setupIncomplete: (setupLink: string | undefined) =>
-                    `<muted-text-label>Verbonden. ${setupLink ? `<a href="${setupLink}">Instellen voltooien</a>` : 'Configuratie voltooien'} om werknemers te importeren.</muted-text-label>`,
-                groups: {title: 'Groepen', description: 'Kies de groepen werknemers die je met deze workspace wilt synchroniseren'},
-            },
-        },
-        emptyDomain: {title: 'Verbeter je beveiliging met domeinen', subtitle: 'Vereis dat leden op je domein inloggen via single sign-on, beperk het aanmaken van werkruimtes en meer.'},
     },
     getAssistancePage: {
         title: 'Hulp krijgen',
@@ -7486,7 +6493,6 @@ er bestedingsregels toe om de kasstroom van het bedrijf te beschermen.`,
             symbols: 'Symbolen',
             flags: 'Vlaggen',
         },
-        emojiNotSelected: 'Emoji niet geselecteerd',
     },
     newRoomPage: {
         newRoom: 'Nieuwe ruimte',
@@ -7499,7 +6505,7 @@ er bestedingsregels toe om de kasstroom van het bedrijf te beschermen.`,
         public_announceDescription: 'Iedereen kan deze ruimte vinden',
         createRoom: 'Ruimte maken',
         roomAlreadyExistsError: 'Er bestaat al een kamer met deze naam',
-        roomNameReservedError: (reservedName: string) => `${reservedName} is een standaardruimte in alle werkruimtes. Kies een andere naam.`,
+        roomNameReservedError: ({reservedName}: RoomNameReservedErrorParams) => `${reservedName} is een standaardruimte in alle werkruimtes. Kies een andere naam.`,
         roomNameInvalidError: 'Kamernamen mogen alleen kleine letters, cijfers en koppeltekens bevatten',
         pleaseEnterRoomName: 'Voer een kamernaam in',
         pleaseSelectWorkspace: 'Selecteer een werkruimte',
@@ -7507,7 +6513,7 @@ er bestedingsregels toe om de kasstroom van het bedrijf te beschermen.`,
             const actor = actorName ? `${actorName} ` : '';
             return isExpenseReport ? `${actor}hernoemd naar "${newName}" (voorheen "${oldName}")` : `${actor}heeft deze ruimte hernoemd naar "${newName}" (voorheen "${oldName}")`;
         },
-        roomRenamedTo: (newName: string) => `Chatruimte hernoemd naar ${newName}`,
+        roomRenamedTo: ({newName}: RoomRenamedToParams) => `Chatruimte hernoemd naar ${newName}`,
         social: 'sociaal',
         selectAWorkspace: 'Selecteer een werkruimte',
         growlMessageOnRenameError: 'Kan de werkruimtekamer niet hernoemen. Controleer je verbinding en probeer het opnieuw.',
@@ -7549,14 +6555,14 @@ er bestedingsregels toe om de kasstroom van het bedrijf te beschermen.`,
             `${approverName} (${approverEmail}) toegevoegd als fiatteur voor het veld ${field} "${name}"`,
         deleteApprovalRule: (approverEmail: string, approverName: string, field: string, name: string) =>
             `heeft ${approverName} (${approverEmail}) verwijderd als fiatteur voor het veld ${field} „${name}”`,
-        updateApprovalRule: (field: string, name: string, newApproverEmail: string, newApproverName: string | undefined, oldApproverEmail: string, oldApproverName: string | undefined) => {
+        updateApprovalRule: ({field, name, newApproverEmail, newApproverName, oldApproverEmail, oldApproverName}: UpdatedPolicyApprovalRuleParams) => {
             const formatApprover = (displayName?: string, email?: string) => (displayName ? `${displayName} (${email})` : email);
             return `heeft de fiatteur voor het ${field} „${name}” gewijzigd in ${formatApprover(newApproverName, newApproverEmail)} (voorheen ${formatApprover(oldApproverName, oldApproverEmail)})`;
         },
-        addCategory: (categoryName: string) => `heeft de categorie ‘${categoryName}’ toegevoegd`,
-        deleteCategory: (categoryName: string) => `heeft de categorie ‘${categoryName}’ verwijderd`,
-        updateCategory: (categoryName: string, oldValue: boolean) => `${oldValue ? 'uitgeschakeld' : 'ingeschakeld'} de categorie ‘${categoryName}’`,
-        updateCategoryPayrollCode: (categoryName: string, newValue?: string, oldValue?: string) => {
+        addCategory: ({categoryName}: UpdatedPolicyCategoryParams) => `heeft de categorie ‘${categoryName}’ toegevoegd`,
+        deleteCategory: ({categoryName}: UpdatedPolicyCategoryParams) => `heeft de categorie ‘${categoryName}’ verwijderd`,
+        updateCategory: ({oldValue, categoryName}: UpdatedPolicyCategoryParams) => `${oldValue ? 'uitgeschakeld' : 'ingeschakeld'} de categorie ‘${categoryName}’`,
+        updateCategoryPayrollCode: ({oldValue, categoryName, newValue}: UpdatedPolicyCategoryGLCodeParams) => {
             if (!oldValue) {
                 return `heeft de looncode „${newValue}” toegevoegd aan de categorie „${categoryName}”`;
             }
@@ -7565,7 +6571,7 @@ er bestedingsregels toe om de kasstroom van het bedrijf te beschermen.`,
             }
             return `heeft de looncode van categorie „${categoryName}” gewijzigd in „${newValue}” (voorheen „${oldValue}”)`;
         },
-        updateCategoryGLCode: (categoryName: string, newValue?: string, oldValue?: string) => {
+        updateCategoryGLCode: ({oldValue, categoryName, newValue}: UpdatedPolicyCategoryGLCodeParams) => {
             if (!oldValue) {
                 return `heeft de GL-code "${newValue}” toegevoegd aan de categorie "${categoryName}"`;
             }
@@ -7574,10 +6580,10 @@ er bestedingsregels toe om de kasstroom van het bedrijf te beschermen.`,
             }
             return `heeft de GL-code van categorie ‘${categoryName}’ gewijzigd in ‘${newValue}’ (voorheen ‘${oldValue}’)`;
         },
-        updateAreCommentsRequired: (categoryName: string, oldValue: boolean) => {
+        updateAreCommentsRequired: ({oldValue, categoryName}: UpdatedPolicyCategoryParams) => {
             return `heeft de beschrijving van categorie "${categoryName}" gewijzigd in ${!oldValue ? 'vereist' : 'niet vereist'} (voorheen ${!oldValue ? 'niet vereist' : 'vereist'})`;
         },
-        updateCategoryMaxExpenseAmount: (categoryName: string, newAmount?: string, oldAmount?: string) => {
+        updateCategoryMaxExpenseAmount: ({categoryName, oldAmount, newAmount}: UpdatedPolicyCategoryMaxExpenseAmountParams) => {
             if (newAmount && !oldAmount) {
                 return `heeft een maximaal bedrag van ${newAmount} toegevoegd aan de categorie "${categoryName}"`;
             }
@@ -7586,26 +6592,26 @@ er bestedingsregels toe om de kasstroom van het bedrijf te beschermen.`,
             }
             return `heeft het maximumbedrag van categorie „${categoryName}” gewijzigd in ${newAmount} (voorheen ${oldAmount})`;
         },
-        updateCategoryExpenseLimitType: (categoryName: string, newValue: string, oldValue?: string) => {
+        updateCategoryExpenseLimitType: ({categoryName, oldValue, newValue}: UpdatedPolicyCategoryExpenseLimitTypeParams) => {
             if (!oldValue) {
                 return `heeft een limiettType van ${newValue} toegevoegd aan de categorie "${categoryName}"`;
             }
             return `heeft het limiettype van categorie „${categoryName}” gewijzigd naar ${newValue} (voorheen ${oldValue})`;
         },
-        updateCategoryMaxAmountNoReceipt: (categoryName: string, newValue: string, oldValue?: string) => {
+        updateCategoryMaxAmountNoReceipt: ({categoryName, oldValue, newValue}: UpdatedPolicyCategoryMaxAmountNoReceiptParams) => {
             if (!oldValue) {
                 return `heeft de categorie "${categoryName}" bijgewerkt door Bonnetjes te wijzigen naar ${newValue}`;
             }
             return `heeft de categorie „${categoryName}” gewijzigd naar ${newValue} (voorheen ${oldValue})`;
         },
-        updateCategoryMaxAmountNoItemizedReceipt: (categoryName: string, oldValue: string | undefined, newValue: string) => {
+        updateCategoryMaxAmountNoItemizedReceipt: ({categoryName, oldValue, newValue}: UpdatedPolicyCategoryMaxAmountNoReceiptParams) => {
             if (!oldValue) {
                 return `heeft de categorie "${categoryName}" bijgewerkt door Gespecificeerde bonnetten te wijzigen in ${newValue}`;
             }
             return `heeft de categorie „${categoryName}” Itemized receipts gewijzigd naar ${newValue} (voorheen ${oldValue})`;
         },
-        setCategoryName: (oldName: string, newName: string) => `heeft de categorie "${oldName}" hernoemd naar "${newName}"`,
-        updatedDescriptionHint: (categoryName: string, newValue?: string, oldValue?: string) => {
+        setCategoryName: ({oldName, newName}: UpdatedPolicyCategoryNameParams) => `heeft de categorie "${oldName}" hernoemd naar "${newName}"`,
+        updatedDescriptionHint: ({categoryName, oldValue, newValue}: UpdatedPolicyCategoryDescriptionHintTypeParams) => {
             if (!newValue) {
                 return `heeft de beschrijvingshint "${oldValue}" verwijderd uit de categorie "${categoryName}"`;
             }
@@ -7613,44 +6619,46 @@ er bestedingsregels toe om de kasstroom van het bedrijf te beschermen.`,
                 ? `heeft de beschrijvingshint „${newValue}” toegevoegd aan de categorie „${categoryName}”`
                 : `heeft de beschrijvingshint van categorie „${categoryName}” gewijzigd naar „${newValue}” (voorheen „${oldValue}”)`;
         },
-        updateTagListName: (oldName: string, newName: string) => `heeft de naam van de taglijst gewijzigd in „${newName}” (voorheen „${oldName}”)`,
-        addTag: (tagListName: string, tagName?: string) => `heeft de tag "${tagName}" toegevoegd aan de lijst "${tagListName}"`,
-        updateTagName: (tagListName: string, newName: string, oldName: string) => `heeft de taglijst "${tagListName}" bijgewerkt door de tag "${oldName}" te veranderen in "${newName}"`,
-        updateTagEnabled: (tagListName: string, tagName?: string, enabled?: boolean) => `${enabled ? 'ingeschakeld' : 'uitgeschakeld'} de tag "${tagName}" in de lijst "${tagListName}"`,
-        deleteTag: (tagListName: string, tagName?: string) => `heeft het label "${tagName}" verwijderd uit de lijst "${tagListName}"`,
-        deleteMultipleTags: (count?: string, tagListName?: string) => `heeft “${count}” tags verwijderd uit de lijst “${tagListName}”`,
-        updateTag: (tagListName: string, newValue: string, tagName: string, updatedField: string, oldValue?: string) => {
+        updateTagListName: ({oldName, newName}: UpdatedPolicyCategoryNameParams) => `heeft de naam van de taglijst gewijzigd in „${newName}” (voorheen „${oldName}”)`,
+        addTag: ({tagListName, tagName}: UpdatedPolicyTagParams) => `heeft de tag "${tagName}" toegevoegd aan de lijst "${tagListName}"`,
+        updateTagName: ({tagListName, newName, oldName}: UpdatedPolicyTagNameParams) =>
+            `heeft de taglijst "${tagListName}" bijgewerkt door de tag "${oldName}" te veranderen in "${newName}"`,
+        updateTagEnabled: ({tagListName, tagName, enabled}: UpdatedPolicyTagParams) => `${enabled ? 'ingeschakeld' : 'uitgeschakeld'} de tag "${tagName}" in de lijst "${tagListName}"`,
+        deleteTag: ({tagListName, tagName}: UpdatedPolicyTagParams) => `heeft het label "${tagName}" verwijderd uit de lijst "${tagListName}"`,
+        deleteMultipleTags: ({count, tagListName}: UpdatedPolicyTagParams) => `heeft “${count}” tags verwijderd uit de lijst “${tagListName}”`,
+        updateTag: ({tagListName, newValue, tagName, updatedField, oldValue}: UpdatedPolicyTagFieldParams) => {
             if (oldValue) {
                 return `heeft de tag "${tagName}" op de lijst "${tagListName}" bijgewerkt door ${updatedField} te wijzigen in "${newValue}" (voorheen "${oldValue}")`;
             }
             return `heeft de tag ‘${tagName}’ in de lijst ‘${tagListName}’ bijgewerkt door een ${updatedField} met de waarde ‘${newValue}’ toe te voegen`;
         },
-        updateCustomUnit: (customUnitName: string, newValue: string, oldValue: string, updatedField: string) =>
+        updateCustomUnit: ({customUnitName, newValue, oldValue, updatedField}: UpdatePolicyCustomUnitParams) =>
             `heeft de ${customUnitName} ${updatedField} gewijzigd naar "${newValue}" (voorheen "${oldValue}")`,
-        updateCustomUnitTaxEnabled: (newValue: boolean) => `${newValue ? 'ingeschakeld' : 'uitgeschakeld'} belastingregistratie op afstandstarieven`,
-        addCustomUnitRate: (customUnitName: string, rateName: string) => `heeft ${customUnitName}-tarief „${rateName}” toegevoegd`,
-        updatedCustomUnitRate: (customUnitName: string, customUnitRateName: string, updatedField: string, newValue: string, oldValue: string) =>
+        updateCustomUnitTaxEnabled: ({newValue}: UpdatePolicyCustomUnitTaxEnabledParams) => `${newValue ? 'ingeschakeld' : 'uitgeschakeld'} belastingregistratie op afstandstarieven`,
+        addCustomUnitRate: ({customUnitName, rateName}: AddOrDeletePolicyCustomUnitRateParams) => `heeft een nieuw ${customUnitName}-tarief "${rateName}" toegevoegd`,
+        updatedCustomUnitRate: ({customUnitName, customUnitRateName, newValue, oldValue, updatedField}: UpdatedPolicyCustomUnitRateParams) =>
             `heeft het tarief van de ${customUnitName} ${updatedField} "${customUnitRateName}" gewijzigd naar "${newValue}" (voorheen "${oldValue}")`,
-        updatedCustomUnitTaxRateExternalID: (customUnitRateName: string, newValue: string, newTaxPercentage: string, oldTaxPercentage?: string, oldValue?: string) => {
+        updatedCustomUnitTaxRateExternalID: ({customUnitRateName, newValue, newTaxPercentage, oldTaxPercentage, oldValue}: UpdatedPolicyCustomUnitTaxRateExternalIDParams) => {
             if (oldTaxPercentage && oldValue) {
                 return `heeft het belastingtarief van het kilometertarief "${customUnitRateName}" gewijzigd naar "${newValue} (${newTaxPercentage})" (voorheen "${oldValue} (${oldTaxPercentage})")`;
             }
             return `heeft het belastingtarief "${newValue} (${newTaxPercentage})" toegevoegd aan het afstandstarief "${customUnitRateName}"`;
         },
-        updatedCustomUnitTaxClaimablePercentage: (customUnitRateName: string, newValue: number, oldValue?: number) => {
+        updatedCustomUnitTaxClaimablePercentage: ({customUnitRateName, newValue, oldValue}: UpdatedPolicyCustomUnitTaxClaimablePercentageParams) => {
             if (oldValue) {
                 return `heeft het terugvorderbare belastinggedeelte van het afstandstarief "${customUnitRateName}" gewijzigd naar "${newValue}" (voorheen "${oldValue}")`;
             }
             return `heeft een terugvorderbaar belastingdeel van „${newValue}” toegevoegd aan het kilometertarief „${customUnitRateName}”`;
         },
-        updatedCustomUnitRateName: (customUnitName: string, oldValue: string, newValue: string) => `heeft het tarief voor ${customUnitName} hernoemd van „${oldValue}” naar „${newValue}”`,
-        updatedCustomUnitRateEnabled: (customUnitName: string, customUnitRateName: string, newValue: boolean) => {
+        updatedCustomUnitRateEnabled: ({customUnitName, customUnitRateName, newValue}: UpdatedPolicyCustomUnitRateEnabledParams) => {
             return `${newValue ? 'ingeschakeld' : 'uitgeschakeld'} het ${customUnitName}-tarief "${customUnitRateName}"`;
         },
-        deleteCustomUnitRate: (customUnitName: string, rateName: string) => `heeft het tarief „${rateName}” van de eenheid „${customUnitName}” verwijderd`,
-        updateReportFieldDefaultValue: (defaultValue?: string, fieldName?: string) => `stel de standaardwaarde van rapportveld "${fieldName}" in op "${defaultValue}"`,
-        addedReportFieldOption: (fieldName: string, optionName: string) => `heeft de optie ‘${optionName}’ toegevoegd aan het rapportveld ‘${fieldName}’`,
-        removedReportFieldOption: (fieldName: string, optionName: string) => `heeft de optie "${optionName}" verwijderd uit het rapportveld "${fieldName}"`,
+        deleteCustomUnitRate: ({customUnitName, rateName}: AddOrDeletePolicyCustomUnitRateParams) => `heeft het tarief „${rateName}” van de eenheid „${customUnitName}” verwijderd`,
+        addedReportField: ({fieldType, fieldName}: AddedOrDeletedPolicyReportFieldParams) => `${fieldType} rapportveld "${fieldName}" toegevoegd`,
+        updateReportFieldDefaultValue: ({defaultValue, fieldName}: UpdatedPolicyReportFieldDefaultValueParams) =>
+            `stel de standaardwaarde van rapportveld "${fieldName}" in op "${defaultValue}"`,
+        addedReportFieldOption: (fieldName: any, optionName: string) => `heeft de optie ‘${optionName}’ toegevoegd aan het rapportveld ‘${fieldName}’`,
+        removedReportFieldOption: (fieldName: any, optionName: string) => `heeft de optie "${optionName}" verwijderd uit het rapportveld "${fieldName}"`,
         updateReportFieldOptionDisabled: (fieldName: string, optionName: string, optionEnabled: boolean) =>
             `${optionEnabled ? 'ingeschakeld' : 'uitgeschakeld'} de optie "${optionName}" voor het rapportveld "${fieldName}"`,
         updateReportFieldAllOptionsDisabled: (fieldName: string, optionName: string, allEnabled: boolean, toggledOptionsCount?: number) => {
@@ -7660,20 +6668,23 @@ er bestedingsregels toe om de kasstroom van het bedrijf te beschermen.`,
             return `${allEnabled ? 'ingeschakeld' : 'uitgeschakeld'} de optie „${optionName}” voor het rapportveld „${fieldName}”, waardoor alle opties ${allEnabled ? 'ingeschakeld' : 'uitgeschakeld'}`;
         },
         deleteReportField: ({fieldType, fieldName}: {fieldType: string; fieldName?: string}) => `heeft ${fieldType}-rapportveld "${fieldName}" verwijderd`,
-        preventSelfApproval: (oldValue: string, newValue: string) =>
+        preventSelfApproval: ({oldValue, newValue}: UpdatedPolicyPreventSelfApprovalParams) =>
             `heeft “Zelfgoedkeuring voorkomen” bijgewerkt naar “${newValue === 'true' ? 'Ingeschakeld' : 'Uitgeschakeld'}” (voorheen “${oldValue === 'true' ? 'Ingeschakeld' : 'Uitgeschakeld'}”)`,
-        updateMonthlyOffset: (oldValue: string, newValue: string) => {
+        updateMonthlyOffset: ({oldValue, newValue}: UpdatedPolicyFieldWithNewAndOldValueParams) => {
             if (!oldValue) {
                 return `stel de maandelijkse rapportindieningsdatum in op "${newValue}"`;
             }
             return `heeft de maandelijkse rapportindieningsdatum bijgewerkt naar "${newValue}" (voorheen "${oldValue}")`;
         },
-        updateDefaultBillable: (oldValue: string, newValue: string) => `heeft ‘Onkosten opnieuw aan klanten doorberekenen’ bijgewerkt naar ‘${newValue}’ (voorheen ‘${oldValue}’)`,
-        updateDefaultReimbursable: (oldValue: string, newValue: string) => `heeft ‘Contante uitgave standaard’ gewijzigd in ‘${newValue}’ (voorheen ‘${oldValue}’)`,
-        updateDefaultTitleEnforced: (value: boolean) => `heeft ‘Standaardrapporttitels afdwingen’ ${value ? 'aan' : 'uit'} ingeschakeld`,
-        changedCustomReportNameFormula: (oldValue: string, newValue: string) => `heeft de aangepaste rapportnaamsformule gewijzigd in „${newValue}” (voorheen „${oldValue}”)`,
+        updateDefaultBillable: ({oldValue, newValue}: UpdatedPolicyFieldWithNewAndOldValueParams) =>
+            `heeft ‘Onkosten opnieuw aan klanten doorberekenen’ bijgewerkt naar ‘${newValue}’ (voorheen ‘${oldValue}’)`,
+        updateDefaultReimbursable: ({oldValue, newValue}: UpdatedPolicyFieldWithNewAndOldValueParams) =>
+            `heeft ‘Contante uitgave standaard’ gewijzigd in ‘${newValue}’ (voorheen ‘${oldValue}’)`,
+        updateDefaultTitleEnforced: ({value}: UpdatedPolicyFieldWithValueParams) => `heeft ‘Standaardrapporttitels afdwingen’ ${value ? 'aan' : 'uit'} ingeschakeld`,
+        changedCustomReportNameFormula: ({newValue, oldValue}: UpdatedPolicyFieldWithNewAndOldValueParams) =>
+            `heeft de aangepaste rapportnaamsformule gewijzigd in „${newValue}” (voorheen „${oldValue}”)`,
         renamedWorkspaceNameAction: (oldName: string, newName: string) => `heeft de naam van deze workspace gewijzigd in „${newName}” (voorheen „${oldName}”)`,
-        updateWorkspaceDescription: (newDescription: string, oldDescription: string) =>
+        updateWorkspaceDescription: ({newDescription, oldDescription}: UpdatedPolicyDescriptionParams) =>
             !oldDescription
                 ? `stel de beschrijving van deze workspace in op "${newDescription}"`
                 : `heeft de beschrijving van deze workspace bijgewerkt naar „${newDescription}” (voorheen „${oldDescription}”)`,
@@ -7693,23 +6704,23 @@ er bestedingsregels toe om de kasstroom van het bedrijf te beschermen.`,
         },
         demotedFromWorkspace: (policyName: string, oldRole: string) =>
             `heeft je rol in ${policyName} bijgewerkt van ${oldRole} naar gebruiker. Je bent verwijderd uit alle inzendingsdeclaratiechats, behalve uit je eigen.`,
-        updatedWorkspaceCurrencyAction: (oldCurrency: string, newCurrency: string) => `heeft de standaardvaluta bijgewerkt naar ${newCurrency} (voorheen ${oldCurrency})`,
-        updatedWorkspaceFrequencyAction: (oldFrequency: string, newFrequency: string) =>
+        updatedWorkspaceCurrencyAction: ({oldCurrency, newCurrency}: UpdatedPolicyCurrencyParams) => `heeft de standaardvaluta bijgewerkt naar ${newCurrency} (voorheen ${oldCurrency})`,
+        updatedWorkspaceFrequencyAction: ({oldFrequency, newFrequency}: UpdatedPolicyFrequencyParams) =>
             `heeft de frequentie van automatisch rapporteren gewijzigd naar ‘${newFrequency}’ (voorheen ‘${oldFrequency}’)`,
         updateApprovalMode: ({newValue, oldValue}: ChangeFieldParams) => `heeft de goedkeuringsmodus gewijzigd naar ‘${newValue}’ (voorheen ‘${oldValue}’)`,
         upgradedWorkspace: 'heeft deze workspace geüpgraded naar het Control-abonnement',
         forcedCorporateUpgrade: `Deze werkruimte is geüpgraded naar het Control-abonnement. Klik <a href="${CONST.COLLECT_UPGRADE_HELP_URL}">hier</a> voor meer informatie.`,
         downgradedWorkspace: 'heeft deze workspace teruggezet naar het Collect-abonnement',
-        updatedAuditRate: (oldAuditRate: number, newAuditRate: number) =>
+        updatedAuditRate: ({oldAuditRate, newAuditRate}: UpdatedPolicyAuditRateParams) =>
             `heeft het percentage rapporten dat willekeurig voor handmatige goedkeuring wordt doorgestuurd gewijzigd naar ${Math.round(newAuditRate * 100)}% (voorheen ${Math.round(oldAuditRate * 100)}%)`,
-        updatedManualApprovalThreshold: (oldLimit: string, newLimit: string) =>
+        updatedManualApprovalThreshold: ({oldLimit, newLimit}: UpdatedPolicyManualApprovalThresholdParams) =>
             `heeft de handmatige goedkeuringslimiet voor alle declaraties gewijzigd naar ${newLimit} (voorheen ${oldLimit})`,
         updatedFeatureEnabled: ({enabled, featureName}: {enabled: boolean; featureName: string}) => {
             switch (featureName) {
                 case 'categories':
                     return `${enabled ? 'ingeschakeld' : 'uitgeschakeld'} categorieën`;
                 case 'tags':
-                    return `${enabled ? 'ingeschakeld' : 'uitgeschakeld'} tags`;
+                    return `${enabled ? 'ingeschakeld' : 'uitgeschakeld'} labels`;
                 case 'workflows':
                     return `${enabled ? 'ingeschakeld' : 'uitgeschakeld'} workflows`;
                 case 'distance rates':
@@ -7717,9 +6728,7 @@ er bestedingsregels toe om de kasstroom van het bedrijf te beschermen.`,
                 case 'accounting':
                     return `${enabled ? 'ingeschakeld' : 'uitgeschakeld'} boekhouding`;
                 case 'Expensify Cards':
-                    return `${enabled ? 'ingeschakeld' : 'uitgeschakeld'} Expensify Kaarten`;
-                case 'travel invoicing':
-                    return `${enabled ? 'ingeschakeld' : 'uitgeschakeld'} reisfacturering`;
+                    return `${enabled ? 'ingeschakeld' : 'uitgeschakeld'} Expensify Cards`;
                 case 'company cards':
                     return `${enabled ? 'ingeschakeld' : 'uitgeschakeld'} bedrijfskaarten`;
                 case 'invoicing':
@@ -7727,7 +6736,7 @@ er bestedingsregels toe om de kasstroom van het bedrijf te beschermen.`,
                 case 'per diem':
                     return `${enabled ? 'ingeschakeld' : 'uitgeschakeld'} dagvergoeding`;
                 case 'receipt partners':
-                    return `${enabled ? 'ingeschakeld' : 'uitgeschakeld'} bonpartners`;
+                    return `${enabled ? 'ingeschakeld' : 'uitgeschakeld'} ontvangstpartners`;
                 case 'rules':
                     return `${enabled ? 'ingeschakeld' : 'uitgeschakeld'} regels`;
                 case 'tax tracking':
@@ -7800,17 +6809,14 @@ er bestedingsregels toe om de kasstroom van het bedrijf te beschermen.`,
             oldValue ? `heeft de naam van het factuurbedrijf gewijzigd naar ‘${newValue}’ (voorheen ‘${oldValue}’)` : `stel de bedrijfsnaam op de factuur in op ‘${newValue}’`,
         changedInvoiceCompanyWebsite: ({newValue, oldValue}: {newValue: string; oldValue?: string}) =>
             oldValue ? `heeft de bedrijfswebsite op de factuur gewijzigd naar "${newValue}" (voorheen "${oldValue}")` : `stel de bedrijfswebsite van de factuur in op "${newValue}"`,
-        changedReimburser: (newReimburser: string, previousReimburser?: string) =>
+        changedReimburser: ({newReimburser, previousReimburser}: UpdatedPolicyReimburserParams) =>
             previousReimburser
                 ? `heeft de gemachtigde betaler gewijzigd in „${newReimburser}” (voorheen „${previousReimburser}”)`
                 : `heeft de gemachtigde betaler gewijzigd naar ‘${newReimburser}’`,
-        updateReimbursementEnabled: (enabled: boolean) => `${enabled ? 'ingeschakeld' : 'uitgeschakeld'} terugbetalingen`,
-        updateCustomTaxName: (oldName: string, newName: string) => `de aangepaste belastingnaam gewijzigd in "${newName}" (voorheen "${oldName}")`,
-        updateCurrencyDefaultTax: (oldName: string, newName: string) => `heeft het standaardbelastingtarief van de werkruimtevaluta gewijzigd in "${newName}" (voorheen "${oldName}")`,
-        updateForeignCurrencyDefaultTax: (oldName: string, newName: string) => `heeft het standaardbelastingtarief voor vreemde valuta gewijzigd in '${newName}' (voorheen '${oldName}')`,
-        addTax: (taxName: string) => `heeft de belasting ‘${taxName}’ toegevoegd`,
-        deleteTax: (taxName: string) => `heeft de belasting ‘${taxName}’ verwijderd`,
-        updateTax: (oldValue?: string | boolean | number, taxName?: string, updatedField?: string, newValue?: string | boolean | number) => {
+        updateReimbursementEnabled: ({enabled}: UpdatedPolicyReimbursementEnabledParams) => `${enabled ? 'ingeschakeld' : 'uitgeschakeld'} terugbetalingen`,
+        addTax: ({taxName}: UpdatedPolicyTaxParams) => `heeft de belasting ‘${taxName}’ toegevoegd`,
+        deleteTax: ({taxName}: UpdatedPolicyTaxParams) => `heeft de belasting ‘${taxName}’ verwijderd`,
+        updateTax: ({oldValue, taxName, updatedField, newValue}: UpdatedPolicyTaxParams) => {
             if (!updatedField) {
                 return '';
             }
@@ -7832,32 +6838,30 @@ er bestedingsregels toe om de kasstroom van het bedrijf te beschermen.`,
                 }
             }
         },
-        setReceiptRequiredAmount: (newValue: string) => `stel het vereiste bonbedrag in op "${newValue}"`,
-        changedReceiptRequiredAmount: (oldValue: string, newValue: string) => `heeft het vereiste bonbedrag gewijzigd naar "${newValue}" (voorheen "${oldValue}")`,
-        removedReceiptRequiredAmount: (oldValue: string) => `vereiste bedrag op verwijderde bon (voorheen “${oldValue}”)`,
-        setItemizedReceiptRequiredAmount: (newValue: string) => `stel het vereiste bedrag voor de gespecificeerde bon in op "${newValue}"`,
-        changedItemizedReceiptRequiredAmount: (oldValue: string, newValue: string) =>
-            `heeft het vereiste bedrag voor gespecificeerde bonnen gewijzigd naar "${newValue}" (voorheen "${oldValue}")`,
-        removedItemizedReceiptRequiredAmount: (oldValue: string) => `vereist bedrag voor gespecificeerde bon verwijderd (voorheen "${oldValue}")`,
-        setMaxExpenseAmount: (newValue: string) => `maximumbedrag voor uitgave instellen op "${newValue}"`,
-        changedMaxExpenseAmount: (oldValue: string, newValue: string) => `maximale onkostensom gewijzigd naar "${newValue}" (voorheen "${oldValue}")`,
-        removedMaxExpenseAmount: (oldValue: string) => `maximaal bedrag voor uitgave verwijderd (voorheen "${oldValue}")`,
-        setMaxExpenseAge: (newValue: string) => `stel maximale leeftijd uitgave in op "${newValue}" dagen`,
-        changedMaxExpenseAge: (oldValue: string, newValue: string) => `maximale uitgaafleeftijd gewijzigd naar "${newValue}" dagen (voorheen "${oldValue}")`,
-        removedMaxExpenseAge: (oldValue: string) => `maximale onkostendatum verwijderd (voorheen "${oldValue}" dagen)`,
-        updateCategories: (count: number) => `${count} categorieën bijgewerkt`,
-        updateTagList: (tagListName: string) => `tags op de lijst "${tagListName}" bijgewerkt`,
-        updateTagListRequired: (tagListsName: string, isRequired: boolean) => `heeft taglijst "${tagListsName}" gewijzigd naar ${isRequired ? 'vereist' : 'niet vereist'}`,
+        setReceiptRequiredAmount: ({newValue}: UpdatedPolicyFieldWithNewAndOldValueParams) => `stel het vereiste bonbedrag in op "${newValue}"`,
+        changedReceiptRequiredAmount: ({oldValue, newValue}: UpdatedPolicyFieldWithNewAndOldValueParams) =>
+            `heeft het vereiste bonbedrag gewijzigd naar "${newValue}" (voorheen "${oldValue}")`,
+        removedReceiptRequiredAmount: ({oldValue}: UpdatedPolicyFieldWithNewAndOldValueParams) => `vereiste bedrag op verwijderde bon (voorheen “${oldValue}”)`,
+        setMaxExpenseAmount: ({newValue}: UpdatedPolicyFieldWithNewAndOldValueParams) => `maximumbedrag voor uitgave instellen op "${newValue}"`,
+        changedMaxExpenseAmount: ({oldValue, newValue}: UpdatedPolicyFieldWithNewAndOldValueParams) => `maximale onkostensom gewijzigd naar "${newValue}" (voorheen "${oldValue}")`,
+        removedMaxExpenseAmount: ({oldValue}: UpdatedPolicyFieldWithNewAndOldValueParams) => `maximaal bedrag voor uitgave verwijderd (voorheen "${oldValue}")`,
+        setMaxExpenseAge: ({newValue}: UpdatedPolicyFieldWithNewAndOldValueParams) => `stel maximale leeftijd uitgave in op "${newValue}" dagen`,
+        changedMaxExpenseAge: ({oldValue, newValue}: UpdatedPolicyFieldWithNewAndOldValueParams) => `maximale uitgaafleeftijd gewijzigd naar "${newValue}" dagen (voorheen "${oldValue}")`,
+        removedMaxExpenseAge: ({oldValue}: UpdatedPolicyFieldWithNewAndOldValueParams) => `maximale onkostendatum verwijderd (voorheen "${oldValue}" dagen)`,
+        updateCategories: ({count}: UpdatedPolicyCategoriesParams) => `${count} categorieën bijgewerkt`,
+        updateTagList: ({tagListName}: UpdatedPolicyTagListParams) => `tags op de lijst "${tagListName}" bijgewerkt`,
+        updateTagListRequired: ({tagListsName, isRequired}: UpdatedPolicyTagListRequiredParams) =>
+            `heeft taglijst "${tagListsName}" gewijzigd naar ${isRequired ? 'vereist' : 'niet vereist'}`,
         importTags: 'geïmporteerde labels uit een spreadsheet',
         deletedAllTags: 'alle tags verwijderd',
-        updateCustomUnitDefaultCategory: (customUnitName: string, newValue?: string, oldValue?: string) =>
+        updateCustomUnitDefaultCategory: ({customUnitName, newValue, oldValue}: UpdatePolicyCustomUnitDefaultCategoryParams) =>
             `heeft de standaardcategorie voor ${customUnitName} gewijzigd in „${newValue}” ${oldValue ? `(eerder "${oldValue}")` : ''}`,
-        importCustomUnitRates: (customUnitName: string) => `geïmporteerde tarieven voor aangepaste eenheid "${customUnitName}"`,
-        updateCustomUnitSubRate: (customUnitName: string, customUnitRateName: string, customUnitSubRateName: string, oldValue: string, newValue: string, updatedField: string) =>
+        importCustomUnitRates: ({customUnitName}: ImportPolicyCustomUnitRatesParams) => `geïmporteerde tarieven voor aangepaste eenheid "${customUnitName}"`,
+        updateCustomUnitSubRate: ({customUnitName, customUnitRateName, customUnitSubRateName, oldValue, newValue, updatedField}: UpdatedPolicyCustomUnitSubRateParams) =>
             `heeft "${customUnitName}" tarief "${customUnitRateName}" subtarief "${customUnitSubRateName}" ${updatedField} gewijzigd naar "${newValue}" (voorheen "${oldValue}")`,
-        removedCustomUnitSubRate: (customUnitName: string, customUnitRateName: string, removedSubRateName: string) =>
+        removedCustomUnitSubRate: ({customUnitName, customUnitRateName, removedSubRateName}: RemovedPolicyCustomUnitSubRateParams) =>
             `heeft subtarief „${removedSubRateName}” verwijderd uit tarief „${customUnitRateName}” van eenheid „${customUnitName}”`,
-        addBudget: (frequency: string, entityName: string, entityType: string, shared?: string, individual?: string, notificationThreshold?: number) => {
+        addBudget: ({frequency, entityName, entityType, shared, individual, notificationThreshold}: AddBudgetParams) => {
             const thresholdSuffix = typeof notificationThreshold === 'number' ? `met een meldingsdrempel van "${notificationThreshold}%"` : '';
             if (typeof shared !== 'undefined' && typeof individual !== 'undefined') {
                 return `heeft ${frequency} individueel budget „${individual}” en ${frequency} gedeeld budget „${shared}”${thresholdSuffix} toegevoegd aan de ${entityType} „${entityName}”`;
@@ -7867,18 +6871,18 @@ er bestedingsregels toe om de kasstroom van het bedrijf te beschermen.`,
             }
             return `heeft ${frequency} gedeeld budget van "${shared}"${thresholdSuffix} toegevoegd aan de ${entityType} "${entityName}"`;
         },
-        updateBudget: (
-            entityType: string,
-            entityName: string,
-            oldFrequency?: string,
-            newFrequency?: string,
-            oldIndividual?: string,
-            newIndividual?: string,
-            oldShared?: string,
-            newShared?: string,
-            oldNotificationThreshold?: number,
-            newNotificationThreshold?: number,
-        ) => {
+        updateBudget: ({
+            entityType,
+            entityName,
+            oldFrequency,
+            newFrequency,
+            oldIndividual,
+            newIndividual,
+            oldShared,
+            newShared,
+            oldNotificationThreshold,
+            newNotificationThreshold,
+        }: UpdatedBudgetParams) => {
             const frequencyChanged = !!(newFrequency && oldFrequency !== newFrequency);
             const sharedChanged = !!(newShared && oldShared !== newShared);
             const individualChanged = !!(newIndividual && oldIndividual !== newIndividual);
@@ -7913,7 +6917,7 @@ er bestedingsregels toe om de kasstroom van het bedrijf te beschermen.`,
             }
             return `bijgewerkt budget voor de ${entityType} "${entityName}": ${changesList.join('; ')}`;
         },
-        deleteBudget: (entityType: string, entityName: string, frequency?: string, individual?: string, shared?: string, notificationThreshold?: number) => {
+        deleteBudget: ({entityType, entityName, frequency, individual, shared, notificationThreshold}: DeleteBudgetParams) => {
             const thresholdSuffix = typeof notificationThreshold === 'number' ? `met een meldingsdrempel van "${notificationThreshold}%"` : '';
             if (shared && individual) {
                 return `heeft ${frequency} gedeeld budget van „${shared}” en individueel budget van „${individual}”${thresholdSuffix} verwijderd uit de ${entityType} „${entityName}”`;
@@ -7926,124 +6930,49 @@ er bestedingsregels toe om de kasstroom van het bedrijf te beschermen.`,
             }
             return `heeft budget verwijderd uit de ${entityType} "${entityName}"`;
         },
-        updatedTimeEnabled: (enabled?: boolean) => {
+        updatedTimeEnabled: ({enabled}: UpdatedPolicyTimeEnabledParams) => {
             return `${enabled ? 'ingeschakeld' : 'uitgeschakeld'} tijdregistratie`;
         },
-        updatedTimeRate: (newRate?: string, oldRate?: string) => {
+        updatedTimeRate: ({newRate, oldRate}: UpdatedPolicyTimeRateParams) => {
             return `uurloon gewijzigd naar ‘${newRate}’ (voorheen ‘${oldRate}’)`;
         },
         addedProhibitedExpense: ({prohibitedExpense}: {prohibitedExpense: string}) => `heeft ‘${prohibitedExpense}’ toegevoegd aan verboden uitgaven`,
         removedProhibitedExpense: ({prohibitedExpense}: {prohibitedExpense: string}) => `heeft „${prohibitedExpense}” verwijderd uit verboden uitgaven`,
-        updatedReimbursementChoice: (newReimbursementChoice: string, oldReimbursementChoice: string) =>
+        updatedReimbursementChoice: ({newReimbursementChoice, oldReimbursementChoice}: UpdatedPolicyReimbursementChoiceParams) =>
             `vergoedingsmethode gewijzigd naar ‘${newReimbursementChoice}’ (voorheen ‘${oldReimbursementChoice}’)`,
         setAutoJoin: ({enabled}: {enabled: boolean}) => `${enabled ? 'ingeschakeld' : 'uitgeschakeld'} vooraf goedkeuren van werkruimte-toevoegingsverzoeken`,
-        updatedDefaultTitle: (newDefaultTitle: string, oldDefaultTitle: string) => `heeft aangepaste rapportnaamformule gewijzigd in "${newDefaultTitle}" (voorheen "${oldDefaultTitle}")`,
-        updatedOwnership: (oldOwnerEmail: string, oldOwnerName: string, policyName: string) => `heeft het eigendom van ${policyName} overgenomen van ${oldOwnerName} (${oldOwnerEmail})`,
-        updatedAutoHarvesting: (enabled: boolean) => `${enabled ? 'ingeschakeld' : 'uitgeschakeld'} gepland indienen`,
-        updatedIndividualBudgetNotification: (
-            budgetAmount: string,
-            budgetFrequency: string,
-            budgetName: string,
-            budgetTypeForNotificationMessage: string,
-            thresholdPercentage: number,
-            totalSpend: number,
-            unsubmittedSpend: number,
-            awaitingApprovalSpend: number,
-            approvedReimbursedClosedSpend: number,
-            summaryLink?: string,
-            userEmail?: string,
-        ) =>
+        updatedDefaultTitle: ({newDefaultTitle, oldDefaultTitle}: UpdatedPolicyDefaultTitleParams) =>
+            `heeft aangepaste rapportnaamformule gewijzigd in "${newDefaultTitle}" (voorheen "${oldDefaultTitle}")`,
+        updatedOwnership: ({oldOwnerEmail, oldOwnerName, policyName}: UpdatedPolicyOwnershipParams) =>
+            `heeft het eigendom van ${policyName} overgenomen van ${oldOwnerName} (${oldOwnerEmail})`,
+        updatedAutoHarvesting: ({enabled}: UpdatedPolicyAutoHarvestingParams) => `${enabled ? 'ingeschakeld' : 'uitgeschakeld'} gepland indienen`,
+        updatedIndividualBudgetNotification: ({
+            budgetAmount,
+            budgetFrequency,
+            budgetName,
+            budgetTypeForNotificationMessage,
+            summaryLink,
+            thresholdPercentage,
+            totalSpend,
+            unsubmittedSpend,
+            userEmail,
+            awaitingApprovalSpend,
+            approvedReimbursedClosedSpend,
+        }: UpdatedPolicyBudgetNotificationParams) =>
             `Let op! Deze workspace heeft een ${budgetFrequency}-budget van '${budgetAmount}' voor de ${budgetTypeForNotificationMessage} '${budgetName}'. ${userEmail} zit momenteel op ${approvedReimbursedClosedSpend}, wat meer is dan ${thresholdPercentage}% van het budget. Er staat ook nog ${awaitingApprovalSpend} in afwachting van goedkeuring en ${unsubmittedSpend} dat nog niet is ingediend, voor een totaal van ${totalSpend}.${summaryLink ? `<a href="${summaryLink}">Hier is een rapport</a> met al die uitgaven voor jouw administratie!` : ''}`,
-        updatedSharedBudgetNotification: (
-            budgetAmount: string,
-            budgetFrequency: string,
-            budgetName: string,
-            budgetTypeForNotificationMessage: string,
-            summaryLink: string | undefined,
-            thresholdPercentage: number,
-            totalSpend: number,
-            unsubmittedSpend: number,
-            awaitingApprovalSpend: number,
-            approvedReimbursedClosedSpend: number,
-        ) =>
+        updatedSharedBudgetNotification: ({
+            budgetAmount,
+            budgetFrequency,
+            budgetName,
+            budgetTypeForNotificationMessage,
+            summaryLink,
+            thresholdPercentage,
+            totalSpend,
+            unsubmittedSpend,
+            awaitingApprovalSpend,
+            approvedReimbursedClosedSpend,
+        }: UpdatedPolicyBudgetNotificationParams) =>
             `Let op! Deze workspace heeft een ${budgetFrequency}-budget van ‘${budgetAmount}’ voor de ${budgetTypeForNotificationMessage} ‘${budgetName}’. Je zit nu op ${approvedReimbursedClosedSpend}, wat meer is dan ${thresholdPercentage}% van het budget. Er staat ook nog ${awaitingApprovalSpend} in afwachting van goedkeuring en ${unsubmittedSpend} is nog niet ingediend, voor een totaal van ${totalSpend}. ${summaryLink ? `<a href="${summaryLink}">Hier is een rapport</a> met al die onkosten voor je administratie!` : ''}`,
-        addedCardFeed: (feedName: string) => `kaartfeed ‘${feedName}’ toegevoegd`,
-        removedCardFeed: (feedName: string) => `kaartfeed "${feedName}" verwijderd`,
-        renamedCardFeed: (newName: string, oldName: string) => `kaartfeed hernoemd naar ‘${newName}’ (voorheen ‘${oldName}’)`,
-        assignedCompanyCard: (email: string, feedName: string, cardLastFour: string) =>
-            `heeft ${feedName ? `"${feedName}" ` : ''}bedrijfskaart eindigend op ${cardLastFour} toegewezen aan ${email}`,
-        unassignedCompanyCard: (email: string, feedName: string, cardLastFour: string) =>
-            `niet-toegewezen ${feedName ? `"${feedName}" ` : ''}bedrijfskaart van ${email} eindigend op ${cardLastFour}`,
-        updatedCardFeedLiability: (feedName: string, enabled: boolean) =>
-            `${enabled ? 'ingeschakeld' : 'uitgeschakeld'} kaarthouders om kaarttransacties te verwijderen voor kaartfeed "${feedName}"`,
-        updatedCardFeedStatementPeriod: (feedName: string, newValue?: string, previousValue?: string) =>
-            `heeft de einddag van de afrekenperiode van kaartfeed "${feedName}" gewijzigd${newValue ? ` naar "${newValue}"` : ''}${previousValue ? ` (voorheen "${previousValue}")` : ''}`,
-        addedReportField: (fieldType: string, fieldName?: string, defaultValue?: string) =>
-            `heeft ${fieldType}-rapportveld "${fieldName}" toegevoegd${defaultValue ? ` met standaardwaarde "${defaultValue}"` : ''}`,
-        updatedMccGroupCategory: ({mccGroupName, oldCategory, newCategory}: {mccGroupName: string; oldCategory: string; newCategory: string}) =>
-            `heeft de standaarduitgavencategorie voor ‘${mccGroupName}’ gewijzigd in ‘${newCategory}’ (voorheen ‘${oldCategory}’)`,
-        updatedRequireCompanyCards: ({enabled}: {enabled: boolean}) => `vereiste ${enabled ? 'ingeschakeld' : 'uitgeschakeld'} voor bedrijfskaarttransacties`,
-        expensifyCardRule: {
-            actionVerb: {block: 'geblokkeerd', allow: 'toegestaan'},
-            amountOperator: {over: 'over', under: 'onder'},
-            amountFilter: ({operator, amount}: {operator: string; amount: string}) => `bedragen ${operator} ${amount}`,
-            theCard: 'de kaart',
-            multipleCards: ({count}: {count: number}) => ({
-                one: '1 kaart',
-                other: `${count} kaarten`,
-            }),
-            addRule: ({verb, filters, cards}: {verb: string; filters: string; cards: string}) => {
-                let text = verb;
-                if (filters !== '') {
-                    text += ` ${filters}`;
-                }
-                text += ` op ${cards}`;
-                return text;
-            },
-            removeRule: ({cards}: {cards: string}) => `besteedregel verwijderd van ${cards}`,
-            restrictionVerb: {block: 'blokkeren', allow: 'alleen toestaan'},
-            update: {
-                modeChange: ({fromAction, toAction, cards}: {fromAction: string; toAction: string; cards: string}) =>
-                    `heeft bestedingsregel gewijzigd van ${fromAction} naar ${toAction} op ${cards}`,
-                appliedToAdditionalCards: ({count}: {count: number}) => ({
-                    one: 'uitgavenregel toegepast op 1 extra kaart',
-                    other: `uitgavenregel toegepast op ${count} extra kaarten`,
-                }),
-                phraseVerb: {added: 'toegevoegd', removed: 'verwijderd', changed: 'gewijzigd', set: 'instellen', applied: 'toegepast'},
-                bodyMerchant: ({adjective, value}: {adjective: string; value: string}) => (adjective !== '' ? `${adjective} handelaar '${value}'` : `handelaar '${value}'`),
-                bodyMerchantChange: ({adjective, oldValue, newValue}: {adjective: string; oldValue: string; newValue: string}) =>
-                    adjective !== '' ? `${adjective} verkoper gewijzigd van '${oldValue}' naar '${newValue}'` : `handelaar van '${oldValue}' naar '${newValue}'`,
-                bodySpendCategory: ({adjective, value}: {adjective: string; value: string}) =>
-                    adjective !== '' ? `${adjective} uitgavencategorie '${value}'` : `uitgavencategorie ‘${value}’`,
-                bodySpendCategoryChange: ({adjective, oldValue, newValue}: {adjective: string; oldValue: string; newValue: string}) =>
-                    adjective !== '' ? `${adjective} uitgavencategorie van '${oldValue}' naar '${newValue}'` : `uitgavencategorie van '${oldValue}' naar '${newValue}'`,
-                bodyMaxAmount: 'maximum bedrag',
-                bodyMaxAmountSet: ({value}: {value: string}) => `maximumbedrag tot ${value}`,
-                bodyMaxAmountChange: ({oldValue, newValue}: {oldValue: string; newValue: string}) => `maximumbedrag van ${oldValue} naar ${newValue}`,
-                bodyAppliedToAdditionalCards: ({count}: {count: number}) => ({
-                    one: 'bestedingsregel naar 1 extra kaart',
-                    other: `bestedingsregel naar ${count} extra kaarten`,
-                }),
-                bodyRemovedFromCards: ({cards}: {cards: string}) => `bestedingsregel van ${cards}`,
-                composeOnCards: ({content, cards}: {content: string; cards: string}) => `${content} op ${cards}`,
-                composeFromCards: ({content, cards}: {content: string; cards: string}) => `${content} van ${cards}`,
-            },
-        },
-        addCustomUnitRateWithAmount: (rateName: string, rateValue: string) => `heeft tarief „${rateName}” van ${rateValue} toegevoegd`,
-        addCustomUnitRateWithAmountAndStartDate: (rateName: string, rateValue: string, startDate: string) => `tarief "${rateName}" van ${rateValue} toegevoegd, geldig vanaf ${startDate}`,
-        addCustomUnitRateWithAmountAndEndDate: (rateName: string, rateValue: string, endDate: string) => `heeft tarief „${rateName}” van ${rateValue} toegevoegd, geldig tot ${endDate}`,
-        addCustomUnitRateWithAmountAndDates: (rateName: string, rateValue: string, startDate: string, endDate: string) =>
-            `heeft tarief "${rateName}" van ${rateValue} toegevoegd, geldig van ${startDate} - ${endDate}`,
-        updatedCustomUnitRateStartDate: (rateName: string, newDate: string, oldDate?: string) =>
-            oldDate ? `startdatum van tarief "${rateName}" bijgewerkt naar ${newDate} (voorheen ${oldDate})` : `startdatum van tarief "${rateName}" instellen op ${newDate}`,
-        updatedCustomUnitRateEndDate: (rateName: string, newDate: string, oldDate?: string) =>
-            oldDate ? `einddatum van tarief "${rateName}" bijgewerkt naar ${newDate} (voorheen ${oldDate})` : `einddatum van tarief "${rateName}" instellen op ${newDate}`,
-        updatedCustomUnitRateStartAndEndDate: (rateName: string, newStartDate: string, newEndDate: string, oldStartDate?: string, oldEndDate?: string) =>
-            oldStartDate && oldEndDate
-                ? `start- en einddatum van tarief "${rateName}" bijgewerkt naar ${newStartDate} - ${newEndDate} (voorheen ${oldStartDate} - ${oldEndDate})`
-                : `start- en einddatum van tarief "${rateName}" ingesteld op ${newStartDate} - ${newEndDate}`,
-        removedCustomUnitRateStartDate: (rateName: string, oldDate: string) => `startdatum verwijderd van tarief "${rateName}" (voorheen ${oldDate})`,
-        removedCustomUnitRateEndDate: (rateName: string, oldDate: string) => `einddatum verwijderd van tarief "${rateName}" (voorheen ${oldDate})`,
     },
     roomMembersPage: {
         memberNotFound: 'Lid niet gevonden.',
@@ -8075,7 +7004,7 @@ er bestedingsregels toe om de kasstroom van het bedrijf te beschermen.`,
         completed: 'Voltooid',
         action: 'Voltooien',
         messages: {
-            created: (title: string) => `taak voor ${title}`,
+            created: ({title}: TaskCreatedActionParams) => `taak voor ${title}`,
             completed: 'gemarkeerd als voltooid',
             canceled: 'verwijderde taak',
             reopened: 'gemarkeerd als onvolledig',
@@ -8089,7 +7018,7 @@ er bestedingsregels toe om de kasstroom van het bedrijf te beschermen.`,
         deleteConfirmation: 'Weet je zeker dat je deze taak wilt verwijderen?',
     },
     statementPage: {
-        title: (year: number | string, monthName: string) => `Overzicht van ${monthName} ${year}`,
+        title: ({year, monthName}: StatementTitleParams) => `Overzicht van ${monthName} ${year}`,
     },
     keyboardShortcutsPage: {
         title: 'Sneltoetsen',
@@ -8102,8 +7031,6 @@ er bestedingsregels toe om de kasstroom van het bedrijf te beschermen.`,
             newChat: 'Nieuw chatscherm',
             copy: 'Opmerking kopiëren',
             openDebug: 'Dialoogvenster testvoorkeuren openen',
-            expenseReportSearch: 'Onkostendeclaraties zoeken',
-            goToWorkspace: 'Ga naar de werkruimte van het huidige rapport',
         },
     },
     guides: {
@@ -8113,8 +7040,6 @@ er bestedingsregels toe om de kasstroom van het bedrijf te beschermen.`,
     search: {
         resultsAreLimited: 'Zoekresultaten zijn beperkt.',
         viewResults: 'Resultaten bekijken',
-        applyFilters: 'Filters toepassen',
-        appliedFilters: 'Toegepaste filters',
         resetFilters: 'Filters resetten',
         searchResults: {
             emptyResults: {
@@ -8122,23 +7047,27 @@ er bestedingsregels toe om de kasstroom van het bedrijf te beschermen.`,
                 subtitle: `Probeer je zoekcriteria aan te passen of iets te maken met de knop +.`,
             },
             emptyExpenseResults: {
-                title: 'Nog geen uitgaven',
+                title: 'Je hebt nog geen uitgaven aangemaakt',
                 subtitle: 'Maak een uitgave aan of maak een testrit met Expensify om meer te leren.',
                 subtitleWithOnlyCreateButton: 'Gebruik de groene knop hieronder om een uitgave aan te maken.',
             },
             emptyReportResults: {
-                title: 'Nog geen rapporten',
+                title: 'Je hebt nog geen rapporten gemaakt',
                 subtitle: 'Maak een rapport of probeer Expensify uit om meer te weten te komen.',
                 subtitleWithOnlyCreateButton: 'Gebruik de groene knop hieronder om een rapport te maken.',
             },
             emptyInvoiceResults: {
-                title: 'Nog geen facturen',
+                title: dedent(`
+                    Je hebt nog geen facturen aangemaakt
+                `),
                 subtitle: 'Stuur een factuur of maak een testrit met Expensify om meer te weten te komen.',
                 subtitleWithOnlyCreateButton: 'Gebruik de groene knop hieronder om een factuur te versturen.',
-                subtitleCannotSend: 'Je hebt een werkruimte met Invoices ingeschakeld nodig om facturen te versturen.',
-                subtitleCannotSendWithTestDrive: 'Je hebt een werkruimte met Invoices ingeschakeld nodig om facturen te versturen. Maak een testrit met Expensify om meer te weten te komen.',
             },
-            emptyTripResults: {title: 'Nog geen reizen', subtitle: 'Begin met het boeken van je eerste reis hieronder.', buttonText: 'Boek een reis'},
+            emptyTripResults: {
+                title: 'Geen reizen om weer te geven',
+                subtitle: 'Begin met het boeken van je eerste reis hieronder.',
+                buttonText: 'Boek een reis',
+            },
             emptySubmitResults: {
                 title: 'Geen uitgaven om in te dienen',
                 subtitle: 'Alles is in orde. Maak een ererondje!',
@@ -8166,31 +7095,30 @@ er bestedingsregels toe om de kasstroom van het bedrijf te beschermen.`,
             },
         },
         columns: 'Kolommen',
-        editColumns: 'Kolommen bewerken',
         resetColumns: 'Kolommen opnieuw instellen',
         groupColumns: 'Kolommen groeperen',
         expenseColumns: 'Onkostencolommen',
-        saveView: 'Weergave opslaan',
+        statements: 'Afschriften',
+        unapprovedCash: 'Niet-goedgekeurde contante uitgaven',
+        unapprovedCard: 'Niet-goedgekeurde kaart',
+        reconciliation: 'Afstemming',
+        topSpenders: 'Grootste uitgaven doeners',
+        saveSearch: 'Zoekopdracht opslaan',
         deleteSavedSearch: 'Opgeslagen zoekopdracht verwijderen',
         deleteSavedSearchConfirm: 'Weet je zeker dat je deze zoekopdracht wilt verwijderen?',
         searchName: 'Zoeknaam',
         savedSearchesMenuItemTitle: 'Opgeslagen',
-        urlCopied: 'URL gekopieerd',
+        topCategories: 'Topcategorieën',
+        topMerchants: 'Topverkopers',
         groupedExpenses: 'gegroepeerde uitgaven',
         bulkActions: {
-            editMultiple: 'Meerdere bewerken',
-            editMultipleTitle: 'Meerdere uitgaven bewerken',
-            editMultipleDescription: 'Wijzigingen worden toegepast op alle geselecteerde uitgaven en overschrijven eerder ingestelde waarden.',
             approve: 'Goedkeuren',
             pay: 'Betalen',
             delete: 'Verwijderen',
             hold: 'Vasthouden',
             unhold: 'Blokkering opheffen',
             reject: 'Afwijzen',
-            duplicateExpense: ({count}: {count: number}) => `${count === 1 ? 'Declaratie' : 'Declaraties'} dupliceren`,
             noOptionsAvailable: 'Geen opties beschikbaar voor de geselecteerde groep onkosten.',
-            undelete: 'Terugzetten',
-            duplicateReport: ({count}: {count: number}) => `Duplicaat ${count === 1 ? 'rapport' : 'rapporten'}`,
         },
         filtersHeader: 'Filters',
         filters: {
@@ -8198,14 +7126,11 @@ er bestedingsregels toe om de kasstroom van het bedrijf te beschermen.`,
                 before: (date?: string) => `Voor ${date ?? ''}`,
                 after: (date?: string) => `Na ${date ?? ''}`,
                 on: (date?: string) => `Op ${date ?? ''}`,
-                customDate: 'Aangepaste datum',
-                customRange: 'Aangepast bereik',
                 presets: {
                     [CONST.SEARCH.DATE_PRESETS.NEVER]: 'Nooit',
                     [CONST.SEARCH.DATE_PRESETS.LAST_MONTH]: 'Vorige maand',
                     [CONST.SEARCH.DATE_PRESETS.THIS_MONTH]: 'Deze maand',
                     [CONST.SEARCH.DATE_PRESETS.YEAR_TO_DATE]: 'Jaar tot nu toe',
-                    [CONST.SEARCH.DATE_PRESETS.LAST_12_MONTHS]: 'Laatste 12 maanden',
                     [CONST.SEARCH.DATE_PRESETS.LAST_STATEMENT]: 'Laatste afschrift',
                 },
             },
@@ -8217,15 +7142,10 @@ er bestedingsregels toe om de kasstroom van het bedrijf te beschermen.`,
             currency: 'Valuta',
             completed: 'Voltooid',
             amount: {
-                lessThan: (amount?: string) => `Minder dan ${amount ?? ''}`,
-                greaterThan: (amount?: string) => `Groter dan ${amount ?? ''}`,
-                between: (greaterThan?: string, lessThan?: string) => {
-                    if (greaterThan && lessThan) {
-                        return `Tussen ${greaterThan} en ${lessThan}`;
-                    }
-                    return 'Tussen';
-                },
-                equalTo: (amount?: string) => `Gelijk aan ${amount ?? ''}`,
+                lessThan: ({amount}: OptionalParam<RequestAmountParams> = {}) => `Minder dan ${amount ?? ''}`,
+                greaterThan: ({amount}: OptionalParam<RequestAmountParams> = {}) => `Groter dan ${amount ?? ''}`,
+                between: (greaterThan: string, lessThan: string) => `Tussen ${greaterThan} en ${lessThan}`,
+                equalTo: ({amount}: OptionalParam<RequestAmountParams> = {}) => `Gelijk aan ${amount ?? ''}`,
             },
             card: {
                 expensify: 'Expensify',
@@ -8235,9 +7155,8 @@ er bestedingsregels toe om de kasstroom van het bedrijf te beschermen.`,
                 cardFeedName: ({cardFeedBankName, cardFeedLabel}: {cardFeedBankName: string; cardFeedLabel?: string}) =>
                     `Alle ${cardFeedBankName}${cardFeedLabel ? ` - ${cardFeedLabel}` : ''}`,
                 cardFeedNameCSV: ({cardFeedLabel}: {cardFeedLabel?: string}) => `Alle geïmporteerde CSV-kaarten${cardFeedLabel ? ` - ${cardFeedLabel}` : ''}`,
-                travelInvoicing: 'Reisfacturatie',
             },
-            reportField: (name: string, value: string) => `${name} is ${value}`,
+            reportField: ({name, value}: OptionalParam<ReportFieldParams>) => `${name} is ${value}`,
             current: 'Huidig',
             past: 'Verleden',
             submitted: 'Ingediend',
@@ -8249,10 +7168,6 @@ er bestedingsregels toe om de kasstroom van het bedrijf te beschermen.`,
             billable: 'Factureerbaar',
             reimbursable: 'Vergoedbaar',
             purchaseCurrency: 'Aankoopvaluta',
-            sortOrder: {
-                [CONST.SEARCH.SORT_ORDER.ASC]: 'Oplopend',
-                [CONST.SEARCH.SORT_ORDER.DESC]: 'Aflopend',
-            },
             groupBy: {
                 [CONST.SEARCH.GROUP_BY.FROM]: 'Van',
                 [CONST.SEARCH.GROUP_BY.CARD]: 'Kaart',
@@ -8267,9 +7182,8 @@ er bestedingsregels toe om de kasstroom van het bedrijf te beschermen.`,
             },
             feed: 'Feed',
             withdrawalType: {
-                [CONST.SEARCH.WITHDRAWAL_TYPE.EXPENSIFY_CARD]: 'Expensify Kaart',
-                [CONST.SEARCH.WITHDRAWAL_TYPE.REIMBURSEMENT]: 'Terugbetaling',
-                [CONST.SEARCH.WITHDRAWAL_TYPE.CENTRAL_TRAVEL_INVOICING]: 'Reisfacturatie',
+                [CONST.SEARCH.WITHDRAWAL_TYPE.EXPENSIFY_CARD]: 'Expensify Card',
+                [CONST.SEARCH.WITHDRAWAL_TYPE.REIMBURSEMENT]: 'Vergoeding',
             },
             is: 'Is',
             action: {
@@ -8279,20 +7193,25 @@ er bestedingsregels toe om de kasstroom van het bedrijf te beschermen.`,
                 [CONST.SEARCH.ACTION_FILTERS.EXPORT]: 'Exporteren',
             },
         },
-        display: {
-            label: 'Weergave',
-            sortBy: 'Sorteren op',
-            sortOrder: 'Sorteervolgorde',
-            groupBy: 'Groeperen op',
-            limitResults: 'Resultaten beperken',
-        },
         has: 'Heeft',
+        groupBy: 'Groeperen op',
         view: {
             label: 'Bekijken',
             table: 'Tabel',
             bar: 'Balk',
             line: 'Lijn',
-            pie: 'Cirkeldiagram',
+        },
+        chartTitles: {
+            [CONST.SEARCH.GROUP_BY.FROM]: 'Van',
+            [CONST.SEARCH.GROUP_BY.CARD]: 'Kaarten',
+            [CONST.SEARCH.GROUP_BY.WITHDRAWAL_ID]: 'Exporten',
+            [CONST.SEARCH.GROUP_BY.CATEGORY]: 'Categorieën',
+            [CONST.SEARCH.GROUP_BY.MERCHANT]: 'Handelaars',
+            [CONST.SEARCH.GROUP_BY.TAG]: 'Tags',
+            [CONST.SEARCH.GROUP_BY.MONTH]: 'Maanden',
+            [CONST.SEARCH.GROUP_BY.WEEK]: 'Weken',
+            [CONST.SEARCH.GROUP_BY.YEAR]: 'Jaren',
+            [CONST.SEARCH.GROUP_BY.QUARTER]: 'Kwartalen',
         },
         moneyRequestReport: {
             emptyStateTitle: 'Dit rapport heeft geen uitgaven.',
@@ -8301,26 +7220,13 @@ er bestedingsregels toe om de kasstroom van het bedrijf te beschermen.`,
         noCategory: 'Geen categorie',
         noMerchant: 'Geen handelaar',
         noTag: 'Geen tag',
-        expenseType: 'Onkostentype',
+        expenseType: 'Uitgavetype',
         withdrawalType: 'Type opname',
         recentSearches: 'Recente zoekopdrachten',
         recentChats: 'Recente chats',
-        serverResults: 'Zoekresultaten',
         searchIn: 'Zoeken in',
-        askConcierge: (message: string) => `Vraag Concierge: “${message}”`,
-        searchPlaceholder: 'Zoek iets...',
+        searchPlaceholder: 'Zoek iets',
         suggestions: 'Suggesties',
-        suggestionsAvailable: (
-            {
-                count,
-            }: {
-                count: number;
-            },
-            query = '',
-        ) => ({
-            one: `Suggesties beschikbaar${query ? ` voor ${query}` : ''}. ${count} resultaat.`,
-            other: (resultCount: number) => `Suggesties beschikbaar${query ? ` voor ${query}` : ''}. ${resultCount} resultaten.`,
-        }),
         exportSearchResults: {
             title: 'Export maken',
             description: 'Wow, dat zijn veel items! We bundelen ze, en Concierge stuurt je binnenkort een bestand.',
@@ -8329,41 +7235,6 @@ er bestedingsregels toe om de kasstroom van het bedrijf te beschermen.`,
         exportAll: {
             selectAllMatchingItems: 'Selecteer alle overeenkomende items',
             allMatchingItemsSelected: 'Alle overeenkomende items geselecteerd',
-            selectAllOnThisPage: 'Selecteer alles op deze pagina',
-        },
-        errors: {
-            pleaseSelectDatesForBothFromAndTo: 'Selecteer datums voor Van en Tot',
-        },
-        chartTitles: {
-            [CONST.SEARCH.GROUP_BY.FROM]: 'Van',
-            [CONST.SEARCH.GROUP_BY.CARD]: 'Kaarten',
-            [CONST.SEARCH.GROUP_BY.WITHDRAWAL_ID]: 'Exporten',
-            [CONST.SEARCH.GROUP_BY.CATEGORY]: 'Categorieën',
-            [CONST.SEARCH.GROUP_BY.MERCHANT]: 'Handelaars',
-            [CONST.SEARCH.GROUP_BY.TAG]: 'Tags',
-            [CONST.SEARCH.GROUP_BY.MONTH]: 'Maanden',
-            [CONST.SEARCH.GROUP_BY.WEEK]: 'Weken',
-            [CONST.SEARCH.GROUP_BY.YEAR]: 'Jaren',
-            [CONST.SEARCH.GROUP_BY.QUARTER]: 'Kwartalen',
-        },
-        spendOverTime: 'Uitgaven in de tijd',
-        tabs: {
-            expenseReports: 'Declaraties',
-            reports: 'Rapporten',
-            expenses: 'Declaraties',
-            submit: 'Concepten',
-            approve: 'Moet worden goedgekeurd',
-            pay: 'Klaar om te betalen',
-            accounting: 'Boekhouding',
-            export: 'Wachten op export',
-            unapprovedCash: 'Kasverplichtingen',
-            unapprovedCard: 'Kaartoplopende posten',
-            statements: 'Kaartafschriften',
-            reconciliation: 'Bankafstemming',
-            insights: 'Inzichten',
-            topSpenders: 'Grootste uitgaven doeners',
-            topCategories: 'Topcategorieën',
-            topMerchants: 'Topverkopers',
         },
     },
     genericErrorPage: {
@@ -8420,6 +7291,7 @@ er bestedingsregels toe om de kasstroom van het bedrijf te beschermen.`,
             emptyReportConfirmationTitle: 'Je hebt al een leeg rapport',
             emptyReportConfirmationPrompt: ({workspaceName}: {workspaceName: string}) =>
                 `Weet je zeker dat je nog een rapport wilt maken in ${workspaceName}? Je kunt je lege rapporten openen in`,
+            emptyReportConfirmationPromptLink: 'Rapporten',
             emptyReportConfirmationDontShowAgain: 'Dit niet meer tonen',
             genericWorkspaceName: 'deze workspace',
         },
@@ -8457,7 +7329,6 @@ er bestedingsregels toe om de kasstroom van het bedrijf te beschermen.`,
                     reimburseableLink: 'uit eigen zak gemaakte uitgaven',
                     nonReimbursableLink: 'uitgaven met bedrijfskaart',
                     pending: (label: string) => `is begonnen dit rapport te exporteren naar ${label}...`,
-                    travelCardLink: 'reiskartuitgaven',
                 },
                 integrationsMessage: (errorMessage: string, label: string, linkText?: string, linkURL?: string) =>
                     `het exporteren van dit rapport naar ${label} is mislukt ("${errorMessage}${linkText ? `<a href="${linkURL}">${linkText}</a>` : ''}")`,
@@ -8466,8 +7337,7 @@ er bestedingsregels toe om de kasstroom van het bedrijf te beschermen.`,
                 markedReimbursed: (amount: string, currency: string) => `elders ${currency}${amount} betaald`,
                 markedReimbursedFromIntegration: ({amount, currency}: MarkReimbursedFromIntegrationParams) => `heeft ${currency}${amount} betaald via integratie`,
                 outdatedBankAccount: `kon de betaling niet verwerken vanwege een probleem met de bankrekening van de betaler`,
-                reimbursementACHBounceDefault: `kon de betaling niet verwerken vanwege een verkeerd bank-/rekeningnummer of een gesloten rekening`,
-                reimbursementACHBounceWithReason: ({returnReason}: {returnReason: string}) => `kon de betaling niet verwerken: ${returnReason}`,
+                reimbursementACHBounce: `kon de betaling niet verwerken vanwege een probleem met de bankrekening`,
                 reimbursementACHCancelled: `heeft de betaling geannuleerd`,
                 reimbursementAccountChanged: `kon de betaling niet verwerken omdat de betaler van bankrekening is veranderd`,
                 reimbursementDelayed: `heeft de betaling verwerkt, maar deze is nog 1-2 extra werkdagen vertraagd`,
@@ -8475,22 +7345,17 @@ er bestedingsregels toe om de kasstroom van het bedrijf te beschermen.`,
                 selectedForRandomAuditMarkdown: `willekeurig geselecteerd voor controle`,
                 share: ({to}: ShareParams) => `heeft lid ${to} uitgenodigd`,
                 unshare: ({to}: UnshareParams) => `heeft lid ${to} verwijderd`,
-                stripePaid: (amount: string, currency: string) => `betaald ${currency}${amount}`,
+                stripePaid: ({amount, currency}: StripePaidParams) => `betaald ${currency}${amount}`,
                 takeControl: `nam de controle over`,
                 integrationSyncFailed: (label: string, errorMessage: string, workspaceAccountingLink?: string) =>
                     `er trad een probleem op bij het synchroniseren met ${label}${errorMessage ? ` ("${errorMessage}")` : ''}. Los het probleem op in de <a href="${workspaceAccountingLink}">werkruimte-instellingen</a>.`,
-                integrationSyncFailedRecurrence: ({count}: {count: number}) => `(${count} keer herhaald.)`,
                 companyCardConnectionBroken: ({feedName, workspaceCompanyCardRoute}: {feedName: string; workspaceCompanyCardRoute: string}) =>
                     `De verbinding met ${feedName} is verbroken. <a href='${workspaceCompanyCardRoute}'>Log in bij je bank</a> om kaartimports te herstellen.`,
                 plaidBalanceFailure: ({maskedAccountNumber, walletRoute}: {maskedAccountNumber: string; walletRoute: string}) =>
-                    `de Plaid-verbinding met je zakelijke bankrekening is verbroken. <a href='${walletRoute}'>Verbind je bankrekening ${maskedAccountNumber} opnieuw</a> zodat je je Expensify Kaarten kunt blijven gebruiken.`,
-                addEmployee: (email: string, role: string, didJoinPolicy?: boolean) => {
-                    const translatedRole = String(translations.workspace.common.roleName(role)).toLowerCase();
-                    const article = role === CONST.POLICY.ROLE.AUDITOR ? 'een' : 'een';
-                    return didJoinPolicy ? `${email} is via de werkruimte-uitnodigingslink lid geworden` : `heeft ${email} toegevoegd als ${article} ${translatedRole}`;
-                },
+                    `de Plaid-verbinding met je zakelijke bankrekening is verbroken. <a href='${walletRoute}'>Verbind je bankrekening ${maskedAccountNumber} opnieuw</a> zodat je je Expensify Cards kunt blijven gebruiken.`,
+                addEmployee: (email: string, role: string) => `${email} toegevoegd als ${role === 'member' ? 'een' : 'een'} ${role}`,
                 updateRole: ({email, currentRole, newRole}: UpdateRoleParams) => `heeft de rol van ${email} bijgewerkt naar ${newRole} (voorheen ${currentRole})`,
-                updatedCustomField1: (email: string, newValue: string, previousValue: string) => {
+                updatedCustomField1: ({email, previousValue, newValue}: UpdatedCustomFieldParams) => {
                     if (!newValue) {
                         return `heeft aangepaste veld 1 van ${email} verwijderd (voorheen "${previousValue}")`;
                     }
@@ -8498,7 +7363,7 @@ er bestedingsregels toe om de kasstroom van het bedrijf te beschermen.`,
                         ? `heeft "${newValue}" toegevoegd aan aangepast veld 1 van ${email}`
                         : `heeft aangepaste veld 1 van ${email} gewijzigd in "${newValue}" (voorheen "${previousValue}")`;
                 },
-                updatedCustomField2: (email: string, newValue: string, previousValue: string) => {
+                updatedCustomField2: ({email, previousValue, newValue}: UpdatedCustomFieldParams) => {
                     if (!newValue) {
                         return `heeft aangepaste veld 2 van ${email} verwijderd (voorheen "${previousValue}")`;
                     }
@@ -8512,12 +7377,8 @@ er bestedingsregels toe om de kasstroom van het bedrijf te beschermen.`,
                 addedConnection: ({connectionName}: ConnectionNameParams) => `verbonden met ${CONST.POLICY.CONNECTIONS.NAME_USER_FRIENDLY[connectionName]}`,
                 leftTheChat: 'heeft de chat verlaten',
                 settlementAccountLocked: ({maskedBankAccountNumber}: OriginalMessageSettlementAccountLocked, linkURL: string) =>
-                    `zakelijke bankrekening ${maskedBankAccountNumber} is automatisch vergrendeld vanwege een probleem met terugbetalingen of Expensify Kaart-afwikkeling. Los het probleem op in je <a href="${linkURL}">werkruimte-instellingen</a>.`,
+                    `de zakelijke bankrekening ${maskedBankAccountNumber} is automatisch vergrendeld vanwege een probleem met terugbetalingen of de afrekening van Expensify Cards. Los het probleem op in je <a href="${linkURL}">werkruimte-instellingen</a>.`,
                 leftTheChatWithName: (nameOrEmail: string) => `${nameOrEmail ? `${nameOrEmail}: ` : ''}heeft de chat verlaten`,
-                actionableCard3DSTransactionApproval: (amount: string, merchant: string | undefined) => {
-                    const amountAndMerchantText = [amount, merchant].filter((s) => !!s?.length).join(' ');
-                    return `Open de mobiele Expensify-app om je${amountAndMerchantText ? ` ${amountAndMerchantText}-` : ' '}transactie te bekijken`;
-                },
             },
             error: {
                 invalidCredentials: 'Ongeldige inloggegevens, controleer de configuratie van je verbinding.',
@@ -8527,23 +7388,6 @@ er bestedingsregels toe om de kasstroom van het bedrijf te beschermen.`,
     chronos: {
         oooEventSummaryFullDay: (summary: string, dayCount: number, date: string) => `${summary} voor ${dayCount} ${dayCount === 1 ? 'dag' : 'dagen'} tot ${date}`,
         oooEventSummaryPartialDay: (summary: string, timePeriod: string, date: string) => `${summary} van ${timePeriod} op ${date}`,
-        startTimer: 'Timer starten',
-        stopTimer: (duration: string) => `Timer stoppen (${duration})`,
-        scheduleOOO: 'Afwezigheid plannen',
-        scheduleOOOTitle: 'Afwezigheid plannen',
-        date: 'Datum',
-        time: 'Tijd (24-uursnotatie)',
-        durationAmount: 'Duur',
-        durationUnit: 'Eenheid',
-        reason: 'Reden',
-        workingPercentage: 'Werkpercentage',
-        dateRequired: 'Datum is verplicht.',
-        invalidTimeFormat: 'Voer een geldige 24-uurs tijd in (bijv. 14:30).',
-        enterANumber: 'Voer een getal in.',
-        hour: 'uren',
-        day: 'dagen',
-        week: 'weken',
-        month: 'maanden',
     },
     footer: {
         features: 'Functies',
@@ -8586,24 +7430,8 @@ er bestedingsregels toe om de kasstroom van het bedrijf te beschermen.`,
         workspaceName: 'Naam werkruimte',
         chatUserDisplayNames: 'Weergavenamen van chatleden',
         scrollToNewestMessages: 'Scroll naar nieuwste berichten',
-        scrollToActionBadgeTarget: 'Scroll naar actie die aandacht vereist',
         preStyledText: 'Vooraf opgemaakte tekst',
         viewAttachment: 'Bijlage bekijken',
-        contextMenuAvailable: 'Contextmenu beschikbaar. Druk op Shift+F10 om het te openen.',
-        contextMenuAvailableMacOS: 'Contextmenu beschikbaar. Druk op VO-Shift-M om het te openen.',
-        contextMenuAvailableNative: 'Contextmenu beschikbaar. Dubbeltik en houd vast om het te openen.',
-        selectAllFeatures: 'Selecteer alle functies',
-        selectAllTransactions: 'Selecteer alle transacties',
-        selectAllItems: 'Alle items selecteren',
-        openActionsMenu: 'Acties-menu openen',
-        selectAllCategories: 'Selecteer alle categorieën',
-        selectAllDistanceRates: 'Selecteer alle afstandstarieven',
-        selectAllTags: 'Alle tags selecteren',
-        selectAllTaxes: 'Selecteer alle belastingen',
-        selectAllPerDiemRates: 'Selecteer alle dagvergoedingen',
-        selectAllMembers: 'Alle leden selecteren',
-        selectAllValues: 'Selecteer alle waarden',
-        selectAllRules: 'Selecteer alle regels',
     },
     parentReportAction: {
         deletedReport: 'Verwijderd rapport',
@@ -8622,7 +7450,6 @@ er bestedingsregels toe om de kasstroom van het bedrijf te beschermen.`,
         parentNavigationSummary: ({reportName, workspaceName}: ParentNavigationSummaryParams) => `Van ${reportName}${workspaceName ? `in ${workspaceName}` : ''}`,
     },
     qrCodes: {
-        qrCode: 'QR-code',
         copy: 'URL kopiëren',
         copied: 'Gekopieerd!',
     },
@@ -8669,11 +7496,6 @@ er bestedingsregels toe om de kasstroom van het bedrijf te beschermen.`,
             'Sluit je aan bij Expensify.org om onrecht overal ter wereld uit te bannen. De huidige campagne “Teachers Unite” ondersteunt onderwijzers overal door de kosten van essentiële schoolbenodigdheden te delen.',
         iKnowATeacher: 'Ik ken een leraar',
         iAmATeacher: 'Ik ben een leraar',
-        personalKarma: {
-            title: 'Persoonlijke karma inschakelen',
-            description: 'Doneer $1 aan Expensify.org voor elke $500 die je elke maand uitgeeft',
-            stopDonationsPrompt: 'Weet je zeker dat je wilt stoppen met doneren aan Expensify.org?',
-        },
         getInTouch: 'Uitstekend! Deel hun gegevens zodat we contact met hen kunnen opnemen.',
         introSchoolPrincipal: 'Introductie bij je schooldirecteur',
         schoolPrincipalVerifyExpense:
@@ -8696,11 +7518,6 @@ er bestedingsregels toe om de kasstroom van het bedrijf te beschermen.`,
         notActivated: 'Niet geactiveerd',
         outOfPocket: 'Vergoedbaar',
         companySpend: 'Niet vergoedbaar',
-        personalCard: 'Persoonlijke kaart',
-        companyCard: 'Bedrijfskaart',
-        expensifyCard: 'Expensify Kaart',
-        travelInvoicing: 'Reisfacturatie',
-        travelCard: 'Reiskaart',
     },
     distance: {
         addStop: 'Stop toevoegen',
@@ -8724,18 +7541,14 @@ er bestedingsregels toe om de kasstroom van het bedrijf te beschermen.`,
             endReading: 'Lezen beëindigen',
             saveForLater: 'Bewaren voor later',
             totalDistance: 'Totale afstand',
+            startTitle: 'Foto beginstand kilometerteller',
+            endTitle: 'Eindfoto kilometerteller',
             startMessageWeb: 'Voeg een foto toe van de kilometerteller aan het <strong>begin</strong> van je reis. Sleep een bestand hierheen of kies er een om te uploaden.',
             endMessageWeb: 'Voeg een foto toe van je kilometerteller aan het <strong>einde</strong> van je reis. Sleep hier een bestand naartoe of kies er één om te uploaden.',
-            startTitle: 'Kilometerstand beginfoto',
-            endTitle: 'Eindfoto kilometerteller',
-            deleteOdometerPhoto: 'Kilometerstandfoto verwijderen',
-            deleteOdometerPhotoConfirmation: 'Weet je zeker dat je deze kilometertellerfoto wilt verwijderen?',
-            cameraAccessRequired: 'Cameratoegang is nodig om foto’s te maken.',
-            snapPhotoStart: '<muted-text-label>Maak een foto van je kilometerteller aan het <strong>begin</strong> van je rit.</muted-text-label>',
-            snapPhotoEnd: '<muted-text-label>Maak een foto van je kilometerteller aan het <strong>einde</strong> van je rit.</muted-text-label>',
         },
     },
     gps: {
+        disclaimer: 'Gebruik GPS om een uitgave van je reis te maken. Tik hieronder op Start om de registratie te beginnen.',
         error: {
             failedToStart: 'Locatietracking starten is mislukt.',
             failedToGetPermissions: 'Locatievereisten ophalen mislukt.',
@@ -8744,9 +7557,13 @@ er bestedingsregels toe om de kasstroom van het bedrijf te beschermen.`,
         stopped: 'Gestopt',
         start: 'Start',
         stop: 'Stop',
-        save: 'Opslaan',
-        resume: 'Hervatten',
         discard: 'Weggooien',
+        stopGpsTrackingModal: {
+            title: 'GPS-tracking stoppen',
+            prompt: 'Weet je het zeker? Dit beëindigt je huidige sessie.',
+            cancel: 'Tracking hervatten',
+            confirm: 'GPS-tracking stoppen',
+        },
         discardDistanceTrackingModal: {
             title: 'Afstandsregistratie negeren',
             prompt: 'Weet je het zeker? Hiermee wordt je huidige proces afgebroken en dit kan niet ongedaan worden gemaakt.',
@@ -8794,18 +7611,12 @@ er bestedingsregels toe om de kasstroom van het bedrijf te beschermen.`,
             prompt: 'Weet je zeker dat je het volgen via gps wilt stoppen en wilt overschakelen naar Expensify Classic?',
             confirm: 'Stoppen en overschakelen',
         },
-        switchAccountWarningTripInProgress: {
-            title: 'GPS-tracking bezig',
-            prompt: 'Weet je zeker dat je GPS-tracking wilt stoppen en van account wilt wisselen?',
-            confirm: 'Stoppen en overschakelen',
-        },
         locationServicesRequiredModal: {
             title: 'Locatietoegang vereist',
             confirm: 'Instellingen openen',
             prompt: 'Sta locatiestoegang toe in de instellingen van je apparaat om GPS-afstandsregistratie te starten.',
         },
-        gpsFloatingPillText: 'GPS-tracking bezig...',
-        liveActivity: {subtitle: 'Afstand bijhouden', button: 'Voortgang bekijken', lockScreenBadgeText: 'Afstand', lockScreenTrackingText: 'Bezig met bijhouden...'},
+        fabGpsTripExplained: 'Ga naar GPS-scherm (zwevende actie)',
     },
     reportCardLostOrDamaged: {
         screenTitle: 'Rapportkaart kwijt of beschadigd',
@@ -8832,13 +7643,11 @@ er bestedingsregels toe om de kasstroom van het bedrijf te beschermen.`,
         [CONST.REFERRAL_PROGRAM.CONTENT_TYPES.START_CHAT]: {
             buttonText: 'Begin een chat, <success><strong>verwijs een vriend</strong></success>.',
             header: 'Begin een chat, verwijs een vriend',
-            closeAccessibilityLabel: 'Sluiten, een chat starten, een vriend doorverwijzen, banner',
             body: 'Wil je dat je vrienden ook Expensify gebruiken? Begin gewoon een chat met hen en wij regelen de rest.',
         },
         [CONST.REFERRAL_PROGRAM.CONTENT_TYPES.SUBMIT_EXPENSE]: {
             buttonText: 'Dien een uitgave in, <success><strong>verwijs je team door</strong></success>.',
             header: 'Dien een uitgave in, verwijs je team',
-            closeAccessibilityLabel: 'Sluiten, een uitgave indienen, je team uitnodigen, banner',
             body: 'Wil je dat je team Expensify ook gebruikt? Dien gewoon een uitgave bij hen in en wij zorgen voor de rest.',
         },
         [CONST.REFERRAL_PROGRAM.CONTENT_TYPES.REFER_FRIEND]: {
@@ -8854,27 +7663,26 @@ er bestedingsregels toe om de kasstroom van het bedrijf te beschermen.`,
     },
     systemChatFooterMessage: {
         [CONST.INTRO_CHOICES.MANAGE_TEAM]: ({adminReportName, href}: {adminReportName: string; href: string}) =>
-            `Chat met je accountmanager in <a href="${href}">${adminReportName}</a> voor hulp`,
+            `Chat met je setupspecificus in <a href="${href}">${adminReportName}</a> voor hulp`,
         default: `Stuur een bericht naar <concierge-link>${CONST.CONCIERGE_CHAT_NAME}</concierge-link> voor hulp bij de installatie`,
     },
     violations: {
         allTagLevelsRequired: 'Alle tags verplicht',
         autoReportedRejectedExpense: 'Deze uitgave is afgewezen.',
         billableExpense: 'Factureerbaar niet langer geldig',
-        cashExpenseWithNoReceipt: (formattedLimit?: string) => `Bon vereist${formattedLimit ? `boven ${formattedLimit}` : ''}`,
+        cashExpenseWithNoReceipt: ({formattedLimit}: ViolationsCashExpenseWithNoReceiptParams = {}) => `Bon vereist${formattedLimit ? `boven ${formattedLimit}` : ''}`,
         categoryOutOfPolicy: 'Categorie niet meer geldig',
-        conversionSurcharge: (surcharge: number) => `${surcharge}% omrekeningsopslag toegepast`,
+        conversionSurcharge: ({surcharge}: ViolationsConversionSurchargeParams) => `${surcharge}% omrekeningsopslag toegepast`,
         customUnitOutOfPolicy: 'Tarief niet geldig voor deze werkruimte',
         duplicatedTransaction: 'Mogelijke duplicaat',
         fieldRequired: 'Rapportvelden zijn verplicht',
         futureDate: 'Toekomstige datum niet toegestaan',
-        inactiveVendor: 'Leverancier niet meer geldig',
-        invoiceMarkup: (invoiceMarkup: number) => `Met ${invoiceMarkup}% verhoogd`,
-        maxAge: (maxAge: number) => `Datum ouder dan ${maxAge} dagen`,
+        invoiceMarkup: ({invoiceMarkup}: ViolationsInvoiceMarkupParams) => `Met ${invoiceMarkup}% verhoogd`,
+        maxAge: ({maxAge}: ViolationsMaxAgeParams) => `Datum ouder dan ${maxAge} dagen`,
         missingCategory: 'Ontbrekende categorie',
         missingComment: 'Beschrijving vereist voor geselecteerde categorie',
         missingAttendees: 'Meerdere deelnemers vereist voor deze categorie',
-        missingTag: (tagName?: string) => `Ontbreekt ${tagName ?? 'label'}`,
+        missingTag: ({tagName}: ViolationsMissingTagParams = {}) => `Ontbreekt ${tagName ?? 'label'}`,
         modifiedAmount: ({type, displayPercentVariance}: ViolationsModifiedAmountParams) => {
             switch (type) {
                 case 'distance':
@@ -8889,17 +7697,15 @@ er bestedingsregels toe om de kasstroom van het bedrijf te beschermen.`,
             }
         },
         modifiedDate: 'Datum wijkt af van gescande bon',
-        increasedDistance: ({formattedRouteDistance}: ViolationsIncreasedDistanceParams) =>
-            formattedRouteDistance ? `Afstand overschrijdt de berekende route van ${formattedRouteDistance}` : 'Afstand overschrijdt de berekende route',
         nonExpensiworksExpense: 'Niet-Expensiworks-uitgave',
-        overAutoApprovalLimit: (formattedLimit: string) => `Kosten overschrijden de automatische goedkeuringslimiet van ${formattedLimit}`,
-        overCategoryLimit: (formattedLimit: string) => `Bedrag boven de categorielimiet van ${formattedLimit} per persoon`,
-        overLimit: (formattedLimit: string) => `Bedrag boven de limiet van ${formattedLimit} per persoon`,
-        overTripLimit: (formattedLimit: string) => `Bedrag boven limiet van ${formattedLimit} per reis`,
-        overLimitAttendee: (formattedLimit: string) => `Bedrag boven de limiet van ${formattedLimit} per persoon`,
-        perDayLimit: (formattedLimit: string) => `Bedrag boven de dagelijkse ${formattedLimit}/persoon-categorielimiet`,
+        overAutoApprovalLimit: ({formattedLimit}: ViolationsOverLimitParams) => `Kosten overschrijden de automatische goedkeuringslimiet van ${formattedLimit}`,
+        overCategoryLimit: ({formattedLimit}: ViolationsOverCategoryLimitParams) => `Bedrag boven de categorielimiet van ${formattedLimit} per persoon`,
+        overLimit: ({formattedLimit}: ViolationsOverLimitParams) => `Bedrag boven de limiet van ${formattedLimit} per persoon`,
+        overTripLimit: ({formattedLimit}: ViolationsOverLimitParams) => `Bedrag boven limiet van ${formattedLimit} per reis`,
+        overLimitAttendee: ({formattedLimit}: ViolationsOverLimitParams) => `Bedrag boven de limiet van ${formattedLimit} per persoon`,
+        perDayLimit: ({formattedLimit}: ViolationsPerDayLimitParams) => `Bedrag boven de dagelijkse ${formattedLimit}/persoon-categorielimiet`,
         receiptNotSmartScanned: 'Ontvangst- en onkostendetails handmatig toegevoegd.',
-        receiptRequired: (formattedLimit?: string, category?: string) => {
+        receiptRequired: ({formattedLimit, category}: ViolationsReceiptRequiredParams) => {
             if (formattedLimit && category) {
                 return `Bon nodig boven categorielimiet van ${formattedLimit}`;
             }
@@ -8911,8 +7717,8 @@ er bestedingsregels toe om de kasstroom van het bedrijf te beschermen.`,
             }
             return 'Bon vereist';
         },
-        itemizedReceiptRequired: (formattedLimit?: string) => `Gespecificeerde bon vereist${formattedLimit ? `boven ${formattedLimit}` : ''}`,
-        prohibitedExpense: (prohibitedExpenseTypes: string | string[]) => {
+        itemizedReceiptRequired: ({formattedLimit}: {formattedLimit?: string}) => `Gespecificeerde bon vereist${formattedLimit ? `boven ${formattedLimit}` : ''}`,
+        prohibitedExpense: ({prohibitedExpenseTypes}: ViolationsProhibitedExpenseParams) => {
             const preMessage = 'Verboden uitgave:';
             const getProhibitedExpenseTypeText = (prohibitedExpenseType: string) => {
                 switch (prohibitedExpenseType) {
@@ -8926,10 +7732,6 @@ er bestedingsregels toe om de kasstroom van het bedrijf te beschermen.`,
                         return `entertainment voor volwassenen`;
                     case 'hotelIncidentals':
                         return `hotelincidentals`;
-                    case 'giftCard':
-                        return `cadeaukaartaankopen`;
-                    case 'handwrittenReceipt':
-                        return `handgeschreven bonnen`;
                     default:
                         return `${prohibitedExpenseType}`;
                 }
@@ -8945,37 +7747,19 @@ er bestedingsregels toe om de kasstroom van het bedrijf te beschermen.`,
             }
             return `${preMessage} ${types.map(getProhibitedExpenseTypeText).join(', ')}`;
         },
-        customRules: (message: string) => message,
+        customRules: ({message}: ViolationsCustomRulesParams) => message,
         reviewRequired: 'Beoordeling vereist',
-        rter: (
-            brokenBankConnection: boolean,
-            isAdmin: boolean,
-            isTransactionOlderThan7Days: boolean,
-            member?: string,
-            rterType?: string,
-            companyCardPageURL?: string,
-            connectionLink?: string,
-            isPersonalCard?: boolean,
-            isMarkAsCash?: boolean,
-        ) => {
+        rter: ({brokenBankConnection, isAdmin, isTransactionOlderThan7Days, member, rterType, companyCardPageURL}: ViolationsRterParams) => {
             if (rterType === CONST.RTER_VIOLATION_TYPES.BROKEN_CARD_CONNECTION_530) {
-                return 'Bon kan automatisch aan bon koppelen vanwege verbroken bankverbinding.';
-            }
-            if (isPersonalCard && (rterType === CONST.RTER_VIOLATION_TYPES.BROKEN_CARD_CONNECTION || brokenBankConnection)) {
-                if (!connectionLink) {
-                    return 'Bon kan automatisch aan bon koppelen vanwege verbroken bankverbinding.';
-                }
-                return isMarkAsCash
-                    ? `Kan bon niet automatisch koppelen vanwege een verbroken kaartverbinding. Markeer als contant om te negeren, of <a href="${connectionLink}">repareer de kaart</a> om de bon te koppelen.`
-                    : `Kan bon automatisch koppelen aan bon vanwege verbroken kaartverbinding. <a href="${connectionLink}">Herstel de kaart</a> om de bon te koppelen.`;
+                return 'Kan bon niet automatisch koppelen vanwege een verbroken bankverbinding';
             }
             if (brokenBankConnection || rterType === CONST.RTER_VIOLATION_TYPES.BROKEN_CARD_CONNECTION) {
                 return isAdmin
-                    ? `Bankkoppeling verbroken. <a href="${companyCardPageURL}">Opnieuw verbinden om bon te koppelen</a>`
-                    : 'Bankkoppeling verbroken. Vraag een beheerder om de verbinding opnieuw te maken om de bon te laten overeenkomen.';
+                    ? `Bankkoppeling verbroken. <a href="${companyCardPageURL}">Opnieuw verbinden om bon te matchen</a>`
+                    : 'Bankverbinding verbroken. Vraag een beheerder om opnieuw te verbinden om het met de bon te matchen.';
             }
             if (!isTransactionOlderThan7Days) {
-                return isAdmin ? `Vraag ${member} om het als contant te markeren of wacht 7 dagen en probeer het opnieuw` : 'In afwachting van koppeling met kaarttransactie.';
+                return isAdmin ? `Vraag ${member} om het als contant te markeren of wacht 7 dagen en probeer het opnieuw` : 'In afwachting van samenvoeging met kaarttransactie.';
             }
             return '';
         },
@@ -8984,21 +7768,12 @@ er bestedingsregels toe om de kasstroom van het bedrijf te beschermen.`,
             `<muted-text-label>Bon in behandeling vanwege een verbroken bankverbinding. Los dit op in <a href="${workspaceCompanyCardRoute}">Bedrijfspassen</a>.</muted-text-label>`,
         memberBrokenConnectionError: 'Bon wordt vastgehouden vanwege een verbroken bankkoppeling. Vraag een werkruimtebeheerder om dit op te lossen.',
         markAsCashToIgnore: 'Markeren als contant om te negeren en betaling aan te vragen.',
-        smartscanFailed: ({canEdit = true, missingFields = []}: {canEdit?: boolean; missingFields?: string[]}) => {
-            if (missingFields.length > 0) {
-                const fieldNames: Record<string, string> = {merchant: 'handelaar', date: 'datum', amount: 'bedrag'};
-                const translated = missingFields.map((f) => fieldNames[f] ?? f);
-                const fieldList = translated.join(translated.length > 2 ? ', ' : ' en ');
-                const verb = translated.length === 1 ? 'ontbreekt' : 'ontbreken';
-                return `Bon scannen mislukt — ${fieldList} ${verb}.${canEdit ? ' Voer gegevens handmatig in.' : ''}`;
-            }
-            return `Bon scannen mislukt.${canEdit ? 'Voer gegevens handmatig in.' : ''}`;
-        },
+        smartscanFailed: ({canEdit = true}) => `Bon scannen mislukt.${canEdit ? 'Voer gegevens handmatig in.' : ''}`,
         receiptGeneratedWithAI: 'Mogelijke AI-gegenereerde bon',
-        someTagLevelsRequired: (tagName?: string) => `Ontbreekt ${tagName ?? 'Label'}`,
-        tagOutOfPolicy: (tagName?: string) => `${tagName ?? 'Label'} niet meer geldig`,
+        someTagLevelsRequired: ({tagName}: ViolationsTagOutOfPolicyParams = {}) => `Ontbreekt ${tagName ?? 'Label'}`,
+        tagOutOfPolicy: ({tagName}: ViolationsTagOutOfPolicyParams = {}) => `${tagName ?? 'Label'} niet meer geldig`,
         taxAmountChanged: 'Belastingbedrag is gewijzigd',
-        taxOutOfPolicy: (taxName?: string) => `${taxName ?? 'Belasting'} niet meer geldig`,
+        taxOutOfPolicy: ({taxName}: ViolationsTaxOutOfPolicyParams = {}) => `${taxName ?? 'Belasting'} niet meer geldig`,
         taxRateChanged: 'Belastingtarief is gewijzigd',
         taxRequired: 'Ontbrekend belastingtarief',
         none: 'Geen',
@@ -9018,7 +7793,7 @@ er bestedingsregels toe om de kasstroom van het bedrijf te beschermen.`,
         noRoute: 'Selecteer een geldig adres',
     },
     reportViolations: {
-        [CONST.REPORT_VIOLATIONS.FIELD_REQUIRED]: (fieldName: string) => `${fieldName} is verplicht`,
+        [CONST.REPORT_VIOLATIONS.FIELD_REQUIRED]: ({fieldName}: RequiredFieldParams) => `${fieldName} is verplicht`,
         reportContainsExpensesWithViolations: 'Rapport bevat onkosten met overtredingen.',
     },
     violationDismissal: {
@@ -9074,7 +7849,6 @@ er bestedingsregels toe om de kasstroom van het bedrijf te beschermen.`,
         bookACallTextTop: 'Als je overschakelt naar Expensify Classic, loop je het volgende mis:',
         bookACallTextBottom: 'We spreken graag met je om te begrijpen waarom. Je kunt een gesprek inplannen met een van onze senior productmanagers om je behoeften te bespreken.',
         takeMeToExpensifyClassic: 'Breng me naar Expensify Classic',
-        goBackJustOnce: 'Eenmalig teruggaan',
     },
     listBoundary: {
         errorMessage: 'Er is een fout opgetreden bij het laden van meer berichten',
@@ -9148,7 +7922,7 @@ er bestedingsregels toe om de kasstroom van het bedrijf te beschermen.`,
                 subtitle: 'Als volgende stap kun je <a href="#">je configuratiechecklist voltooien</a>, zodat je team kan beginnen met declareren.',
             },
             trialStarted: {
-                title: (numOfDays: number) => `Proefperiode: nog ${numOfDays} ${numOfDays === 1 ? 'dag' : 'dagen'}!`,
+                title: ({numOfDays}: TrialStartedTitleParams) => `Proefperiode: nog ${numOfDays} ${numOfDays === 1 ? 'dag' : 'dagen'}!`,
                 subtitle: 'Voeg een betaalkaart toe om al je favoriete functies te blijven gebruiken.',
             },
             trialEnded: {
@@ -9186,15 +7960,15 @@ er bestedingsregels toe om de kasstroom van het bedrijf te beschermen.`,
             title: 'Uw abonnement',
             exploreAllPlans: 'Bekijk alle abonnementen',
             customPricing: 'Aangepaste prijsstelling',
-            asLowAs: (price: string) => `al vanaf ${price} per actieve deelnemer/maand`,
-            pricePerMemberMonth: (price: string) => `${price} per lid/maand`,
-            pricePerMemberPerMonth: (price: string) => `${price} per lid per maand`,
+            asLowAs: ({price}: YourPlanPriceValueParams) => `al vanaf ${price} per actieve deelnemer/maand`,
+            pricePerMemberMonth: ({price}: YourPlanPriceValueParams) => `${price} per lid/maand`,
+            pricePerMemberPerMonth: ({price}: YourPlanPriceValueParams) => `${price} per lid per maand`,
             perMemberMonth: 'per lid/maand',
             collect: {
                 title: 'Incasseren',
                 description: 'Het kleinzakelijke abonnement dat je onkosten, reizen en chat biedt.',
-                priceAnnual: ({lower, upper}: YourPlanPriceParams) => `Van ${lower}/actief lid met de Expensify Kaart, ${upper}/actief lid zonder de Expensify Kaart.`,
-                pricePayPerUse: ({lower, upper}: YourPlanPriceParams) => `Van ${lower}/actief lid met de Expensify Kaart, ${upper}/actief lid zonder de Expensify Kaart.`,
+                priceAnnual: ({lower, upper}: YourPlanPriceParams) => `Van ${lower}/actief lid met de Expensify Card, ${upper}/actief lid zonder de Expensify Card.`,
+                pricePayPerUse: ({lower, upper}: YourPlanPriceParams) => `Van ${lower}/actief lid met de Expensify Card, ${upper}/actief lid zonder de Expensify Card.`,
                 benefit1: 'Bonnetjes scannen',
                 benefit2: 'Terugbetalingen',
                 benefit3: 'Beheer van bedrijfskaarten',
@@ -9207,8 +7981,8 @@ er bestedingsregels toe om de kasstroom van het bedrijf te beschermen.`,
             control: {
                 title: 'Beheer',
                 description: 'Declareren, reizen en chatten voor grotere bedrijven.',
-                priceAnnual: ({lower, upper}: YourPlanPriceParams) => `Van ${lower}/actief lid met de Expensify Kaart, ${upper}/actief lid zonder de Expensify Kaart.`,
-                pricePayPerUse: ({lower, upper}: YourPlanPriceParams) => `Van ${lower}/actief lid met de Expensify Kaart, ${upper}/actief lid zonder de Expensify Kaart.`,
+                priceAnnual: ({lower, upper}: YourPlanPriceParams) => `Van ${lower}/actief lid met de Expensify Card, ${upper}/actief lid zonder de Expensify Card.`,
+                pricePayPerUse: ({lower, upper}: YourPlanPriceParams) => `Van ${lower}/actief lid met de Expensify Card, ${upper}/actief lid zonder de Expensify Card.`,
                 benefit1: 'Alles in het Collect-abonnement',
                 benefit2: 'Meerlagige goedkeuringsworkflows',
                 benefit3: 'Aangepaste onkostregels',
@@ -9222,8 +7996,8 @@ er bestedingsregels toe om de kasstroom van het bedrijf te beschermen.`,
             downgrade: 'Downgraden naar Collect',
             upgrade: 'Upgraden naar Control',
             addMembers: 'Leden toevoegen',
-            saveWithExpensifyTitle: 'Bespaar met de Expensify Kaart',
-            saveWithExpensifyDescription: 'Gebruik onze besparingscalculator om te zien hoe cashback van de Expensify Kaart je Expensify‑rekening kan verlagen.',
+            saveWithExpensifyTitle: 'Bespaar met de Expensify Card',
+            saveWithExpensifyDescription: 'Gebruik onze besparingscalculator om te zien hoe cashback van de Expensify Card je Expensify‑rekening kan verlagen.',
             saveWithExpensifyButton: 'Meer informatie',
         },
         compareModal: {
@@ -9233,7 +8007,6 @@ er bestedingsregels toe om de kasstroom van het bedrijf te beschermen.`,
         details: {
             title: 'Abonnementsgegevens',
             annual: 'Jaarabonnement',
-            creditBalance: 'Creditsaldo',
             taxExempt: 'Vrijstelling van belasting aanvragen',
             taxExemptEnabled: 'Vrijgesteld van belasting',
             taxExemptStatus: 'Belastingvrijstellingstatus',
@@ -9251,10 +8024,10 @@ er bestedingsregels toe om de kasstroom van het bedrijf te beschermen.`,
             note: 'Opmerking: Een actief lid is iedereen die onkostengegevens die aan de werkruimte van je bedrijf zijn gekoppeld heeft aangemaakt, bewerkt, ingediend, goedgekeurd, terugbetaald of geëxporteerd.',
             confirmDetails: 'Bevestig de details van je nieuwe jaarlijkse abonnement:',
             subscriptionSize: 'Abonnementsgrootte',
-            activeMembers: (size: number) => `${size} actieve leden/maand`,
+            activeMembers: ({size}: SubscriptionSizeParams) => `${size} actieve leden/maand`,
             subscriptionRenews: 'Abonnement wordt verlengd',
             youCantDowngrade: 'Je kunt je jaarlijkse abonnement niet downgraden.',
-            youAlreadyCommitted: (size: number, date: string) =>
+            youAlreadyCommitted: ({size, date}: SubscriptionCommitmentParams) =>
                 `Je hebt je al vastgelegd op een jaarlijkse abonnementsomvang van ${size} actieve leden per maand tot ${date}. Je kunt op ${date} overstappen naar een gebruiksafhankelijk abonnement door automatisch verlengen uit te schakelen.`,
             error: {
                 size: 'Voer een geldig abonnementsaantal in',
@@ -9267,50 +8040,37 @@ er bestedingsregels toe om de kasstroom van het bedrijf te beschermen.`,
             security: 'Expensify is PCI-DSS-conform, gebruikt encryptie op bankniveau en maakt gebruik van redundante infrastructuur om je gegevens te beschermen.',
             learnMoreAboutSecurity: 'Meer informatie over onze beveiliging.',
         },
-        expensifyCode: {
-            title: 'Expensify-code',
-            discountCode: 'Kortingscode',
-            enterCode: 'Voer een Expensify-code in om toe te passen op je abonnement.',
-            discountMessage: (promoDiscount: string, validBillingCycles: string) =>
-                `Je ontvangt ${promoDiscount}% korting op je volgende ${validBillingCycles ? `${validBillingCycles} ` : ''}factureringskosten.`,
-            apply: 'Toepassen',
-            error: {
-                invalid: 'Deze code is ongeldig',
-            },
-        },
         subscriptionSettings: {
             title: 'Abonnementsinstellingen',
-            summary: (subscriptionType: string, subscriptionSize: string, expensifyCode: string, autoRenew: string, autoIncrease: string) =>
-                `Abonnementstype: ${subscriptionType}, Abonnementsomvang: ${subscriptionSize}${expensifyCode ? `, Expensify-code: ${expensifyCode}` : ''}, Automatisch verlengen: ${autoRenew}, Automatisch jaarlijkse seats verhogen: ${autoIncrease}`,
+            summary: ({subscriptionType, subscriptionSize, autoRenew, autoIncrease}: SubscriptionSettingsSummaryParams) =>
+                `Abonnementstype: ${subscriptionType}, Abonnementsomvang: ${subscriptionSize}, Automatisch verlengen: ${autoRenew}, Automatisch jaarlijkse seats verhogen: ${autoIncrease}`,
             none: 'geen',
             on: 'aan',
             off: 'uit',
             annual: 'Jaarlijks',
             autoRenew: 'Automatisch verlengen',
             autoIncrease: 'Automatisch jaarlijks aantal licenties verhogen',
-            saveUpTo: (amountWithCurrency: string) => `Bespaar tot ${amountWithCurrency}/maand per actief lid`,
+            saveUpTo: ({amountWithCurrency}: SubscriptionSettingsSaveUpToParams) => `Bespaar tot ${amountWithCurrency}/maand per actief lid`,
             automaticallyIncrease:
                 'Verhoog je jaarlijkse aantal seats automatisch om actieve leden te accommoderen die het aantal in je abonnement overschrijden. Let op: hierdoor wordt de einddatum van je jaarlijkse abonnement verlengd.',
             disableAutoRenew: 'Automatisch verlengen uitschakelen',
             helpUsImprove: 'Help ons Expensify verbeteren',
             whatsMainReason: 'Wat is de belangrijkste reden dat je automatische verlenging uitschakelt?',
-            renewsOn: (date: string) => `Wordt verlengd op ${date}.`,
-            pricingConfiguration: 'De prijs is afhankelijk van de configuratie. Kies voor de laagste prijs een jaarlijks abonnement en krijg de Expensify Kaart.',
-            learnMore: (hasAdminsRoom: boolean) =>
+            renewsOn: ({date}: SubscriptionSettingsRenewsOnParams) => `Wordt verlengd op ${date}.`,
+            pricingConfiguration: 'De prijs is afhankelijk van de configuratie. Kies voor de laagste prijs een jaarlijks abonnement en neem de Expensify Card.',
+            learnMore: ({hasAdminsRoom}: SubscriptionSettingsLearnMoreParams) =>
                 `<muted-text>Lees meer op onze <a href="${CONST.PRICING}">prijspagina</a> of chat met ons team in je ${hasAdminsRoom ? `<a href="adminsRoom">#admins-kamer.</a>` : '#admins-kamer.'}</muted-text>`,
             estimatedPrice: 'Geschatte prijs',
-            changesBasedOn: 'Dit verandert op basis van je gebruik van de Expensify Kaart en de abonnementsopties hieronder.',
-            collectBillingDescription: 'Collect-werkruimtes worden maandelijks per lid gefactureerd, zonder jaarlijkse verplichting.',
-            pricing: 'Prijzen',
+            changesBasedOn: 'Dit verandert op basis van je gebruik van de Expensify Card en de onderstaande abonnementopties.',
         },
-        cancelSubscription: {
-            title: 'Abonnement opzeggen',
-            subtitle: 'Wat is de belangrijkste reden dat je je abonnement opzegt?',
+        requestEarlyCancellation: {
+            title: 'Vroegtijdige annulering aanvragen',
+            subtitle: 'Wat is de belangrijkste reden dat je om vervroegde annulering vraagt?',
             subscriptionCanceled: {
                 title: 'Abonnement geannuleerd',
                 subtitle: 'Je jaarlijkse abonnement is opgezegd.',
                 info: 'Als je je werkruimte(s) op basis van betalen-per-gebruik wilt blijven gebruiken, ben je helemaal klaar.',
-                preventFutureActivity: (workspacesListRoute: string) =>
+                preventFutureActivity: ({workspacesListRoute}: WorkspacesListRouteParams) =>
                     `Als je toekomstige activiteit en kosten wilt voorkomen, moet je je <a href="${workspacesListRoute}">werkruimte(s) verwijderen</a>. Let op: wanneer je je werkruimte(s) verwijdert, worden eventuele openstaande activiteiten die in de huidige kalendermaand hebben plaatsgevonden alsnog in rekening gebracht.`,
             },
             requestSubmitted: {
@@ -9318,7 +8078,7 @@ er bestedingsregels toe om de kasstroom van het bedrijf te beschermen.`,
                 subtitle:
                     'Bedankt dat je ons laat weten dat je je abonnement wilt opzeggen. We bekijken je verzoek en nemen binnenkort contact met je op via je chat met <concierge-link>Concierge</concierge-link>.',
             },
-            acknowledgement: `Door het verzoek om opzegging erken en ga ik ermee akkoord dat Expensify volgens de Expensify <a href=${CONST.OLD_DOT_PUBLIC_URLS.TERMS_URL}>Servicevoorwaarden</a> of een andere toepasselijke dienstverleningsovereenkomst tussen mij en Expensify niet verplicht is om een dergelijk verzoek te honoreren en dat Expensify de volledige beslissingsbevoegdheid behoudt met betrekking tot het al dan niet inwilligen van een dergelijk verzoek.`,
+            acknowledgement: `Door het verzoek om vroegtijdige opzegging erken en ga ik ermee akkoord dat Expensify volgens de Expensify <a href=${CONST.OLD_DOT_PUBLIC_URLS.TERMS_URL}>Servicevoorwaarden</a> of een andere toepasselijke dienstverleningsovereenkomst tussen mij en Expensify niet verplicht is om een dergelijk verzoek te honoreren en dat Expensify de volledige beslissingsbevoegdheid behoudt met betrekking tot het al dan niet inwilligen van een dergelijk verzoek.`,
         },
     },
     feedbackSurvey: {
@@ -9337,14 +8097,11 @@ er bestedingsregels toe om de kasstroom van het bedrijf te beschermen.`,
     },
     delegate: {
         switchAccount: 'Van account wisselen:',
-        switch: 'Wisselen',
-        copilot: 'Copilot',
         copilotDelegatedAccess: 'Copilot: Gedelegeerde toegang',
         copilotDelegatedAccessDescription: 'Sta andere leden toe toegang te krijgen tot je account.',
-        learnMoreAboutDelegatedAccess: 'Meer informatie over gedelegeerde toegang',
-        addCopilot: 'Co-piloot toevoegen',
+        addCopilot: 'Copiloot toevoegen',
         membersCanAccessYourAccount: 'Deze leden hebben toegang tot je account:',
-        youCanAccessTheseAccounts: 'Je hebt toegang tot deze accounts:',
+        youCanAccessTheseAccounts: 'Je hebt toegang tot deze accounts via de accountwisselaar:',
         role: ({role}: OptionalParam<DelegateRoleParams> = {}) => {
             switch (role) {
                 case CONST.DELEGATE_ROLE.ALL:
@@ -9464,7 +8221,6 @@ er bestedingsregels toe om de kasstroom van het bedrijf te beschermen.`,
             theresWasAProblemDuringAWorkspaceConnectionSync: 'Er is een probleem opgetreden tijdens een synchronisatie van de werkruimtekoppeling',
             theresAProblemWithYourWallet: 'Er is een probleem met je wallet',
             theresAProblemWithYourWalletTerms: 'Er is een probleem met de voorwaarden van je wallet',
-            aBankAccountIsLocked: 'Een bankrekening is geblokkeerd',
         },
     },
     emptySearchView: {
@@ -9485,10 +8241,15 @@ er bestedingsregels toe om de kasstroom van het bedrijf te beschermen.`,
         conciergeLHNGBR: '<tooltip>Begin <strong>hier!</strong></tooltip>',
         saveSearchTooltip: '<tooltip><strong>Hernoem hier je opgeslagen zoekopdrachten</strong>!</tooltip>',
         accountSwitcher: '<tooltip>Krijg hier toegang tot je <strong>Copilot-accounts</strong></tooltip>',
+        scanTestTooltip: {
+            main: '<tooltip><strong>Scan onze testbon</strong> om te zien hoe het werkt!</tooltip>',
+            manager: '<tooltip>Kies onze <strong>testmanager</strong> om het uit te proberen!</tooltip>',
+            confirmation: '<tooltip>Dien nu <strong>je uitgave in</strong> en zie de magie gebeuren!</tooltip>',
+            tryItOut: 'Probeer het uit',
+        },
         outstandingFilter: '<tooltip>Filter voor uitgaven\ndie <strong>goedkeuring nodig hebben</strong></tooltip>',
         scanTestDriveTooltip: '<tooltip>Stuur deze bon om\n<strong>de proefrit te voltooien!</strong></tooltip>',
         gpsTooltip: '<tooltip>GPS-tracking bezig! Als je klaar bent, stop dan hieronder met bijhouden.</tooltip>',
-        hasFilterNegation: '<tooltip>Zoek naar uitgaven zonder bonnen met <strong>-has:receipt</strong>.</tooltip>',
     },
     discardChangesConfirmation: {
         title: 'Wijzigingen negeren?',
@@ -9504,7 +8265,7 @@ er bestedingsregels toe om de kasstroom van het bedrijf te beschermen.`,
         confirmation: {
             title: 'Gesprek bevestigen',
             description: 'Controleer of de onderstaande gegevens er goed uitzien. Zodra je het gesprek bevestigt, sturen we een uitnodiging met meer informatie.',
-            setupSpecialist: 'Je accountmanager',
+            setupSpecialist: 'Je configuratiespecialist',
             meetingLength: 'Vergaderduur',
             dateTime: 'Datum en tijd',
             minutes: '30 minuten',
@@ -9552,20 +8313,6 @@ Hier is een *proefbon* om je te laten zien hoe het werkt:`,
         exportInProgress: 'Export bezig',
         conciergeWillSend: 'Concierge stuurt je het bestand zo meteen.',
     },
-    exportDownload: {
-        preparingTitle: 'Preparing download...',
-        preparingBody: 'You can either wait for the download to finish or Concierge can send it to you via chat.',
-        sendFromConcierge: "Send me the file when it's ready",
-        conciergeTitle: 'You bet!',
-        conciergeBody: 'Concierge will send you a message when the file is ready.',
-        goToConcierge: 'Go to Concierge',
-        dismiss: 'Dismiss',
-        readyTitle: 'Your file is ready!',
-        readyBody: "If it didn't automatically download, use the button below.",
-        downloadFile: 'Download file',
-        failedTitle: 'Export failed',
-        close: 'Close',
-    },
     domain: {
         notVerified: 'Niet geverifieerd',
         retry: 'Opnieuw proberen',
@@ -9599,7 +8346,7 @@ Hier is een *proefbon* om je te laten zien hoe het werkt:`,
         goToDomain: 'Ga naar domein',
         samlLogin: {
             title: 'SAML-login',
-            subtitle: `<muted-text>Configureer aanmelden van leden met <a href="${CONST.SAML_HELP_URL}">SAML Single Sign-On (SSO)</a>.</muted-text>`,
+            subtitle: `<muted-text>Configureer aanmelden van leden met <a href="${CONST.SAML_HELP_URL}">SAML Single Sign-On (SSO).</a></muted-text>`,
             enableSamlLogin: 'SAML-login inschakelen',
             allowMembers: 'Leden toestaan in te loggen met SAML.',
             requireSamlLogin: 'SAML-login vereisen',
@@ -9609,8 +8356,6 @@ Hier is een *proefbon* om je te laten zien hoe het werkt:`,
             disableSamlRequired: 'Uitschakelen SAML vereist',
             oktaWarningPrompt: 'Weet je het zeker? Dit schakelt ook Okta SCIM uit.',
             requireWithEmptyMetadataError: 'Voeg hieronder de Identity Provider-metadata toe om in te schakelen',
-            pleaseDisableTwoFactorAuth: (twoFactorAuthSettingsUrl: string) =>
-                `<muted-text>Schakel <a href="${twoFactorAuthSettingsUrl}">het verplicht instellen van twee-factor-authenticatie</a> uit om SAML-aanmelding in te schakelen.</muted-text>`,
         },
         samlConfigurationDetails: {
             title: 'SAML-configuratiedetails',
@@ -9659,6 +8404,7 @@ Hier is een *proefbon* om je te laten zien hoe het werkt:`,
             primaryContact: 'Primair contactpersoon',
             addPrimaryContact: 'Primair contactpersoon toevoegen',
             setPrimaryContactError: 'Kan hoofdcontact niet instellen. Probeer het later opnieuw.',
+            settings: 'Instellingen',
             consolidatedDomainBilling: 'Geconsolideerde domeinfacturering',
             consolidatedDomainBillingDescription: (domainName: string) =>
                 `<comment><muted-text-label>Indien ingeschakeld betaalt de primaire contactpersoon voor alle werkruimtes die eigendom zijn van leden van <strong>${domainName}</strong> en ontvangt diegene alle factuurbewijzen.</muted-text-label></comment>`,
@@ -9675,107 +8421,25 @@ Hier is een *proefbon* om je te laten zien hoe het werkt:`,
             resetDomain: 'Domein resetten',
             resetDomainExplanation: ({domainName}: {domainName?: string}) => `Typ <strong>${domainName}</strong> om het resetten van het domein te bevestigen.`,
             enterDomainName: 'Voer hier je domeinnaam in',
-            resetDomainInfo: `Deze actie is <strong>definitief</strong> en de volgende gegevens worden verwijderd: <br/> <bullet-list><bullet-item>Bedrijfskaartverbindingen en alle niet-ingediende uitgaven van die kaarten</bullet-item><bullet-item>SAML- en groepsinstellingen</bullet-item><bullet-item>Reisgegevens en toegang tot Expensify Travel</bullet-item></bullet-list> Alle accounts, werkruimtes, rapporten, uitgaven en andere gegevens blijven behouden. <br/><br/>Opmerking: je kunt dit domein uit je domeinlijst verwijderen door het bijbehorende e-mailadres uit je <a href="#">contactmethoden</a> te verwijderen.`,
+            resetDomainInfo: `Deze actie is <strong>definitief</strong> en de volgende gegevens worden verwijderd: <br/> <ul><li>Bedrijfskaartverbindingen en alle niet-gerapporteerde uitgaven van die kaarten</li> <li>SAML- en groepsinstellingen</li> </ul> Alle accounts, werkruimten, rapporten, uitgaven en andere gegevens blijven behouden. <br/><br/>Opmerking: je kunt dit domein uit je domeinlijst verwijderen door het bijbehorende e-mailadres te verwijderen uit je <a href="#">contactmethoden</a>.`,
         },
         domainMembers: 'Domeinleden',
         members: {
             title: 'Leden',
             findMember: 'Lid zoeken',
             addMember: 'Lid toevoegen',
-            allMembers: 'Alle leden',
             email: 'E-mailadres',
-            closeAccount: () => ({
-                one: 'Account sluiten',
-                other: 'Accounts sluiten',
-            }),
+            closeAccount: 'Account sluiten',
             closeAccountPrompt: 'Weet je het zeker? Deze actie is permanent.',
-            forceCloseAccount: () => ({one: 'Account geforceerd sluiten', other: 'Accounts geforceerd sluiten'}),
-            safeCloseAccount: () => ({
-                one: 'Account veilig sluiten',
-                other: 'Accounts veilig sluiten',
-            }),
-            closeAccountInfo: () => ({
-                one: 'We raden aan om de account veilig te sluiten om te vermijden dat je deze moet sluiten als er zijn: <bullet-list><bullet-item>Openstaande goedkeuringen</bullet-item><bullet-item>Actieve terugbetalingen</bullet-item><bullet-item>Geen alternatieve inlogmethoden</bullet-item></bullet-list>Anders kun je de bovenstaande veiligheidsmaatregelen negeren en de geselecteerde account geforceerd sluiten.',
-                other: 'We raden aan om de accounts veilig te sluiten om te vermijden dat je deze moet sluiten als er zijn: <bullet-list><bullet-item>Openstaande goedkeuringen</bullet-item><bullet-item>Actieve terugbetalingen</bullet-item><bullet-item>Geen alternatieve inlogmethoden</bullet-item></bullet-list>Anders kun je de bovenstaande veiligheidsmaatregelen negeren en de geselecteerde accounts geforceerd sluiten.',
-            }),
+            forceCloseAccount: 'Account geforceerd sluiten',
+            safeCloseAccount: 'Account veilig sluiten',
+            closeAccountInfo:
+                'We raden aan om de account veilig te sluiten om te vermijden dat je deze moet sluiten als er zijn: <ul><li>Openstaande goedkeuringen</li><li>Actieve terugbetalingen</li><li>Geen alternatieve inlogmethoden</li></ul>Anders kun je de bovenstaande veiligheidsmaatregelen negeren en de geselecteerde account geforceerd sluiten.',
             error: {
                 removeMember: 'Kan deze gebruiker niet verwijderen. Probeer het opnieuw.',
                 addMember: 'Kan dit lid niet toevoegen. Probeer het opnieuw.',
-                vacationDelegate: 'Kan deze gebruiker niet als vakantiemandataris instellen. Probeer het opnieuw.',
-                moveMember: 'Kan dit lid niet verplaatsen. Probeer het opnieuw.',
-                moveMemberNotPolicyAdmin:
-                    'Kan het lid niet naar de domeingroep verplaatsen. U moet Beleidsbeheerder zijn voor het Voorkeursbeleid dat is ingesteld op de domeingroep waarnaar u deze gebruiker probeert te verplaatsen.',
-            },
-            cannotSetVacationDelegateForMember: (email: string) =>
-                `Je kunt geen vakantiemandataris instellen voor ${email} omdat die persoon momenteel gedelegeerde is voor de volgende leden:`,
-            reportSuspiciousActivityPrompt: (email: string) =>
-                `Weet je het zeker? Hiermee wordt het account van <strong>${email}</strong> vergrendeld. <br /><br /> Ons team zal het account vervolgens beoordelen en ongeautoriseerde toegang verwijderen. Om weer toegang te krijgen, moeten ze samenwerken met Concierge.`,
-            reportSuspiciousActivityConfirmationPrompt:
-                'We beoordelen de account om te verifiëren dat het veilig is om deze te ontgrendelen en nemen via Concierge contact op als we vragen hebben.',
-            emptyMembers: {title: 'Geen leden in deze groep', subtitle: 'Voeg een lid toe of probeer het filter hierboven te wijzigen.'},
-            moveToGroup: 'Verplaatsen naar groep',
-            chooseWhereToMove: ({count}: {count: number}) => `Kies waar je ${count} ${count === 1 ? 'lid' : 'leden'} naartoe wilt verplaatsen.`,
-            domainGroup: 'Domeingroep',
-            chooseWhereToMoveName: ({name}: {name: string}) => `Kies waar je ${name} naartoe wilt verplaatsen.`,
-            membersFeatureList: {
-                subtitle: ({domainName}: {domainName: string}) =>
-                    `<muted-text>Verifieer je domein voor meer controle over leden met <strong>${domainName}</strong> in Expensify.</muted-text>`,
-                controlPolicyCreation: 'Aanmaken van werkruimtes beperken',
-                enableSamlSso: 'SAML-SSO inschakelen',
-                enforce2FA: '2FA afdwingen',
             },
         },
-        common: {
-            settings: 'Instellingen',
-            forceTwoFactorAuth: 'Tweeledige verificatie afdwingen',
-            forceTwoFactorAuthSAMLEnabledDescription: (samlPageUrl: string) =>
-                `<muted-text>Schakel <a href="${samlPageUrl}">SAML</a> uit om het gebruik van twee-factor-authenticatie af te dwingen.</muted-text>`,
-            forceTwoFactorAuthDescription: `<muted-text>Tweeledige verificatie vereisen voor alle leden van dit domein. Domeinleden worden gevraagd om tweefactorauthenticatie voor hun account in te stellen wanneer ze zich aanmelden.</muted-text>`,
-            forceTwoFactorAuthError: 'Verplichte twee-factor-authenticatie kon niet worden gewijzigd. Probeer het later opnieuw.',
-            resetTwoFactorAuth: 'Tweeledige verificatie opnieuw instellen',
-            error: 'Deze wijziging kon niet worden opgeslagen. Probeer het opnieuw.',
-        },
-        groups: {
-            title: 'Groepen',
-            memberCount: () => ({one: '1 lid', other: (count: number) => `${count} leden`}),
-            defaultGroup: 'Standaardgroep voor nieuwe leden',
-            defaultGroupPrompt: (currentName: string, newName: string) =>
-                `Weet je zeker dat je ${newName} de standaardgroep wilt maken? Nieuwe leden worden uitgenodigd voor deze groep in plaats van de vorige standaardgroep (${currentName}). `,
-            makeDefault: 'Standaard maken',
-            neverMind: 'Laat maar',
-            createGroupError: 'Kan deze groep niet aanmaken. Probeer het opnieuw.',
-            permissions: 'Groepsmachtigingen',
-            createNewGroupButton: 'Nieuwe groep',
-            createGroupSubmitButton: 'Groep aanmaken',
-            expensifyCardPreferredWorkspace: 'Expensify Card voorkeurswerkruimte',
-            expensifyCardPreferredWorkspaceDescription: 'Alle Expensify Card-transacties worden aangemaakt in de Expensify Card-voorkeurswerkruimte in plaats van de voorkeurswerkruimte.',
-            strictlyEnforceWorkspaceRules: 'Werkruimteregels strikt afdwingen',
-            strictlyEnforceWorkspaceRulesDescription:
-                'Aan alle werkruimteregels moet worden voldaan voordat een rapport kan worden ingediend. Handmatige uitzonderingen zijn niet toegestaan.',
-            restrictExpenseWorkspaceCreation: 'Aanmaken/verwijderen van onkostenwerkruimte beperken',
-            restrictExpenseWorkspaceCreationDescription:
-                'Voorkom dat leden een onkostenwerkruimte kunnen aanmaken of zichzelf uit een onkostenwerkruimte kunnen verwijderen. Dit is nuttig om te voorkomen dat mensen Expensify gebruiken om rapporten in te dienen voor gebruik buiten jouw domein, wanneer dit wordt gecombineerd met strikte werkruimtehandhaving.',
-            deleteGroup: 'Groep verwijderen',
-            deleteGroupDangerConfirmationModal: 'Groep verwijderen',
-            deleteGroupDangerConfirmationModalDescription: (defaultGroupName: string) =>
-                `Weet je het zeker? Dit wijst alle leden opnieuw toe aan de standaardgroep (${defaultGroupName}) en kan niet ongedaan worden gemaakt.`,
-            deleteGroupError: 'Kan deze groep niet verwijderen. Probeer het opnieuw.',
-            preferredWorkspace: 'Voorkeurswerkruimte',
-            preferredWorkspaceDescription: (enabled: boolean) => `Alle nieuwe rapporten en uitgaven worden aangemaakt in ${enabled ? 'de geselecteerde voorkeurs' : 'deze'} werkruimte.`,
-            preferredWorkspaceSelectDescription: 'Alle nieuwe uitgaven en rapporten worden aangemaakt in deze werkruimte.',
-            noWorkspacesMessage: 'Er zijn geen werkruimtes op dit domein. Een werkruimte is vereist om deze beperking in te schakelen.',
-            restrictDefaultLoginSelection: 'Standaard login-selectie beperken',
-            restrictDefaultLoginSelectionDescription: 'Voorkomt dat leden hun login-e-mail wijzigen naar een adres buiten het bedrijfsdomein om beleidsbeperkingen te omzeilen.',
-            expensifyCardPreferredWorkspaceDisabledMessage: 'Om deze instelling in te schakelen, schakelt u eerst een voorkeurswerkruimte in en stelt u Expensify Cards in op uw domein.',
-            findGroup: 'Groep zoeken',
-        },
-    },
-    proactiveAppReview: {
-        title: 'Geniet je van de nieuwe Expensify?',
-        description: 'Laat het ons weten, zodat we je uitgavenervaring nog beter kunnen maken.',
-        positiveButton: 'Ja!',
-        negativeButton: 'Niet echt',
-    },
-    monthPickerPage: {month: 'Maand', selectMonth: 'Selecteer een maand'},
+    },
 };
 export default translations;
diff --git a/src/languages/params.ts b/src/languages/params.ts
index 41610783b027..cb8a8c17f9fc 100644
--- a/src/languages/params.ts
+++ b/src/languages/params.ts
@@ -1,8 +1,28 @@
+import type {ValueOf} from 'type-fest';
+import type {AuthTypeName} from '@libs/MultifactorAuthentication/Biometrics/types';
+import type CONST from '@src/CONST';
 import type {OnyxInputOrEntry, ReportAction} from '@src/types/onyx';
 import type {DelegateRole} from '@src/types/onyx/Account';
 import type {AllConnectionName, ConnectionName, PolicyConnectionSyncStage, SageIntacctMappingName} from '@src/types/onyx/Policy';
 import type {ViolationDataType} from '@src/types/onyx/TransactionViolation';
 
+type MultifactorAuthenticationTranslationParams = {
+    authType?: AuthTypeName;
+    registered?: boolean;
+};
+
+type ZipCodeExampleFormatParams = {
+    zipSampleFormat: string;
+};
+
+type SignUpNewFaceCodeParams = {
+    login: string;
+};
+
+type WelcomeEnterMagicCodeParams = {
+    login: string;
+};
+
 type EditActionParams = {
     action: OnyxInputOrEntry<ReportAction>;
 };
@@ -15,6 +35,18 @@ type DeleteConfirmationParams = {
     action: OnyxInputOrEntry<ReportAction>;
 };
 
+type BeginningOfChatHistoryAnnounceRoomPartTwo = {
+    workspaceName: string;
+};
+
+type WelcomeToRoomParams = {
+    roomName: string;
+};
+
+type UsePlusButtonParams = {
+    additionalText: string;
+};
+
 type ReportArchiveReasonsClosedParams = {
     displayName: string;
 };
@@ -24,40 +56,270 @@ type ReportArchiveReasonsMergedParams = {
     oldDisplayName: string;
 };
 
-type ReportArchiveReasonsInvoiceReceiverPolicyDeletedParams = {
-    policyName: string;
-};
-
 type ReportArchiveReasonsRemovedFromPolicyParams = {
     displayName: string;
     policyName: string;
     shouldUseYou?: boolean;
 };
 
+type ReportPolicyNameParams = {
+    policyName: string;
+};
+
+type ReportArchiveReasonsInvoiceReceiverPolicyDeletedParams = {
+    policyName: string;
+};
+
+type CreatedReportForUnapprovedTransactionsParams = {
+    reportUrl: string;
+    reportName: string;
+};
+
+type SettleExpensifyCardParams = {
+    formattedAmount: string;
+};
+
+type WorkspacesListRouteParams = {
+    workspacesListRoute: string;
+};
+
+type WorkspaceRouteParams = {
+    workspaceRoute: string;
+};
+
+type RequestAmountParams = {amount: string};
+
+type ReportFieldParams = {name: string; value: string};
+
+type SplitAmountParams = {amount: string};
+
+type UserSplitParams = {amount: string};
+
 type PaidElsewhereParams = {payer?: string; comment?: string};
 
-type MovedFromPersonalSpaceParams = {workspaceName?: string; reportName?: string};
+type WaitingOnBankAccountParams = {submitterDisplayName: string};
 
-type ResolutionConstraintsParams = {minHeightInPx: number; minWidthInPx: number; maxHeightInPx: number; maxWidthInPx: number};
+type SettledAfterAddedBankAccountParams = {submitterDisplayName: string; amount: string};
+
+type ThreadRequestReportNameParams = {formattedAmount: string; comment: string};
+
+type ThreadSentMoneyReportNameParams = {formattedAmount: string; comment: string};
+
+type MovedFromPersonalSpaceParams = {workspaceName?: string; reportName?: string};
 
 type SizeExceededParams = {maxUploadSizeInMB: number};
 
+type ResolutionConstraintsParams = {minHeightInPx: number; minWidthInPx: number; maxHeightInPx: number; maxWidthInPx: number};
+
 type NotAllowedExtensionParams = {allowedExtensions: string[]};
 
+type TransferParams = {amount: string};
+
+type WeSentYouMagicSignInLinkParams = {login: string; loginType: string};
+
+type ToValidateLoginParams = {primaryLogin: string; secondaryLogin: string};
+
+type UntilTimeParams = {time: string};
+
 type StepCounterParams = {step: number; total?: number; text?: string};
 
+type UserIsAlreadyMemberParams = {login: string; name: string};
+
+type RoomNameReservedErrorParams = {reservedName: string};
+
+type RoomRenamedToParams = {newName: string};
+
 type ParentNavigationSummaryParams = {reportName?: string; workspaceName?: string};
 
+type SetTheRequestParams = {valueName: string; newValueToDisplay: string};
+
+type SetTheDistanceMerchantParams = {translatedChangedField: string; newMerchant: string; newAmountToDisplay: string};
+
+type UpdatedTheRequestParams = {valueName: string; newValueToDisplay: string; oldValueToDisplay: string};
+
+type UpdatedTheDistanceMerchantParams = {translatedChangedField: string; newMerchant: string; oldMerchant: string; newAmountToDisplay: string; oldAmountToDisplay: string};
+
+type WalletProgramParams = {walletProgram: string};
+
+type ViolationsCashExpenseWithNoReceiptParams = {formattedLimit?: string} | undefined;
+
+type ViolationsConversionSurchargeParams = {surcharge: number};
+
+type ViolationsInvoiceMarkupParams = {invoiceMarkup: number};
+
+type ViolationsMaxAgeParams = {maxAge: number};
+
+type ViolationsMissingTagParams = {tagName?: string} | undefined;
+
 type ViolationsModifiedAmountParams = {type?: ViolationDataType; displayPercentVariance?: number};
 
-type ViolationsIncreasedDistanceParams = {formattedRouteDistance?: string};
+type ViolationsOverAutoApprovalLimitParams = {formattedLimit: string};
+
+type ViolationsOverCategoryLimitParams = {formattedLimit: string};
+
+type ViolationsOverLimitParams = {formattedLimit: string};
+
+type ViolationsPerDayLimitParams = {formattedLimit: string};
+
+type ViolationsReceiptRequiredParams = {formattedLimit?: string; category?: string};
+
+type ViolationsCustomRulesParams = {message: string};
+
+type ViolationsRterParams = {
+    brokenBankConnection: boolean;
+    isAdmin: boolean;
+    isTransactionOlderThan7Days: boolean;
+    member?: string;
+    rterType?: ValueOf<typeof CONST.RTER_VIOLATION_TYPES>;
+    companyCardPageURL?: string;
+};
+
+type ViolationsTagOutOfPolicyParams = {tagName?: string} | undefined;
+
+type ViolationsProhibitedExpenseParams = {prohibitedExpenseTypes: string | string[]};
+
+type ViolationsTaxOutOfPolicyParams = {taxName?: string} | undefined;
+
+type TaskCreatedActionParams = {title: string};
 
 type OptionalParam<T> = Partial<T>;
 
+type TermsParams = {amount: string};
+
+type LogSizeAndDateParams = {size: number; date: string};
+
+type HeldRequestParams = {comment: string};
+
 type ChangeFieldParams = {oldValue?: string; newValue: string; fieldName: string};
 
+type UpdatedPolicyDescriptionParams = {oldDescription: string; newDescription: string};
+
+type UpdatedPolicyCurrencyParams = {oldCurrency: string; newCurrency: string};
+
+type UpdatedPolicyCategoryParams = {categoryName: string; oldValue?: boolean | string | number; newValue?: boolean | string | number};
+
+type UpdatedPolicyCategoryDescriptionHintTypeParams = {categoryName: string; oldValue?: string; newValue?: string};
+
+type UpdatedPolicyCategoryGLCodeParams = {categoryName: string; oldValue?: string; newValue?: string};
+
+type UpdatedPolicyCategoryMaxExpenseAmountParams = {categoryName: string; oldAmount?: string; newAmount?: string};
+
+type UpdatedPolicyCategoryExpenseLimitTypeParams = {categoryName: string; oldValue?: string; newValue: string};
+
+type UpdatedPolicyCategoryMaxAmountNoReceiptParams = {categoryName: string; oldValue?: string; newValue: string};
+
+type UpdatedPolicyTaxParams = {taxName: string; oldValue?: string | boolean | number; newValue?: string | boolean | number; updatedField?: string};
+
+type UpdatedPolicyTagParams = {tagListName: string; tagName?: string; enabled?: boolean; count?: string};
+
+type UpdatedPolicyTagNameParams = {oldName: string; newName: string; tagListName: string};
+
+type UpdatedPolicyTagFieldParams = {oldValue?: string; newValue: string; tagName: string; tagListName: string; updatedField: string};
+
+type UpdatedPolicyCategoryNameParams = {oldName: string; newName?: string};
+
+type UpdatedPolicyTagListParams = {tagListName: string};
+
+type UpdatedPolicyTagListRequiredParams = {tagListsName: string; isRequired: boolean};
+
+type UpdatePolicyCustomUnitTaxEnabledParams = {newValue: boolean};
+
+type ImportPolicyCustomUnitRatesParams = {customUnitName: string};
+
+type UpdatePolicyCustomUnitDefaultCategoryParams = {customUnitName: string; newValue?: string; oldValue?: string};
+
+type UpdatePolicyCustomUnitParams = {oldValue: string; newValue: string; customUnitName: string; updatedField: string};
+
+type UpdatedPolicyCustomUnitRateParams = {customUnitName: string; customUnitRateName: string; oldValue: string; newValue: string; updatedField: string};
+
+type UpdatedPolicyCustomUnitTaxRateExternalIDParams = {customUnitRateName: string; newValue: string; newTaxPercentage: string; oldValue?: string; oldTaxPercentage?: string};
+
+type UpdatedPolicyCustomUnitTaxClaimablePercentageParams = {customUnitRateName: string; newValue: number; oldValue?: number};
+
+type UpdatedPolicyCustomUnitSubRateParams = {customUnitName: string; customUnitRateName: string; customUnitSubRateName: string; oldValue: string; newValue: string; updatedField: string};
+
+type RemovedPolicyCustomUnitSubRateParams = {customUnitName: string; customUnitRateName: string; removedSubRateName: string};
+
+type AddedOrDeletedPolicyReportFieldParams = {fieldType: string; fieldName?: string};
+
+type UpdatedPolicyCustomUnitRateEnabledParams = {customUnitName: string; customUnitRateName: string; oldValue: boolean; newValue: boolean};
+
+type UpdatedPolicyReportFieldDefaultValueParams = {fieldName?: string; defaultValue?: string};
+
+type UpdatedPolicyApprovalRuleParams = {oldApproverEmail: string; oldApproverName?: string; newApproverEmail: string; newApproverName?: string; field: string; name: string};
+
+type UpdatedPolicyPreventSelfApprovalParams = {oldValue: string; newValue: string};
+
+type UpdatedPolicyOwnershipParams = {oldOwnerEmail: string; oldOwnerName: string; policyName: string};
+
+type UpdatedPolicyFieldWithNewAndOldValueParams = {oldValue: string; newValue: string};
+
+type UpdatedPolicyTimeEnabledParams = {enabled?: boolean};
+
+type UpdatedPolicyTimeRateParams = {newRate?: string; oldRate?: string};
+
+type UpdatedPolicyAutoHarvestingParams = {enabled: boolean};
+
+type UpdatedPolicyBudgetNotificationParams = {
+    budgetAmount: string;
+    budgetFrequency: string;
+    budgetName: string;
+    budgetTypeForNotificationMessage: string;
+    summaryLink?: string;
+    thresholdPercentage: number;
+    totalSpend: number;
+    unsubmittedSpend: number;
+    userEmail?: string;
+    awaitingApprovalSpend: number;
+    approvedReimbursedClosedSpend: number;
+};
+
+type UpdatedPolicyReimbursementChoiceParams = {newReimbursementChoice: string; oldReimbursementChoice: string};
+
+type UpdatedPolicyDefaultTitleParams = {newDefaultTitle: string; oldDefaultTitle: string};
+
+type UpdatedPolicyFieldWithValueParams = {value: boolean};
+
+type UpdatedPolicySetAutoJoinParams = {enabled: boolean};
+
+type UpdatedPolicyFrequencyParams = {oldFrequency: string; newFrequency: string};
+
+type UpdatedPolicyAuditRateParams = {oldAuditRate: number; newAuditRate: number};
+
+type UpdatedPolicyManualApprovalThresholdParams = {oldLimit: string; newLimit: string};
+
+type UpdatedPolicyReimbursementEnabledParams = {enabled: boolean};
+
+type UpdatedPolicyReimburserParams = {newReimburser: string; previousReimburser?: string};
+
 type ExportedToIntegrationParams = {label: string; markedManually?: boolean; inProgress?: boolean; lastModified?: string};
 
+type AddBudgetParams = {frequency: string; entityType: string; entityName: string; shared?: string; individual?: string; notificationThreshold?: number};
+
+type AddOrDeletePolicyCustomUnitRateParams = {customUnitName: string; rateName: string};
+
+type UpdatedBudgetParams = {
+    entityType: string;
+    entityName: string;
+    oldFrequency?: string;
+    newFrequency?: string;
+    oldIndividual?: string;
+    newIndividual?: string;
+    oldShared?: string;
+    newShared?: string;
+    oldNotificationThreshold?: number;
+    newNotificationThreshold?: number;
+};
+
+type DeleteBudgetParams = {
+    entityType: string;
+    entityName: string;
+    frequency?: string;
+    individual?: string;
+    shared?: string;
+    notificationThreshold?: number;
+};
+
 type IntegrationsMessageParams = {
     label: string;
     result: {
@@ -75,12 +337,10 @@ type MarkReimbursedFromIntegrationParams = {amount: string; currency: string};
 
 type ShareParams = {to: string};
 
-type UnsupportedFormulaValueErrorParams = {
-    value: string;
-};
-
 type UnshareParams = {to: string};
 
+type StripePaidParams = {amount: string; currency: string};
+
 type ConnectionNameParams = {
     connectionName: AllConnectionName;
 };
@@ -92,16 +352,68 @@ type ExportAgainModalDescriptionParams = {
 
 type UpdateRoleParams = {email: string; currentRole: string; newRole: string};
 
+type UpdatedCustomFieldParams = {email: string; previousValue: string; newValue: string};
+
+type RemoveMemberParams = {email: string; role: string};
+
+type StatementPageTitleParams = {year: string | number; monthName: string};
+
+type DisconnectPromptParams = {currentIntegration?: ConnectionName} | undefined;
+
+type DisconnectTitleParams = {integration?: ConnectionName} | undefined;
+
+type AmountWithCurrencyParams = {amountWithCurrency: string};
+
+type LowerUpperParams = {lower: string; upper: string};
+
+type UpdatedPolicyCategoriesParams = {count: number};
+
+type TaxAmountParams = {taxAmount: number};
+
+type SecondaryLoginParams = {secondaryLogin: string};
+
+type WorkspaceMembersCountParams = {count: number};
+
+type WorkspaceOwnerWillNeedToAddOrUpdatePaymentCardParams = {workspaceOwnerName: string};
+
+type StatementTitleParams = {year: number | string; monthName: string};
+
+type TrialStartedTitleParams = {numOfDays: number};
+
 type YourPlanPriceParams = {lower: string; upper: string};
 
+type YourPlanPriceValueParams = {price: string};
+
+type SubscriptionSizeParams = {size: number};
+
+type SubscriptionCommitmentParams = {size: number; date: string};
+
+type SubscriptionSettingsSaveUpToParams = {amountWithCurrency: string};
+
+type SubscriptionSettingsSummaryParams = {subscriptionType: string; subscriptionSize: string; autoRenew: string; autoIncrease: string};
+
+type SubscriptionSettingsRenewsOnParams = {date: string};
+
+type SubscriptionSettingsLearnMoreParams = {hasAdminsRoom: boolean};
+
+type UnapproveWithIntegrationWarningParams = {accountingIntegration: string};
+
 type ExportIntegrationSelectedParams = {connectionName: ConnectionName};
 
+type RequiredFieldParams = {fieldName: string};
+
 type IntacctMappingTitleParams = {mappingName: SageIntacctMappingName};
 
 type SyncStageNameConnectionsParams = {stage: PolicyConnectionSyncStage};
 
 type DelegateRoleParams = {role: DelegateRole};
 
+type VacationDelegateParams = {nameOrEmail: string};
+
+type SubmittedToVacationDelegateParams = {submittedToName: string; vacationDelegateName: string};
+
+type RoleNamesParams = {role: string};
+
 type RemovedFromApprovalWorkflowParams = {
     submittersNames: string[];
 };
@@ -119,53 +431,313 @@ type InvalidValueParams = {
     expectedValues: string;
 };
 
+type WorkspaceYouMayJoin = {
+    domain: string;
+    email: string;
+};
+
+type WorkEmailResendCodeParams = {
+    workEmail: string | undefined;
+};
+
+type WorkEmailMergingBlockedParams = {
+    workEmail: string | undefined;
+};
+
+type WorkspaceMemberList = {
+    employeeCount: number;
+    policyOwner: string;
+};
+
 type WorkspaceLockedPlanTypeParams = {
     count: number;
     annualSubscriptionEndDate: string;
 };
 
-type ConciergeBrokenCardConnectionParams = {
-    cardName: string;
-    connectionLink?: string;
+type SignerInfoMessageParams = {
+    bankAccountLastFour: string | undefined;
+    currency: string | undefined;
+};
+
+type CustomUnitRateParams = {
+    rate: number;
+};
+
+type SubmitsToParams = {
+    name: string;
+};
+
+type SettlementDateParams = {
+    settlementDate: string;
+};
+
+type ReviewParams = {
+    amount: string;
+};
+
+type SplitExpenseSubtitleParams = {
+    amount: string;
+    merchant: string;
+};
+
+type SplitExpenseEditTitleParams = {
+    amount: string;
+    merchant: string;
+};
+
+type SplitDateRangeParams = {
+    startDate: string;
+    endDate: string;
+    count: number;
+};
+
+type TotalAmountGreaterOrLessThanOriginalParams = {
+    amount: string;
+};
+
+type TravelTypeParams = {
+    type: string;
+    id?: string;
+};
+
+type SettlementAccountInfoParams = {
+    reconciliationAccountSettingsLink: string;
+    accountNumber: string;
+};
+
+type WorkspaceUpgradeNoteParams = {
+    subscriptionLink: string;
+};
+
+type WorkflowSettingsParam = {workflowSettingLink: string};
+
+type WorkspaceShareNoteParams = {
+    adminsRoomLink: string;
+};
+
+type RulesEnableWorkflowsParams = {
+    moreFeaturesLink: string;
+};
+
+type UpgradeSuccessMessageParams = {
+    policyName: string;
+    subscriptionLink: string;
+};
+
+type SubmittedWithMemoParams = {
+    memo?: string;
+};
+
+type WalletAgreementParams = {
+    walletAgreementUrl: string;
+};
+
+type SettlementAccountReconciliationParams = {
+    settlementAccountUrl: string;
+    lastFourPAN: string;
+};
+
+type NextStepParams = {
+    actor: string;
+    actorType: ValueOf<typeof CONST.NEXT_STEP.ACTOR_TYPE>;
+    eta?: string;
+    etaType?: ValueOf<typeof CONST.NEXT_STEP.ETA_TYPE>;
+};
+
+type ToggleImportTitleParams = {
+    mappingTitle: string;
+};
+
+type RoutedDueToDEWParams = {
+    to: string;
 };
 
 export type {
+    SettlementAccountReconciliationParams,
+    ToggleImportTitleParams,
+    SplitExpenseEditTitleParams,
+    SplitExpenseSubtitleParams,
+    SplitDateRangeParams,
+    TotalAmountGreaterOrLessThanOriginalParams,
     MissingPropertyParams,
     InvalidPropertyParams,
     InvalidValueParams,
     RemovedFromApprovalWorkflowParams,
     DelegateRoleParams,
+    VacationDelegateParams,
     SyncStageNameConnectionsParams,
+    RequiredFieldParams,
     IntacctMappingTitleParams,
     ExportIntegrationSelectedParams,
+    UnapproveWithIntegrationWarningParams,
     YourPlanPriceParams,
+    SubscriptionSizeParams,
+    SubscriptionCommitmentParams,
+    SubscriptionSettingsSaveUpToParams,
+    SubscriptionSettingsRenewsOnParams,
+    TrialStartedTitleParams,
+    StatementTitleParams,
+    WorkspaceOwnerWillNeedToAddOrUpdatePaymentCardParams,
+    SecondaryLoginParams,
+    TaxAmountParams,
+    UpdatedPolicyCategoriesParams,
+    AmountWithCurrencyParams,
+    LowerUpperParams,
+    LogSizeAndDateParams,
+    BeginningOfChatHistoryAnnounceRoomPartTwo,
     DeleteActionParams,
     DeleteConfirmationParams,
     EditActionParams,
     MovedFromPersonalSpaceParams,
+    SubmittedToVacationDelegateParams,
+    HeldRequestParams,
+    SignUpNewFaceCodeParams,
     NotAllowedExtensionParams,
     ParentNavigationSummaryParams,
+    RoleNamesParams,
     PaidElsewhereParams,
-    ConciergeBrokenCardConnectionParams,
     ReportArchiveReasonsClosedParams,
     ReportArchiveReasonsMergedParams,
+    ReportPolicyNameParams,
     ReportArchiveReasonsInvoiceReceiverPolicyDeletedParams,
+    CreatedReportForUnapprovedTransactionsParams,
     ReportArchiveReasonsRemovedFromPolicyParams,
+    RequestAmountParams,
     ResolutionConstraintsParams,
+    RoomNameReservedErrorParams,
+    RoomRenamedToParams,
+    SetTheDistanceMerchantParams,
+    SetTheRequestParams,
+    SettleExpensifyCardParams,
+    SettledAfterAddedBankAccountParams,
     SizeExceededParams,
+    SplitAmountParams,
     StepCounterParams,
+    TaskCreatedActionParams,
+    TermsParams,
+    ThreadRequestReportNameParams,
+    ThreadSentMoneyReportNameParams,
+    ToValidateLoginParams,
+    TransferParams,
+    UntilTimeParams,
+    UpdatedTheDistanceMerchantParams,
+    UpdatedTheRequestParams,
+    UsePlusButtonParams,
+    UserIsAlreadyMemberParams,
+    UserSplitParams,
+    ViolationsCashExpenseWithNoReceiptParams,
+    ViolationsConversionSurchargeParams,
+    ViolationsInvoiceMarkupParams,
+    ViolationsMaxAgeParams,
+    ViolationsMissingTagParams,
     ViolationsModifiedAmountParams,
-    ViolationsIncreasedDistanceParams,
+    ViolationsOverAutoApprovalLimitParams,
+    ViolationsOverCategoryLimitParams,
+    ViolationsOverLimitParams,
+    ViolationsPerDayLimitParams,
+    ViolationsReceiptRequiredParams,
+    ViolationsCustomRulesParams,
+    ViolationsRterParams,
+    ViolationsTagOutOfPolicyParams,
+    ViolationsProhibitedExpenseParams,
+    ViolationsTaxOutOfPolicyParams,
+    WaitingOnBankAccountParams,
+    WalletProgramParams,
+    WeSentYouMagicSignInLinkParams,
+    WelcomeEnterMagicCodeParams,
+    WelcomeToRoomParams,
+    ZipCodeExampleFormatParams,
     ChangeFieldParams,
     ExportedToIntegrationParams,
     IntegrationsMessageParams,
     MarkReimbursedFromIntegrationParams,
     ShareParams,
+    UpdatedPolicyFieldWithValueParams,
     UnshareParams,
-    UnsupportedFormulaValueErrorParams,
+    StripePaidParams,
     ConnectionNameParams,
     ExportAgainModalDescriptionParams,
     UpdateRoleParams,
+    UpdatedCustomFieldParams,
+    RemoveMemberParams,
+    StatementPageTitleParams,
+    DisconnectPromptParams,
+    DisconnectTitleParams,
     OptionalParam,
+    WorkspaceYouMayJoin,
+    WorkspaceMemberList,
     WorkspaceLockedPlanTypeParams,
+    CustomUnitRateParams,
+    UpdatedPolicyCurrencyParams,
+    UpdatedPolicyFrequencyParams,
+    UpdatedPolicyCategoryParams,
+    UpdatedPolicyCategoryDescriptionHintTypeParams,
+    UpdatedPolicyCategoryNameParams,
+    UpdatedPolicyTagListParams,
+    UpdatedPolicyTagListRequiredParams,
+    UpdatedPolicyPreventSelfApprovalParams,
+    UpdatedPolicyFieldWithNewAndOldValueParams,
+    UpdatedPolicyTimeEnabledParams,
+    UpdatedPolicyTimeRateParams,
+    UpdatedPolicyDescriptionParams,
+    WorkEmailResendCodeParams,
+    WorkEmailMergingBlockedParams,
+    UpdatedPolicyCustomUnitRateParams,
+    UpdatedPolicyCustomUnitTaxRateExternalIDParams,
+    UpdatedPolicyCustomUnitTaxClaimablePercentageParams,
+    UpdatedPolicyTagParams,
+    UpdatedPolicyTaxParams,
+    UpdatedPolicyTagNameParams,
+    UpdatedPolicyTagFieldParams,
+    UpdatedPolicyReportFieldDefaultValueParams,
+    SubmitsToParams,
+    SettlementDateParams,
+    RemovedPolicyCustomUnitSubRateParams,
+    UpdatedPolicyCustomUnitSubRateParams,
+    YourPlanPriceValueParams,
+    AddedOrDeletedPolicyReportFieldParams,
+    UpdatedPolicyAuditRateParams,
+    UpdatedPolicyManualApprovalThresholdParams,
+    UpdatedPolicyReimbursementEnabledParams,
+    UpdatedPolicyReimburserParams,
+    UpdatePolicyCustomUnitTaxEnabledParams,
+    ImportPolicyCustomUnitRatesParams,
+    UpdatePolicyCustomUnitDefaultCategoryParams,
+    UpdatePolicyCustomUnitParams,
+    UpdatedPolicyApprovalRuleParams,
+    UpdatedPolicyCategoryGLCodeParams,
+    UpdatedPolicyCategoryMaxExpenseAmountParams,
+    UpdatedPolicyCategoryExpenseLimitTypeParams,
+    UpdatedPolicyCategoryMaxAmountNoReceiptParams,
+    SubscriptionSettingsSummaryParams,
+    ReviewParams,
+    WorkspaceMembersCountParams,
+    TravelTypeParams,
+    WorkspacesListRouteParams,
+    WorkspaceRouteParams,
+    AddBudgetParams,
+    UpdatedBudgetParams,
+    DeleteBudgetParams,
+    AddOrDeletePolicyCustomUnitRateParams,
+    SettlementAccountInfoParams,
+    WorkspaceUpgradeNoteParams,
+    WorkflowSettingsParam,
+    WorkspaceShareNoteParams,
+    RulesEnableWorkflowsParams,
+    UpgradeSuccessMessageParams,
+    SubmittedWithMemoParams,
+    SignerInfoMessageParams,
+    WalletAgreementParams,
+    SubscriptionSettingsLearnMoreParams,
+    NextStepParams,
+    ReportFieldParams,
+    UpdatedPolicyOwnershipParams,
+    UpdatedPolicyAutoHarvestingParams,
+    UpdatedPolicyBudgetNotificationParams,
+    UpdatedPolicyReimbursementChoiceParams,
+    UpdatedPolicyDefaultTitleParams,
+    UpdatedPolicySetAutoJoinParams,
+    RoutedDueToDEWParams,
+    UpdatedPolicyCustomUnitRateEnabledParams,
+    MultifactorAuthenticationTranslationParams,
 };
diff --git a/src/languages/pl.ts b/src/languages/pl.ts
index e3ddbc27dc9a..96f4d6b655e9 100644
--- a/src/languages/pl.ts
+++ b/src/languages/pl.ts
@@ -11,52 +11,189 @@
  */
 import {CONST as COMMON_CONST} from 'expensify-common';
 import startCase from 'lodash/startCase';
-import type {ValueOf} from 'type-fest';
 import type {OnboardingTask} from '@libs/actions/Welcome/OnboardingFlow';
 import StringUtils from '@libs/StringUtils';
 import dedent from '@libs/StringUtils/dedent';
 import CONST from '@src/CONST';
 import type {Country} from '@src/CONST';
 import type OriginalMessage from '@src/types/onyx/OriginalMessage';
-import type {OriginalMessageSettlementAccountLocked, PersonalRulesModifiedFields, PolicyRulesModifiedFields} from '@src/types/onyx/OriginalMessage';
+import type {OriginalMessageSettlementAccountLocked, PolicyRulesModifiedFields} from '@src/types/onyx/OriginalMessage';
+import ObjectUtils from '@src/types/utils/ObjectUtils';
 import type en from './en';
 import type {
+    AddBudgetParams,
+    AddedOrDeletedPolicyReportFieldParams,
+    AddOrDeletePolicyCustomUnitRateParams,
     ChangeFieldParams,
-    ConciergeBrokenCardConnectionParams,
     ConnectionNameParams,
+    CreatedReportForUnapprovedTransactionsParams,
     DelegateRoleParams,
     DeleteActionParams,
+    DeleteBudgetParams,
     DeleteConfirmationParams,
     EditActionParams,
     ExportAgainModalDescriptionParams,
     ExportIntegrationSelectedParams,
+    ImportPolicyCustomUnitRatesParams,
     IntacctMappingTitleParams,
     InvalidPropertyParams,
     InvalidValueParams,
     MarkReimbursedFromIntegrationParams,
     MissingPropertyParams,
     MovedFromPersonalSpaceParams,
+    MultifactorAuthenticationTranslationParams,
+    NextStepParams,
     NotAllowedExtensionParams,
     OptionalParam,
     PaidElsewhereParams,
     ParentNavigationSummaryParams,
     RemovedFromApprovalWorkflowParams,
+    RemovedPolicyCustomUnitSubRateParams,
     ReportArchiveReasonsClosedParams,
     ReportArchiveReasonsInvoiceReceiverPolicyDeletedParams,
     ReportArchiveReasonsMergedParams,
     ReportArchiveReasonsRemovedFromPolicyParams,
+    ReportFieldParams,
+    ReportPolicyNameParams,
+    RequestAmountParams,
+    RequiredFieldParams,
     ResolutionConstraintsParams,
+    ReviewParams,
+    RoleNamesParams,
+    RoomNameReservedErrorParams,
+    RoomRenamedToParams,
+    RoutedDueToDEWParams,
+    RulesEnableWorkflowsParams,
+    SecondaryLoginParams,
+    SetTheDistanceMerchantParams,
+    SetTheRequestParams,
+    SettledAfterAddedBankAccountParams,
+    SettleExpensifyCardParams,
+    SettlementAccountInfoParams,
+    SettlementAccountReconciliationParams,
+    SettlementDateParams,
     ShareParams,
+    SignerInfoMessageParams,
+    SignUpNewFaceCodeParams,
     SizeExceededParams,
+    SplitAmountParams,
+    SplitDateRangeParams,
+    SplitExpenseEditTitleParams,
+    SplitExpenseSubtitleParams,
+    StatementTitleParams,
     StepCounterParams,
+    StripePaidParams,
+    SubmitsToParams,
+    SubmittedToVacationDelegateParams,
+    SubmittedWithMemoParams,
+    SubscriptionCommitmentParams,
+    SubscriptionSettingsLearnMoreParams,
+    SubscriptionSettingsRenewsOnParams,
+    SubscriptionSettingsSaveUpToParams,
+    SubscriptionSettingsSummaryParams,
+    SubscriptionSizeParams,
     SyncStageNameConnectionsParams,
+    TaskCreatedActionParams,
+    TaxAmountParams,
+    TermsParams,
+    ThreadRequestReportNameParams,
+    ThreadSentMoneyReportNameParams,
+    ToggleImportTitleParams,
+    TotalAmountGreaterOrLessThanOriginalParams,
+    ToValidateLoginParams,
+    TransferParams,
+    TravelTypeParams,
+    TrialStartedTitleParams,
+    UnapproveWithIntegrationWarningParams,
     UnshareParams,
-    UnsupportedFormulaValueErrorParams,
+    UntilTimeParams,
+    UpdatedBudgetParams,
+    UpdatedCustomFieldParams,
+    UpdatedPolicyApprovalRuleParams,
+    UpdatedPolicyAuditRateParams,
+    UpdatedPolicyAutoHarvestingParams,
+    UpdatedPolicyBudgetNotificationParams,
+    UpdatedPolicyCategoriesParams,
+    UpdatedPolicyCategoryDescriptionHintTypeParams,
+    UpdatedPolicyCategoryExpenseLimitTypeParams,
+    UpdatedPolicyCategoryGLCodeParams,
+    UpdatedPolicyCategoryMaxAmountNoReceiptParams,
+    UpdatedPolicyCategoryMaxExpenseAmountParams,
+    UpdatedPolicyCategoryNameParams,
+    UpdatedPolicyCategoryParams,
+    UpdatedPolicyCurrencyParams,
+    UpdatedPolicyCustomUnitRateEnabledParams,
+    UpdatedPolicyCustomUnitRateParams,
+    UpdatedPolicyCustomUnitSubRateParams,
+    UpdatedPolicyCustomUnitTaxClaimablePercentageParams,
+    UpdatedPolicyCustomUnitTaxRateExternalIDParams,
+    UpdatedPolicyDefaultTitleParams,
+    UpdatedPolicyDescriptionParams,
+    UpdatedPolicyFieldWithNewAndOldValueParams,
+    UpdatedPolicyFieldWithValueParams,
+    UpdatedPolicyFrequencyParams,
+    UpdatedPolicyManualApprovalThresholdParams,
+    UpdatedPolicyOwnershipParams,
+    UpdatedPolicyPreventSelfApprovalParams,
+    UpdatedPolicyReimbursementChoiceParams,
+    UpdatedPolicyReimbursementEnabledParams,
+    UpdatedPolicyReimburserParams,
+    UpdatedPolicyReportFieldDefaultValueParams,
+    UpdatedPolicyTagFieldParams,
+    UpdatedPolicyTagListParams,
+    UpdatedPolicyTagListRequiredParams,
+    UpdatedPolicyTagNameParams,
+    UpdatedPolicyTagParams,
+    UpdatedPolicyTaxParams,
+    UpdatedPolicyTimeEnabledParams,
+    UpdatedPolicyTimeRateParams,
+    UpdatedTheDistanceMerchantParams,
+    UpdatedTheRequestParams,
+    UpdatePolicyCustomUnitDefaultCategoryParams,
+    UpdatePolicyCustomUnitParams,
+    UpdatePolicyCustomUnitTaxEnabledParams,
     UpdateRoleParams,
-    ViolationsIncreasedDistanceParams,
+    UpgradeSuccessMessageParams,
+    UsePlusButtonParams,
+    UserIsAlreadyMemberParams,
+    UserSplitParams,
+    VacationDelegateParams,
+    ViolationsCashExpenseWithNoReceiptParams,
+    ViolationsConversionSurchargeParams,
+    ViolationsCustomRulesParams,
+    ViolationsInvoiceMarkupParams,
+    ViolationsMaxAgeParams,
+    ViolationsMissingTagParams,
     ViolationsModifiedAmountParams,
+    ViolationsOverCategoryLimitParams,
+    ViolationsOverLimitParams,
+    ViolationsPerDayLimitParams,
+    ViolationsProhibitedExpenseParams,
+    ViolationsReceiptRequiredParams,
+    ViolationsRterParams,
+    ViolationsTagOutOfPolicyParams,
+    ViolationsTaxOutOfPolicyParams,
+    WaitingOnBankAccountParams,
+    WalletAgreementParams,
+    WalletProgramParams,
+    WelcomeEnterMagicCodeParams,
+    WelcomeToRoomParams,
+    WeSentYouMagicSignInLinkParams,
+    WorkEmailMergingBlockedParams,
+    WorkEmailResendCodeParams,
+    WorkflowSettingsParam,
     WorkspaceLockedPlanTypeParams,
+    WorkspaceMemberList,
+    WorkspaceMembersCountParams,
+    WorkspaceOwnerWillNeedToAddOrUpdatePaymentCardParams,
+    WorkspaceRouteParams,
+    WorkspaceShareNoteParams,
+    WorkspacesListRouteParams,
+    WorkspaceUpgradeNoteParams,
+    WorkspaceYouMayJoin,
     YourPlanPriceParams,
+    YourPlanPriceValueParams,
+    ZipCodeExampleFormatParams,
 } from './params';
 import type {TranslationDeepObject} from './types';
 
@@ -90,10 +227,8 @@ const translations: TranslationDeepObject<typeof en> = {
         optional: 'Opcjonalne',
         new: 'Nowy',
         newFeature: 'Nowa funkcja',
-        beta: 'Beta',
         search: 'Szukaj',
         reports: 'Raporty',
-        spend: 'Wydatki',
         find: 'Znajdź',
         searchWithThreeDots: 'Szukaj...',
         next: 'Dalej',
@@ -118,14 +253,6 @@ const translations: TranslationDeepObject<typeof en> = {
         workspaces: 'Przestrzenie robocze',
         home: 'Strona główna',
         inbox: 'Skrzynka odbiorcza',
-        yourReviewIsRequired: 'Wymagana jest Twoja weryfikacja',
-        actionBadge: {
-            submit: 'Wyślij',
-            approve: 'Zatwierdź',
-            pay: 'Zapłać',
-            fix: 'Napraw',
-            task: 'Zadanie',
-        },
         success: 'Sukces',
         group: 'Grupa',
         profile: 'Profil',
@@ -135,7 +262,7 @@ const translations: TranslationDeepObject<typeof en> = {
         wallet: 'Portfel',
         preferences: 'Preferencje',
         view: 'Pokaż',
-        review: (amount?: string) => `Przejrzyj${amount ? ` ${amount}` : ''}`,
+        review: (reviewParams?: ReviewParams) => `Przejrzyj${reviewParams?.amount ? ` ${reviewParams?.amount}` : ''}`,
         not: 'Nie',
         signIn: 'Zaloguj się',
         signInWithGoogle: 'Zaloguj się przez Google',
@@ -146,7 +273,6 @@ const translations: TranslationDeepObject<typeof en> = {
         lastName: 'Nazwisko',
         scanning: 'Skanowanie',
         analyzing: 'Trwa analizowanie...',
-        thinking: 'Concierge myśli...',
         addCardTermsOfService: 'Regulamin Expensify',
         perPerson: 'na osobę',
         phone: 'Telefon',
@@ -208,12 +334,10 @@ const translations: TranslationDeepObject<typeof en> = {
         admin: 'Administrator',
         owner: 'Właściciel',
         dateFormat: 'YYYY-MM-DD',
-        calendarOpened: 'kalendarz otwarty',
         send: 'Wyślij',
         na: 'ND dotyczy',
         noResultsFound: 'Nie znaleziono wyników',
         noResultsFoundMatching: (searchString: string) => `Nie znaleziono wyników pasujących do „${searchString}”`,
-        suggestionsAvailableFor: (searchString: string) => (searchString ? `Dostępne sugestie dla „${searchString}”.` : 'Dostępne sugestie.'),
         recentDestinations: 'Ostatnie miejsca docelowe',
         timePrefix: 'To jest',
         conjunctionFor: 'dla',
@@ -224,7 +348,6 @@ const translations: TranslationDeepObject<typeof en> = {
         conjunctionTo: 'do',
         genericErrorMessage: 'Ups... coś poszło nie tak i Twoje żądanie nie mogło zostać zrealizowane. Spróbuj ponownie później.',
         percentage: 'Procent',
-        progressBarLabel: 'Postęp wdrożenia',
         converted: 'Przekonwertowano',
         error: {
             invalidAmount: 'Nieprawidłowa kwota',
@@ -263,7 +386,6 @@ const translations: TranslationDeepObject<typeof en> = {
         reset: 'Reset',
         done: 'Gotowe',
         more: 'Więcej',
-        other: 'Inne',
         debitCard: 'Karta debetowa',
         bankAccount: 'Konto bankowe',
         personalBankAccount: 'Prywatne konto bankowe',
@@ -289,7 +411,7 @@ const translations: TranslationDeepObject<typeof en> = {
         verify: 'Zweryfikuj',
         yesContinue: 'Tak, kontynuuj',
         websiteExample: 'np. https://www.expensify.com',
-        zipCodeExampleFormat: (zipSampleFormat: string) => (zipSampleFormat ? `np. ${zipSampleFormat}` : ''),
+        zipCodeExampleFormat: ({zipSampleFormat}: ZipCodeExampleFormatParams) => (zipSampleFormat ? `np. ${zipSampleFormat}` : ''),
         description: 'Opis',
         title: 'Tytuł',
         assignee: 'Osoba przypisana',
@@ -300,8 +422,6 @@ const translations: TranslationDeepObject<typeof en> = {
         per: 'na',
         mi: 'mila',
         km: 'kilometr',
-        milesAbbreviated: 'mi',
-        kilometersAbbreviated: 'km',
         copied: 'Skopiowano!',
         someone: 'Ktoś',
         total: 'Suma',
@@ -310,7 +430,6 @@ const translations: TranslationDeepObject<typeof en> = {
         letsStart: `Zacznijmy`,
         showMore: 'Pokaż więcej',
         showLess: 'Pokaż mniej',
-        plusMore: ({count}: {count: number}) => `+${count} więcej`,
         merchant: 'Sprzedawca',
         change: 'Zmień',
         category: 'Kategoria',
@@ -334,11 +453,8 @@ const translations: TranslationDeepObject<typeof en> = {
         selectCurrency: 'Wybierz walutę',
         selectSymbolOrCurrency: 'Wybierz symbol lub walutę',
         card: 'Karta',
-        mcc: 'MCC',
-        categoryGLCode: 'Kod księgi głównej kategorii',
         whyDoWeAskForThis: 'Dlaczego o to prosimy?',
         required: 'Wymagane',
-        automatic: 'Automatyczny',
         showing: 'Wyświetlanie',
         of: 'z',
         default: 'Domyślne',
@@ -346,7 +462,6 @@ const translations: TranslationDeepObject<typeof en> = {
         member: 'Członek',
         auditor: 'Audytor',
         role: 'Rola',
-        roleCannotBeChanged: (workflowsLinkPage: string) => `Nie można zmienić roli, ponieważ ten członek jest <a href="${workflowsLinkPage}">płatnikiem</a> w tym obszarze roboczym.`,
         currency: 'Waluta',
         groupCurrency: 'Waluta grupy',
         rate: 'Oceń',
@@ -384,7 +499,6 @@ const translations: TranslationDeepObject<typeof en> = {
         reportID: 'ID raportu',
         longReportID: 'Długi identyfikator raportu',
         withdrawalID: 'Identyfikator wypłaty',
-        withdrawalStatus: 'Status wypłaty',
         bankAccounts: 'Konta bankowe',
         chooseFile: 'Wybierz plik',
         chooseFiles: 'Wybierz pliki',
@@ -418,21 +532,19 @@ const translations: TranslationDeepObject<typeof en> = {
         validate: 'Zatwierdź',
         downloadAsPDF: 'Pobierz jako PDF',
         downloadAsCSV: 'Pobierz jako CSV',
-        print: 'Drukuj',
         help: 'Pomoc',
-        collapsed: 'Zwinięte',
-        expanded: 'Rozwinięte',
         expenseReport: 'Raport wydatków',
+        expenseReports: 'Raporty wydatków',
         rateOutOfPolicy: 'Stawka poza zasadami',
         leaveWorkspace: 'Opuść przestrzeń roboczą',
         leaveWorkspaceConfirmation: 'Jeśli opuścisz ten obszar roboczy, nie będziesz mógł przesyłać do niego wydatków.',
         leaveWorkspaceConfirmationAuditor: 'Jeśli opuścisz tę przestrzeń roboczą, nie będziesz mieć dostępu do jej raportów ani ustawień.',
         leaveWorkspaceConfirmationAdmin: 'Jeśli opuścisz tę przestrzeń roboczą, nie będziesz mógł zarządzać jej ustawieniami.',
-        leaveWorkspaceConfirmationApprover: (workspaceOwner: string) =>
+        leaveWorkspaceConfirmationApprover: ({workspaceOwner}: {workspaceOwner: string}) =>
             `Jeśli opuścisz tę przestrzeń roboczą, w ścieżce zatwierdzania zastąpi Cię ${workspaceOwner}, właściciel przestrzeni roboczej.`,
-        leaveWorkspaceConfirmationExporter: (workspaceOwner: string) =>
+        leaveWorkspaceConfirmationExporter: ({workspaceOwner}: {workspaceOwner: string}) =>
             `Jeśli opuścisz tę przestrzeń roboczą, zostaniesz zastąpiony jako preferowany eksporter przez ${workspaceOwner}, właściciela przestrzeni roboczej.`,
-        leaveWorkspaceConfirmationTechContact: (workspaceOwner: string) =>
+        leaveWorkspaceConfirmationTechContact: ({workspaceOwner}: {workspaceOwner: string}) =>
             `Jeśli opuścisz tę przestrzeń roboczą, zostaniesz zastąpiony jako kontakt techniczny przez ${workspaceOwner}, właściciela przestrzeni roboczej.`,
         leaveWorkspaceReimburser:
             'Nie możesz opuścić tej przestrzeni roboczej jako osoba rozliczająca wydatki. Ustaw nową osobę rozliczającą w Przestrzenie robocze > Dokonuj lub śledź płatności, a następnie spróbuj ponownie.',
@@ -441,6 +553,9 @@ const translations: TranslationDeepObject<typeof en> = {
         comments: 'Komentarze',
         sharedIn: 'Udostępnione w',
         unreported: 'Nierozliczone',
+        explore: 'Odkrywaj',
+        insights: 'Wgląd',
+        todo: 'Do zrobienia',
         invoice: 'Faktura',
         expense: 'Wydatek',
         chat: 'Czat',
@@ -450,16 +565,13 @@ const translations: TranslationDeepObject<typeof en> = {
         status: 'Status',
         on: 'Włączone',
         before: 'Przed',
-        after: 'Po',
-        range: 'Zakres',
+        after: 'PoPo',
         reschedule: 'Przełóż',
         general: 'Ogólne',
         workspacesTabTitle: 'Przestrzenie robocze',
         headsUp: 'Uwaga!',
         submitTo: 'Przekaż do',
         forwardTo: 'Przekaż do',
-        approvalLimit: 'Limit zatwierdzenia',
-        overLimitForwardTo: 'Przekaż przy przekroczeniu limitu',
         merge: 'Scal',
         none: 'Brak',
         unstableInternetConnection: 'Niestabilne połączenie internetowe. Sprawdź swoją sieć i spróbuj ponownie.',
@@ -476,7 +588,6 @@ const translations: TranslationDeepObject<typeof en> = {
         actionRequired: 'Wymagane działanie',
         duplicate: 'Duplikuj',
         duplicated: 'Zduplikowano',
-        opensInNewTab: 'Otwiera się w nowej karcie',
         locked: 'Zablokowane',
         duplicateExpense: 'Zduplikowany wydatek',
         exchangeRate: 'Kurs wymiany',
@@ -486,38 +597,14 @@ const translations: TranslationDeepObject<typeof en> = {
         week: 'Tydzień',
         year: 'Rok',
         quarter: 'Kwartał',
-        vacationDelegate: 'Zastępca urlopowy',
-        expensifyLogo: 'Logo Expensify',
-        concierge: {greeting: 'Cześć, w czym mogę pomóc?', showHistory: 'Pokaż historię'},
-        duplicateReport: 'Zduplikowany raport',
-        approver: 'Osoba zatwierdzająca',
-        goToConcierge: 'Przejdź do Concierge',
-        allSet: 'Gotowe!',
-        enterDigitLabel: ({digitIndex, totalDigits}: {digitIndex: number; totalDigits: number}) => `wprowadź cyfrę ${digitIndex} z ${totalDigits}`,
-        copyOfReportName: (reportName: string) => `Kopia raportu ${reportName}`,
-        previousMonth: 'Poprzedni miesiąc',
-        nextMonth: 'W przyszłym miesiącu',
-        previousYear: 'Poprzedni rok',
-        nextYear: 'W przyszłym roku',
-        avatar: 'Avatar',
-        editor: 'Edytor',
-        restrictions: 'Ograniczenia',
-    },
-    socials: {
-        podcast: 'Śledź nas na Podcast',
-        twitter: 'Śledź nas na Twitter',
-        instagram: 'Śledź nas na Instagram',
-        facebook: 'Śledź nas na Facebook',
-        linkedin: 'Śledź nas na LinkedIn',
-    },
-    concierge: {
-        collapseReasoning: 'Zwiń rozumowanie',
-        expandReasoning: 'Rozwiń rozumowanie',
-        enableNotifications: {prompt: 'Chcesz otrzymywać powiadomienia, gdy Concierge odpowie?', cta: 'Powiadom'},
     },
     supportalNoAccess: {
         title: 'Nie tak szybko',
-        descriptionWithCommand: (command?: string) =>
+        descriptionWithCommand: ({
+            command,
+        }: {
+            command?: string;
+        } = {}) =>
             `Nie masz uprawnień do wykonania tej akcji, gdy wsparcie jest zalogowane (polecenie: ${command ?? ''}). Jeśli uważasz, że Success powinien móc wykonać tę akcję, rozpocznij proszę rozmowę na Slacku.`,
     },
     lockedAccount: {
@@ -553,7 +640,7 @@ const translations: TranslationDeepObject<typeof en> = {
         chooseDocument: 'Wybierz plik',
         attachmentTooLarge: 'Załącznik jest zbyt duży',
         sizeExceeded: 'Rozmiar załącznika przekracza limit 24 MB',
-        sizeExceededWithLimit: (maxUploadSizeInMB: number) => `Rozmiar załącznika przekracza limit ${maxUploadSizeInMB} MB`,
+        sizeExceededWithLimit: ({maxUploadSizeInMB}: SizeExceededParams) => `Rozmiar załącznika przekracza limit ${maxUploadSizeInMB} MB`,
         attachmentTooSmall: 'Załącznik jest za mały',
         sizeNotMet: 'Rozmiar załącznika musi być większy niż 240 bajtów',
         wrongFileType: 'Nieprawidłowy typ pliku',
@@ -564,9 +651,9 @@ const translations: TranslationDeepObject<typeof en> = {
         attachmentImageTooLarge: 'Ten obraz jest zbyt duży, aby wyświetlić podgląd przed przesłaniem.',
         imageDimensionsTooLarge: 'Wymiary obrazu są zbyt duże do przetworzenia. Użyj mniejszego obrazu.',
         tooManyFiles: (fileLimit: number) => `Możesz jednorazowo przesłać maksymalnie ${fileLimit} plików.`,
-        sizeExceededWithValue: (maxUploadSizeInMB: number) => `Plik przekracza ${maxUploadSizeInMB} MB. Spróbuj ponownie.`,
+        sizeExceededWithValue: ({maxUploadSizeInMB}: SizeExceededParams) => `Plik przekracza ${maxUploadSizeInMB} MB. Spróbuj ponownie.`,
         someFilesCantBeUploaded: 'Niektórych plików nie można przesłać',
-        sizeLimitExceeded: (maxUploadSizeInMB: number) => `Pliki muszą mieć mniej niż ${maxUploadSizeInMB} MB. Większe pliki nie zostaną przesłane.`,
+        sizeLimitExceeded: ({maxUploadSizeInMB}: SizeExceededParams) => `Pliki muszą mieć mniej niż ${maxUploadSizeInMB} MB. Większe pliki nie zostaną przesłane.`,
         maxFileLimitExceeded: 'Możesz jednocześnie przesłać maksymalnie 30 paragonów. Dodatkowe paragony nie zostaną przesłane.',
         unsupportedFileType: (fileType: string) => `Pliki typu ${fileType} nie są obsługiwane. Zostaną przesłane tylko obsługiwane typy plików.`,
         learnMoreAboutSupportedFiles: 'Dowiedz się więcej o obsługiwanych formatach.',
@@ -606,55 +693,17 @@ const translations: TranslationDeepObject<typeof en> = {
         signIn: 'Zaloguj się ponownie.',
     },
     multifactorAuthentication: {
-        reviewTransaction: {
-            reviewTransaction: 'Sprawdź transakcję',
-            pleaseReview: 'Proszę przejrzeć tę transakcję',
-            requiresYourReview: 'Transakcja kartą Expensify wymaga Twojej weryfikacji poniżej.',
-            transactionDetails: 'Szczegóły transakcji',
-            deny: 'Odrzuć',
-            approve: 'Zatwierdź',
-            denyTransaction: 'Odrzuć transakcję',
-            transactionDenied: 'Transakcja odrzucona',
-            transactionApproved: 'Transakcja zatwierdzona!',
-            areYouSureToDeny: 'Na pewno? Transakcja zostanie odrzucona, jeśli zamkniesz ten ekran.',
-            youCanTryAgainAtMerchantOrReachOut:
-                'Możesz spróbować ponownie u sprzedawcy. Jeśli nie próbowałeś(-aś) wykonać tej transakcji, <concierge-link>skontaktuj się z Concierge</concierge-link>, aby zgłosić potencjalne oszustwo.',
-            youNeedToTryAgainAtMerchant: 'Ta transakcja nie została zweryfikowana, więc ją odrzuciliśmy. Musisz spróbować ponownie u sprzedawcy.',
-            goBackToTheMerchant: 'Wróć do strony sprzedawcy, aby kontynuować transakcję.',
-            attemptedTransaction: 'Próbowana transakcja',
-            transactionFailed: 'Transakcja nie powiodła się',
-            transactionCouldNotBeCompleted: 'Twoja transakcja nie mogła zostać zrealizowana. Spróbuj ponownie u sprzedawcy.',
-            transactionCouldNotBeCompletedReachOut:
-                'Nie można było sfinalizować Twojej transakcji. Jeśli nie próbowałeś(-aś) wykonać tej transakcji, <concierge-link>skontaktuj się z Concierge</concierge-link>, aby zgłosić potencjalne oszustwo.',
-            reviewFailed: 'Recenzja nie powiodła się',
-            alreadyReviewedSubtitle:
-                'Ta transakcja została już przez Ciebie sprawdzona. Sprawdź swoją <transaction-history-link>historię transakcji</transaction-history-link> lub skontaktuj się z <concierge-link>Concierge</concierge-link>, aby zgłosić wszelkie problemy.',
-        },
         biometricsTest: {
             biometricsTest: 'Test biometrii',
             authenticationSuccessful: 'Uwierzytelnianie powiodło się',
-            successfullyAuthenticatedUsing: (authType?: string) => `Pomyślnie uwierzytelniłeś się za pomocą ${authType}.`,
-            troubleshootBiometricsStatus: ({status}: {status?: string}) => `Dane biometryczne (${status})`,
+            successfullyAuthenticatedUsing: ({authType}: MultifactorAuthenticationTranslationParams) => `Pomyślnie uwierzytelniono przy użyciu ${authType}.`,
+            troubleshootBiometricsStatus: ({registered}: MultifactorAuthenticationTranslationParams) => `Dane biometryczne (${registered ? 'Zarejestrowano' : 'Nie zarejestrowano'})`,
             yourAttemptWasUnsuccessful: 'Twoja próba uwierzytelnienia nie powiodła się.',
             youCouldNotBeAuthenticated: 'Nie udało się uwierzytelnić użytkownika',
             areYouSureToReject: 'Na pewno? Próba uwierzytelnienia zostanie odrzucona, jeśli zamkniesz ten ekran.',
             rejectAuthentication: 'Odrzuć uwierzytelnianie',
             test: 'Test',
             biometricsAuthentication: 'Uwierzytelnianie biometryczne',
-            authType: {
-                unknown: 'Nieznany',
-                none: 'Brak',
-                credentials: 'Dane logowania',
-                biometrics: 'Biometria',
-                faceId: 'Face ID',
-                touchId: 'Touch ID',
-                opticId: 'Optic ID',
-                passkey: 'Passkey',
-            },
-            statusNeverRegistered: 'Nigdy nie zarejestrowano',
-            statusNotRegistered: 'Nie zarejestrowano',
-            statusRegisteredThisDevice: 'Zarejestrowano',
-            statusRegisteredOtherDevice: () => ({one: 'Zarejestrowano inne urządzenie', other: 'Inne zarejestrowane urządzenia'}),
         },
         pleaseEnableInSystemSettings: {
             start: 'Włącz weryfikację twarzą/odciskiem palca lub ustaw kod blokady urządzenia w swoim',
@@ -667,43 +716,28 @@ const translations: TranslationDeepObject<typeof en> = {
         letsVerifyItsYou: 'Zweryfikujmy, czy to na pewno Ty',
         nowLetsAuthenticateYou: 'Teraz Cię uwierzytelnimy…',
         letsAuthenticateYou: 'Uwierzytelnijmy Cię…',
-        verifyYourself: {biometrics: 'Zweryfikuj się za pomocą twarzy lub odcisku palca', passkeys: 'Zweryfikuj się za pomocą klucza dostępu'},
+        verifyYourself: {
+            biometrics: 'Zweryfikuj się za pomocą twarzy lub odcisku palca',
+        },
         enableQuickVerification: {
             biometrics: 'Włącz szybką i bezpieczną weryfikację za pomocą twarzy lub odcisku palca. Bez haseł i kodów.',
-            passkeys: 'Włącz szybką, bezpieczną weryfikację za pomocą klucza dostępu. Nie są wymagane żadne hasła ani kody.',
         },
         revoke: {
-            title: 'Face/odcisk palca i klucze dostępu',
+            remove: 'Usuń',
+            title: 'Twarz/odcisk palca i klucze dostępu',
             explanation:
-                'Weryfikacja twarzą/odciskiem palca lub kluczem dostępu jest włączona na jednym lub kilku urządzeniach. Odwołanie dostępu spowoduje, że przy następnej weryfikacji na tym urządzeniu będzie wymagany magiczny kod.',
-            confirmationPrompt: 'Na pewno? Będziesz potrzebować magicznego kodu przy następnej weryfikacji na tym urządzeniu.',
+                'Weryfikacja twarzy/odciskiem palca lub kluczem dostępu jest włączona na jednym lub kilku urządzeniach. Cofnięcie dostępu spowoduje konieczność użycia magicznego kodu przy następnej weryfikacji na dowolnym urządzeniu.',
+            confirmationPrompt: 'Na pewno? Do kolejnej weryfikacji na dowolnym urządzeniu będziesz potrzebować magicznego kodu.',
             cta: 'Cofnij dostęp',
             noDevices:
-                'Nie masz żadnych urządzeń zarejestrowanych do weryfikacji twarzą/odciskiem palca ani kluczem dostępu. Jeśli jakieś zarejestrujesz, będziesz mógł tutaj cofnąć ten dostęp.',
-            dismiss: 'Jasne',
+                'Nie masz zarejestrowanych żadnych urządzeń do weryfikacji twarzą/odciskiem palca ani kluczem dostępu. Jeśli jakieś zarejestrujesz, będziesz mógł/mogła cofnąć ten dostęp tutaj.',
+            dismiss: 'Rozumiem',
             error: 'Żądanie nie powiodło się. Spróbuj ponownie później.',
-            revoke: 'Unieważnij',
-            confirmationPromptAll: 'Na pewno? Będziesz potrzebować magicznego kodu do następnej weryfikacji na każdym urządzeniu.',
-            ctaAll: 'Cofnij wszystkie',
-            thisDevice: 'To urządzenie',
-            otherDevices: (otherDeviceCount?: number) => {
-                const numberWords = ['Jeden', 'Dwa', 'Trzy', 'Cztery', 'Pięć', 'Sześć', 'Siedem', 'Osiem', 'Dziewięć'];
-                const displayCount = otherDeviceCount !== undefined && otherDeviceCount >= 1 && otherDeviceCount <= 9 ? numberWords.at(otherDeviceCount - 1) : `${otherDeviceCount}`;
-                return `${displayCount} inna ${otherDeviceCount === 1 ? 'urządzenie' : 'urządzenia'}`;
-            },
-            confirmationPromptThisDevice: 'Na pewno? Będziesz potrzebować magicznego kodu przy następnej weryfikacji na tym urządzeniu.',
-            confirmationPromptMultiple: 'Na pewno? Będziesz potrzebować magicznego kodu przy następnej weryfikacji na tych urządzeniach.',
         },
         unsupportedDevice: {
             unsupportedDevice: 'Nieobsługiwane urządzenie',
-            pleaseDownloadMobileApp: `Ta akcja nie jest obsługiwana na Twoim urządzeniu. Pobierz aplikację Expensify z <a href="${CONST.APP_DOWNLOAD_LINKS.IOS}">App Store</a> lub <a href="${CONST.APP_DOWNLOAD_LINKS.ANDROID}">Sklepu Google Play</a> i spróbuj ponownie.`,
-            pleaseUseWebApp: `Ta akcja nie jest obsługiwana na Twoim urządzeniu. Użyj <a href="${CONST.NEW_EXPENSIFY_URL}">aplikacji webowej Expensify</a> i spróbuj ponownie.`,
+            pleaseDownloadMobileApp: `<centered-text><muted-text> Ta akcja nie jest obsługiwana na Twoim urządzeniu. Pobierz aplikację Expensify z <a href="${CONST.APP_DOWNLOAD_LINKS.IOS}">App Store</a> lub <a href="${CONST.APP_DOWNLOAD_LINKS.ANDROID}">Sklepu Google Play</a> i spróbuj ponownie.</muted-text></centered-text>`,
         },
-        verificationFailed: 'Weryfikacja nie powiodła się',
-        setPin: {didNotShipCard: 'Nie wysłaliśmy twojej karty. Spróbuj ponownie.'},
-        revealPin: {couldNotReveal: 'Nie udało się wyświetlić twojego PIN-u. Spróbuj ponownie.'},
-        changePin: {didNotChange: 'Nie zmieniliśmy twojego PIN-u. Spróbuj ponownie.'},
-        revealCardDetail: {couldNotReveal: 'Nie udało się wyświetlić szczegółów Twojej karty. Spróbuj ponownie.'},
     },
     validateCodeModal: {
         successfulSignInTitle: dedent(`
@@ -742,7 +776,11 @@ const translations: TranslationDeepObject<typeof en> = {
         nameEmailOrPhoneNumber: 'Imię i nazwisko, e-mail lub numer telefonu',
         findMember: 'Znajdź członka',
         searchForSomeone: 'Wyszukaj osobę',
-        userSelected: (username: string) => `Wybrano: ${username}`,
+    },
+    customApprovalWorkflow: {
+        title: 'Niestandardowy przepływ zatwierdzania',
+        description: 'Twoja firma ma niestandardowy proces zatwierdzania w tym obszarze roboczym. Wykonaj tę akcję w Expensify Classic',
+        goToExpensifyClassic: 'Przełącz na Expensify Classic',
     },
     emptyList: {
         [CONST.IOU.TYPE.CREATE]: {
@@ -764,8 +802,8 @@ const translations: TranslationDeepObject<typeof en> = {
         phrase2: 'Pieniądze mają głos. A teraz, gdy czat i płatności są w jednym miejscu, jest to także proste.',
         phrase3: 'Twoje płatności docierają do Ciebie tak szybko, jak szybko potrafisz przekazać swoją myśl.',
         enterPassword: 'Wprowadź swoje hasło',
-        welcomeNewFace: (login: string) => `${login}, zawsze miło zobaczyć tu nową twarz!`,
-        welcomeEnterMagicCode: (login: string) => `Wprowadź magiczny kod wysłany na ${login}. Powinien dotrzeć w ciągu minuty lub dwóch.`,
+        welcomeNewFace: ({login}: SignUpNewFaceCodeParams) => `${login}, zawsze miło zobaczyć tu nową twarz!`,
+        welcomeEnterMagicCode: ({login}: WelcomeEnterMagicCodeParams) => `Wprowadź magiczny kod wysłany na ${login}. Powinien dotrzeć w ciągu minuty lub dwóch.`,
     },
     login: {
         hero: {
@@ -793,9 +831,6 @@ const translations: TranslationDeepObject<typeof en> = {
         emoji: 'Emoji',
         collapse: 'Zwiń',
         expand: 'Rozwiń',
-        askConciergeToUpdate: 'Spróbuj „Zaktualizuj wydatek”…',
-        askConciergeToCorrect: 'Spróbuj „Skorygować wydatek”…',
-        askConciergeForHelp: 'Poproś Concierge AI o pomoc...',
     },
     reportActionContextMenu: {
         copyMessage: 'Kopiuj wiadomość',
@@ -859,9 +894,9 @@ const translations: TranslationDeepObject<typeof en> = {
         askMeAnything: 'Zapytaj mnie o cokolwiek!',
         sayHello: 'Przywitaj się!',
         yourSpace: 'Twoja przestrzeń',
-        welcomeToRoom: (roomName: string) => `Witaj w ${roomName}!`,
-        usePlusButton: (additionalText: string) => `Użyj przycisku +, aby ${additionalText} wydatek.`,
-        askConcierge: 'Concierge może odpowiadać na pytania, aktualizować wydatki i nie tylko.',
+        welcomeToRoom: ({roomName}: WelcomeToRoomParams) => `Witaj w ${roomName}!`,
+        usePlusButton: ({additionalText}: UsePlusButtonParams) => `Użyj przycisku +, aby ${additionalText} wydatek.`,
+        askConcierge: 'Zapytaj mnie o cokolwiek!',
         conciergeSupport: 'Twój osobisty agent AI',
         create: 'utwórz',
         iouTypes: {
@@ -873,17 +908,12 @@ const translations: TranslationDeepObject<typeof en> = {
         },
     },
     adminOnlyCanPost: 'Tylko administratorzy mogą wysyłać wiadomości w tym pokoju.',
-    readOnlyConversation: 'Ta rozmowa jest tylko do odczytu.',
     reportAction: {
         asCopilot: 'jako drugi pilot dla',
-        assistedBy: (agentName: string) => `wspierany przez ${agentName}`,
-        humanSupportAgent: 'ludzki agent wsparcia',
         harvestCreatedExpenseReport: (reportUrl: string, reportName: string) =>
             `utworzył(-a) ten raport, aby zawierał wszystkie wydatki z <a href="${reportUrl}">${reportName}</a>, których nie można było złożyć z wybraną przez Ciebie częstotliwością`,
-        createdReportForUnapprovedTransactions: (reportUrl: string, reportName: string, reportID: string, isReportDeleted: boolean) =>
-            isReportDeleted
-                ? `utworzono ten raport dla wszystkich wstrzymanych wydatków z usuniętego raportu nr ${reportID}`
-                : `utworzył(-a) ten raport dla wszystkich wstrzymanych wydatków z <a href="${reportUrl}">${reportName}</a>`,
+        createdReportForUnapprovedTransactions: ({reportUrl, reportName}: CreatedReportForUnapprovedTransactionsParams) =>
+            `utworzył/-a ten raport dla wszystkich wstrzymanych wydatków z <a href="${reportUrl}">${reportName}</a>`,
     },
     mentionSuggestions: {
         hereAlternateText: 'Powiadom wszystkich w tej konwersacji',
@@ -923,6 +953,7 @@ const translations: TranslationDeepObject<typeof en> = {
         buttonFind: 'Znajdź coś...',
         buttonMySettings: 'Moje ustawienia',
         fabNewChat: 'Rozpocznij czat',
+        fabNewChatExplained: 'Otwórz menu działań',
         fabScanReceiptExplained: 'Zeskanuj paragon',
         chatPinned: 'Czatu przypięto',
         draftedMessage: 'Wiadomość robocza',
@@ -930,44 +961,40 @@ const translations: TranslationDeepObject<typeof en> = {
         listOfChats: 'Lista czatów',
         saveTheWorld: 'Uratuj świat',
         tooltip: 'Zacznij tutaj!',
+        redirectToExpensifyClassicModal: {
+            title: 'Wkrótce dostępne',
+            description: 'Dopasowujemy jeszcze kilka elementów Nowego Expensify do Twojej specyficznej konfiguracji. Tymczasem przejdź do klasycznej wersji Expensify.',
+        },
     },
     homePage: {
         forYou: 'Dla ciebie',
         timeSensitiveSection: {
             title: 'Wymaga szybkiej reakcji',
-            addShippingAddress: {title: 'Potrzebujemy Twojego adresu wysyłki', subtitle: 'Podaj adres, na który mamy wysłać twoją Kartę Expensify.', cta: 'Dodaj adres'},
-            addPaymentCard: {title: 'Dodaj kartę płatniczą, żeby dalej korzystać z Expensify', subtitle: 'Konto > Subskrypcja', cta: 'Dodaj'},
-            activateCard: {title: 'Aktywuj swoją Kartę Expensify', subtitle: 'Zatwierdź swoją kartę i zacznij wydawać.', cta: 'Aktywuj'},
-            reviewCardFraud: {
-                title: 'Sprawdź potencjalne oszustwo na swojej Karcie Expensify',
-                titleWithDetails: ({amount, merchant}: {amount: string; merchant: string}) => `Przejrzyj ${amount} potencjalnie oszukańczych transakcji u ${merchant}`,
-                subtitle: 'Karta Expensify',
-                cta: 'Przejrzyj',
+            cta: 'Roszczenie',
+            offer50off: {
+                title: 'Otrzymaj 50% zniżki na pierwszy rok!',
+                subtitle: ({formattedTime}: {formattedTime: string}) => `Pozostało ${formattedTime}`,
             },
-            ctaFix: 'Napraw',
-            fixCompanyCardConnection: {
-                title: ({feedName}: {feedName: string}) => (feedName ? `Napraw połączenie karty firmowej ${feedName}` : 'Napraw połączenie karty firmowej'),
-                defaultSubtitle: 'Obszar roboczy',
-                subtitle: ({policyName}: {policyName: string}) => `${policyName} > Karty firmowe`,
+            offer25off: {
+                title: 'Uzyskaj 25% zniżki na pierwszy rok!',
+                subtitle: ({days}: {days: number}) => `Pozostało ${days} ${days === 1 ? 'dzień' : 'dni'}`,
             },
-            fixPolicyConnection: {
-                title: ({integrationName}: {integrationName: string}) => `Napraw połączenie ${integrationName}`,
-                defaultSubtitle: 'Obszar roboczy',
-                subtitle: ({policyName}: {policyName: string}) => `${policyName} > Księgowość`,
+            addShippingAddress: {
+                title: 'Potrzebujemy Twojego adresu wysyłki',
+                subtitle: 'Podaj adres, na który mamy wysłać Twoją kartę Expensify.',
+                cta: 'Dodaj adres',
             },
-            fixPersonalCardConnection: {
-                title: ({cardName}: {cardName?: string}) => (cardName ? `Napraw połączenie z prywatną kartą ${cardName}` : 'Napraw połączenie karty prywatnej'),
-                subtitle: 'Portfel',
+            activateCard: {
+                title: 'Aktywuj swoją kartę Expensify',
+                subtitle: 'Zatwierdź swoją kartę i zacznij wydawać.',
+                cta: 'Aktywuj',
             },
-            validateAccount: {title: 'Zweryfikuj swoje konto', subtitle: 'Konto', cta: 'Zatwierdź'},
-            fixFailedBilling: {title: 'Nie mogliśmy obciążyć zapisanej karty', subtitle: 'Subskrypcja'},
-            unlockBankAccount: {
-                workspaceTitle: 'Twoje firmowe konto bankowe zostało zablokowane',
-                personalTitle: 'Twoje konto bankowe zostało zablokowane',
-                workspaceSubtitle: ({policyName}: {policyName: string}) => policyName,
-                personalSubtitle: 'Portfel',
+            ctaFix: 'Napraw',
+            fixCompanyCardConnection: {
+                title: ({feedName}: {feedName: string}) => (feedName ? `Napraw połączenie karty firmowej ${feedName}` : 'Napraw połączenie karty firmowej'),
+                subtitle: 'Workspace > Karty firmowe',
             },
-            enterSignerInfo: {title: 'Wymagane dane podpisującego', subtitle: ({bankAccountLastFour}: {bankAccountLastFour: string}) => `Konto bankowe ${bankAccountLastFour}`},
+            fixAccountingConnection: {title: ({integrationName}: {integrationName: string}) => `Napraw połączenie ${integrationName}`, subtitle: 'Przestrzeń robocza > Księgowość'},
         },
         announcements: 'Ogłoszenia',
         discoverSection: {
@@ -983,78 +1010,12 @@ const translations: TranslationDeepObject<typeof en> = {
             export: ({count}: {count: number}) => `Eksportuj ${count} ${count === 1 ? 'raport' : 'raporty'}`,
             begin: 'Rozpocznij',
             emptyStateMessages: {
-                thumbsUpStarsTitle: 'Gotowe!',
-                thumbsUpStarsDescription: 'Brawo dla ciebie, wypatruj kolejnych zadań.',
-                smallRocketTitle: 'Wszystko nadrobione',
-                smallRocketDescription: 'Nadchodzące zadania pojawią się tutaj.',
-                cowboyHatTitle: 'Gotowe!',
-                cowboyHatDescription: 'Wszystkie zadania ogarnięte, wypatruj kolejnych.',
-                trophy1Title: 'Nic do wyświetlenia',
-                trophy1Description: 'Udało ci się! Wypatruj kolejnych zadań do wykonania.',
-                palmTreeTitle: 'Wszystko nadrobione',
-                palmTreeDescription: 'Czas na relaks, ale wypatruj przyszłych zadań.',
-                fishbowlBlueTitle: 'Gotowe!',
-                fishbowlBlueDescription: 'Przyszłe zadania pojawią się tutaj.',
-                targetTitle: 'Wszystko nadrobione',
-                targetDescription: 'Świetnie trzymasz się celu. Wróć po kolejne zadania!',
-                chairTitle: 'Nic do wyświetlenia',
-                chairDescription: 'Idź odpocząć, nadchodzące zadania wyświetlimy tutaj.',
-                broomTitle: 'Gotowe!',
-                broomDescription: 'Zadania są ogarnięte, ale wypatruj kolejnych rzeczy do zrobienia.',
-                houseTitle: 'Wszystko nadrobione',
-                houseDescription: 'To twoja baza dla nadchodzących zadań.',
-                conciergeBotTitle: 'Nic do wyświetlenia',
-                conciergeBotDescription: 'Bip bop bip bop, wróć po kolejne zadania!',
-                checkboxTextTitle: 'Wszystko nadrobione',
-                checkboxTextDescription: 'Odhaczaj tutaj swoje nadchodzące zadania.',
-                flashTitle: 'Gotowe!',
-                flashDescription: 'Twoje przyszłe zadania błyskawicznie pojawią się tutaj.',
-                sunglassesTitle: 'Nic do wyświetlenia',
-                sunglassesDescription: 'Czas się zrelaksować, ale wypatruj tego, co nadchodzi!',
-                f1FlagsTitle: 'Wszystko nadrobione',
-                f1FlagsDescription: 'Ukończyłeś wszystkie zaległe zadania.',
-            },
-        },
-        upcomingTravel: 'Nadchodząca podróż',
-        upcomingTravelSection: {
-            flightTo: ({destination}: {destination: string}) => `Lot do ${destination}`,
-            trainTo: ({destination}: {destination: string}) => `Pociąg do ${destination}`,
-            hotelIn: ({destination}: {destination: string}) => `Hotel w ${destination}`,
-            carRentalIn: ({destination}: {destination: string}) => `Wynajem samochodu w ${destination}`,
-            inOneWeek: 'Za 1 tydzień',
-            inDays: () => ({one: 'Za 1 dzień', other: (count: number) => `Za ${count} dni`}),
-            today: 'Dzisiaj',
-        },
-        freeTrialSection: {
-            title: ({days}: {days: number}) => `Darmowy okres próbny: pozostało ${days} ${days === 1 ? 'dzień' : 'dni'}!`,
-            offer50Body: 'Zyskaj 50% zniżki na pierwszy rok',
-            offer25Body: 'Uzyskaj 25% zniżki na pierwszy rok',
-            addCardBody: 'Dodaj kartę płatniczą',
-            ctaClaim: 'Roszczenie',
-            ctaAdd: 'Dodaj kartę',
-            timeRemaining: ({formattedTime}: {formattedTime: string}) => `Pozostały czas: ${formattedTime}`,
-            timeRemainingDays: () => ({
-                one: 'Pozostały czas: 1 dzień',
-                other: (pluralCount: number) => `Pozostały czas: ${pluralCount} dni`,
-            }),
-        },
-        gettingStartedSection: {
-            title: 'Pierwsze kroki',
-            createWorkspace: 'Utwórz przestrzeń roboczą',
-            connectAccounting: ({integrationName}: {integrationName: string}) => `Połącz z ${integrationName}`,
-            connectAccountingDefault: 'Połącz z księgowością',
-            customizeCategories: 'Dostosuj kategorie księgowe',
-            linkCompanyCards: 'Połącz firmowe karty',
-            setupRules: 'Skonfiguruj zasady wydatków',
-            inviteAccountant: 'Zaproś swojego księgowego',
-        },
-        yourSpend: {
-            title: 'Twoje wydatki',
-            awaitingApproval: 'Oczekuje na zatwierdzenie',
-            repaidLast30Days: 'Spłacono w ciągu ostatnich 30 dni',
-            recentTransactions: ({lastFour}: {lastFour: string}) => `Ostatnie transakcje • ${lastFour}`,
+                nicelyDone: 'Dobra robota',
+                keepAnEyeOut: 'Wypatruj tego, co nadejdzie!',
+                allCaughtUp: 'Wszystko odrobione',
+                upcomingTodos: 'Nadchodzące zadania pojawią się tutaj.',
+            },
         },
-        seeMore: ({count}: {count: number}) => `Zobacz jeszcze ${count}`,
     },
     allSettingsScreen: {
         subscription: 'Subskrypcja',
@@ -1083,19 +1044,7 @@ const translations: TranslationDeepObject<typeof en> = {
         singleFieldMultipleColumns: (fieldName: string) => `Ups! Przypisałeś jedno pole („${fieldName}”) do wielu kolumn. Sprawdź ustawienia i spróbuj ponownie.`,
         emptyMappedField: (fieldName: string) => `Ups! Pole („${fieldName}”) zawiera jedną lub więcej pustych wartości. Sprawdź je i spróbuj ponownie.`,
         importSuccessfulTitle: 'Import zakończony powodzeniem',
-        importCategoriesSuccessfulDescription: ({added, updated}: {added: number; updated: number}) => {
-            if (!added && !updated) {
-                return 'Nie dodano ani nie zaktualizowano żadnych kategorii.';
-            }
-            if (added && updated) {
-                return `Dodano ${added} ${added === 1 ? 'kategorię' : 'kategorie'}, zaktualizowano ${updated} ${updated === 1 ? 'kategorię' : 'kategorie'}.`;
-            }
-            if (added) {
-                return added === 1 ? 'Dodano 1 kategorię.' : `Dodano ${added} kategorie.`;
-            }
-            return updated === 1 ? 'Zaktualizowano 1 kategorię.' : `Zaktualizowano ${updated} kategorie.`;
-        },
-        importCompanyCardTransactionsSuccessfulDescription: ({transactions}: {transactions: number}) => (transactions > 1 ? `Dodano ${transactions} transakcji.` : 'Dodano 1 transakcję.'),
+        importCategoriesSuccessfulDescription: ({categories}: {categories: number}) => (categories > 1 ? `Dodano ${categories} kategorie.` : 'Dodano 1 kategorię.'),
         importMembersSuccessfulDescription: ({added, updated}: {added: number; updated: number}) => {
             if (!added && !updated) {
                 return 'Nie dodano ani nie zaktualizowano żadnych członków.';
@@ -1126,7 +1075,6 @@ const translations: TranslationDeepObject<typeof en> = {
             other: (count: number) =>
                 `Potwierdź poniższe szczegóły dotyczące ${count} nowych członków przestrzeni roboczej, którzy zostaną dodani w ramach tego przesyłania. Istniejący członkowie nie otrzymają żadnych aktualizacji ról ani wiadomości z zaproszeniem.`,
         }),
-        importCompanyCardTransactionsPendingMessage: 'Nowe karty i transakcje mogą potrzebować trochę czasu, aby się pojawić, prosimy o cierpliwość.',
     },
     receipt: {
         upload: 'Prześlij paragon',
@@ -1158,9 +1106,7 @@ const translations: TranslationDeepObject<typeof en> = {
         deleteReceipt: 'Usuń paragon',
         deleteConfirmation: 'Czy na pewno chcesz usunąć ten paragon?',
         addReceipt: 'Dodaj paragon',
-        addAdditionalReceipt: 'Dodaj dodatkowy paragon',
         scanFailed: 'Nie można było zeskanować paragonu, ponieważ brakuje na nim sprzedawcy, daty lub kwoty.',
-        crop: 'Przytnij',
         addAReceipt: {
             phrase1: 'Dodaj paragon',
             phrase2: 'lub przeciągnij i upuść tutaj',
@@ -1180,7 +1126,6 @@ const translations: TranslationDeepObject<typeof en> = {
         noLongerHaveReportAccess: 'Nie masz już dostępu do swojego poprzedniego szybkiego działania. Wybierz poniżej nowe.',
         updateDestination: 'Zaktualizuj miejsce docelowe',
         createReport: 'Utwórz raport',
-        createTimeExpense: 'Utwórz wydatek czasowy',
     },
     iou: {
         amount: 'Kwota',
@@ -1200,18 +1145,18 @@ const translations: TranslationDeepObject<typeof en> = {
         split: 'Podziel',
         splitExpense: 'Podziel wydatek',
         splitDates: 'Podziel daty',
-        splitDateRange: (startDate: string, endDate: string, count: number) => `${startDate} do ${endDate} (${count} dni)`,
-        splitExpenseSubtitle: (amount: string, merchant: string) => `${amount} od ${merchant}`,
+        splitDateRange: ({startDate, endDate, count}: SplitDateRangeParams) => `${startDate} do ${endDate} (${count} dni)`,
+        splitExpenseSubtitle: ({amount, merchant}: SplitExpenseSubtitleParams) => `${amount} od ${merchant}`,
         splitByPercentage: 'Podziel procentowo',
         splitByDate: 'Podziel według daty',
         addSplit: 'Dodaj podział',
         makeSplitsEven: 'Podziel równo',
         editSplits: 'Edytuj podziały',
-        totalAmountGreaterThanOriginal: (amount: string) => `Kwota łączna jest o ${amount} wyższa niż pierwotny wydatek.`,
-        totalAmountLessThanOriginal: (amount: string) => `Kwota całkowita jest o ${amount} mniejsza niż pierwotny wydatek.`,
+        totalAmountGreaterThanOriginal: ({amount}: TotalAmountGreaterOrLessThanOriginalParams) => `Kwota łączna jest o ${amount} wyższa niż pierwotny wydatek.`,
+        totalAmountLessThanOriginal: ({amount}: TotalAmountGreaterOrLessThanOriginalParams) => `Kwota całkowita jest o ${amount} mniejsza niż pierwotny wydatek.`,
         splitExpenseZeroAmount: 'Wprowadź prawidłową kwotę przed kontynuowaniem.',
         splitExpenseOneMoreSplit: 'Nie dodano podziałów. Dodaj co najmniej jeden, aby zapisać.',
-        splitExpenseEditTitle: (amount: string, merchant: string) => `Edytuj ${amount} dla ${merchant}`,
+        splitExpenseEditTitle: ({amount, merchant}: SplitExpenseEditTitleParams) => `Edytuj ${amount} dla ${merchant}`,
         removeSplit: 'Usuń podział',
         splitExpenseCannotBeEditedModalTitle: 'Ten wydatek nie może zostać edytowany',
         splitExpenseCannotBeEditedModalDescription: 'Zatwierdzonych ani opłaconych wydatków nie można edytować',
@@ -1242,12 +1187,9 @@ const translations: TranslationDeepObject<typeof en> = {
         deleteReceipt: 'Usuń paragon',
         findExpense: 'Znajdź wydatek',
         deletedTransaction: (amount: string, merchant: string) => `usunął(-ę) wydatek (${amount} dla ${merchant})`,
-        movedFromReport: (reportName: string) => `przeniesiono wydatek z ${reportName}`,
-        movedFromReportNoName: 'przeniesiono wydatek',
-        movedTransactionTo: (reportUrl: string, reportName: string) => `przeniósł ten wydatek do <a href="${reportUrl}">${reportName}</a>`,
-        movedTransactionToAnotherReport: 'przeniesiono ten wydatek do innego raportu',
-        movedTransactionFrom: (reportUrl: string, reportName: string) => `przeniósł ten wydatek z <a href="${reportUrl}">${reportName}</a>`,
-        movedTransactionFromAnotherReport: 'przeniesiono ten wydatek z innego raportu',
+        movedFromReport: (reportName: string) => `przeniesiono wydatek${reportName ? `z ${reportName}` : ''}`,
+        movedTransactionTo: (reportUrl: string, reportName?: string) => `przeniósł ten wydatek${reportName ? `do <a href="${reportUrl}">${reportName}</a>` : ''}`,
+        movedTransactionFrom: (reportUrl: string, reportName?: string) => `przeniósł(-ę) ten wydatek${reportName ? `z <a href="${reportUrl}">${reportName}</a>` : ''}`,
         unreportedTransaction: (reportUrl: string) => `przeniósł ten wydatek do Twojej <a href="${reportUrl}">przestrzeni osobistej</a>`,
         movedAction: (shouldHideMovedReportUrl: boolean, movedReportUrl: string, newParentReportUrl: string, toPolicyName: string) => {
             if (shouldHideMovedReportUrl) {
@@ -1259,10 +1201,7 @@ const translations: TranslationDeepObject<typeof en> = {
         pendingMatch: 'Oczekujące dopasowanie',
         pendingMatchWithCreditCardDescription: 'Oczekuje na dopasowanie paragonu do transakcji kartą. Oznacz jako gotówkę, aby anulować.',
         markAsCash: 'Oznacz jako gotówkę',
-        pendingMatchSubmitTitle: 'Wyślij raport',
-        pendingMatchSubmitDescription: 'Niektóre wydatki oczekują na dopasowanie z transakcją kartą kredytową. Czy chcesz oznaczyć je jako gotówkę?',
         routePending: 'Trasa w toku…',
-        automaticallyEnterExpenseDetails: 'Concierge uzupełni szczegóły za ciebie.',
         receiptScanning: () => ({
             one: 'Skanowanie paragonu...',
             other: 'Skanowanie paragonów...',
@@ -1289,7 +1228,7 @@ const translations: TranslationDeepObject<typeof en> = {
         receiptStatusTitle: 'Skanowanie…',
         receiptStatusText: 'Tylko ty widzisz ten paragon podczas skanowania. Sprawdź ponownie później lub wprowadź szczegóły teraz.',
         receiptScanningFailed: 'Skanowanie paragonu nie powiodło się. Wprowadź dane ręcznie.',
-        allTransactionsPendingNextStep: 'Wszystkie transakcje są w toku. Nie możesz złożyć tego raportu, dopóki nie zostaną zaksięgowane za kilka dni.',
+        transactionPendingDescription: 'Transakcja w toku. Zaksięgowanie może potrwać kilka dni.',
         companyInfo: 'Informacje o firmie',
         companyInfoDescription: 'Potrzebujemy jeszcze kilku informacji, zanim będziesz mógł wysłać swoją pierwszą fakturę.',
         yourCompanyName: 'Nazwa Twojej firmy',
@@ -1324,18 +1263,20 @@ const translations: TranslationDeepObject<typeof en> = {
         settledElsewhere: 'Opłacone gdzie indziej',
         individual: 'Osoba',
         business: 'Firma',
-        settlePersonal: (formattedAmount?: string) => (formattedAmount ? `Zapłać ${formattedAmount} jako osoba prywatna` : `Zapłać z konta osobistego`),
-        settleWallet: (formattedAmount?: string) => (formattedAmount ? `Zapłać ${formattedAmount} z portfela` : `Zapłać portfelem`),
-        settlePayment: (formattedAmount: string) => `Zapłać ${formattedAmount}`,
-        settleBusiness: (formattedAmount?: string) => (formattedAmount ? `Zapłać ${formattedAmount} jako firma` : `Zapłać z konta firmowego`),
-        payElsewhere: (formattedAmount?: string) => (formattedAmount ? `Oznacz ${formattedAmount} jako zapłaconą` : `Oznacz jako zapłacone`),
-        confirmPaymentReceivedModalTitle: 'Potwierdź otrzymanie płatności',
-        receivedPayment: 'Otrzymana płatność',
-        receivedPaymentConfirmation: 'Kontynuuj tylko, jeśli płatność została już otrzymana poza Expensify.',
-        confirmReceivedPayment: 'Tak, otrzymałem(-am) płatność.',
+        settleExpensify: ({formattedAmount}: SettleExpensifyCardParams) => (formattedAmount ? `Zapłać ${formattedAmount} z Expensify` : `Zapłać przez Expensify`),
+        settlePersonal: ({formattedAmount}: SettleExpensifyCardParams) => (formattedAmount ? `Zapłać ${formattedAmount} jako osoba prywatna` : `Zapłać z konta osobistego`),
+        settleWallet: ({formattedAmount}: SettleExpensifyCardParams) => (formattedAmount ? `Zapłać ${formattedAmount} z portfela` : `Zapłać portfelem`),
+        settlePayment: ({formattedAmount}: SettleExpensifyCardParams) => `Zapłać ${formattedAmount}`,
+        settleBusiness: ({formattedAmount}: SettleExpensifyCardParams) => (formattedAmount ? `Zapłać ${formattedAmount} jako firma` : `Zapłać z konta firmowego`),
+        payElsewhere: ({formattedAmount}: SettleExpensifyCardParams) => (formattedAmount ? `Oznacz ${formattedAmount} jako zapłaconą` : `Oznacz jako zapłacone`),
         settleInvoicePersonal: (amount?: string, last4Digits?: string) => (amount ? `zapłacono ${amount} z konta osobistego ${last4Digits}` : `Zapłacono z konta osobistego`),
         settleInvoiceBusiness: (amount?: string, last4Digits?: string) => (amount ? `zapłacono ${amount} z firmowego konta ${last4Digits}` : `Zapłacono z konta firmowego`),
-        payWithPolicy: (policyName: string, formattedAmount?: string) => (formattedAmount ? `Zapłać ${formattedAmount} przez ${policyName}` : `Zapłać przez ${policyName}`),
+        payWithPolicy: ({
+            formattedAmount,
+            policyName,
+        }: SettleExpensifyCardParams & {
+            policyName: string;
+        }) => (formattedAmount ? `Zapłać ${formattedAmount} przez ${policyName}` : `Zapłać przez ${policyName}`),
         businessBankAccount: (amount?: string, last4Digits?: string) => (amount ? `zapłacono ${amount} z konta bankowego ${last4Digits}` : `zapłacono z konta bankowego ${last4Digits}`),
         automaticallyPaidWithBusinessBankAccount: (amount?: string, last4Digits?: string) =>
             `zapłacono ${amount ? `${amount} ` : ''} z konta bankowego ${last4Digits} przez <a href="${CONST.CONFIGURE_EXPENSE_REPORT_RULES_HELP_URL}">zasady przestrzeni roboczej</a>`,
@@ -1344,16 +1285,16 @@ const translations: TranslationDeepObject<typeof en> = {
         nextStep: 'Następne kroki',
         finished: 'Zakończono',
         flip: 'Odwróć',
-        sendInvoice: (amount: string) => `Wyślij fakturę na ${amount}`,
+        sendInvoice: ({amount}: RequestAmountParams) => `Wyślij fakturę na ${amount}`,
         expenseAmount: (formattedAmount: string, comment?: string) => `${formattedAmount}${comment ? `za ${comment}` : ''}`,
-        submitted: (memo?: string) => `przesłano${memo ? `, wpisując ${memo}` : ''}`,
+        submitted: ({memo}: SubmittedWithMemoParams) => `przesłano${memo ? `, wpisując ${memo}` : ''}`,
         automaticallySubmitted: `przesłano przez <a href="${CONST.SELECT_WORKFLOWS_HELP_URL}">opóźnianie wysyłania</a>`,
         queuedToSubmitViaDEW: 'w kolejce do przesłania przez niestandardowy proces zatwierdzania',
         queuedToApproveViaDEW: 'oczekuje na zatwierdzenie w niestandardowym procesie akceptacji',
         trackedAmount: (formattedAmount: string, comment?: string) => `śledzenie ${formattedAmount}${comment ? `za ${comment}` : ''}`,
-        splitAmount: (amount: string) => `podziel ${amount}`,
-        didSplitAmount: (formattedAmount: string, comment?: string) => `podziel ${formattedAmount}${comment ? `za ${comment}` : ''}`,
-        yourSplit: (amount: string) => `Twój podział ${amount}`,
+        splitAmount: ({amount}: SplitAmountParams) => `podziel ${amount}`,
+        didSplitAmount: (formattedAmount: string, comment: string) => `podziel ${formattedAmount}${comment ? `za ${comment}` : ''}`,
+        yourSplit: ({amount}: UserSplitParams) => `Twój podział ${amount}`,
         payerOwesAmount: (amount: number | string, payer: string, comment?: string) => `${payer} jest winien ${amount}${comment ? `za ${comment}` : ''}`,
         payerOwes: (payer: string) => `${payer} jest winien:`,
         payerPaidAmount: (amount: number | string, payer?: string) => `${payer ? `${payer} ` : ''}zapłacił(a) ${amount}`,
@@ -1369,70 +1310,33 @@ const translations: TranslationDeepObject<typeof en> = {
         approvedMessage: `zatwierdzono`,
         unapproved: `niezatwierdzone`,
         automaticallyForwarded: `zatwierdzone przez <a href="${CONST.CONFIGURE_EXPENSE_REPORT_RULES_HELP_URL}">reguły przestrzeni roboczej</a>`,
-        forwarded: (memo?: string) => `zatwierdzono${memo ? `, wpisując ${memo}` : ''}`,
-        rejectedThisReport: 'odrzucono',
-        waitingOnBankAccount: (submitterDisplayName: string) => `rozpoczęto płatność, ale oczekuje na to, aż ${submitterDisplayName} doda konto bankowe.`,
+        forwarded: `zatwierdzono`,
+        rejectedThisReport: 'odrzucił(-a) ten raport',
+        waitingOnBankAccount: ({submitterDisplayName}: WaitingOnBankAccountParams) => `rozpoczęto płatność, ale oczekuje na to, aż ${submitterDisplayName} doda konto bankowe.`,
         adminCanceledRequest: 'anulowano płatność',
         canceledRequest: (amount: string, submitterDisplayName: string) =>
             `anulowano płatność ${amount}, ponieważ ${submitterDisplayName} nie aktywował(-a) swojego portfela Expensify w ciągu 30 dni`,
-        settledAfterAddedBankAccount: (submitterDisplayName: string, amount: string) => `${submitterDisplayName} dodał konto bankowe. Płatność w wysokości ${amount} została wykonana.`,
+        settledAfterAddedBankAccount: ({submitterDisplayName, amount}: SettledAfterAddedBankAccountParams) =>
+            `${submitterDisplayName} dodał konto bankowe. Płatność w wysokości ${amount} została wykonana.`,
         paidElsewhere: ({payer, comment}: PaidElsewhereParams = {}) => `${payer ? `${payer} ` : ''}oznaczone jako opłacone${comment ? `, mówiąc „${comment}”` : ''}`,
         paidWithExpensify: (payer?: string) => `${payer ? `${payer} ` : ''}zapłacono z portfela`,
         automaticallyPaidWithExpensify: (payer?: string) =>
             `${payer ? `${payer} ` : ''}zapłacono przez Expensify za pomocą <a href="${CONST.CONFIGURE_EXPENSE_REPORT_RULES_HELP_URL}">reguł przestrzeni roboczej</a>`,
-        reimbursedThisReport: 'zwrócił(-a) koszty z tego raportu',
-        paidThisBill: 'zapłacił(a) ten rachunek',
-        reimbursedOnBehalfOf: (actor: string) => `w imieniu ${actor}`,
-        reimbursedFromBankAccount: (debitBankAccount: string) => `z konta bankowego kończącego się na ${debitBankAccount}`,
-        reimbursedSubmitterAddedBankAccount: (submitter: string) => `${submitter} dodał konto bankowe, zdejmując raport z wstrzymania. Zwrot został zainicjowany`,
-        reimbursedWithFastACH: ({
-            isCurrentUser,
-            submitterLogin,
-            creditBankAccount,
-            expectedDate,
-        }: {
-            isCurrentUser: boolean;
-            submitterLogin: string;
-            creditBankAccount: string;
-            expectedDate: string;
-        }) =>
-            isCurrentUser
-                ? `. Pieniądze są w drodze na twoje ${creditBankAccount ? `konto bankowe kończące się na ${creditBankAccount}` : 'konto'}. Zwrot kosztów powinien zostać zrealizowany do ${expectedDate}.`
-                : `. Przelew jest w drodze na konto bankowe ${submitterLogin}${creditBankAccount ? ` kończące się na ${creditBankAccount}` : ''}. Zwrot kosztów powinien zostać zrealizowany do ${expectedDate}.`,
-        reimbursedWithCheck: ' czekiem.',
-        reimbursedWithStripeConnect: ({
-            isCurrentUser,
-            submitterLogin,
-            creditBankAccount,
-            isCard,
-        }: {
-            isCurrentUser: boolean;
-            submitterLogin: string;
-            creditBankAccount: string;
-            isCard: boolean;
-        }) => {
-            const paymentMethod = isCard ? 'karta' : 'konto bankowe';
-            return isCurrentUser
-                ? `. Pieniądze są w drodze na twoje ${creditBankAccount ? `konto bankowe kończące się na ${creditBankAccount}` : 'konto'} (zapłacono przez ${paymentMethod}). Może to potrwać do 10 dni roboczych.`
-                : `. Pieniądze są w drodze na konto bankowe ${submitterLogin}${creditBankAccount ? ` kończące się na ${creditBankAccount}` : ''} (zapłacono przez ${paymentMethod}). Może to potrwać do 10 dni roboczych.`;
-        },
-        reimbursedWithACH: ({creditBankAccount, expectedDate}: {creditBankAccount?: string; expectedDate?: string}) =>
-            ` z wpłatą bezpośrednią (ACH)${creditBankAccount ? ` na konto bankowe kończące się na ${creditBankAccount}.` : '. '}${expectedDate ? `Zwrot kosztów powinien zostać zrealizowany do ${expectedDate}.` : 'To zazwyczaj zajmuje 4–5 dni roboczych.'}`,
         noReimbursableExpenses: 'Ten raport ma nieprawidłową kwotę',
         pendingConversionMessage: 'Suma zaktualizuje się, gdy wrócisz do trybu online',
         changedTheExpense: 'zmienił(a) wydatek',
-        setTheRequest: (valueName: string, newValueToDisplay: string) => `${valueName} na ${newValueToDisplay}`,
-        setTheDistanceMerchant: (translatedChangedField: string, newMerchant: string, newAmountToDisplay: string) =>
+        setTheRequest: ({valueName, newValueToDisplay}: SetTheRequestParams) => `${valueName} na ${newValueToDisplay}`,
+        setTheDistanceMerchant: ({translatedChangedField, newMerchant, newAmountToDisplay}: SetTheDistanceMerchantParams) =>
             `ustawiono ${translatedChangedField} na ${newMerchant}, co ustawiło kwotę na ${newAmountToDisplay}`,
         removedTheRequest: (valueName: string, oldValueToDisplay: string) => `${valueName} (wcześniej ${oldValueToDisplay})`,
-        updatedTheRequest: (valueName: string, newValueToDisplay: string, oldValueToDisplay: string) => `${valueName} na ${newValueToDisplay} (wcześniej ${oldValueToDisplay})`,
-        updatedTheDistanceMerchant: (translatedChangedField: string, newMerchant: string, oldMerchant: string, newAmountToDisplay: string, oldAmountToDisplay: string) =>
+        updatedTheRequest: ({valueName, newValueToDisplay, oldValueToDisplay}: UpdatedTheRequestParams) => `${valueName} na ${newValueToDisplay} (wcześniej ${oldValueToDisplay})`,
+        updatedTheDistanceMerchant: ({translatedChangedField, newMerchant, oldMerchant, newAmountToDisplay, oldAmountToDisplay}: UpdatedTheDistanceMerchantParams) =>
             `zmienił(a) ${translatedChangedField} na ${newMerchant} (wcześniej ${oldMerchant}), co zaktualizowało kwotę na ${newAmountToDisplay} (wcześniej ${oldAmountToDisplay})`,
         basedOnAI: 'na podstawie dotychczasowej aktywności',
         basedOnMCC: ({rulesLink}: {rulesLink: string}) => (rulesLink ? `na podstawie <a href="${rulesLink}">zasad przestrzeni roboczej</a>` : 'na podstawie reguły przestrzeni roboczej'),
-        threadExpenseReportName: (formattedAmount: string, comment?: string) => `${formattedAmount} ${comment ? `dla ${comment}` : 'wydatek'}`,
+        threadExpenseReportName: ({formattedAmount, comment}: ThreadRequestReportNameParams) => `${formattedAmount} ${comment ? `dla ${comment}` : 'wydatek'}`,
         invoiceReportName: ({linkedReportID}: OriginalMessage<typeof CONST.REPORT.ACTIONS.TYPE.REPORT_PREVIEW>) => `Raport faktury nr ${linkedReportID}`,
-        threadPaySomeoneReportName: (formattedAmount: string, comment?: string) => `Wysłano ${formattedAmount}${comment ? `za ${comment}` : ''}`,
+        threadPaySomeoneReportName: ({formattedAmount, comment}: ThreadSentMoneyReportNameParams) => `Wysłano ${formattedAmount}${comment ? `za ${comment}` : ''}`,
         movedFromPersonalSpace: ({workspaceName, reportName}: MovedFromPersonalSpaceParams) => `przeniesiono wydatek z przestrzeni osobistej do ${workspaceName ?? `czat z ${reportName}`}`,
         movedToPersonalSpace: 'przeniesiono wydatek do przestrzeni prywatnej',
         error: {
@@ -1440,14 +1344,10 @@ const translations: TranslationDeepObject<typeof en> = {
             invalidTagLength: 'Nazwa taga przekracza 255 znaków. Skróć ją lub wybierz inny tag.',
             invalidAmount: 'Wprowadź poprawną kwotę przed kontynuowaniem',
             invalidDistance: 'Wprowadź prawidłowy dystans przed kontynuowaniem',
-            invalidReadings: 'Wprowadź zarówno odczyt początkowy, jak i końcowy przed kontynuowaniem',
+            invalidReadings: 'Wprowadź zarówno odczyt początkowy, jak i końcowy',
             negativeDistanceNotAllowed: 'Końcowy odczyt musi być większy niż początkowy odczyt',
-            distanceAmountTooLarge: 'Łączna kwota jest zbyt wysoka. Zmniejsz dystans lub obniż stawkę.',
-            distanceAmountTooLargeReduceDistance: 'Łączna kwota jest zbyt wysoka. Zmniejsz dystans.',
-            distanceAmountTooLargeReduceRate: 'Łączna kwota jest zbyt wysoka. Obniż stawkę.',
-            odometerReadingTooLarge: (formattedMax: string) => `Odczyty licznika nie mogą przekraczać ${formattedMax}.`,
             invalidIntegerAmount: 'Przed kontynuowaniem wprowadź kwotę w pełnych dolarach',
-            invalidTaxAmount: (amount: string) => `Maksymalna kwota podatku to ${amount}`,
+            invalidTaxAmount: ({amount}: RequestAmountParams) => `Maksymalna kwota podatku to ${amount}`,
             invalidSplit: 'Suma podziałów musi być równa całkowitej kwocie',
             invalidSplitParticipants: 'Wprowadź kwotę większą od zera dla co najmniej dwóch uczestników',
             invalidSplitYourself: 'Wprowadź niezerową kwotę dla swojego podziału',
@@ -1460,8 +1360,6 @@ const translations: TranslationDeepObject<typeof en> = {
             receiptDeleteFailureError: 'Nieoczekiwany błąd podczas usuwania tego paragonu. Spróbuj ponownie później.',
             receiptFailureMessage: '<rbr>Wystąpił błąd podczas przesyłania paragonu. Prosimy <a href="download">zapisać paragon</a> i <a href="retry">spróbować ponownie</a> później.</rbr>',
             receiptFailureMessageShort: 'Wystąpił błąd podczas przesyłania paragonu.',
-            receiptUploadFailedMessage: 'Nie udało się przesłać paragonu. Zapisz paragon lub usuń wydatek i utracisz go.',
-            saveReceipt: 'Zapisz paragon',
             genericDeleteFailureMessage: 'Nieoczekiwany błąd podczas usuwania tego wydatku. Spróbuj ponownie później.',
             genericEditFailureMessage: 'Nieoczekiwany błąd podczas edycji tego wydatku. Spróbuj ponownie później.',
             genericSmartscanFailureMessage: 'W transakcji brakuje pól',
@@ -1478,14 +1376,11 @@ const translations: TranslationDeepObject<typeof en> = {
             endDateSameAsStartDate: 'Data zakończenia nie może być taka sama jak data rozpoczęcia',
             manySplitsProvided: `Maksymalna dozwolona liczba podziałów to ${CONST.IOU.SPLITS_LIMIT}.`,
             dateRangeExceedsMaxDays: `Zakres dat nie może przekraczać ${CONST.IOU.SPLITS_LIMIT} dni.`,
-            unableToSubmitReport: 'Nie można wysłać raportu',
-            allTransactionsPendingDescription: 'Nie możesz przesłać tego raportu, ponieważ wszystkie transakcje są w toku. Zaksięgowanie ich może zająć kilka dni.',
-            stitchOdometerImagesFailed: 'Nie udało się połączyć zdjęć licznika kilometrów. Spróbuj ponownie później.',
-            failedToSaveOdometerDraft: 'Nie udało się zapisać Twojego szkicu licznika przebiegu. Spróbuj ponownie.',
         },
         dismissReceiptError: 'Odrzuć błąd',
         dismissReceiptErrorConfirmation: 'Uwaga! Zamknięcie tego błędu spowoduje całkowite usunięcie przesłanego paragonu. Czy na pewno chcesz kontynuować?',
-        waitingOnEnabledWallet: (submitterDisplayName: string) => `rozpoczął rozliczanie. Płatność jest wstrzymana, dopóki ${submitterDisplayName} nie włączy swojego portfela.`,
+        waitingOnEnabledWallet: ({submitterDisplayName}: WaitingOnBankAccountParams) =>
+            `rozpoczął rozliczanie. Płatność jest wstrzymana, dopóki ${submitterDisplayName} nie włączy swojego portfela.`,
         enableWallet: 'Włącz portfel',
         hold: 'Wstrzymaj',
         unhold: 'Usuń blokadę',
@@ -1497,20 +1392,16 @@ const translations: TranslationDeepObject<typeof en> = {
         heldExpense: 'wstrzymał ten wydatek',
         unheldExpense: 'zdjął wstrzymanie z tego wydatku',
         moveUnreportedExpense: 'Przenieś nierozliczony wydatek',
-        addExistingExpense: 'Dodaj istniejący wydatek',
-        selectExistingExpense: 'Wybierz co najmniej jeden wydatek, aby dodać go do raportu.',
-        emptyStateExistingExpenseTitle: 'Brak istniejących wydatków',
-        emptyStateExistingExpenseSubtitle: 'Wygląda na to, że nie masz żadnych istniejących wydatków. Spróbuj utworzyć jeden poniżej.',
-        addExistingExpenseConfirm: 'Dodaj do raportu',
+        addUnreportedExpense: 'Dodaj nierozliczony wydatek',
+        selectUnreportedExpense: 'Wybierz co najmniej jeden wydatek, aby dodać go do raportu.',
+        emptyStateUnreportedExpenseTitle: 'Brak nierozliczonych wydatków',
+        emptyStateUnreportedExpenseSubtitle: 'Wygląda na to, że nie masz żadnych nierozliczonych wydatków. Spróbuj utworzyć jeden poniżej.',
+        addUnreportedExpenseConfirm: 'Dodaj do raportu',
         newReport: 'Nowy raport',
         explainHold: () => ({
             one: 'Wyjaśnij, dlaczego wstrzymujesz ten wydatek.',
             other: 'Wyjaśnij, dlaczego wstrzymujesz te wydatki.',
         }),
-        explainHoldApprover: () => ({
-            one: 'Wyjaśnij, czego potrzebujesz przed zatwierdzeniem tego wydatku.',
-            other: 'Wyjaśnij, czego potrzebujesz przed zatwierdzeniem tych wydatków.',
-        }),
         retracted: 'wycofano',
         retract: 'Wycofaj',
         reopened: 'ponownie otwarto',
@@ -1526,9 +1417,6 @@ const translations: TranslationDeepObject<typeof en> = {
         someDuplicatesArePaid: 'Niektóre z tych duplikatów zostały już zatwierdzone lub opłacone.',
         reviewDuplicates: 'Przejrzyj duplikaty',
         keepAll: 'Zachowaj wszystko',
-        keepSelected: 'Zachowaj wybrane',
-        noDuplicatesTitle: 'Wszystko gotowe!',
-        noDuplicatesDescription: 'Nie ma tutaj zduplikowanych transakcji do sprawdzenia.',
         confirmApprove: 'Potwierdź kwotę zatwierdzenia',
         confirmApprovalAmount: 'Zatwierdź tylko zgodne wydatki lub zatwierdź cały raport.',
         confirmApprovalAllHoldAmount: () => ({
@@ -1562,7 +1450,7 @@ const translations: TranslationDeepObject<typeof en> = {
         unapprove: 'Cofnij zatwierdzenie',
         unapproveReport: 'Cofnij zatwierdzenie raportu',
         headsUp: 'Uwaga!',
-        unapproveWithIntegrationWarning: (accountingIntegration: string) =>
+        unapproveWithIntegrationWarning: ({accountingIntegration}: UnapproveWithIntegrationWarningParams) =>
             `Ten raport został już wyeksportowany do ${accountingIntegration}. Zmiana może prowadzić do rozbieżności w danych. Czy na pewno chcesz cofnąć zatwierdzenie tego raportu?`,
         reimbursable: 'podlegające zwrotowi',
         nonReimbursable: 'bez zwrotu kosztów',
@@ -1571,7 +1459,6 @@ const translations: TranslationDeepObject<typeof en> = {
         bookingArchived: 'Ta rezerwacja jest zarchiwizowana',
         bookingArchivedDescription: 'Ta rezerwacja została zarchiwizowana, ponieważ data podróży już minęła. W razie potrzeby dodaj wydatek na ostateczną kwotę.',
         attendees: 'Uczestnicy',
-        totalPerAttendee: 'Na uczestnika',
         whoIsYourAccountant: 'Kim jest twój księgowy?',
         paymentComplete: 'Płatność zakończona',
         time: 'Czas',
@@ -1598,7 +1485,7 @@ const translations: TranslationDeepObject<typeof en> = {
         }),
         dates: 'Daty',
         rates: 'Stawki',
-        submitsTo: (name: string) => `Przesyła do ${name}`,
+        submitsTo: ({name}: SubmitsToParams) => `Przesyła do ${name}`,
         reject: {
             educationalTitle: 'Zatrzymać czy odrzucić?',
             educationalText: 'Jeśli nie jesteś gotowy, aby zatwierdzić lub opłacić wydatek, możesz go wstrzymać lub odrzucić.',
@@ -1607,7 +1494,7 @@ const translations: TranslationDeepObject<typeof en> = {
             heldExpenseLeftBehindTitle: 'Wstrzymane wydatki są pomijane, gdy zatwierdzasz cały raport.',
             rejectExpenseTitle: 'Odrzuć wydatek, którego nie zamierzasz zatwierdzić ani opłacić.',
             reasonPageTitle: 'Odrzuć wydatek',
-            reasonPageDescription: 'Wyjaśnij, dlaczego nie zatwierdzisz tego wydatku.',
+            reasonPageDescription: 'Wyjaśnij, dlaczego odrzucasz ten wydatek.',
             rejectReason: 'Powód odrzucenia',
             markAsResolved: 'Oznacz jako rozwiązane',
             rejectedStatus: 'Ten wydatek został odrzucony. Czekamy, aż naprawisz problemy i oznaczysz go jako rozwiązany, aby umożliwić przesłanie.',
@@ -1616,26 +1503,13 @@ const translations: TranslationDeepObject<typeof en> = {
                 markedAsResolved: 'oznaczono powód odrzucenia jako rozwiązany',
             },
         },
-        rejectReport: {
-            title: 'Odrzuć raport',
-            description: 'Wyjaśnij, dlaczego nie zatwierdzisz tego raportu:',
-            rejectReason: 'Powód odrzucenia',
-            selectTarget: 'Wybierz członka, do którego chcesz odesłać ten raport do ponownego przejrzenia:',
-            lastApprover: 'Ostatni akceptujący',
-            submitter: 'Zgłaszający',
-            rejectedReportMessage: 'Ten raport został odrzucony.',
-            rejectedNextStep: 'Ten raport został odrzucony. Czekamy, aż naprawisz problemy i wyślesz go ponownie ręcznie.',
-            selectMemberError: 'Wybierz członka, do którego chcesz odesłać ten raport do odrzucenia.',
-            couldNotReject: 'Nie udało się odrzucić raportu. Spróbuj ponownie.',
-        },
-        moveExpenses: 'Przenieś do raportu',
+        moveExpenses: () => ({one: 'Przenieś wydatek', other: 'Przenieś wydatki'}),
         moveExpensesError: 'Nie możesz przenosić diet do raportów w innych przestrzeniach roboczych, ponieważ stawki diet mogą się różnić między przestrzeniami roboczymi.',
         changeApprover: {
             title: 'Zmień osobę zatwierdzającą',
-            header: (workflowSettingLink: string) =>
+            header: ({workflowSettingLink}: WorkflowSettingsParam) =>
                 `Wybierz opcję, aby zmienić osobę zatwierdzającą ten raport. (Zaktualizuj swoje <a href="${workflowSettingLink}">ustawienia przestrzeni roboczej</a>, aby zmienić to na stałe dla wszystkich raportów).`,
             changedApproverMessage: (managerID: number) => `zmienił(a) akceptującego na <mention-user accountID="${managerID}"/>`,
-            reassignedApproverMessage: (managerID: number) => `ponownie przypisał(a) akceptującego do <mention-user accountID="${managerID}"/> w wyniku aktualizacji przepływu pracy`,
             actions: {
                 addApprover: 'Dodaj zatwierdzającego',
                 addApproverSubtitle: 'Dodaj dodatkową osobę zatwierdzającą do istniejącego przepływu zatwierdzania.',
@@ -1644,12 +1518,10 @@ const translations: TranslationDeepObject<typeof en> = {
             },
             addApprover: {
                 subtitle: 'Wybierz dodatkowego akceptującego ten raport, zanim przekażemy go dalej w procesie akceptacji.',
-                bulkSubtitle: 'Wybierz dodatkowego akceptującego dla tych raportów, zanim przekażemy je dalej w pozostałej części procesu zatwierdzania.',
             },
-            bulkSubtitle: 'Wybierz opcję, aby zmienić akceptującego dla tych raportów.',
         },
         chooseWorkspace: 'Wybierz przestrzeń roboczą',
-        routedDueToDEW: (to: string, reason?: string) => `raport przekazany do ${to}${reason ? ` bo ${reason}` : ''}`,
+        routedDueToDEW: ({to}: RoutedDueToDEWParams) => `raport skierowano do ${to} z powodu niestandardowego przepływu zatwierdzania`,
         timeTracking: {
             hoursAt: (hours: number, rate: string) => `${hours} ${hours === 1 ? 'godzina' : 'godziny'} @ ${rate} / godzinę`,
             hrs: 'godz.',
@@ -1657,35 +1529,34 @@ const translations: TranslationDeepObject<typeof en> = {
             ratePreview: (rate: string) => `${rate} / godzinę`,
             amountTooLargeError: 'Łączna kwota jest zbyt wysoka. Zmniejsz liczbę godzin lub obniż stawkę.',
         },
-        correctRateError: 'Napraw błąd stawki i spróbuj ponownie.',
-        AskToExplain: `. <a href="${CONST.CONCIERGE_EXPLAIN_LINK_PATH}">Wyjaśnij<sparkles-icon/></a>`,
-        duplicateNonDefaultWorkspacePerDiemError:
-            'Nie możesz duplikować wydatków z tytułu diet między przestrzeniami roboczymi, ponieważ stawki mogą się różnić między poszczególnymi przestrzeniami.',
-        rulesModifiedFields: {
-            reimbursable: (value: boolean) => (value ? 'oznaczył(a) wydatek jako „podlegający zwrotowi”' : 'oznaczył(a) wydatek jako „niepodlegający zwrotowi kosztów”'),
-            billable: (value: boolean) => (value ? 'oznaczył(-a) wydatek jako „fakturowany”' : 'oznaczono wydatek jako „niefakturowalny”'),
-            tax: (value: string, isFirst: boolean) => (isFirst ? `ustaw stawkę podatku na „${value}”` : `stawka podatku na „${value}”`),
-            reportName: (value: string) => `przeniósł ten wydatek do raportu „${value}”`,
-            common: (key: keyof PolicyRulesModifiedFields | keyof PersonalRulesModifiedFields, value: string, isFirst: boolean) => {
-                const field = translations.common[key].toLowerCase();
-                return isFirst ? `ustaw ${field} na „${value}”` : `${field} na „${value}”`;
-            },
-            formatPersonalRules: (fragments: string, route: string) => `${fragments} przez <a href="${route}">zasady wydatków prywatnych</a>`,
-            formatPolicyRules: (fragments: string, route: string) => `${fragments} przez <a href="${route}">zasady workspace’u</a>`,
-        },
-        failedToAutoSubmitViaDEW: (reason: string) => `nie udało się przesłać raportu przez <a href="${CONST.SELECT_WORKFLOWS_HELP_URL}">opóźnianie wysyłki</a>. ${reason}`,
-        failedToSubmitViaDEW: (reason: string) => `nie udało się wysłać raportu. ${reason}`,
-        failedToAutoApproveViaDEW: (reason: string) =>
-            `nie udało się zatwierdzić przez <a href="${CONST.CONFIGURE_EXPENSE_REPORT_RULES_HELP_URL}">zasady w przestrzeni roboczej</a>. ${reason}`,
-        failedToApproveViaDEW: (reason: string) => `nie udało się zaakceptować. ${reason}`,
-        cannotDuplicateDistanceExpense: 'Nie możesz duplikować wydatków za przejazdy między przestrzeniami roboczymi, ponieważ stawki mogą się różnić między poszczególnymi przestrzeniami.',
-        taxDisabledAlert: {
-            title: 'Podatek wyłączony',
-            prompt: 'Włącz śledzenie podatku w przestrzeni roboczej, aby edytować szczegóły wydatku lub usunąć podatek z tego wydatku.',
-            confirmText: 'Usuń podatek',
-        },
-        bulkDuplicateLimit: `Możesz jednocześnie zduplikować maksymalnie ${CONST.SEARCH.BULK_DUPLICATE_LIMIT} wydatków. Wybierz mniej wydatków i spróbuj ponownie.`,
-        deleted: 'Usunięto',
+        correctDistanceRateError: 'Napraw błąd stawki za dystans i spróbuj ponownie.',
+        AskToExplain: `. <a href="${CONST.CONCIERGE_EXPLAIN_LINK_PATH}"><strong>Wyjaśnij</strong></a> &#x2728;`,
+        policyRulesModifiedFields: (policyRulesModifiedFields: PolicyRulesModifiedFields, policyRulesRoute: string, formatList: (list: string[]) => string) => {
+            const entries = ObjectUtils.typedEntries(policyRulesModifiedFields);
+            const fragments = entries.map(([key, value], i) => {
+                const isFirst = i === 0;
+                if (key === 'reimbursable') {
+                    return value ? 'oznaczył(a) wydatek jako „podlegający zwrotowi”' : 'oznaczył(a) wydatek jako „niepodlegający zwrotowi”';
+                }
+                if (key === 'billable') {
+                    return value ? 'oznaczył(-a) wydatek jako „fakturowany”' : 'oznaczono wydatek jako „niefakturowalny”';
+                }
+                if (key === 'tax') {
+                    const taxEntry = value as PolicyRulesModifiedFields['tax'];
+                    const taxRateName = taxEntry?.field_id_TAX.name ?? '';
+                    if (isFirst) {
+                        return `ustaw stawkę podatku na „${taxRateName}”`;
+                    }
+                    return `stawka podatku na „${taxRateName}”`;
+                }
+                const updatedValue = value as string | boolean;
+                if (isFirst) {
+                    return `ustaw ${translations.common[key].toLowerCase()} na „${updatedValue}”`;
+                }
+                return `${translations.common[key].toLowerCase()} na „${updatedValue}”`;
+            });
+            return `${formatList(fragments)} przez <a href="${policyRulesRoute}">zasady przestrzeni roboczej</a>`;
+        },
     },
     transactionMerge: {
         listPage: {
@@ -1758,185 +1629,110 @@ const translations: TranslationDeepObject<typeof en> = {
     },
     nextStep: {
         message: {
-            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_TO_ADD_TRANSACTIONS]: (
-                actor: string,
-                actorType: ValueOf<typeof CONST.NEXT_STEP.ACTOR_TYPE>,
-                _eta?: string,
-                _etaType?: ValueOf<typeof CONST.NEXT_STEP.ETA_TYPE>,
-            ) => {
+            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_TO_ADD_TRANSACTIONS]: ({actor, actorType}: NextStepParams) => {
                 switch (actorType) {
                     case CONST.NEXT_STEP.ACTOR_TYPE.CURRENT_USER:
-                        return `Czekamy, aż to <strong>ty</strong> dodasz wydatki.`;
+                        return `Czekamy, aż <strong>Ty</strong> dodasz wydatki.`;
                     case CONST.NEXT_STEP.ACTOR_TYPE.OTHER_USER:
                         return `Oczekiwanie, aż <strong>${actor}</strong> doda wydatki.`;
                     case CONST.NEXT_STEP.ACTOR_TYPE.UNSPECIFIED_ADMIN:
-                        return `Oczekiwanie, aż administrator doda wydatki.`;
+                        return `Oczekiwanie na dodanie wydatków przez administratora.`;
                 }
             },
-            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_TO_SUBMIT]: (
-                actor: string,
-                actorType: ValueOf<typeof CONST.NEXT_STEP.ACTOR_TYPE>,
-                _eta?: string,
-                _etaType?: ValueOf<typeof CONST.NEXT_STEP.ETA_TYPE>,
-            ) => {
+            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_TO_SUBMIT]: ({actor, actorType}: NextStepParams) => {
                 switch (actorType) {
                     case CONST.NEXT_STEP.ACTOR_TYPE.CURRENT_USER:
-                        return `Czekamy, aż <strong>Ty</strong> zgłosisz wydatki.`;
+                        return `Czekamy, aż <strong>ty</strong> złożysz wydatki.`;
                     case CONST.NEXT_STEP.ACTOR_TYPE.OTHER_USER:
-                        return `Oczekiwanie, aż <strong>${actor}</strong> prześle wydatki.`;
+                        return `Oczekiwanie, aż <strong>${actor}</strong> przesłał(a) wydatki.`;
                     case CONST.NEXT_STEP.ACTOR_TYPE.UNSPECIFIED_ADMIN:
-                        return `Oczekiwanie, aż administrator złoży wydatki.`;
+                        return `Oczekiwanie, aż administrator prześle wydatki.`;
                 }
             },
-            [CONST.NEXT_STEP.MESSAGE_KEY.NO_FURTHER_ACTION]: (
-                _actor: string,
-                _actorType: ValueOf<typeof CONST.NEXT_STEP.ACTOR_TYPE>,
-                _eta?: string,
-                _etaType?: ValueOf<typeof CONST.NEXT_STEP.ETA_TYPE>,
-            ) => `Nie są wymagane dalsze działania!`,
-            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_FOR_SUBMITTER_ACCOUNT]: (
-                actor: string,
-                actorType: ValueOf<typeof CONST.NEXT_STEP.ACTOR_TYPE>,
-                _eta?: string,
-                _etaType?: ValueOf<typeof CONST.NEXT_STEP.ETA_TYPE>,
-            ) => {
+            [CONST.NEXT_STEP.MESSAGE_KEY.NO_FURTHER_ACTION]: (_: NextStepParams) => `Nie są wymagane dalsze działania!`,
+            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_FOR_SUBMITTER_ACCOUNT]: ({actor, actorType}: NextStepParams) => {
                 switch (actorType) {
                     case CONST.NEXT_STEP.ACTOR_TYPE.CURRENT_USER:
-                        return `Czekamy, aż <strong>dodasz</strong> konto bankowe.`;
+                        return `Czekamy, aż <strong>Ty</strong> dodasz konto bankowe.`;
                     case CONST.NEXT_STEP.ACTOR_TYPE.OTHER_USER:
                         return `Oczekiwanie, aż <strong>${actor}</strong> doda konto bankowe.`;
                     case CONST.NEXT_STEP.ACTOR_TYPE.UNSPECIFIED_ADMIN:
                         return `Oczekiwanie na dodanie konta bankowego przez administratora.`;
                 }
             },
-            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_FOR_AUTOMATIC_SUBMIT]: (
-                actor: string,
-                actorType: ValueOf<typeof CONST.NEXT_STEP.ACTOR_TYPE>,
-                eta?: string,
-                etaType?: ValueOf<typeof CONST.NEXT_STEP.ETA_TYPE>,
-            ) => {
+            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_FOR_AUTOMATIC_SUBMIT]: ({actor, actorType, eta, etaType}: NextStepParams) => {
                 let formattedETA = '';
                 if (eta) {
-                    formattedETA = etaType === CONST.NEXT_STEP.ETA_TYPE.DATE_TIME ? `${eta}. dnia każdego miesiąca` : ` ${eta}`;
+                    formattedETA = etaType === CONST.NEXT_STEP.ETA_TYPE.DATE_TIME ? `o ${eta}` : ` ${eta}`;
                 }
                 switch (actorType) {
                     case CONST.NEXT_STEP.ACTOR_TYPE.CURRENT_USER:
-                        return `Oczekiwanie, aż <strong>twoje</strong> wydatki zostaną automatycznie przesłane${formattedETA}.`;
+                        return `Oczekiwanie na automatyczne zgłoszenie <strong>Twoich</strong> wydatków${formattedETA}.`;
                     case CONST.NEXT_STEP.ACTOR_TYPE.OTHER_USER:
-                        return `Oczekiwanie, aż wydatki użytkownika <strong>${actor}</strong> zostaną automatycznie przesłane${formattedETA}.`;
+                        return `Oczekiwanie na automatyczne przesłanie wydatków użytkownika <strong>${actor}</strong>${formattedETA}.`;
                     case CONST.NEXT_STEP.ACTOR_TYPE.UNSPECIFIED_ADMIN:
-                        return `Oczekiwanie, aż wydatki administratora zostaną automatycznie wysłane${formattedETA}.`;
+                        return `Oczekiwanie na automatyczne złożenie wydatków administratora${formattedETA}.`;
                 }
             },
-            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_TO_FIX_ISSUES]: (
-                actor: string,
-                actorType: ValueOf<typeof CONST.NEXT_STEP.ACTOR_TYPE>,
-                _eta?: string,
-                _etaType?: ValueOf<typeof CONST.NEXT_STEP.ETA_TYPE>,
-            ) => {
+            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_TO_FIX_ISSUES]: ({actor, actorType}: NextStepParams) => {
                 switch (actorType) {
                     case CONST.NEXT_STEP.ACTOR_TYPE.CURRENT_USER:
-                        return `Czekamy, aż <strong>ty</strong> naprawisz problemy.`;
+                        return `Czekamy, aż <strong>Ty</strong> naprawisz problemy.`;
                     case CONST.NEXT_STEP.ACTOR_TYPE.OTHER_USER:
                         return `Oczekiwanie, aż <strong>${actor}</strong> naprawi problemy.`;
                     case CONST.NEXT_STEP.ACTOR_TYPE.UNSPECIFIED_ADMIN:
                         return `Oczekiwanie na naprawienie problemów przez administratora.`;
                 }
             },
-            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_TO_APPROVE]: (
-                actor: string,
-                actorType: ValueOf<typeof CONST.NEXT_STEP.ACTOR_TYPE>,
-                _eta?: string,
-                _etaType?: ValueOf<typeof CONST.NEXT_STEP.ETA_TYPE>,
-            ) => {
+            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_TO_APPROVE]: ({actor, actorType}: NextStepParams) => {
                 switch (actorType) {
                     case CONST.NEXT_STEP.ACTOR_TYPE.CURRENT_USER:
-                        return `Czekamy, aż <strong>ty</strong> zatwierdzisz wydatki.`;
+                        return `Oczekiwanie, aż <strong>Ty</strong> zatwierdzisz wydatki.`;
                     case CONST.NEXT_STEP.ACTOR_TYPE.OTHER_USER:
                         return `Oczekiwanie, aż <strong>${actor}</strong> zatwierdzi wydatki.`;
                     case CONST.NEXT_STEP.ACTOR_TYPE.UNSPECIFIED_ADMIN:
                         return `Oczekiwanie na zatwierdzenie wydatków przez administratora.`;
                 }
             },
-            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_TO_EXPORT]: (
-                actor: string,
-                actorType: ValueOf<typeof CONST.NEXT_STEP.ACTOR_TYPE>,
-                _eta?: string,
-                _etaType?: ValueOf<typeof CONST.NEXT_STEP.ETA_TYPE>,
-            ) => {
+            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_TO_EXPORT]: ({actor, actorType}: NextStepParams) => {
                 switch (actorType) {
                     case CONST.NEXT_STEP.ACTOR_TYPE.CURRENT_USER:
-                        return `Czekamy, aż to <strong>ty</strong> wyeksportujesz ten raport.`;
+                        return `Oczekuje, aż <strong>Ty</strong> wyeksportujesz ten raport.`;
                     case CONST.NEXT_STEP.ACTOR_TYPE.OTHER_USER:
                         return `Oczekiwanie, aż <strong>${actor}</strong> wyeksportuje ten raport.`;
                     case CONST.NEXT_STEP.ACTOR_TYPE.UNSPECIFIED_ADMIN:
-                        return `Oczekiwanie na administratora, który wyeksportuje ten raport.`;
+                        return `Oczekiwanie na administratora, aby wyeksportował ten raport.`;
                 }
             },
-            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_TO_PAY]: (
-                actor: string,
-                actorType: ValueOf<typeof CONST.NEXT_STEP.ACTOR_TYPE>,
-                _eta?: string,
-                _etaType?: ValueOf<typeof CONST.NEXT_STEP.ETA_TYPE>,
-            ) => {
+            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_TO_PAY]: ({actor, actorType}: NextStepParams) => {
                 switch (actorType) {
                     case CONST.NEXT_STEP.ACTOR_TYPE.CURRENT_USER:
-                        return `Czekamy, aż <strong>ty</strong> zapłacisz wydatki.`;
+                        return `Oczekiwanie, aż <strong>Ty</strong> opłacisz wydatki.`;
                     case CONST.NEXT_STEP.ACTOR_TYPE.OTHER_USER:
-                        return `Oczekiwanie, aż <strong>${actor}</strong> zapłaci wydatki.`;
+                        return `Oczekiwanie, aż <strong>${actor}</strong> zapłaci za wydatki.`;
                     case CONST.NEXT_STEP.ACTOR_TYPE.UNSPECIFIED_ADMIN:
                         return `Oczekiwanie na opłacenie wydatków przez administratora.`;
                 }
             },
-            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_FOR_POLICY_BANK_ACCOUNT]: (
-                actor: string,
-                actorType: ValueOf<typeof CONST.NEXT_STEP.ACTOR_TYPE>,
-                _eta?: string,
-                _etaType?: ValueOf<typeof CONST.NEXT_STEP.ETA_TYPE>,
-            ) => {
+            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_FOR_POLICY_BANK_ACCOUNT]: ({actor, actorType}: NextStepParams) => {
                 switch (actorType) {
                     case CONST.NEXT_STEP.ACTOR_TYPE.CURRENT_USER:
-                        return `Czekamy, aż <strong>Ty</strong> skończysz zakładać firmowe konto bankowe.`;
+                        return `Czekamy, aż <strong>Ty</strong> zakończysz konfigurację firmowego konta bankowego.`;
                     case CONST.NEXT_STEP.ACTOR_TYPE.OTHER_USER:
-                        return `Oczekiwanie, aż <strong>${actor}</strong> zakończy konfigurowanie firmowego konta bankowego.`;
+                        return `Oczekiwanie, aż <strong>${actor}</strong> zakończy zakładanie firmowego konta bankowego.`;
                     case CONST.NEXT_STEP.ACTOR_TYPE.UNSPECIFIED_ADMIN:
-                        return `Czekanie, aż administrator skończy konfigurować firmowe konto bankowe.`;
+                        return `Oczekiwanie na ukończenie konfiguracji firmowego konta bankowego przez administratora.`;
                 }
             },
-            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_FOR_PAYMENT]: (
-                _actor: string,
-                _actorType: ValueOf<typeof CONST.NEXT_STEP.ACTOR_TYPE>,
-                eta?: string,
-                etaType?: ValueOf<typeof CONST.NEXT_STEP.ETA_TYPE>,
-            ) => {
+            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_FOR_PAYMENT]: ({eta, etaType}: NextStepParams) => {
                 let formattedETA = '';
                 if (eta) {
                     formattedETA = etaType === CONST.NEXT_STEP.ETA_TYPE.DATE_TIME ? `do ${eta}` : ` ${eta}`;
                 }
                 return `Oczekiwanie na zakończenie płatności${formattedETA}.`;
             },
-            [CONST.NEXT_STEP.MESSAGE_KEY.SUBMITTING_TO_SELF]: (
-                _actor: string,
-                _actorType: ValueOf<typeof CONST.NEXT_STEP.ACTOR_TYPE>,
-                _eta?: string,
-                _etaType?: ValueOf<typeof CONST.NEXT_STEP.ETA_TYPE>,
-            ) =>
-                `Ups! Wygląda na to, że wysyłasz raport do <strong>siebie</strong>. Zatwierdzanie własnych raportów jest <strong>zabronione</strong> w twojej przestrzeni roboczej. Wyślij ten raport do kogoś innego albo skontaktuj się z administratorem, żeby zmienić osobę, do której wysyłasz.`,
-            [CONST.NEXT_STEP.MESSAGE_KEY.REJECTED_REPORT]: (
-                actor: string,
-                actorType: ValueOf<typeof CONST.NEXT_STEP.ACTOR_TYPE>,
-                _eta?: string,
-                _etaType?: ValueOf<typeof CONST.NEXT_STEP.ETA_TYPE>,
-            ) => {
-                switch (actorType) {
-                    case CONST.NEXT_STEP.ACTOR_TYPE.CURRENT_USER:
-                        return `Ten raport został odrzucony. Czekamy, aż <strong>ty</strong> naprawisz problemy i ręcznie go prześlesz ponownie.`;
-                    case CONST.NEXT_STEP.ACTOR_TYPE.OTHER_USER:
-                        return `Ten raport został odrzucony. Oczekiwanie na <strong>${actor}</strong> w celu naprawienia problemów i ręcznego ponownego przesłania.`;
-                    case CONST.NEXT_STEP.ACTOR_TYPE.UNSPECIFIED_ADMIN:
-                        return `Ten raport został odrzucony. Czekamy, aż administrator naprawi problemy i prześle go ponownie ręcznie.`;
-                }
-            },
+            [CONST.NEXT_STEP.MESSAGE_KEY.SUBMITTING_TO_SELF]: (_: NextStepParams) =>
+                `Ups! Wygląda na to, że wysyłasz zgłoszenie <strong>do siebie</strong>. Zatwierdzanie własnych raportów jest <strong>zabronione</strong> w Twojej przestrzeni roboczej. Wyślij ten raport do kogoś innego lub skontaktuj się z administratorem, aby zmienić osobę, do której je przesyłasz.`,
         },
         eta: {
             [CONST.NEXT_STEP.ETA_KEY.SHORTLY]: 'wkrótce',
@@ -1962,8 +1758,6 @@ const translations: TranslationDeepObject<typeof en> = {
         offline: 'Offline',
         syncing: 'Synchronizowanie',
         profileAvatar: 'Awatar profilu',
-        customInstructions: 'Niestandardowe instrukcje',
-        copilotIntoAccount: 'Copilot do konta',
         publicSection: {
             title: 'Public',
             subtitle: 'Te dane są wyświetlane w Twoim publicznym profilu. Każdy może je zobaczyć.',
@@ -1972,16 +1766,12 @@ const translations: TranslationDeepObject<typeof en> = {
             title: 'Prywatne',
             subtitle: 'Te dane są używane do podróży i płatności. Nigdy nie są wyświetlane w Twoim publicznym profilu.',
         },
-        aiPromptSection: {
-            title: 'Prompt AI',
-            subtitle: 'Napisz niestandardowe instrukcje',
-            prompt: 'Zachęta',
-            editPrompt: 'Edytuj podpowiedź',
-            promptCannotBeEmpty: 'Pole nie może być puste',
-            saved: 'Zapisano',
-        },
     },
-    securityPage: {title: 'Bezpieczeństwo', subtitle: 'Zadbaj o bezpieczeństwo swojego konta.', goToSecurity: 'Wróć do strony zabezpieczeń'},
+    securityPage: {
+        title: 'Opcje zabezpieczeń',
+        subtitle: 'Włącz uwierzytelnianie dwuskładnikowe, aby chronić swoje konto.',
+        goToSecurity: 'Wróć do strony zabezpieczeń',
+    },
     shareCodePage: {
         title: 'Twój kod',
         subtitle: 'Zaproś członków do Expensify, udostępniając swój osobisty kod QR lub link polecający.',
@@ -2018,7 +1808,6 @@ const translations: TranslationDeepObject<typeof en> = {
         },
         newContactMethod: 'Nowy sposób kontaktu',
         goBackContactMethods: 'Wróć do metod kontaktu',
-        yourDefaultContactMethodRestrictedSwitch: 'To jest Twoja domyślna metoda kontaktu. Twoja firma zablokowała możliwość usuwania lub zmiany tej metody.',
     },
     pronouns: {
         coCos: 'Co / Coś',
@@ -2078,6 +1867,8 @@ const translations: TranslationDeepObject<typeof en> = {
         },
         troubleshoot: {
             clearCacheAndRestart: 'Wyczyść pamięć podręczną i uruchom ponownie',
+            viewConsole: 'Wyświetl konsolę debugowania',
+            debugConsole: 'Konsola debugowania',
             description:
                 '<muted-text>Użyj poniższych narzędzi, aby rozwiązać problemy z działaniem Expensify. Jeśli napotkasz jakiekolwiek problemy, prosimy <concierge-link>zgłosić błąd</concierge-link>.</muted-text>',
             confirmResetDescription: 'Wszystkie niewysłane szkice wiadomości zostaną utracone, ale reszta Twoich danych jest bezpieczna.',
@@ -2109,47 +1900,35 @@ const translations: TranslationDeepObject<typeof en> = {
             invalidateWithDelay: 'Unieważnij z opóźnieniem',
             leftHandNavCache: 'Pamięć podręczna lewego panelu nawigacji',
             clearleftHandNavCache: 'Wyczyść',
+            recordTroubleshootData: 'Rejestruj dane do rozwiązywania problemów',
             softKillTheApp: 'Miękko zamknij aplikację',
             kill: 'Zabij',
             sentryDebug: 'Debugowanie Sentry',
-            sentrySendDescription: 'Wysyłaj dane do Sentry',
             sentryDebugDescription: 'Rejestruj żądania Sentry w konsoli',
             sentryHighlightedSpanOps: 'Wyróżnione nazwy zakresów',
             sentryHighlightedSpanOpsPlaceholder: 'kliknięcie interfejsu, nawigacja, ładowanie interfejsu',
-            showBranchNameInTitle: 'Pokaż nazwę gałęzi w tytule przeglądarki',
+        },
+        debugConsole: {
+            saveLog: 'Zapisz dziennik',
+            shareLog: 'Udostępnij dziennik',
+            enterCommand: 'Wpisz polecenie',
+            execute: 'Wykonaj',
+            noLogsAvailable: 'Brak dostępnych dzienników',
+            logSizeTooLarge: (size: number) => `Rozmiar dziennika przekracza limit ${size} MB. Użyj proszę opcji „Zapisz dziennik”, aby zamiast tego pobrać plik dziennika.`,
+            logs: 'Dzienniki',
+            viewConsole: 'Wyświetl konsolę',
         },
         security: 'Bezpieczeństwo',
         signOut: 'Wyloguj się',
         restoreStashed: 'Przywróć zapisane logowanie',
         signOutConfirmationText: 'Utracisz wszystkie zmiany w trybie offline, jeśli się wylogujesz.',
         versionLetter: 'v',
-        readTheTermsAndPrivacy: `Przeczytaj <a href="${CONST.OLD_DOT_PUBLIC_URLS.TERMS_URL}">Warunki korzystania z usługi</a> i <a href="${CONST.OLD_DOT_PUBLIC_URLS.PRIVACY_URL}">Politykę prywatności</a>.`,
+        readTheTermsAndPrivacy: `<muted-text-micro>Przeczytaj <a href="${CONST.OLD_DOT_PUBLIC_URLS.TERMS_URL}">Warunki korzystania z usługi</a> i <a href="${CONST.OLD_DOT_PUBLIC_URLS.PRIVACY_URL}">Politykę prywatności</a>.</muted-text-micro>`,
         help: 'Pomoc',
         whatIsNew: 'Nowości',
         accountSettings: 'Ustawienia konta',
         account: 'Konto',
         general: 'Ogólne',
-        helpPage: {
-            title: 'Pomoc i wsparcie',
-            description: 'Jesteśmy tutaj, aby pomagać przez całą dobę.',
-            helpSite: 'Centrum pomocy',
-            helpSiteDescription: 'Artykuły, poradniki i więcej',
-            conciergeChat: 'Concierge',
-            conciergeChatDescription: 'Twój osobisty agent AI',
-            accountManager: 'Opiekun konta',
-            yourAccountManager: 'Twój opiekun klienta',
-            accountManagerDescription: 'Zadawaj pytania i uzyskaj pomoc dla klientów',
-            partnerManager: 'Menedżer ds. partnerstw',
-            yourPartnerManager: 'Twój opiekun partnerski',
-            partnerManagerDescription: 'Wzmocnij swoją współpracę i zwiększ liczbę poleceń',
-            guideDescription: 'Twój opiekun klienta',
-            approvedPartnerTeamTitle: 'Poznaj swój zespół partnerski Approved!',
-            approvedPartnerTeamDescription:
-                'Dedykowany zespół, który pomoże twojej firmie się rozwijać, szybciej wdrażać klientów i zapewni eksperckie wsparcie, kiedy tylko go potrzebujesz.',
-            accountExecutive: 'Opiekun klienta',
-            accountExecutiveDescription: 'Skutecznie skonfiguruj klientów',
-            moreResources: 'Więcej zasobów',
-        },
     },
     closeAccountPage: {
         closeAccount: 'Zamknij konto',
@@ -2223,12 +2002,10 @@ const translations: TranslationDeepObject<typeof en> = {
         lockAccount: 'Zablokuj konto',
         unlockAccount: 'Odblokuj konto',
         compromisedDescription:
-            'Zauważyłeś coś niepokojącego na swoim koncie? Zgłoszenie tego natychmiast zablokuje twoje konto, wstrzyma nowe transakcje Kartą Expensify i uniemożliwi wprowadzanie jakichkolwiek zmian na koncie.',
-        domainAdminsDescription: 'Dla administratorów domen: to również wstrzymuje całą aktywność Kart Expensify i działania administracyjne w twoich domenach.',
+            'Zauważyłeś coś niepokojącego na swoim koncie? Zgłoszenie tego natychmiast zablokuje Twoje konto, wstrzyma nowe transakcje kartą Expensify i uniemożliwi wprowadzanie zmian na koncie.',
+        domainAdminsDescription: 'Dla administratorów domeny: to również wstrzymuje całą aktywność kart Expensify oraz działania administracyjne w Twojej domenie (domenach).',
         areYouSure: 'Czy na pewno chcesz zablokować swoje konto Expensify?',
         onceLocked: 'Po zablokowaniu Twoje konto będzie ograniczone do czasu złożenia prośby o odblokowanie i przeprowadzenia kontroli bezpieczeństwa',
-        unlockTitle: 'Otrzymaliśmy Twoją prośbę',
-        unlockDescription: 'Przejrzymy konto, aby potwierdzić, że bezpiecznie je odblokować, i skontaktujemy się przez Concierge w razie pytań.',
     },
     failedToLockAccountPage: {
         failedToLockAccount: 'Nie udało się zablokować konta',
@@ -2241,13 +2018,6 @@ const translations: TranslationDeepObject<typeof en> = {
         chatToConciergeToUnlock: 'Porozmawiaj z Concierge, aby rozwiązać problemy z bezpieczeństwem i odblokować swoje konto.',
         chatWithConcierge: 'Czat z Concierge',
     },
-    deviceManagementPage: {
-        title: 'Zarządzanie urządzeniami',
-        description:
-            'Zarządzaj wszystkimi urządzeniami, na które zalogowałeś(-aś) się za pomocą konta Expensify. <a href="https://help.expensify.com/articles/new-expensify/settings/Manage-Logged-in-Devices">Dowiedz się więcej</a>.',
-        revoke: 'Cofnąć',
-        unknownDevice: 'Nieznane Urządzenie',
-    },
     twoFactorAuth: {
         headerTitle: 'Uwierzytelnianie dwuskładnikowe',
         twoFactorAuthEnabled: 'Włączono uwierzytelnianie dwuskładnikowe',
@@ -2259,17 +2029,17 @@ const translations: TranslationDeepObject<typeof en> = {
         disabled: 'Uwierzytelnianie dwuskładnikowe jest teraz wyłączone',
         noAuthenticatorApp: 'Nie będziesz już potrzebować aplikacji uwierzytelniającej, aby logować się do Expensify.',
         stepCodes: 'Kody odzyskiwania',
-        keepCodesSafe: 'Zachowaj te kody w bezpiecznym miejscu!',
+        keepCodesSafe: 'Zachowaj te kody odzyskiwania w bezpiecznym miejscu!',
         codesLoseAccess: dedent(`
-            Jeśli stracisz dostęp do aplikacji uwierzytelniającej i nie będziesz mieć tych kodów, zostaniesz zablokowany(-a) na swoim koncie.<br><br>
-            <strong>Uwaga</strong>: Włączenie 2FA wyloguje cię ze wszystkich innych sesji.
+            Jeśli utracisz dostęp do aplikacji uwierzytelniającej i nie będziesz mieć tych kodów, stracisz dostęp do swojego konta.
+
+            Uwaga: Włączenie uwierzytelniania dwuskładnikowego spowoduje wylogowanie Cię ze wszystkich innych aktywnych sesji.
         `),
         errorStepCodes: 'Skopiuj lub pobierz kody przed kontynuowaniem',
         stepVerify: 'Zweryfikuj',
         scanCode: 'Zeskanuj kod QR za pomocą swojego',
         authenticatorApp: 'aplikacja uwierzytelniająca',
         addKey: 'Lub dodaj ten tajny klucz do swojej aplikacji uwierzytelniającej:',
-        secretKey: 'tajny klucz',
         enterCode: 'Następnie wprowadź sześciocyfrowy kod wygenerowany przez aplikację uwierzytelniającą.',
         stepSuccess: 'Zakończono',
         enabled: 'Włączono uwierzytelnianie dwuskładnikowe',
@@ -2285,14 +2055,6 @@ const translations: TranslationDeepObject<typeof en> = {
         twoFactorAuthIsRequiredCompany: 'Twoetapowe uwierzytelnianie jest wymagane przez Twoją firmę.',
         twoFactorAuthCannotDisable: 'Nie można wyłączyć 2FA',
         twoFactorAuthRequired: 'Dla połączenia z Xero wymagana jest weryfikacja dwuetapowa (2FA) i nie można jej wyłączyć.',
-        replaceDevice: 'Zastąp urządzenie',
-        replaceDeviceTitle: 'Zastąp urządzenie dwuetapowej weryfikacji',
-        verifyOldDeviceTitle: 'Zweryfikuj stare urządzenie',
-        verifyOldDeviceDescription: 'Wpisz sześciocyfrowy kod z bieżącej aplikacji uwierzytelniającej, żeby potwierdzić, że masz do niej dostęp.',
-        verifyNewDeviceTitle: 'Skonfiguruj nowe urządzenie',
-        verifyNewDeviceDescription: 'Zeskanuj kod QR nowym urządzeniem, a następnie wpisz ten kod, aby zakończyć konfigurację.',
-        downloadCodes: 'Pobierz kody',
-        copyCodes: 'Skopiuj kody',
     },
     recoveryCodeForm: {
         error: {
@@ -2380,39 +2142,6 @@ const translations: TranslationDeepObject<typeof en> = {
             password: 'Wprowadź swoje hasło do Expensify',
         },
     },
-    personalCard: {
-        addPersonalCard: 'Dodaj kartę osobistą',
-        addCompanyCard: 'Dodaj kartę firmową',
-        lookingForCompanyCards: 'Potrzebujesz dodać karty firmowe?',
-        lookingForCompanyCardsDescription: 'Dodaj własne karty z ponad 10 000 banków na całym świecie.',
-        personalCardAdded: 'Karta osobista została dodana!',
-        personalCardAddedDescription: 'Gratulacje, rozpoczniemy importowanie transakcji z Twojej karty.',
-        isPersonalCard: 'Czy to karta osobista?',
-        thisIsPersonalCard: 'To jest karta osobista',
-        thisIsCompanyCard: 'To jest karta firmowa',
-        askAdmin: 'Zapytaj administratora.',
-        warningDescription: ({isAdmin}: {isAdmin?: boolean}) =>
-            `Jeśli tak, świetnie! Ale jeśli to karta <strong>firmowa</strong>, ${isAdmin ? 'przypisz ją z poziomu obszaru roboczego.' : 'poproś administratora o przypisanie jej z poziomu obszaru roboczego.'}`,
-        bankConnectionError: 'Problem z połączeniem z bankiem',
-        bankConnectionDescription: 'Spróbuj ponownie dodać karty. W przeciwnym razie możesz',
-        connectWithPlaid: 'połączyć się przez Plaid.',
-        fixCard: 'Napraw kartę',
-        brokenConnection: 'Połączenie Twojej karty jest przerwane.',
-        conciergeBrokenConnection: ({cardName, connectionLink}: ConciergeBrokenCardConnectionParams) =>
-            connectionLink
-                ? `Połączenie Twojej karty ${cardName} jest przerwane. <a href="${connectionLink}">Zaloguj się do swojego banku</a>, aby naprawić kartę.`
-                : `Połączenie Twojej karty ${cardName} jest przerwane. Zaloguj się do swojego banku, aby naprawić kartę.`,
-        addAdditionalCards: 'Dodaj kolejne karty',
-        upgradeDescription: 'Potrzebujesz dodać więcej kart? Utwórz obszar roboczy, aby dodać kolejne karty osobiste lub przypisać karty firmowe całemu zespołowi.',
-        onlyAvailableOnPlan: ({formattedPrice}: {formattedPrice: string}) =>
-            `<muted-text>Dostępne w planie Collect — <strong>${formattedPrice}</strong> za członka miesięcznie.</muted-text>`,
-        note: (subscriptionLink: string) =>
-            `<muted-text>Utwórz obszar roboczy, aby uzyskać dostęp do tej funkcji, lub <a href="${subscriptionLink}">dowiedz się więcej</a> o naszych planach i cenach.</muted-text>`,
-        workspaceCreated: 'Obszar roboczy utworzony',
-        newWorkspace: 'Utworzyłeś obszar roboczy!',
-        successMessage: ({subscriptionLink}: {subscriptionLink: string}) =>
-            `<centered-text>Możesz teraz dodać kolejne karty. <a href="${subscriptionLink}">Zobacz subskrypcję</a>, aby uzyskać szczegóły.</centered-text>`,
-    },
     walletPage: {
         balance: 'Saldo',
         paymentMethodsTitle: 'Metody płatności',
@@ -2440,9 +2169,8 @@ const translations: TranslationDeepObject<typeof en> = {
         enableWallet: 'Włącz portfel',
         addBankAccountToSendAndReceive: 'Dodaj konto bankowe, aby wysyłać lub odbierać płatności.',
         addDebitOrCreditCard: 'Dodaj kartę debetową lub kredytową',
-        cardInactive: 'Nieaktywne',
-        assignedCards: 'Karty',
-        assignedCardsDescription: 'Transakcje z przypisanych kart synchronizują się automatycznie.',
+        assignedCards: 'Przypisane karty',
+        assignedCardsDescription: 'Transakcje z tych kart synchronizują się automatycznie.',
         expensifyCard: 'Karta Expensify',
         walletActivationPending: 'Sprawdzamy Twoje informacje. Sprawdź ponownie za kilka minut!',
         walletActivationFailed: 'Niestety w tej chwili nie można włączyć Twojego portfela. Skontaktuj się z Concierge, aby uzyskać dalszą pomoc.',
@@ -2465,13 +2193,8 @@ const translations: TranslationDeepObject<typeof en> = {
         unshareBankAccount: 'Przestań udostępniać konto bankowe',
         unshareBankAccountDescription: 'Wszyscy poniżej mają dostęp do tego konta bankowego. Możesz w każdej chwili odebrać im dostęp. Nadal zrealizujemy wszystkie płatności będące w toku.',
         unshareBankAccountWarning: ({admin}: {admin?: string | null}) => `${admin} straci dostęp do tego firmowego konta bankowego. Nadal zrealizujemy wszystkie płatności w toku.`,
-        reachOutForHelp: 'Jest używany z Kartą Expensify. <concierge-link>Skontaktuj się z Concierge</concierge-link>, jeśli musisz przestać się nim dzielić.',
+        reachOutForHelp: 'Jest używany z kartą Expensify. <concierge-link>Skontaktuj się z Concierge</concierge-link>, jeśli musisz przestać się nim dzielić.',
         unshareErrorModalTitle: 'Nie można cofnąć udostępniania konta bankowego',
-        travelCVV: {
-            title: 'CVV podróży',
-            subtitle: 'Użyj tego podczas rezerwacji podróży',
-            description: 'Użyj tej karty do rezerwacji w Expensify Travel. Podczas płatności będzie wyświetlana jako “Travel Card”.',
-        },
         chaseAccountNumberDifferent: 'Dlaczego mój numer konta jest inny?',
     },
     cardPage: {
@@ -2480,15 +2203,16 @@ const translations: TranslationDeepObject<typeof en> = {
         availableSpend: 'Pozostały limit',
         smartLimit: {
             name: 'Inteligentny limit',
-            title: (formattedLimit: string) => `Możesz wydać do ${formattedLimit} tą kartą, a limit będzie się odnawiał w miarę zatwierdzania zgłoszonych wydatków.`,
+            title: ({formattedLimit}: ViolationsOverLimitParams) => `Możesz wydać do ${formattedLimit} tą kartą, a limit będzie się odnawiał w miarę zatwierdzania zgłoszonych wydatków.`,
         },
         fixedLimit: {
             name: 'Stały limit',
-            title: (formattedLimit: string) => `Możesz wydać do ${formattedLimit} na tej karcie, a następnie zostanie ona dezaktywowana.`,
+            title: ({formattedLimit}: ViolationsOverLimitParams) => `Możesz wydać do ${formattedLimit} na tej karcie, a następnie zostanie ona dezaktywowana.`,
         },
         monthlyLimit: {
             name: 'Limit miesięczny',
-            title: (formattedLimit: string) => `Możesz wydawać do ${formattedLimit} miesięcznie na tej karcie. Limit zostanie zresetowany pierwszego dnia każdego miesiąca kalendarzowego.`,
+            title: ({formattedLimit}: ViolationsOverLimitParams) =>
+                `Możesz wydawać do ${formattedLimit} miesięcznie na tej karcie. Limit zostanie zresetowany pierwszego dnia każdego miesiąca kalendarzowego.`,
         },
         virtualCardNumber: 'Numer karty wirtualnej',
         travelCardCvv: 'Kod CVV karty podróżnej',
@@ -2509,17 +2233,16 @@ const translations: TranslationDeepObject<typeof en> = {
             expiration: 'Wygaśnięcie',
             cvv: 'CVV',
             address: 'Adres',
-            reveal: 'Pokaż',
             revealDetails: 'Pokaż szczegóły',
             revealCvv: 'Pokaż kod CVV',
             copyCardNumber: 'Skopiuj numer karty',
-            copyCvv: 'Skopiuj CVV',
             updateAddress: 'Zaktualizuj adres',
         },
         cardAddedToWallet: ({platform}: {platform: 'Google' | 'Apple'}) => `Dodano do portfela ${platform}`,
         cardDetailsLoadingFailure: 'Wystąpił błąd podczas wczytywania szczegółów karty. Sprawdź swoje połączenie internetowe i spróbuj ponownie.',
         validateCardTitle: 'Upewnijmy się, że to Ty',
         enterMagicCode: (contactMethod: string) => `Wprowadź magiczny kod wysłany na ${contactMethod}, aby wyświetlić szczegóły karty. Powinien dotrzeć w ciągu minuty lub dwóch.`,
+        missingPrivateDetails: ({missingDetailsLink}: {missingDetailsLink: string}) => `Dodaj proszę <a href="${missingDetailsLink}">swoje dane osobowe</a>, a następnie spróbuj ponownie.`,
         unexpectedError: 'Wystąpił błąd podczas pobierania szczegółów Twojej karty Expensify. Spróbuj ponownie.',
         cardFraudAlert: {
             confirmButtonText: 'Tak, robię',
@@ -2540,42 +2263,6 @@ const translations: TranslationDeepObject<typeof en> = {
 
 ${amount} dla ${merchant} - ${date}`,
         },
-        setYourPin: 'Ustaw swój PIN.',
-        confirmYourPin: 'Potwierdź swój PIN.',
-        changeYourPin: 'Wprowadź nowy PIN do swojej karty.',
-        confirmYourChangedPin: 'Potwierdź swój nowy PIN.',
-        pinMustBeFourDigits: 'PIN musi mieć dokładnie 4 cyfry.',
-        invalidPin: 'Wybierz proszę bardziej bezpieczny PIN.',
-        pinMismatch: 'Kody PIN nie są takie same. Spróbuj ponownie.',
-        revealPin: 'Pokaż PIN',
-        hidePin: 'Ukryj PIN',
-        pin: 'PIN',
-        changePin: 'Zmień PIN',
-        pinChanged: 'PIN zmieniony!',
-        pinChangedHeader: 'PIN został zmieniony',
-        pinChangedDescription: 'Możesz już teraz używać swojego PIN-u.',
-        changePinAtATM: 'Zmień swój PIN w dowolnym bankomacie',
-        changePinAtATMDescription: 'To jest wymagane w twoim regionie. <concierge-link>Skontaktuj się z Concierge</concierge-link> jeśli masz jakieś pytania.',
-        freezeCard: 'Zamroź kartę',
-        unfreeze: 'Odmroź',
-        unfreezeCard: 'Odmroź kartę',
-        askToUnfreeze: 'Poproś o odmrożenie',
-        freezeDescription: 'Zamrożonej karty nie można używać do zakupów i transakcji. Możesz ją odmrozić w dowolnym momencie.',
-        unfreezeDescription: 'Odmrożenie tej karty ponownie umożliwi zakupy i transakcje. Kontynuuj tylko wtedy, gdy masz pewność, że korzystanie z karty jest bezpieczne.',
-        frozen: 'Zamrożona',
-        youFroze: ({date}: {date: string}) => `Zamroziłeś tę kartę ${date}.`,
-        frozenBy: ({person, date}: {person: string; date: string}) => `${person} zamroził(a) tę kartę ${date}.`,
-        frozenByAdminPrefix: ({date}: {date: string}) => `Ta karta została zamrożona ${date} przez `,
-        frozenByAdminNeedsUnfreezePrefix: 'Ta karta została zamrożona przez ',
-        frozenByAdminNeedsUnfreezeSuffix: '. Skontaktuj się z administratorem, aby ją odmrozić.',
-        frozenByAdminNeedsUnfreeze: ({person}: {person: string}) => `Ta karta została zamrożona przez ${person}. Skontaktuj się z administratorem, aby ją odmrozić.`,
-        spendRules: 'Zasady wydatków',
-        editSpendRules: 'Edytuj zasady wydatków',
-        cardUnblocked: 'Karta odblokowana!',
-        cardUnblockedDescription: 'Przy następnych zakupach możesz zostać poproszony(-a) o włożenie karty do czytnika.',
-        pinBlocked: 'Twoja karta została zablokowana z powodu błędnego wprowadzenia kodu PIN.',
-        unblock: 'Odblokuj',
-        unblockCard: 'Odblokuj kartę',
     },
     workflowsPage: {
         workflowTitle: 'Wydatki',
@@ -2587,14 +2274,9 @@ ${amount} dla ${merchant} - ${date}`,
         addApprovalsTitle: 'Zatwierdzenia',
         accessibilityLabel: ({members, approvers}: {members: string; approvers: string}) => `wydatki od ${members}, a zatwierdzającym jest ${approvers}`,
         addApprovalButton: 'Dodaj proces akceptacji',
-        editWorkflowAction: 'Edytuj',
-        addAgentAction: 'Dodaj agenta',
-        findWorkflow: 'Znajdź przepływ pracy',
         addApprovalTip: 'Domyślny proces pracy ma zastosowanie do wszystkich członków, chyba że istnieje bardziej szczegółowy proces pracy.',
         approver: 'Osoba zatwierdzająca',
         addApprovalsDescription: 'Wymagaj dodatkowej akceptacji przed autoryzacją płatności.',
-        automateApprovalsWithAgentsTitle: 'Automatyzuj zatwierdzanie z agentami',
-        automateApprovalsWithAgentsSubtitle: 'Dodaj agenta poniżej do przepływu pracy, aby zautomatyzować zatwierdzanie.',
         makeOrTrackPaymentsTitle: 'Płatności',
         makeOrTrackPaymentsDescription: 'Dodaj upoważnionego płatnika dla płatności dokonywanych w Expensify lub śledź płatności wykonywane gdzie indziej.',
         customApprovalWorkflowEnabled:
@@ -2639,15 +2321,7 @@ ${amount} dla ${merchant} - ${date}`,
             title: 'Brak członków do wyświetlenia',
             expensesFromSubtitle: 'Wszyscy członkowie tego obszaru roboczego już należą do istniejącego obiegu zatwierdzania.',
             approverSubtitle: 'Wszyscy zatwierdzający należą do istniejącego przepływu pracy.',
-            bulkApproverSubtitle: 'Żaden akceptujący nie spełnia kryteriów dla wybranych raportów.',
         },
-        configureViaHR: ({provider}: {provider: string}) => `Skonfiguruj przez ${provider}.`,
-        hrApprovalWorkflowLockedPrompt: ({provider}: {provider: string}) =>
-            `Zatwierdzanie jest zarządzane przez Twoją integrację z ${provider}. Aby zaktualizować swój proces zatwierdzania, przejdź do ustawień połączenia z ${provider}.`,
-        goToHRSettings: ({provider}: {provider: string}) => `Przejdź do ustawień ${provider}`,
-        approverFromProvider: ({provider}: {provider: string}) => `od ${provider}`,
-        finalApprover: 'Ostateczny akceptujący',
-        manager: 'Menedżer',
     },
     workflowsDelayedSubmissionPage: {
         autoReportingFrequencyErrorMessage: 'Nie udało się zmienić częstotliwości wysyłania. Spróbuj ponownie lub skontaktuj się z pomocą techniczną.',
@@ -2667,9 +2341,6 @@ ${amount} dla ${merchant} - ${date}`,
     workflowsExpensesFromPage: {
         title: 'Wydatki od',
         header: 'Gdy następujący członkowie przesyłają wydatki:',
-        memberAlreadyInWorkflowTitle: 'Członek jest już w procesie',
-        memberAlreadyInWorkflowPrompt: ({memberName, approverName}: {memberName: string; approverName: string}) =>
-            `${memberName} jest już w procesie zatwierdzania, który przesyła do ${approverName}. Dodanie go tutaj przeniesie go do tego procesu.`,
     },
     workflowsApproverPage: {
         genericErrorMessage: 'Nie udało się zmienić osoby zatwierdzającej. Spróbuj ponownie lub skontaktuj się z pomocą techniczną.',
@@ -2699,16 +2370,6 @@ ${amount} dla ${merchant} - ${date}`,
         admins: 'Administratorzy',
         payer: 'Płatnik',
         paymentAccount: 'Konto płatnicze',
-        shareBankAccount: {
-            shareTitle: 'Udostępnić dostęp do konta bankowego?',
-            shareDescription: ({admin}: {admin: string}) => `Musisz udostępnić dostęp do konta bankowego użytkownikowi ${admin}, aby uczynić go płatnikiem.`,
-            validationTitle: 'Konto bankowe oczekuje na walidację',
-            validationDescription: ({admin}: {admin: string}) =>
-                `Musisz <a href="#">zweryfikować to konto bankowe</a>. Po wykonaniu tej czynności możesz udostępnić dostęp do konta bankowego użytkownikowi ${admin}, aby uczynić go płatnikiem.`,
-            errorTitle: 'Nie można zmienić płatnika',
-            errorDescription: ({admin, owner}: {admin: string; owner: string}) =>
-                `${admin} nie ma dostępu do tego konta bankowego, więc nie możesz uczynić go płatnikiem. <a href="#">Porozmawiaj z ${owner}</a>, jeśli konto bankowe powinno być współdzielone.`,
-        },
     },
     reportFraudPage: {
         title: 'Zgłoś oszustwo kartą wirtualną',
@@ -2719,7 +2380,6 @@ ${amount} dla ${merchant} - ${date}`,
     reportFraudConfirmationPage: {
         title: 'Zgłoszono oszustwo kartowe',
         description: 'Trwale dezaktywowaliśmy Twoją dotychczasową kartę. Gdy wrócisz do szczegółów karty, będzie tam dostępna nowa wirtualna karta.',
-        descriptionCardNotReplaced: 'Twoja karta została trwale dezaktywowana. Skontaktuj się z administratorem, aby wydać nową kartę.',
         buttonText: 'Jasne, dzięki!',
     },
     activateCardPage: {
@@ -2729,7 +2389,7 @@ ${amount} dla ${merchant} - ${date}`,
         error: {
             thatDidNotMatch: 'To nie zgadza się z ostatnimi 4 cyframi Twojej karty. Spróbuj ponownie.',
             throttled:
-                'Zbyt wiele razy błędnie wpisałeś ostatnie 4 cyfry swojej Karty Expensify. Jeśli jesteś pewien, że numery są poprawne, skontaktuj się z Concierge, żeby rozwiązać problem. W przeciwnym razie spróbuj ponownie później.',
+                'Zbyt wiele razy błędnie wprowadziłeś(-aś) ostatnie 4 cyfry swojej karty Expensify. Jeśli jesteś pewien/pewna, że numery są poprawne, skontaktuj się z Concierge, aby rozwiązać problem. W przeciwnym razie spróbuj ponownie później.',
         },
     },
     getPhysicalCard: {
@@ -2754,7 +2414,7 @@ ${amount} dla ${merchant} - ${date}`,
         shipCard: 'Wyślij kartę',
     },
     transferAmountPage: {
-        transfer: (amount: string) => `Przelew${amount ? ` ${amount}` : ''}`,
+        transfer: ({amount}: TransferParams) => `Przelew${amount ? ` ${amount}` : ''}`,
         instant: 'Natychmiastowa (karta debetowa)',
         instantSummary: (rate: string, minAmount: string) => `Opłata ${rate}% (minimum ${minAmount})`,
         ach: '1–3 dni robocze (konto bankowe)',
@@ -2781,46 +2441,14 @@ ${amount} dla ${merchant} - ${date}`,
         defaultPaymentMethod: 'Domyślne',
         bankAccountLastFour: (lastFour: string) => `Konto bankowe • ${lastFour}`,
     },
-    agentsPage: {
-        title: 'Agenci',
-        subtitle: 'Twórz agentów do obsługi swojego przepływu pracy. Pomiń ręczną pracę i odzyskaj godziny w ciągu dnia.',
-        newAgent: 'Nowy agent',
-        emptyAgents: {title: 'Nie utworzono agentów', subtitle: 'Przestań robić wszystko ręcznie. Zamiast tego wydaj polecenia agentowi i zaoszczędź mnóstwo czasu.'},
-        error: {
-            genericAdd: 'Wystąpił problem podczas dodawania tego agenta',
-            genericUpdate: 'Wystąpił problem z aktualizacją tego agenta',
-            updateName: 'Wystąpił problem z aktualizacją imienia i nazwiska tego agenta',
-            updatePrompt: 'Wystąpił problem z aktualizacją instrukcji tego agenta',
-            updateAvatar: 'Wystąpił problem z aktualizacją awatara tego agenta',
-        },
-    },
-    addAgentPage: {
-        title: 'Nowy agent',
-        agentName: 'Nazwa agenta',
-        instructions: 'Napisz niestandardowe instrukcje',
-        createAgent: 'Utwórz agenta',
-        editAvatar: 'Zmień awatar',
-        defaultAgentName: (displayName: string) => `Agent ${displayName}`,
-        defaultPrompt:
-            'Odrzucaj wydatki związane z hazardem, filmami lub innymi oczywistymi celami niezwiązanymi z działalnością biznesową.\n\nPrzypominaj użytkownikowi, aby zawsze dołączał zdjęcie paragonu, na którym wysokość napiwku jest wyraźnie widoczna.\n\nZatwierdź raport, jeśli jest bardzo podobny do wcześniejszych raportów tego samego użytkownika.\n\nOdrzucaj raporty zawierające więcej niż 500 USD wydatków na podróże.',
-    },
-    editAgentPage: {
-        title: 'Edytuj agenta',
-        agentName: 'Nazwa agenta',
-        instructions: 'Napisz własne instrukcje',
-        chatWithAgent: 'Czat z agentem',
-        copilotIntoAccount: 'Copilot na konto',
-        deleteAgent: 'Usuń agenta',
-        deleteAgentTitle: 'Usunąć agenta?',
-        deleteAgentMessage: 'Czy na pewno chcesz usunąć tego agenta? Tej akcji nie można cofnąć.',
-    },
-    editAgentAvatarPage: {title: 'Edytuj awatar'},
-    editAgentNamePage: {title: 'Nazwa agenta'},
-    editAgentPromptPage: {title: 'Napisz własne instrukcje', error: {emptyPrompt: 'Wprowadź instrukcje dla swojego agenta.'}},
     expenseRulesPage: {
         title: 'Reguły wydatków',
+        subtitle: 'Te zasady będą miały zastosowanie do Twoich wydatków. Jeśli wyślesz je do przestrzeni roboczej, zasady tej przestrzeni mogą je zastąpić.',
         findRule: 'Znajdź regułę',
-        emptyRules: {title: 'Nie ma jeszcze żadnych zasad', subtitle: 'Dodaj regułę, aby zautomatyzować raportowanie wydatków.'},
+        emptyRules: {
+            title: 'Nie utworzono żadnych reguł',
+            subtitle: 'Dodaj regułę, aby zautomatyzować raportowanie wydatków.',
+        },
         changes: {
             billableUpdate: (value: boolean) => `Zaktualizuj wydatek ${value ? 'rozliczalny' : 'niepodlegające fakturowaniu'}`,
             categoryUpdate: (value: string) => `Zaktualizuj kategorię na „${value}”`,
@@ -2861,7 +2489,6 @@ ${amount} dla ${merchant} - ${date}`,
             deleteSinglePrompt: 'Czy na pewno chcesz usunąć tę regułę?',
             deleteMultiplePrompt: 'Czy na pewno chcesz usunąć te reguły?',
         },
-        subtitle: 'Te zasady będą miały zastosowanie do Twoich wydatków.',
     },
     preferencesPage: {
         appSection: {
@@ -2889,12 +2516,11 @@ ${amount} dla ${merchant} - ${date}`,
         },
     },
     reportDetailsPage: {
-        inWorkspace: (policyName: string) => `w ${policyName}`,
+        inWorkspace: ({policyName}: ReportPolicyNameParams) => `w ${policyName}`,
         generatingPDF: 'Wygeneruj PDF',
         waitForPDF: 'Poczekaj, aż wygenerujemy plik PDF.',
         errorPDF: 'Wystąpił błąd podczas próby wygenerowania Twojego pliku PDF',
         successPDF: 'Twój plik PDF został wygenerowany! Jeśli nie pobrał się automatycznie, użyj przycisku poniżej.',
-        goToRoom: 'Przejdź do pokoju',
     },
     reportDescriptionPage: {
         roomDescription: 'Opis pokoju',
@@ -2904,7 +2530,7 @@ ${amount} dla ${merchant} - ${date}`,
     groupChat: {
         lastMemberTitle: 'Uwaga!',
         lastMemberWarning: 'Ponieważ jesteś ostatnią osobą w tym czacie, wyjście spowoduje, że stanie się on niedostępny dla wszystkich członków. Czy na pewno chcesz opuścić czat?',
-        defaultReportName: (displayName: string) => `Czat grupowy ${displayName}`,
+        defaultReportName: ({displayName}: ReportArchiveReasonsClosedParams) => `Czat grupowy ${displayName}`,
     },
     languagePage: {
         language: 'Język',
@@ -2923,25 +2549,19 @@ ${amount} dla ${merchant} - ${date}`,
                 label: 'Użyj ustawień urządzenia',
             },
         },
-        highContrastMode: 'Tryb wysokiego kontrastu',
-        enableHighContrast: 'Włącz wysoki kontrast',
-        disableHighContrast: 'Wyłącz wysoki kontrast',
         chooseThemeBelowOrSync: 'Wybierz motyw poniżej lub zsynchronizuj z ustawieniami urządzenia.',
     },
     termsOfUse: {
         terms: `<muted-text-xs>Logując się, wyrażasz zgodę na <a href="${CONST.OLD_DOT_PUBLIC_URLS.TERMS_URL}">Warunki korzystania z usługi</a> oraz <a href="${CONST.OLD_DOT_PUBLIC_URLS.PRIVACY_URL}">Prywatność</a>.</muted-text-xs>`,
-        license: `Usługę przekazu pieniężnego świadczy ${CONST.WALLET.PROGRAM_ISSUERS.EXPENSIFY_PAYMENTS} (NMLS ID:2017010) na podstawie swoich <a href="${CONST.OLD_DOT_PUBLIC_URLS.LICENSES_URL}">licencji</a>.`,
+        license: `<muted-text-xs>Przekazy pieniężne są świadczone przez ${CONST.WALLET.PROGRAM_ISSUERS.EXPENSIFY_PAYMENTS} (NMLS ID:2017010) na podstawie jego <a href="${CONST.OLD_DOT_PUBLIC_URLS.LICENSES_URL}">licencji</a>.</muted-text-xs>`,
     },
     validateCodeForm: {
         magicCodeNotReceived: 'Nie otrzymano magicznego kodu?',
-        avoidScamsMessage: '<strong>Unikaj oszustw. Nie udostępniaj nikomu swojego kodu.</strong> Nasz zespół nigdy nie zadzwoni, nie wyśle SMS-a ani e-maila z prośbą o ten kod.',
         enterAuthenticatorCode: 'Wprowadź swój kod z aplikacji uwierzytelniającej',
         enterRecoveryCode: 'Wprowadź swój kod odzyskiwania',
         requiredWhen2FAEnabled: 'Wymagane, gdy włączone jest 2FA',
         requestNewCode: ({timeRemaining}: {timeRemaining: string}) => `Poproś o nowy kod za <a>${timeRemaining}</a>`,
         requestNewCodeAfterErrorOccurred: 'Poproś o nowy kod',
-        timeRemainingAnnouncement: ({timeRemaining}) => `Pozostały czas: ${timeRemaining} ${timeRemaining === 1 ? 'sekunda' : 'sekund'}`,
-        timeExpiredAnnouncement: 'Czas minął',
         error: {
             pleaseFillMagicCode: 'Wprowadź swój magiczny kod',
             incorrectMagicCode: 'Nieprawidłowy lub niepoprawny kod magiczny. Spróbuj ponownie lub poproś o nowy kod.',
@@ -2972,7 +2592,6 @@ ${amount} dla ${merchant} - ${date}`,
         phoneOrEmail: 'Telefon lub e-mail',
         error: {
             invalidFormatEmailLogin: 'Wprowadzony adres e-mail jest nieprawidłowy. Popraw jego format i spróbuj ponownie.',
-            agentSignInBlocked: 'Na konta agenta nie można logować się bezpośrednio. Żeby korzystać z agenta, zaloguj się na własne konto i uzyskaj do niego dostęp przez Copilota.',
         },
         cannotGetAccountDetails: 'Nie można pobrać szczegółów konta. Spróbuj zalogować się ponownie.',
         loginForm: 'Formularz logowania',
@@ -2989,36 +2608,25 @@ ${amount} dla ${merchant} - ${date}`,
         },
         getStarted: 'Rozpocznij',
         whatsYourName: 'Jak masz na imię?',
-        peopleYouMayKnow: 'Sprawdź, czy twój zespół jest w Expensify',
-        workspaceYouMayJoin: (domain: string, email: string) => `Wpisz kod wysłany na adres ${email}, żeby sprawdzić, czy ktoś z ${domain} ma przestrzeń roboczą, do której możesz dołączyć.`,
+        peopleYouMayKnow: 'Osoby, które możesz znać, są już tutaj! Zweryfikuj swój e-mail, aby do nich dołączyć.',
+        workspaceYouMayJoin: ({domain, email}: WorkspaceYouMayJoin) => `Ktoś z domeny ${domain} utworzył już przestrzeń roboczą. Wprowadź magiczny kod wysłany na adres ${email}.`,
         joinAWorkspace: 'Dołącz do przestrzeni roboczej',
-        listOfWorkspaces: 'Oto lista przestrzeni roboczych, do których możesz dołączyć.',
-        skipForNow: 'Pomiń na razie',
-        workspaceMemberList: (employeeCount: number, policyOwner: string) => `${employeeCount} członek${employeeCount > 1 ? 's' : ''} • ${policyOwner}`,
+        listOfWorkspaces: 'Oto lista przestrzeni roboczych, do których możesz dołączyć. Nie martw się, zawsze możesz dołączyć do nich później, jeśli wolisz.',
+        workspaceMemberList: ({employeeCount, policyOwner}: WorkspaceMemberList) => `${employeeCount} członek${employeeCount > 1 ? 's' : ''} • ${policyOwner}`,
         whereYouWork: 'Gdzie pracujesz?',
         errorSelection: 'Wybierz opcję, aby przejść dalej',
         purpose: {
             title: 'Co chcesz dzisiaj zrobić?',
             errorContinue: 'Naciśnij „Kontynuuj”, aby się skonfigurować',
             errorBackButton: 'Dokończ pytania konfiguracyjne, aby zacząć korzystać z aplikacji',
-            [CONST.ONBOARDING_CHOICES.EMPLOYER]: 'Zgłoś wydatki pracodawcy',
+            [CONST.ONBOARDING_CHOICES.EMPLOYER]: 'Otrzymuj zwrot od pracodawcy',
             [CONST.ONBOARDING_CHOICES.MANAGE_TEAM]: 'Zarządzaj wydatkami mojego zespołu',
-            [CONST.ONBOARDING_CHOICES.TRACK_BUSINESS]: 'Śledź wydatki firmowe',
-            [CONST.ONBOARDING_CHOICES.TRACK_PERSONAL]: 'Organizuj swoje wydatki osobiste',
+            [CONST.ONBOARDING_CHOICES.PERSONAL_SPEND]: 'Śledź i planuj wydatki',
+            [CONST.ONBOARDING_CHOICES.CHAT_SPLIT]: 'Czatuj i dziel wydatki ze znajomymi',
             [CONST.ONBOARDING_CHOICES.LOOKING_AROUND]: 'Coś innego',
         },
-        personalTrackGoal: {
-            title: 'Co chcesz śledzić?',
-            [CONST.ONBOARDING_PERSONAL_TRACK_GOALS.INVESTMENT_TRACKING]: 'Koszty związane z nieruchomością inwestycyjną',
-            [CONST.ONBOARDING_PERSONAL_TRACK_GOALS.HOUSEHOLD_TRACKING]: 'Wydatki domowe',
-            [CONST.ONBOARDING_PERSONAL_TRACK_GOALS.SIDEPROJECT_TRACKING]: 'Wydatki na projekty poboczne',
-            [CONST.ONBOARDING_PERSONAL_TRACK_GOALS.SOMETHING_ELSE]: 'Coś innego',
-            somethingElsePlaceholder: 'Co śledzisz?',
-        },
         employees: {
             title: 'Ilu masz pracowników?',
-            [CONST.ONBOARDING_COMPANY_SIZE.MICRO_SMALL]: '1–4 pracowników',
-            [CONST.ONBOARDING_COMPANY_SIZE.MICRO_MEDIUM]: '5–10 pracowników',
             [CONST.ONBOARDING_COMPANY_SIZE.MICRO]: '1–10 pracowników',
             [CONST.ONBOARDING_COMPANY_SIZE.SMALL]: '11–50 pracowników',
             [CONST.ONBOARDING_COMPANY_SIZE.MEDIUM_SMALL]: '51–100 pracowników',
@@ -3049,18 +2657,16 @@ ${amount} dla ${merchant} - ${date}`,
         },
         workEmailValidation: {
             title: 'Zweryfikuj służbowy adres e-mail',
-            magicCodeSent: (workEmail: string | undefined) => `Wprowadź magiczny kod wysłany na adres ${workEmail}. Powinien dotrzeć w ciągu minuty lub dwóch.`,
+            magicCodeSent: ({workEmail}: WorkEmailResendCodeParams) => `Wprowadź magiczny kod wysłany na adres ${workEmail}. Powinien dotrzeć w ciągu minuty lub dwóch.`,
         },
         workEmailValidationError: {
             publicEmail: 'Wpisz poprawny służbowy adres e‑mail z prywatnej domeny, np. mitch@company.com',
-            sameAsSignupEmail: 'Podaj inny adres e-mail niż ten, którego użyłeś przy rejestracji',
             offline: 'Nie mogliśmy dodać Twojego służbowego adresu e‑mail, ponieważ wydajesz się być offline',
         },
         mergeBlockScreen: {
             title: 'Nie udało się dodać służbowego adresu e-mail',
-            subtitle: (workEmail: string | undefined) => `Nie udało się dodać ${workEmail}. Spróbuj ponownie później w Ustawieniach lub porozmawiaj z Concierge, aby uzyskać pomoc.`,
-            workAccountClosedSubtitle:
-                'Konto służbowe powiązane z tym adresem e‑mail jest zamknięte. Skontaktuj się z administratorem w swojej firmie, żeby je ponownie aktywować, albo zarejestruj się przy użyciu innego adresu e‑mail.',
+            subtitle: ({workEmail}: WorkEmailMergingBlockedParams) =>
+                `Nie udało się dodać ${workEmail}. Spróbuj ponownie później w Ustawieniach lub porozmawiaj z Concierge, aby uzyskać pomoc.`,
         },
         tasks: {
             testDriveAdminTask: {
@@ -3091,7 +2697,7 @@ ${amount} dla ${merchant} - ${date}`,
             },
             createTestDriveAdminWorkspaceTask: {
                 title: ({workspaceConfirmationLink}) => `[Utwórz](${workspaceConfirmationLink}) przestrzeń roboczą`,
-                description: 'Utwórz przestrzeń roboczą i skonfiguruj ustawienia z pomocą swojego opiekuna klienta!',
+                description: 'Utwórz przestrzeń roboczą i skonfiguruj ustawienia z pomocą swojego specjalisty ds. konfiguracji!',
             },
             createWorkspaceTask: {
                 title: ({workspaceSettingsLink}) => `Utwórz [workspace](${workspaceSettingsLink})`,
@@ -3107,10 +2713,10 @@ ${amount} dla ${merchant} - ${date}`,
                 title: ({workspaceCategoriesLink}) => `Skonfiguruj [kategorie](${workspaceCategoriesLink})`,
                 description: ({workspaceCategoriesLink}) =>
                     dedent(`
-                        *Skonfiguruj kategorie*, aby Twój zespół mógł kategoryzować wydatki i ułatwić raportowanie.
+                        *Skonfiguruj kategorie*, aby Twój zespół mógł kategoryzować wydatki dla łatwiejszego raportowania.
 
                         1. Kliknij *Workspaces*.
-                        2. Wybierz swoją przestrzeń roboczą.
+                        2. Wybierz swoje środowisko pracy.
                         3. Kliknij *Categories*.
                         4. Wyłącz wszystkie kategorie, których nie potrzebujesz.
                         5. Dodaj własne kategorie w prawym górnym rogu.
@@ -3123,7 +2729,7 @@ ${amount} dla ${merchant} - ${date}`,
                 description: dedent(`
                     *Zgłoś wydatek*, wprowadzając kwotę lub skanując paragon.
 
-                    1. Kliknij przycisk *+*.
+                    1. Kliknij przycisk ${CONST.CUSTOM_EMOJIS.GLOBAL_CREATE}.
                     2. Wybierz *Utwórz wydatek*.
                     3. Wprowadź kwotę lub zeskanuj paragon.
                     4. Dodaj adres e-mail lub numer telefonu swojego przełożonego.
@@ -3137,7 +2743,7 @@ ${amount} dla ${merchant} - ${date}`,
                 description: dedent(`
                     *Zgłoś wydatek*, wpisując kwotę lub skanując paragon.
 
-                    1. Kliknij przycisk *+*.
+                    1. Kliknij przycisk ${CONST.CUSTOM_EMOJIS.GLOBAL_CREATE}.
                     2. Wybierz *Utwórz wydatek*.
                     3. Wpisz kwotę lub zeskanuj paragon.
                     4. Potwierdź szczegóły.
@@ -3151,7 +2757,7 @@ ${amount} dla ${merchant} - ${date}`,
                 description: dedent(`
                     *Śledź wydatek* w dowolnej walucie, niezależnie od tego, czy masz paragon, czy nie.
 
-                    1. Kliknij przycisk *+*.
+                    1. Kliknij przycisk ${CONST.CUSTOM_EMOJIS.GLOBAL_CREATE}.
                     2. Wybierz *Utwórz wydatek*.
                     3. Wprowadź kwotę lub zeskanuj paragon.
                     4. Wybierz swoją *przestrzeń osobistą*.
@@ -3173,8 +2779,13 @@ ${amount} dla ${merchant} - ${date}`,
                         4. Znajdź ${integrationName}.
                         5. Kliknij *Connect*.
 
-                        [Przejdź do księgowości](${workspaceAccountingLink}).
-                    `),
+${
+    integrationName && CONST.connectionsVideoPaths[integrationName]
+        ? `[Przejdź do księgowości](${workspaceAccountingLink}).
+
+                        ![Połącz z ${integrationName}](${CONST.CLOUDFRONT_URL}/${CONST.connectionsVideoPaths[integrationName]})`
+        : `[Przejdź do księgowości](${workspaceAccountingLink}).`
+}`),
             },
             connectCorporateCardTask: {
                 title: ({corporateCardLink}) => `Połącz [swoje karty firmowe](${corporateCardLink})`,
@@ -3195,8 +2806,8 @@ ${amount} dla ${merchant} - ${date}`,
                     dedent(`
                         *Zaproś swój zespół* do Expensify, aby mógł zacząć śledzić wydatki już dziś.
 
-                        1. Kliknij *Workspaces*.
-                        2. Wybierz swoją przestrzeń roboczą.
+                        1. Kliknij *Workspace*.
+                        2. Wybierz swój workspace.
                         3. Kliknij *Members* > *Invite member*.
                         4. Wpisz adresy e-mail lub numery telefonów.
                         5. Dodaj własną wiadomość z zaproszeniem, jeśli chcesz!
@@ -3216,16 +2827,16 @@ ${amount} dla ${merchant} - ${date}`,
                 title: ({workspaceTagsLink}) => `Skonfiguruj [tagi](${workspaceTagsLink})`,
                 description: ({workspaceMoreFeaturesLink}) =>
                     dedent(`
-                        Używaj tagów, aby dodać dodatkowe szczegóły wydatków, takie jak projekty, klienci, lokalizacje i działy. Jeśli potrzebujesz wielu poziomów tagów, możesz przejść na plan Control.
+                        Użyj tagów, aby dodać dodatkowe szczegóły wydatków, takie jak projekty, klienci, lokalizacje i działy. Jeśli potrzebujesz wielu poziomów tagów, możesz uaktualnić do planu Control.
 
                         1. Kliknij *Workspaces*.
-                        2. Wybierz swoją przestrzeń roboczą.
+                        2. Wybierz swój workspace.
                         3. Kliknij *More features*.
                         4. Włącz *Tags*.
-                        5. Przejdź do *Tags* w edytorze przestrzeni roboczej.
-                        6. Kliknij *+ Add tag*, aby utworzyć własne.
+                        5. Przejdź do *Tags* w edytorze workspace’u.
+                        6. Kliknij *+ Add tag*, aby utworzyć własny.
 
-                        [Przejdź do opcji „More features”](${workspaceMoreFeaturesLink}).
+                        [Przejdź do dodatkowych funkcji](${workspaceMoreFeaturesLink}).
 
                     `),
             },
@@ -3248,7 +2859,7 @@ ${amount} dla ${merchant} - ${date}`,
                 description: dedent(`
                     *Rozpocznij czat* z dowolną osobą, używając jej adresu e-mail lub numeru telefonu.
 
-                    1. Kliknij przycisk *+*.
+                    1. Kliknij przycisk ${CONST.CUSTOM_EMOJIS.GLOBAL_CREATE}.
                     2. Wybierz *Rozpocznij czat*.
                     3. Wpisz adres e-mail lub numer telefonu.
 
@@ -3262,7 +2873,7 @@ ${amount} dla ${merchant} - ${date}`,
                 description: dedent(`
                     *Podziel wydatki* z jedną lub większą liczbą osób.
 
-                    1. Kliknij przycisk *+*.
+                    1. Kliknij przycisk ${CONST.CUSTOM_EMOJIS.GLOBAL_CREATE}.
                     2. Wybierz *Rozpocznij czat*.
                     3. Wpisz adresy e‑mail lub numery telefonów.
                     4. Kliknij szary przycisk *+* na czacie > *Podziel wydatek*.
@@ -3286,7 +2897,7 @@ ${amount} dla ${merchant} - ${date}`,
                 description: dedent(`
                     Oto jak utworzyć raport:
 
-                    1. Kliknij przycisk *+*.
+                    1. Kliknij przycisk ${CONST.CUSTOM_EMOJIS.GLOBAL_CREATE}.
                     2. Wybierz *Utwórz raport*.
                     3. Kliknij *Dodaj wydatek*.
                     4. Dodaj swój pierwszy wydatek.
@@ -3309,15 +2920,18 @@ ${amount} dla ${merchant} - ${date}`,
                 isOnboardingFlow
                     ? dedent(`
                         # Twój bezpłatny okres próbny właśnie się rozpoczął! Skonfigurujmy wszystko.
-                        👋 Cześć, jestem Twoim opiekunem konta w Expensify. Utworzyłem już przestrzeń roboczą, która pomoże Ci zarządzać paragonami i wydatkami Twojego zespołu. Aby jak najlepiej wykorzystać 30-dniowy bezpłatny okres próbny, po prostu wykonaj poniższe kroki konfiguracji!
+                        👋 Cześć, jestem Twoim specjalistą ds. konfiguracji Expensify. Utworzyłem już przestrzeń roboczą, aby pomóc w zarządzaniu paragonami i wydatkami Twojego zespołu. Aby jak najlepiej wykorzystać 30-dniowy bezpłatny okres próbny, po prostu wykonaj poniższe pozostałe kroki konfiguracji!
                     `)
                     : dedent(`
-                        # Twój bezpłatny okres próbny się rozpoczął! Skonfigurujmy wszystko.
-                        👋 Cześć, jestem twoim opiekunem konta Expensify. Teraz, gdy utworzyłeś przestrzeń roboczą, jak najlepiej wykorzystaj swój 30-dniowy bezpłatny okres próbny, wykonując poniższe kroki!
+                        # Twój bezpłatny okres próbny właśnie się rozpoczął! Skonfigurujmy wszystko.
+                        👋 Cześć, jestem Twoim specjalistą ds. konfiguracji Expensify. Skoro utworzyłeś(-aś) już przestrzeń roboczą, wykorzystaj w pełni swój 30-dniowy bezpłatny okres próbny, wykonując poniższe kroki!
                     `),
-            onboardingTrackWorkspaceMessage: 'Aby jak najlepiej wykorzystać bezpłatny 30‑dniowy okres próbny, wykonaj pozostałe kroki poniżej:',
+            onboardingTrackWorkspaceMessage:
+                '# Skonfigurujmy wszystko\n👋 Cześć, jestem Twoim specjalistą ds. konfiguracji Expensify. Utworzyłem już przestrzeń roboczą, aby pomóc Ci zarządzać paragonami i wydatkami. Aby jak najlepiej wykorzystać 30-dniowy bezpłatny okres próbny, po prostu wykonaj pozostałe kroki konfiguracji poniżej!',
             onboardingChatSplitMessage: 'Dziel się rachunkami ze znajomymi tak łatwo, jak wysyłasz wiadomość. Oto jak to działa.',
             onboardingAdminMessage: 'Dowiedz się, jak zarządzać przestrzenią roboczą swojego zespołu jako administrator i rozliczać własne wydatki.',
+            onboardingLookingAroundMessage:
+                'Expensify jest najbardziej znane z obsługi wydatków, podróży i kart firmowych, ale robimy o wiele więcej. Daj znać, czym jesteś zainteresowany/zainteresowana, a pomogę Ci zacząć.',
             onboardingTestDriveReceiverMessage: '*Masz 3 miesiące za darmo! Zacznij poniżej.*',
         },
         workspace: {
@@ -3328,7 +2942,7 @@ ${amount} dla ${merchant} - ${date}`,
                 descriptionTwo: 'Kategoryzuj i taguj wydatki',
                 descriptionThree: 'Twórz i udostępniaj raporty',
             },
-            price: (price?: string) => `Wypróbuj za darmo przez 30 dni, a potem przejdź na wyższy plan za jedyne <strong>${price ?? '5 USD'}/użytkownika/miesiąc</strong>.`,
+            price: 'Wypróbuj za darmo przez 30 dni, a potem przejdź na wyższy plan za jedyne <strong>5 USD/użytkownika/miesiąc</strong>.',
             createWorkspace: 'Utwórz przestrzeń roboczą',
         },
         confirmWorkspace: {
@@ -3339,8 +2953,6 @@ ${amount} dla ${merchant} - ${date}`,
             title: 'Zaproś członków',
             subtitle: 'Dodaj swój zespół lub zaproś księgowego. Im więcej, tym weselej!',
         },
-        workEmail2FAError: 'To logowanie jest istniejącym kontem z włączonym uwierzytelnianiem dwuskładnikowym (2FA).',
-        singleSignOnError: 'To logowanie jest powiązane z istniejącym kontem z włączonym SSO/SAML.',
     },
     featureTraining: {
         doNotShowAgain: 'Nie pokazuj mi tego ponownie',
@@ -3360,7 +2972,6 @@ ${amount} dla ${merchant} - ${date}`,
         enterPhoneNumber: 'Jaki jest Twój numer telefonu?',
         personalDetails: 'Dane osobiste',
         privateDataMessage: 'Te dane są używane do podróży i płatności. Nigdy nie są wyświetlane w Twoim publicznym profilu.',
-        basicDetails: 'Podstawowe dane',
         legalName: 'Imię i nazwisko (pełne)',
         legalFirstName: 'Imię (zgodnie z dokumentem tożsamości)',
         legalLastName: 'Nazwisko zgodne z dokumentami',
@@ -3369,18 +2980,18 @@ ${amount} dla ${merchant} - ${date}`,
             dateShouldBeBefore: (dateString: string) => `Data powinna być wcześniejsza niż ${dateString}`,
             dateShouldBeAfter: (dateString: string) => `Data powinna być po ${dateString}`,
             hasInvalidCharacter: 'Nazwa może zawierać tylko znaki łacińskie',
-            cannotIncludeCommaOrSemicolon: 'Nazwa nie może zawierać przecinka ani średnika',
             incorrectZipFormat: (zipFormat?: string) => `Nieprawidłowy format kodu pocztowego${zipFormat ? `Akceptowalny format: ${zipFormat}` : ''}`,
             invalidPhoneNumber: `Upewnij się, że numer telefonu jest prawidłowy (np. ${CONST.EXAMPLE_PHONE_NUMBER})`,
         },
     },
     resendValidationForm: {
         linkHasBeenResent: 'Link został wysłany ponownie',
-        weSentYouMagicSignInLink: (login: string, loginType: string) => `Wysłałem(-am) magiczny link logowania na adres ${login}. Sprawdź swój ${loginType}, aby się zalogować.`,
+        weSentYouMagicSignInLink: ({login, loginType}: WeSentYouMagicSignInLinkParams) =>
+            `Wysłałem(-am) magiczny link logowania na adres ${login}. Sprawdź swój ${loginType}, aby się zalogować.`,
         resendLink: 'Wyślij ponownie link',
     },
     unlinkLoginForm: {
-        toValidateLogin: (primaryLogin: string, secondaryLogin: string) => `Aby zweryfikować ${secondaryLogin}, wyślij ponownie magiczny kod z Ustawień konta ${primaryLogin}.`,
+        toValidateLogin: ({primaryLogin, secondaryLogin}: ToValidateLoginParams) => `Aby zweryfikować ${secondaryLogin}, wyślij ponownie magiczny kod z Ustawień konta ${primaryLogin}.`,
         noLongerHaveAccess: (primaryLogin: string) => `Jeśli nie masz już dostępu do ${primaryLogin}, odłącz swoje konta.`,
         unlink: 'Odłącz',
         linkSent: 'Link wysłany!',
@@ -3437,12 +3048,14 @@ ${amount} dla ${merchant} - ${date}`,
     },
     welcomeSignUpForm: {
         join: 'Dołącz',
-        marketingSMSConsent: 'Wyrażam zgodę na otrzymywanie marketingowych wiadomości SMS od Expensify',
     },
     detailsPage: {
         localTime: 'Czas lokalny',
     },
-    newChatPage: {startGroup: 'Rozpocznij grupę', addToGroup: 'Dodaj do grupy', addUserToGroup: (username: string) => `Dodaj ${username} do grupy`},
+    newChatPage: {
+        startGroup: 'Rozpocznij grupę',
+        addToGroup: 'Dodaj do grupy',
+    },
     yearPickerPage: {
         year: 'Rok',
         selectYear: 'Wybierz rok',
@@ -3485,18 +3098,17 @@ ${amount} dla ${merchant} - ${date}`,
             custom: 'Niestandardowe',
         },
         untilTomorrow: 'Do jutra',
-        untilTime: (time: string) => `Do ${time}`,
+        untilTime: ({time}: UntilTimeParams) => `Do ${time}`,
         date: 'Data',
         time: 'Czas',
         clearAfter: 'Wyczyść po',
         whenClearStatus: 'Kiedy powinniśmy wyczyścić Twój status?',
+        vacationDelegate: 'Zastępca urlopowy',
         setVacationDelegate: `Ustaw zastępcę na czas urlopu, aby zatwierdzał raporty w Twoim imieniu, gdy jesteś poza biurem.`,
-        cannotSetVacationDelegate: `Nie możesz ustawić delegata urlopowego, ponieważ obecnie jesteś delegatem dla następujących członków:`,
-        addVacationDelegate: 'Dodaj zastępcę urlopowego',
         vacationDelegateError: 'Wystąpił błąd podczas aktualizowania Twojego zastępcy urlopowego.',
-        asVacationDelegate: (nameOrEmail: string) => `jako osoba zastępująca ${nameOrEmail} podczas urlopu`,
-        toAsVacationDelegate: (submittedToName: string, vacationDelegateName: string) => `do ${submittedToName} jako zastępca urlopowy dla ${vacationDelegateName}`,
-        vacationDelegateWarning: (nameOrEmail: string) =>
+        asVacationDelegate: ({nameOrEmail}: VacationDelegateParams) => `jako osoba zastępująca ${nameOrEmail} podczas urlopu`,
+        toAsVacationDelegate: ({submittedToName, vacationDelegateName}: SubmittedToVacationDelegateParams) => `do ${submittedToName} jako zastępca urlopowy dla ${vacationDelegateName}`,
+        vacationDelegateWarning: ({nameOrEmail}: VacationDelegateParams) =>
             `Przydzielasz ${nameOrEmail} jako osobę zastępującą Cię podczas urlopu. Nie jest ona jeszcze we wszystkich Twoich przestrzeniach roboczych. Jeśli zdecydujesz się kontynuować, do wszystkich administratorów Twoich przestrzeni roboczych zostanie wysłany e-mail z prośbą o dodanie jej.`,
     },
     stepCounter: ({step, total, text}: StepCounterParams) => {
@@ -3525,35 +3137,23 @@ ${amount} dla ${merchant} - ${date}`,
         connectManually: 'Połącz ręcznie',
         desktopConnection: 'Uwaga: aby połączyć się z Chase, Wells Fargo, Capital One lub Bank of America, kliknij tutaj, aby zakończyć ten proces w przeglądarce.',
         yourDataIsSecure: 'Twoje dane są bezpieczne',
-        toGetStarted: 'Dodaj konto bankowe, żeby zwracać wydatki, wydawać Karty Expensify, przyjmować płatności faktur i opłacać rachunki — wszystko w jednym miejscu.',
+        toGetStarted: 'Dodaj konto bankowe, aby zwracać wydatki, wydawać karty Expensify, pobierać płatności za faktury i opłacać rachunki — wszystko w jednym miejscu.',
         plaidBodyCopy: 'Daj pracownikom łatwiejszy sposób płacenia – i otrzymywania zwrotów – za wydatki firmowe.',
         checkHelpLine: 'Numer rozliczeniowy i numer rachunku znajdziesz na czeku powiązanym z tym kontem.',
-        bankAccountPurposeTitle: 'Co chcesz zrobić ze swoim kontem bankowym?',
-        getReimbursed: 'Otrzymać zwrot kosztów',
-        getReimbursedDescription: 'Od pracodawcy lub innych',
-        makePayments: 'Dokonywać płatności',
-        makePaymentsDescription: 'Opłacaj wydatki lub wydawaj Karty Expensify',
         hasPhoneLoginError: (contactMethodRoute: string) =>
             `Aby połączyć konto bankowe, <a href="${contactMethodRoute}">dodaj adres e‑mail jako swój główny login</a> i spróbuj ponownie. Numer telefonu możesz dodać jako login dodatkowy.`,
         hasBeenThrottledError: 'Wystąpił błąd podczas dodawania Twojego konta bankowego. Poczekaj kilka minut i spróbuj ponownie.',
-        hasCurrencyError: (workspaceRoute: string) =>
+        hasCurrencyError: ({workspaceRoute}: WorkspaceRouteParams) =>
             `Ups! Wygląda na to, że waluta Twojego przestrzeni roboczej jest inna niż USD. Aby kontynuować, przejdź do <a href="${workspaceRoute}">ustawień swojej przestrzeni roboczej</a>, ustaw ją na USD i spróbuj ponownie.`,
         bbaAdded: 'Dodano firmowe konto bankowe!',
         bbaAddedDescription: 'Jest gotowe do używania do płatności.',
-        lockedBankAccount: 'Zablokowane konto bankowe',
-        unlockBankAccount: 'Odblokuj konto bankowe',
-        youCantPayThis: `Nie możesz zapłacić za ten raport, ponieważ masz <a href="${CONST.UNLOCK_BANK_ACCOUNT_HELP_URL}">zablokowane konto bankowe</a>. Stuknij poniżej, a Concierge pomoże Ci w kolejnych krokach odblokowania.`,
-        htmlUnlockMessage: (maskedAccountNumber: string) =>
-            `<h1>Expensify Business Bank Account ${maskedAccountNumber}</h1><p>Dziękujemy za przesłanie prośby o odblokowanie konta bankowego. Wnioski o wypłatę mogą zostać odrzucone z powodu niewystarczających środków lub jeśli konto bankowe nie zostało aktywowane do polecenia zapłaty. Przeanalizujemy Twoją sprawę i skontaktujemy się z Tobą, jeśli będziemy potrzebować dodatkowych informacji w celu rozwiązania tego problemu.</p>`,
-        textUnlockMessage: (maskedAccountNumber: string) =>
-            `Expensify Business Bank Account ${maskedAccountNumber}\nDziękujemy za przesłanie prośby o odblokowanie konta bankowego. Wnioski o wypłatę mogą zostać odrzucone z powodu niewystarczających środków lub jeśli konto bankowe nie zostało aktywowane do polecenia zapłaty. Przeanalizujemy Twoją sprawę i skontaktujemy się z Tobą, jeśli będziemy potrzebować dodatkowych informacji w celu rozwiązania tego problemu.`,
         error: {
             youNeedToSelectAnOption: 'Wybierz opcję, aby kontynuować',
             noBankAccountAvailable: 'Przepraszamy, brak dostępnego konta bankowego',
             noBankAccountSelected: 'Wybierz konto',
             taxID: 'Wprowadź prawidłowy numer identyfikacji podatkowej',
             website: 'Wprowadź prawidłową stronę internetową',
-            zipCode: `Wprowadź prawidłowy kod ZIP w formacie: ${COMMON_CONST.COUNTRY_ZIP_REGEX_DATA.US.samples}`,
+            zipCode: `Wprowadź prawidłowy kod ZIP w formacie: ${CONST.COUNTRY_ZIP_REGEX_DATA.US.samples}`,
             phoneNumber: 'Wprowadź prawidłowy numer telefonu',
             email: 'Wpisz prawidłowy adres e‑mail',
             companyName: 'Wprowadź prawidłową nazwę firmy',
@@ -3580,7 +3180,7 @@ ${amount} dla ${merchant} - ${date}`,
             fullName: 'Wpisz prawidłowe imię i nazwisko',
             ownershipPercentage: 'Wprowadź prawidłową liczbę procentową',
             deletePaymentBankAccount:
-                'To konto bankowe nie może zostać usunięte, ponieważ jest używane do płatności Kartą Expensify. Jeśli mimo to chcesz usunąć to konto, skontaktuj się z Concierge.',
+                'To konto bankowe nie może zostać usunięte, ponieważ jest używane do płatności kartą Expensify. Jeśli mimo to chcesz usunąć to konto, skontaktuj się z Concierge.',
             sameDepositAndWithdrawalAccount: 'Konta wpłat i wypłat są takie same.',
         },
     },
@@ -3595,11 +3195,6 @@ ${amount} dla ${merchant} - ${date}`,
         confirmationStepHeader: 'Sprawdź swoje dane.',
         confirmationStepSubHeader: 'Sprawdź poniższe szczegóły i zaznacz pole z warunkami, aby potwierdzić.',
         toGetStarted: 'Dodaj osobiste konto bankowe, aby otrzymywać zwroty wydatków, opłacać faktury lub włączyć Portfel Expensify.',
-        updatePersonalInfo: 'Aktualizuj konto bankowe',
-        updatePersonalInfoFailure: 'Nie można zaktualizować informacji o koncie bankowym. Spróbuj ponownie później.',
-        updateSuccessTitle: 'Konto bankowe zaktualizowane!',
-        updateSuccessHeader: 'Konto bankowe zaktualizowane',
-        updateSuccessMessage: 'Gratulacje, Twoje konto bankowe jest skonfigurowane i gotowe do przyjmowania zwrotów.',
     },
     addPersonalBankAccountPage: {
         enterPassword: 'Wpisz hasło do Expensify',
@@ -3627,8 +3222,8 @@ ${amount} dla ${merchant} - ${date}`,
     messages: {
         errorMessageInvalidPhone: `Wprowadź prawidłowy numer telefonu bez nawiasów i myślników. Jeśli jesteś poza USA, dodaj kod kraju (np. ${CONST.EXAMPLE_PHONE_NUMBER}).`,
         errorMessageInvalidEmail: 'Nieprawidłowy adres e-mail',
-        userIsAlreadyMember: (login: string, name: string) => `${login} jest już członkiem ${name}`,
-        userIsAlreadyAnAdmin: (login: string, name: string) => `${login} jest już administratorem ${name}`,
+        userIsAlreadyMember: ({login, name}: UserIsAlreadyMemberParams) => `${login} jest już członkiem ${name}`,
+        userIsAlreadyAnAdmin: ({login, name}: UserIsAlreadyMemberParams) => `${login} jest już administratorem ${name}`,
     },
     onfidoStep: {
         acceptTerms: 'Kontynuując wniosek o aktywację portfela Expensify, potwierdzasz, że zapoznałeś(-aś) się, rozumiesz i akceptujesz',
@@ -3674,7 +3269,7 @@ ${amount} dla ${merchant} - ${date}`,
         haveReadAndAgreePlain: 'Przeczytałem(-am) i zgadzam się na otrzymywanie ujawnień w formie elektronicznej.',
         haveReadAndAgree: `Przeczytałem(-am) i wyrażam zgodę na otrzymywanie <a href="${CONST.ELECTRONIC_DISCLOSURES_URL}">elektronicznych powiadomień</a>.`,
         agreeToThePlain: 'Zgadzam się na Politykę prywatności i warunki portfela.',
-        agreeToThe: (walletAgreementUrl: string) =>
+        agreeToThe: ({walletAgreementUrl}: WalletAgreementParams) =>
             `Zgadzam się z <a href="${CONST.OLD_DOT_PUBLIC_URLS.PRIVACY_URL}">polityką prywatności</a> oraz <a href="${walletAgreementUrl}">warunkami korzystania z portfela</a>.`,
         enablePayments: 'Włącz płatności',
         monthlyFee: 'Miesięczna opłata',
@@ -3686,7 +3281,7 @@ ${amount} dla ${merchant} - ${date}`,
         checkTheBoxes: 'Zaznacz pola poniżej.',
         agreeToTerms: 'Zaakceptuj warunki i wszystko będzie gotowe!',
         shortTermsForm: {
-            expensifyPaymentsAccount: (walletProgram: string) => `Portfel Expensify jest wydawany przez ${walletProgram}.`,
+            expensifyPaymentsAccount: ({walletProgram}: WalletProgramParams) => `Portfel Expensify jest wydawany przez ${walletProgram}.`,
             perPurchase: 'Za zakup',
             atmWithdrawal: 'Wypłata z bankomatu',
             cashReload: 'Doładowanie gotówką',
@@ -3700,7 +3295,7 @@ ${amount} dla ${merchant} - ${date}`,
             generalInfo: `Aby uzyskać ogólne informacje o kontach przedpłaconych, odwiedź <a href="${CONST.CFPB_PREPAID_URL}">${CONST.TERMS.CFPB_PREPAID}</a>.`,
             conditionsDetails: `Aby zapoznać się ze szczegółami i warunkami wszystkich opłat i usług, odwiedź stronę <a href="${CONST.FEES_URL}">${CONST.FEES_URL}</a> lub zadzwoń pod numer +1 833-400-0904.`,
             electronicFundsWithdrawalInstant: 'Elektroniczne wycofanie środków (natychmiastowe)',
-            electronicFundsInstantFeeMin: (amount: string) => `(min ${amount})`,
+            electronicFundsInstantFeeMin: ({amount}: TermsParams) => `(min ${amount})`,
         },
         longTermsForm: {
             listOfAllFees: 'Lista wszystkich opłat za portfel Expensify',
@@ -3720,7 +3315,7 @@ ${amount} dla ${merchant} - ${date}`,
             electronicFundsInstantDetails: (percentage: string, amount: string) =>
                 'Przy natychmiastowym przelewie środków z Twojego Portfela Expensify na powiązaną kartę debetową pobierana jest opłata. Ten przelew zazwyczaj zostaje zrealizowany w ciągu kilku minut.' +
                 `Opłata wynosi ${percentage}% kwoty przelewu (przy minimalnej opłacie ${amount}).`,
-            fdicInsuranceBancorp: (amount: string) =>
+            fdicInsuranceBancorp: ({amount}: TermsParams) =>
                 `Twoje środki kwalifikują się do objęcia ubezpieczeniem FDIC. Twoje środki będą przechowywane w lub przenoszone do ${CONST.WALLET.PROGRAM_ISSUERS.BANCORP_BANK}, instytucji ubezpieczonej przez FDIC.` +
                 `Gdy już tam trafią, Twoje środki są ubezpieczone przez FDIC do kwoty ${amount} na wypadek upadłości ${CONST.WALLET.PROGRAM_ISSUERS.BANCORP_BANK}, jeśli spełnione są określone wymogi dotyczące ubezpieczenia depozytów i Twoja karta jest zarejestrowana. Szczegóły znajdziesz w ${CONST.TERMS.FDIC_PREPAID}.`,
             contactExpensifyPayments: `Skontaktuj się z ${CONST.WALLET.PROGRAM_ISSUERS.EXPENSIFY_PAYMENTS}, dzwoniąc pod numer +1 833-400-0904, wysyłając e-mail na adres ${CONST.EMAIL.CONCIERGE} lub logując się na ${CONST.NEW_EXPENSIFY_URL}.`,
@@ -3729,7 +3324,7 @@ ${amount} dla ${merchant} - ${date}`,
             automated: 'Zautomatyzowane',
             liveAgent: 'Agent na żywo',
             instant: 'Natychmiast',
-            electronicFundsInstantFeeMin: (amount: string) => `Min ${amount}`,
+            electronicFundsInstantFeeMin: ({amount}: TermsParams) => `Min ${amount}`,
         },
     },
     activateStep: {
@@ -4015,10 +3610,6 @@ ${amount} dla ${merchant} - ${date}`,
         youCanChange: 'Możesz zmienić walutę swojego workspace’u w swoim',
         findCountry: 'Znajdź kraj',
         selectCountry: 'Wybierz kraj',
-        error: {
-            connectToWorkspace: (workspaceRoute: string) =>
-                `To konto bankowe musi zostać powiązane z przestrzenią roboczą. Przejdź do <a href="${workspaceRoute}">Przestrzeni roboczych</a>, wybierz swoją przestrzeń roboczą, a następnie przejdź do Przepływy pracy > Płatności > Dodaj konto bankowe.`,
-        },
     },
     bankInfoStep: {
         whatAreYour: 'Jakie są dane Twojego firmowego konta bankowego?',
@@ -4062,7 +3653,7 @@ ${amount} dla ${merchant} - ${date}`,
         pleaseUpload: 'Prześlij poniżej dodatkową dokumentację, abyśmy mogli zweryfikować Twoją tożsamość jako dyrektora firmy.',
         enterSignerInfo: 'Wprowadź dane sygnatariusza',
         thisStep: 'Ten krok został ukończony',
-        isConnecting: (bankAccountLastFour: string | undefined, currency: string | undefined) =>
+        isConnecting: ({bankAccountLastFour, currency}: SignerInfoMessageParams) =>
             `łączy firmowe konto bankowe w ${currency} z numerem kończącym się na ${bankAccountLastFour} z Expensify, aby wypłacać wynagrodzenia pracownikom w ${currency}. Następnym krokiem jest podanie danych sygnatariusza będącego dyrektorem.`,
         error: {
             emailsMustBeDifferent: 'Adresy e-mail muszą być różne',
@@ -4074,7 +3665,7 @@ ${amount} dla ${merchant} - ${date}`,
         regulationRequiresUs: 'Przepisy wymagają od nas weryfikacji tożsamości każdej osoby, która posiada ponad 25% udziałów w firmie.',
         iAmAuthorized: 'Mam upoważnienie do korzystania z firmowego rachunku bankowego na wydatki służbowe.',
         iCertify: 'Oświadczam, że podane informacje są prawdziwe i dokładne.',
-        iAcceptTheTermsAndConditions: `Akceptuję <a href="https://www.corpay.com/cross-border/terms">warunki i zasady</a>.`,
+        iAcceptTheTermsAndConditions: `Akceptuję <a href="https://cross-border.corpay.com/tc/">warunki i zasady</a>.`,
         iAcceptTheTermsAndConditionsAccessibility: 'Akceptuję warunki.',
         accept: 'Zaakceptuj i dodaj konto bankowe',
         iConsentToThePrivacyNotice: 'Wyrażam zgodę na <a href="https://payments.corpay.com/compliance">informację o ochronie prywatności</a>.',
@@ -4106,37 +3697,6 @@ ${amount} dla ${merchant} - ${date}`,
         weTake: 'Poważnie podchodzimy do kwestii bezpieczeństwa. Skonfiguruj teraz uwierzytelnianie dwuskładnikowe (2FA), aby dodać dodatkową warstwę ochrony swojego konta.',
         secure: 'Zabezpiecz swoje konto',
     },
-    documentsStep: {
-        beforeYouGo: 'Zanim przejdziesz dalej, potrzebujemy kilku dokumentów do weryfikacji informacji',
-        subheader: 'Weryfikacja',
-        verificationFailed: 'Weryfikacja nie powiodła się, dlatego potrzebujemy dodatkowych dokumentów do potwierdzenia Twojej tożsamości i firmy',
-        taxIDVerification: 'Weryfikacja numeru podatkowego',
-        taxIDVerificationDescription: dedent(`
-        Prześlij jeden z poniższych plików:
-        • List przydziału TIN/EIN z IRS
-        • Potwierdzenie wniosku TIN/EIN z IRS (zwykle zawiera „Congratulations! The EIN has been successfully assigned”)
-        • Pismo o zwolnieniu podatkowym z IRS zawierające nazwę firmy i EIN`),
-        nameChangeDocument: 'Dokument zmiany nazwy',
-        nameChangeDocumentDescription: 'Jeśli nazwa firmy zmieniła się od momentu złożenia wniosku o TIN/EIN, dokument ten jest wymagany do weryfikacji podanego numeru podatkowego',
-        companyAddressVerification: 'Weryfikacja adresu firmy',
-        companyAddressVerificationDescription: dedent(`
-        Prześlij jeden z poniższych plików:
-        • Aktualny rachunek za media z nazwą i adresem firmy
-        • Wyciąg bankowy z nazwą i adresem firmy
-        • Aktualna umowa najmu z podpisaną stroną zawierającą nazwę i adres firmy
-        • Dokument ubezpieczeniowy z nazwą i adresem firmy
-        • Dokument przydziału TIN z nazwą i adresem firmy`),
-        userAddressVerification: 'Weryfikacja adresu',
-        userAddressVerificationDescription: dedent(`
-        Prześlij jeden z poniższych plików:
-        • Karta rejestracji wyborcy
-        • Prawo jazdy
-        • Wyciąg bankowy
-        • Rachunek za media`),
-        userDOBVerification: 'Weryfikacja daty urodzenia',
-        userDOBVerificationDescription: 'Prześlij dokument tożsamości wydany w USA',
-        finishViaChat: 'Zakończ przez czat',
-    },
     reimbursementAccountLoadingAnimation: {
         oneMoment: 'Chwileczkę',
         explanationLine: 'Sprawdzamy Twoje informacje. Wkrótce będziesz mógł/mogła przejść do kolejnych kroków.',
@@ -4274,15 +3834,15 @@ ${amount} dla ${merchant} - ${date}`,
             flightSeatChanged: (airlineCode: string) => `Twoje miejsce na locie ${airlineCode} zostało zmienione.`,
             flightSeatCancelled: (airlineCode: string) => `Twoja przydzielona miejscówka na locie ${airlineCode} została usunięta.`,
             paymentDeclined: 'Płatność za rezerwację lotu nie powiodła się. Spróbuj ponownie.',
-            bookingCancelledByTraveler: (type: string, id = '') => `Anulowano Twoją rezerwację ${type} ${id}.`,
-            bookingCancelledByVendor: (type: string, id = '') => `Dostawca anulował Twoją rezerwację typu ${type} ${id}.`,
-            bookingRebooked: (type: string, id = '') => `Twoja rezerwacja (${type}) została ponownie zarezerwowana. Nowy numer potwierdzenia: ${id}.`,
-            bookingUpdated: (type: string) => `Twoja rezerwacja (${type}) została zaktualizowana. Sprawdź nowe szczegóły w planie podróży.`,
+            bookingCancelledByTraveler: ({type, id = ''}: TravelTypeParams) => `Anulowano Twoją rezerwację ${type} ${id}.`,
+            bookingCancelledByVendor: ({type, id = ''}: TravelTypeParams) => `Dostawca anulował Twoją rezerwację typu ${type} ${id}.`,
+            bookingRebooked: ({type, id = ''}: TravelTypeParams) => `Twoja rezerwacja (${type}) została ponownie zarezerwowana. Nowy numer potwierdzenia: ${id}.`,
+            bookingUpdated: ({type}: TravelTypeParams) => `Twoja rezerwacja (${type}) została zaktualizowana. Sprawdź nowe szczegóły w planie podróży.`,
             railTicketRefund: (origin: string, destination: string, startDate: string) =>
                 `Twój bilet kolejowy z ${origin} do ${destination} na ${startDate} został zwrócony. Zostanie przetworzony kredyt.`,
             railTicketExchange: (origin: string, destination: string, startDate: string) => `Twój bilet kolejowy z ${origin} → ${destination} na ${startDate} został wymieniony.`,
             railTicketUpdate: (origin: string, destination: string, startDate: string) => `Twój bilet kolejowy z ${origin} → ${destination} na ${startDate} został zaktualizowany.`,
-            defaultUpdate: (type: string) => `Twoja rezerwacja (${type}) została zaktualizowana.`,
+            defaultUpdate: ({type}: TravelTypeParams) => `Twoja rezerwacja (${type}) została zaktualizowana.`,
         },
         flightTo: 'Lot do',
         trainTo: 'Pociąg do',
@@ -4299,13 +3859,13 @@ ${amount} dla ${merchant} - ${date}`,
             workflows: 'Przepływy pracy',
             workspace: 'Przestrzeń robocza',
             findWorkspace: 'Znajdź przestrzeń roboczą',
-            findRoom: 'Znajdź pokój',
             edit: 'Edytuj przestrzeń roboczą',
             enabled: 'Włączone',
             disabled: 'Wyłączone',
             everyone: 'Wszyscy',
             delete: 'Usuń przestrzeń roboczą',
             settings: 'Ustawienia',
+            reimburse: 'Zwroty kosztów',
             categories: 'Kategorie',
             tags: 'Tagi',
             customField1: 'Niestandardowe pole 1',
@@ -4313,7 +3873,6 @@ ${amount} dla ${merchant} - ${date}`,
             customFieldHint: 'Dodaj niestandardowe kodowanie, które będzie stosowane do wszystkich wydatków tego członka.',
             reports: 'Raporty',
             reportFields: 'Pola raportu',
-            invoiceFields: 'Pola faktury',
             reportTitle: 'Tytuł raportu',
             reportField: 'Pole raportu',
             taxes: 'Podatki',
@@ -4342,10 +3901,6 @@ ${amount} dla ${merchant} - ${date}`,
             defaultNote: `Paragony wysłane na ${CONST.EMAIL.RECEIPTS} pojawią się w tym obszarze roboczym.`,
             deleteConfirmation: 'Czy na pewno chcesz usunąć tę przestrzeń roboczą?',
             deleteWithCardsConfirmation: 'Na pewno chcesz usunąć tę przestrzeń roboczą? Spowoduje to usunięcie wszystkich źródeł kart i przypisanych kart.',
-            deleteOpenExpensifyCardsError: 'Twoja firma nadal ma aktywne karty Expensify.',
-            outstandingBalanceWarning:
-                'Masz zaległe saldo, które musi zostać uregulowane przed usunięciem ostatniego miejsca pracy. Przejdź do ustawień subskrypcji, aby uregulować płatność.',
-            settleBalance: 'Przejdź do subskrypcji',
             unavailable: 'Niedostępne miejsce pracy',
             memberNotFound: 'Nie znaleziono członka. Aby zaprosić nową osobę do przestrzeni roboczej, użyj przycisku zaproszenia powyżej.',
             notAuthorized: `Nie masz dostępu do tej strony. Jeśli próbujesz dołączyć do tego obszaru roboczego, poproś właściciela obszaru roboczego, aby dodał Cię jako członka. Coś innego? Skontaktuj się z ${CONST.EMAIL.CONCIERGE}.`,
@@ -4356,11 +3911,8 @@ ${amount} dla ${merchant} - ${date}`,
             clearFilter: 'Wyczyść filtr',
             workspaceName: 'Nazwa przestrzeni roboczej',
             workspaceOwner: 'Właściciel',
-            keepMeAsAdmin: 'Zachowaj mnie jako administratora',
             workspaceType: 'Typ przestrzeni roboczej',
             workspaceAvatar: 'Awatar przestrzeni roboczej',
-            clientID: 'ID klienta',
-            clientIDInputHint: 'Wprowadź unikalny identyfikator klienta',
             mustBeOnlineToViewMembers: 'Musisz być online, aby wyświetlić członków tego workspace.',
             moreFeatures: 'Więcej funkcji',
             requested: 'Zamówiono',
@@ -4379,7 +3931,7 @@ ${amount} dla ${merchant} - ${date}`,
             appliedOnExport: 'Nie zaimportowano do Expensify, zastosowane przy eksporcie',
             shareNote: {
                 header: 'Udostępnij swoją przestrzeń roboczą innym członkom',
-                content: (adminsRoomLink: string) =>
+                content: ({adminsRoomLink}: WorkspaceShareNoteParams) =>
                     `Udostępnij ten kod QR lub skopiuj poniższy link, aby członkowie mogli łatwo poprosić o dostęp do Twojego obszaru roboczego. Wszystkie prośby o dołączenie do obszaru roboczego pojawią się w pokoju <a href="${adminsRoomLink}">${CONST.REPORT.WORKSPACE_CHAT_ROOMS.ADMINS}</a> do Twojej weryfikacji.`,
             },
             connectTo: ({connectionName}: ConnectionNameParams) => `Połącz z ${CONST.POLICY.CONNECTIONS.NAME_USER_FRIENDLY[connectionName]}`,
@@ -4394,20 +3946,12 @@ ${amount} dla ${merchant} - ${date}`,
             memberAlternateText: 'Przesyłaj i zatwierdzaj raporty.',
             adminAlternateText: 'Zarządzaj raportami i ustawieniami przestrzeni roboczej.',
             auditorAlternateText: 'Przeglądaj i komentuj raporty.',
-            roleName: (role?: string) => {
+            roleName: ({role}: OptionalParam<RoleNamesParams> = {}) => {
                 switch (role) {
                     case CONST.POLICY.ROLE.ADMIN:
-                        return 'Administrator przestrzeni roboczej';
+                        return 'Administrator';
                     case CONST.POLICY.ROLE.AUDITOR:
                         return 'Audytor';
-                    case CONST.POLICY.ROLE.EDITOR:
-                        return 'Edytor';
-                    case CONST.POLICY.ROLE.CARD_ADMIN:
-                        return 'Administrator karty';
-                    case CONST.POLICY.ROLE.PEOPLE_ADMIN:
-                        return 'Administrator osób';
-                    case CONST.POLICY.ROLE.PAYMENTS_ADMIN:
-                        return 'Administrator płatności';
                     case CONST.POLICY.ROLE.USER:
                         return 'Członek';
                     default:
@@ -4437,22 +3981,7 @@ ${amount} dla ${merchant} - ${date}`,
             budgetFrequencyUnit: {monthly: 'miesiąc', yearly: 'rok'},
             budgetTypeForNotificationMessage: {tag: 'znacznik', category: 'kategoria'},
             policyExpenseChatName: (displayName: string) => `Wydatki ${displayName}`,
-            deepDiveExpensifyCard: `<muted-text-label>Transakcje z Karty Expensify będą automatycznie eksportowane do „Konta zobowiązań Karty Expensify” utworzonego dzięki <a href="${CONST.DEEP_DIVE_EXPENSIFY_CARD}">naszej integracji</a>.</muted-text-label>`,
-            travelInvoicing: 'Eksportuj wydatki z fakturowania podróży jako',
-            travelInvoicingVendor: 'Dostawca usług turystycznych',
-            travelInvoicingPayableAccount: 'Konto zobowiązań z tytułu podróży',
-            hr: 'HR',
-            rooms: 'Pokoje',
-            findDomain: 'Znajdź domenę',
-            cardAdminAlternateText: 'Zarządzaj kartami przestrzeni roboczej.',
-            peopleAdminAlternateText: 'Zarządzaj członkami i procesami akceptacji.',
-            paymentsAdminAlternateText: 'Zarządzaj płatnościami w przepływie pracy.',
-            readOnlyActionTitle: 'Nie tak szybko…',
-            readOnlyActionPrompt: 'Twoja rola w przestrzeni roboczej może wyświetlać te ustawienia, ale nie może ich edytować.',
-        },
-        createdForClient: {
-            title: 'Utworzyłeś przestrzeń roboczą dla swojego klienta!',
-            description: 'Świetna wiadomość 🎉. Skontaktuj się z nami, jeśli potrzebują pomocy przy konfiguracji.',
+            deepDiveExpensifyCard: `<muted-text-label>Transakcje kartą Expensify będą automatycznie eksportowane do „Konta zobowiązań karty Expensify” utworzonego za pomocą <a href="${CONST.DEEP_DIVE_EXPENSIFY_CARD}">naszej integracji</a>.</muted-text-label>`,
         },
         receiptPartners: {
             uber: {
@@ -4516,7 +4045,7 @@ ${amount} dla ${merchant} - ${date}`,
             exportDescription: 'Skonfiguruj sposób eksportu danych z Expensify do QuickBooks Desktop.',
             date: 'Data eksportu',
             exportInvoices: 'Eksportuj faktury do',
-            exportExpensifyCard: 'Eksportuj transakcje Karty Expensify jako',
+            exportExpensifyCard: 'Wyeksportuj transakcje karty Expensify jako',
             account: 'Konto',
             accountDescription: 'Wybierz miejsce księgowania zapisów w dzienniku.',
             accountsPayable: 'Zobowiązania z tytułu dostaw i usług',
@@ -4635,7 +4164,7 @@ ${amount} dla ${merchant} - ${date}`,
             exportDescription: 'Skonfiguruj sposób eksportu danych z Expensify do QuickBooks Online.',
             date: 'Data eksportu',
             exportInvoices: 'Eksportuj faktury do',
-            exportExpensifyCard: 'Eksportuj transakcje Karty Expensify jako',
+            exportExpensifyCard: 'Wyeksportuj transakcje karty Expensify jako',
             exportDate: {
                 label: 'Data eksportu',
                 description: 'Użyj tej daty podczas eksportowania raportów do QuickBooks Online.',
@@ -4673,9 +4202,8 @@ ${amount} dla ${merchant} - ${date}`,
             notConfigured: 'Nie skonfigurowano',
             bankAccountDescription: 'Wybierz, skąd wysyłać czeki.',
             creditCardAccount: 'Konto karty kredytowej',
-            travelInvoicingDescription: 'Wydatki na podróże zostaną wyeksportowane jako obciążenia karty kredytowej na konto QuickBooks Online wskazane poniżej.',
             companyCardsLocationEnabledDescription:
-                'QuickBooks Online nie obsługuje lokalizacji w eksportach rachunków od dostawców, gdy lokalizacje są importowane jako tagi. Ponieważ w tym obszarze roboczym masz lokalizacje importowane jako tagi, ta opcja eksportu jest niedostępna.',
+                'QuickBooks Online nie obsługuje lokalizacji w eksporcie rachunków do dostawców. Ponieważ masz włączone lokalizacje w swoim obszarze roboczym, ta opcja eksportu jest niedostępna.',
             outOfPocketTaxEnabledDescription:
                 'QuickBooks Online nie obsługuje podatków przy eksporcie zapisów w dzienniku. Ponieważ masz włączone podatki w swoim obszarze roboczym, ta opcja eksportu jest niedostępna.',
             outOfPocketTaxEnabledError: 'Zapisy w dzienniku są niedostępne, gdy podatki są włączone. Wybierz inną opcję eksportu.',
@@ -4768,7 +4296,6 @@ ${amount} dla ${merchant} - ${date}`,
             exportDeepDiveCompanyCard:
                 'Wyeksportowane wydatki zostaną zaksięgowane jako transakcje bankowe na poniższym koncie bankowym Xero, a daty transakcji będą zgodne z datami na Twoim wyciągu bankowym.',
             bankTransactions: 'Transakcje bankowe',
-            travelInvoicingDescription: 'Wydatki na podróże zostaną wyeksportowane jako transakcje bankowe na konto Xero wskazane poniżej.',
             xeroBankAccount: 'Konto bankowe Xero',
             xeroBankAccountDescription: 'Wybierz, gdzie wydatki będą księgowane jako transakcje bankowe.',
             exportExpensesDescription: 'Raporty zostaną wyeksportowane jako rachunek zakupu z datą i statusem wybranymi poniżej.',
@@ -4864,7 +4391,6 @@ ${amount} dla ${merchant} - ${date}`,
                     [CONST.SAGE_INTACCT_NON_REIMBURSABLE_EXPENSE_TYPE.VENDOR_BILL]: 'Rachunki od dostawców',
                 },
             },
-            travelInvoicingDescription: 'Wydatki na podróże zostaną wyeksportowane jako obciążenia karty kredytowej na konto Sage Intacct wskazane poniżej.',
             creditCardAccount: 'Konto karty kredytowej',
             defaultVendor: 'Domyślny dostawca',
             defaultVendorDescription: (isReimbursable: boolean) =>
@@ -4897,68 +4423,6 @@ ${amount} dla ${merchant} - ${date}`,
                 },
             },
         },
-        certinia: {
-            title: 'Certinia',
-            titleFFA: 'Certinia (FFA)',
-            autoSyncDescription: 'Expensify będzie automatycznie synchronizować się z Certinia każdego dnia.',
-            syncReimbursedReportsDescription:
-                'Gdy ta opcja jest włączona, za każdym razem gdy Należna faktura zostanie opłacona w FFA, powiązany raport Expensify zostanie automatycznie oznaczony jako zwrócony.',
-            exportDescription: 'Skonfiguruj sposób eksportu danych z Expensify do Certinia.',
-            payableInvoices: 'Należne faktury',
-            exportStatus: {
-                label: 'Status faktury do zapłaty',
-                values: {
-                    [CONST.CERTINIA_EXPORT_STATUS.APPROVED]: 'Zakończ',
-                    [CONST.CERTINIA_EXPORT_STATUS.IN_PROGRESS]: 'W toku',
-                    [CONST.CERTINIA_EXPORT_STATUS.SUBMITTED]: 'Wysłano',
-                },
-            },
-            exportDate: {
-                label: 'Data płatności faktury',
-                values: {
-                    [CONST.CERTINIA_EXPORT_DATE.LAST_EXPENSE]: 'Data ostatniego wydatku',
-                    [CONST.CERTINIA_EXPORT_DATE.REPORT_SUBMITTED]: 'Data wysłania raportu',
-                    [CONST.CERTINIA_EXPORT_DATE.REPORT_EXPORTED]: 'Data eksportu',
-                },
-            },
-            exportReimbursable: {
-                label: 'Eksportuj zwracane wydatki jako',
-                helperText: 'Wydatki oznaczone jako podlegające zwrotowi zostaną wyeksportowane jako faktury do zapłaty wystawione na pracownika.',
-            },
-            exportNonReimbursable: {label: 'Eksportuj niewliczane do zwrotu wydatki jako'},
-            noVendorsFound: 'Nie znaleziono dostawców',
-            noVendorsFoundDescription: 'Po dodaniu dostawców w Certinia zsynchronizuj ponownie to połączenie.',
-            prerequisites: {
-                title: 'Zanim się połączysz',
-                installBundle: 'Dla połączeń FFA',
-                installBundleDescription: ({href, version}: {href: string; version: string}) =>
-                    `Zainstaluj pakiet Expensify w Salesforce, klikając ten link: <a href="${href}">Zainstaluj pakiet FFA Expensify (wersja ${version})</a>`,
-                installBundleConfirm: 'Zainstalowałem pakiet',
-                setupContacts: 'Skonfiguruj użytkownika i kontakty',
-                setupContactsBullet1:
-                    'Utwórz dla siebie zarówno użytkownika, jak i kontakt w Certinia, jeśli jeszcze nie istnieją, upewniając się, że adres e‑mail jest taki sam jak twój główny adres e‑mail w Expensify.',
-                setupContactsBullet2:
-                    'Utwórz kontakty dla każdego pracownika, który będzie składał raporty wydatków, oraz dla każdej osoby je zatwierdzającej. Upewnij się, że adres e‑mail każdego kontaktu odpowiada adresowi e‑mail na koncie Expensify pracownika.',
-                setupContactsBullet3: 'Ustaw uprawnienia dla swojego użytkownika dla każdego kontaktu/zasobu.',
-                setupContactsConfirm: 'Skonfigurowałem użytkownika i kontakty',
-                oauth: 'Zaloguj się przez Salesforce',
-                oauthDescription: 'Aby zakończyć konfigurację, musisz się zalogować przez Salesforce i Certinia.\n\nUżyj przycisku poniżej, żeby kontynuować.',
-                connectButton: 'Połącz z Certinia',
-            },
-            import: {
-                chartOfAccounts: 'Plan kont',
-                chartOfAccountsDescription: 'Plan kont jest importowany do Expensify jako kategorie.',
-                dimensionMapping: ({n}: {n: number}) => `Wymiar ${n}`,
-                dimensions: {dimension1: 'Wymiar 1', dimension2: 'Wymiar 2', dimension3: 'Wymiar 3', dimension4: 'Wymiar 4'},
-                doNotMap: 'Nie mapuj',
-                doNotMapSubtitle: 'Domyślnie użyj zasobu pracownika',
-                mappingTypes: {
-                    [CONST.CERTINIA_MAPPING_VALUE.DEFAULT]: 'Nie mapuj',
-                    [CONST.CERTINIA_MAPPING_VALUE.TAG]: 'Zaimportowano jako tagi',
-                    [CONST.CERTINIA_MAPPING_VALUE.REPORT_FIELD]: 'Zaimportowano jako pola raportu',
-                },
-            },
-        },
         netsuite: {
             subsidiary: 'Spółka zależna',
             subsidiarySelectDescription: 'Wybierz jednostkę zależną w NetSuite, z której chcesz zaimportować dane.',
@@ -4973,8 +4437,8 @@ ${amount} dla ${merchant} - ${date}`,
             journalPostingPreference: {
                 label: 'Preferencje księgowania zapisów w dzienniku',
                 values: {
-                    [CONST.NETSUITE_JOURNAL_POSTING_PREFERENCE.JOURNALS_POSTING_INDIVIDUAL_LINE]: 'Pojedynczy wpis dla każdego wydatku',
-                    [CONST.NETSUITE_JOURNAL_POSTING_PREFERENCE.JOURNALS_POSTING_TOTAL_LINE]: 'Pojedyncza, wyszczególniona pozycja dla każdego raportu',
+                    [CONST.NETSUITE_JOURNAL_POSTING_PREFERENCE.JOURNALS_POSTING_INDIVIDUAL_LINE]: 'Pojedynczy, wyszczególniony wpis dla każdego raportu',
+                    [CONST.NETSUITE_JOURNAL_POSTING_PREFERENCE.JOURNALS_POSTING_TOTAL_LINE]: 'Pojedynczy wpis dla każdego wydatku',
                 },
             },
             invoiceItem: {
@@ -5040,7 +4504,6 @@ ${amount} dla ${merchant} - ${date}`,
 
                             Jeśli chcesz ustawić konkretnego dostawcę dla każdej karty, przejdź do *Ustawienia > Domeny > Karty firmowe*.
                         `),
-                        travelDescription: 'Wydatki na podróże służbowe zostaną wyeksportowane jako zapisy księgowe na konto NetSuite wskazane poniżej.',
                     },
                 },
                 expenseReportDestinationConfirmDescription:
@@ -5185,7 +4648,7 @@ ${amount} dla ${merchant} - ${date}`,
                 importCustomFields: {
                     chooseOptionBelow: 'Wybierz jedną z poniższych opcji:',
                     label: (importedTypes: string[]) => `Zaimportowano jako ${importedTypes.join('i')}`,
-                    requiredFieldError: (fieldName: string) => `Wpisz proszę ${fieldName}`,
+                    requiredFieldError: ({fieldName}: RequiredFieldParams) => `Wpisz proszę ${fieldName}`,
                     customSegments: {
                         title: 'Niestandardowe segmenty/rejestry',
                         addText: 'Dodaj własny segment/rejestr',
@@ -5238,7 +4701,7 @@ _Aby uzyskać bardziej szczegółowe instrukcje, [odwiedź naszą stronę pomocy
 
 _Aby uzyskać bardziej szczegółowe instrukcje, [odwiedź naszą stronę pomocy](${CONST.NETSUITE_IMPORT.HELP_LINKS.CUSTOM_SEGMENTS})_.`,
                             customSegmentScriptIDTitle: 'Jaki jest identyfikator skryptu?',
-                            customSegmentScriptIDFooter: `Możesz znaleźć identyfikatory skryptów niestandardowych segmentów w NetSuite w menu:
+                            customSegmentScriptIDFooter: `Możesz znaleźć identyfikatory skryptów niestandardowych segmentów w NetSuite w menu: 
 
 1. *Customization > Lists, Records, & Fields > Custom Segments*.
 2. Wejdź w szczegóły wybranego niestandardowego segmentu.
@@ -5259,7 +4722,7 @@ _Aby uzyskać bardziej szczegółowe instrukcje, [odwiedź naszą stronę pomocy
                             customRecordMappingTitle: 'Jak powinien być wyświetlany ten niestandardowy rekord w Expensify?',
                         },
                         errors: {
-                            uniqueFieldError: (fieldName: string) => `Niestandardowy segment/rekord z tym ${fieldName?.toLowerCase()} już istnieje`,
+                            uniqueFieldError: ({fieldName}: RequiredFieldParams) => `Niestandardowy segment/rekord z tym ${fieldName?.toLowerCase()} już istnieje`,
                         },
                     },
                     customLists: {
@@ -5326,7 +4789,7 @@ _Aby uzyskać bardziej szczegółowe instrukcje, [odwiedź naszą stronę pomocy
             employeeDefaultDescription: 'Domyślny dział pracownika zostanie zastosowany do jego wydatków w Sage Intacct, jeśli istnieje.',
             displayedAsTagDescription: 'Dział będzie można wybrać osobno dla każdego wydatku w raporcie pracownika.',
             displayedAsReportFieldDescription: 'Wybór działu zostanie zastosowany do wszystkich wydatków w raporcie pracownika.',
-            toggleImportTitle: (mappingTitle: string) => `Wybierz, jak obsługiwać Sage Intacct <strong>${mappingTitle}</strong> w Expensify.`,
+            toggleImportTitle: ({mappingTitle}: ToggleImportTitleParams) => `Wybierz, jak obsługiwać Sage Intacct <strong>${mappingTitle}</strong> w Expensify.`,
             expenseTypes: 'Typy wydatków',
             expenseTypesDescription: 'Typy wydatków z Sage Intacct zostaną zaimportowane do Expensify jako kategorie.',
             accountTypesDescription: 'Twój plan kont Sage Intacct zostanie zaimportowany do Expensify jako kategorie.',
@@ -5366,14 +4829,10 @@ _Aby uzyskać bardziej szczegółowe instrukcje, [odwiedź naszą stronę pomocy
             free: 'Darmowy',
             control: 'Sterowanie',
             collect: 'Zbierz',
-            submit: 'Prześlij',
         },
         companyCards: {
             addCards: 'Dodaj karty',
             selectCards: 'Wybierz karty',
-            fromOtherWorkspaces: 'Z innych przestrzeni roboczych',
-            addWorkEmail: 'Dodaj swój służbowy e-mail',
-            addWorkEmailDescription: 'Dodaj swój służbowy e-mail, aby korzystać z istniejących kanałów z innych przestrzeni roboczych.',
             error: {
                 workspaceFeedsCouldNotBeLoadedTitle: 'Nie można wczytać kanałów kart',
                 workspaceFeedsCouldNotBeLoadedMessage: 'Wystąpił błąd podczas ładowania kanałów kart w przestrzeni roboczej. Spróbuj ponownie lub skontaktuj się ze swoim administratorem.',
@@ -5383,11 +4842,6 @@ _Aby uzyskać bardziej szczegółowe instrukcje, [odwiedź naszą stronę pomocy
             },
             addNewCard: {
                 other: 'Inne',
-                fileImport: 'Importuj transakcje z pliku',
-                createFileFeedHelpText: `<muted-text>Postępuj zgodnie z <a href="${CONST.COMPANY_CARDS_CREATE_FILE_FEED_HELP_URL}">tym przewodnikiem pomocy</a>, aby zaimportować wydatki z kart firmowych!</muted-text>`,
-                companyCardLayoutName: 'Nazwa układu karty firmowej',
-                cardLayoutNameRequired: 'Nazwa układu karty firmowej jest wymagana',
-                useAdvancedFields: 'Użyj pól zaawansowanych (niezalecane)',
                 cardProviders: {
                     gl1025: 'Karty korporacyjne American Express',
                     cdf: 'Firmowe karty Mastercard',
@@ -5466,26 +4920,6 @@ _Aby uzyskać bardziej szczegółowe instrukcje, [odwiedź naszą stronę pomocy
                     confirmText: 'Zgłoś problem',
                     cancelText: 'Pomiń',
                 },
-                csvColumns: {
-                    cardNumber: 'Numer karty',
-                    postedDate: 'Data',
-                    merchant: 'Sprzedawca',
-                    amount: 'Kwota',
-                    currency: 'Waluta',
-                    ignore: 'Ignoruj',
-                    originalTransactionDate: 'Data pierwotnej transakcji',
-                    originalAmount: 'Kwota pierwotna',
-                    originalCurrency: 'Pierwotna waluta',
-                    comment: 'Komentarz',
-                    category: 'Kategoria',
-                    tag: 'Tag',
-                },
-                csvErrors: {
-                    requiredColumns: (missingColumns: string) => `Przypisz kolumnę do każdego z atrybutów: ${missingColumns}.`,
-                    duplicateColumns: (duplicateColumn: string) => `Ups! Przypisałeś jedno pole („${duplicateColumn}”) do wielu kolumn. Sprawdź i spróbuj ponownie.`,
-                },
-                fileImportDescription: 'Ręczna opcja, jeśli Twój bank nie może wysyłać kanału danych.',
-                duplicateFeedModal: {title: 'Kanał karty jest już połączony', prompt: 'Nie możesz dodać tego samego źródła danych karty do tego samego obszaru roboczego dwa razy.'},
             },
             statementCloseDate: {
                 [CONST.COMPANY_CARDS.STATEMENT_CLOSE_DATE.LAST_DAY_OF_MONTH]: 'Ostatni dzień miesiąca',
@@ -5535,14 +4969,12 @@ _Aby uzyskać bardziej szczegółowe instrukcje, [odwiedź naszą stronę pomocy
                 flipAmountSign: 'Odwróć znak kwoty',
                 importButton: 'Importuj transakcje',
             },
-            deletedCard: 'Usunięta karta',
-            assignNewCards: {title: 'Przydziel nowe karty', description: 'Pobierz z banku najnowsze karty do przypisania'},
         },
         expensifyCard: {
-            issueAndManageCards: 'Wydawaj i zarządzaj Kartami Expensify',
+            issueAndManageCards: 'Wydawaj i zarządzaj swoimi kartami Expensify',
             getStartedIssuing: 'Zacznij od wydania swojej pierwszej wirtualnej lub fizycznej karty.',
             verificationInProgress: 'Weryfikacja w toku...',
-            verifyingTheDetails: 'Weryfikujemy kilka szczegółów. Concierge da ci znać, kiedy Karty Expensify będą gotowe do wydania.',
+            verifyingTheDetails: 'Weryfikujemy kilka szczegółów. Concierge poinformuje Cię, gdy karty Expensify będą gotowe do wydania.',
             disclaimer:
                 'Komercyjna karta Expensify Visa® jest wydawana przez The Bancorp Bank, N.A., członka FDIC, na podstawie licencji udzielonej przez Visa U.S.A. Inc. i może nie być akceptowana u wszystkich sprzedawców, którzy przyjmują karty Visa. Apple® i logo Apple® są znakami towarowymi Apple Inc., zarejestrowanymi w USA i innych krajach. App Store jest znakiem usługowym Apple Inc. Google Play i logo Google Play są znakami towarowymi Google LLC.',
             euUkDisclaimer:
@@ -5554,8 +4986,8 @@ _Aby uzyskać bardziej szczegółowe instrukcje, [odwiedź naszą stronę pomocy
             lastFour: 'Ostatnie 4',
             limit: 'Limit',
             currentBalance: 'Bieżące saldo',
-            currentBalanceDescription: 'Bieżące saldo to suma wszystkich zaksięgowanych transakcji Kartą Expensify, które miały miejsce od ostatniej daty rozliczenia.',
-            balanceWillBeSettledOn: (settlementDate: string) => `Saldo zostanie rozliczone w dniu ${settlementDate}`,
+            currentBalanceDescription: 'Bieżące saldo to suma wszystkich zaksięgowanych transakcji kartą Expensify, które miały miejsce od ostatniej daty rozliczenia.',
+            balanceWillBeSettledOn: ({settlementDate}: SettlementDateParams) => `Saldo zostanie rozliczone w dniu ${settlementDate}`,
             settleBalance: 'Ureguluj saldo',
             cardLimit: 'Limit karty',
             remainingLimit: 'Pozostały limit',
@@ -5563,27 +4995,26 @@ _Aby uzyskać bardziej szczegółowe instrukcje, [odwiedź naszą stronę pomocy
             remainingLimitDescription:
                 'Bierzemy pod uwagę kilka czynników przy obliczaniu Twojego pozostałego limitu: staż jako klient, informacje biznesowe podane podczas rejestracji oraz dostępne środki na koncie firmowym. Twój pozostały limit może zmieniać się każdego dnia.',
             earnedCashback: 'Zwrot gotówki',
-            earnedCashbackDescription: 'Saldo zwrotu gotówki jest oparte na rozliczonych miesięcznych wydatkach Kartą Expensify w twoim zespole.',
+            earnedCashbackDescription: 'Saldo zwrotu gotówki opiera się na rozliczonych miesięcznych wydatkach kartą Expensify w całej Twojej przestrzeni roboczej.',
             issueNewCard: 'Wydaj nową kartę',
             finishSetup: 'Zakończ konfigurację',
             chooseBankAccount: 'Wybierz konto bankowe',
-            chooseExistingBank: 'Wybierz istniejące firmowe konto bankowe, żeby spłacić saldo Karty Expensify, albo dodaj nowe konto bankowe',
+            chooseExistingBank: 'Wybierz istniejące firmowe konto bankowe, aby spłacić saldo karty Expensify, lub dodaj nowe konto bankowe',
             accountEndingIn: 'Konto kończące się na',
             addNewBankAccount: 'Dodaj nowe konto bankowe',
             settlementAccount: 'Konto rozliczeniowe',
-            settlementAccountDescription: 'Wybierz konto, z którego spłacisz saldo swojej Karty Expensify.',
-            settlementAccountInfo: (reconciliationAccountSettingsLink: string, accountNumber: string) =>
+            settlementAccountDescription: 'Wybierz konto, z którego spłacisz saldo karty Expensify.',
+            settlementAccountInfo: ({reconciliationAccountSettingsLink, accountNumber}: SettlementAccountInfoParams) =>
                 `Upewnij się, że to konto jest takie samo jak <a href="${reconciliationAccountSettingsLink}">konto do uzgadniania</a> (${accountNumber}), aby Ciągłe uzgadnianie działało poprawnie.`,
             settlementFrequency: 'Częstotliwość rozliczeń',
-            settlementFrequencyDescription: 'Wybierz, jak często będziesz spłacać saldo swojej Karty Expensify.',
+            settlementFrequencyDescription: 'Wybierz, jak często będziesz spłacać saldo karty Expensify.',
             settlementFrequencyInfo: 'Jeśli chcesz przejść na miesięczne rozliczenie, musisz podłączyć swoje konto bankowe przez Plaid i mieć dodatnią historię salda z ostatnich 90 dni.',
-            applyCashbackToBill: 'Zastosuj zwrot gotówki do mojego rachunku Expensify',
-            applyCashbackToBillDescription: 'Zwrot gotówki z Karty Expensify zostanie wykorzystany do opłacenia Twojego rachunku Expensify.',
             frequency: {
                 daily: 'Codziennie',
                 monthly: 'Miesięcznie',
             },
             cardDetails: 'Dane karty',
+            cardPending: ({name}: {name: string}) => `Karta jest obecnie w oczekiwaniu i zostanie wydana po zweryfikowaniu konta ${name}.`,
             virtual: 'Wirtualna',
             physical: 'Fizyczny',
             deactivate: 'Dezaktywuj kartę',
@@ -5599,28 +5030,24 @@ _Aby uzyskać bardziej szczegółowe instrukcje, [odwiedź naszą stronę pomocy
             changeCardMonthlyLimitTypeWarning: (limit: number | string) =>
                 `Jeśli zmienisz typ limitu tej karty na miesięczny, nowe transakcje zostaną odrzucone, ponieważ miesięczny limit ${limit} został już osiągnięty.`,
             addShippingDetails: 'Dodaj dane wysyłki',
-            issuedCard: (assignee: string) => `przydzielono osobie ${assignee} Kartę Expensify! Karta dotrze w ciągu 2–3 dni roboczych.`,
-            issuedCardNoShippingDetails: (assignee: string) => `wydano dla ${assignee} Kartę Expensify! Karta zostanie wysłana, gdy dane do wysyłki zostaną potwierdzone.`,
-            issuedCardVirtual: (assignee: string, link: string) => `przyznał(-a) ${assignee} wirtualną Kartę Expensify! Z ${link} można korzystać od razu.`,
-            addedShippingDetails: (assignee: string) => `${assignee} dodał dane wysyłki. Karta Expensify dotrze w ciągu 2–3 dni roboczych.`,
-            replacedCard: (assignee: string) => `${assignee} wymienił(a) swoją Kartę Expensify. Nowa karta dotrze w ciągu 2–3 dni roboczych.`,
-            replacedVirtualCard: (assignee: string, link: string) => `${assignee} wymienił(-a) swoją wirtualną Kartę Expensify! ${link} można używać od razu.`,
+            issuedCard: (assignee: string) => `wydano użytkownikowi ${assignee} kartę Expensify! Karta dotrze w ciągu 2–3 dni roboczych.`,
+            issuedCardNoShippingDetails: (assignee: string) => `przyznał(-a) ${assignee} kartę Expensify! Karta zostanie wysłana po potwierdzeniu danych wysyłki.`,
+            issuedCardVirtual: (assignee: string, link: string) => `wydał(a) użytkownikowi ${assignee} wirtualną kartę Expensify! Z ${link} można korzystać od razu.`,
+            addedShippingDetails: (assignee: string) => `${assignee} dodał(a) dane wysyłki. Karta Expensify dotrze w ciągu 2–3 dni roboczych.`,
+            replacedCard: (assignee: string) => `${assignee} wymienił(-a) swoją kartę Expensify. Nowa karta dotrze w ciągu 2–3 dni roboczych.`,
+            replacedVirtualCard: (assignee: string, link: string) => `${assignee} wymienił(-a) swoją wirtualną kartę Expensify! ${link} można używać od razu.`,
             card: 'karta',
             replacementCard: 'karta zastępcza',
             verifyingHeader: 'Weryfikowanie',
             bankAccountVerifiedHeader: 'Konto bankowe zweryfikowane',
             verifyingBankAccount: 'Weryfikowanie konta bankowego...',
-            verifyingBankAccountDescription: 'Poczekaj, aż potwierdzimy, że to konto może zostać użyte do wydawania Kart Expensify.',
+            verifyingBankAccountDescription: 'Poczekaj, aż potwierdzimy, że to konto może być użyte do wydawania kart Expensify.',
             bankAccountVerified: 'Konto bankowe zostało zweryfikowane!',
-            bankAccountVerifiedDescription: 'Możesz teraz wydawać Karty Expensify członkom swojego przestrzeni roboczej.',
+            bankAccountVerifiedDescription: 'Możesz teraz wydawać karty Expensify członkom swojego obszaru roboczego.',
             oneMoreStep: 'Jeszcze jeden krok…',
             oneMoreStepDescription: 'Wygląda na to, że musimy ręcznie zweryfikować Twoje konto bankowe. Przejdź do Concierge, gdzie czekają na Ciebie dalsze instrukcje.',
             gotIt: 'Rozumiem',
             goToConcierge: 'Przejdź do Concierge',
-            exportAsCSV: 'Eksportuj jako CSV',
-            csvColumnType: 'Typ',
-            csvColumnLimitType: 'Typ limitu',
-            csvColumnLimit: 'Limit',
         },
         categories: {
             deleteCategories: 'Usuń kategorie',
@@ -5639,10 +5066,10 @@ _Aby uzyskać bardziej szczegółowe instrukcje, [odwiedź naszą stronę pomocy
             needCategoryForExportToIntegration: (connectionName: string) => `Wszystkie wydatki muszą zostać skategoryzowane, aby można je było wyeksportować do ${connectionName}.`,
             subtitle: 'Uzyskaj lepszy wgląd w to, gdzie wydawane są pieniądze. Użyj naszych domyślnych kategorii lub dodaj własne.',
             emptyCategories: {
-                title: 'Brak kategorii',
+                title: 'Nie utworzyłeś(-aś) żadnych kategorii',
                 subtitle: 'Dodaj kategorię, aby uporządkować swoje wydatki.',
-                subtitleWithAccounting: (accountingPageURL: string, canManage = true) =>
-                    `<muted-text><centered-text>Twoje kategorie są obecnie importowane z połączenia księgowego.${canManage ? ` Przejdź do sekcji <a href="${accountingPageURL}">księgowość</a>, aby wprowadzić zmiany.` : ''}</centered-text></muted-text>`,
+                subtitleWithAccounting: (accountingPageURL: string) =>
+                    `<muted-text><centered-text>Twoje kategorie są obecnie importowane z połączenia księgowego. Przejdź do sekcji <a href="${accountingPageURL}">księgowość</a>, aby wprowadzić zmiany.</centered-text></muted-text>`,
             },
             updateFailureMessage: 'Wystąpił błąd podczas aktualizowania kategorii, spróbuj ponownie',
             createFailureMessage: 'Wystąpił błąd podczas tworzenia kategorii, spróbuj ponownie',
@@ -5697,9 +5124,6 @@ _Aby uzyskać bardziej szczegółowe instrukcje, [odwiedź naszą stronę pomocy
             travel: {
                 title: 'Podróże',
                 subtitle: 'Rezerwuj, zarządzaj i uzgadniaj wszystkie wyjazdy służbowe.',
-                disableTravelTitle: 'Najpierw wyłącz fakturowanie podróży',
-                disableTravelPrompt: 'Fakturowanie podróży jest włączone dla tego obszaru roboczego. Wyłącz je, zanim będziesz mógł wyłączyć funkcję Podróże.',
-                disableTravelButton: 'Przejdź do ustawień Podróży',
                 getStarted: {
                     title: 'Pierwsze kroki z Expensify Travel',
                     subtitle: 'Potrzebujemy jeszcze tylko kilku informacji o Twojej firmie, a potem będziesz gotowy do startu.',
@@ -5711,12 +5135,9 @@ _Aby uzyskać bardziej szczegółowe instrukcje, [odwiedź naszą stronę pomocy
                     ctaText: 'Żądanie wysłane',
                 },
                 bookOrManageYourTrip: {
-                    title: 'Rezerwacja podróży',
-                    subtitle: 'Gratulacje! Możesz już rezerwować i zarządzać podróżami w tym obszarze roboczym.',
-                    ctaText: 'Zarządzaj podróżami',
-                },
-                settings: {
-                    autoAddTripName: {title: 'Dodaj nazwy podróży do wydatków', subtitle: 'Automatycznie dodawaj nazwy podróży do opisów wydatków za podróże zarezerwowane w Expensify.'},
+                    title: 'Zarezerwuj lub zarządzaj swoją podróżą',
+                    subtitle: 'Korzystaj z Expensify Travel, aby uzyskać najlepsze oferty podróży i zarządzać wszystkimi wydatkami służbowymi w jednym miejscu.',
+                    ctaText: 'Zarezerwuj lub zarządzaj',
                 },
                 travelInvoicing: {
                     travelBookingSection: {
@@ -5724,58 +5145,29 @@ _Aby uzyskać bardziej szczegółowe instrukcje, [odwiedź naszą stronę pomocy
                         subtitle: 'Gratulacje! Wszystko gotowe, aby rezerwować i zarządzać podróżami w tym obszarze roboczym.',
                         manageTravelLabel: 'Zarządzaj podróżami',
                     },
-                    travelInvoicingSection: {
-                        title: 'Fakturowanie podróży',
+                    centralInvoicingSection: {
+                        title: 'Centralne fakturowanie',
                         subtitle: 'Skonsoliduj wszystkie wydatki na podróże w jednym miesięcznym rachunku zamiast płacić w momencie zakupu.',
                         learnHow: 'Dowiedz się jak.',
                         subsections: {
                             currentTravelSpendLabel: 'Aktualne wydatki na podróże',
-                            currentTravelSpendPaymentQueued: (amount: string) => `Płatność w wysokości ${amount} jest w kolejce i wkrótce zostanie przetworzona.`,
                             currentTravelSpendCta: 'Spłać saldo',
                             currentTravelLimitLabel: 'Aktualny limit podróży',
                             settlementAccountLabel: 'Konto rozliczeniowe',
                             settlementFrequencyLabel: 'Częstotliwość rozliczeń',
                             settlementFrequencyDescription: 'Jak często Expensify będzie pobierać środki z firmowego konta bankowego, aby rozliczyć ostatnie transakcje Expensify Travel.',
-                            monthlySpendLimitLabel: 'Miesięczny limit wydatków na członka',
-                            monthlySpendLimitDescription: 'Maksymalna kwota, jaką każdy członek może wydać na podróże w ciągu miesiąca.',
-                            reduceLimitTitle: 'Zmniejszyć limit wydatków na podróże?',
-                            reduceLimitWarning:
-                                'Jeśli zmniejszysz limit, członkowie, którzy już wydali więcej niż ta kwota, nie będą mogli dokonywać nowych rezerwacji podróży do następnego miesiąca.',
-                            provisioningError:
-                                'Nie udało się utworzyć dostępu do fakturowania podróży dla części członków Twojego workspace. Spróbuj ponownie później albo skontaktuj się z Concierge, żeby uzyskać pomoc.',
                         },
                     },
-                    disableModal: {
-                        title: 'Wyłączyć fakturowanie podróży?',
-                        body: 'Nadchodzące rezerwacje hoteli i wynajmu samochodów mogą wymagać ponownej rezerwacji z użyciem innej metody płatności, aby uniknąć anulowania.',
-                        confirm: 'Wyłącz',
-                    },
-                    outstandingBalanceModal: {
-                        title: 'Nie można wyłączyć fakturowania podróży',
-                        body: 'Masz nadal zaległe saldo za podróż. Najpierw ureguluj swoje saldo.',
-                        confirm: 'Rozumiem',
-                    },
-                    payBalanceModal: {
-                        title: (amount: string) => `Spłacić saldo w wysokości ${amount}?`,
-                        body: 'Płatność zostanie zakolejkowana i wkrótce przetworzona. Po rozpoczęciu tej operacji nie będzie można cofnąć.',
-                    },
-                    exportToPDF: 'Eksportuj do PDF',
-                    exportToCSV: 'Eksportuj do CSV',
-                    selectDateRangeError: 'Wybierz zakres dat do eksportu',
-                    invalidDateRangeError: 'Data początkowa musi być wcześniejsza niż data końcowa',
-                    enabled: 'Fakturowanie podróży włączone!',
-                    enabledDescription: 'Wszystkie wydatki podróżne w tym obszarze roboczym będą teraz rozliczane na scentralizowanej, miesięcznej fakturze.',
                 },
-                personalDetailsDescription: 'Aby zarezerwować podróż, wpisz swoje imię i nazwisko dokładnie tak, jak widnieje w Twoim dokumencie tożsamości wydanym przez organ państwowy.',
             },
             expensifyCard: {
                 title: 'Karta Expensify',
                 subtitle: 'Uzyskaj wgląd i kontrolę nad wydatkami.',
-                disableCardTitle: 'Wyłącz Kartę Expensify',
-                disableCardPrompt: 'Nie możesz wyłączyć Karty Expensify, ponieważ jest już używana. Skontaktuj się z Concierge, żeby poznać kolejne kroki.',
+                disableCardTitle: 'Wyłącz kartę Expensify',
+                disableCardPrompt: 'Nie możesz wyłączyć karty Expensify, ponieważ jest już w użyciu. Skontaktuj się z Concierge, aby poznać kolejne kroki.',
                 disableCardButton: 'Czat z Concierge',
                 feed: {
-                    title: 'Zamów Kartę Expensify',
+                    title: 'Zdobądź kartę Expensify',
                     subTitle: 'Usprawnij rozliczanie wydatków firmowych i zaoszczędź do 50% na rachunku Expensify, a dodatkowo:',
                     features: {
                         cashBack: 'Zwrot gotówki od każdego zakupu w USA',
@@ -5820,10 +5212,7 @@ _Aby uzyskać bardziej szczegółowe instrukcje, [odwiedź naszą stronę pomocy
                 updateCard: 'Zaktualizuj kartę',
                 unassignCard: 'Cofnij przypisanie karty',
                 unassign: 'Cofnij przypisanie',
-                unassignCardDescription: 'Cofnięcie przypisania tej karty spowoduje usunięcie wszystkich niewysłanych transakcji.',
-                removeCard: 'Usuń kartę',
-                remove: 'Usuń',
-                removeCardDescription: 'Usunięcie tej karty spowoduje usunięcie wszystkich niewysłanych transakcji.',
+                unassignCardDescription: 'Odłączenie tej karty spowoduje usunięcie wszystkich transakcji z raportów w wersji roboczej z konta posiadacza karty.',
                 assignCard: 'Przypisz kartę',
                 cardFeedName: 'Nazwa źródła karty',
                 cardFeedNameDescription: 'Nadaj kanałowi karty unikalną nazwę, aby odróżnić go od pozostałych.',
@@ -5855,9 +5244,9 @@ _Aby uzyskać bardziej szczegółowe instrukcje, [odwiedź naszą stronę pomocy
                 noAccountsFound: 'Nie znaleziono kont',
                 defaultCard: 'Domyślna karta',
                 downgradeTitle: `Nie można obniżyć planu przestrzeni roboczej`,
-                downgradeSubTitle: `Tego przestrzeni roboczej nie można zdegradować, ponieważ jest podłączonych wiele źródeł kart (z wyłączeniem Kart Expensify). Aby kontynuować, proszę <a href="#">pozostaw tylko jedno źródło karty</a>.`,
+                downgradeSubTitle: `Nie można obniżyć poziomu tej przestrzeni roboczej, ponieważ podłączonych jest wiele źródeł kart (z wyłączeniem kart Expensify). Aby kontynuować, prosimy <a href="#">pozostawić tylko jedno źródło kart</a>.`,
                 noAccountsFoundDescription: (connection: string) => `Dodaj konto w ${connection} i zsynchronizuj to połączenie ponownie`,
-                expensifyCardBannerTitle: 'Zamów Kartę Expensify',
+                expensifyCardBannerTitle: 'Zdobądź kartę Expensify',
                 expensifyCardBannerSubtitle:
                     'Korzystaj z cash backu przy każdym zakupie w USA, zniżki do 50% na swój rachunek w Expensify, nielimitowanych kart wirtualnych i wielu innych korzyści.',
                 expensifyCardBannerLearnMoreButton: 'Dowiedz się więcej',
@@ -5868,7 +5257,7 @@ _Aby uzyskać bardziej szczegółowe instrukcje, [odwiedź naszą stronę pomocy
                 title: 'Przepływy pracy',
                 subtitle: 'Skonfiguruj sposób zatwierdzania i opłacania wydatków.',
                 disableApprovalPrompt:
-                    'Karty Expensify z tego obszaru roboczego obecnie polegają na zatwierdzaniu przy ustalaniu swoich Inteligentnych Limitów. Zmień typy limitów wszystkich Kart Expensify z Inteligentnymi Limitami, zanim wyłączysz zatwierdzanie.',
+                    'Karty Expensify z tego obszaru roboczego obecnie opierają swoje Inteligentne Limity na procesie zatwierdzania. Zmień typy limitów wszystkich Kart Expensify z Inteligentnymi Limitami przed wyłączeniem zatwierdzania.',
             },
             invoices: {
                 title: 'Faktury',
@@ -5913,8 +5302,8 @@ _Aby uzyskać bardziej szczegółowe instrukcje, [odwiedź naszą stronę pomocy
             workflowWarningModal: {
                 featureEnabledTitle: 'Nie tak szybko...',
                 featureEnabledText:
-                    'Karty Expensify w tym obszarze roboczym opierają się na przepływach akceptacji, aby określić swoje Smart Limits.\n\nZmień typy limitów wszystkich kart z włączonymi Smart Limits, zanim wyłączysz przepływy akceptacji.',
-                confirmText: 'Przejdź do Kart Expensify',
+                    'Karty Expensify w tym obszarze roboczym opierają się na przepływach zatwierdzania, aby określić ich Inteligentne Limity.\n\nZmień typy limitów wszystkich kart z Inteligentnymi Limitami, zanim wyłączysz przepływy pracy.',
+                confirmText: 'Przejdź do kart Expensify',
             },
             rules: {
                 title: 'Zasady',
@@ -5925,7 +5314,6 @@ _Aby uzyskać bardziej szczegółowe instrukcje, [odwiedź naszą stronę pomocy
                 subtitle: 'Ustaw godzinową stawkę rozliczeniową do śledzenia czasu.',
                 defaultHourlyRate: 'Domyślna stawka godzinowa',
             },
-            hrWarningModal: {disconnectText: ({integration}: {integration: string}) => `Aby wyłączyć HR, najpierw odłącz ${integration} od tego workspace’a.`},
         },
         reports: {
             reportsCustomTitleExamples: 'Przykłady:',
@@ -5947,7 +5335,10 @@ _Aby uzyskać bardziej szczegółowe instrukcje, [odwiedź naszą stronę pomocy
             findReportField: 'Znajdź pole raportu',
             deleteConfirmation: 'Czy na pewno chcesz usunąć to pole raportu?',
             deleteFieldsConfirmation: 'Czy na pewno chcesz usunąć te pola raportu?',
-            emptyReportFields: {title: 'Brak jeszcze pól raportu', subtitle: 'Dodaj niestandardowe pole (tekstowe, daty lub z listą wyboru), które będzie widoczne w raportach.'},
+            emptyReportFields: {
+                title: 'Nie utworzyłeś żadnych pól raportu',
+                subtitle: 'Dodaj niestandardowe pole (tekstowe, daty lub z listą wyboru), które będzie widoczne w raportach.',
+            },
             subtitle: 'Pola raportu mają zastosowanie do wszystkich wydatków i mogą być pomocne, gdy chcesz poprosić o dodatkowe informacje.',
             disableReportFields: 'Wyłącz pola raportu',
             disableReportFieldsConfirmation: 'Na pewno? Pola tekstowe i daty zostaną usunięte, a listy wyłączone.',
@@ -5971,7 +5362,10 @@ _Aby uzyskać bardziej szczegółowe instrukcje, [odwiedź naszą stronę pomocy
             disableValues: 'Wyłącz wartości',
             enableValue: 'Włącz wartość',
             enableValues: 'Włącz wartości',
-            emptyReportFieldsValues: {title: 'Nie ma jeszcze wartości listy', subtitle: 'Dodaj własne wartości, które będą wyświetlane w raportach.'},
+            emptyReportFieldsValues: {
+                title: 'Nie utworzyłeś(-aś) żadnych wartości listy',
+                subtitle: 'Dodaj własne wartości, które będą wyświetlane w raportach.',
+            },
             deleteValuePrompt: 'Czy na pewno chcesz usunąć tę wartość listy?',
             deleteValuesPrompt: 'Czy na pewno chcesz usunąć te wartości listy?',
             listValueRequiredError: 'Wpisz nazwę wartości listy',
@@ -5983,33 +5377,9 @@ _Aby uzyskać bardziej szczegółowe instrukcje, [odwiedź naszą stronę pomocy
             reportFieldNameRequiredError: 'Wprowadź nazwę pola raportu',
             reportFieldTypeRequiredError: 'Wybierz typ pola raportu',
             circularReferenceError: 'To pole nie może odnosić się do siebie. Zaktualizuj je.',
-            unsupportedFormulaValueError: ({value}: UnsupportedFormulaValueErrorParams) => `Pole formuły ${value} nie zostało rozpoznane`,
             reportFieldInitialValueRequiredError: 'Wybierz początkową wartość pola raportu',
             genericFailureMessage: 'Wystąpił błąd podczas aktualizowania pola raportu. Spróbuj ponownie.',
         },
-        invoiceFields: {
-            subtitle: 'Pola faktury mogą być pomocne, gdy chcesz dodać dodatkowe informacje.',
-            importedFromAccountingSoftware: 'Poniższe pola faktury są importowane z Twojego',
-            disableInvoiceFields: 'Wyłącz pola faktury',
-            disableInvoiceFieldsConfirmation: 'Czy na pewno? Pola faktury zostaną wyłączone na fakturach.',
-            delete: 'Usuń pole faktury',
-            deleteConfirmation: 'Czy na pewno chcesz usunąć to pole faktury?',
-            findInvoiceField: 'Znajdź pole faktury',
-            nameInputSubtitle: 'Wybierz nazwę pola faktury.',
-            typeInputSubtitle: 'Wybierz typ pola faktury, którego chcesz użyć.',
-            initialValueInputSubtitle: 'Wprowadź wartość początkową, która ma być wyświetlana w polu faktury.',
-            listValuesInputSubtitle: 'Te wartości pojawią się na liście rozwijanej pola faktury. Członkowie mogą wybierać włączone wartości.',
-            listInputSubtitle: 'Te wartości pojawią się na liście pola faktury. Członkowie mogą wybierać włączone wartości.',
-            emptyInvoiceFieldsValues: {
-                title: 'Brak wartości listy',
-                subtitle: 'Dodaj niestandardowe wartości, które mają pojawiać się na fakturach.',
-            },
-            existingInvoiceFieldNameError: 'Pole faktury o tej nazwie już istnieje',
-            invoiceFieldNameRequiredError: 'Wprowadź nazwę pola faktury',
-            invoiceFieldTypeRequiredError: 'Wybierz typ pola faktury',
-            invoiceFieldInitialValueRequiredError: 'Wybierz początkową wartość pola faktury',
-            addField: 'Dodaj pole',
-        },
         tags: {
             tagName: 'Nazwa tagu',
             requiresTag: 'Członkowie muszą otagować wszystkie wydatki',
@@ -6027,14 +5397,14 @@ _Aby uzyskać bardziej szczegółowe instrukcje, [odwiedź naszą stronę pomocy
             editTags: 'Edytuj tagi',
             findTag: 'Znajdź tag',
             subtitle: 'Tagi umożliwiają bardziej szczegółowe klasyfikowanie kosztów.',
-            subtitleWithDependentTags: (importSpreadsheetLink: string, canReimport = true) =>
-                `<muted-text>Tagi umożliwiają bardziej szczegółowe klasyfikowanie kosztów. Używasz <a href="${CONST.IMPORT_TAGS_EXPENSIFY_URL_DEPENDENT_TAGS}">zależnych tagów</a>.${canReimport ? ` Możesz <a href="${importSpreadsheetLink}">ponownie zaimportować arkusz kalkulacyjny</a>, aby zaktualizować swoje tagi.` : ''}</muted-text>`,
+            dependentMultiLevelTagsSubtitle: (importSpreadsheetLink: string) =>
+                `<muted-text>Używasz <a href="${CONST.IMPORT_TAGS_EXPENSIFY_URL_DEPENDENT_TAGS}">zależnych tagów</a>. Możesz <a href="${importSpreadsheetLink}">ponownie zaimportować arkusz kalkulacyjny</a>, aby zaktualizować swoje tagi.</muted-text>`,
             emptyTags: {
-                title: 'Brak tagów',
+                title: 'Nie utworzono jeszcze żadnych tagów',
                 subtitle: 'Dodaj tag, aby śledzić projekty, lokalizacje, działy i inne.',
                 subtitleHTML: `<muted-text><centered-text>Dodaj tagi, aby śledzić projekty, lokalizacje, działy i nie tylko. <a href="${CONST.IMPORT_TAGS_EXPENSIFY_URL}">Dowiedz się więcej</a> o formatowaniu plików tagów do importu.</centered-text></muted-text>`,
-                subtitleWithAccounting: (accountingPageURL: string, canManage = true) =>
-                    `<muted-text><centered-text>Twoje tagi są obecnie importowane z połączenia księgowego.${canManage ? ` Przejdź do sekcji <a href="${accountingPageURL}">Księgowość</a>, aby wprowadzić zmiany.` : ''}</centered-text></muted-text>`,
+                subtitleWithAccounting: (accountingPageURL: string) =>
+                    `<muted-text><centered-text>Twoje tagi są obecnie importowane z połączenia księgowego. Przejdź do sekcji <a href="${accountingPageURL}">Księgowość</a>, aby wprowadzić zmiany.</centered-text></muted-text>`,
             },
             deleteTag: 'Usuń tag',
             deleteTags: 'Usuń tagi',
@@ -6120,7 +5490,7 @@ _Aby uzyskać bardziej szczegółowe instrukcje, [odwiedź naszą stronę pomocy
                 updateTaxClaimableFailureMessage: 'Część podlegająca zwrotowi musi być mniejsza niż kwota stawki za przejazd',
             },
             deleteTaxConfirmation: 'Czy na pewno chcesz usunąć ten podatek?',
-            deleteMultipleTaxConfirmation: (taxAmount: number) => `Czy na pewno chcesz usunąć podatek ${taxAmount}?`,
+            deleteMultipleTaxConfirmation: ({taxAmount}: TaxAmountParams) => `Czy na pewno chcesz usunąć podatek ${taxAmount}?`,
             actions: {
                 delete: 'Usuń stawkę',
                 deleteMultiple: 'Usuń stawki',
@@ -6148,47 +5518,10 @@ _Aby uzyskać bardziej szczegółowe instrukcje, [odwiedź naszą stronę pomocy
             reimbursementAccount: 'konto zwrotów',
             welcomeNote: 'Proszę, zacznij używać mojego nowego obszaru roboczego',
             delayedSubmission: 'opóźnione przesłanie',
-            merchantRules: 'Zasady sprzedawcy',
-            merchantRulesCount: () => ({
-                one: '1 zasada sprzedawcy',
-                other: (count: number) => `${count} zasady sprzedawcy`,
-            }),
             confirmTitle: ({newWorkspaceName, totalMembers}: {newWorkspaceName?: string; totalMembers?: number}) =>
                 `Za chwilę utworzysz i udostępnisz ${newWorkspaceName ?? ''} ${totalMembers ?? 0} członkom oryginalnego obszaru roboczego.`,
             error: 'Wystąpił błąd podczas duplikowania Twojego nowego obszaru roboczego. Spróbuj ponownie.',
         },
-        copyPolicySettings: {
-            title: 'Skopiuj ustawienia',
-            error: 'Wystąpił błąd podczas kopiowania ustawień przestrzeni roboczej. Spróbuj ponownie.',
-            selectWorkspaces: {
-                title: 'Wybierz przestrzenie robocze',
-                description: 'Wybierz przestrzenie robocze, do których chcesz skopiować ustawienia, a potem zaznacz ustawienia, które chcesz skopiować.',
-                searchPlaceholder: 'Szukaj przestrzeni roboczych',
-            },
-            selectSettings: {
-                title: 'Wybierz funkcje do skopiowania',
-                description: 'Wybierz ustawienia, które chcesz nadpisać w swoich istniejących przestrzeniach roboczych.',
-                accountingMismatch: ({part}: {part: string}) =>
-                    `Możesz skopiować ${part} tylko wtedy, gdy wszystkie przestrzenie robocze używają tego samego systemu księgowego i połączenia z firmą.`,
-            },
-            confirmSettings: {
-                title: 'Upewnijmy się, że wszystko wygląda poprawnie.',
-                description: ({workspaceName}: {workspaceName: string}) =>
-                    `Skopiujemy następujące ustawienia z <strong>${workspaceName}</strong> do wskazanych przez ciebie przestrzeni roboczych`,
-            },
-            confirmWorkflows: {
-                continue: 'Kontynuuj bez członków',
-                description: 'Kopiowanie przepływów pracy bez członków nie skopiuje przepływów zatwierdzania. Ustawienia przesyłania i płatności nadal zostaną skopiowane.',
-            },
-            progress: {
-                copyInProgressTitle: 'Trwa kopiowanie...',
-                copyInProgressDescription: 'Możesz poczekać, aż proces się zakończy, albo Concierge może dać ci znać, kiedy będzie gotowe.',
-                letMeKnowPrompt: 'Daj mi znać, kiedy będzie gotowe',
-                conciergeNotificationTitle: 'Concierge da ci znać',
-                conciergeNotificationDescription: 'Gdy proces się zakończy, Concierge wyśle ci wiadomość.',
-                copyCompleted: 'Twoje ustawienia przestrzeni roboczej zostały skopiowane.',
-            },
-        },
         emptyWorkspace: {
             title: 'Nie masz żadnych przestrzeni roboczych',
             subtitle: 'Śledź paragony, rozliczaj wydatki, zarządzaj podróżami, wysyłaj faktury i wiele więcej.',
@@ -6203,7 +5536,7 @@ _Aby uzyskać bardziej szczegółowe instrukcje, [odwiedź naszą stronę pomocy
         },
         new: {
             newWorkspace: 'Nowa przestrzeń robocza',
-            getTheExpensifyCardAndMore: 'Zdobądź Kartę Expensify i więcej',
+            getTheExpensifyCardAndMore: 'Zdobądź kartę Expensify i więcej',
             confirmWorkspace: 'Potwierdź przestrzeń roboczą',
             myGroupWorkspace: ({workspaceNumber}: {workspaceNumber?: number}) => `Moja grupa robocza${workspaceNumber ? ` ${workspaceNumber}` : ''}`,
             workspaceName: (userName: string, workspaceNumber?: number) => `Workspace użytkownika ${userName}${workspaceNumber ? ` ${workspaceNumber}` : ''}`,
@@ -6246,12 +5579,12 @@ _Aby uzyskać bardziej szczegółowe instrukcje, [odwiedź naszą stronę pomocy
                 genericRemove: 'Wystąpił problem z usunięciem tego członka przestrzeni roboczej',
             },
             addedWithPrimary: 'Niektóre osoby zostały dodane za pomocą swoich głównych loginów.',
-            invitedBySecondaryLogin: (secondaryLogin: string) => `Dodane przez dodatkowy login ${secondaryLogin}.`,
-            workspaceMembersCount: (count: number) => `Łączna liczba członków przestrzeni roboczej: ${count}`,
+            invitedBySecondaryLogin: ({secondaryLogin}: SecondaryLoginParams) => `Dodane przez dodatkowy login ${secondaryLogin}.`,
+            workspaceMembersCount: ({count}: WorkspaceMembersCountParams) => `Łączna liczba członków przestrzeni roboczej: ${count}`,
             importMembers: 'Zaimportuj członków',
-            removeMemberPromptApprover: (approver: string, workspaceOwner: string) =>
+            removeMemberPromptApprover: ({approver, workspaceOwner}: {approver: string; workspaceOwner: string}) =>
                 `Jeśli usuniesz ${approver} z tego obszaru roboczego, zastąpimy tę osobę w procesie zatwierdzania przez ${workspaceOwner}, właściciela obszaru roboczego.`,
-            removeMemberPromptPendingApproval: (memberName: string) =>
+            removeMemberPromptPendingApproval: ({memberName}: {memberName: string}) =>
                 `${memberName} ma zaległe raporty wydatków do zatwierdzenia. Poproś tę osobę o ich zatwierdzenie lub przejmij kontrolę nad jej raportami, zanim usuniesz ją z przestrzeni roboczej.`,
             removeMemberPromptReimburser: ({memberName}: {memberName: string}) =>
                 `Nie możesz usunąć ${memberName} z tego przestrzeni roboczej. Ustaw nową osobę zwracającą wydatki w Workflows > Make or track payments, a następnie spróbuj ponownie.`,
@@ -6261,20 +5594,10 @@ _Aby uzyskać bardziej szczegółowe instrukcje, [odwiedź naszą stronę pomocy
                 `Jeśli usuniesz ${memberName} z tej przestrzeni roboczej, zastąpimy tę osobę jako kontakt techniczny użytkownikiem ${workspaceOwner}, właścicielem przestrzeni roboczej.`,
             cannotRemoveUserDueToReport: ({memberName}: {memberName: string}) =>
                 `${memberName} ma nierozliczony raport w trakcie przetwarzania, który wymaga działania. Poproś tę osobę o wykonanie wymaganej czynności przed jej usunięciem z przestrzeni roboczej.`,
-            allMembers: 'Wszyscy członkowie',
-            admins: 'Administratorzy obszaru roboczego',
-            cardAdmins: 'Administratorzy kart',
-            approvers: 'Osoby zatwierdzające',
-            auditors: 'Audytorzy',
-            emptyRoleFilter: {title: 'Żadni członkowie nie pasują do tego filtra', subtitle: 'Zaproś członka lub zmień filtr powyżej.'},
-            configureHRSync: (providerName: string) => `Skonfiguruj synchronizację ${providerName}.`,
-            syncWithHR: (providerName: string) => `Synchronizuj z ${providerName}`,
-            makeCardAdmin: () => ({one: 'Ustaw jako administratora karty', other: 'Ustaw administratorów kart'}),
         },
         card: {
             getStartedIssuing: 'Zacznij od wydania swojej pierwszej wirtualnej lub fizycznej karty.',
             issueCard: 'Wydaj kartę',
-            chooseRule: 'Wybierz regułę',
             issueNewCard: {
                 whoNeedsCard: 'Kto potrzebuje karty?',
                 inviteNewMember: 'Zaproś nowego członka',
@@ -6316,27 +5639,21 @@ _Aby uzyskać bardziej szczegółowe instrukcje, [odwiedź naszą stronę pomocy
                 enterValidDate: 'Wprowadź prawidłową datę',
                 expirationDate: 'Data ważności',
                 limitAmount: 'Kwota limitu',
-                setCardRules: 'Ustaw zasady karty',
-                addSpendRule: 'Dodaj regułę wydatków',
-                addExpirationDate: 'Dodaj datę ważności',
-                addExpirationDateDescription: 'Jeśli nie ustawiono konkretnej daty, karta wygaśnie zgodnie z jej obecną datą ważności.',
+                setExpiryOptions: 'Ustaw opcje wygaśnięcia',
+                setExpiryDate: 'Ustaw datę wygaśnięcia',
+                setExpiryDateDescription: 'Karta wygaśnie zgodnie z informacją na karcie',
                 amount: 'Kwota',
-                copyExisting: 'Skopiuj istniejący',
-                createNew: 'Utwórz nowy',
-                spendRulesEmptyStateTitle: 'Brak reguł do wyboru',
-                spendRulesEmptyStateSubtitle: 'Brak jeszcze żadnych reguł. Możesz utworzyć jedną na poprzednim ekranie.',
             },
             deactivateCardModal: {
                 deactivate: 'Dezaktywuj',
                 deactivateCard: 'Dezaktywuj kartę',
                 deactivateConfirmation: 'Dezaktywacja tej karty spowoduje odrzucenie wszystkich przyszłych transakcji i nie będzie można jej cofnąć.',
             },
-            searchRules: 'Znajdź regułę wydatków',
         },
         accounting: {
             settings: 'ustawienia',
             title: 'Połączenia',
-            subtitle: 'Podłącz swoje oprogramowanie księgowe, aby włączyć automatyczną synchronizację.',
+            subtitle: 'Połącz się ze swoim systemem księgowym, aby kategoryzować transakcje za pomocą planu kont, automatycznie dopasowywać płatności i utrzymywać finanse w synchronizacji.',
             qbo: 'QuickBooks Online',
             qbd: 'QuickBooks Desktop',
             xero: 'Xero',
@@ -6345,7 +5662,7 @@ _Aby uzyskać bardziej szczegółowe instrukcje, [odwiedź naszą stronę pomocy
             sap: 'SAP',
             oracle: 'Oracle',
             microsoftDynamics: 'Microsoft Dynamics',
-            talkYourOnboardingSpecialist: 'Porozmawiaj ze swoim opiekunem klienta.',
+            talkYourOnboardingSpecialist: 'Porozmawiaj ze swoim specjalistą ds. konfiguracji.',
             talkYourAccountManager: 'Porozmawiaj ze swoim opiekunem konta.',
             talkToConcierge: 'Czat z Concierge.',
             needAnotherAccounting: 'Potrzebujesz innego programu księgowego?',
@@ -6420,8 +5737,6 @@ _Aby uzyskać bardziej szczegółowe instrukcje, [odwiedź naszą stronę pomocy
             connectPrompt: ({connectionName}: ConnectionNameParams) =>
                 `Czy na pewno chcesz połączyć ${CONST.POLICY.CONNECTIONS.NAME_USER_FRIENDLY[connectionName] ?? 'ta integracja księgowa'}? Spowoduje to usunięcie wszystkich istniejących połączeń księgowych.`,
             enterCredentials: 'Wprowadź swoje dane logowania',
-            reconnect: 'Połącz ponownie',
-            updateCredentials: 'Zaktualizuj dane logowania',
             claimOffer: {
                 badgeText: 'Oferta dostępna!',
                 xero: {
@@ -6564,26 +5879,6 @@ _Aby uzyskać bardziej szczegółowe instrukcje, [odwiedź naszą stronę pomocy
                             return 'Importowanie wymiarów Sage Intacct';
                         case 'intacctImportTitle':
                             return 'Importowanie danych Sage Intacct';
-                        case 'financialForceSyncTitle':
-                            return 'Synchronizowanie danych Certinia';
-                        case 'financialForceSyncStep':
-                            return 'Synchronizowanie polaczenia Certinia';
-                        case 'financialForceSyncCategories':
-                            return 'Importowanie kategorii';
-                        case 'financialForceSyncTags':
-                            return 'Importowanie tagow';
-                        case 'financialForceSyncVendors':
-                            return 'Importowanie dostawcow';
-                        case 'financialForceSyncContacts':
-                            return 'Importowanie kontaktow';
-                        case 'financialForceSyncCompanies':
-                            return 'Importowanie firm';
-                        case 'financialForceSyncUsers':
-                            return 'Importowanie uzytkownikow';
-                        case 'financialForceSyncDimensions':
-                            return 'Importowanie wymiarow';
-                        case 'financialForceMarkAsReimbursed':
-                            return 'Oznaczanie raportow jako zwrocone';
                         default: {
                             return `Brak tłumaczenia dla etapu: ${stage}`;
                         }
@@ -6605,18 +5900,15 @@ _Aby uzyskać bardziej szczegółowe instrukcje, [odwiedź naszą stronę pomocy
             cardReconciliation: 'Uzgadnianie karty',
             reconciliationAccount: 'Konto rozliczeniowe',
             continuousReconciliation: 'Ciągłe uzgadnianie',
-            saveHoursOnReconciliation: 'Oszczędzaj godziny przy każdej sesji uzgadniania, pozwalając Expensify na ciągłe uzgadnianie wyciągów i rozliczeń Karty Expensify w Twoim imieniu.',
+            saveHoursOnReconciliation:
+                'Oszczędzaj godziny przy każdej zamknięciu okresu rozliczeniowego, powierzając Expensify ciągłe uzgadnianie wyciągów i rozliczeń karty Expensify Card w Twoim imieniu.',
             enableContinuousReconciliation: (accountingAdvancedSettingsLink: string, connectionName: string) =>
                 `<muted-text-label>Aby włączyć ciągłe uzgadnianie, włącz proszę <a href="${accountingAdvancedSettingsLink}">auto-sync</a> dla ${connectionName}.</muted-text-label>`,
             chooseReconciliationAccount: {
-                chooseBankAccount: 'Wybierz konto bankowe, do którego będą uzgadniane płatności kartą Karta Expensify.',
-                settlementAccountReconciliation: (settlementAccountUrl: string, lastFourPAN: string) =>
-                    `Upewnij się, że to konto jest takie samo jak twoje <a href="${settlementAccountUrl}">konto rozliczeniowe Karty Expensify</a> (kończące się na ${lastFourPAN}), aby Ciągłe Uzgadnianie działało poprawnie.`,
-                chooseTravelInvoicingBankAccount: 'Wybierz konto bankowe, z którym będą uzgadniane płatności za faktury podróżne.',
-                travelInvoicingSettlementAccountReconciliation: (lastFourPAN: string) =>
-                    `Upewnij się, że to konto jest takie samo jak konto rozliczeniowe do fakturowania podróży (kończące się na ${lastFourPAN}), żeby Ciągłe Uzgadnianie działało poprawnie.`,
+                chooseBankAccount: 'Wybierz konto bankowe, z którym będą uzgadniane płatności Twoją kartą Expensify.',
+                settlementAccountReconciliation: ({settlementAccountUrl, lastFourPAN}: SettlementAccountReconciliationParams) =>
+                    `Upewnij się, że to konto jest takie samo jak <a href="${settlementAccountUrl}">konto rozliczeniowe karty Expensify</a> (kończące się na ${lastFourPAN}), aby Ciągłe Uzgadnianie działało poprawnie.`,
             },
-            syncTravelInvoicingSettlements: 'Synchronizuj rozliczenia faktur podróżnych',
         },
         export: {
             notReadyHeading: 'Niegotowe do eksportu',
@@ -6695,13 +5987,7 @@ _Aby uzyskać bardziej szczegółowe instrukcje, [odwiedź naszą stronę pomocy
             errors: {
                 rateNameRequired: 'Nazwa stawki jest wymagana',
                 existingRateName: 'Stawka za odległość o tej nazwie już istnieje',
-                nameRequired: 'Imię jest wymagane',
-                startDateMustBeBeforeEndDate: 'Data początkowa musi być wcześniejsza niż data końcowa',
-                amountRequired: 'Kwota jest wymagana',
             },
-            amountPerUnit: (unit: string) => `Kwota za ${unit}`,
-            startDate: 'Data rozpoczęcia',
-            endDate: 'Data zakończenia',
         },
         editor: {
             descriptionInputLabel: 'Opis',
@@ -6744,7 +6030,7 @@ _Aby uzyskać bardziej szczegółowe instrukcje, [odwiedź naszą stronę pomocy
             updateToUSD: 'Zaktualizuj na USD',
             updateWorkspaceCurrency: 'Zaktualizuj walutę przestrzeni roboczej',
             workspaceCurrencyNotSupported: 'Waluta przestrzeni roboczej nie jest obsługiwana',
-            yourWorkspace: `Twoje miejsce pracy jest ustawione na nieobsługiwaną walutę. Zobacz <a href="${CONST.ENABLE_GLOBAL_REIMBURSEMENT_HELP_URL}">listę obsługiwanych walut</a>.`,
+            yourWorkspace: `Twoje miejsce pracy jest ustawione na nieobsługiwaną walutę. Zobacz <a href="${CONST.CONNECT_A_BUSINESS_BANK_ACCOUNT_HELP_URL}">listę obsługiwanych walut</a>.`,
             chooseAnExisting: 'Wybierz istniejące konto bankowe do opłacania wydatków lub dodaj nowe.',
         },
         changeOwner: {
@@ -6781,7 +6067,7 @@ Jeśli chcesz przejąć rozliczenia za całą ich subskrypcję, poproś ich najp
             hasFailedSettlementsTitle: 'Nie można przenieść własności',
             hasFailedSettlementsButtonText: 'Rozumiem',
             hasFailedSettlementsText: (email: string) =>
-                `Nie możesz przejąć rozliczeń, ponieważ ${email} ma zaległe rozliczenie Karty Expensify. Poproś tę osobę o kontakt z concierge@expensify.com w celu rozwiązania problemu. Następnie będziesz mógł przejąć rozliczenia dla tego obszaru roboczego.`,
+                `Nie możesz przejąć rozliczeń, ponieważ ${email} ma zaległe rozliczenie karty Expensify Card. Poproś tę osobę o kontakt z concierge@expensify.com w celu rozwiązania problemu. Następnie będziesz mógł/mogła przejąć rozliczenia dla tego obszaru roboczego.`,
             failedToClearBalanceTitle: 'Nie udało się wyczyścić salda',
             failedToClearBalanceButtonText: 'OK',
             failedToClearBalanceText: 'Nie udało się wyczyścić salda. Spróbuj ponownie później.',
@@ -6810,12 +6096,6 @@ Czy na pewno chcesz wyeksportować je ponownie?`,
                 onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
                     `<muted-text>Pola raportu są dostępne tylko w planie Control, od <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `za użytkownika miesięcznie.` : `na aktywnego członka miesięcznie.`}</muted-text>`,
             },
-            invoiceFields: {
-                title: 'Pola faktury',
-                description: `Pola faktury pozwalają dodać dodatkowe szczegóły na poziomie faktury.`,
-                onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
-                    `<muted-text>Pola faktury są dostępne tylko w planie Control, od <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `za użytkownika miesięcznie.` : `na aktywnego członka miesięcznie.`}</muted-text>`,
-            },
             [CONST.POLICY.CONNECTIONS.NAME.NETSUITE]: {
                 title: 'NetSuite',
                 description: `Korzystaj z automatycznej synchronizacji i ograniczaj ręczne wprowadzanie danych dzięki integracji Expensify + NetSuite. Uzyskaj dogłębny, aktualny w czasie rzeczywistym wgląd w finanse dzięki obsłudze natywnych i niestandardowych segmentów, w tym mapowaniu projektów i klientów.`,
@@ -6834,12 +6114,6 @@ Czy na pewno chcesz wyeksportować je ponownie?`,
                 onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
                     `<muted-text>Nasza integracja z QuickBooks Desktop jest dostępna wyłącznie w planie Control, zaczynającym się od <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `za użytkownika miesięcznie.` : `na aktywnego członka miesięcznie.`}</muted-text>`,
             },
-            [CONST.POLICY.CONNECTIONS.NAME.CERTINIA]: {
-                title: 'Certinia',
-                description: `Korzystaj z automatycznej synchronizacji i ogranicz ręczne wprowadzanie danych dzięki integracji Expensify + Certinia. Dopasuj wymiary kategoryzacji wydatków i synchronizację podatków do konfiguracji Certinia, aby uzyskać lepszą widoczność finansową.`,
-                onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
-                    `<muted-text>Integracja z Certinia jest dostępna tylko w planie Control, zaczynającym się od <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `za użytkownika miesięcznie.` : `na aktywnego członka miesięcznie.`}</muted-text>`,
-            },
             [CONST.UPGRADE_FEATURE_INTRO_MAPPING.approvals.id]: {
                 title: 'Zaawansowane zatwierdzanie',
                 description: `Jeśli chcesz dodać więcej poziomów akceptacji – albo po prostu upewnić się, że największe wydatki zostaną przejrzane przez kolejną osobę – mamy na to rozwiązanie. Zaawansowane zatwierdzanie pomaga wdrożyć odpowiednie mechanizmy kontrolne na każdym poziomie, aby utrzymać wydatki zespołu pod kontrolą.`,
@@ -6917,7 +6191,7 @@ Wymagaj szczegółów wydatków, takich jak paragony i opisy, ustawiaj limity i
                 onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
                     `<muted-text>Stawki za przejazdy są dostępne w planie Collect, zaczynając od <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `za użytkownika miesięcznie.` : `na aktywnego członka miesięcznie.`}</muted-text>`,
             },
-            controlPolicyRoles: {
+            auditor: {
                 title: 'Audytor',
                 description: 'Biegli rewidentci otrzymują dostęp tylko do odczytu do wszystkich raportów, aby zapewnić pełną widoczność i monitorowanie zgodności.',
                 onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
@@ -6934,12 +6208,13 @@ Wymagaj szczegółów wydatków, takich jak paragony i opisy, ustawiaj limity i
                 perActiveMember: 'na aktywnego członka miesięcznie.',
                 perMember: 'za użytkownika miesięcznie.',
             },
-            note: (subscriptionLink: string) => `<muted-text><a href="${subscriptionLink}">Dowiedz się więcej</a> o naszych planach i cenach.</muted-text>`,
+            note: ({subscriptionLink}: WorkspaceUpgradeNoteParams) =>
+                `<muted-text>Uaktualnij, aby uzyskać dostęp do tej funkcji, lub <a href="${subscriptionLink}">dowiedz się więcej</a> o naszych planach i cenach.</muted-text>`,
             upgradeToUnlock: 'Odblokuj tę funkcję',
             completed: {
                 headline: `Zaktualizowano Twoją przestrzeń roboczą!`,
-                successMessage: (policyName: string, planName: string, subscriptionLink: string) =>
-                    `<centered-text>Udało Ci się uaktualnić ${policyName} do planu ${planName}! <a href="${subscriptionLink}">Wyświetl swoją subskrypcję</a>, aby uzyskać więcej szczegółów.</centered-text>`,
+                successMessage: ({policyName, subscriptionLink}: UpgradeSuccessMessageParams) =>
+                    `<centered-text>Udało Ci się uaktualnić ${policyName} do planu Control! <a href="${subscriptionLink}">Wyświetl swoją subskrypcję</a>, aby uzyskać więcej szczegółów.</centered-text>`,
                 categorizeMessage: `Pomyślnie uaktualniono do planu Collect. Teraz możesz kategoryzować swoje wydatki!`,
                 travelMessage: `Pomyślnie uaktualniono do planu Collect. Teraz możesz zacząć rezerwować i zarządzać podróżami!`,
                 distanceRateMessage: `Pomyślnie zmieniono plan na Collect. Teraz możesz zmienić stawkę za przejazd!`,
@@ -6963,87 +6238,25 @@ Wymagaj szczegółów wydatków, takich jak paragony i opisy, ustawiaj limity i
                 upgradeWorkspaceWarningForRestrictedPolicyCreationPrompt:
                     'Twoja firma ograniczyła możliwość tworzenia przestrzeni roboczych. Skontaktuj się z administratorem, aby uzyskać pomoc.',
             },
-            hr: {
-                title: 'Integracje HR',
-                description:
-                    'Połącz się ze swoim dostawcą HR, aby automatycznie synchronizować pracowników i zarządzać ścieżkami akceptacji. Utrzymuj listę członków zespołu i strukturę raportowania na bieżąco, bez ręcznej pracy.',
-                onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
-                    `<muted-text>Integracje HR są dostępne tylko w planie Control, zaczynającym się od <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `za osobę miesięcznie.` : `za aktywnego członka miesięcznie.`}</muted-text>`,
-            },
-            approvalSubmit: {
-                title: 'Zatwierdzenia',
-                description: 'Skonfiguruj centralnie, do kogo wszyscy członkowie składają raporty, włączając zatwierdzanie.',
-                onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
-                    `<muted-text>Zatwierdzanie jest dostępne w planach Collect i Control, zaczynając od <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `za członka za miesiąc.` : `za aktywnego członka miesięcznie.`}</muted-text>`,
-            },
-            companyCardSubmit: {
-                title: 'Firmowe karty',
-                description: `Dodaj swoją firmową kartę do Expensify, aby uzyskać automatyczny import, automatyczną kategoryzację, obsługę konfigurowalnych reguł i zintegrowane uzgadnianie.`,
-                onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
-                    `<muted-text>Importowanie kart firmowych jest dostępne w planach Collect i Control, zaczynających się od <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `za członka za miesiąc.` : `za aktywnego członka miesięcznie.`}</muted-text>`,
-            },
-            travelSubmit: {
-                title: 'Podróże Expensify',
-                description: 'Rezerwuj na całym świecie tańsze loty, hotele, samochody i pociągi bezpośrednio w Expensify, z raportami duty of care i zintegrowanym zarządzaniem wydatkami.',
-                onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
-                    `<muted-text>Expensify Travel jest dostępny w planach Collect i Control, zaczynając od <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `za członka za miesiąc.` : `za aktywnego członka miesięcznie.`}</muted-text>`,
-            },
-            roles: {
-                title: 'Role',
-                description: 'Przypisz różne role różnym członkom, aby w razie potrzeby zwiększyć lub zmniejszyć poziom widoczności i kontroli.',
-                onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
-                    `<muted-text>Role są dostępne w planach Collect i Control, zaczynając od <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `za członka za miesiąc.` : `za aktywnego członka miesięcznie.`}</muted-text>`,
-            },
-            payments: {
-                title: 'Płatności',
-                description: 'Zwracaj pracownikom wydatki bezpośrednio z firmowego konta bankowego.',
-                onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
-                    `<muted-text>Płatności są dostępne w planach Collect i Control, zaczynając od <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `za członka za miesiąc.` : `za aktywnego członka miesięcznie.`}</muted-text>`,
-            },
-            accounting: {
-                title: 'Księgowość',
-                description:
-                    'Synchronizuj kategorie, tagi, stawki podatkowe i więcej z Twojego systemu księgowego do Expensify, a także eksportuj raporty wydatków i transakcje kartą – bez przepisywania (i bez literówek)!',
-                onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
-                    `<muted-text>Księgowość jest dostępna w planach Collect i Control, zaczynając od <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `za członka za miesiąc.` : `za aktywnego członka miesięcznie.`}</muted-text>`,
-            },
-            expensifyCard: {
-                title: 'Karta Expensify',
-                description:
-                    'Wydawaj firmowe karty (w tym karty wirtualne) bezpośrednio z własnego konta bankowego, aby zyskać kontrolę nad wydatkami w czasie rzeczywistym dzięki nierozerwalnemu połączeniu i nawet do 2% zwrotu gotówki!',
-                onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
-                    `<muted-text>Karta Expensify jest dostępna w planach Collect i Control, zaczynając od <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `za członka za miesiąc.` : `za aktywnego członka miesięcznie.`}</muted-text>`,
-                upgradeButton: 'Ulepsz i włącz',
-            },
-            invoicing: {
-                title: 'Fakturowanie',
-                description:
-                    'Twórz, wysyłaj i śledź profesjonalne faktury — wszystko w Expensify. Otrzymuj płatności szybciej dzięki zintegrowanym płatnościom i wglądowi w czasie rzeczywistym.',
-                onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
-                    `<muted-text>Fakturowanie jest dostępne w planach Collect i Control, zaczynając od <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `za członka za miesiąc.` : `za aktywnego członka miesięcznie.`}</muted-text>`,
-            },
         },
         downgrade: {
             commonFeatures: {
                 title: 'Zmień plan na Collect',
-                note: 'Stracisz dostęp do następujących funkcji',
+                note: 'Jeśli przejdziesz na niższy plan, utracisz dostęp do tych funkcji i wielu innych:',
                 benefits: {
-                    confirm: 'Musisz zmienić „Typ planu” każdego obszaru roboczego na „Collect”, aby uzyskać stawkę Collect.',
-                    benefit1: 'NetSuite, Sage Intacct, QuickBooks Desktop, Oracle, Microsoft Dynamics',
-                    benefit2: 'Workday, Certinia',
-                    benefit3: 'SSO/SAML',
-                    benefit4: 'Inteligentne reguły wydatków, diety, wielopoziomowe zatwierdzanie, raportowanie niestandardowe i budżetowanie',
+                    note: 'Aby zobaczyć pełne porównanie naszych planów, sprawdź nasz',
+                    pricingPage: 'strona cenowa',
+                    confirm: 'Czy na pewno chcesz obniżyć plan i usunąć swoje konfiguracje?',
+                    warning: 'Tej operacji nie można cofnąć.',
+                    benefit1: 'Połączenia księgowe (z wyjątkiem QuickBooks Online i Xero)',
+                    benefit2: 'Inteligentne reguły wydatków',
+                    benefit3: 'Wielopoziomowe przepływy zatwierdzania',
+                    benefit4: 'Zaawansowane mechanizmy zabezpieczeń',
                     headsUp: 'Uwaga!',
                     multiWorkspaceNote:
                         'Przed pierwszą miesięczną płatnością musisz obniżyć pakiet wszystkich swoich przestrzeni roboczych, aby rozpocząć subskrypcję w taryfie Collect. Kliknij',
                     selectStep: '> wybierz każdą przestrzeń roboczą > zmień typ planu na',
-                    benefit1Label: 'Integracje ERP',
-                    benefit2Label: 'Integracje HR',
-                    benefit3Label: 'Bezpieczeństwo',
-                    benefit4Label: 'Zaawansowane',
-                    important: 'WAŻNE:',
                 },
-                noteAndMore: 'i więcej:',
             },
             completed: {
                 headline: 'Twoje środowisko pracy zostało zdegradowane',
@@ -7063,7 +6276,7 @@ Wymagaj szczegółów wydatków, takich jak paragony i opisy, ustawiaj limity i
         restrictedAction: {
             restricted: 'Ograniczone',
             actionsAreCurrentlyRestricted: (workspaceName: string) => `Działania w przestrzeni roboczej ${workspaceName} są obecnie ograniczone`,
-            workspaceOwnerWillNeedToAddOrUpdatePaymentCard: (workspaceOwnerName: string) =>
+            workspaceOwnerWillNeedToAddOrUpdatePaymentCard: ({workspaceOwnerName}: WorkspaceOwnerWillNeedToAddOrUpdatePaymentCardParams) =>
                 `Właściciel przestrzeni roboczej, ${workspaceOwnerName}, musi dodać lub zaktualizować zapisaną kartę płatniczą, aby odblokować nową aktywność w przestrzeni roboczej.`,
             youWillNeedToAddOrUpdatePaymentCard: 'Aby odblokować nowe działania w przestrzeni roboczej, musisz dodać lub zaktualizować zapisaną kartę płatniczą.',
             addPaymentCardToUnlock: 'Dodaj kartę płatniczą, aby odblokować!',
@@ -7116,18 +6329,16 @@ Wymagaj szczegółów wydatków, takich jak paragony i opisy, ustawiaj limity i
                 eReceiptsHint: `eParagony są automatycznie tworzone [dla większości transakcji kartą kredytową w USD](${CONST.DEEP_DIVE_ERECEIPTS}).`,
                 attendeeTracking: 'Śledzenie uczestników',
                 attendeeTrackingHint: 'Śledź koszt na osobę dla każdego wydatku.',
-                prohibitedDefaultDescription: 'Oznacz paragony z tymi pozycjami do ręcznej weryfikacji.',
+                prohibitedDefaultDescription:
+                    'Oznacz paragony, na których występują alkohol, hazard lub inne zabronione pozycje. Wydatki z paragonami zawierającymi takie pozycje będą wymagały ręcznego sprawdzenia.',
                 prohibitedExpenses: 'Wydatki niedozwolone',
                 alcohol: 'Alkohol',
                 hotelIncidentals: 'Dodatkowe opłaty hotelowe',
                 gambling: 'Hazard',
                 tobacco: 'Tytoń',
                 adultEntertainment: 'Rozrywka dla dorosłych',
-                giftCard: 'Zakup kart podarunkowych',
-                handwrittenReceipt: 'Odręczne paragony',
                 requireCompanyCard: 'Wymagaj kart służbowych dla wszystkich zakupów',
                 requireCompanyCardDescription: 'Oznacz wszystkie wydatki gotówkowe, w tym koszty za przejechane kilometry i ryczałty dzienne.',
-                requireCompanyCardDisabledTooltip: 'Włącz karty firmowe (w sekcji Więcej funkcji), aby odblokować.',
             },
             expenseReportRules: {
                 title: 'Zaawansowane',
@@ -7136,8 +6347,8 @@ Wymagaj szczegółów wydatków, takich jak paragony i opisy, ustawiaj limity i
                 preventSelfApprovalsSubtitle: 'Uniemożliwij członkom przestrzeni roboczej zatwierdzanie własnych raportów wydatków.',
                 autoApproveCompliantReportsTitle: 'Automatycznie zatwierdzaj zgodne raporty',
                 autoApproveCompliantReportsSubtitle: 'Skonfiguruj, które raporty wydatków kwalifikują się do automatycznego zatwierdzania.',
-                autoApproveReportsUnderTitle: 'Automatycznie zatwierdzaj raporty, gdy wszystkie wydatki są poniżej',
-                autoApproveReportsUnderDescription: 'W pełni zgodne raporty wydatków, w których wszystkie wydatki są poniżej tej kwoty, zostaną zatwierdzone automatycznie.',
+                autoApproveReportsUnderTitle: 'Automatycznie zatwierdzaj raporty poniżej',
+                autoApproveReportsUnderDescription: 'W pełni zgodne raporty wydatków poniżej tej kwoty zostaną zatwierdzone automatycznie.',
                 randomReportAuditTitle: 'Losowa kontrola raportów',
                 randomReportAuditDescription: 'Wymagaj ręcznego zatwierdzania niektórych raportów, nawet jeśli kwalifikują się do automatycznego zatwierdzenia.',
                 autoPayApprovedReportsTitle: 'Automatycznie opłacaj zatwierdzone raporty',
@@ -7150,7 +6361,6 @@ Wymagaj szczegółów wydatków, takich jak paragony i opisy, ustawiaj limity i
                 enableFeatureSubtitle: (featureName: string, moreFeaturesLink?: string) =>
                     `Przejdź do [więcej funkcji](${moreFeaturesLink}) i włącz ${featureName}, aby odblokować tę funkcję.`,
             },
-            agentsPromoBanner: {title: 'Nie widzisz potrzebnej reguły? Dodaj agenta', subtitle: 'Dodaj złożone reguły i ogranicz ręczne akceptacje dzięki własnym agentom.', cta: 'Wypróbuj'},
             merchantRules: {
                 title: 'Sprzedawca',
                 subtitle: 'Skonfiguruj reguły dla sprzedawców, aby wydatki trafiały z prawidłowym kodowaniem i wymagały mniej poprawek.',
@@ -7178,10 +6388,9 @@ Wymagaj szczegółów wydatków, takich jak paragony i opisy, ustawiaj limity i
                 matchTypeContains: 'Zawiera',
                 matchTypeExact: 'Dokładnie pasuje',
                 duplicateRuleTitle: 'Podobna reguła dla sprzedawcy już istnieje',
-                duplicateRulePrompt: (merchantName: string) => `Twoja istniejąca reguła dla „${merchantName}” będzie mieć pierwszeństwo przed tą. Zapisać mimo to?`,
+                duplicateRulePrompt: (merchantName: string) => `Czy chcesz zapisać nową regułę dla „${merchantName}”, mimo że masz już istniejącą?`,
                 saveAnyway: 'Zapisz mimo to',
                 applyToExistingUnsubmittedExpenses: 'Zastosuj do istniejących niewysłanych wydatków',
-                findRule: 'Znajdź regułę sprzedawcy',
             },
             categoryRules: {
                 title: 'Reguły kategorii',
@@ -7219,131 +6428,12 @@ Wymagaj szczegółów wydatków, takich jak paragony i opisy, ustawiaj limity i
                     always: 'Zawsze wymagaj zewidencjonowanych paragonów',
                 },
                 defaultTaxRate: 'Domyślna stawka podatku',
-                enableWorkflows: (moreFeaturesLink: string) =>
+                enableWorkflows: ({moreFeaturesLink}: RulesEnableWorkflowsParams) =>
                     `Przejdź do [Więcej funkcji](${moreFeaturesLink}) i włącz przepływy pracy, a następnie dodaj zatwierdzenia, aby odblokować tę funkcję.`,
             },
             customRules: {
                 title: 'Polityka wydatków',
                 cardSubtitle: 'To tutaj znajduje się polityka wydatków Twojego zespołu, aby wszyscy mieli jasność co do tego, co jest objęte.',
-                policyDocument: 'Dokument polityki',
-                policyText: 'Tekst polityki',
-            },
-            spendRules: {
-                title: 'Wydatki',
-                subtitle: 'Zatwierdzaj lub odrzucaj transakcje Karty Expensify w czasie rzeczywistym.',
-                defaultRuleDescription: 'Wszystkie karty',
-                block: 'Zablokuj',
-                defaultRuleTitle: 'Kategorie: Usługi dla dorosłych, bankomaty, hazard, przelewy pieniężne',
-                builtInProtectionModal: {
-                    title: 'Karty Expensify zapewniają wbudowaną ochronę – zawsze',
-                    description: `Expensify zawsze odrzuca te obciążenia:
-
-  • Usługi dla dorosłych
-  • Bankomaty
-  • Hazard
-  • Przelewy pieniężne
-
-Dodaj więcej zasad wydatków, żeby chronić płynność finansową firmy.`,
-                },
-                addSpendRule: 'Dodaj regułę wydatków',
-                cardPageTitle: 'Karta',
-                cardsSectionTitle: 'Karty',
-                chooseCards: 'Wybierz karty',
-                saveRule: 'Zapisz regułę',
-                allow: 'Zezwól',
-                spendRuleSectionTitle: 'Reguła wydatków',
-                restrictionType: 'Typ ograniczenia',
-                restrictionTypeHelpAllow: 'Obciążenia są zatwierdzane, jeśli pasują do jakiegokolwiek sprzedawcy lub kategorii i nie przekraczają maksymalnej kwoty.',
-                restrictionTypeHelpBlock: 'Obciążenia są odrzucane, jeśli pasują do jakiegokolwiek sprzedawcy lub kategorii albo przekraczają maksymalną kwotę.',
-                addMerchant: 'Dodaj sprzedawcę',
-                merchantContains: 'Sprzedawca zawiera',
-                merchantExactlyMatches: 'Sprzedawca dokładnie pasuje',
-                noBlockedMerchants: 'Brak zablokowanych sprzedawców',
-                addMerchantToBlockSpend: 'Dodaj sprzedawcę, aby zablokować wydatki',
-                noAllowedMerchants: 'Brak dozwolonych sprzedawców',
-                addMerchantToAllowSpend: 'Dodaj sprzedawcę, aby zezwolić na wydatki',
-                matchType: 'Typ dopasowania',
-                matchTypeContains: 'Zawiera',
-                matchTypeExact: 'Dokładnie pasuje',
-                spendCategory: 'Kategoria wydatków',
-                maxAmount: 'Maksymalna kwota',
-                maxAmountHelp: 'Każda transakcja powyżej tej kwoty zostanie odrzucona, niezależnie od ograniczeń dotyczących sprzedawcy i kategorii wydatków.',
-                currencyMismatchTitle: 'Niezgodność waluty',
-                currencyMismatchPrompt: 'Aby ustawić maksymalną kwotę, wybierz karty rozliczane w tej samej walucie.',
-                reviewSelectedCards: 'Przejrzyj wybrane karty',
-                summaryMoreCount: ({summary, count}: {summary: string; count: number}) => (count > 0 ? `${summary}, +${count} więcej` : summary),
-                confirmErrorApplyAtLeastOneSpendRuleToOneCard: 'Zastosuj co najmniej jedną regułę wydatków do jednej karty',
-                confirmErrorCardRequired: 'Pole „Karta” jest wymagane',
-                confirmErrorApplyAtLeastOneSpendRule: 'Zastosuj co najmniej jedną regułę wydatków',
-                categories: 'Kategorie',
-                merchants: 'Sprzedawcy',
-                noAvailableCards: 'Wszystkie karty mają już regułę',
-                noAvailableCardsSubtitle: 'Edytuj istniejącą regułę karty, aby wprowadzić zmiany',
-                noCardsIssuedTitle: 'Nie wydano żadnych Kart Expensify',
-                noCardsIssuedSubtitle: 'Wydaj karty Expensify, aby utworzyć zasady wydatków',
-                max: 'Maks',
-                categoryOptions: {
-                    [CONST.SPEND_RULES.CATEGORIES.AIRLINES]: 'Linie lotnicze',
-                    [CONST.SPEND_RULES.CATEGORIES.ALCOHOL_AND_BARS]: 'Alkohol i bary',
-                    [CONST.SPEND_RULES.CATEGORIES.AMAZON_AND_BOOKSTORES]: 'Amazon i księgarnie',
-                    [CONST.SPEND_RULES.CATEGORIES.AUTOMOTIVE]: 'Motoryzacja',
-                    [CONST.SPEND_RULES.CATEGORIES.CAR_RENTALS]: 'Wypożyczalnie samochodów',
-                    [CONST.SPEND_RULES.CATEGORIES.DINING]: 'Posiłki',
-                    [CONST.SPEND_RULES.CATEGORIES.FUEL_AND_GAS]: 'Paliwo i gaz',
-                    [CONST.SPEND_RULES.CATEGORIES.GOVERNMENT_AND_NON_PROFITS]: 'Sektor publiczny i organizacje non-profit',
-                    [CONST.SPEND_RULES.CATEGORIES.GROCERIES]: 'Zakupy spożywcze',
-                    [CONST.SPEND_RULES.CATEGORIES.GYMS_AND_FITNESS]: 'Siłownie i fitness',
-                    [CONST.SPEND_RULES.CATEGORIES.HEALTHCARE]: 'Opieka zdrowotna',
-                    [CONST.SPEND_RULES.CATEGORIES.HOTELS]: 'Hotele',
-                    [CONST.SPEND_RULES.CATEGORIES.INTERNET_AND_PHONE]: 'Internet i telefon',
-                    [CONST.SPEND_RULES.CATEGORIES.OFFICE_SUPPLIES]: 'Artykuły biurowe',
-                    [CONST.SPEND_RULES.CATEGORIES.PARKING_AND_TOLLS]: 'Parking i opłaty drogowe',
-                    [CONST.SPEND_RULES.CATEGORIES.PROFESSIONAL_SERVICES]: 'Usługi profesjonalne',
-                    [CONST.SPEND_RULES.CATEGORIES.RETAIL]: 'Sprzedaż detaliczna',
-                    [CONST.SPEND_RULES.CATEGORIES.SHIPPING_AND_DELIVERY]: 'Wysyłka i dostawa',
-                    [CONST.SPEND_RULES.CATEGORIES.SOFTWARE]: 'Oprogramowanie',
-                    [CONST.SPEND_RULES.CATEGORIES.TRANSIT_AND_RIDESHARE]: 'Transport i przejazdy współdzielone',
-                    [CONST.SPEND_RULES.CATEGORIES.TRAVEL_AGENCIES]: 'Biura podróży',
-                },
-                editRuleTitle: 'Edytuj regułę',
-                deleteRule: 'Usuń regułę',
-                deleteRuleConfirmation: 'Na pewno chcesz usunąć tę regułę?',
-                summaryMerchants: ({
-                    merchants,
-                    hiddenCount,
-                    shownCount,
-                    action,
-                }: {
-                    merchants: string;
-                    hiddenCount: number;
-                    shownCount: number;
-                    action: ValueOf<typeof CONST.SPEND_RULES.ACTION>;
-                }) =>
-                    `${action === CONST.SPEND_RULES.ACTION.BLOCK ? 'Zablokowane' : 'Dozwolone'} ${shownCount > 1 ? 'sprzedawcy' : 'sprzedawca'}: ${merchants}${hiddenCount > 0 ? `, +${hiddenCount} więcej` : ''}`,
-                summaryCategories: ({
-                    categories,
-                    hiddenCount,
-                    shownCount,
-                    action,
-                }: {
-                    categories: string;
-                    hiddenCount: number;
-                    shownCount: number;
-                    action: ValueOf<typeof CONST.SPEND_RULES.ACTION>;
-                }) =>
-                    `${action === CONST.SPEND_RULES.ACTION.BLOCK ? 'Zablokowane' : 'Dozwolone'} ${shownCount > 1 ? 'kategorie' : 'kategoria'}: ${categories}${hiddenCount > 0 ? `, +${hiddenCount} więcej` : ''}`,
-            },
-            aiRules: {
-                title: 'Zasady AI',
-                subtitle: 'Opisz elastyczne reguły, które działają wtedy, gdy ich potrzebujesz',
-                addRule: 'Dodaj regułę AI',
-                findRule: 'Znajdź regułę AI',
-                addRuleTitle: 'Dodaj regułę',
-                editRuleTitle: 'Edytuj regułę',
-                deleteRule: 'Usuń regułę',
-                deleteRuleConfirmation: 'Na pewno chcesz usunąć tę regułę?',
-                describeRuleTitle: 'Opisz swoją regułę',
-                describeRuleSubtitle: 'Opisz swoją regułę, a Concierge ją utworzy',
             },
         },
         planTypePage: {
@@ -7356,105 +6446,15 @@ Dodaj więcej zasad wydatków, żeby chronić płynność finansową firmy.`,
                     label: 'Sterowanie',
                     description: 'Dla organizacji z zaawansowanymi wymaganiami.',
                 },
-                submit2026: {
-                    label: 'Prześlij',
-                    description: 'Dla pracowników, którzy chcą przesyłać wydatki do pracodawcy.',
-                },
             },
-            description: 'Wybierz plan odpowiedni dla siebie.',
-            subscriptionLink: 'Dowiedz się więcej',
+            description: 'Wybierz plan odpowiedni dla siebie. Szczegółową listę funkcji i cen znajdziesz w naszej',
+            subscriptionLink: 'strona pomocy dotycząca typów planów i cen',
             lockedPlanDescription: ({count, annualSubscriptionEndDate}: WorkspaceLockedPlanTypeParams) => ({
                 one: `Zobowiązałeś(-aś) się do 1 aktywnego członka w planie Control do końca rocznej subskrypcji ${annualSubscriptionEndDate}. Możesz przejść na subskrypcję z rozliczaniem za użycie i zmienić plan na Collect od ${annualSubscriptionEndDate}, wyłączając automatyczne odnawianie w`,
                 other: `Zobowiązałeś(-aś) się do ${count} aktywnych członków w planie Control do końca rocznej subskrypcji ${annualSubscriptionEndDate}. Możesz przejść na subskrypcję płatną za użycie i zmienić plan na Collect od ${annualSubscriptionEndDate}, wyłączając automatyczne odnawianie w`,
             }),
             subscriptions: 'Subskrypcje',
         },
-        hr: {
-            title: 'HR',
-            connections: 'Połączenia',
-            connectionsSubtitle:
-                'Połącz się ze swoim systemem HR, aby synchronizować dane pracowników, automatycznie dopasowywać zwroty do właściwych osób i utrzymywać wydatki zespołu w porządku bez ręcznej pracy.',
-            subtitle: 'Połącz narzędzia HR i utrzymuj zgody pracowników w synchronizacji.',
-            connect: 'Połącz',
-            syncNow: 'Synchronizuj teraz',
-            disconnect: 'Odłącz',
-            disconnectTitle: (providerName: string) => `Odłącz ${providerName}`,
-            disconnectPrompt: (providerName: string) => `Czy na pewno chcesz odłączyć ${providerName}?`,
-            alreadyConnectedTitle: 'Nie można połączyć się z wieloma platformami HR',
-            alreadyConnectedPrompt: 'Musisz odłączyć swoją obecną platformę HR, zanim podłączysz inną.',
-            lastSync: (relativeDate: string) => `Ostatnia synchronizacja ${relativeDate}`,
-            syncError: (providerName: string) => `Nie można połączyć z ${providerName}`,
-            connectionDescription: (providerName: string) => `Połącz ${providerName}, aby synchronizować akceptacje pracowników z Twoim miejscem pracy.`,
-            approvalMode: 'Tryb zatwierdzania',
-            providerApprovalMode: (providerName: string) => `Tryb zatwierdzania ${providerName}`,
-            finalApprover: 'Ostateczny zatwierdzający',
-            providerFinalApprover: (providerName: string) => `Ostateczny zatwierdzający ${providerName}`,
-            notSet: 'Nie ustawiono',
-            approvalModeDescription: (providerName: string) => `Członkowie i menedżerowie są skonfigurowani do synchronizacji z ${providerName}.`,
-            approvalModeWarningTitle: 'Zmienić tryb zatwierdzania?',
-            approvalModeWarningPrompt: (providerName: string, helpSiteURL: string) =>
-                `Czy na pewno chcesz zmienić tryb zatwierdzania dla tego obszaru roboczego? Dowiedz się więcej o różnych trybach przepływu pracy obsługiwanych przez ${providerName} w naszej <a href="${helpSiteURL}">witrynie pomocy</a>.`,
-            approvalModeWarningConfirm: 'Zmień tryb zatwierdzania',
-            approvalModes: {
-                basic: {label: 'Podstawowe zatwierdzanie', description: 'Wszyscy użytkownicy przesyłają wydatki do jednej osoby w celu ich przetworzenia i zatwierdzenia.'},
-                manager: {
-                    label: 'Zatwierdzanie przez menedżera',
-                    description: (providerName: string) => `Pracownicy przesyłają raporty do swojego bezpośredniego menedżera skonfigurowanego w ${providerName}.`,
-                },
-                custom: {label: 'Niestandardowe zatwierdzanie', description: 'Ręcznie skonfiguruję procesy zatwierdzania w Expensify.'},
-            },
-            syncStageName: ({stage}: SyncStageNameConnectionsParams) => {
-                switch (stage) {
-                    case 'gustoSyncTitle':
-                        return 'Synchronizowanie pracowników Gusto';
-                    case 'gustoSyncLoadData':
-                        return 'Wczytywanie danych z Gusto';
-                    case 'gustoSyncProvisioning':
-                        return 'Przydzielanie pracowników w polisie';
-                    case 'zenefitsSyncTitle':
-                        return 'Synchronizowanie pracowników TriNet';
-                    case 'zenefitsSyncLoadData':
-                        return 'Wczytywanie danych z TriNet';
-                    case 'zenefitsSyncProvisioning':
-                        return 'Przydzielanie pracowników w polisie';
-                    case 'jobDone':
-                        return 'Oczekiwanie na załadowanie zaimportowanych danych';
-                    default: {
-                        return `Brak tłumaczenia dla etapu: ${stage}`;
-                    }
-                }
-            },
-            syncResults: {
-                title: (provider: string) => `Synchronizacja z ${provider} zakończona`,
-                successTitle: (provider: string) => `Pomyślnie zsynchronizowano twoje połączenie z ${provider}!`,
-                added: 'Dodano',
-                removed: 'Usunięto',
-                skipped: 'Pominięto',
-                employeeCount: () => ({
-                    one: '1 pracownik',
-                    other: (count: number) => `${count} pracownicy`,
-                }),
-            },
-            gusto: {
-                title: 'Gusto',
-            },
-            zenefits: {
-                title: 'TriNet',
-            },
-            syncingModalTitle: 'Twoje połączenie jest synchronizowane',
-            syncingModalDescription: 'Pierwsze połączenie może chwilę potrwać. Zostaniesz powiadomiony o wszelkich błędach.',
-            syncing: 'Synchronizowanie pracowników',
-            mergeHR: {
-                completeSetup: 'Zakończ konfigurację',
-                setupIncomplete: (setupLink: string | undefined) =>
-                    `<muted-text-label>Połączono. ${setupLink ? `<a href="${setupLink}">Zakończ konfigurację</a>` : 'Zakończ konfigurację'}, aby zaimportować pracowników.</muted-text-label>`,
-                groups: {title: 'Grupy', description: 'Wybierz grupy pracowników, które chcesz zsynchronizować z tą przestrzenią roboczą'},
-            },
-        },
-        emptyDomain: {
-            title: 'Zwiększ swoje bezpieczeństwo dzięki domenom',
-            subtitle: 'Wymagaj od członków swojej domeny logowania jednokrotnym logowaniem (SSO), ograniczaj tworzenie przestrzeni roboczych i nie tylko.',
-        },
     },
     getAssistancePage: {
         title: 'Uzyskaj pomoc',
@@ -7482,7 +6482,6 @@ Dodaj więcej zasad wydatków, żeby chronić płynność finansową firmy.`,
             symbols: 'Symbole',
             flags: 'Flagi',
         },
-        emojiNotSelected: 'Nie wybrano emotikony',
     },
     newRoomPage: {
         newRoom: 'Nowy pokój',
@@ -7495,7 +6494,7 @@ Dodaj więcej zasad wydatków, żeby chronić płynność finansową firmy.`,
         public_announceDescription: 'Każdy może znaleźć ten pokój',
         createRoom: 'Utwórz pokój',
         roomAlreadyExistsError: 'Pokój o tej nazwie już istnieje',
-        roomNameReservedError: (reservedName: string) => `${reservedName} to domyślny pokój we wszystkich przestrzeniach roboczych. Wybierz inną nazwę.`,
+        roomNameReservedError: ({reservedName}: RoomNameReservedErrorParams) => `${reservedName} to domyślny pokój we wszystkich przestrzeniach roboczych. Wybierz inną nazwę.`,
         roomNameInvalidError: 'Nazwy pokojów mogą zawierać tylko małe litery, cyfry i łączniki',
         pleaseEnterRoomName: 'Wprowadź nazwę pokoju',
         pleaseSelectWorkspace: 'Wybierz przestrzeń roboczą',
@@ -7503,7 +6502,7 @@ Dodaj więcej zasad wydatków, żeby chronić płynność finansową firmy.`,
             const actor = actorName ? `${actorName} ` : '';
             return isExpenseReport ? `${actor}zmieniono nazwę na „${newName}” (wcześniej „${oldName}”)` : `${actor} zmienił(a) nazwę tego pokoju na „${newName}” (wcześniej „${oldName}”)`;
         },
-        roomRenamedTo: (newName: string) => `Pokój zmieniono na ${newName}`,
+        roomRenamedTo: ({newName}: RoomRenamedToParams) => `Pokój zmieniono na ${newName}`,
         social: 'społeczny',
         selectAWorkspace: 'Wybierz przestrzeń roboczą',
         growlMessageOnRenameError: 'Nie można zmienić nazwy pokoju w przestrzeni roboczej. Sprawdź połączenie i spróbuj ponownie.',
@@ -7545,14 +6544,14 @@ Dodaj więcej zasad wydatków, żeby chronić płynność finansową firmy.`,
             `dodano ${approverName} (${approverEmail}) jako osobę zatwierdzającą dla pola ${field} „${name}”`,
         deleteApprovalRule: (approverEmail: string, approverName: string, field: string, name: string) =>
             `usunięto ${approverName} (${approverEmail}) jako osobę zatwierdzającą dla pola ${field} „${name}”`,
-        updateApprovalRule: (field: string, name: string, newApproverEmail: string, newApproverName: string | undefined, oldApproverEmail: string, oldApproverName: string | undefined) => {
+        updateApprovalRule: ({field, name, newApproverEmail, newApproverName, oldApproverEmail, oldApproverName}: UpdatedPolicyApprovalRuleParams) => {
             const formatApprover = (displayName?: string, email?: string) => (displayName ? `${displayName} (${email})` : email);
             return `zmieniono akceptującego dla pola ${field} „${name}” na ${formatApprover(newApproverName, newApproverEmail)} (wcześniej ${formatApprover(oldApproverName, oldApproverEmail)})`;
         },
-        addCategory: (categoryName: string) => `dodano kategorię „${categoryName}”`,
-        deleteCategory: (categoryName: string) => `usunięto kategorię „${categoryName}”`,
-        updateCategory: (categoryName: string, oldValue: boolean) => `${oldValue ? 'wyłączone' : 'włączone'} kategorię „${categoryName}”`,
-        updateCategoryPayrollCode: (categoryName: string, newValue?: string, oldValue?: string) => {
+        addCategory: ({categoryName}: UpdatedPolicyCategoryParams) => `dodano kategorię „${categoryName}”`,
+        deleteCategory: ({categoryName}: UpdatedPolicyCategoryParams) => `usunięto kategorię „${categoryName}”`,
+        updateCategory: ({oldValue, categoryName}: UpdatedPolicyCategoryParams) => `${oldValue ? 'wyłączone' : 'włączone'} kategorię „${categoryName}”`,
+        updateCategoryPayrollCode: ({oldValue, categoryName, newValue}: UpdatedPolicyCategoryGLCodeParams) => {
             if (!oldValue) {
                 return `dodano kod płacowy „${newValue}” do kategorii „${categoryName}”`;
             }
@@ -7561,7 +6560,7 @@ Dodaj więcej zasad wydatków, żeby chronić płynność finansową firmy.`,
             }
             return `zmienił(a) kod płacowy kategorii „${categoryName}” na „${newValue}” (wcześniej „${oldValue}”)`;
         },
-        updateCategoryGLCode: (categoryName: string, newValue?: string, oldValue?: string) => {
+        updateCategoryGLCode: ({oldValue, categoryName, newValue}: UpdatedPolicyCategoryGLCodeParams) => {
             if (!oldValue) {
                 return `dodano kod KG „${newValue}” do kategorii „${categoryName}”`;
             }
@@ -7570,10 +6569,10 @@ Dodaj więcej zasad wydatków, żeby chronić płynność finansową firmy.`,
             }
             return `zmienił(a) kod GL kategorii „${categoryName}” na „${newValue}” (wcześniej „${oldValue}”)`;
         },
-        updateAreCommentsRequired: (categoryName: string, oldValue: boolean) => {
+        updateAreCommentsRequired: ({oldValue, categoryName}: UpdatedPolicyCategoryParams) => {
             return `zmienił opis kategorii „${categoryName}” na ${!oldValue ? 'wymagane' : 'niewymagane'} (wcześniej ${!oldValue ? 'niewymagane' : 'wymagane'})`;
         },
-        updateCategoryMaxExpenseAmount: (categoryName: string, newAmount?: string, oldAmount?: string) => {
+        updateCategoryMaxExpenseAmount: ({categoryName, oldAmount, newAmount}: UpdatedPolicyCategoryMaxExpenseAmountParams) => {
             if (newAmount && !oldAmount) {
                 return `dodano maksymalną kwotę ${newAmount} do kategorii „${categoryName}”`;
             }
@@ -7582,26 +6581,26 @@ Dodaj więcej zasad wydatków, żeby chronić płynność finansową firmy.`,
             }
             return `zmieniono maksymalną kwotę dla kategorii „${categoryName}” na ${newAmount} (wcześniej ${oldAmount})`;
         },
-        updateCategoryExpenseLimitType: (categoryName: string, newValue: string, oldValue?: string) => {
+        updateCategoryExpenseLimitType: ({categoryName, oldValue, newValue}: UpdatedPolicyCategoryExpenseLimitTypeParams) => {
             if (!oldValue) {
                 return `dodano typ limitu ${newValue} do kategorii „${categoryName}”`;
             }
             return `zmienił(a) typ limitu kategorii „${categoryName}” na ${newValue} (wcześniej ${oldValue})`;
         },
-        updateCategoryMaxAmountNoReceipt: (categoryName: string, newValue: string, oldValue?: string) => {
+        updateCategoryMaxAmountNoReceipt: ({categoryName, oldValue, newValue}: UpdatedPolicyCategoryMaxAmountNoReceiptParams) => {
             if (!oldValue) {
                 return `zaktualizowano kategorię „${categoryName}”, zmieniając paragony na ${newValue}`;
             }
             return `zmieniono kategorię „${categoryName}” na ${newValue} (wcześniej ${oldValue})`;
         },
-        updateCategoryMaxAmountNoItemizedReceipt: (categoryName: string, oldValue: string | undefined, newValue: string) => {
+        updateCategoryMaxAmountNoItemizedReceipt: ({categoryName, oldValue, newValue}: UpdatedPolicyCategoryMaxAmountNoReceiptParams) => {
             if (!oldValue) {
                 return `zaktualizowano kategorię „${categoryName}”, zmieniając Pozycjonowane paragony na ${newValue}`;
             }
             return `zmienił(a) pozycjonowanie paragonów dla kategorii „${categoryName}” na ${newValue} (wcześniej ${oldValue})`;
         },
-        setCategoryName: (oldName: string, newName: string) => `zmieniono nazwę kategorii „${oldName}” na „${newName}”`,
-        updatedDescriptionHint: (categoryName: string, newValue?: string, oldValue?: string) => {
+        setCategoryName: ({oldName, newName}: UpdatedPolicyCategoryNameParams) => `zmieniono nazwę kategorii „${oldName}” na „${newName}”`,
+        updatedDescriptionHint: ({categoryName, oldValue, newValue}: UpdatedPolicyCategoryDescriptionHintTypeParams) => {
             if (!newValue) {
                 return `usunięto podpowiedź opisu „${oldValue}” z kategorii „${categoryName}”`;
             }
@@ -7609,44 +6608,44 @@ Dodaj więcej zasad wydatków, żeby chronić płynność finansową firmy.`,
                 ? `dodano podpowiedź opisu „${newValue}” do kategorii „${categoryName}”`
                 : `zmienił(-a) podpowiedź opisu kategorii „${categoryName}” na „${newValue}” (wcześniej „${oldValue}”)`;
         },
-        updateTagListName: (oldName: string, newName: string) => `zmienił nazwę listy tagów na „${newName}” (poprzednio „${oldName}”)`,
-        addTag: (tagListName: string, tagName?: string) => `dodano znacznik „${tagName}” do listy „${tagListName}”`,
-        updateTagName: (tagListName: string, newName: string, oldName: string) => `zaktualizowano listę znaczników „${tagListName}”, zmieniając znacznik „${oldName}” na „${newName}”`,
-        updateTagEnabled: (tagListName: string, tagName?: string, enabled?: boolean) => `${enabled ? 'włączone' : 'Wyłączone'} tag "${tagName}" na liście "${tagListName}"`,
-        deleteTag: (tagListName: string, tagName?: string) => `usunięto tag „${tagName}” z listy „${tagListName}”`,
-        deleteMultipleTags: (count?: string, tagListName?: string) => `usunięto tagi „${count}” z listy „${tagListName}”`,
-        updateTag: (tagListName: string, newValue: string, tagName: string, updatedField: string, oldValue?: string) => {
+        updateTagListName: ({oldName, newName}: UpdatedPolicyCategoryNameParams) => `zmienił nazwę listy tagów na „${newName}” (poprzednio „${oldName}”)`,
+        addTag: ({tagListName, tagName}: UpdatedPolicyTagParams) => `dodano znacznik „${tagName}” do listy „${tagListName}”`,
+        updateTagName: ({tagListName, newName, oldName}: UpdatedPolicyTagNameParams) => `zaktualizowano listę znaczników „${tagListName}”, zmieniając znacznik „${oldName}” na „${newName}”`,
+        updateTagEnabled: ({tagListName, tagName, enabled}: UpdatedPolicyTagParams) => `${enabled ? 'włączone' : 'Wyłączone'} tag "${tagName}" na liście "${tagListName}"`,
+        deleteTag: ({tagListName, tagName}: UpdatedPolicyTagParams) => `usunięto tag „${tagName}” z listy „${tagListName}”`,
+        deleteMultipleTags: ({count, tagListName}: UpdatedPolicyTagParams) => `usunięto tagi „${count}” z listy „${tagListName}”`,
+        updateTag: ({tagListName, newValue, tagName, updatedField, oldValue}: UpdatedPolicyTagFieldParams) => {
             if (oldValue) {
                 return `zaktualizowano znacznik „${tagName}” na liście „${tagListName}”, zmieniając ${updatedField} na „${newValue}” (wcześniej „${oldValue}”)`;
             }
             return `zaktualizowano znacznik „${tagName}” na liście „${tagListName}”, dodając ${updatedField} o wartości „${newValue}”`;
         },
-        updateCustomUnit: (customUnitName: string, newValue: string, oldValue: string, updatedField: string) =>
+        updateCustomUnit: ({customUnitName, newValue, oldValue, updatedField}: UpdatePolicyCustomUnitParams) =>
             `zmienił(a) ${updatedField} jednostki ${customUnitName} na „${newValue}” (wcześniej „${oldValue}”)`,
-        updateCustomUnitTaxEnabled: (newValue: boolean) => `${newValue ? 'włączone' : 'wyłączone'} śledzenie podatku dla stawek za dystans`,
-        addCustomUnitRate: (customUnitName: string, rateName: string) => `dodano stawkę jednostki niestandardowej ${customUnitName} „${rateName}”`,
-        updatedCustomUnitRate: (customUnitName: string, customUnitRateName: string, updatedField: string, newValue: string, oldValue: string) =>
+        updateCustomUnitTaxEnabled: ({newValue}: UpdatePolicyCustomUnitTaxEnabledParams) => `${newValue ? 'włączone' : 'wyłączone'} śledzenie podatku dla stawek za dystans`,
+        addCustomUnitRate: ({customUnitName, rateName}: AddOrDeletePolicyCustomUnitRateParams) => `dodano nową stawkę ${customUnitName} „${rateName}”`,
+        updatedCustomUnitRate: ({customUnitName, customUnitRateName, newValue, oldValue, updatedField}: UpdatedPolicyCustomUnitRateParams) =>
             `zmienił(a) stawkę ${customUnitName} ${updatedField} „${customUnitRateName}” na „${newValue}” (wcześniej „${oldValue}”)`,
-        updatedCustomUnitTaxRateExternalID: (customUnitRateName: string, newValue: string, newTaxPercentage: string, oldTaxPercentage?: string, oldValue?: string) => {
+        updatedCustomUnitTaxRateExternalID: ({customUnitRateName, newValue, newTaxPercentage, oldTaxPercentage, oldValue}: UpdatedPolicyCustomUnitTaxRateExternalIDParams) => {
             if (oldTaxPercentage && oldValue) {
                 return `zmienił(a) stawkę podatku w stawce za dystans „${customUnitRateName}” na „${newValue} (${newTaxPercentage})” (poprzednio „${oldValue} (${oldTaxPercentage})”)`;
             }
             return `dodano stawkę podatku „${newValue} (${newTaxPercentage})” do stawki za dystans „${customUnitRateName}”`;
         },
-        updatedCustomUnitTaxClaimablePercentage: (customUnitRateName: string, newValue: number, oldValue?: number) => {
+        updatedCustomUnitTaxClaimablePercentage: ({customUnitRateName, newValue, oldValue}: UpdatedPolicyCustomUnitTaxClaimablePercentageParams) => {
             if (oldValue) {
                 return `zmienił zwrotną część podatku w stawce za dystans „${customUnitRateName}” na „${newValue}” (wcześniej „${oldValue}”)`;
             }
             return `dodano odzyskiwalną część podatku w wysokości „${newValue}” do stawki za dystans „${customUnitRateName}”`;
         },
-        updatedCustomUnitRateName: (customUnitName: string, oldValue: string, newValue: string) => `zmienił nazwę stawki ${customUnitName} z „${oldValue}” na „${newValue}”`,
-        updatedCustomUnitRateEnabled: (customUnitName: string, customUnitRateName: string, newValue: boolean) => {
+        updatedCustomUnitRateEnabled: ({customUnitName, customUnitRateName, newValue}: UpdatedPolicyCustomUnitRateEnabledParams) => {
             return `${newValue ? 'włączone' : 'wyłączone'} stawkę jednostki niestandardowej ${customUnitName} „${customUnitRateName}”`;
         },
-        deleteCustomUnitRate: (customUnitName: string, rateName: string) => `usunięto stawkę „${rateName}” jednostki „${customUnitName}”`,
-        updateReportFieldDefaultValue: (defaultValue?: string, fieldName?: string) => `ustaw domyślną wartość pola raportu „${fieldName}” na „${defaultValue}”`,
-        addedReportFieldOption: (fieldName: string, optionName: string) => `dodano opcję „${optionName}” do pola raportu „${fieldName}”`,
-        removedReportFieldOption: (fieldName: string, optionName: string) => `usunął opcję „${optionName}” z pola raportu „${fieldName}”`,
+        deleteCustomUnitRate: ({customUnitName, rateName}: AddOrDeletePolicyCustomUnitRateParams) => `usunięto stawkę „${rateName}” jednostki „${customUnitName}”`,
+        addedReportField: ({fieldType, fieldName}: AddedOrDeletedPolicyReportFieldParams) => `dodano pole raportu ${fieldType} „${fieldName}”`,
+        updateReportFieldDefaultValue: ({defaultValue, fieldName}: UpdatedPolicyReportFieldDefaultValueParams) => `ustaw domyślną wartość pola raportu „${fieldName}” na „${defaultValue}”`,
+        addedReportFieldOption: (fieldName: any, optionName: string) => `dodano opcję „${optionName}” do pola raportu „${fieldName}”`,
+        removedReportFieldOption: (fieldName: any, optionName: string) => `usunął opcję „${optionName}” z pola raportu „${fieldName}”`,
         updateReportFieldOptionDisabled: (fieldName: string, optionName: string, optionEnabled: boolean) =>
             `${optionEnabled ? 'włączone' : 'wyłączone'} opcję „${optionName}” dla pola raportu „${fieldName}”`,
         updateReportFieldAllOptionsDisabled: (fieldName: string, optionName: string, allEnabled: boolean, toggledOptionsCount?: number) => {
@@ -7656,20 +6655,23 @@ Dodaj więcej zasad wydatków, żeby chronić płynność finansową firmy.`,
             return `${allEnabled ? 'włączone' : 'wyłączone'} opcję „${optionName}” dla pola raportu „${fieldName}”, ustawiając wszystkie opcje jako ${allEnabled ? 'włączone' : 'wyłączone'}`;
         },
         deleteReportField: ({fieldType, fieldName}: {fieldType: string; fieldName?: string}) => `usunięto pole raportu ${fieldType} „${fieldName}”`,
-        preventSelfApproval: (oldValue: string, newValue: string) =>
+        preventSelfApproval: ({oldValue, newValue}: UpdatedPolicyPreventSelfApprovalParams) =>
             `zaktualizowano „Zapobiegaj samodzielnemu zatwierdzaniu” na „${newValue === 'true' ? 'Włączone' : 'Wyłączone'}” (wcześniej „${oldValue === 'true' ? 'Włączone' : 'Wyłączone'}”)`,
-        updateMonthlyOffset: (oldValue: string, newValue: string) => {
+        updateMonthlyOffset: ({oldValue, newValue}: UpdatedPolicyFieldWithNewAndOldValueParams) => {
             if (!oldValue) {
                 return `ustaw miesięczną datę przesyłania raportu na „${newValue}”`;
             }
             return `zaktualizowano termin przesyłania comiesięcznego raportu na „${newValue}” (wcześniej „${oldValue}”)`;
         },
-        updateDefaultBillable: (oldValue: string, newValue: string) => `zaktualizowano „Refakturowanie wydatków klientom” na „${newValue}” (wcześniej „${oldValue}”)`,
-        updateDefaultReimbursable: (oldValue: string, newValue: string) => `zaktualizowano „Domyślne wydatki gotówkowe” na „${newValue}” (wcześniej „${oldValue}”)`,
-        updateDefaultTitleEnforced: (value: boolean) => `włączył(-a) „Wymuszanie domyślnych tytułów raportów” ${value ? 'włączone' : 'wyłączone'}`,
-        changedCustomReportNameFormula: (oldValue: string, newValue: string) => `zmieniono formułę nazwy raportu niestandardowego na „${newValue}” (wcześniej „${oldValue}”)`,
+        updateDefaultBillable: ({oldValue, newValue}: UpdatedPolicyFieldWithNewAndOldValueParams) =>
+            `zaktualizowano „Refakturowanie wydatków klientom” na „${newValue}” (wcześniej „${oldValue}”)`,
+        updateDefaultReimbursable: ({oldValue, newValue}: UpdatedPolicyFieldWithNewAndOldValueParams) =>
+            `zaktualizowano „Domyślne wydatki gotówkowe” na „${newValue}” (wcześniej „${oldValue}”)`,
+        updateDefaultTitleEnforced: ({value}: UpdatedPolicyFieldWithValueParams) => `włączył(-a) „Wymuszanie domyślnych tytułów raportów” ${value ? 'włączone' : 'wyłączone'}`,
+        changedCustomReportNameFormula: ({newValue, oldValue}: UpdatedPolicyFieldWithNewAndOldValueParams) =>
+            `zmieniono formułę nazwy raportu niestandardowego na „${newValue}” (wcześniej „${oldValue}”)`,
         renamedWorkspaceNameAction: (oldName: string, newName: string) => `zaktualizowano nazwę tego obszaru roboczego na „${newName}” (wcześniej „${oldName}”)`,
-        updateWorkspaceDescription: (newDescription: string, oldDescription: string) =>
+        updateWorkspaceDescription: ({newDescription, oldDescription}: UpdatedPolicyDescriptionParams) =>
             !oldDescription ? `ustaw opis tego obszaru roboczego na „${newDescription}”` : `zaktualizowano opis tego workspace’u na „${newDescription}” (wcześniej „${oldDescription}”)`,
         removedFromApprovalWorkflow: ({submittersNames}: RemovedFromApprovalWorkflowParams) => {
             let joinedNames = '';
@@ -7687,42 +6689,41 @@ Dodaj więcej zasad wydatków, żeby chronić płynność finansową firmy.`,
         },
         demotedFromWorkspace: (policyName: string, oldRole: string) =>
             `zaktualizowano Twoją rolę w ${policyName} z ${oldRole} na użytkownika. Zostałeś usunięty ze wszystkich czatów wydatków osób rozliczających się, z wyjątkiem własnego czatu.`,
-        updatedWorkspaceCurrencyAction: (oldCurrency: string, newCurrency: string) => `zaktualizowano domyślną walutę na ${newCurrency} (wcześniej ${oldCurrency})`,
-        updatedWorkspaceFrequencyAction: (oldFrequency: string, newFrequency: string) =>
+        updatedWorkspaceCurrencyAction: ({oldCurrency, newCurrency}: UpdatedPolicyCurrencyParams) => `zaktualizowano domyślną walutę na ${newCurrency} (wcześniej ${oldCurrency})`,
+        updatedWorkspaceFrequencyAction: ({oldFrequency, newFrequency}: UpdatedPolicyFrequencyParams) =>
             `zaktualizowano częstotliwość automatycznego raportowania na „${newFrequency}” (poprzednio „${oldFrequency}”)`,
         updateApprovalMode: ({newValue, oldValue}: ChangeFieldParams) => `zaktualizowano tryb zatwierdzania na „${newValue}” (wcześniej „${oldValue}”)`,
         upgradedWorkspace: 'zaktualizowano ten workspace do planu Control',
         forcedCorporateUpgrade: `Ta przestrzeń robocza została zaktualizowana do planu Control. Kliknij <a href="${CONST.COLLECT_UPGRADE_HELP_URL}">tutaj</a>, aby uzyskać więcej informacji.`,
         downgradedWorkspace: 'zmniejszono plan tego workspace’u do Collect',
-        updatedAuditRate: (oldAuditRate: number, newAuditRate: number) =>
+        updatedAuditRate: ({oldAuditRate, newAuditRate}: UpdatedPolicyAuditRateParams) =>
             `zmienił(a) odsetek raportów losowo kierowanych do ręcznej akceptacji na ${Math.round(newAuditRate * 100)}% (wcześniej ${Math.round(oldAuditRate * 100)}%)`,
-        updatedManualApprovalThreshold: (oldLimit: string, newLimit: string) => `zmienił(a) ręczny limit zatwierdzania dla wszystkich wydatków na ${newLimit} (wcześniej ${oldLimit})`,
+        updatedManualApprovalThreshold: ({oldLimit, newLimit}: UpdatedPolicyManualApprovalThresholdParams) =>
+            `zmienił(a) ręczny limit zatwierdzania dla wszystkich wydatków na ${newLimit} (wcześniej ${oldLimit})`,
         updatedFeatureEnabled: ({enabled, featureName}: {enabled: boolean; featureName: string}) => {
             switch (featureName) {
                 case 'categories':
                     return `${enabled ? 'włączone' : 'wyłączone'} kategorie`;
                 case 'tags':
-                    return `${enabled ? 'włączone' : 'wyłączone'} tagi`;
+                    return `${enabled ? 'włączone' : 'wyłączone'} etykiety`;
                 case 'workflows':
-                    return `${enabled ? 'włączone' : 'wyłączone'} przepływy pracy`;
+                    return `Procesy ${enabled ? 'włączone' : 'wyłączone'}`;
                 case 'distance rates':
-                    return `stawki za przejazdy ${enabled ? 'włączone' : 'wyłączone'}`;
+                    return `stawki za odległość ${enabled ? 'włączone' : 'wyłączone'}`;
                 case 'accounting':
                     return `${enabled ? 'włączone' : 'wyłączone'} księgowość`;
                 case 'Expensify Cards':
-                    return `${enabled ? 'włączone' : 'wyłączone'} Karty Expensify`;
-                case 'travel invoicing':
-                    return `Fakturowanie podróży ${enabled ? 'włączone' : 'wyłączone'}`;
+                    return `Karty Expensify ${enabled ? 'włączone' : 'wyłączone'}`;
                 case 'company cards':
-                    return `${enabled ? 'włączone' : 'wyłączone'} karty firmowe`;
+                    return `${enabled ? 'włączone' : 'wyłączone'} karty służbowe`;
                 case 'invoicing':
                     return `Fakturowanie ${enabled ? 'włączone' : 'wyłączone'}`;
                 case 'per diem':
-                    return `${enabled ? 'włączone' : 'wyłączone'} dieta dzienna`;
+                    return `${enabled ? 'włączone' : 'wyłączone'} diety`;
                 case 'receipt partners':
-                    return `partnerzy paragonów ${enabled ? 'włączone' : 'wyłączone'}`;
+                    return `Partnerzy paragonów ${enabled ? 'włączone' : 'wyłączone'}`;
                 case 'rules':
-                    return `${enabled ? 'włączone' : 'wyłączone'} zasad`;
+                    return `Zasady ${enabled ? 'włączone' : 'wyłączone'}`;
                 case 'tax tracking':
                     return `Śledzenie podatku ${enabled ? 'włączone' : 'wyłączone'}`;
                 default:
@@ -7793,17 +6794,14 @@ Dodaj więcej zasad wydatków, żeby chronić płynność finansową firmy.`,
             oldValue ? `zmieniono nazwę firmy na fakturze na „${newValue}” (poprzednio „${oldValue}”)` : `ustaw nazwę firmy na fakturze na „${newValue}”`,
         changedInvoiceCompanyWebsite: ({newValue, oldValue}: {newValue: string; oldValue?: string}) =>
             oldValue ? `zmienił(a) firmową stronę internetową faktury na „${newValue}” (poprzednio „${oldValue}”)` : `ustawiono firmową stronę internetową na fakturze na „${newValue}”`,
-        changedReimburser: (newReimburser: string, previousReimburser?: string) =>
+        changedReimburser: ({newReimburser, previousReimburser}: UpdatedPolicyReimburserParams) =>
             previousReimburser
                 ? `zmienił(a) upoważnioną osobę zwracającą wydatki na „${newReimburser}” (wcześniej „${previousReimburser}”)`
                 : `zmienił(a) upoważnionego płatnika na „${newReimburser}”`,
-        updateReimbursementEnabled: (enabled: boolean) => `${enabled ? 'włączone' : 'wyłączone'} zwrotów kosztów`,
-        updateCustomTaxName: (oldName: string, newName: string) => `zmieniono niestandardową nazwę podatku na „${newName}" (poprzednio „${oldName}")`,
-        updateCurrencyDefaultTax: (oldName: string, newName: string) => `zmienił domyślną stawkę podatku waluty w przestrzeni roboczej na „${newName}" (wcześniej „${oldName}")`,
-        updateForeignCurrencyDefaultTax: (oldName: string, newName: string) => `zmieniono domyślną stawkę podatku dla obcej waluty na „${newName}" (wcześniej „${oldName}")`,
-        addTax: (taxName: string) => `dodano podatek „${taxName}”`,
-        deleteTax: (taxName: string) => `usunął(-ę) podatek „${taxName}”`,
-        updateTax: (oldValue?: string | boolean | number, taxName?: string, updatedField?: string, newValue?: string | boolean | number) => {
+        updateReimbursementEnabled: ({enabled}: UpdatedPolicyReimbursementEnabledParams) => `${enabled ? 'włączone' : 'wyłączone'} zwrotów kosztów`,
+        addTax: ({taxName}: UpdatedPolicyTaxParams) => `dodano podatek „${taxName}”`,
+        deleteTax: ({taxName}: UpdatedPolicyTaxParams) => `usunął(-ę) podatek „${taxName}”`,
+        updateTax: ({oldValue, taxName, updatedField, newValue}: UpdatedPolicyTaxParams) => {
             if (!updatedField) {
                 return '';
             }
@@ -7825,31 +6823,28 @@ Dodaj więcej zasad wydatków, żeby chronić płynność finansową firmy.`,
                 }
             }
         },
-        setReceiptRequiredAmount: (newValue: string) => `ustaw wymaganą kwotę paragonu na „${newValue}”`,
-        changedReceiptRequiredAmount: (oldValue: string, newValue: string) => `zmienił(a) wymaganą kwotę paragonu na „${newValue}” (wcześniej „${oldValue}”)`,
-        removedReceiptRequiredAmount: (oldValue: string) => `usunięto wymagany limit paragonu (wcześniej „${oldValue}”)`,
-        setItemizedReceiptRequiredAmount: (newValue: string) => `ustaw wymaganą kwotę z wyszczególnionego paragonu na „${newValue}”`,
-        changedItemizedReceiptRequiredAmount: (oldValue: string, newValue: string) => `zmienił wymaganą kwotę za zindeksowany paragon na „${newValue}” (wcześniej „${oldValue}”)`,
-        removedItemizedReceiptRequiredAmount: (oldValue: string) => `usunięto wymaganą kwotę z rozbitego paragonu (wcześniej „${oldValue}”)`,
-        setMaxExpenseAmount: (newValue: string) => `ustaw maksymalną kwotę wydatku na „${newValue}”`,
-        changedMaxExpenseAmount: (oldValue: string, newValue: string) => `zmieniono maksymalną kwotę wydatku na „${newValue}” (wcześniej „${oldValue}”)`,
-        removedMaxExpenseAmount: (oldValue: string) => `usunięto maksymalną kwotę wydatku (wcześniej „${oldValue}”)`,
-        setMaxExpenseAge: (newValue: string) => `ustaw maksymalny wiek wydatku na „${newValue}” dni`,
-        changedMaxExpenseAge: (oldValue: string, newValue: string) => `zmieniono maksymalny wiek wydatku na „${newValue}” dni (wcześniej „${oldValue}”)`,
-        removedMaxExpenseAge: (oldValue: string) => `usunięto maksymalny wiek wydatku (wcześniej „${oldValue}” dni)`,
-        updateCategories: (count: number) => `zaktualizowano ${count} kategorie`,
-        updateTagList: (tagListName: string) => `zaktualizowano tagi na liście „${tagListName}”`,
-        updateTagListRequired: (tagListsName: string, isRequired: boolean) => `zmieniono listę tagów „${tagListsName}” na ${isRequired ? 'wymagane' : 'niewymagane'}`,
+        setReceiptRequiredAmount: ({newValue}: UpdatedPolicyFieldWithNewAndOldValueParams) => `ustaw wymaganą kwotę paragonu na „${newValue}”`,
+        changedReceiptRequiredAmount: ({oldValue, newValue}: UpdatedPolicyFieldWithNewAndOldValueParams) => `zmienił(a) wymaganą kwotę paragonu na „${newValue}” (wcześniej „${oldValue}”)`,
+        removedReceiptRequiredAmount: ({oldValue}: UpdatedPolicyFieldWithNewAndOldValueParams) => `usunięto wymagany limit paragonu (wcześniej „${oldValue}”)`,
+        setMaxExpenseAmount: ({newValue}: UpdatedPolicyFieldWithNewAndOldValueParams) => `ustaw maksymalną kwotę wydatku na „${newValue}”`,
+        changedMaxExpenseAmount: ({oldValue, newValue}: UpdatedPolicyFieldWithNewAndOldValueParams) => `zmieniono maksymalną kwotę wydatku na „${newValue}” (wcześniej „${oldValue}”)`,
+        removedMaxExpenseAmount: ({oldValue}: UpdatedPolicyFieldWithNewAndOldValueParams) => `usunięto maksymalną kwotę wydatku (wcześniej „${oldValue}”)`,
+        setMaxExpenseAge: ({newValue}: UpdatedPolicyFieldWithNewAndOldValueParams) => `ustaw maksymalny wiek wydatku na „${newValue}” dni`,
+        changedMaxExpenseAge: ({oldValue, newValue}: UpdatedPolicyFieldWithNewAndOldValueParams) => `zmieniono maksymalny wiek wydatku na „${newValue}” dni (wcześniej „${oldValue}”)`,
+        removedMaxExpenseAge: ({oldValue}: UpdatedPolicyFieldWithNewAndOldValueParams) => `usunięto maksymalny wiek wydatku (wcześniej „${oldValue}” dni)`,
+        updateCategories: ({count}: UpdatedPolicyCategoriesParams) => `zaktualizowano ${count} kategorie`,
+        updateTagList: ({tagListName}: UpdatedPolicyTagListParams) => `zaktualizowano tagi na liście „${tagListName}”`,
+        updateTagListRequired: ({tagListsName, isRequired}: UpdatedPolicyTagListRequiredParams) => `zmieniono listę tagów „${tagListsName}” na ${isRequired ? 'wymagane' : 'niewymagane'}`,
         importTags: 'zaimportowano tagi z arkusza kalkulacyjnego',
         deletedAllTags: 'usunął(-ę) wszystkie tagi',
-        updateCustomUnitDefaultCategory: (customUnitName: string, newValue?: string, oldValue?: string) =>
+        updateCustomUnitDefaultCategory: ({customUnitName, newValue, oldValue}: UpdatePolicyCustomUnitDefaultCategoryParams) =>
             `zmienił(a) domyślną kategorię jednostki ${customUnitName} na „${newValue}” ${oldValue ? `(uprzednio „${oldValue}”)` : ''}`,
-        importCustomUnitRates: (customUnitName: string) => `zaimportowano stawki dla niestandardowej jednostki „${customUnitName}”`,
-        updateCustomUnitSubRate: (customUnitName: string, customUnitRateName: string, customUnitSubRateName: string, oldValue: string, newValue: string, updatedField: string) =>
+        importCustomUnitRates: ({customUnitName}: ImportPolicyCustomUnitRatesParams) => `zaimportowano stawki dla niestandardowej jednostki „${customUnitName}”`,
+        updateCustomUnitSubRate: ({customUnitName, customUnitRateName, customUnitSubRateName, oldValue, newValue, updatedField}: UpdatedPolicyCustomUnitSubRateParams) =>
             `zmieniono stawkę „${customUnitName}” stawka „${customUnitRateName}” stawka podrzędna „${customUnitSubRateName}” ${updatedField} na „${newValue}” (wcześniej „${oldValue}”)`,
-        removedCustomUnitSubRate: (customUnitName: string, customUnitRateName: string, removedSubRateName: string) =>
+        removedCustomUnitSubRate: ({customUnitName, customUnitRateName, removedSubRateName}: RemovedPolicyCustomUnitSubRateParams) =>
             `usunięto stawkę „${customUnitName}” o nazwie „${customUnitRateName}” i podstawkę „${removedSubRateName}”`,
-        addBudget: (frequency: string, entityName: string, entityType: string, shared?: string, individual?: string, notificationThreshold?: number) => {
+        addBudget: ({frequency, entityName, entityType, shared, individual, notificationThreshold}: AddBudgetParams) => {
             const thresholdSuffix = typeof notificationThreshold === 'number' ? `z progiem powiadomień wynoszącym „${notificationThreshold}%”` : '';
             if (typeof shared !== 'undefined' && typeof individual !== 'undefined') {
                 return `dodano ${frequency} indywidualny budżet „${individual}” oraz ${frequency} współdzielony budżet „${shared}”${thresholdSuffix} do ${entityType} „${entityName}”`;
@@ -7859,18 +6854,18 @@ Dodaj więcej zasad wydatków, żeby chronić płynność finansową firmy.`,
             }
             return `dodano ${frequency} współdzielony budżet „${shared}”${thresholdSuffix} do ${entityType} „${entityName}”`;
         },
-        updateBudget: (
-            entityType: string,
-            entityName: string,
-            oldFrequency?: string,
-            newFrequency?: string,
-            oldIndividual?: string,
-            newIndividual?: string,
-            oldShared?: string,
-            newShared?: string,
-            oldNotificationThreshold?: number,
-            newNotificationThreshold?: number,
-        ) => {
+        updateBudget: ({
+            entityType,
+            entityName,
+            oldFrequency,
+            newFrequency,
+            oldIndividual,
+            newIndividual,
+            oldShared,
+            newShared,
+            oldNotificationThreshold,
+            newNotificationThreshold,
+        }: UpdatedBudgetParams) => {
             const frequencyChanged = !!(newFrequency && oldFrequency !== newFrequency);
             const sharedChanged = !!(newShared && oldShared !== newShared);
             const individualChanged = !!(newIndividual && oldIndividual !== newIndividual);
@@ -7905,7 +6900,7 @@ Dodaj więcej zasad wydatków, żeby chronić płynność finansową firmy.`,
             }
             return `zaktualizowano budżet dla ${entityType} „${entityName}”: ${changesList.join('; ')}`;
         },
-        deleteBudget: (entityType: string, entityName: string, frequency?: string, individual?: string, shared?: string, notificationThreshold?: number) => {
+        deleteBudget: ({entityType, entityName, frequency, individual, shared, notificationThreshold}: DeleteBudgetParams) => {
             const thresholdSuffix = typeof notificationThreshold === 'number' ? `z progiem powiadomień wynoszącym „${notificationThreshold}%”` : '';
             if (shared && individual) {
                 return `usunięto ${frequency} współdzielony budżet „${shared}” oraz indywidualny budżet „${individual}”${thresholdSuffix} z ${entityType} „${entityName}”`;
@@ -7918,125 +6913,48 @@ Dodaj więcej zasad wydatków, żeby chronić płynność finansową firmy.`,
             }
             return `usunięto budżet z ${entityType} „${entityName}”`;
         },
-        updatedTimeEnabled: (enabled?: boolean) => {
+        updatedTimeEnabled: ({enabled}: UpdatedPolicyTimeEnabledParams) => {
             return `${enabled ? 'włączone' : 'wyłączone'} śledzenie czasu`;
         },
-        updatedTimeRate: (newRate?: string, oldRate?: string) => {
+        updatedTimeRate: ({newRate, oldRate}: UpdatedPolicyTimeRateParams) => {
             return `zmieniono stawkę godzinową na „${newRate}” (wcześniej „${oldRate}”)`;
         },
         addedProhibitedExpense: ({prohibitedExpense}: {prohibitedExpense: string}) => `dodano „${prohibitedExpense}” do zabronionych wydatków`,
         removedProhibitedExpense: ({prohibitedExpense}: {prohibitedExpense: string}) => `usunięto „${prohibitedExpense}” z wydatków zabronionych`,
-        updatedReimbursementChoice: (newReimbursementChoice: string, oldReimbursementChoice: string) =>
+        updatedReimbursementChoice: ({newReimbursementChoice, oldReimbursementChoice}: UpdatedPolicyReimbursementChoiceParams) =>
             `zmieniono metodę zwrotu kosztów na „${newReimbursementChoice}” (wcześniej „${oldReimbursementChoice}”)`,
         setAutoJoin: ({enabled}: {enabled: boolean}) => `${enabled ? 'włączone' : 'wyłączone'} wstępna akceptacja próśb o dołączenie do przestrzeni workspace`,
-        updatedDefaultTitle: (newDefaultTitle: string, oldDefaultTitle: string) =>
+        updatedDefaultTitle: ({newDefaultTitle, oldDefaultTitle}: UpdatedPolicyDefaultTitleParams) =>
             `zmieniono formułę nazwy niestandardowego raportu na „${newDefaultTitle}” (wcześniej „${oldDefaultTitle}”)`,
-        updatedOwnership: (oldOwnerEmail: string, oldOwnerName: string, policyName: string) => `przejął(a) własność ${policyName} od ${oldOwnerName} (${oldOwnerEmail})`,
-        updatedAutoHarvesting: (enabled: boolean) => `Zaplanowane przesłanie ${enabled ? 'włączone' : 'wyłączone'}`,
-        updatedIndividualBudgetNotification: (
-            budgetAmount: string,
-            budgetFrequency: string,
-            budgetName: string,
-            budgetTypeForNotificationMessage: string,
-            thresholdPercentage: number,
-            totalSpend: number,
-            unsubmittedSpend: number,
-            awaitingApprovalSpend: number,
-            approvedReimbursedClosedSpend: number,
-            summaryLink?: string,
-            userEmail?: string,
-        ) =>
+        updatedOwnership: ({oldOwnerEmail, oldOwnerName, policyName}: UpdatedPolicyOwnershipParams) => `przejął(a) własność ${policyName} od ${oldOwnerName} (${oldOwnerEmail})`,
+        updatedAutoHarvesting: ({enabled}: UpdatedPolicyAutoHarvestingParams) => `Zaplanowane przesłanie ${enabled ? 'włączone' : 'wyłączone'}`,
+        updatedIndividualBudgetNotification: ({
+            budgetAmount,
+            budgetFrequency,
+            budgetName,
+            budgetTypeForNotificationMessage,
+            summaryLink,
+            thresholdPercentage,
+            totalSpend,
+            unsubmittedSpend,
+            userEmail,
+            awaitingApprovalSpend,
+            approvedReimbursedClosedSpend,
+        }: UpdatedPolicyBudgetNotificationParams) =>
             `Uwaga! Ta przestrzeń robocza ma ${budgetFrequency} budżet w wysokości „${budgetAmount}” dla ${budgetTypeForNotificationMessage} „${budgetName}”. ${userEmail} jest obecnie na poziomie ${approvedReimbursedClosedSpend}, co przekracza ${thresholdPercentage}% budżetu. Jest też ${awaitingApprovalSpend} oczekujące na zatwierdzenie oraz ${unsubmittedSpend}, które nie zostały jeszcze przesłane, co daje łączną kwotę ${totalSpend}.${summaryLink ? `<a href="${summaryLink}">Oto raport</a> ze wszystkimi tymi wydatkami do Twojej dokumentacji!` : ''}`,
-        updatedSharedBudgetNotification: (
-            budgetAmount: string,
-            budgetFrequency: string,
-            budgetName: string,
-            budgetTypeForNotificationMessage: string,
-            summaryLink: string | undefined,
-            thresholdPercentage: number,
-            totalSpend: number,
-            unsubmittedSpend: number,
-            awaitingApprovalSpend: number,
-            approvedReimbursedClosedSpend: number,
-        ) =>
+        updatedSharedBudgetNotification: ({
+            budgetAmount,
+            budgetFrequency,
+            budgetName,
+            budgetTypeForNotificationMessage,
+            summaryLink,
+            thresholdPercentage,
+            totalSpend,
+            unsubmittedSpend,
+            awaitingApprovalSpend,
+            approvedReimbursedClosedSpend,
+        }: UpdatedPolicyBudgetNotificationParams) =>
             `Uwaga! Ta przestrzeń robocza ma ${budgetFrequency} budżet w wysokości „${budgetAmount}” dla ${budgetTypeForNotificationMessage} „${budgetName}”. Obecnie wykorzystano ${approvedReimbursedClosedSpend}, co przekracza ${thresholdPercentage}% budżetu. Dodatkowo ${awaitingApprovalSpend} czeka na zatwierdzenie, a ${unsubmittedSpend} nie zostało jeszcze przesłane, co daje łącznie ${totalSpend}. ${summaryLink ? `<a href="${summaryLink}">Oto raport</a> ze wszystkimi tymi wydatkami do Twoich dokumentów!` : ''}`,
-        addedCardFeed: (feedName: string) => `dodano strumień karty „${feedName}”`,
-        removedCardFeed: (feedName: string) => `usunięto kanał karty „${feedName}”`,
-        renamedCardFeed: (newName: string, oldName: string) => `zmieniono nazwę kanału karty na „${newName}” (wcześniej „${oldName}”)`,
-        assignedCompanyCard: (email: string, feedName: string, cardLastFour: string) =>
-            `przypisano użytkownikowi ${email} ${feedName ? `„${feedName}" ` : ''}firmową kartę kończącą się na ${cardLastFour}`,
-        unassignedCompanyCard: (email: string, feedName: string, cardLastFour: string) =>
-            `nieprzypisana ${feedName ? `„${feedName}" ` : ''}firmowa karta ${email} kończąca się na ${cardLastFour}`,
-        updatedCardFeedLiability: (feedName: string, enabled: boolean) =>
-            `${enabled ? 'włączone' : 'wyłączone'} posiadaczy karty może usuwać transakcje z karty dla kanału kart „${feedName}”`,
-        updatedCardFeedStatementPeriod: (feedName: string, newValue?: string, previousValue?: string) =>
-            `zmienił dzień zakończenia okresu rozliczeniowego dla źródła karty „${feedName}”${newValue ? ` na „${newValue}”` : ''}${previousValue ? ` (wcześniej „${previousValue}”)` : ''}`,
-        addedReportField: (fieldType: string, fieldName?: string, defaultValue?: string) =>
-            `dodano pole raportu typu ${fieldType} „${fieldName}”${defaultValue ? ` z domyślną wartością „${defaultValue}”` : ''}`,
-        updatedMccGroupCategory: ({mccGroupName, oldCategory, newCategory}: {mccGroupName: string; oldCategory: string; newCategory: string}) =>
-            `zmieniono domyślną kategorię wydatków dla „${mccGroupName}” na „${newCategory}” (poprzednio „${oldCategory}”)`,
-        updatedRequireCompanyCards: ({enabled}: {enabled: boolean}) => `${enabled ? 'włączone' : 'wyłączone'} wymóg dotyczący zakupów kartą służbową`,
-        expensifyCardRule: {
-            actionVerb: {block: 'zablokowane', allow: 'dozwolone'},
-            amountOperator: {over: 'ponad', under: 'pod'},
-            amountFilter: ({operator, amount}: {operator: string; amount: string}) => `kwoty ${operator} ${amount}`,
-            theCard: 'karta',
-            multipleCards: ({count}: {count: number}) => ({
-                one: '1 karta',
-                other: `${count} karty`,
-            }),
-            addRule: ({verb, filters, cards}: {verb: string; filters: string; cards: string}) => {
-                let text = verb;
-                if (filters !== '') {
-                    text += ` ${filters}`;
-                }
-                text += ` na ${cards}`;
-                return text;
-            },
-            removeRule: ({cards}: {cards: string}) => `usunięto regułę wydatków z ${cards}`,
-            restrictionVerb: {block: 'zablokuj', allow: 'zezwalaj tylko'},
-            update: {
-                modeChange: ({fromAction, toAction, cards}: {fromAction: string; toAction: string; cards: string}) => `zmieniono regułę wydatków z ${fromAction} na ${toAction} na ${cards}`,
-                appliedToAdditionalCards: ({count}: {count: number}) => ({
-                    one: 'zastosowano regułę wydatków do 1 dodatkowej karty',
-                    other: `zastosowano regułę wydatków do ${count} dodatkowych kart`,
-                }),
-                phraseVerb: {added: 'dodano', removed: 'usunięto', changed: 'zmieniono', set: 'ustaw', applied: 'zastosowano'},
-                bodyMerchant: ({adjective, value}: {adjective: string; value: string}) => (adjective !== '' ? `${adjective} sprzedawca '${value}'` : `sprzedawca „${value}”`),
-                bodyMerchantChange: ({adjective, oldValue, newValue}: {adjective: string; oldValue: string; newValue: string}) =>
-                    adjective !== '' ? `zmieniono ${adjective} sprzedawcę z „${oldValue}” na „${newValue}”` : `sprzedawcę z „${oldValue}” na „${newValue}”`,
-                bodySpendCategory: ({adjective, value}: {adjective: string; value: string}) =>
-                    adjective !== '' ? `${adjective} kategoria wydatków „${value}”` : `kategoria wydatków „${value}”`,
-                bodySpendCategoryChange: ({adjective, oldValue, newValue}: {adjective: string; oldValue: string; newValue: string}) =>
-                    adjective !== '' ? `${adjective} kategorię wydatków z „${oldValue}” na „${newValue}”` : `kategorię wydatku z „${oldValue}” na „${newValue}”`,
-                bodyMaxAmount: 'maksymalna kwota',
-                bodyMaxAmountSet: ({value}: {value: string}) => `maksymalna kwota do ${value}`,
-                bodyMaxAmountChange: ({oldValue, newValue}: {oldValue: string; newValue: string}) => `maksymalną kwotę z ${oldValue} na ${newValue}`,
-                bodyAppliedToAdditionalCards: ({count}: {count: number}) => ({
-                    one: 'zasada wydatków dla 1 dodatkowej karty',
-                    other: `zasada wydatków dla ${count} dodatkowych kart`,
-                }),
-                bodyRemovedFromCards: ({cards}: {cards: string}) => `zasada wydatków z ${cards}`,
-                composeOnCards: ({content, cards}: {content: string; cards: string}) => `${content} na ${cards}`,
-                composeFromCards: ({content, cards}: {content: string; cards: string}) => `${content} z ${cards}`,
-            },
-        },
-        addCustomUnitRateWithAmount: (rateName: string, rateValue: string) => `dodano stawkę „${rateName}” w wysokości ${rateValue}`,
-        addCustomUnitRateWithAmountAndStartDate: (rateName: string, rateValue: string, startDate: string) =>
-            `dodano stawkę „${rateName}” w wysokości ${rateValue}, obowiązującą od ${startDate}`,
-        addCustomUnitRateWithAmountAndEndDate: (rateName: string, rateValue: string, endDate: string) => `dodano stawkę „${rateName}” w wysokości ${rateValue}, obowiązującą do ${endDate}`,
-        addCustomUnitRateWithAmountAndDates: (rateName: string, rateValue: string, startDate: string, endDate: string) =>
-            `dodano stawkę „${rateName}” w wysokości ${rateValue}, obowiązującą od ${startDate} do ${endDate}`,
-        updatedCustomUnitRateStartDate: (rateName: string, newDate: string, oldDate?: string) =>
-            oldDate ? `zaktualizowano datę rozpoczęcia stawki „${rateName}” na ${newDate} (wcześniej ${oldDate})` : `ustaw datę rozpoczęcia stawki „${rateName}” na ${newDate}`,
-        updatedCustomUnitRateEndDate: (rateName: string, newDate: string, oldDate?: string) =>
-            oldDate ? `zaktualizowano datę końcową stawki „${rateName}” na ${newDate} (wcześniej ${oldDate})` : `ustaw datę zakończenia stawki „${rateName}” na ${newDate}`,
-        updatedCustomUnitRateStartAndEndDate: (rateName: string, newStartDate: string, newEndDate: string, oldStartDate?: string, oldEndDate?: string) =>
-            oldStartDate && oldEndDate
-                ? `zaktualizowano datę początkową i końcową stawki „${rateName}” na ${newStartDate} – ${newEndDate} (wcześniej ${oldStartDate} – ${oldEndDate})`
-                : `ustaw początkową i końcową datę stawki „${rateName}” na ${newStartDate} – ${newEndDate}`,
-        removedCustomUnitRateStartDate: (rateName: string, oldDate: string) => `usunięto datę początkową ze stawki „${rateName}” (wcześniej ${oldDate})`,
-        removedCustomUnitRateEndDate: (rateName: string, oldDate: string) => `usunięto datę zakończenia ze stawki „${rateName}” (wcześniej ${oldDate})`,
     },
     roomMembersPage: {
         memberNotFound: 'Nie znaleziono członka.',
@@ -8068,7 +6986,7 @@ Dodaj więcej zasad wydatków, żeby chronić płynność finansową firmy.`,
         completed: 'Zakończono',
         action: 'Zakończ',
         messages: {
-            created: (title: string) => `zadanie dla ${title}`,
+            created: ({title}: TaskCreatedActionParams) => `zadanie dla ${title}`,
             completed: 'oznaczono jako ukończone',
             canceled: 'usunięte zadanie',
             reopened: 'oznaczono jako niekompletne',
@@ -8082,7 +7000,7 @@ Dodaj więcej zasad wydatków, żeby chronić płynność finansową firmy.`,
         deleteConfirmation: 'Czy na pewno chcesz usunąć to zadanie?',
     },
     statementPage: {
-        title: (year: number | string, monthName: string) => `Wyciąg za ${monthName} ${year}`,
+        title: ({year, monthName}: StatementTitleParams) => `Wyciąg za ${monthName} ${year}`,
     },
     keyboardShortcutsPage: {
         title: 'Skróty klawiaturowe',
@@ -8095,8 +7013,6 @@ Dodaj więcej zasad wydatków, żeby chronić płynność finansową firmy.`,
             newChat: 'Nowy ekran czatu',
             copy: 'Skopiuj komentarz',
             openDebug: 'Otwórz okno preferencji testowania',
-            expenseReportSearch: 'Szukaj raportów wydatków',
-            goToWorkspace: 'Przejdź do przestrzeni roboczej bieżącego raportu',
         },
     },
     guides: {
@@ -8106,8 +7022,6 @@ Dodaj więcej zasad wydatków, żeby chronić płynność finansową firmy.`,
     search: {
         resultsAreLimited: 'Wyniki wyszukiwania są ograniczone.',
         viewResults: 'Zobacz wyniki',
-        applyFilters: 'Zastosuj filtry',
-        appliedFilters: 'Zastosowane filtry',
         resetFilters: 'Resetuj filtry',
         searchResults: {
             emptyResults: {
@@ -8115,23 +7029,27 @@ Dodaj więcej zasad wydatków, żeby chronić płynność finansową firmy.`,
                 subtitle: `Spróbuj zmienić kryteria wyszukiwania lub utworzyć coś za pomocą przycisku +.`,
             },
             emptyExpenseResults: {
-                title: 'Brak wydatków',
+                title: 'Nie utworzyłeś jeszcze żadnych wydatków',
                 subtitle: 'Utwórz wydatek lub wypróbuj Expensify, aby dowiedzieć się więcej.',
                 subtitleWithOnlyCreateButton: 'Użyj zielonego przycisku poniżej, aby utworzyć wydatek.',
             },
             emptyReportResults: {
-                title: 'Brak raportów',
+                title: 'Nie utworzyłeś jeszcze żadnych raportów',
                 subtitle: 'Utwórz raport lub wypróbuj Expensify, aby dowiedzieć się więcej.',
                 subtitleWithOnlyCreateButton: 'Użyj zielonego przycisku poniżej, aby utworzyć raport.',
             },
             emptyInvoiceResults: {
-                title: 'Brak faktur',
+                title: dedent(`
+                    Nie utworzyłeś(-aś) jeszcze żadnych faktur
+                `),
                 subtitle: 'Wyślij fakturę lub wypróbuj Expensify, aby dowiedzieć się więcej.',
                 subtitleWithOnlyCreateButton: 'Użyj zielonego przycisku poniżej, aby wysłać fakturę.',
-                subtitleCannotSend: 'Potrzebujesz przestrzeni roboczej z włączonym Invoices, aby wysyłać faktury.',
-                subtitleCannotSendWithTestDrive: 'Potrzebujesz przestrzeni roboczej z włączonym Invoices, aby wysyłać faktury. Wypróbuj Expensify, aby dowiedzieć się więcej.',
             },
-            emptyTripResults: {title: 'Brak podróży', subtitle: 'Zacznij od zarezerwowania swojej pierwszej podróży poniżej.', buttonText: 'Zarezerwuj podróż'},
+            emptyTripResults: {
+                title: 'Brak podróży do wyświetlenia',
+                subtitle: 'Zacznij od zarezerwowania swojej pierwszej podróży poniżej.',
+                buttonText: 'Zarezerwuj podróż',
+            },
             emptySubmitResults: {
                 title: 'Brak wydatków do przesłania',
                 subtitle: 'Wszystko gotowe. Czas na rundę zwycięstwa!',
@@ -8159,31 +7077,30 @@ Dodaj więcej zasad wydatków, żeby chronić płynność finansową firmy.`,
             },
         },
         columns: 'Kolumny',
-        editColumns: 'Edytuj kolumny',
         resetColumns: 'Resetuj kolumny',
         groupColumns: 'Grupuj kolumny',
         expenseColumns: 'Kolumny wydatków',
-        saveView: 'Zapisz widok',
+        statements: 'Wyciągi',
+        unapprovedCash: 'Niezaakceptowana gotówka',
+        unapprovedCard: 'Niezaakceptowana karta',
+        reconciliation: 'Uzgodnienie',
+        topSpenders: 'Najwięksi wydający',
+        saveSearch: 'Zapisz wyszukiwanie',
         deleteSavedSearch: 'Usuń zapisaną wyszukiwanie',
         deleteSavedSearchConfirm: 'Na pewno chcesz usunąć to wyszukiwanie?',
         searchName: 'Wyszukaj nazwę',
         savedSearchesMenuItemTitle: 'Zapisano',
-        urlCopied: 'URL skopiowany',
+        topCategories: 'Najpopularniejsze kategorie',
+        topMerchants: 'Najlepsi sprzedawcy',
         groupedExpenses: 'zgrupowane wydatki',
         bulkActions: {
-            editMultiple: 'Edytuj wiele',
-            editMultipleTitle: 'Edytuj wiele wydatków',
-            editMultipleDescription: 'Zmiany zostaną ustawione dla wszystkich wybranych wydatków i nadpiszą wszystkie wcześniej ustawione wartości.',
             approve: 'Zatwierdź',
             pay: 'Zapłać',
             delete: 'Usuń',
             hold: 'Wstrzymaj',
             unhold: 'Usuń blokadę',
             reject: 'Odrzuć',
-            duplicateExpense: ({count}: {count: number}) => `Duplikuj ${count === 1 ? 'wydatek' : 'wydatki'}`,
             noOptionsAvailable: 'Brak opcji dostępnych dla wybranej grupy wydatków.',
-            undelete: 'Cofnij usunięcie',
-            duplicateReport: ({count}: {count: number}) => `Duplikat ${count === 1 ? 'raport' : 'raporty'}`,
         },
         filtersHeader: 'Filtry',
         filters: {
@@ -8191,14 +7108,11 @@ Dodaj więcej zasad wydatków, żeby chronić płynność finansową firmy.`,
                 before: (date?: string) => `Przed ${date ?? ''}`,
                 after: (date?: string) => `Po ${date ?? ''}`,
                 on: (date?: string) => `Na ${date ?? ''}`,
-                customDate: 'Niestandardowa data',
-                customRange: 'Niestandardowy zakres',
                 presets: {
                     [CONST.SEARCH.DATE_PRESETS.NEVER]: 'Nigdy',
                     [CONST.SEARCH.DATE_PRESETS.LAST_MONTH]: 'W zeszłym miesiącu',
                     [CONST.SEARCH.DATE_PRESETS.THIS_MONTH]: 'Ten miesiąc',
                     [CONST.SEARCH.DATE_PRESETS.YEAR_TO_DATE]: 'Od początku roku',
-                    [CONST.SEARCH.DATE_PRESETS.LAST_12_MONTHS]: 'Ostatnie 12 miesięcy',
                     [CONST.SEARCH.DATE_PRESETS.LAST_STATEMENT]: 'Ostatnie zestawienie',
                 },
             },
@@ -8210,15 +7124,10 @@ Dodaj więcej zasad wydatków, żeby chronić płynność finansową firmy.`,
             currency: 'Waluta',
             completed: 'Zakończono',
             amount: {
-                lessThan: (amount?: string) => `Mniej niż ${amount ?? ''}`,
-                greaterThan: (amount?: string) => `Większe niż ${amount ?? ''}`,
-                between: (greaterThan?: string, lessThan?: string) => {
-                    if (greaterThan && lessThan) {
-                        return `Między ${greaterThan} a ${lessThan}`;
-                    }
-                    return 'Między';
-                },
-                equalTo: (amount?: string) => `Równe ${amount ?? ''}`,
+                lessThan: ({amount}: OptionalParam<RequestAmountParams> = {}) => `Mniej niż ${amount ?? ''}`,
+                greaterThan: ({amount}: OptionalParam<RequestAmountParams> = {}) => `Większe niż ${amount ?? ''}`,
+                between: (greaterThan: string, lessThan: string) => `Między ${greaterThan} a ${lessThan}`,
+                equalTo: ({amount}: OptionalParam<RequestAmountParams> = {}) => `Równe ${amount ?? ''}`,
             },
             card: {
                 expensify: 'Expensify',
@@ -8228,9 +7137,8 @@ Dodaj więcej zasad wydatków, żeby chronić płynność finansową firmy.`,
                 cardFeedName: ({cardFeedBankName, cardFeedLabel}: {cardFeedBankName: string; cardFeedLabel?: string}) =>
                     `Wszystkie ${cardFeedBankName}${cardFeedLabel ? ` - ${cardFeedLabel}` : ''}`,
                 cardFeedNameCSV: ({cardFeedLabel}: {cardFeedLabel?: string}) => `Wszystkie zaimportowane karty CSV${cardFeedLabel ? ` - ${cardFeedLabel}` : ''}`,
-                travelInvoicing: 'Fakturowanie podróży',
             },
-            reportField: (name: string, value: string) => `${name} to ${value}`,
+            reportField: ({name, value}: OptionalParam<ReportFieldParams>) => `${name} to ${value}`,
             current: 'Bieżące',
             past: 'Przeszłe',
             submitted: 'Przesłano',
@@ -8242,10 +7150,6 @@ Dodaj więcej zasad wydatków, żeby chronić płynność finansową firmy.`,
             billable: 'Fakturowalne',
             reimbursable: 'Podlegające zwrotowi',
             purchaseCurrency: 'Waluta zakupu',
-            sortOrder: {
-                [CONST.SEARCH.SORT_ORDER.ASC]: 'Rosnąco',
-                [CONST.SEARCH.SORT_ORDER.DESC]: 'Zstępujący',
-            },
             groupBy: {
                 [CONST.SEARCH.GROUP_BY.FROM]: 'Od',
                 [CONST.SEARCH.GROUP_BY.CARD]: 'Karta',
@@ -8262,7 +7166,6 @@ Dodaj więcej zasad wydatków, żeby chronić płynność finansową firmy.`,
             withdrawalType: {
                 [CONST.SEARCH.WITHDRAWAL_TYPE.EXPENSIFY_CARD]: 'Karta Expensify',
                 [CONST.SEARCH.WITHDRAWAL_TYPE.REIMBURSEMENT]: 'Zwrot kosztów',
-                [CONST.SEARCH.WITHDRAWAL_TYPE.CENTRAL_TRAVEL_INVOICING]: 'Fakturowanie podróży',
             },
             is: 'Jest',
             action: {
@@ -8272,20 +7175,13 @@ Dodaj więcej zasad wydatków, żeby chronić płynność finansową firmy.`,
                 [CONST.SEARCH.ACTION_FILTERS.EXPORT]: 'Eksportuj',
             },
         },
-        display: {
-            label: 'Wyświetl',
-            sortBy: 'Sortuj według',
-            sortOrder: 'Kolejność sortowania',
-            groupBy: 'Grupuj według',
-            limitResults: 'Ogranicz wyniki',
-        },
         has: 'Ma',
+        groupBy: 'Grupuj według',
         view: {
             label: 'Pokaż',
             table: 'Tabela',
             bar: 'Bar',
             line: 'Linia',
-            pie: 'Wykres kołowy',
         },
         chartTitles: {
             [CONST.SEARCH.GROUP_BY.FROM]: 'Od',
@@ -8310,22 +7206,9 @@ Dodaj więcej zasad wydatków, żeby chronić płynność finansową firmy.`,
         withdrawalType: 'Typ wypłaty',
         recentSearches: 'Ostatnie wyszukiwania',
         recentChats: 'Ostatnie czaty',
-        serverResults: 'Wyniki wyszukiwania',
         searchIn: 'Szukaj w',
-        askConcierge: (message: string) => `Zapytaj Concierge: „${message}”`,
-        searchPlaceholder: 'Wyszukaj coś...',
+        searchPlaceholder: 'Wyszukaj coś',
         suggestions: 'Sugestie',
-        suggestionsAvailable: (
-            {
-                count,
-            }: {
-                count: number;
-            },
-            query = '',
-        ) => ({
-            one: `Dostępne sugestie${query ? ` dla ${query}` : ''}. ${count} wynik.`,
-            other: (resultCount: number) => `Dostępne sugestie${query ? ` dla ${query}` : ''}. ${resultCount} wyniki.`,
-        }),
         exportSearchResults: {
             title: 'Utwórz eksport',
             description: 'Wow, ale dużo pozycji! Spakujemy je, a Concierge wkrótce wyśle Ci plik.',
@@ -8334,29 +7217,6 @@ Dodaj więcej zasad wydatków, żeby chronić płynność finansową firmy.`,
         exportAll: {
             selectAllMatchingItems: 'Zaznacz wszystkie pasujące elementy',
             allMatchingItemsSelected: 'Zaznaczono wszystkie pasujące elementy',
-            selectAllOnThisPage: 'Zaznacz wszystko na tej stronie',
-        },
-        errors: {
-            pleaseSelectDatesForBothFromAndTo: 'Wybierz daty dla Od i Do',
-        },
-        spendOverTime: 'Wydatki w czasie',
-        tabs: {
-            expenseReports: 'Raporty wydatków',
-            reports: 'Raporty',
-            expenses: 'Wydatki',
-            submit: 'Szkice',
-            approve: 'Wymaga zatwierdzenia',
-            pay: 'Gotowe do zapłaty',
-            accounting: 'Księgowość',
-            export: 'Oczekuje na eksport',
-            unapprovedCash: 'Rozliczenia kasowe',
-            unapprovedCard: 'Rozliczenia narosłe na kartach',
-            statements: 'Wyciągi z karty',
-            reconciliation: 'Uzgadnianie bankowe',
-            insights: 'Wnioski',
-            topSpenders: 'Najwięksi wydający',
-            topCategories: 'Najpopularniejsze kategorie',
-            topMerchants: 'Najważniejsi sprzedawcy',
         },
     },
     genericErrorPage: {
@@ -8412,6 +7272,7 @@ Dodaj więcej zasad wydatków, żeby chronić płynność finansową firmy.`,
             chooseWorkspace: 'Wybierz przestrzeń roboczą dla tego raportu.',
             emptyReportConfirmationTitle: 'Masz już pusty raport',
             emptyReportConfirmationPrompt: ({workspaceName}: {workspaceName: string}) => `Czy na pewno chcesz utworzyć kolejny raport w ${workspaceName}? Puste raporty znajdziesz w`,
+            emptyReportConfirmationPromptLink: 'Raporty',
             emptyReportConfirmationDontShowAgain: 'Nie pokazuj mi tego ponownie',
             genericWorkspaceName: 'ten workspace',
         },
@@ -8449,7 +7310,6 @@ Dodaj więcej zasad wydatków, żeby chronić płynność finansową firmy.`,
                     reimburseableLink: 'wydatki z własnej kieszeni',
                     nonReimbursableLink: 'wydatki z firmowej karty',
                     pending: (label: string) => `rozpoczęto eksport tego raportu do ${label}...`,
-                    travelCardLink: 'wydatki z karty podróżnej',
                 },
                 integrationsMessage: (errorMessage: string, label: string, linkText?: string, linkURL?: string) =>
                     `nie udało się wyeksportować tego raportu do ${label} („${errorMessage}${linkText ? `<a href="${linkURL}">${linkText}</a>` : ''}”)`,
@@ -8458,8 +7318,7 @@ Dodaj więcej zasad wydatków, żeby chronić płynność finansową firmy.`,
                 markedReimbursed: (amount: string, currency: string) => `zapłacono ${currency}${amount} gdzie indziej`,
                 markedReimbursedFromIntegration: ({amount, currency}: MarkReimbursedFromIntegrationParams) => `zapłacono ${currency}${amount} przez integrację`,
                 outdatedBankAccount: `nie można było przetworzyć płatności z powodu problemu z kontem bankowym płatnika`,
-                reimbursementACHBounceDefault: `nie udało się przetworzyć płatności z powodu nieprawidłowego numeru rozliczeniowego/konta lub zamkniętego konta`,
-                reimbursementACHBounceWithReason: ({returnReason}: {returnReason: string}) => `nie udało się przetworzyć płatności: ${returnReason}`,
+                reimbursementACHBounce: `nie udało się przetworzyć płatności z powodu problemu z kontem bankowym`,
                 reimbursementACHCancelled: `anulowano płatność`,
                 reimbursementAccountChanged: `nie można było przetworzyć płatności, ponieważ płatnik zmienił konto bankowe`,
                 reimbursementDelayed: `przetworzono płatność, ale jest opóźniona o kolejne 1–2 dni robocze`,
@@ -8467,22 +7326,17 @@ Dodaj więcej zasad wydatków, żeby chronić płynność finansową firmy.`,
                 selectedForRandomAuditMarkdown: `[losowo wybrany](https://help.expensify.com/articles/expensify-classic/reports/Set-a-random-report-audit-schedule) do weryfikacji`,
                 share: ({to}: ShareParams) => `zaprosił(-a) członka ${to}`,
                 unshare: ({to}: UnshareParams) => `usunięto członka ${to}`,
-                stripePaid: (amount: string, currency: string) => `zapłacono ${currency}${amount}`,
+                stripePaid: ({amount, currency}: StripePaidParams) => `zapłacono ${currency}${amount}`,
                 takeControl: `przejął kontrolę`,
                 integrationSyncFailed: (label: string, errorMessage: string, workspaceAccountingLink?: string) =>
                     `wystąpił problem z synchronizacją z ${label}${errorMessage ? ` ("${errorMessage}")` : ''}. Napraw problem w <a href="${workspaceAccountingLink}">ustawieniach przestrzeni roboczej</a>.`,
-                integrationSyncFailedRecurrence: ({count}: {count: number}) => `(Powtórzono ${count} razy.)`,
                 companyCardConnectionBroken: ({feedName, workspaceCompanyCardRoute}: {feedName: string; workspaceCompanyCardRoute: string}) =>
                     `Połączenie ${feedName} jest przerwane. Aby przywrócić importy kart, <a href='${workspaceCompanyCardRoute}'>zaloguj się do swojego banku</a>.`,
                 plaidBalanceFailure: ({maskedAccountNumber, walletRoute}: {maskedAccountNumber: string; walletRoute: string}) =>
-                    `połączenie Plaid z twoim firmowym kontem bankowym jest przerwane. Proszę, <a href='${walletRoute}'>połącz ponownie swoje konto bankowe ${maskedAccountNumber}</a>, aby móc dalej używać Kart Expensify.`,
-                addEmployee: (email: string, role: string, didJoinPolicy?: boolean) => {
-                    const translatedRole = String(translations.workspace.common.roleName(role)).toLowerCase();
-                    const article = role === CONST.POLICY.ROLE.AUDITOR ? 'jeden' : 'a';
-                    return didJoinPolicy ? `${email} dołączył przez link zaproszenia do przestrzeni roboczej` : `dodano ${email} jako ${article} ${translatedRole}`;
-                },
+                    `połączenie Plaid z Twoim firmowym kontem bankowym jest przerwane. Prosimy, <a href='${walletRoute}'>ponownie połącz konto bankowe ${maskedAccountNumber}</a>, aby móc dalej korzystać z kart Expensify.`,
+                addEmployee: (email: string, role: string) => `dodano ${email} jako ${role === 'member' ? 'a' : 'włączony'} ${role}`,
                 updateRole: ({email, currentRole, newRole}: UpdateRoleParams) => `zaktualizowano rolę użytkownika ${email} na ${newRole} (wcześniej ${currentRole})`,
-                updatedCustomField1: (email: string, newValue: string, previousValue: string) => {
+                updatedCustomField1: ({email, previousValue, newValue}: UpdatedCustomFieldParams) => {
                     if (!newValue) {
                         return `usunięto własne pole 1 użytkownika ${email} (wcześniej „${previousValue}”)`;
                     }
@@ -8490,7 +7344,7 @@ Dodaj więcej zasad wydatków, żeby chronić płynność finansową firmy.`,
                         ? `dodano „${newValue}” do niestandardowego pola 1 użytkownika ${email}`
                         : `zmieniono pole niestandardowe 1 użytkownika ${email} na „${newValue}” (poprzednio „${previousValue}”)`;
                 },
-                updatedCustomField2: (email: string, newValue: string, previousValue: string) => {
+                updatedCustomField2: ({email, previousValue, newValue}: UpdatedCustomFieldParams) => {
                     if (!newValue) {
                         return `usunięto pole niestandardowe 2 użytkownika ${email} (wcześniej „${previousValue}”)`;
                     }
@@ -8504,12 +7358,8 @@ Dodaj więcej zasad wydatków, żeby chronić płynność finansową firmy.`,
                 addedConnection: ({connectionName}: ConnectionNameParams) => `połączono z ${CONST.POLICY.CONNECTIONS.NAME_USER_FRIENDLY[connectionName]}`,
                 leftTheChat: 'opuścił czat',
                 settlementAccountLocked: ({maskedBankAccountNumber}: OriginalMessageSettlementAccountLocked, linkURL: string) =>
-                    `firmowe konto bankowe ${maskedBankAccountNumber} zostało automatycznie zablokowane z powodu problemu z rozliczeniami zwrotów lub Karty Expensify. Napraw problem w <a href="${linkURL}">ustawieniach przestrzeni roboczej</a>.`,
+                    `firmowe konto bankowe ${maskedBankAccountNumber} zostało automatycznie zablokowane z powodu problemu z rozliczeniem zwrotów lub rozliczeniem karty Expensify. Napraw problem w <a href="${linkURL}">ustawieniach swojego workspace</a>.`,
                 leftTheChatWithName: (nameOrEmail: string) => `${nameOrEmail ? `${nameOrEmail}: ` : ''} opuścił czat`,
-                actionableCard3DSTransactionApproval: (amount: string, merchant: string | undefined) => {
-                    const amountAndMerchantText = [amount, merchant].filter((s) => !!s?.length).join(' ');
-                    return `Otwórz aplikację mobilną Expensify, aby przejrzeć transakcję${amountAndMerchantText ? ` ${amountAndMerchantText}` : ''}`;
-                },
             },
             error: {
                 invalidCredentials: 'Nieprawidłowe dane logowania, sprawdź konfigurację swojego połączenia.',
@@ -8519,23 +7369,6 @@ Dodaj więcej zasad wydatków, żeby chronić płynność finansową firmy.`,
     chronos: {
         oooEventSummaryFullDay: (summary: string, dayCount: number, date: string) => `${summary} za ${dayCount} ${dayCount === 1 ? 'dzień' : 'dni'} do ${date}`,
         oooEventSummaryPartialDay: (summary: string, timePeriod: string, date: string) => `${summary} z ${timePeriod} z dnia ${date}`,
-        startTimer: 'Startuj licznik',
-        stopTimer: (duration: string) => `Zatrzymaj licznik czasu (${duration})`,
-        scheduleOOO: 'Zaplanuj nieobecność',
-        scheduleOOOTitle: 'Zaplanuj nieobecność',
-        date: 'Data',
-        time: 'Czas (format 24-godzinny)',
-        durationAmount: 'Czas trwania',
-        durationUnit: 'Jednostka',
-        reason: 'Powód',
-        workingPercentage: 'Procent pracy',
-        dateRequired: 'Data jest wymagana.',
-        invalidTimeFormat: 'Podaj poprawny czas w formacie 24-godzinnym (np. 14:30).',
-        enterANumber: 'Wpisz liczbę.',
-        hour: 'godziny',
-        day: 'dni',
-        week: 'tygodnie',
-        month: 'miesiące',
     },
     footer: {
         features: 'Funkcje',
@@ -8578,24 +7411,8 @@ Dodaj więcej zasad wydatków, żeby chronić płynność finansową firmy.`,
         workspaceName: 'Nazwa przestrzeni roboczej',
         chatUserDisplayNames: 'Wyświetlane nazwy członków czatu',
         scrollToNewestMessages: 'Przewiń do najnowszych wiadomości',
-        scrollToActionBadgeTarget: 'Przewiń do akcji wymagającej uwagi',
         preStyledText: 'Wstępnie ostylowany tekst',
         viewAttachment: 'Zobacz załącznik',
-        contextMenuAvailable: 'Menu kontekstowe jest dostępne. Naciśnij Shift+F10, aby je otworzyć.',
-        contextMenuAvailableMacOS: 'Menu kontekstowe jest dostępne. Naciśnij VO-Shift-M, aby je otworzyć.',
-        contextMenuAvailableNative: 'Menu kontekstowe jest dostępne. Dotknij dwukrotnie i przytrzymaj, aby je otworzyć.',
-        selectAllFeatures: 'Zaznacz wszystkie funkcje',
-        selectAllTransactions: 'Zaznacz wszystkie transakcje',
-        selectAllItems: 'Zaznacz wszystkie elementy',
-        openActionsMenu: 'Otwórz menu działań',
-        selectAllCategories: 'Zaznacz wszystkie kategorie',
-        selectAllDistanceRates: 'Wybierz wszystkie stawki za dystans',
-        selectAllTags: 'Zaznacz wszystkie tagi',
-        selectAllTaxes: 'Wybierz wszystkie podatki',
-        selectAllPerDiemRates: 'Wybierz wszystkie stawki diet',
-        selectAllMembers: 'Zaznacz wszystkich członków',
-        selectAllValues: 'Zaznacz wszystkie wartości',
-        selectAllRules: 'Zaznacz wszystkie reguły',
     },
     parentReportAction: {
         deletedReport: 'Usunięty raport',
@@ -8614,7 +7431,6 @@ Dodaj więcej zasad wydatków, żeby chronić płynność finansową firmy.`,
         parentNavigationSummary: ({reportName, workspaceName}: ParentNavigationSummaryParams) => `Z raportu ${reportName}${workspaceName ? `w ${workspaceName}` : ''}`,
     },
     qrCodes: {
-        qrCode: 'Kod QR',
         copy: 'Skopiuj URL',
         copied: 'Skopiowano!',
     },
@@ -8661,11 +7477,6 @@ Dodaj więcej zasad wydatków, żeby chronić płynność finansową firmy.`,
             'Dołącz do Expensify.org w eliminowaniu niesprawiedliwości na całym świecie. Obecna kampania „Teachers Unite” wspiera nauczycieli wszędzie, dzieląc koszty niezbędnych przyborów szkolnych.',
         iKnowATeacher: 'Znam nauczyciela',
         iAmATeacher: 'Jestem nauczycielem',
-        personalKarma: {
-            title: 'Włącz osobistą karmę',
-            description: 'Przekaż 1 USD na Expensify.org za każde 500 USD wydane w miesiącu',
-            stopDonationsPrompt: 'Czy na pewno chcesz przestać przekazywać darowizny na rzecz Expensify.org?',
-        },
         getInTouch: 'Świetnie! Udostępnij ich dane kontaktowe, abyśmy mogli się z nimi skontaktować.',
         introSchoolPrincipal: 'Wprowadzenie dla dyrektora szkoły',
         schoolPrincipalVerifyExpense:
@@ -8688,11 +7499,6 @@ Dodaj więcej zasad wydatków, żeby chronić płynność finansową firmy.`,
         notActivated: 'Nieaktywne',
         outOfPocket: 'Zwrotne',
         companySpend: 'Niezgodne z refundacją',
-        personalCard: 'Karta osobista',
-        companyCard: 'Karta firmowa',
-        expensifyCard: 'Karta Expensify',
-        travelInvoicing: 'Fakturowanie podróży',
-        travelCard: 'Karta podróżna',
     },
     distance: {
         addStop: 'Dodaj przystanek',
@@ -8716,18 +7522,14 @@ Dodaj więcej zasad wydatków, żeby chronić płynność finansową firmy.`,
             endReading: 'Zakończ czytanie',
             saveForLater: 'Zapisz na później',
             totalDistance: 'Całkowity dystans',
+            startTitle: 'Zdjęcie początku stanu licznika',
+            endTitle: 'Zdjęcie końcowe licznika przebiegu',
             startMessageWeb: 'Dodaj zdjęcie licznika kilometrów z <strong>początku</strong> swojej podróży. Przeciągnij tutaj plik lub wybierz go, aby przesłać.',
             endMessageWeb: 'Dodaj zdjęcie licznika przebiegu z <strong>końca</strong> swojej podróży. Przeciągnij tutaj plik lub wybierz jeden, aby go przesłać.',
-            startTitle: 'Zdjęcie licznika na początku',
-            endTitle: 'Końcowe zdjęcie licznika przebiegu',
-            deleteOdometerPhoto: 'Usuń zdjęcie licznika przebiegu',
-            deleteOdometerPhotoConfirmation: 'Na pewno chcesz usunąć to zdjęcie licznika?',
-            cameraAccessRequired: 'Aby robić zdjęcia, wymagany jest dostęp do aparatu.',
-            snapPhotoStart: '<muted-text-label>Zrób zdjęcie licznika kilometrów na <strong>początku</strong> podróży.</muted-text-label>',
-            snapPhotoEnd: '<muted-text-label>Zrób zdjęcie licznika kilometrów na <strong>koniec</strong> swojej podróży.</muted-text-label>',
         },
     },
     gps: {
+        disclaimer: 'Użyj GPS, aby utworzyć wydatek z podróży. Stuknij przycisk „Start” poniżej, aby rozpocząć śledzenie.',
         error: {
             failedToStart: 'Nie udało się uruchomić śledzenia lokalizacji.',
             failedToGetPermissions: 'Nie udało się uzyskać wymaganych uprawnień lokalizacji.',
@@ -8736,9 +7538,13 @@ Dodaj więcej zasad wydatków, żeby chronić płynność finansową firmy.`,
         stopped: 'Zatrzymano',
         start: 'Start',
         stop: 'Zatrzymaj',
-        save: 'Zapisz',
-        resume: 'Wznów',
         discard: 'Odrzuć',
+        stopGpsTrackingModal: {
+            title: 'Zatrzymaj śledzenie GPS',
+            prompt: 'Na pewno? Spowoduje to zakończenie Twojej obecnej ścieżki.',
+            cancel: 'Wznów śledzenie',
+            confirm: 'Zatrzymaj śledzenie GPS',
+        },
         discardDistanceTrackingModal: {
             title: 'Odrzuć śledzenie dystansu',
             prompt: 'Na pewno? Spowoduje to porzucenie Twojej bieżącej ścieżki i nie będzie można tego cofnąć.',
@@ -8786,14 +7592,12 @@ Dodaj więcej zasad wydatków, żeby chronić płynność finansową firmy.`,
             prompt: 'Czy na pewno chcesz zatrzymać śledzenie GPS i przełączyć się na Expensify Classic?',
             confirm: 'Zatrzymaj i przełącz',
         },
-        switchAccountWarningTripInProgress: {title: 'Trwa śledzenie GPS', prompt: 'Na pewno chcesz zatrzymać śledzenie GPS i przełączyć konto?', confirm: 'Zatrzymaj i przełącz'},
         locationServicesRequiredModal: {
             title: 'Wymagany dostęp do lokalizacji',
             confirm: 'Otwórz ustawienia',
             prompt: 'Zezwól na dostęp do lokalizacji w ustawieniach urządzenia, aby rozpocząć śledzenie dystansu GPS.',
         },
-        gpsFloatingPillText: 'Trwa śledzenie GPS...',
-        liveActivity: {subtitle: 'Śledzenie dystansu', button: 'Zobacz postęp', lockScreenBadgeText: 'Dystans', lockScreenTrackingText: 'Śledzenie...'},
+        fabGpsTripExplained: 'Przejdź do ekranu GPS (działanie pływające)',
     },
     reportCardLostOrDamaged: {
         screenTitle: 'Świadectwo zgubione lub uszkodzone',
@@ -8820,13 +7624,11 @@ Dodaj więcej zasad wydatków, żeby chronić płynność finansową firmy.`,
         [CONST.REFERRAL_PROGRAM.CONTENT_TYPES.START_CHAT]: {
             buttonText: 'Rozpocznij czat, <success><strong>poleć znajomego</strong></success>.',
             header: 'Rozpocznij czat, poleć znajomego',
-            closeAccessibilityLabel: 'Zamknij, rozpocznij czat, poleć znajomego, baner',
             body: 'Chcesz, aby Twoi znajomi też korzystali z Expensify? Po prostu rozpocznij z nimi czat, a my zajmiemy się resztą.',
         },
         [CONST.REFERRAL_PROGRAM.CONTENT_TYPES.SUBMIT_EXPENSE]: {
             buttonText: 'Złóż raport wydatków, <success><strong>poleć swój zespół</strong></success>.',
             header: 'Wyślij wydatek, poleć swój zespół',
-            closeAccessibilityLabel: 'Zamknij, prześlij wydatek, poleć swój zespół, baner',
             body: 'Chcesz, aby Twój zespół też korzystał z Expensify? Po prostu prześlij im wydatek, a my zajmiemy się resztą.',
         },
         [CONST.REFERRAL_PROGRAM.CONTENT_TYPES.REFER_FRIEND]: {
@@ -8842,27 +7644,26 @@ Dodaj więcej zasad wydatków, żeby chronić płynność finansową firmy.`,
     },
     systemChatFooterMessage: {
         [CONST.INTRO_CHOICES.MANAGE_TEAM]: ({adminReportName, href}: {adminReportName: string; href: string}) =>
-            `Porozmawiaj ze swoim opiekunem klienta w <a href="${href}">${adminReportName}</a>, żeby uzyskać pomoc`,
-        default: `Napisz do <concierge-link>${CONST.CONCIERGE_CHAT_NAME}</concierge-link>, żeby uzyskać pomoc z konfiguracją`,
+            `Porozmawiaj ze swoim specjalistą ds. konfiguracji w <a href="${href}">${adminReportName}</a>, aby uzyskać pomoc`,
+        default: `Wyślij wiadomość do <concierge-link>${CONST.CONCIERGE_CHAT_NAME}</concierge-link>, aby uzyskać pomoc z konfiguracją`,
     },
     violations: {
         allTagLevelsRequired: 'Wszystkie tagi są wymagane',
         autoReportedRejectedExpense: 'Ten wydatek został odrzucony.',
         billableExpense: 'Rozliczalne już nieważne',
-        cashExpenseWithNoReceipt: (formattedLimit?: string) => `Wymagany paragon${formattedLimit ? `powyżej ${formattedLimit}` : ''}`,
+        cashExpenseWithNoReceipt: ({formattedLimit}: ViolationsCashExpenseWithNoReceiptParams = {}) => `Wymagany paragon${formattedLimit ? `powyżej ${formattedLimit}` : ''}`,
         categoryOutOfPolicy: 'Kategoria nie jest już prawidłowa',
-        conversionSurcharge: (surcharge: number) => `Zastosowano prowizję za przewalutowanie w wysokości ${surcharge}%`,
+        conversionSurcharge: ({surcharge}: ViolationsConversionSurchargeParams) => `Zastosowano prowizję za przewalutowanie w wysokości ${surcharge}%`,
         customUnitOutOfPolicy: 'Stawka nie jest ważna dla tego workspace’u',
         duplicatedTransaction: 'Potencjalny duplikat',
         fieldRequired: 'Pola raportu są wymagane',
         futureDate: 'Przyszła data jest niedozwolona',
-        inactiveVendor: 'Dostawca nie jest już prawidłowy',
-        invoiceMarkup: (invoiceMarkup: number) => `Podwyższono o ${invoiceMarkup}%`,
-        maxAge: (maxAge: number) => `Data starsza niż ${maxAge} dni`,
+        invoiceMarkup: ({invoiceMarkup}: ViolationsInvoiceMarkupParams) => `Podwyższono o ${invoiceMarkup}%`,
+        maxAge: ({maxAge}: ViolationsMaxAgeParams) => `Data starsza niż ${maxAge} dni`,
         missingCategory: 'Brak kategorii',
         missingComment: 'Wymagany opis dla wybranej kategorii',
         missingAttendees: 'Wymaganych jest wielu uczestników dla tej kategorii',
-        missingTag: (tagName?: string) => `Brak ${tagName ?? 'etykieta'}`,
+        missingTag: ({tagName}: ViolationsMissingTagParams = {}) => `Brak ${tagName ?? 'etykieta'}`,
         modifiedAmount: ({type, displayPercentVariance}: ViolationsModifiedAmountParams) => {
             switch (type) {
                 case 'distance':
@@ -8877,17 +7678,15 @@ Dodaj więcej zasad wydatków, żeby chronić płynność finansową firmy.`,
             }
         },
         modifiedDate: 'Data różni się od zeskanowanego paragonu',
-        increasedDistance: ({formattedRouteDistance}: ViolationsIncreasedDistanceParams) =>
-            formattedRouteDistance ? `Dystans przekracza obliczoną trasę ${formattedRouteDistance}` : 'Dystans przekracza obliczoną trasę',
         nonExpensiworksExpense: 'Wydatek spoza Expensiworks',
-        overAutoApprovalLimit: (formattedLimit: string) => `Wydatek przekracza automatyczny limit zatwierdzania w wysokości ${formattedLimit}`,
-        overCategoryLimit: (formattedLimit: string) => `Kwota przekracza limit kategorii w wysokości ${formattedLimit}/osobę`,
-        overLimit: (formattedLimit: string) => `Kwota powyżej limitu ${formattedLimit}/osobę`,
-        overTripLimit: (formattedLimit: string) => `Kwota powyżej limitu ${formattedLimit}/podróż`,
-        overLimitAttendee: (formattedLimit: string) => `Kwota powyżej limitu ${formattedLimit}/osobę`,
-        perDayLimit: (formattedLimit: string) => `Kwota przekraczająca dzienny limit kategorii ${formattedLimit}/osobę`,
+        overAutoApprovalLimit: ({formattedLimit}: ViolationsOverLimitParams) => `Wydatek przekracza automatyczny limit zatwierdzania w wysokości ${formattedLimit}`,
+        overCategoryLimit: ({formattedLimit}: ViolationsOverCategoryLimitParams) => `Kwota przekracza limit kategorii w wysokości ${formattedLimit}/osobę`,
+        overLimit: ({formattedLimit}: ViolationsOverLimitParams) => `Kwota powyżej limitu ${formattedLimit}/osobę`,
+        overTripLimit: ({formattedLimit}: ViolationsOverLimitParams) => `Kwota powyżej limitu ${formattedLimit}/podróż`,
+        overLimitAttendee: ({formattedLimit}: ViolationsOverLimitParams) => `Kwota powyżej limitu ${formattedLimit}/osobę`,
+        perDayLimit: ({formattedLimit}: ViolationsPerDayLimitParams) => `Kwota przekraczająca dzienny limit kategorii ${formattedLimit}/osobę`,
         receiptNotSmartScanned: 'Ręcznie dodano paragon i szczegóły wydatku.',
-        receiptRequired: (formattedLimit?: string, category?: string) => {
+        receiptRequired: ({formattedLimit, category}: ViolationsReceiptRequiredParams) => {
             if (formattedLimit && category) {
                 return `Wymagany paragon powyżej limitu kategorii ${formattedLimit}`;
             }
@@ -8899,8 +7698,8 @@ Dodaj więcej zasad wydatków, żeby chronić płynność finansową firmy.`,
             }
             return 'Wymagany paragon';
         },
-        itemizedReceiptRequired: (formattedLimit?: string) => `Wymagany paragon z wyszczególnieniem pozycji${formattedLimit ? `powyżej ${formattedLimit}` : ''}`,
-        prohibitedExpense: (prohibitedExpenseTypes: string | string[]) => {
+        itemizedReceiptRequired: ({formattedLimit}: {formattedLimit?: string}) => `Wymagany paragon z wyszczególnieniem pozycji${formattedLimit ? `powyżej ${formattedLimit}` : ''}`,
+        prohibitedExpense: ({prohibitedExpenseTypes}: ViolationsProhibitedExpenseParams) => {
             const preMessage = 'Zabroniony wydatek:';
             const getProhibitedExpenseTypeText = (prohibitedExpenseType: string) => {
                 switch (prohibitedExpenseType) {
@@ -8914,10 +7713,6 @@ Dodaj więcej zasad wydatków, żeby chronić płynność finansową firmy.`,
                         return `rozrywka dla dorosłych`;
                     case 'hotelIncidentals':
                         return `dodatkowe opłaty hotelowe`;
-                    case 'giftCard':
-                        return `zakup kart podarunkowych`;
-                    case 'handwrittenReceipt':
-                        return `odręczne paragony`;
                     default:
                         return `${prohibitedExpenseType}`;
                 }
@@ -8933,37 +7728,19 @@ Dodaj więcej zasad wydatków, żeby chronić płynność finansową firmy.`,
             }
             return `${preMessage} ${types.map(getProhibitedExpenseTypeText).join(', ')}`;
         },
-        customRules: (message: string) => message,
+        customRules: ({message}: ViolationsCustomRulesParams) => message,
         reviewRequired: 'Wymagana weryfikacja',
-        rter: (
-            brokenBankConnection: boolean,
-            isAdmin: boolean,
-            isTransactionOlderThan7Days: boolean,
-            member?: string,
-            rterType?: string,
-            companyCardPageURL?: string,
-            connectionLink?: string,
-            isPersonalCard?: boolean,
-            isMarkAsCash?: boolean,
-        ) => {
+        rter: ({brokenBankConnection, isAdmin, isTransactionOlderThan7Days, member, rterType, companyCardPageURL}: ViolationsRterParams) => {
             if (rterType === CONST.RTER_VIOLATION_TYPES.BROKEN_CARD_CONNECTION_530) {
-                return 'Nie można automatycznie dopasować paragonu z powodu zerwanego połączenia z bankiem.';
-            }
-            if (isPersonalCard && (rterType === CONST.RTER_VIOLATION_TYPES.BROKEN_CARD_CONNECTION || brokenBankConnection)) {
-                if (!connectionLink) {
-                    return 'Nie można automatycznie dopasować paragonu z powodu zerwanego połączenia z bankiem.';
-                }
-                return isMarkAsCash
-                    ? `Nie można automatycznie dopasować paragonu z powodu zerwanego połączenia z kartą. Oznacz jako gotówkę, aby zignorować, lub <a href="${connectionLink}">napraw kartę</a>, aby dopasować paragon.`
-                    : `Nie można automatycznie dopasować paragonu z powodu przerwanego połączenia karty. <a href="${connectionLink}">Napraw kartę</a>, aby dopasować paragon.`;
+                return 'Nie można automatycznie dopasować paragonu z powodu przerwanego połączenia z bankiem';
             }
             if (brokenBankConnection || rterType === CONST.RTER_VIOLATION_TYPES.BROKEN_CARD_CONNECTION) {
                 return isAdmin
                     ? `Połączenie z bankiem przerwane. <a href="${companyCardPageURL}">Połącz ponownie, aby dopasować paragon</a>`
-                    : 'Połączenie z bankiem zostało przerwane. Poproś administratora o ponowne połączenie, aby dopasować paragon.';
+                    : 'Połączenie z bankiem zostało zerwane. Poproś administratora o ponowne połączenie, aby dopasować paragon.';
             }
             if (!isTransactionOlderThan7Days) {
-                return isAdmin ? `Poproś ${member}, aby oznaczył to jako gotówkę, albo poczekaj 7 dni i spróbuj ponownie` : 'Oczekiwanie na połączenie z transakcją kartową.';
+                return isAdmin ? `Poproś ${member}, aby oznaczył to jako gotówkę lub poczekaj 7 dni i spróbuj ponownie` : 'Oczekuje na połączenie z transakcją kartową.';
             }
             return '';
         },
@@ -8972,20 +7749,12 @@ Dodaj więcej zasad wydatków, żeby chronić płynność finansową firmy.`,
             `<muted-text-label>Oczekuje na rachunek z powodu przerwanego połączenia z bankiem. Rozwiąż problem w sekcji <a href="${workspaceCompanyCardRoute}">Karty firmowe</a>.</muted-text-label>`,
         memberBrokenConnectionError: 'Paragon oczekuje z powodu zerwanego połączenia z bankiem. Poproś administratora przestrzeni roboczej o rozwiązanie problemu.',
         markAsCashToIgnore: 'Oznacz jako gotówkę, aby zignorować i poprosić o płatność.',
-        smartscanFailed: ({canEdit = true, missingFields = []}: {canEdit?: boolean; missingFields?: string[]}) => {
-            if (missingFields.length > 0) {
-                const fieldNames: Record<string, string> = {merchant: 'sprzedawcy', date: 'daty', amount: 'kwoty'};
-                const translated = missingFields.map((f) => fieldNames[f] ?? f);
-                const fieldList = translated.join(translated.length > 2 ? ', ' : ' i ');
-                return `Skanowanie paragonu nie powiodło się — brak ${fieldList}.${canEdit ? ' Wpisz szczegóły ręcznie.' : ''}`;
-            }
-            return `Skanowanie paragonu nie powiodło się.${canEdit ? 'Wpisz szczegóły ręcznie.' : ''}`;
-        },
+        smartscanFailed: ({canEdit = true}) => `Skanowanie paragonu nie powiodło się.${canEdit ? 'Wpisz szczegóły ręcznie.' : ''}`,
         receiptGeneratedWithAI: 'Potencjalny paragon wygenerowany przez AI',
-        someTagLevelsRequired: (tagName?: string) => `Brak ${tagName ?? 'Tag'}`,
-        tagOutOfPolicy: (tagName?: string) => `${tagName ?? 'Tag'} nie jest już ważny`,
+        someTagLevelsRequired: ({tagName}: ViolationsTagOutOfPolicyParams = {}) => `Brak ${tagName ?? 'Tag'}`,
+        tagOutOfPolicy: ({tagName}: ViolationsTagOutOfPolicyParams = {}) => `${tagName ?? 'Tag'} nie jest już ważny`,
         taxAmountChanged: 'Kwota podatku została zmieniona',
-        taxOutOfPolicy: (taxName?: string) => `${taxName ?? 'Podatek'} nie jest już prawidłowy`,
+        taxOutOfPolicy: ({taxName}: ViolationsTaxOutOfPolicyParams = {}) => `${taxName ?? 'Podatek'} nie jest już prawidłowy`,
         taxRateChanged: 'Zmodyfikowano stawkę podatku',
         taxRequired: 'Brak stawki podatku',
         none: 'Brak',
@@ -9005,7 +7774,7 @@ Dodaj więcej zasad wydatków, żeby chronić płynność finansową firmy.`,
         noRoute: 'Wybierz prawidłowy adres',
     },
     reportViolations: {
-        [CONST.REPORT_VIOLATIONS.FIELD_REQUIRED]: (fieldName: string) => `Pole ${fieldName} jest wymagane`,
+        [CONST.REPORT_VIOLATIONS.FIELD_REQUIRED]: ({fieldName}: RequiredFieldParams) => `Pole ${fieldName} jest wymagane`,
         reportContainsExpensesWithViolations: 'Raport zawiera wydatki z naruszeniami.',
     },
     violationDismissal: {
@@ -9062,7 +7831,6 @@ Dodaj więcej zasad wydatków, żeby chronić płynność finansową firmy.`,
         bookACallTextBottom:
             'Chętnie umówimy się z Tobą na rozmowę, aby zrozumieć dlaczego. Możesz zarezerwować rozmowę z jednym z naszych starszych menedżerów produktu, aby omówić swoje potrzeby.',
         takeMeToExpensifyClassic: 'Przejdź do Expensify Classic',
-        goBackJustOnce: 'Wróć tylko raz',
     },
     listBoundary: {
         errorMessage: 'Wystąpił błąd podczas wczytywania kolejnych wiadomości',
@@ -9136,7 +7904,7 @@ Dodaj więcej zasad wydatków, żeby chronić płynność finansową firmy.`,
                 subtitle: 'Jako następny krok <a href="#">wypełnij swoją listę kontrolną konfiguracji</a>, aby Twój zespół mógł zacząć rozliczać wydatki.',
             },
             trialStarted: {
-                title: (numOfDays: number) => `Okres próbny: pozostało ${numOfDays} ${numOfDays === 1 ? 'dzień' : 'dni'}!`,
+                title: ({numOfDays}: TrialStartedTitleParams) => `Okres próbny: pozostało ${numOfDays} ${numOfDays === 1 ? 'dzień' : 'dni'}!`,
                 subtitle: 'Dodaj kartę płatniczą, aby nadal korzystać ze wszystkich swoich ulubionych funkcji.',
             },
             trialEnded: {
@@ -9173,15 +7941,15 @@ Dodaj więcej zasad wydatków, żeby chronić płynność finansową firmy.`,
             title: 'Twój plan',
             exploreAllPlans: 'Poznaj wszystkie plany',
             customPricing: 'Niestandardowe ceny',
-            asLowAs: (price: string) => `już od ${price} za aktywnego członka/miesiąc`,
-            pricePerMemberMonth: (price: string) => `${price} za członka/miesiąc`,
-            pricePerMemberPerMonth: (price: string) => `${price} za członka miesięcznie`,
+            asLowAs: ({price}: YourPlanPriceValueParams) => `już od ${price} za aktywnego członka/miesiąc`,
+            pricePerMemberMonth: ({price}: YourPlanPriceValueParams) => `${price} za członka/miesiąc`,
+            pricePerMemberPerMonth: ({price}: YourPlanPriceValueParams) => `${price} za członka miesięcznie`,
             perMemberMonth: 'za użytkownika/miesiąc',
             collect: {
                 title: 'Zbierz',
                 description: 'Plan dla małych firm, który zapewnia wydatki, podróże i czat.',
-                priceAnnual: ({lower, upper}: YourPlanPriceParams) => `Od ${lower}/aktywnego członka z Kartą Expensify do ${upper}/aktywnego członka bez Karty Expensify.`,
-                pricePayPerUse: ({lower, upper}: YourPlanPriceParams) => `Od ${lower}/aktywnego członka z Kartą Expensify do ${upper}/aktywnego członka bez Karty Expensify.`,
+                priceAnnual: ({lower, upper}: YourPlanPriceParams) => `Od ${lower}/aktywnego członka z kartą Expensify, do ${upper}/aktywnego członka bez karty Expensify.`,
+                pricePayPerUse: ({lower, upper}: YourPlanPriceParams) => `Od ${lower}/aktywnego członka z kartą Expensify, do ${upper}/aktywnego członka bez karty Expensify.`,
                 benefit1: 'Skanowanie paragonów',
                 benefit2: 'Zwroty kosztów',
                 benefit3: 'Zarządzanie kartami służbowymi',
@@ -9194,8 +7962,8 @@ Dodaj więcej zasad wydatków, żeby chronić płynność finansową firmy.`,
             control: {
                 title: 'Sterowanie',
                 description: 'Wydatki, podróże służbowe i czat dla większych firm.',
-                priceAnnual: ({lower, upper}: YourPlanPriceParams) => `Od ${lower}/aktywnego członka z Kartą Expensify do ${upper}/aktywnego członka bez Karty Expensify.`,
-                pricePayPerUse: ({lower, upper}: YourPlanPriceParams) => `Od ${lower}/aktywnego członka z Kartą Expensify do ${upper}/aktywnego członka bez Karty Expensify.`,
+                priceAnnual: ({lower, upper}: YourPlanPriceParams) => `Od ${lower}/aktywnego członka z kartą Expensify, do ${upper}/aktywnego członka bez karty Expensify.`,
+                pricePayPerUse: ({lower, upper}: YourPlanPriceParams) => `Od ${lower}/aktywnego członka z kartą Expensify, do ${upper}/aktywnego członka bez karty Expensify.`,
                 benefit1: 'Wszystko w pakiecie Collect',
                 benefit2: 'Wielopoziomowe przepływy zatwierdzania',
                 benefit3: 'Niestandardowe zasady wydatków',
@@ -9209,8 +7977,8 @@ Dodaj więcej zasad wydatków, żeby chronić płynność finansową firmy.`,
             downgrade: 'Zmień na Collect',
             upgrade: 'Ulepsz do Control',
             addMembers: 'Dodaj członków',
-            saveWithExpensifyTitle: 'Oszczędzaj z Kartą Expensify',
-            saveWithExpensifyDescription: 'Skorzystaj z naszego kalkulatora oszczędności, żeby zobaczyć, jak zwrot gotówki z Karty Expensify może obniżyć twój rachunek w Expensify.',
+            saveWithExpensifyTitle: 'Oszczędzaj z kartą Expensify',
+            saveWithExpensifyDescription: 'Skorzystaj z naszego kalkulatora oszczędności, aby zobaczyć, jak zwrot gotówki z karty Expensify może obniżyć Twój rachunek Expensify.',
             saveWithExpensifyButton: 'Dowiedz się więcej',
         },
         compareModal: {
@@ -9220,7 +7988,6 @@ Dodaj więcej zasad wydatków, żeby chronić płynność finansową firmy.`,
         details: {
             title: 'Szczegóły subskrypcji',
             annual: 'Abonament roczny',
-            creditBalance: 'Saldo kredytowe',
             taxExempt: 'Poproś o status zwolnienia z podatku',
             taxExemptEnabled: 'Zwolnione z podatku',
             taxExemptStatus: 'Status zwolnienia z podatku',
@@ -9238,10 +8005,10 @@ Dodaj więcej zasad wydatków, żeby chronić płynność finansową firmy.`,
             note: 'Uwaga: aktywny członek to każda osoba, która utworzyła, edytowała, przesłała, zatwierdziła, zrefundowała lub wyeksportowała dane wydatków powiązane z przestrzenią roboczą Twojej firmy.',
             confirmDetails: 'Potwierdź szczegóły nowej subskrypcji rocznej:',
             subscriptionSize: 'Rozmiar subskrypcji',
-            activeMembers: (size: number) => `${size} aktywnych członków/miesiąc`,
+            activeMembers: ({size}: SubscriptionSizeParams) => `${size} aktywnych członków/miesiąc`,
             subscriptionRenews: 'Odnowienie subskrypcji',
             youCantDowngrade: 'Nie możesz przejść na niższy plan w trakcie rocznej subskrypcji.',
-            youAlreadyCommitted: (size: number, date: string) =>
+            youAlreadyCommitted: ({size, date}: SubscriptionCommitmentParams) =>
                 `Zobowiązałeś(-aś) się już do rocznej subskrypcji w rozmiarze ${size} aktywnych członków miesięcznie do ${date}. Możesz przejść na subskrypcję płatną za użycie w dniu ${date}, wyłączając automatyczne odnawianie.`,
             error: {
                 size: 'Wprowadź prawidłowy rozmiar subskrypcji',
@@ -9251,53 +8018,40 @@ Dodaj więcej zasad wydatków, żeby chronić płynność finansową firmy.`,
         paymentCard: {
             addPaymentCard: 'Dodaj kartę płatniczą',
             enterPaymentCardDetails: 'Wprowadź dane swojej karty płatniczej',
-            security: 'Expensify jest zgodny z PCI-DSS, używa szyfrowania na poziomie bankowym i wykorzystuje redundantną infrastrukturę, aby chronić Twoje dane.',
-            learnMoreAboutSecurity: 'Dowiedz się więcej o naszych zabezpieczeniach.',
-        },
-        expensifyCode: {
-            title: 'Kod Expensify',
-            discountCode: 'Kod rabatowy',
-            enterCode: 'Wprowadź kod Expensify, aby zastosować go do swojej subskrypcji.',
-            discountMessage: (promoDiscount: string, validBillingCycles: string) =>
-                `Otrzymasz ${promoDiscount}% zniżki na kolejne ${validBillingCycles ? `${validBillingCycles} ` : ''}opłaty rozliczeniowe.`,
-            apply: 'Zastosuj',
-            error: {
-                invalid: 'Ten kod jest nieprawidłowy',
-            },
+            security: 'Expensify jest zgodny ze standardem PCI-DSS, używa szyfrowania na poziomie bankowym i wykorzystuje redundantną infrastrukturę, aby chronić Twoje dane.',
+            learnMoreAboutSecurity: 'Dowiedz się więcej o naszym zabezpieczeniu.',
         },
         subscriptionSettings: {
             title: 'Ustawienia subskrypcji',
-            summary: (subscriptionType: string, subscriptionSize: string, expensifyCode: string, autoRenew: string, autoIncrease: string) =>
-                `Typ subskrypcji: ${subscriptionType}, Rozmiar subskrypcji: ${subscriptionSize}${expensifyCode ? `, Kod Expensify: ${expensifyCode}` : ''}, Automatyczne odnawianie: ${autoRenew}, Automatyczne zwiększanie rocznych miejsc: ${autoIncrease}`,
+            summary: ({subscriptionType, subscriptionSize, autoRenew, autoIncrease}: SubscriptionSettingsSummaryParams) =>
+                `Typ subskrypcji: ${subscriptionType}, Rozmiar subskrypcji: ${subscriptionSize}, Automatyczne odnawianie: ${autoRenew}, Automatyczne zwiększanie rocznych miejsc: ${autoIncrease}`,
             none: 'brak',
             on: 'włączony',
             off: 'wyłączone',
             annual: 'Roczny',
             autoRenew: 'Automatyczne odnawianie',
             autoIncrease: 'Automatycznie zwiększaj liczbę rocznych stanowisk',
-            saveUpTo: (amountWithCurrency: string) => `Oszczędzaj do ${amountWithCurrency}/miesiąc na aktywnego członka`,
+            saveUpTo: ({amountWithCurrency}: SubscriptionSettingsSaveUpToParams) => `Oszczędzaj do ${amountWithCurrency}/miesiąc na aktywnego członka`,
             automaticallyIncrease:
                 'Automatycznie zwiększ liczbę rocznych miejsc, aby uwzględnić aktywnych członków przekraczających rozmiar Twojej subskrypcji. Uwaga: spowoduje to wydłużenie daty zakończenia Twojej rocznej subskrypcji.',
             disableAutoRenew: 'Wyłącz automatyczne odnawianie',
             helpUsImprove: 'Pomóż nam ulepszyć Expensify',
             whatsMainReason: 'Jaki jest główny powód wyłączenia automatycznego odnawiania?',
-            renewsOn: (date: string) => `Odnawia się ${date}.`,
-            pricingConfiguration: 'Cena zależy od konfiguracji. Żeby zapłacić jak najmniej, wybierz roczną subskrypcję i zamów Kartę Expensify.',
-            learnMore: (hasAdminsRoom: boolean) =>
+            renewsOn: ({date}: SubscriptionSettingsRenewsOnParams) => `Odnawia się ${date}.`,
+            pricingConfiguration: 'Cena zależy od konfiguracji. Aby uzyskać najniższą cenę, wybierz roczną subskrypcję i zdobądź kartę Expensify.',
+            learnMore: ({hasAdminsRoom}: SubscriptionSettingsLearnMoreParams) =>
                 `<muted-text>Dowiedz się więcej na naszej <a href="${CONST.PRICING}">stronie z cenami</a> lub porozmawiaj z naszym zespołem w swojej ${hasAdminsRoom ? `<a href="adminsRoom">Pokój #admins.</a>` : 'pokój #admins'}</muted-text>`,
             estimatedPrice: 'Szacunkowa cena',
-            changesBasedOn: 'To się zmienia w zależności od korzystania z Karty Expensify i poniższych opcji subskrypcji.',
-            collectBillingDescription: 'Przestrzenie robocze Collect są rozliczane miesięcznie za każdego członka, bez rocznego zobowiązania.',
-            pricing: 'Cennik',
+            changesBasedOn: 'To się zmienia w zależności od korzystania z karty Expensify i opcji subskrypcji poniżej.',
         },
-        cancelSubscription: {
-            title: 'Anuluj subskrypcję',
-            subtitle: 'Jaki jest główny powód, dla którego prosisz o anulowanie subskrypcji?',
+        requestEarlyCancellation: {
+            title: 'Poproś o wcześniejsze anulowanie',
+            subtitle: 'Jaki jest główny powód, dla którego prosisz o wcześniejsze anulowanie?',
             subscriptionCanceled: {
                 title: 'Subskrypcja anulowana',
                 subtitle: 'Twoja subskrypcja roczna została anulowana.',
                 info: 'Jeśli chcesz nadal korzystać ze swojego(-ich) workspace’u(-ów) w modelu płatności za użycie, wszystko jest gotowe.',
-                preventFutureActivity: (workspacesListRoute: string) =>
+                preventFutureActivity: ({workspacesListRoute}: WorkspacesListRouteParams) =>
                     `Jeśli chcesz zapobiec przyszłej aktywności i obciążeniom, musisz <a href="${workspacesListRoute}">usunąć swoje przestrzenie robocze</a>. Pamiętaj, że po usunięciu przestrzeni roboczych zostaniesz obciążony za wszelką nierozliczoną aktywność z bieżącego miesiąca kalendarzowego.`,
             },
             requestSubmitted: {
@@ -9305,7 +8059,7 @@ Dodaj więcej zasad wydatków, żeby chronić płynność finansową firmy.`,
                 subtitle:
                     'Dziękujemy za informację, że jesteś zainteresowany(-a) anulowaniem swojej subskrypcji. Rozpatrujemy Twoją prośbę i wkrótce skontaktujemy się z Tobą na czacie z <concierge-link>Concierge</concierge-link>.',
             },
-            acknowledgement: `Składając prośbę o rozwiązanie, potwierdzam i zgadzam się, że Expensify nie ma obowiązku uwzględnienia takiej prośby na mocy <a href=${CONST.OLD_DOT_PUBLIC_URLS.TERMS_URL}>Regulaminu świadczenia usług</a> Expensify ani innej obowiązującej umowy o świadczenie usług zawartej pomiędzy mną a Expensify oraz że Expensify zachowuje wyłączną dowolność w zakresie rozpatrzenia takiej prośby.`,
+            acknowledgement: `Składając prośbę o wcześniejsze rozwiązanie, potwierdzam i zgadzam się, że Expensify nie ma obowiązku uwzględnienia takiej prośby na mocy <a href=${CONST.OLD_DOT_PUBLIC_URLS.TERMS_URL}>Regulaminu świadczenia usług</a> Expensify ani innej obowiązującej umowy o świadczenie usług zawartej pomiędzy mną a Expensify oraz że Expensify zachowuje wyłączną dowolność w zakresie rozpatrzenia takiej prośby.`,
         },
     },
     feedbackSurvey: {
@@ -9324,14 +8078,11 @@ Dodaj więcej zasad wydatków, żeby chronić płynność finansową firmy.`,
     },
     delegate: {
         switchAccount: 'Przełącz konta:',
-        switch: 'Przełącz',
-        copilot: 'Copilot',
         copilotDelegatedAccess: 'Copilot: Dostęp delegowany',
         copilotDelegatedAccessDescription: 'Zezwól innym członkom na dostęp do Twojego konta.',
-        learnMoreAboutDelegatedAccess: 'Dowiedz się więcej o dostępie delegowanym',
-        addCopilot: 'Dodaj kopilota',
+        addCopilot: 'Dodaj pilota',
         membersCanAccessYourAccount: 'Ci członkowie mają dostęp do Twojego konta:',
-        youCanAccessTheseAccounts: 'Masz dostęp do tych kont:',
+        youCanAccessTheseAccounts: 'Masz dostęp do tych kont za pomocą przełącznika kont:',
         role: ({role}: OptionalParam<DelegateRoleParams> = {}) => {
             switch (role) {
                 case CONST.DELEGATE_ROLE.ALL:
@@ -9449,7 +8200,6 @@ Dodaj więcej zasad wydatków, żeby chronić płynność finansową firmy.`,
             theresWasAProblemDuringAWorkspaceConnectionSync: 'Wystąpił problem podczas synchronizacji połączenia przestrzeni roboczej',
             theresAProblemWithYourWallet: 'Wystąpił problem z Twoim portfelem',
             theresAProblemWithYourWalletTerms: 'Wystąpił problem z warunkami Twojego portfela',
-            aBankAccountIsLocked: 'Konto bankowe jest zablokowane',
         },
     },
     emptySearchView: {
@@ -9470,10 +8220,15 @@ Dodaj więcej zasad wydatków, żeby chronić płynność finansową firmy.`,
         conciergeLHNGBR: '<tooltip>Rozpocznij <strong>tutaj!</strong></tooltip>',
         saveSearchTooltip: '<tooltip><strong>Zmień nazwę zapisanych wyszukiwań</strong> tutaj!</tooltip>',
         accountSwitcher: '<tooltip>Uzyskaj tutaj dostęp do <strong>kont Copilot</strong></tooltip>',
+        scanTestTooltip: {
+            main: '<tooltip><strong>Zeskanuj nasz przykładowy paragon</strong>, aby zobaczyć, jak to działa!</tooltip>',
+            manager: '<tooltip>Wybierz naszego <strong>menedżera testów</strong>, aby go wypróbować!</tooltip>',
+            confirmation: '<tooltip>Teraz <strong>wyślij swój wydatek</strong> i zobacz, jak dzieje się magia!</tooltip>',
+            tryItOut: 'Wypróbuj to',
+        },
         outstandingFilter: '<tooltip>Filtruj wydatki,\nktóre <strong>wymagają zatwierdzenia</strong></tooltip>',
         scanTestDriveTooltip: '<tooltip>Wyślij ten paragon, aby\n<strong>zakończyć jazdę próbną!</strong></tooltip>',
         gpsTooltip: '<tooltip>Śledzenie GPS w toku! Gdy skończysz, zatrzymaj śledzenie poniżej.</tooltip>',
-        hasFilterNegation: '<tooltip>Wyszukaj wydatki bez paragonów za pomocą <strong>-has:receipt</strong>.</tooltip>',
     },
     discardChangesConfirmation: {
         title: 'Odrzucić zmiany?',
@@ -9489,7 +8244,7 @@ Dodaj więcej zasad wydatków, żeby chronić płynność finansową firmy.`,
         confirmation: {
             title: 'Potwierdź połączenie',
             description: 'Upewnij się, że poniższe szczegóły wyglądają dla Ciebie w porządku. Po potwierdzeniu rozmowy wyślemy zaproszenie z dodatkowymi informacjami.',
-            setupSpecialist: 'Twój opiekun klienta',
+            setupSpecialist: 'Twój specjalista ds. konfiguracji',
             meetingLength: 'Długość spotkania',
             dateTime: 'Data i godzina',
             minutes: '30 minut',
@@ -9537,20 +8292,6 @@ Oto *paragon testowy*, żeby pokazać Ci, jak to działa:`,
         exportInProgress: 'Trwa eksport',
         conciergeWillSend: 'Concierge wkrótce wyśle Ci plik.',
     },
-    exportDownload: {
-        preparingTitle: 'Preparing download...',
-        preparingBody: 'You can either wait for the download to finish or Concierge can send it to you via chat.',
-        sendFromConcierge: "Send me the file when it's ready",
-        conciergeTitle: 'You bet!',
-        conciergeBody: 'Concierge will send you a message when the file is ready.',
-        goToConcierge: 'Go to Concierge',
-        dismiss: 'Dismiss',
-        readyTitle: 'Your file is ready!',
-        readyBody: "If it didn't automatically download, use the button below.",
-        downloadFile: 'Download file',
-        failedTitle: 'Export failed',
-        close: 'Close',
-    },
     domain: {
         notVerified: 'Niezweryfikowane',
         retry: 'Ponów próbę',
@@ -9584,7 +8325,7 @@ Oto *paragon testowy*, żeby pokazać Ci, jak to działa:`,
         goToDomain: 'Przejdź do domeny',
         samlLogin: {
             title: 'Logowanie SAML',
-            subtitle: `<muted-text>Skonfiguruj logowanie członków za pomocą <a href="${CONST.SAML_HELP_URL}">jednokrotnego logowania SAML (SSO)</a>.</muted-text>`,
+            subtitle: `<muted-text>Skonfiguruj logowanie członków za pomocą <a href="${CONST.SAML_HELP_URL}">jednokrotnego logowania SAML (SSO).</a></muted-text>`,
             enableSamlLogin: 'Włącz logowanie SAML',
             allowMembers: 'Zezwól członkom logować się przy użyciu SAML.',
             requireSamlLogin: 'Wymagaj logowania SAML',
@@ -9594,8 +8335,6 @@ Oto *paragon testowy*, żeby pokazać Ci, jak to działa:`,
             disableSamlRequired: 'Wyłącz wymaganie SAML',
             oktaWarningPrompt: 'Na pewno? Spowoduje to również wyłączenie Okta SCIM.',
             requireWithEmptyMetadataError: 'Dodaj poniżej metadane dostawcy tożsamości, aby włączyć',
-            pleaseDisableTwoFactorAuth: (twoFactorAuthSettingsUrl: string) =>
-                `<muted-text>Aby włączyć logowanie SAML, wyłącz najpierw <a href="${twoFactorAuthSettingsUrl}">wymuszanie uwierzytelniania dwuskładnikowego</a>.</muted-text>`,
         },
         samlConfigurationDetails: {
             title: 'Szczegóły konfiguracji SAML',
@@ -9644,6 +8383,7 @@ Oto *paragon testowy*, żeby pokazać Ci, jak to działa:`,
             primaryContact: 'Główny kontakt',
             addPrimaryContact: 'Dodaj główny kontakt',
             setPrimaryContactError: 'Nie można ustawić głównego kontaktu. Spróbuj ponownie później.',
+            settings: 'Ustawienia',
             consolidatedDomainBilling: 'Zbiorcze rozliczanie domeny',
             consolidatedDomainBillingDescription: (domainName: string) =>
                 `<comment><muted-text-label>Po włączeniu główny kontakt będzie opłacać wszystkie przestrzenie robocze należące do członków <strong>${domainName}</strong> i otrzymywać wszystkie potwierdzenia rozliczeń.</muted-text-label></comment>`,
@@ -9660,105 +8400,25 @@ Oto *paragon testowy*, żeby pokazać Ci, jak to działa:`,
             resetDomain: 'Resetuj domenę',
             resetDomainExplanation: ({domainName}: {domainName?: string}) => `Wpisz proszę <strong>${domainName}</strong>, aby potwierdzić reset domeny.`,
             enterDomainName: 'Wprowadź tutaj swoją nazwę domeny',
-            resetDomainInfo: `Ta operacja jest <strong>trwała</strong> i spowoduje usunięcie następujących danych: <br/> <bullet-list><bullet-item>Połączenia z firmowymi kartami oraz wszystkie nierozliczone wydatki z tych kart</bullet-item><bullet-item>Ustawienia SAML i ustawienia grup</bullet-item><bullet-item>Dane podróży oraz dostęp do Expensify Travel</bullet-item></bullet-list> Wszystkie konta, przestrzenie robocze, raporty, wydatki i inne dane pozostaną bez zmian. <br/><br/>Uwaga: Możesz usunąć tę domenę ze swojej listy domen, usuwając powiązany adres e-mail z sekcji <a href="#">metody kontaktu</a>.`,
+            resetDomainInfo: `Ta czynność jest <strong>trwała</strong> i spowoduje usunięcie następujących danych: <br/> <ul><li>Połączeń z kartami firmowymi oraz wszystkich nierozliczonych wydatków z tych kart</li> <li>Ustawień SAML i grup</li> </ul> Wszystkie konta, przestrzenie robocze, raporty, wydatki i inne dane pozostaną bez zmian. <br/><br/>Uwaga: Możesz usunąć tę domenę z listy swoich domen, usuwając powiązany adres e-mail z <a href="#">metod kontaktu</a>.`,
         },
         domainMembers: 'Członkowie domeny',
         members: {
             title: 'Członkowie',
             findMember: 'Znajdź członka',
             addMember: 'Dodaj członka',
-            allMembers: 'Wszyscy członkowie',
             email: 'Adres e-mail',
-            closeAccount: () => ({
-                one: 'Zamknij konto',
-                other: 'Zamknij konta',
-            }),
+            closeAccount: 'Zamknij konto',
             closeAccountPrompt: 'Czy na pewno? Ta czynność jest nieodwracalna.',
-            forceCloseAccount: () => ({one: 'Wymuś zamknięcie konta', other: 'Wymuś zamknięcie kont'}),
-            safeCloseAccount: () => ({
-                one: 'Zamknij konto bezpiecznie',
-                other: 'Zamknij konta bezpiecznie',
-            }),
-            closeAccountInfo: () => ({
-                one: 'Zalecamy bezpieczne zamknięcie konta, aby pominąć jego zamykanie w przypadku, gdy występują: <bullet-list><bullet-item>Oczekujące zatwierdzenia</bullet-item><bullet-item>Aktywne zwroty kosztów</bullet-item><bullet-item>Brak alternatywnych metod logowania</bullet-item></bullet-list>W przeciwnym razie możesz zignorować powyższe środki ostrożności i wymusić zamknięcie wybranego konta.',
-                other: 'Zalecamy bezpieczne zamknięcie kont, aby pominąć ich zamykanie w przypadku, gdy występują: <bullet-list><bullet-item>Oczekujące zatwierdzenia</bullet-item><bullet-item>Aktywne zwroty kosztów</bullet-item><bullet-item>Brak alternatywnych metod logowania</bullet-item></bullet-list>W przeciwnym razie możesz zignorować powyższe środki ostrożności i wymusić zamknięcie wybranych kont.',
-            }),
+            forceCloseAccount: 'Wymuś zamknięcie konta',
+            safeCloseAccount: 'Zamknij konto bezpiecznie',
+            closeAccountInfo:
+                'Zalecamy bezpieczne zamknięcie konta, aby pominąć jego zamykanie w przypadku, gdy występują: <ul><li>Oczekujące zatwierdzenia</li><li>Aktywne zwroty kosztów</li><li>Brak alternatywnych metod logowania</li></ul>W przeciwnym razie możesz zignorować powyższe środki ostrożności i wymusić zamknięcie wybranego konta.',
             error: {
                 removeMember: 'Nie można usunąć tego użytkownika. Spróbuj ponownie.',
                 addMember: 'Nie można dodać tego członka. Spróbuj ponownie.',
-                vacationDelegate: 'Nie można ustawić tego użytkownika jako zastępującego na czas nieobecności. Spróbuj ponownie.',
-                moveMember: 'Nie można przenieść tego członka. Spróbuj ponownie.',
-                moveMemberNotPolicyAdmin:
-                    'Nie można przenieść członka do grupy domeny. Musisz być Administratorem Zasad dla Preferowanych Zasad ustawionych dla grupy domeny, do której próbujesz przenieść tego użytkownika.',
-            },
-            cannotSetVacationDelegateForMember: (email: string) => `Nie możesz ustawić zastępstwa urlopowego dla ${email}, ponieważ jest on/ona obecnie zastępcą dla następujących członków:`,
-            reportSuspiciousActivityPrompt: (email: string) =>
-                `Czy na pewno? To zablokuje konto użytkownika <strong>${email}</strong>. <br /><br /> Nasz zespół następnie przejrzy konto i usunie wszelki nieautoryzowany dostęp. Aby odzyskać dostęp, będą musieli współpracować z Concierge.`,
-            reportSuspiciousActivityConfirmationPrompt: 'Przejrzymy konto, aby potwierdzić, że bezpiecznie je odblokować, i skontaktujemy się przez Concierge w razie pytań.',
-            emptyMembers: {title: 'Brak członków w tej grupie', subtitle: 'Dodaj członka lub spróbuj zmienić filtr powyżej.'},
-            moveToGroup: 'Przenieś do grupy',
-            chooseWhereToMove: ({count}: {count: number}) => `Wybierz, dokąd przenieść ${count} ${count === 1 ? 'członka' : 'członków'}.`,
-            domainGroup: 'Grupa domen',
-            chooseWhereToMoveName: ({name}: {name: string}) => `Wybierz, dokąd przenieść ${name}.`,
-            membersFeatureList: {
-                subtitle: ({domainName}: {domainName: string}) =>
-                    `<muted-text>Zweryfikuj swoją domenę, aby mieć większą kontrolę nad członkami <strong>${domainName}</strong> w Expensify.</muted-text>`,
-                controlPolicyCreation: 'Ogranicz tworzenie przestrzeni roboczych',
-                enableSamlSso: 'Włącz logowanie SAML SSO',
-                enforce2FA: 'Wymuś 2FA',
             },
         },
-        common: {
-            settings: 'Ustawienia',
-            forceTwoFactorAuth: 'Wymuś uwierzytelnianie dwuskładnikowe',
-            forceTwoFactorAuthSAMLEnabledDescription: (samlPageUrl: string) =>
-                `<muted-text>Wyłącz proszę <a href="${samlPageUrl}">SAML</a>, aby wymusić uwierzytelnianie dwuskładnikowe.</muted-text>`,
-            forceTwoFactorAuthDescription: `<muted-text>Wymagaj uwierzytelniania dwuskładnikowego od wszystkich członków tej domeny. Członkowie domeny zostaną poproszeni o skonfigurowanie uwierzytelniania dwuskładnikowego na swoim koncie po zalogowaniu.</muted-text>`,
-            forceTwoFactorAuthError: 'Nie udało się zmienić wymuszania uwierzytelniania dwuskładnikowego. Spróbuj ponownie później.',
-            resetTwoFactorAuth: 'Zresetuj uwierzytelnianie dwuskładnikowe',
-            error: 'Nie udało się zapisać tej zmiany. Spróbuj ponownie.',
-        },
-        groups: {
-            title: 'Grupy',
-            memberCount: () => ({one: '1 członek', other: (count: number) => `${count} członków`}),
-            defaultGroup: 'Domyślna grupa dla nowych członków',
-            defaultGroupPrompt: (currentName: string, newName: string) =>
-                `Czy na pewno chcesz ustawić ${newName} jako grupę domyślną? Nowi członkowie będą zapraszani do tej grupy zamiast do poprzedniej grupy domyślnej (${currentName}). `,
-            makeDefault: 'Ustaw jako domyślną',
-            neverMind: 'Nieważne',
-            createGroupError: 'Nie udało się utworzyć tej grupy. Spróbuj ponownie.',
-            permissions: 'Uprawnienia grupy',
-            createNewGroupButton: 'Nowa grupa',
-            createGroupSubmitButton: 'Utwórz grupę',
-            expensifyCardPreferredWorkspace: 'Preferowany workspace karty Expensify',
-            expensifyCardPreferredWorkspaceDescription:
-                'Wszystkie transakcje Expensify Card będą tworzone w preferowanym obszarze roboczym Expensify Card zamiast w preferowanym obszarze roboczym.',
-            strictlyEnforceWorkspaceRules: 'Ściśle egzekwuj reguły przestrzeni roboczej',
-            strictlyEnforceWorkspaceRulesDescription: 'Przed przesłaniem raportu muszą zostać spełnione wszystkie reguły przestrzeni roboczej. Ręczne wyjątki są niedozwolone.',
-            restrictExpenseWorkspaceCreation: 'Ogranicz tworzenie/usuwanie przestrzeni roboczej wydatków',
-            restrictExpenseWorkspaceCreationDescription:
-                'Uniemożliw członkom tworzenie przestrzeni roboczej wydatków lub usuwanie siebie z przestrzeni roboczej wydatków. Jest to przydatne, aby zapobiec używaniu Expensify do przesyłania raportów przeznaczonych do użytku poza Twoją domeną, w połączeniu ze ścisłym egzekwowaniem przestrzeni roboczej.',
-            deleteGroup: 'Usuń grupę',
-            deleteGroupDangerConfirmationModal: 'Usuń grupę',
-            deleteGroupDangerConfirmationModalDescription: (defaultGroupName: string) =>
-                `Czy na pewno? Spowoduje to ponowne przypisanie wszystkich członków do domyślnej grupy (${defaultGroupName}) i nie można tego cofnąć.`,
-            deleteGroupError: 'Nie udało się usunąć tej grupy. Spróbuj ponownie.',
-            preferredWorkspace: 'Preferowany obszar roboczy',
-            preferredWorkspaceDescription: (enabled: boolean) => `Wszystkie nowe raporty i wydatki będą tworzone w ${enabled ? 'wybranym preferowanym' : 'tym'} obszarze roboczym.`,
-            preferredWorkspaceSelectDescription: 'Wszystkie nowe wydatki i raporty będą tworzone w tym obszarze roboczym.',
-            noWorkspacesMessage: 'W tej domenie nie ma żadnych obszarów roboczych. Obszar roboczy jest wymagany, aby włączyć to ograniczenie.',
-            restrictDefaultLoginSelection: 'Ogranicz wybór domyślnego logowania',
-            restrictDefaultLoginSelectionDescription: 'Zapobiega zmianie adresu e-mail do logowania przez członków na adres spoza domeny firmowej, aby obejść ograniczenia zasad.',
-            expensifyCardPreferredWorkspaceDisabledMessage: 'Aby włączyć to ustawienie, najpierw włącz preferowane miejsce pracy i skonfiguruj karty Expensify w swojej domenie.',
-            findGroup: 'Znajdź grupę',
-        },
-    },
-    proactiveAppReview: {
-        title: 'Podoba Ci się nowy Expensify?',
-        description: 'Daj nam znać, abyśmy mogli pomóc uczynić Twoje rozliczanie wydatków jeszcze lepszym.',
-        positiveButton: 'Tak!',
-        negativeButton: 'Niekoniecznie',
-    },
-    monthPickerPage: {month: 'Miesiąc', selectMonth: 'Wybierz miesiąc'},
+    },
 };
 export default translations;
diff --git a/src/languages/pt-BR.ts b/src/languages/pt-BR.ts
index b54b2a91bccd..0cf4500c24fd 100644
--- a/src/languages/pt-BR.ts
+++ b/src/languages/pt-BR.ts
@@ -11,52 +11,189 @@
  */
 import {CONST as COMMON_CONST} from 'expensify-common';
 import startCase from 'lodash/startCase';
-import type {ValueOf} from 'type-fest';
 import type {OnboardingTask} from '@libs/actions/Welcome/OnboardingFlow';
 import StringUtils from '@libs/StringUtils';
 import dedent from '@libs/StringUtils/dedent';
 import CONST from '@src/CONST';
 import type {Country} from '@src/CONST';
 import type OriginalMessage from '@src/types/onyx/OriginalMessage';
-import type {OriginalMessageSettlementAccountLocked, PersonalRulesModifiedFields, PolicyRulesModifiedFields} from '@src/types/onyx/OriginalMessage';
+import type {OriginalMessageSettlementAccountLocked, PolicyRulesModifiedFields} from '@src/types/onyx/OriginalMessage';
+import ObjectUtils from '@src/types/utils/ObjectUtils';
 import type en from './en';
 import type {
+    AddBudgetParams,
+    AddedOrDeletedPolicyReportFieldParams,
+    AddOrDeletePolicyCustomUnitRateParams,
     ChangeFieldParams,
-    ConciergeBrokenCardConnectionParams,
     ConnectionNameParams,
+    CreatedReportForUnapprovedTransactionsParams,
     DelegateRoleParams,
     DeleteActionParams,
+    DeleteBudgetParams,
     DeleteConfirmationParams,
     EditActionParams,
     ExportAgainModalDescriptionParams,
     ExportIntegrationSelectedParams,
+    ImportPolicyCustomUnitRatesParams,
     IntacctMappingTitleParams,
     InvalidPropertyParams,
     InvalidValueParams,
     MarkReimbursedFromIntegrationParams,
     MissingPropertyParams,
     MovedFromPersonalSpaceParams,
+    MultifactorAuthenticationTranslationParams,
+    NextStepParams,
     NotAllowedExtensionParams,
     OptionalParam,
     PaidElsewhereParams,
     ParentNavigationSummaryParams,
     RemovedFromApprovalWorkflowParams,
+    RemovedPolicyCustomUnitSubRateParams,
     ReportArchiveReasonsClosedParams,
     ReportArchiveReasonsInvoiceReceiverPolicyDeletedParams,
     ReportArchiveReasonsMergedParams,
     ReportArchiveReasonsRemovedFromPolicyParams,
+    ReportFieldParams,
+    ReportPolicyNameParams,
+    RequestAmountParams,
+    RequiredFieldParams,
     ResolutionConstraintsParams,
+    ReviewParams,
+    RoleNamesParams,
+    RoomNameReservedErrorParams,
+    RoomRenamedToParams,
+    RoutedDueToDEWParams,
+    RulesEnableWorkflowsParams,
+    SecondaryLoginParams,
+    SetTheDistanceMerchantParams,
+    SetTheRequestParams,
+    SettledAfterAddedBankAccountParams,
+    SettleExpensifyCardParams,
+    SettlementAccountInfoParams,
+    SettlementAccountReconciliationParams,
+    SettlementDateParams,
     ShareParams,
+    SignerInfoMessageParams,
+    SignUpNewFaceCodeParams,
     SizeExceededParams,
+    SplitAmountParams,
+    SplitDateRangeParams,
+    SplitExpenseEditTitleParams,
+    SplitExpenseSubtitleParams,
+    StatementTitleParams,
     StepCounterParams,
+    StripePaidParams,
+    SubmitsToParams,
+    SubmittedToVacationDelegateParams,
+    SubmittedWithMemoParams,
+    SubscriptionCommitmentParams,
+    SubscriptionSettingsLearnMoreParams,
+    SubscriptionSettingsRenewsOnParams,
+    SubscriptionSettingsSaveUpToParams,
+    SubscriptionSettingsSummaryParams,
+    SubscriptionSizeParams,
     SyncStageNameConnectionsParams,
+    TaskCreatedActionParams,
+    TaxAmountParams,
+    TermsParams,
+    ThreadRequestReportNameParams,
+    ThreadSentMoneyReportNameParams,
+    ToggleImportTitleParams,
+    TotalAmountGreaterOrLessThanOriginalParams,
+    ToValidateLoginParams,
+    TransferParams,
+    TravelTypeParams,
+    TrialStartedTitleParams,
+    UnapproveWithIntegrationWarningParams,
     UnshareParams,
-    UnsupportedFormulaValueErrorParams,
+    UntilTimeParams,
+    UpdatedBudgetParams,
+    UpdatedCustomFieldParams,
+    UpdatedPolicyApprovalRuleParams,
+    UpdatedPolicyAuditRateParams,
+    UpdatedPolicyAutoHarvestingParams,
+    UpdatedPolicyBudgetNotificationParams,
+    UpdatedPolicyCategoriesParams,
+    UpdatedPolicyCategoryDescriptionHintTypeParams,
+    UpdatedPolicyCategoryExpenseLimitTypeParams,
+    UpdatedPolicyCategoryGLCodeParams,
+    UpdatedPolicyCategoryMaxAmountNoReceiptParams,
+    UpdatedPolicyCategoryMaxExpenseAmountParams,
+    UpdatedPolicyCategoryNameParams,
+    UpdatedPolicyCategoryParams,
+    UpdatedPolicyCurrencyParams,
+    UpdatedPolicyCustomUnitRateEnabledParams,
+    UpdatedPolicyCustomUnitRateParams,
+    UpdatedPolicyCustomUnitSubRateParams,
+    UpdatedPolicyCustomUnitTaxClaimablePercentageParams,
+    UpdatedPolicyCustomUnitTaxRateExternalIDParams,
+    UpdatedPolicyDefaultTitleParams,
+    UpdatedPolicyDescriptionParams,
+    UpdatedPolicyFieldWithNewAndOldValueParams,
+    UpdatedPolicyFieldWithValueParams,
+    UpdatedPolicyFrequencyParams,
+    UpdatedPolicyManualApprovalThresholdParams,
+    UpdatedPolicyOwnershipParams,
+    UpdatedPolicyPreventSelfApprovalParams,
+    UpdatedPolicyReimbursementChoiceParams,
+    UpdatedPolicyReimbursementEnabledParams,
+    UpdatedPolicyReimburserParams,
+    UpdatedPolicyReportFieldDefaultValueParams,
+    UpdatedPolicyTagFieldParams,
+    UpdatedPolicyTagListParams,
+    UpdatedPolicyTagListRequiredParams,
+    UpdatedPolicyTagNameParams,
+    UpdatedPolicyTagParams,
+    UpdatedPolicyTaxParams,
+    UpdatedPolicyTimeEnabledParams,
+    UpdatedPolicyTimeRateParams,
+    UpdatedTheDistanceMerchantParams,
+    UpdatedTheRequestParams,
+    UpdatePolicyCustomUnitDefaultCategoryParams,
+    UpdatePolicyCustomUnitParams,
+    UpdatePolicyCustomUnitTaxEnabledParams,
     UpdateRoleParams,
-    ViolationsIncreasedDistanceParams,
+    UpgradeSuccessMessageParams,
+    UsePlusButtonParams,
+    UserIsAlreadyMemberParams,
+    UserSplitParams,
+    VacationDelegateParams,
+    ViolationsCashExpenseWithNoReceiptParams,
+    ViolationsConversionSurchargeParams,
+    ViolationsCustomRulesParams,
+    ViolationsInvoiceMarkupParams,
+    ViolationsMaxAgeParams,
+    ViolationsMissingTagParams,
     ViolationsModifiedAmountParams,
+    ViolationsOverCategoryLimitParams,
+    ViolationsOverLimitParams,
+    ViolationsPerDayLimitParams,
+    ViolationsProhibitedExpenseParams,
+    ViolationsReceiptRequiredParams,
+    ViolationsRterParams,
+    ViolationsTagOutOfPolicyParams,
+    ViolationsTaxOutOfPolicyParams,
+    WaitingOnBankAccountParams,
+    WalletAgreementParams,
+    WalletProgramParams,
+    WelcomeEnterMagicCodeParams,
+    WelcomeToRoomParams,
+    WeSentYouMagicSignInLinkParams,
+    WorkEmailMergingBlockedParams,
+    WorkEmailResendCodeParams,
+    WorkflowSettingsParam,
     WorkspaceLockedPlanTypeParams,
+    WorkspaceMemberList,
+    WorkspaceMembersCountParams,
+    WorkspaceOwnerWillNeedToAddOrUpdatePaymentCardParams,
+    WorkspaceRouteParams,
+    WorkspaceShareNoteParams,
+    WorkspacesListRouteParams,
+    WorkspaceUpgradeNoteParams,
+    WorkspaceYouMayJoin,
     YourPlanPriceParams,
+    YourPlanPriceValueParams,
+    ZipCodeExampleFormatParams,
 } from './params';
 import type {TranslationDeepObject} from './types';
 
@@ -90,10 +227,8 @@ const translations: TranslationDeepObject<typeof en> = {
         optional: 'Opcional',
         new: 'Novo',
         newFeature: 'Novo recurso',
-        beta: 'Beta',
         search: 'Buscar',
         reports: 'Relatórios',
-        spend: 'Gastos',
         find: 'Localizar',
         searchWithThreeDots: 'Buscar...',
         next: 'Próximo',
@@ -118,14 +253,6 @@ const translations: TranslationDeepObject<typeof en> = {
         workspaces: 'Espaços de trabalho',
         home: 'Início',
         inbox: 'Caixa de entrada',
-        yourReviewIsRequired: 'Sua revisão é necessária',
-        actionBadge: {
-            submit: 'Enviar',
-            approve: 'Aprovar',
-            pay: 'Pagar',
-            fix: 'Corrigir',
-            task: 'Tarefa',
-        },
         success: 'Concluído',
         group: 'Grupo',
         profile: 'Perfil',
@@ -135,7 +262,7 @@ const translations: TranslationDeepObject<typeof en> = {
         wallet: 'Carteira',
         preferences: 'Preferências',
         view: 'Visualizar',
-        review: (amount?: string) => `Revisar${amount ? ` ${amount}` : ''}`,
+        review: (reviewParams?: ReviewParams) => `Revisar${reviewParams?.amount ? ` ${reviewParams?.amount}` : ''}`,
         not: 'Não',
         signIn: 'Entrar',
         signInWithGoogle: 'Entrar com o Google',
@@ -146,7 +273,6 @@ const translations: TranslationDeepObject<typeof en> = {
         lastName: 'Sobrenome',
         scanning: 'Escaneando',
         analyzing: 'Analisando...',
-        thinking: 'Concierge está pensando...',
         addCardTermsOfService: 'Termos de Serviço da Expensify',
         perPerson: 'por pessoa',
         phone: 'Telefone',
@@ -208,12 +334,10 @@ const translations: TranslationDeepObject<typeof en> = {
         admin: 'Admin',
         owner: 'Proprietário',
         dateFormat: 'YYYY-MM-DD',
-        calendarOpened: 'calendário aberto',
         send: 'Enviar',
         na: 'N/D',
         noResultsFound: 'Nenhum resultado encontrado',
         noResultsFoundMatching: (searchString: string) => `Nenhum resultado encontrado para "${searchString}"`,
-        suggestionsAvailableFor: (searchString: string) => (searchString ? `Sugestões disponíveis para "${searchString}".` : 'Sugestões disponíveis.'),
         recentDestinations: 'Destinos recentes',
         timePrefix: 'É',
         conjunctionFor: 'para',
@@ -224,7 +348,6 @@ const translations: TranslationDeepObject<typeof en> = {
         conjunctionTo: 'para',
         genericErrorMessage: 'Ops... algo deu errado e sua solicitação não pôde ser concluída. Tente novamente mais tarde.',
         percentage: 'Porcentagem',
-        progressBarLabel: 'Progresso da integração',
         converted: 'Convertido',
         error: {
             invalidAmount: 'Valor inválido',
@@ -263,7 +386,6 @@ const translations: TranslationDeepObject<typeof en> = {
         reset: 'Redefinir',
         done: 'Concluído',
         more: 'Mais',
-        other: 'Outro',
         debitCard: 'Cartão de débito',
         bankAccount: 'Conta bancária',
         personalBankAccount: 'Conta bancária pessoal',
@@ -289,7 +411,7 @@ const translations: TranslationDeepObject<typeof en> = {
         verify: 'Verificar',
         yesContinue: 'Sim, continuar',
         websiteExample: 'por exemplo, https://www.expensify.com',
-        zipCodeExampleFormat: (zipSampleFormat: string) => (zipSampleFormat ? `por exemplo, ${zipSampleFormat}` : ''),
+        zipCodeExampleFormat: ({zipSampleFormat}: ZipCodeExampleFormatParams) => (zipSampleFormat ? `por exemplo, ${zipSampleFormat}` : ''),
         description: 'Descrição',
         title: 'Título',
         assignee: 'Responsável',
@@ -300,8 +422,6 @@ const translations: TranslationDeepObject<typeof en> = {
         per: 'por',
         mi: 'milha',
         km: 'quilômetro',
-        milesAbbreviated: 'mi',
-        kilometersAbbreviated: 'km',
         copied: 'Copiado!',
         someone: 'Alguém',
         total: 'Total',
@@ -310,7 +430,6 @@ const translations: TranslationDeepObject<typeof en> = {
         letsStart: `Vamos começar`,
         showMore: 'Mostrar mais',
         showLess: 'Mostrar menos',
-        plusMore: ({count}: {count: number}) => `+${count} mais`,
         merchant: 'Estabelecimento',
         change: 'Alterar',
         category: 'Categoria',
@@ -334,11 +453,8 @@ const translations: TranslationDeepObject<typeof en> = {
         selectCurrency: 'Selecione uma moeda',
         selectSymbolOrCurrency: 'Selecione um símbolo ou moeda',
         card: 'Cartão',
-        mcc: 'MCC',
-        categoryGLCode: 'Código contábil da categoria',
         whyDoWeAskForThis: 'Por que pedimos isso?',
         required: 'Obrigatório',
-        automatic: 'Automático',
         showing: 'Mostrando',
         of: 'de',
         default: 'Padrão',
@@ -346,7 +462,6 @@ const translations: TranslationDeepObject<typeof en> = {
         member: 'Membro',
         auditor: 'Auditor',
         role: 'Função',
-        roleCannotBeChanged: (workflowsLinkPage: string) => `A função não pode ser alterada porque este membro é um <a href="${workflowsLinkPage}">pagador</a> neste espaço de trabalho.`,
         currency: 'Moeda',
         groupCurrency: 'Moeda do grupo',
         rate: 'Avaliar',
@@ -384,7 +499,6 @@ const translations: TranslationDeepObject<typeof en> = {
         reportID: 'ID do relatório',
         longReportID: 'ID de relatório longo',
         withdrawalID: 'ID do saque',
-        withdrawalStatus: 'Status do saque',
         bankAccounts: 'Contas bancárias',
         chooseFile: 'Escolher arquivo',
         chooseFiles: 'Escolher arquivos',
@@ -418,21 +532,19 @@ const translations: TranslationDeepObject<typeof en> = {
         validate: 'Validar',
         downloadAsPDF: 'Baixar como PDF',
         downloadAsCSV: 'Baixar como CSV',
-        print: 'Imprimir',
         help: 'Ajuda',
-        collapsed: 'Recolhido',
-        expanded: 'Expandido',
         expenseReport: 'Relatório de despesas',
-        rateOutOfPolicy: 'Tarifa fora da política',
+        expenseReports: 'Relatórios de despesas',
+        rateOutOfPolicy: 'Taxa fora da política',
         leaveWorkspace: 'Sair do espaço de trabalho',
         leaveWorkspaceConfirmation: 'Se você sair deste workspace, não poderá enviar despesas para ele.',
         leaveWorkspaceConfirmationAuditor: 'Se você sair deste espaço de trabalho, não poderá visualizar seus relatórios e configurações.',
         leaveWorkspaceConfirmationAdmin: 'Se você sair deste workspace, não poderá mais gerenciar as configurações dele.',
-        leaveWorkspaceConfirmationApprover: (workspaceOwner: string) =>
+        leaveWorkspaceConfirmationApprover: ({workspaceOwner}: {workspaceOwner: string}) =>
             `Se você sair deste workspace, você será substituído no fluxo de aprovação por ${workspaceOwner}, o proprietário do workspace.`,
-        leaveWorkspaceConfirmationExporter: (workspaceOwner: string) =>
+        leaveWorkspaceConfirmationExporter: ({workspaceOwner}: {workspaceOwner: string}) =>
             `Se você sair deste espaço de trabalho, você será substituído como exportador preferencial por ${workspaceOwner}, o proprietário do espaço de trabalho.`,
-        leaveWorkspaceConfirmationTechContact: (workspaceOwner: string) =>
+        leaveWorkspaceConfirmationTechContact: ({workspaceOwner}: {workspaceOwner: string}) =>
             `Se você sair deste workspace, você será substituído como contato técnico por ${workspaceOwner}, o proprietário do workspace.`,
         leaveWorkspaceReimburser: 'Você não pode sair deste workspace sendo o reembolsador. Defina um novo reembolsador em Workspaces > Fazer ou acompanhar pagamentos e tente novamente.',
         reimbursable: 'Reembolsável',
@@ -440,6 +552,9 @@ const translations: TranslationDeepObject<typeof en> = {
         comments: 'Comentários',
         sharedIn: 'Compartilhado em',
         unreported: 'Não informado',
+        explore: 'Explorar',
+        insights: 'Insights',
+        todo: 'Pendências',
         invoice: 'Fatura',
         expense: 'Despesa',
         chat: 'Chat',
@@ -450,15 +565,12 @@ const translations: TranslationDeepObject<typeof en> = {
         on: 'Ativado',
         before: 'Antes',
         after: 'Depois',
-        range: 'Intervalo',
         reschedule: 'Reagendar',
         general: 'Geral',
         workspacesTabTitle: 'Espaços de trabalho',
         headsUp: 'Atenção!',
         submitTo: 'Enviar para',
         forwardTo: 'Encaminhar para',
-        approvalLimit: 'Limite de aprovação',
-        overLimitForwardTo: 'Encaminhar se exceder o limite',
         merge: 'Mesclar',
         none: 'Nenhum',
         unstableInternetConnection: 'Conexão de internet instável. Verifique sua rede e tente novamente.',
@@ -475,48 +587,23 @@ const translations: TranslationDeepObject<typeof en> = {
         actionRequired: 'Ação necessária',
         duplicate: 'Duplicar',
         duplicated: 'Duplicado',
-        duplicateExpense: 'Duplicar despesa',
+        duplicateExpense: 'Despesa duplicada',
         exchangeRate: 'Taxa de câmbio',
         reimbursableTotal: 'Total reembolsável',
         nonReimbursableTotal: 'Total não reembolsável',
-        opensInNewTab: 'Abre em uma nova aba',
         locked: 'Bloqueado',
         month: 'Mês',
         week: 'Semana',
         year: 'Ano',
         quarter: 'Trimestre',
-        vacationDelegate: 'Delegado de férias',
-        expensifyLogo: 'Logo da Expensify',
-        concierge: {greeting: 'Oi, como posso ajudar?', showHistory: 'Mostrar histórico'},
-        duplicateReport: 'Duplicar relatório',
-        approver: 'Aprovador',
-        goToConcierge: 'Ir para o Concierge',
-        allSet: 'Tudo pronto!',
-        enterDigitLabel: ({digitIndex, totalDigits}: {digitIndex: number; totalDigits: number}) => `inserir dígito ${digitIndex} de ${totalDigits}`,
-        copyOfReportName: (reportName: string) => `Cópia de ${reportName}`,
-        previousMonth: 'Mês anterior',
-        nextMonth: 'Próximo mês',
-        previousYear: 'Ano anterior',
-        nextYear: 'Ano que vem',
-        avatar: 'Avatar',
-        editor: 'Editor',
-        restrictions: 'Restrições',
-    },
-    socials: {
-        podcast: 'Siga-nos no Podcast',
-        twitter: 'Siga-nos no Twitter',
-        instagram: 'Siga-nos no Instagram',
-        facebook: 'Siga-nos no Facebook',
-        linkedin: 'Siga-nos no LinkedIn',
-    },
-    concierge: {
-        collapseReasoning: 'Recolher raciocínio',
-        expandReasoning: 'Expandir raciocínio',
-        enableNotifications: {prompt: 'Quer ser avisado quando o Concierge responder?', cta: 'Notificar'},
     },
     supportalNoAccess: {
         title: 'Calma aí',
-        descriptionWithCommand: (command?: string) =>
+        descriptionWithCommand: ({
+            command,
+        }: {
+            command?: string;
+        } = {}) =>
             `Você não tem autorização para realizar esta ação quando o suporte estiver conectado (comando: ${command ?? ''}). Se você acha que o time de Success deveria poder realizar esta ação, inicie uma conversa no Slack.`,
     },
     lockedAccount: {
@@ -552,7 +639,7 @@ const translations: TranslationDeepObject<typeof en> = {
         chooseDocument: 'Escolher arquivo',
         attachmentTooLarge: 'O anexo é grande demais',
         sizeExceeded: 'O tamanho do anexo é maior que o limite de 24 MB',
-        sizeExceededWithLimit: (maxUploadSizeInMB: number) => `O tamanho do anexo é maior que o limite de ${maxUploadSizeInMB} MB`,
+        sizeExceededWithLimit: ({maxUploadSizeInMB}: SizeExceededParams) => `O tamanho do anexo é maior que o limite de ${maxUploadSizeInMB} MB`,
         attachmentTooSmall: 'O anexo é muito pequeno',
         sizeNotMet: 'O tamanho do anexo deve ser maior que 240 bytes',
         wrongFileType: 'Tipo de arquivo inválido',
@@ -563,9 +650,9 @@ const translations: TranslationDeepObject<typeof en> = {
         attachmentImageTooLarge: 'Esta imagem é grande demais para ser visualizada antes do envio.',
         imageDimensionsTooLarge: 'As dimensões da imagem são muito grandes para processar. Por favor, use uma imagem menor.',
         tooManyFiles: (fileLimit: number) => `Você só pode enviar até ${fileLimit} arquivos por vez.`,
-        sizeExceededWithValue: (maxUploadSizeInMB: number) => `Os arquivos excedem ${maxUploadSizeInMB} MB. Tente novamente.`,
+        sizeExceededWithValue: ({maxUploadSizeInMB}: SizeExceededParams) => `Os arquivos excedem ${maxUploadSizeInMB} MB. Tente novamente.`,
         someFilesCantBeUploaded: 'Alguns arquivos não podem ser enviados',
-        sizeLimitExceeded: (maxUploadSizeInMB: number) => `Os arquivos devem ter menos de ${maxUploadSizeInMB} MB. Qualquer arquivo maior não será enviado.`,
+        sizeLimitExceeded: ({maxUploadSizeInMB}: SizeExceededParams) => `Os arquivos devem ter menos de ${maxUploadSizeInMB} MB. Qualquer arquivo maior não será enviado.`,
         maxFileLimitExceeded: 'Você pode enviar até 30 recibos por vez. Quaisquer extras não serão enviados.',
         unsupportedFileType: (fileType: string) => `Arquivos ${fileType} não são compatíveis. Somente tipos de arquivo compatíveis serão enviados.`,
         learnMoreAboutSupportedFiles: 'Saiba mais sobre os formatos compatíveis.',
@@ -605,55 +692,17 @@ const translations: TranslationDeepObject<typeof en> = {
         signIn: 'Faça login novamente.',
     },
     multifactorAuthentication: {
-        reviewTransaction: {
-            reviewTransaction: 'Analisar transação',
-            pleaseReview: 'Revise esta transação',
-            requiresYourReview: 'Uma transação com o Cartão Expensify requer sua revisão abaixo.',
-            transactionDetails: 'Detalhes da transação',
-            deny: 'Negar',
-            approve: 'Aprovar',
-            denyTransaction: 'Negar transação',
-            transactionDenied: 'Transação negada',
-            transactionApproved: 'Transação aprovada!',
-            areYouSureToDeny: 'Tem certeza? A transação será recusada se você fechar esta tela.',
-            youCanTryAgainAtMerchantOrReachOut:
-                'Você pode tentar novamente no estabelecimento. Se você não fez esta transação, <concierge-link>entre em contato com a Concierge</concierge-link> para relatar possível fraude.',
-            youNeedToTryAgainAtMerchant: 'Essa transação não foi verificada, então nós a negamos. Você precisará tentar novamente no estabelecimento.',
-            goBackToTheMerchant: 'Volte ao site do estabelecimento para continuar a transação.',
-            attemptedTransaction: 'Transação tentada',
-            transactionFailed: 'Transação falhou',
-            transactionCouldNotBeCompleted: 'Não foi possível concluir sua transação. Tente novamente no estabelecimento.',
-            transactionCouldNotBeCompletedReachOut:
-                'Sua transação não pôde ser concluída. Se você não tentou fazer essa transação, <concierge-link>entre em contato com o Concierge</concierge-link> para relatar possível fraude.',
-            reviewFailed: 'Falha na análise',
-            alreadyReviewedSubtitle:
-                'Você já revisou esta transação. Verifique seu <transaction-history-link>histórico de transações</transaction-history-link> ou entre em contato com o <concierge-link>Concierge</concierge-link> para relatar qualquer problema.',
-        },
         biometricsTest: {
             biometricsTest: 'Teste de biometria',
             authenticationSuccessful: 'Autenticação bem-sucedida',
-            successfullyAuthenticatedUsing: (authType?: string) => `Você se autenticou com sucesso usando ${authType}.`,
-            troubleshootBiometricsStatus: ({status}: {status?: string}) => `Biometria (${status})`,
+            successfullyAuthenticatedUsing: ({authType}: MultifactorAuthenticationTranslationParams) => `Você se autenticou com sucesso usando ${authType}.`,
+            troubleshootBiometricsStatus: ({registered}: MultifactorAuthenticationTranslationParams) => `Biometria (${registered ? 'Registrado' : 'Não registrado'})`,
             yourAttemptWasUnsuccessful: 'Sua tentativa de autenticação não foi bem-sucedida.',
             youCouldNotBeAuthenticated: 'Não foi possível autenticar você',
             areYouSureToReject: 'Tem certeza? A tentativa de autenticação será rejeitada se você fechar esta tela.',
             rejectAuthentication: 'Rejeitar autenticação',
             test: 'Teste',
             biometricsAuthentication: 'Autenticação biométrica',
-            authType: {
-                unknown: 'Desconhecido',
-                none: 'Nenhum',
-                credentials: 'Credenciais',
-                biometrics: 'Biometria',
-                faceId: 'Face ID',
-                touchId: 'Touch ID',
-                opticId: 'Optic ID',
-                passkey: 'Passkey',
-            },
-            statusNeverRegistered: 'Nunca registrado',
-            statusNotRegistered: 'Não registrado',
-            statusRegisteredThisDevice: 'Registrado',
-            statusRegisteredOtherDevice: () => ({one: 'Outro dispositivo registrado', other: 'Outros dispositivos registrados'}),
         },
         pleaseEnableInSystemSettings: {
             start: 'Ative a verificação por rosto/digital ou defina um código de acesso do dispositivo no seu',
@@ -666,42 +715,27 @@ const translations: TranslationDeepObject<typeof en> = {
         letsVerifyItsYou: 'Vamos verificar se é você',
         nowLetsAuthenticateYou: 'Agora, vamos autenticar você...',
         letsAuthenticateYou: 'Vamos autenticar você...',
-        verifyYourself: {biometrics: 'Verifique sua identidade com seu rosto ou impressão digital', passkeys: 'Verifique sua identidade com uma chave de acesso'},
+        verifyYourself: {
+            biometrics: 'Verifique sua identidade com seu rosto ou impressão digital',
+        },
         enableQuickVerification: {
             biometrics: 'Ative uma verificação rápida e segura usando seu rosto ou impressão digital. Nenhuma senha ou código é necessário.',
-            passkeys: 'Ative uma verificação rápida e segura usando uma chave de acesso. Nenhuma senha ou código é necessário.',
         },
         revoke: {
-            title: 'Reconhecimento facial/digital e passkeys',
+            remove: 'Remover',
+            title: 'Face/digital & passkeys',
             explanation:
-                'A verificação por rosto/digital ou chave de acesso está ativada em um ou mais dispositivos. Revogar o acesso exigirá um código mágico na próxima verificação nesse dispositivo.',
-            confirmationPrompt: 'Tem certeza? Você vai precisar de um código mágico para a próxima verificação nesse dispositivo.',
+                'A verificação por rosto/digital ou por chave de acesso está ativada em um ou mais dispositivos. Revogar o acesso exigirá um código mágico para a próxima verificação em qualquer dispositivo.',
+            confirmationPrompt: 'Tem certeza? Você vai precisar de um código mágico para a próxima verificação em qualquer dispositivo.',
             cta: 'Revogar acesso',
-            noDevices: 'Você não tem nenhum dispositivo registrado para verificação por rosto/digital ou passkey. Se registrar algum, você poderá revogar esse acesso aqui.',
+            noDevices: 'Você não tem nenhum dispositivo registrado para verificação por rosto/digital ou passkey. Se você registrar algum, poderá revogar esse acesso aqui.',
             dismiss: 'Entendi',
             error: 'Falha na solicitação. Tente novamente mais tarde.',
-            revoke: 'Revogar',
-            confirmationPromptAll: 'Tem certeza? Você vai precisar de um código mágico para a próxima verificação em qualquer dispositivo.',
-            ctaAll: 'Revogar tudo',
-            thisDevice: 'Este dispositivo',
-            otherDevices: (otherDeviceCount?: number) => {
-                const numberWords = ['Um', 'Dois', 'Três', 'Quatro', 'Cinco', 'Seis', 'Sete', 'Oito', 'Nove'];
-                const displayCount = otherDeviceCount !== undefined && otherDeviceCount >= 1 && otherDeviceCount <= 9 ? numberWords.at(otherDeviceCount - 1) : `${otherDeviceCount}`;
-                return `${displayCount} outro(a) ${otherDeviceCount === 1 ? 'dispositivo' : 'dispositivos'}`;
-            },
-            confirmationPromptThisDevice: 'Tem certeza? Você vai precisar de um código mágico para a próxima verificação neste dispositivo.',
-            confirmationPromptMultiple: 'Você tem certeza? Você vai precisar de um código mágico para a próxima verificação nesses dispositivos.',
         },
         unsupportedDevice: {
             unsupportedDevice: 'Dispositivo não compatível',
-            pleaseDownloadMobileApp: `Esta ação não é compatível com seu dispositivo. Baixe o app do Expensify na <a href="${CONST.APP_DOWNLOAD_LINKS.IOS}">App Store</a> ou na <a href="${CONST.APP_DOWNLOAD_LINKS.ANDROID}">Google Play Store</a> e tente novamente.`,
-            pleaseUseWebApp: `Esta ação não é compatível com seu dispositivo. Use o <a href="${CONST.NEW_EXPENSIFY_URL}">aplicativo web do Expensify</a> e tente novamente.`,
+            pleaseDownloadMobileApp: `<centered-text><muted-text> Esta ação não é compatível com seu dispositivo. Baixe o app do Expensify na <a href="${CONST.APP_DOWNLOAD_LINKS.IOS}">App Store</a> ou na <a href="${CONST.APP_DOWNLOAD_LINKS.ANDROID}">Google Play Store</a> e tente novamente.</muted-text></centered-text>`,
         },
-        verificationFailed: 'Falha na verificação',
-        setPin: {didNotShipCard: 'Não enviamos seu cartão. Tente novamente.'},
-        revealPin: {couldNotReveal: 'Não foi possível revelar seu PIN. Tente novamente.'},
-        changePin: {didNotChange: 'Nós não alteramos seu PIN. Tente novamente.'},
-        revealCardDetail: {couldNotReveal: 'Não foi possível exibir os detalhes do seu cartão. Tente novamente.'},
     },
     validateCodeModal: {
         successfulSignInTitle: dedent(`
@@ -741,7 +775,11 @@ const translations: TranslationDeepObject<typeof en> = {
         nameEmailOrPhoneNumber: 'Nome, e-mail ou número de telefone',
         findMember: 'Encontrar membro',
         searchForSomeone: 'Buscar alguém',
-        userSelected: (username: string) => `${username} selecionado`,
+    },
+    customApprovalWorkflow: {
+        title: 'Fluxo de aprovação personalizado',
+        description: 'Sua empresa tem um fluxo de aprovação personalizado neste workspace. Faça essa ação no Expensify Classic',
+        goToExpensifyClassic: 'Mudar para o Expensify Clássico',
     },
     emptyList: {
         [CONST.IOU.TYPE.CREATE]: {
@@ -763,8 +801,8 @@ const translations: TranslationDeepObject<typeof en> = {
         phrase2: 'Dinheiro fala mais alto. E agora que chat e pagamentos estão no mesmo lugar, também ficou fácil.',
         phrase3: 'Seus pagamentos chegam tão rápido quanto você consegue transmitir seu ponto.',
         enterPassword: 'Insira sua senha',
-        welcomeNewFace: (login: string) => `${login}, é sempre ótimo ver um novo rosto por aqui!`,
-        welcomeEnterMagicCode: (login: string) => `Insira o código mágico enviado para ${login}. Ele deve chegar em um ou dois minutos.`,
+        welcomeNewFace: ({login}: SignUpNewFaceCodeParams) => `${login}, é sempre ótimo ver um novo rosto por aqui!`,
+        welcomeEnterMagicCode: ({login}: WelcomeEnterMagicCodeParams) => `Insira o código mágico enviado para ${login}. Ele deve chegar em um ou dois minutos.`,
     },
     login: {
         hero: {
@@ -792,9 +830,6 @@ const translations: TranslationDeepObject<typeof en> = {
         emoji: 'Emoji',
         collapse: 'Recolher',
         expand: 'Expandir',
-        askConciergeToUpdate: 'Tente "Atualizar uma despesa"...',
-        askConciergeToCorrect: 'Tente "Corrigir uma despesa"...',
-        askConciergeForHelp: 'Peça ajuda à Concierge AI...',
     },
     reportActionContextMenu: {
         copyMessage: 'Copiar mensagem',
@@ -858,9 +893,9 @@ const translations: TranslationDeepObject<typeof en> = {
         askMeAnything: 'Pergunte-me qualquer coisa!',
         sayHello: 'Diga olá!',
         yourSpace: 'Seu espaço',
-        welcomeToRoom: (roomName: string) => `Bem-vindo(a) a ${roomName}!`,
-        usePlusButton: (additionalText: string) => `Use o botão + para ${additionalText} uma despesa.`,
-        askConcierge: 'O Concierge pode responder perguntas, atualizar despesas e muito mais.',
+        welcomeToRoom: ({roomName}: WelcomeToRoomParams) => `Bem-vindo(a) a ${roomName}!`,
+        usePlusButton: ({additionalText}: UsePlusButtonParams) => `Use o botão + para ${additionalText} uma despesa.`,
+        askConcierge: 'Pergunte-me qualquer coisa!',
         conciergeSupport: 'Seu agente de IA pessoal',
         create: 'criar',
         iouTypes: {
@@ -872,17 +907,12 @@ const translations: TranslationDeepObject<typeof en> = {
         },
     },
     adminOnlyCanPost: 'Apenas administradores podem enviar mensagens nesta sala.',
-    readOnlyConversation: 'Esta conversa é somente leitura.',
     reportAction: {
         asCopilot: 'como copiloto de',
-        assistedBy: (agentName: string) => `assistido por ${agentName}`,
-        humanSupportAgent: 'um agente de suporte humano',
         harvestCreatedExpenseReport: (reportUrl: string, reportName: string) =>
             `criou este relatório para manter todas as despesas de <a href="${reportUrl}">${reportName}</a> que não puderam ser enviadas na frequência escolhida por você`,
-        createdReportForUnapprovedTransactions: (reportUrl: string, reportName: string, reportID: string, isReportDeleted: boolean) =>
-            isReportDeleted
-                ? `criou este relatório para quaisquer despesas retidas do relatório excluído nº ${reportID}`
-                : `criou este relatório para quaisquer despesas retidas de <a href="${reportUrl}">${reportName}</a>`,
+        createdReportForUnapprovedTransactions: ({reportUrl, reportName}: CreatedReportForUnapprovedTransactionsParams) =>
+            `criou este relatório para quaisquer despesas em espera de <a href="${reportUrl}">${reportName}</a>`,
     },
     mentionSuggestions: {
         hereAlternateText: 'Notificar todas as pessoas nesta conversa',
@@ -921,6 +951,7 @@ const translations: TranslationDeepObject<typeof en> = {
         buttonFind: 'Encontre algo...',
         buttonMySettings: 'Minhas configurações',
         fabNewChat: 'Iniciar chat',
+        fabNewChatExplained: 'Abrir menu de ações',
         fabScanReceiptExplained: 'Digitalizar recibo',
         chatPinned: 'Conversa fixada',
         draftedMessage: 'Mensagem em rascunho',
@@ -928,44 +959,40 @@ const translations: TranslationDeepObject<typeof en> = {
         listOfChats: 'Lista de chats',
         saveTheWorld: 'Salvar o mundo',
         tooltip: 'Comece aqui!',
+        redirectToExpensifyClassicModal: {
+            title: 'Em breve',
+            description: 'Estamos ajustando mais alguns detalhes do New Expensify para acomodar sua configuração específica. Enquanto isso, vá para o Expensify Classic.',
+        },
     },
     homePage: {
         forYou: 'Para você',
         timeSensitiveSection: {
             title: 'Urgente',
-            addShippingAddress: {title: 'Precisamos do seu endereço de entrega', subtitle: 'Informe um endereço para receber seu Cartão Expensify.', cta: 'Adicionar endereço'},
-            addPaymentCard: {title: 'Adicione um cartão de pagamento para continuar usando o Expensify', subtitle: 'Conta > Assinatura', cta: 'Adicionar'},
-            activateCard: {title: 'Ative seu Cartão Expensify', subtitle: 'Valide seu cartão e comece a gastar.', cta: 'Ativar'},
-            reviewCardFraud: {
-                title: 'Analisar possível fraude no seu Cartão Expensify',
-                titleWithDetails: ({amount, merchant}: {amount: string; merchant: string}) => `Analisar ${amount} em possível fraude em ${merchant}`,
-                subtitle: 'Cartão Expensify',
-                cta: 'Revisar',
+            cta: 'Solicitação',
+            offer50off: {
+                title: 'Ganhe 50% de desconto no seu primeiro ano!',
+                subtitle: ({formattedTime}: {formattedTime: string}) => `${formattedTime} restante`,
             },
-            ctaFix: 'Corrigir',
-            fixCompanyCardConnection: {
-                title: ({feedName}: {feedName: string}) => (feedName ? `Corrigir conexão do cartão corporativo ${feedName}` : 'Corrigir conexão do cartão corporativo'),
-                defaultSubtitle: 'Espaço de trabalho',
-                subtitle: ({policyName}: {policyName: string}) => `${policyName} > Cartões corporativos`,
+            offer25off: {
+                title: 'Ganhe 25% de desconto no seu primeiro ano!',
+                subtitle: ({days}: {days: number}) => `Restam ${days} ${days === 1 ? 'dia' : 'dias'}`,
             },
-            fixPolicyConnection: {
-                title: ({integrationName}: {integrationName: string}) => `Corrigir conexão com ${integrationName}`,
-                defaultSubtitle: 'Espaço de trabalho',
-                subtitle: ({policyName}: {policyName: string}) => `${policyName} > Contabilidade`,
+            addShippingAddress: {
+                title: 'Precisamos do seu endereço de entrega',
+                subtitle: 'Informe um endereço para receber seu Cartão Expensify.',
+                cta: 'Adicionar endereço',
             },
-            fixPersonalCardConnection: {
-                title: ({cardName}: {cardName?: string}) => (cardName ? `Corrigir conexão do cartão pessoal ${cardName}` : 'Corrigir conexão do cartão pessoal'),
-                subtitle: 'Carteira',
+            activateCard: {
+                title: 'Ative seu Cartão Expensify',
+                subtitle: 'Valide seu cartão e comece a gastar.',
+                cta: 'Ativar',
             },
-            validateAccount: {title: 'Valide sua conta', subtitle: 'Conta', cta: 'Validar'},
-            fixFailedBilling: {title: 'Não foi possível cobrar o cartão cadastrado', subtitle: 'Assinatura'},
-            unlockBankAccount: {
-                workspaceTitle: 'Sua conta bancária comercial foi bloqueada',
-                personalTitle: 'Sua conta bancária foi bloqueada',
-                workspaceSubtitle: ({policyName}: {policyName: string}) => policyName,
-                personalSubtitle: 'Carteira',
+            ctaFix: 'Corrigir',
+            fixCompanyCardConnection: {
+                title: ({feedName}: {feedName: string}) => (feedName ? `Corrigir conexão do cartão corporativo ${feedName}` : 'Corrigir conexão do cartão corporativo'),
+                subtitle: 'Área de trabalho > Cartões corporativos',
             },
-            enterSignerInfo: {title: 'Informações do signatário necessárias', subtitle: ({bankAccountLastFour}: {bankAccountLastFour: string}) => `Conta bancária ${bankAccountLastFour}`},
+            fixAccountingConnection: {title: ({integrationName}: {integrationName: string}) => `Corrigir conexão com ${integrationName}`, subtitle: 'Espaço de trabalho > Contabilidade'},
         },
         announcements: 'Comunicados',
         discoverSection: {
@@ -981,78 +1008,12 @@ const translations: TranslationDeepObject<typeof en> = {
             export: ({count}: {count: number}) => `Exportar ${count} ${count === 1 ? 'relatório' : 'relatórios'}`,
             begin: 'Iniciar',
             emptyStateMessages: {
-                thumbsUpStarsTitle: 'Você terminou!',
-                thumbsUpStarsDescription: 'Parabéns para você, fique atento a mais tarefas.',
-                smallRocketTitle: 'Tudo em dia',
-                smallRocketDescription: 'As próximas tarefas pendentes serão exibidas aqui.',
-                cowboyHatTitle: 'Você terminou!',
-                cowboyHatDescription: 'Todas as tarefas estão controladas, fique de olho nas próximas.',
-                trophy1Title: 'Nada para mostrar',
-                trophy1Description: 'Você conseguiu! Fique de olho nas próximas tarefas.',
-                palmTreeTitle: 'Tudo em dia',
-                palmTreeDescription: 'Hora de relaxar, mas fique atento a futuras tarefas.',
-                fishbowlBlueTitle: 'Você terminou!',
-                fishbowlBlueDescription: 'As futuras tarefas aparecerão aqui.',
-                targetTitle: 'Tudo em dia',
-                targetDescription: 'Boa, você está mantendo o foco. Volte para mais tarefas!',
-                chairTitle: 'Nada para mostrar',
-                chairDescription: 'Vá relaxar, listaremos as próximas tarefas aqui.',
-                broomTitle: 'Você terminou!',
-                broomDescription: 'As tarefas estão em dia, mas fique atento a mais tarefas.',
-                houseTitle: 'Tudo em dia',
-                houseDescription: 'Esta é sua base para as próximas tarefas.',
-                conciergeBotTitle: 'Nada para mostrar',
-                conciergeBotDescription: 'Bi bi bi bi, volte para mais tarefas!',
-                checkboxTextTitle: 'Tudo em dia',
-                checkboxTextDescription: 'Marque aqui suas próximas tarefas pendentes.',
-                flashTitle: 'Você terminou!',
-                flashDescription: 'Suas futuras tarefas aparecerão aqui.',
-                sunglassesTitle: 'Nada para mostrar',
-                sunglassesDescription: 'Hora de relaxar, mas fique atento ao que vem por aí!',
-                f1FlagsTitle: 'Tudo em dia',
-                f1FlagsDescription: 'Você concluiu todas as tarefas pendentes.',
-            },
-        },
-        upcomingTravel: 'Próximas viagens',
-        upcomingTravelSection: {
-            flightTo: ({destination}: {destination: string}) => `Voo para ${destination}`,
-            trainTo: ({destination}: {destination: string}) => `Trem para ${destination}`,
-            hotelIn: ({destination}: {destination: string}) => `Hotel em ${destination}`,
-            carRentalIn: ({destination}: {destination: string}) => `Aluguel de carro em ${destination}`,
-            inOneWeek: 'Em 1 semana',
-            inDays: () => ({one: 'Em 1 dia', other: (count: number) => `Em ${count} dias`}),
-            today: 'Hoje',
-        },
-        freeTrialSection: {
-            title: ({days}: {days: number}) => `Avaliação gratuita: restam ${days} ${days === 1 ? 'dia' : 'dias'}!`,
-            offer50Body: 'Ganhe 50% de desconto no seu primeiro ano',
-            offer25Body: 'Ganhe 25% de desconto no seu primeiro ano',
-            addCardBody: 'Adicionar um cartão de pagamento',
-            ctaClaim: 'Solicitação',
-            ctaAdd: 'Adicionar cartão',
-            timeRemaining: ({formattedTime}: {formattedTime: string}) => `Tempo restante: ${formattedTime}`,
-            timeRemainingDays: () => ({
-                one: 'Tempo restante: 1 dia',
-                other: (pluralCount: number) => `Tempo restante: ${pluralCount} dias`,
-            }),
-        },
-        gettingStartedSection: {
-            title: 'Introdução',
-            createWorkspace: 'Criar um workspace',
-            connectAccounting: ({integrationName}: {integrationName: string}) => `Conectar ao ${integrationName}`,
-            connectAccountingDefault: 'Conectar à contabilidade',
-            customizeCategories: 'Personalizar categorias contábeis',
-            linkCompanyCards: 'Vincular cartões corporativos',
-            setupRules: 'Configurar regras de gasto',
-            inviteAccountant: 'Convide seu contador',
-        },
-        yourSpend: {
-            title: 'Seus gastos',
-            awaitingApproval: 'Aguardando aprovação',
-            repaidLast30Days: 'Reembolsado nos últimos 30 dias',
-            recentTransactions: ({lastFour}: {lastFour: string}) => `Transações recentes • ${lastFour}`,
+                nicelyDone: 'Muito bem feito',
+                keepAnEyeOut: 'Fique de olho no que vem por aí!',
+                allCaughtUp: 'Você está em dia',
+                upcomingTodos: 'Os próximos afazeres aparecerão aqui.',
+            },
         },
-        seeMore: ({count}: {count: number}) => `Ver mais ${count}`,
     },
     allSettingsScreen: {
         subscription: 'Assinatura',
@@ -1081,20 +1042,7 @@ const translations: TranslationDeepObject<typeof en> = {
         singleFieldMultipleColumns: (fieldName: string) => `Ops! Você mapeou um único campo ("${fieldName}") para várias colunas. Revise e tente novamente.`,
         emptyMappedField: (fieldName: string) => `Ops! O campo ("${fieldName}") contém um ou mais valores vazios. Revise e tente novamente.`,
         importSuccessfulTitle: 'Importação concluída',
-        importCategoriesSuccessfulDescription: ({added, updated}: {added: number; updated: number}) => {
-            if (!added && !updated) {
-                return 'Nenhuma categoria foi adicionada ou atualizada.';
-            }
-            if (added && updated) {
-                return `${added} ${added === 1 ? 'categoria' : 'categorias'} adicionada${added === 1 ? '' : 's'}, ${updated} ${updated === 1 ? 'categoria' : 'categorias'} atualizada${updated === 1 ? '' : 's'}.`;
-            }
-            if (added) {
-                return added === 1 ? '1 categoria foi adicionada.' : `${added} categorias foram adicionadas.`;
-            }
-            return updated === 1 ? '1 categoria foi atualizada.' : `${updated} categorias foram atualizadas.`;
-        },
-        importCompanyCardTransactionsSuccessfulDescription: ({transactions}: {transactions: number}) =>
-            transactions > 1 ? `${transactions} transações foram adicionadas.` : '1 transação foi adicionada.',
+        importCategoriesSuccessfulDescription: ({categories}: {categories: number}) => (categories > 1 ? `${categories} categorias foram adicionadas.` : '1 categoria foi adicionada.'),
         importMembersSuccessfulDescription: ({added, updated}: {added: number; updated: number}) => {
             if (!added && !updated) {
                 return 'Nenhum membro foi adicionado ou atualizado.';
@@ -1126,7 +1074,6 @@ const translations: TranslationDeepObject<typeof en> = {
             other: (count: number) =>
                 `Confirme os detalhes abaixo para os ${count} novos membros do workspace que serão adicionados como parte deste upload. Membros existentes não receberão nenhuma atualização de função nem mensagens de convite.`,
         }),
-        importCompanyCardTransactionsPendingMessage: 'Novos cartões e transações podem levar algum tempo para aparecer, aguarde um momento.',
     },
     receipt: {
         upload: 'Carregar recibo',
@@ -1158,9 +1105,7 @@ const translations: TranslationDeepObject<typeof en> = {
         deleteReceipt: 'Excluir recibo',
         deleteConfirmation: 'Tem certeza de que deseja excluir este recibo?',
         addReceipt: 'Adicionar recibo',
-        addAdditionalReceipt: 'Adicionar recibo adicional',
         scanFailed: 'O recibo não pôde ser digitalizado porque está faltando o comerciante, a data ou o valor.',
-        crop: 'Cortar',
         addAReceipt: {
             phrase1: 'Adicionar um recibo',
             phrase2: 'ou arraste e solte um aqui',
@@ -1180,7 +1125,6 @@ const translations: TranslationDeepObject<typeof en> = {
         noLongerHaveReportAccess: 'Você não tem mais acesso ao seu destino anterior de ação rápida. Escolha um novo abaixo.',
         updateDestination: 'Atualizar destino',
         createReport: 'Criar relatório',
-        createTimeExpense: 'Criar despesa de tempo',
     },
     iou: {
         amount: 'Valor',
@@ -1200,18 +1144,18 @@ const translations: TranslationDeepObject<typeof en> = {
         split: 'Dividir',
         splitExpense: 'Dividir despesa',
         splitDates: 'Dividir datas',
-        splitDateRange: (startDate: string, endDate: string, count: number) => `${startDate} a ${endDate} (${count} dias)`,
-        splitExpenseSubtitle: (amount: string, merchant: string) => `${amount} de ${merchant}`,
+        splitDateRange: ({startDate, endDate, count}: SplitDateRangeParams) => `${startDate} a ${endDate} (${count} dias)`,
+        splitExpenseSubtitle: ({amount, merchant}: SplitExpenseSubtitleParams) => `${amount} de ${merchant}`,
         splitByPercentage: 'Dividir por porcentagem',
         splitByDate: 'Dividir por data',
         addSplit: 'Adicionar divisão',
         makeSplitsEven: 'Dividir igualmente',
         editSplits: 'Editar divisões',
-        totalAmountGreaterThanOriginal: (amount: string) => `O valor total é ${amount} maior do que a despesa original.`,
-        totalAmountLessThanOriginal: (amount: string) => `O valor total é ${amount} menor que a despesa original.`,
+        totalAmountGreaterThanOriginal: ({amount}: TotalAmountGreaterOrLessThanOriginalParams) => `O valor total é ${amount} maior do que a despesa original.`,
+        totalAmountLessThanOriginal: ({amount}: TotalAmountGreaterOrLessThanOriginalParams) => `O valor total é ${amount} menor que a despesa original.`,
         splitExpenseZeroAmount: 'Insira um valor válido antes de continuar.',
         splitExpenseOneMoreSplit: 'Nenhuma divisão adicionada. Adicione pelo menos uma para salvar.',
-        splitExpenseEditTitle: (amount: string, merchant: string) => `Editar ${amount} para ${merchant}`,
+        splitExpenseEditTitle: ({amount, merchant}: SplitExpenseEditTitleParams) => `Editar ${amount} para ${merchant}`,
         removeSplit: 'Remover divisão',
         splitExpenseCannotBeEditedModalTitle: 'Esta despesa não pode ser editada',
         splitExpenseCannotBeEditedModalDescription: 'Despesas aprovadas ou pagas não podem ser editadas',
@@ -1242,12 +1186,9 @@ const translations: TranslationDeepObject<typeof en> = {
         deleteReceipt: 'Excluir recibo',
         findExpense: 'Encontrar despesa',
         deletedTransaction: (amount: string, merchant: string) => `excluiu uma despesa (${amount} em ${merchant})`,
-        movedFromReport: (reportName: string) => `moveu uma despesa de ${reportName}`,
-        movedFromReportNoName: 'moveu uma despesa',
-        movedTransactionTo: (reportUrl: string, reportName: string) => `moveu esta despesa para <a href="${reportUrl}">${reportName}</a>`,
-        movedTransactionToAnotherReport: 'moveu esta despesa para outro relatório',
-        movedTransactionFrom: (reportUrl: string, reportName: string) => `moveu esta despesa de <a href="${reportUrl}">${reportName}</a>`,
-        movedTransactionFromAnotherReport: 'moveu esta despesa de outro relatório',
+        movedFromReport: (reportName: string) => `moveu uma despesa${reportName ? `de ${reportName}` : ''}`,
+        movedTransactionTo: (reportUrl: string, reportName?: string) => `moveu esta despesa${reportName ? `para <a href="${reportUrl}">${reportName}</a>` : ''}`,
+        movedTransactionFrom: (reportUrl: string, reportName?: string) => `moveu esta despesa${reportName ? `de <a href="${reportUrl}">${reportName}</a>` : ''}`,
         unreportedTransaction: (reportUrl: string) => `moveu esta despesa para o seu <a href="${reportUrl}">espaço pessoal</a>`,
         movedAction: (shouldHideMovedReportUrl: boolean, movedReportUrl: string, newParentReportUrl: string, toPolicyName: string) => {
             if (shouldHideMovedReportUrl) {
@@ -1259,10 +1200,7 @@ const translations: TranslationDeepObject<typeof en> = {
         pendingMatch: 'Correspondência pendente',
         pendingMatchWithCreditCardDescription: 'Recibo aguardando correspondência com transação do cartão. Marque como dinheiro para cancelar.',
         markAsCash: 'Marcar como dinheiro',
-        pendingMatchSubmitTitle: 'Enviar relatório',
-        pendingMatchSubmitDescription: 'Algumas despesas estão pendentes de correspondência com uma transação de cartão de crédito. Deseja marcá-las como dinheiro?',
         routePending: 'Rota pendente...',
-        automaticallyEnterExpenseDetails: 'O Concierge vai preencher os detalhes para você.',
         receiptScanning: () => ({
             one: 'Digitalizando recibo...',
             other: 'Escaneando recibos...',
@@ -1289,7 +1227,7 @@ const translations: TranslationDeepObject<typeof en> = {
         receiptStatusTitle: 'Escaneando…',
         receiptStatusText: 'Só você pode ver este recibo enquanto ele está sendo digitalizado. Volte mais tarde ou insira os detalhes agora.',
         receiptScanningFailed: 'Falha ao escanear o recibo. Insira os detalhes manualmente.',
-        allTransactionsPendingNextStep: 'Todas as transações estão pendentes. Você não pode enviar este relatório até que elas sejam lançadas em alguns dias.',
+        transactionPendingDescription: 'Transação pendente. Pode levar alguns dias para ser lançada.',
         companyInfo: 'Informações da empresa',
         companyInfoDescription: 'Precisamos de mais alguns detalhes antes que você possa enviar sua primeira fatura.',
         yourCompanyName: 'Nome da sua empresa',
@@ -1324,18 +1262,20 @@ const translations: TranslationDeepObject<typeof en> = {
         settledElsewhere: 'Pago em outro lugar',
         individual: 'Individual',
         business: 'Negócios',
-        settlePersonal: (formattedAmount?: string) => (formattedAmount ? `Pagar ${formattedAmount} como pessoa física` : `Pagar com conta pessoal`),
-        settleWallet: (formattedAmount?: string) => (formattedAmount ? `Pagar ${formattedAmount} com a carteira` : `Pagar com carteira`),
-        settlePayment: (formattedAmount: string) => `Pagar ${formattedAmount}`,
-        settleBusiness: (formattedAmount?: string) => (formattedAmount ? `Pagar ${formattedAmount} como empresa` : `Pagar com conta empresarial`),
-        payElsewhere: (formattedAmount?: string) => (formattedAmount ? `Marcar ${formattedAmount} como pago` : `Marcar como pago`),
-        confirmPaymentReceivedModalTitle: 'Confirmar recebimento do pagamento',
-        receivedPayment: 'Pagamento recebido',
-        receivedPaymentConfirmation: 'Prossiga apenas se você já tiver recebido o pagamento fora do Expensify.',
-        confirmReceivedPayment: 'Sim, recebi o pagamento.',
+        settleExpensify: ({formattedAmount}: SettleExpensifyCardParams) => (formattedAmount ? `Pagar ${formattedAmount} com o Expensify` : `Pagar com Expensify`),
+        settlePersonal: ({formattedAmount}: SettleExpensifyCardParams) => (formattedAmount ? `Pagar ${formattedAmount} como pessoa física` : `Pagar com conta pessoal`),
+        settleWallet: ({formattedAmount}: SettleExpensifyCardParams) => (formattedAmount ? `Pagar ${formattedAmount} com a carteira` : `Pagar com carteira`),
+        settlePayment: ({formattedAmount}: SettleExpensifyCardParams) => `Pagar ${formattedAmount}`,
+        settleBusiness: ({formattedAmount}: SettleExpensifyCardParams) => (formattedAmount ? `Pagar ${formattedAmount} como empresa` : `Pagar com conta empresarial`),
+        payElsewhere: ({formattedAmount}: SettleExpensifyCardParams) => (formattedAmount ? `Marcar ${formattedAmount} como pago` : `Marcar como pago`),
         settleInvoicePersonal: (amount?: string, last4Digits?: string) => (amount ? `pagou ${amount} com a conta pessoal ${last4Digits}` : `Pago com conta pessoal`),
         settleInvoiceBusiness: (amount?: string, last4Digits?: string) => (amount ? `pagou ${amount} com a conta empresarial ${last4Digits}` : `Pago com conta empresarial`),
-        payWithPolicy: (policyName: string, formattedAmount?: string) => (formattedAmount ? `Pagar ${formattedAmount} via ${policyName}` : `Pagar via ${policyName}`),
+        payWithPolicy: ({
+            formattedAmount,
+            policyName,
+        }: SettleExpensifyCardParams & {
+            policyName: string;
+        }) => (formattedAmount ? `Pagar ${formattedAmount} via ${policyName}` : `Pagar via ${policyName}`),
         businessBankAccount: (amount?: string, last4Digits?: string) => (amount ? `pagou ${amount} com a conta bancária ${last4Digits}` : `pago com conta bancária ${last4Digits}`),
         automaticallyPaidWithBusinessBankAccount: (amount?: string, last4Digits?: string) =>
             `pagou ${amount ? `${amount} ` : ''} com a conta bancária ${last4Digits} via <a href="${CONST.CONFIGURE_EXPENSE_REPORT_RULES_HELP_URL}">regras da workspace</a>`,
@@ -1344,16 +1284,16 @@ const translations: TranslationDeepObject<typeof en> = {
         nextStep: 'Próximas etapas',
         finished: 'Concluído',
         flip: 'Virar',
-        sendInvoice: (amount: string) => `Enviar fatura de ${amount}`,
+        sendInvoice: ({amount}: RequestAmountParams) => `Enviar fatura de ${amount}`,
         expenseAmount: (formattedAmount: string, comment?: string) => `${formattedAmount}${comment ? `para ${comment}` : ''}`,
-        submitted: (memo?: string) => `enviado${memo ? `, dizendo ${memo}` : ''}`,
+        submitted: ({memo}: SubmittedWithMemoParams) => `enviado${memo ? `, dizendo ${memo}` : ''}`,
         automaticallySubmitted: `enviado via <a href="${CONST.SELECT_WORKFLOWS_HELP_URL}">atrasar envios</a>`,
         queuedToSubmitViaDEW: 'na fila para enviar via fluxo de aprovação personalizado',
         queuedToApproveViaDEW: 'na fila para aprovar via fluxo de aprovação personalizado',
         trackedAmount: (formattedAmount: string, comment?: string) => `rastreamento de ${formattedAmount}${comment ? `para ${comment}` : ''}`,
-        splitAmount: (amount: string) => `dividir ${amount}`,
-        didSplitAmount: (formattedAmount: string, comment?: string) => `dividir ${formattedAmount}${comment ? `para ${comment}` : ''}`,
-        yourSplit: (amount: string) => `Sua parte ${amount}`,
+        splitAmount: ({amount}: SplitAmountParams) => `dividir ${amount}`,
+        didSplitAmount: (formattedAmount: string, comment: string) => `dividir ${formattedAmount}${comment ? `para ${comment}` : ''}`,
+        yourSplit: ({amount}: UserSplitParams) => `Sua parte ${amount}`,
         payerOwesAmount: (amount: number | string, payer: string, comment?: string) => `${payer} deve ${amount}${comment ? `para ${comment}` : ''}`,
         payerOwes: (payer: string) => `${payer} deve:`,
         payerPaidAmount: (amount: number | string, payer?: string) => `${payer ? `${payer} ` : ''}pagou ${amount}`,
@@ -1369,84 +1309,43 @@ const translations: TranslationDeepObject<typeof en> = {
         approvedMessage: `aprovado`,
         unapproved: `não aprovado`,
         automaticallyForwarded: `aprovado por meio das <a href="${CONST.CONFIGURE_EXPENSE_REPORT_RULES_HELP_URL}">regras do workspace</a>`,
-        forwarded: (memo?: string) => `aprovado${memo ? `, dizendo ${memo}` : ''}`,
-        rejectedThisReport: 'rejeitou',
-        waitingOnBankAccount: (submitterDisplayName: string) => `iniciou o pagamento, mas está aguardando ${submitterDisplayName} adicionar uma conta bancária.`,
+        forwarded: `aprovado`,
+        rejectedThisReport: 'rejeitou este relatório',
+        waitingOnBankAccount: ({submitterDisplayName}: WaitingOnBankAccountParams) => `iniciou o pagamento, mas está aguardando ${submitterDisplayName} adicionar uma conta bancária.`,
         adminCanceledRequest: 'cancelou o pagamento',
         canceledRequest: (amount: string, submitterDisplayName: string) => `cancelou o pagamento de ${amount} porque ${submitterDisplayName} não ativou a Carteira Expensify em 30 dias`,
-        settledAfterAddedBankAccount: (submitterDisplayName: string, amount: string) => `${submitterDisplayName} adicionou uma conta bancária. O pagamento de ${amount} foi efetuado.`,
+        settledAfterAddedBankAccount: ({submitterDisplayName, amount}: SettledAfterAddedBankAccountParams) =>
+            `${submitterDisplayName} adicionou uma conta bancária. O pagamento de ${amount} foi efetuado.`,
         paidElsewhere: ({payer, comment}: PaidElsewhereParams = {}) => `${payer ? `${payer} ` : ''}marcou como pago${comment ? `, dizendo "${comment}"` : ''}`,
         paidWithExpensify: (payer?: string) => `${payer ? `${payer} ` : ''}pago com carteira`,
         automaticallyPaidWithExpensify: (payer?: string) =>
             `${payer ? `${payer} ` : ''}pagos com Expensify via <a href="${CONST.CONFIGURE_EXPENSE_REPORT_RULES_HELP_URL}">regras do workspace</a>`,
-        reimbursedThisReport: 'reembolsou este relatório',
-        paidThisBill: 'pagou esta conta',
-        reimbursedOnBehalfOf: (actor: string) => `em nome de ${actor}`,
-        reimbursedFromBankAccount: (debitBankAccount: string) => `da conta bancária com final ${debitBankAccount}`,
-        reimbursedSubmitterAddedBankAccount: (submitter: string) => `${submitter} adicionou uma conta bancária, retirando o relatório da suspensão. O reembolso foi iniciado`,
-        reimbursedWithFastACH: ({
-            isCurrentUser,
-            submitterLogin,
-            creditBankAccount,
-            expectedDate,
-        }: {
-            isCurrentUser: boolean;
-            submitterLogin: string;
-            creditBankAccount: string;
-            expectedDate: string;
-        }) =>
-            isCurrentUser
-                ? `. O dinheiro está a caminho da sua ${creditBankAccount ? `conta bancária terminada em ${creditBankAccount}` : 'conta'}. Reembolso previsto para ser concluído em ${expectedDate}.`
-                : `. O dinheiro está a caminho da conta bancária de ${submitterLogin}${creditBankAccount ? ` terminada em ${creditBankAccount}` : ''}. Reembolso com conclusão estimada em ${expectedDate}.`,
-        reimbursedWithCheck: ' por cheque.',
-        reimbursedWithStripeConnect: ({
-            isCurrentUser,
-            submitterLogin,
-            creditBankAccount,
-            isCard,
-        }: {
-            isCurrentUser: boolean;
-            submitterLogin: string;
-            creditBankAccount: string;
-            isCard: boolean;
-        }) => {
-            const paymentMethod = isCard ? 'cartão' : 'conta bancária';
-            return isCurrentUser
-                ? `. O dinheiro está a caminho da sua ${creditBankAccount ? `conta bancária terminada em ${creditBankAccount}` : 'conta'} (pago via ${paymentMethod}). Isso pode levar até 10 dias úteis.`
-                : `. O dinheiro está a caminho da conta bancária de ${submitterLogin}${creditBankAccount ? ` terminada em ${creditBankAccount}` : ''} (pago via ${paymentMethod}). Isso pode levar até 10 dias úteis.`;
-        },
-        reimbursedWithACH: ({creditBankAccount, expectedDate}: {creditBankAccount?: string; expectedDate?: string}) =>
-            ` com depósito direto (ACH)${creditBankAccount ? ` para a conta bancária terminada em ${creditBankAccount}.` : '. '}${expectedDate ? `O reembolso está previsto para ser concluído até ${expectedDate}.` : 'Geralmente isso leva de 4 a 5 dias úteis.'}`,
         noReimbursableExpenses: 'Este relatório tem um valor inválido',
         pendingConversionMessage: 'O total será atualizado quando você voltar a ficar online',
         changedTheExpense: 'alterou a despesa',
-        setTheRequest: (valueName: string, newValueToDisplay: string) => `o(a) ${valueName} para ${newValueToDisplay}`,
-        setTheDistanceMerchant: (translatedChangedField: string, newMerchant: string, newAmountToDisplay: string) =>
+        setTheRequest: ({valueName, newValueToDisplay}: SetTheRequestParams) => `o(a) ${valueName} para ${newValueToDisplay}`,
+        setTheDistanceMerchant: ({translatedChangedField, newMerchant, newAmountToDisplay}: SetTheDistanceMerchantParams) =>
             `definiu ${translatedChangedField} como ${newMerchant}, o que definiu o valor como ${newAmountToDisplay}`,
         removedTheRequest: (valueName: string, oldValueToDisplay: string) => `o ${valueName} (antes ${oldValueToDisplay})`,
-        updatedTheRequest: (valueName: string, newValueToDisplay: string, oldValueToDisplay: string) => `o ${valueName} para ${newValueToDisplay} (antes ${oldValueToDisplay})`,
-        updatedTheDistanceMerchant: (translatedChangedField: string, newMerchant: string, oldMerchant: string, newAmountToDisplay: string, oldAmountToDisplay: string) =>
+        updatedTheRequest: ({valueName, newValueToDisplay, oldValueToDisplay}: UpdatedTheRequestParams) => `o ${valueName} para ${newValueToDisplay} (antes ${oldValueToDisplay})`,
+        updatedTheDistanceMerchant: ({translatedChangedField, newMerchant, oldMerchant, newAmountToDisplay, oldAmountToDisplay}: UpdatedTheDistanceMerchantParams) =>
             `alterou ${translatedChangedField} para ${newMerchant} (antes ${oldMerchant}), o que atualizou o valor para ${newAmountToDisplay} (antes ${oldAmountToDisplay})`,
         basedOnAI: 'com base na atividade anterior',
         basedOnMCC: ({rulesLink}: {rulesLink: string}) => (rulesLink ? `com base nas <a href="${rulesLink}">regras do workspace</a>` : 'com base na regra do workspace'),
-        threadExpenseReportName: (formattedAmount: string, comment?: string) => `${formattedAmount} ${comment ? `para ${comment}` : 'despesa'}`,
+        threadExpenseReportName: ({formattedAmount, comment}: ThreadRequestReportNameParams) => `${formattedAmount} ${comment ? `para ${comment}` : 'despesa'}`,
         invoiceReportName: ({linkedReportID}: OriginalMessage<typeof CONST.REPORT.ACTIONS.TYPE.REPORT_PREVIEW>) => `Relatório de fatura nº ${linkedReportID}`,
-        threadPaySomeoneReportName: (formattedAmount: string, comment?: string) => `${formattedAmount} enviado${comment ? `para ${comment}` : ''}`,
-        movedFromPersonalSpace: ({workspaceName, reportName}: MovedFromPersonalSpaceParams) => `moveu a despesa do espaço pessoal para ${workspaceName ?? `conversar com ${reportName}`}`,
+        threadPaySomeoneReportName: ({formattedAmount, comment}: ThreadSentMoneyReportNameParams) => `${formattedAmount} enviado${comment ? `para ${comment}` : ''}`,
+        movedFromPersonalSpace: ({workspaceName, reportName}: MovedFromPersonalSpaceParams) => `moveu despesa do espaço pessoal para ${workspaceName ?? `conversar com ${reportName}`}`,
         movedToPersonalSpace: 'moveu a despesa para o espaço pessoal',
         error: {
             invalidCategoryLength: 'O nome da categoria excede 255 caracteres. Reduza-o ou escolha uma categoria diferente.',
             invalidTagLength: 'O nome da tag excede 255 caracteres. Reduza-o ou escolha uma tag diferente.',
             invalidAmount: 'Insira um valor válido antes de continuar',
             invalidDistance: 'Insira uma distância válida antes de continuar',
-            invalidReadings: 'Insira as leituras de início e fim antes de continuar',
+            invalidReadings: 'Insira as leituras de início e fim',
             negativeDistanceNotAllowed: 'A leitura final deve ser maior que a leitura inicial',
-            distanceAmountTooLarge: 'O valor total é muito alto. Diminua a distância ou reduza a tarifa.',
-            distanceAmountTooLargeReduceDistance: 'O valor total é muito alto. Diminua a distância.',
-            distanceAmountTooLargeReduceRate: 'O valor total é muito alto. Reduza a tarifa.',
-            odometerReadingTooLarge: (formattedMax: string) => `As leituras do hodômetro não podem exceder ${formattedMax}.`,
             invalidIntegerAmount: 'Insira um valor inteiro em dólares antes de continuar',
-            invalidTaxAmount: (amount: string) => `O valor máximo de imposto é ${amount}`,
+            invalidTaxAmount: ({amount}: RequestAmountParams) => `O valor máximo de imposto é ${amount}`,
             invalidSplit: 'A soma das divisões deve ser igual ao valor total',
             invalidSplitParticipants: 'Insira um valor maior que zero para pelo menos dois participantes',
             invalidSplitYourself: 'Insira um valor diferente de zero para a sua divisão',
@@ -1459,8 +1358,6 @@ const translations: TranslationDeepObject<typeof en> = {
             receiptDeleteFailureError: 'Erro inesperado ao excluir este recibo. Tente novamente mais tarde.',
             receiptFailureMessage: '<rbr>Ocorreu um erro ao enviar seu recibo. Por favor, <a href="download">salve o recibo</a> e <a href="retry">tente novamente</a> mais tarde.</rbr>',
             receiptFailureMessageShort: 'Ocorreu um erro ao enviar seu recibo.',
-            receiptUploadFailedMessage: 'Falha no envio do recibo. Salve o recibo ou exclua a despesa e perca-a.',
-            saveReceipt: 'Salvar recibo',
             genericDeleteFailureMessage: 'Erro inesperado ao excluir esta despesa. Tente novamente mais tarde.',
             genericEditFailureMessage: 'Erro inesperado ao editar esta despesa. Tente novamente mais tarde.',
             genericSmartscanFailureMessage: 'A transação está com campos ausentes',
@@ -1477,14 +1374,11 @@ const translations: TranslationDeepObject<typeof en> = {
             endDateSameAsStartDate: 'A data de término não pode ser igual à data de início',
             manySplitsProvided: `O número máximo de divisões permitido é ${CONST.IOU.SPLITS_LIMIT}.`,
             dateRangeExceedsMaxDays: `O intervalo de datas não pode exceder ${CONST.IOU.SPLITS_LIMIT} dias.`,
-            unableToSubmitReport: 'Não foi possível enviar o relatório',
-            allTransactionsPendingDescription: 'Você não pode enviar este relatório porque todas as transações estão pendentes. Elas podem levar alguns dias para serem lançadas.',
-            stitchOdometerImagesFailed: 'Falha ao combinar imagens do hodômetro. Tente novamente mais tarde.',
-            failedToSaveOdometerDraft: 'Não foi possível salvar seu rascunho do hodômetro. Tente novamente.',
         },
         dismissReceiptError: 'Dispensar erro',
         dismissReceiptErrorConfirmation: 'Atenção! Ignorar este erro removerá completamente o comprovante que você enviou. Tem certeza?',
-        waitingOnEnabledWallet: (submitterDisplayName: string) => `começou a acertar as contas. O pagamento está em espera até ${submitterDisplayName} ativar a carteira.`,
+        waitingOnEnabledWallet: ({submitterDisplayName}: WaitingOnBankAccountParams) =>
+            `começou a acertar as contas. O pagamento está em espera até ${submitterDisplayName} ativar a carteira.`,
         enableWallet: 'Ativar carteira',
         hold: 'Reter',
         unhold: 'Remover bloqueio',
@@ -1496,20 +1390,16 @@ const translations: TranslationDeepObject<typeof en> = {
         heldExpense: 'reteve esta despesa',
         unheldExpense: 'removeu a retenção desta despesa',
         moveUnreportedExpense: 'Mover despesa não relatada',
-        addExistingExpense: 'Adicionar despesa existente',
-        selectExistingExpense: 'Selecione pelo menos uma despesa para adicionar ao relatório.',
-        emptyStateExistingExpenseTitle: 'Nenhuma despesa existente',
-        emptyStateExistingExpenseSubtitle: 'Parece que você não tem nenhuma despesa existente. Tente criar uma abaixo.',
-        addExistingExpenseConfirm: 'Adicionar ao relatório',
+        addUnreportedExpense: 'Adicionar despesa não relatada',
+        selectUnreportedExpense: 'Selecione pelo menos uma despesa para adicionar ao relatório.',
+        emptyStateUnreportedExpenseTitle: 'Nenhuma despesa não reportada',
+        emptyStateUnreportedExpenseSubtitle: 'Parece que você não tem nenhuma despesa não reportada. Tente criar uma abaixo.',
+        addUnreportedExpenseConfirm: 'Adicionar ao relatório',
         newReport: 'Novo relatório',
         explainHold: () => ({
             one: 'Explique por que você está retendo esta despesa.',
             other: 'Explique por que você está segurando essas despesas.',
         }),
-        explainHoldApprover: () => ({
-            one: 'Explique o que você precisa antes de aprovar esta despesa.',
-            other: 'Explique o que você precisa antes de aprovar estas despesas.',
-        }),
         retracted: 'retraído',
         retract: 'Retrair',
         reopened: 'reaberto',
@@ -1525,9 +1415,6 @@ const translations: TranslationDeepObject<typeof en> = {
         someDuplicatesArePaid: 'Alguns desses duplicados já foram aprovados ou pagos.',
         reviewDuplicates: 'Revisar duplicados',
         keepAll: 'Manter tudo',
-        keepSelected: 'Manter selecionados',
-        noDuplicatesTitle: 'Tudo pronto!',
-        noDuplicatesDescription: 'Não há transações duplicadas para revisar aqui.',
         confirmApprove: 'Confirmar valor da aprovação',
         confirmApprovalAmount: 'Aprove apenas as despesas em conformidade ou aprove o relatório inteiro.',
         confirmApprovalAllHoldAmount: () => ({
@@ -1561,7 +1448,7 @@ const translations: TranslationDeepObject<typeof en> = {
         unapprove: 'Reprovar',
         unapproveReport: 'Rejeitar relatório',
         headsUp: 'Atenção!',
-        unapproveWithIntegrationWarning: (accountingIntegration: string) =>
+        unapproveWithIntegrationWarning: ({accountingIntegration}: UnapproveWithIntegrationWarningParams) =>
             `Este relatório já foi exportado para ${accountingIntegration}. Alterá-lo pode causar discrepâncias nos dados. Tem certeza de que deseja cancelar a aprovação deste relatório?`,
         reimbursable: 'reembolsável',
         nonReimbursable: 'não reembolsável',
@@ -1570,7 +1457,6 @@ const translations: TranslationDeepObject<typeof en> = {
         bookingArchived: 'Esta reserva está arquivada',
         bookingArchivedDescription: 'Esta reserva está arquivada porque a data da viagem já passou. Adicione uma despesa com o valor final, se necessário.',
         attendees: 'Participantes',
-        totalPerAttendee: 'Por participante',
         whoIsYourAccountant: 'Quem é seu contador?',
         paymentComplete: 'Pagamento concluído',
         time: 'Hora',
@@ -1597,7 +1483,7 @@ const translations: TranslationDeepObject<typeof en> = {
         }),
         dates: 'Datas',
         rates: 'Taxas',
-        submitsTo: (name: string) => `Envia para ${name}`,
+        submitsTo: ({name}: SubmitsToParams) => `Envia para ${name}`,
         reject: {
             educationalTitle: 'Você deve manter ou rejeitar?',
             educationalText: 'Se você não estiver pronto para aprovar ou pagar uma despesa, você pode colocá-la em espera ou rejeitá-la.',
@@ -1606,7 +1492,7 @@ const translations: TranslationDeepObject<typeof en> = {
             heldExpenseLeftBehindTitle: 'Despesas retidas são deixadas para trás quando você aprova um relatório inteiro.',
             rejectExpenseTitle: 'Rejeite uma despesa que você não pretende aprovar ou pagar.',
             reasonPageTitle: 'Rejeitar despesa',
-            reasonPageDescription: 'Explique por que você não aprovará esta despesa.',
+            reasonPageDescription: 'Explique por que você está rejeitando esta despesa.',
             rejectReason: 'Motivo da rejeição',
             markAsResolved: 'Marcar como resolvido',
             rejectedStatus: 'Esta despesa foi rejeitada. Estamos aguardando você corrigir os problemas e marcá-la como resolvida para permitir o envio.',
@@ -1615,26 +1501,13 @@ const translations: TranslationDeepObject<typeof en> = {
                 markedAsResolved: 'marcou o motivo da rejeição como resolvido',
             },
         },
-        rejectReport: {
-            title: 'Rejeitar relatório',
-            description: 'Explique por que você não vai aprovar este relatório:',
-            rejectReason: 'Motivo da rejeição',
-            selectTarget: 'Escolha o membro para quem rejeitar este relatório para revisão:',
-            lastApprover: 'Último aprovador',
-            submitter: 'Remetente',
-            rejectedReportMessage: 'Este relatório foi rejeitado.',
-            rejectedNextStep: 'Este relatório foi rejeitado. Aguardando você corrigir os problemas e reenviar manualmente.',
-            selectMemberError: 'Selecione um membro para o qual rejeitar este relatório.',
-            couldNotReject: 'Não foi possível rejeitar o relatório. Tente novamente.',
-        },
-        moveExpenses: 'Mover para relatório',
+        moveExpenses: () => ({one: 'Mover despesa', other: 'Mover despesas'}),
         moveExpensesError: 'Você não pode mover despesas de diária para relatórios em outros workspaces, porque as tarifas de diária podem ser diferentes entre os workspaces.',
         changeApprover: {
             title: 'Alterar aprovador',
-            header: (workflowSettingLink: string) =>
+            header: ({workflowSettingLink}: WorkflowSettingsParam) =>
                 `Escolha uma opção para alterar o aprovador deste relatório. (Atualize as <a href="${workflowSettingLink}">configurações do espaço de trabalho</a> para alterar isso permanentemente para todos os relatórios.)`,
             changedApproverMessage: (managerID: number) => `alterou o aprovador para <mention-user accountID="${managerID}"/>`,
-            reassignedApproverMessage: (managerID: number) => `reatribuiu o aprovador para <mention-user accountID="${managerID}"/> por meio de uma atualização do fluxo de trabalho`,
             actions: {
                 addApprover: 'Adicionar aprovador',
                 addApproverSubtitle: 'Adicione um aprovador adicional ao fluxo de aprovação existente.',
@@ -1643,12 +1516,10 @@ const translations: TranslationDeepObject<typeof en> = {
             },
             addApprover: {
                 subtitle: 'Escolha um aprovador adicional para este relatório antes de seguirmos pelo restante do fluxo de aprovação.',
-                bulkSubtitle: 'Escolha um aprovador adicional para estes relatórios antes de seguirmos pelo restante do fluxo de aprovação.',
             },
-            bulkSubtitle: 'Escolha uma opção para alterar o aprovador destes relatórios.',
         },
         chooseWorkspace: 'Escolha um workspace',
-        routedDueToDEW: (to: string, reason?: string) => `relatório encaminhado para ${to}${reason ? ` porque ${reason}` : ''}`,
+        routedDueToDEW: ({to}: RoutedDueToDEWParams) => `relatório encaminhado para ${to} devido ao fluxo de aprovação personalizado`,
         timeTracking: {
             hoursAt: (hours: number, rate: string) => `${hours} ${hours === 1 ? 'hora' : 'horas'} @ ${rate} / hora`,
             hrs: 'h',
@@ -1656,33 +1527,34 @@ const translations: TranslationDeepObject<typeof en> = {
             ratePreview: (rate: string) => `${rate} / hora`,
             amountTooLargeError: 'O valor total é muito alto. Diminua as horas ou reduza a tarifa.',
         },
-        correctRateError: 'Corrija o erro de taxa e tente novamente.',
-        AskToExplain: `. <a href="${CONST.CONCIERGE_EXPLAIN_LINK_PATH}">Explicar<sparkles-icon/></a>`,
-        duplicateNonDefaultWorkspacePerDiemError: 'Você não pode duplicar despesas de diárias entre espaços de trabalho porque as tarifas podem variar entre eles.',
-        rulesModifiedFields: {
-            reimbursable: (value: boolean) => (value ? 'marcou a despesa como "reembolsável"' : 'marcou a despesa como “não reembolsável”'),
-            billable: (value: boolean) => (value ? 'marcou a despesa como "faturável"' : 'marcou a despesa como "não faturável"'),
-            tax: (value: string, isFirst: boolean) => (isFirst ? `definir a alíquota de imposto como "${value}"` : `alíquota de imposto para "${value}"`),
-            reportName: (value: string) => `moveu esta despesa para o relatório "${value}"`,
-            common: (key: keyof PolicyRulesModifiedFields | keyof PersonalRulesModifiedFields, value: string, isFirst: boolean) => {
-                const field = translations.common[key].toLowerCase();
-                return isFirst ? `defina ${field} como "${value}"` : `${field} para "${value}"`;
-            },
-            formatPersonalRules: (fragments: string, route: string) => `${fragments} via <a href="${route}">regras de despesas pessoais</a>`,
-            formatPolicyRules: (fragments: string, route: string) => `${fragments} via <a href="${route}">regras do workspace</a>`,
-        },
-        failedToAutoSubmitViaDEW: (reason: string) => `falha ao enviar o relatório via <a href="${CONST.SELECT_WORKFLOWS_HELP_URL}">adiar envios</a>. ${reason}`,
-        failedToSubmitViaDEW: (reason: string) => `falha ao enviar o relatório. ${reason}`,
-        failedToAutoApproveViaDEW: (reason: string) => `falha ao aprovar pelas <a href="${CONST.CONFIGURE_EXPENSE_REPORT_RULES_HELP_URL}">regras do workspace</a>. ${reason}`,
-        failedToApproveViaDEW: (reason: string) => `falha ao aprovar. ${reason}`,
-        cannotDuplicateDistanceExpense: 'Você não pode duplicar despesas de distância entre espaços de trabalho porque as tarifas podem ser diferentes entre eles.',
-        taxDisabledAlert: {
-            title: 'Imposto desativado',
-            prompt: 'Ative o acompanhamento de impostos no espaço de trabalho para editar os detalhes da despesa ou excluir o imposto desta despesa.',
-            confirmText: 'Excluir imposto',
-        },
-        bulkDuplicateLimit: `Você pode duplicar até ${CONST.SEARCH.BULK_DUPLICATE_LIMIT} despesas por vez. Selecione menos despesas e tente novamente.`,
-        deleted: 'Excluído',
+        correctDistanceRateError: 'Corrija o erro na taxa de distância e tente novamente.',
+        AskToExplain: `. <a href="${CONST.CONCIERGE_EXPLAIN_LINK_PATH}"><strong>Explicar</strong></a> &#x2728;`,
+        policyRulesModifiedFields: (policyRulesModifiedFields: PolicyRulesModifiedFields, policyRulesRoute: string, formatList: (list: string[]) => string) => {
+            const entries = ObjectUtils.typedEntries(policyRulesModifiedFields);
+            const fragments = entries.map(([key, value], i) => {
+                const isFirst = i === 0;
+                if (key === 'reimbursable') {
+                    return value ? 'marcou a despesa como "reembolsável"' : 'marcou a despesa como “não reembolsável”';
+                }
+                if (key === 'billable') {
+                    return value ? 'marcou a despesa como "faturável"' : 'marcou a despesa como “não faturável”';
+                }
+                if (key === 'tax') {
+                    const taxEntry = value as PolicyRulesModifiedFields['tax'];
+                    const taxRateName = taxEntry?.field_id_TAX.name ?? '';
+                    if (isFirst) {
+                        return `definir a alíquota de imposto como "${taxRateName}"`;
+                    }
+                    return `alíquota de imposto para “${taxRateName}”`;
+                }
+                const updatedValue = value as string | boolean;
+                if (isFirst) {
+                    return `defina ${translations.common[key].toLowerCase()} como "${updatedValue}"`;
+                }
+                return `${translations.common[key].toLowerCase()} para "${updatedValue}"`;
+            });
+            return `${formatList(fragments)} via <a href="${policyRulesRoute}">regras do espaço de trabalho</a>`;
+        },
     },
     transactionMerge: {
         listPage: {
@@ -1755,66 +1627,41 @@ const translations: TranslationDeepObject<typeof en> = {
     },
     nextStep: {
         message: {
-            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_TO_ADD_TRANSACTIONS]: (
-                actor: string,
-                actorType: ValueOf<typeof CONST.NEXT_STEP.ACTOR_TYPE>,
-                _eta?: string,
-                _etaType?: ValueOf<typeof CONST.NEXT_STEP.ETA_TYPE>,
-            ) => {
+            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_TO_ADD_TRANSACTIONS]: ({actor, actorType}: NextStepParams) => {
                 switch (actorType) {
                     case CONST.NEXT_STEP.ACTOR_TYPE.CURRENT_USER:
-                        return `Aguardando <strong>você</strong> adicionar despesas.`;
+                        return `Esperando que <strong>você</strong> adicione despesas.`;
                     case CONST.NEXT_STEP.ACTOR_TYPE.OTHER_USER:
                         return `Aguardando <strong>${actor}</strong> adicionar despesas.`;
                     case CONST.NEXT_STEP.ACTOR_TYPE.UNSPECIFIED_ADMIN:
-                        return `Aguardando um administrador adicionar despesas.`;
+                        return `Aguardando um admin adicionar despesas.`;
                 }
             },
-            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_TO_SUBMIT]: (
-                actor: string,
-                actorType: ValueOf<typeof CONST.NEXT_STEP.ACTOR_TYPE>,
-                _eta?: string,
-                _etaType?: ValueOf<typeof CONST.NEXT_STEP.ETA_TYPE>,
-            ) => {
+            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_TO_SUBMIT]: ({actor, actorType}: NextStepParams) => {
                 switch (actorType) {
                     case CONST.NEXT_STEP.ACTOR_TYPE.CURRENT_USER:
-                        return `Aguardando <strong>você</strong> enviar despesas.`;
+                        return `Aguardando que <strong>você</strong> envie despesas.`;
                     case CONST.NEXT_STEP.ACTOR_TYPE.OTHER_USER:
                         return `Aguardando <strong>${actor}</strong> enviar as despesas.`;
                     case CONST.NEXT_STEP.ACTOR_TYPE.UNSPECIFIED_ADMIN:
                         return `Aguardando um administrador enviar as despesas.`;
                 }
             },
-            [CONST.NEXT_STEP.MESSAGE_KEY.NO_FURTHER_ACTION]: (
-                _actor: string,
-                _actorType: ValueOf<typeof CONST.NEXT_STEP.ACTOR_TYPE>,
-                _eta?: string,
-                _etaType?: ValueOf<typeof CONST.NEXT_STEP.ETA_TYPE>,
-            ) => `Nenhuma ação adicional é necessária!`,
-            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_FOR_SUBMITTER_ACCOUNT]: (
-                actor: string,
-                actorType: ValueOf<typeof CONST.NEXT_STEP.ACTOR_TYPE>,
-                _eta?: string,
-                _etaType?: ValueOf<typeof CONST.NEXT_STEP.ETA_TYPE>,
-            ) => {
+            [CONST.NEXT_STEP.MESSAGE_KEY.NO_FURTHER_ACTION]: (_: NextStepParams) => `Nenhuma ação adicional necessária!`,
+            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_FOR_SUBMITTER_ACCOUNT]: ({actor, actorType}: NextStepParams) => {
                 switch (actorType) {
                     case CONST.NEXT_STEP.ACTOR_TYPE.CURRENT_USER:
-                        return `Esperando <strong>você</strong> adicionar uma conta bancária.`;
+                        return `Aguardando <strong>você</strong> adicionar uma conta bancária.`;
                     case CONST.NEXT_STEP.ACTOR_TYPE.OTHER_USER:
                         return `Aguardando <strong>${actor}</strong> adicionar uma conta bancária.`;
                     case CONST.NEXT_STEP.ACTOR_TYPE.UNSPECIFIED_ADMIN:
                         return `Aguardando um administrador adicionar uma conta bancária.`;
                 }
             },
-            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_FOR_AUTOMATIC_SUBMIT]: (
-                actor: string,
-                actorType: ValueOf<typeof CONST.NEXT_STEP.ACTOR_TYPE>,
-                eta?: string,
-                etaType?: ValueOf<typeof CONST.NEXT_STEP.ETA_TYPE>,
-            ) => {
+            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_FOR_AUTOMATIC_SUBMIT]: ({actor, actorType, eta, etaType}: NextStepParams) => {
                 let formattedETA = '';
                 if (eta) {
-                    formattedETA = etaType === CONST.NEXT_STEP.ETA_TYPE.DATE_TIME ? `no dia ${eta} de cada mês` : ` ${eta}`;
+                    formattedETA = etaType === CONST.NEXT_STEP.ETA_TYPE.DATE_TIME ? `em ${eta}` : ` ${eta}`;
                 }
                 switch (actorType) {
                     case CONST.NEXT_STEP.ACTOR_TYPE.CURRENT_USER:
@@ -1825,12 +1672,7 @@ const translations: TranslationDeepObject<typeof en> = {
                         return `Aguardando as despesas de um administrador serem enviadas automaticamente${formattedETA}.`;
                 }
             },
-            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_TO_FIX_ISSUES]: (
-                actor: string,
-                actorType: ValueOf<typeof CONST.NEXT_STEP.ACTOR_TYPE>,
-                _eta?: string,
-                _etaType?: ValueOf<typeof CONST.NEXT_STEP.ETA_TYPE>,
-            ) => {
+            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_TO_FIX_ISSUES]: ({actor, actorType}: NextStepParams) => {
                 switch (actorType) {
                     case CONST.NEXT_STEP.ACTOR_TYPE.CURRENT_USER:
                         return `Aguardando <strong>você</strong> corrigir os problemas.`;
@@ -1840,12 +1682,7 @@ const translations: TranslationDeepObject<typeof en> = {
                         return `Aguardando um administrador corrigir os problemas.`;
                 }
             },
-            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_TO_APPROVE]: (
-                actor: string,
-                actorType: ValueOf<typeof CONST.NEXT_STEP.ACTOR_TYPE>,
-                _eta?: string,
-                _etaType?: ValueOf<typeof CONST.NEXT_STEP.ETA_TYPE>,
-            ) => {
+            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_TO_APPROVE]: ({actor, actorType}: NextStepParams) => {
                 switch (actorType) {
                     case CONST.NEXT_STEP.ACTOR_TYPE.CURRENT_USER:
                         return `Aguardando <strong>você</strong> aprovar as despesas.`;
@@ -1855,12 +1692,7 @@ const translations: TranslationDeepObject<typeof en> = {
                         return `Aguardando um administrador aprovar as despesas.`;
                 }
             },
-            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_TO_EXPORT]: (
-                actor: string,
-                actorType: ValueOf<typeof CONST.NEXT_STEP.ACTOR_TYPE>,
-                _eta?: string,
-                _etaType?: ValueOf<typeof CONST.NEXT_STEP.ETA_TYPE>,
-            ) => {
+            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_TO_EXPORT]: ({actor, actorType}: NextStepParams) => {
                 switch (actorType) {
                     case CONST.NEXT_STEP.ACTOR_TYPE.CURRENT_USER:
                         return `Aguardando <strong>você</strong> exportar este relatório.`;
@@ -1870,70 +1702,35 @@ const translations: TranslationDeepObject<typeof en> = {
                         return `Aguardando um administrador exportar este relatório.`;
                 }
             },
-            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_TO_PAY]: (
-                actor: string,
-                actorType: ValueOf<typeof CONST.NEXT_STEP.ACTOR_TYPE>,
-                _eta?: string,
-                _etaType?: ValueOf<typeof CONST.NEXT_STEP.ETA_TYPE>,
-            ) => {
+            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_TO_PAY]: ({actor, actorType}: NextStepParams) => {
                 switch (actorType) {
                     case CONST.NEXT_STEP.ACTOR_TYPE.CURRENT_USER:
                         return `Aguardando <strong>você</strong> pagar as despesas.`;
                     case CONST.NEXT_STEP.ACTOR_TYPE.OTHER_USER:
-                        return `Aguardando <strong>${actor}</strong> pagar as despesas.`;
+                        return `Aguardando o pagamento das despesas por <strong>${actor}</strong>.`;
                     case CONST.NEXT_STEP.ACTOR_TYPE.UNSPECIFIED_ADMIN:
-                        return `Aguardando um administrador pagar as despesas.`;
+                        return `Aguardando que um administrador pague as despesas.`;
                 }
             },
-            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_FOR_POLICY_BANK_ACCOUNT]: (
-                actor: string,
-                actorType: ValueOf<typeof CONST.NEXT_STEP.ACTOR_TYPE>,
-                _eta?: string,
-                _etaType?: ValueOf<typeof CONST.NEXT_STEP.ETA_TYPE>,
-            ) => {
+            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_FOR_POLICY_BANK_ACCOUNT]: ({actor, actorType}: NextStepParams) => {
                 switch (actorType) {
                     case CONST.NEXT_STEP.ACTOR_TYPE.CURRENT_USER:
-                        return `Aguardando <strong>você</strong> concluir a configuração de uma conta bancária empresarial.`;
+                        return `Aguardando que <strong>você</strong> conclua a configuração de uma conta bancária comercial.`;
                     case CONST.NEXT_STEP.ACTOR_TYPE.OTHER_USER:
                         return `Aguardando <strong>${actor}</strong> terminar de configurar uma conta bancária empresarial.`;
                     case CONST.NEXT_STEP.ACTOR_TYPE.UNSPECIFIED_ADMIN:
                         return `Aguardando um administrador concluir a configuração de uma conta bancária empresarial.`;
                 }
             },
-            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_FOR_PAYMENT]: (
-                _actor: string,
-                _actorType: ValueOf<typeof CONST.NEXT_STEP.ACTOR_TYPE>,
-                eta?: string,
-                etaType?: ValueOf<typeof CONST.NEXT_STEP.ETA_TYPE>,
-            ) => {
+            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_FOR_PAYMENT]: ({eta, etaType}: NextStepParams) => {
                 let formattedETA = '';
                 if (eta) {
                     formattedETA = etaType === CONST.NEXT_STEP.ETA_TYPE.DATE_TIME ? `até ${eta}` : ` ${eta}`;
                 }
                 return `Aguardando o pagamento ser concluído${formattedETA}.`;
             },
-            [CONST.NEXT_STEP.MESSAGE_KEY.SUBMITTING_TO_SELF]: (
-                _actor: string,
-                _actorType: ValueOf<typeof CONST.NEXT_STEP.ACTOR_TYPE>,
-                _eta?: string,
-                _etaType?: ValueOf<typeof CONST.NEXT_STEP.ETA_TYPE>,
-            ) =>
-                `Opa! Parece que você está enviando para <strong>você mesmo</strong>. Aprovar seus próprios relatórios é <strong>proibido</strong> pelo seu espaço de trabalho. Envie este relatório para outra pessoa ou entre em contato com seu administrador para alterar a pessoa para quem você envia.`,
-            [CONST.NEXT_STEP.MESSAGE_KEY.REJECTED_REPORT]: (
-                actor: string,
-                actorType: ValueOf<typeof CONST.NEXT_STEP.ACTOR_TYPE>,
-                _eta?: string,
-                _etaType?: ValueOf<typeof CONST.NEXT_STEP.ETA_TYPE>,
-            ) => {
-                switch (actorType) {
-                    case CONST.NEXT_STEP.ACTOR_TYPE.CURRENT_USER:
-                        return `Este relatório foi recusado. Aguardando que <strong>você</strong> corrija os problemas e o envie novamente manualmente.`;
-                    case CONST.NEXT_STEP.ACTOR_TYPE.OTHER_USER:
-                        return `Este relatório foi rejeitado. Aguardando <strong>${actor}</strong> corrigir os problemas e reenviar manualmente.`;
-                    case CONST.NEXT_STEP.ACTOR_TYPE.UNSPECIFIED_ADMIN:
-                        return `Este relatório foi rejeitado. Aguardando um administrador corrigir os problemas e reenviar manualmente.`;
-                }
-            },
+            [CONST.NEXT_STEP.MESSAGE_KEY.SUBMITTING_TO_SELF]: (_: NextStepParams) =>
+                `Ops! Parece que você está enviando para <strong>você mesmo(a)</strong>. Aprovar seus próprios relatórios é <strong>proibido</strong> pelo seu workspace. Envie este relatório para outra pessoa ou entre em contato com o(a) administrador(a) para alterar a pessoa para quem você envia.`,
         },
         eta: {
             [CONST.NEXT_STEP.ETA_KEY.SHORTLY]: 'em breve',
@@ -1959,8 +1756,6 @@ const translations: TranslationDeepObject<typeof en> = {
         offline: 'Offline',
         syncing: 'Sincronizando',
         profileAvatar: 'Avatar do perfil',
-        customInstructions: 'Instruções personalizadas',
-        copilotIntoAccount: 'Copilot na conta',
         publicSection: {
             title: 'Público',
             subtitle: 'Esses detalhes são exibidos no seu perfil público. Qualquer pessoa pode vê-los.',
@@ -1969,16 +1764,12 @@ const translations: TranslationDeepObject<typeof en> = {
             title: 'Privado',
             subtitle: 'Esses detalhes são usados para viagens e pagamentos. Eles nunca são exibidos no seu perfil público.',
         },
-        aiPromptSection: {
-            title: 'Prompt de IA',
-            subtitle: 'Escrever instruções personalizadas',
-            prompt: 'Prompt',
-            editPrompt: 'Editar prompt',
-            promptCannotBeEmpty: 'O prompt não pode ficar vazio',
-            saved: 'Salvo',
-        },
     },
-    securityPage: {title: 'Segurança', subtitle: 'Mantenha sua conta segura.', goToSecurity: 'Voltar para a página de segurança'},
+    securityPage: {
+        title: 'Opções de segurança',
+        subtitle: 'Ative a autenticação em duas etapas para manter sua conta segura.',
+        goToSecurity: 'Voltar para a página de segurança',
+    },
     shareCodePage: {
         title: 'Seu código',
         subtitle: 'Convide pessoas para o Expensify compartilhando seu código QR pessoal ou link de indicação.',
@@ -2015,7 +1806,6 @@ const translations: TranslationDeepObject<typeof en> = {
         },
         newContactMethod: 'Novo método de contato',
         goBackContactMethods: 'Voltar para métodos de contato',
-        yourDefaultContactMethodRestrictedSwitch: 'Este é seu método de contato padrão atual. Sua empresa restringiu a remoção ou alteração dele.',
     },
     pronouns: {
         coCos: 'Co / Cos',
@@ -2075,6 +1865,8 @@ const translations: TranslationDeepObject<typeof en> = {
         },
         troubleshoot: {
             clearCacheAndRestart: 'Limpar cache e reiniciar',
+            viewConsole: 'Ver console de depuração',
+            debugConsole: 'Console de depuração',
             description:
                 '<muted-text>Use as ferramentas abaixo para ajudar a solucionar problemas na experiência do Expensify. Se você encontrar algum problema, por favor, <concierge-link>envie um bug</concierge-link>.</muted-text>',
             confirmResetDescription: 'Todas as mensagens de rascunho não enviadas serão perdidas, mas o restante dos seus dados está seguro.',
@@ -2106,47 +1898,35 @@ const translations: TranslationDeepObject<typeof en> = {
             invalidateWithDelay: 'Invalidar com atraso',
             leftHandNavCache: 'Cache da navegação à esquerda',
             clearleftHandNavCache: 'Limpar',
+            recordTroubleshootData: 'Registrar dados de diagnóstico',
             softKillTheApp: 'Encerrar o app suavemente',
             kill: 'Matar',
             sentryDebug: 'Depuração do Sentry',
-            sentrySendDescription: 'Enviar dados ao Sentry',
             sentryDebugDescription: 'Registrar solicitações do Sentry no console',
             sentryHighlightedSpanOps: 'Nomes de trechos destacados',
             sentryHighlightedSpanOpsPlaceholder: 'ui.interaction.click, navegação, ui.carregar',
-            showBranchNameInTitle: 'Mostrar nome da branch no título do navegador',
+        },
+        debugConsole: {
+            saveLog: 'Salvar log',
+            shareLog: 'Compartilhar registro',
+            enterCommand: 'Inserir comando',
+            execute: 'Executar',
+            noLogsAvailable: 'Nenhum registro disponível',
+            logSizeTooLarge: (size: number) => `O tamanho do log excede o limite de ${size} MB. Use “Salvar log” para baixar o arquivo de log.`,
+            logs: 'Logs',
+            viewConsole: 'Ver console',
         },
         security: 'Segurança',
         signOut: 'Sair',
         restoreStashed: 'Restaurar login armazenado',
         signOutConfirmationText: 'Você perderá quaisquer alterações offline se sair.',
         versionLetter: 'v',
-        readTheTermsAndPrivacy: `Leia os <a href="${CONST.OLD_DOT_PUBLIC_URLS.TERMS_URL}">Termos de Serviço</a> e a <a href="${CONST.OLD_DOT_PUBLIC_URLS.PRIVACY_URL}">Política de Privacidade</a>.`,
+        readTheTermsAndPrivacy: `<muted-text-micro>Leia os <a href="${CONST.OLD_DOT_PUBLIC_URLS.TERMS_URL}">Termos de Serviço</a> e a <a href="${CONST.OLD_DOT_PUBLIC_URLS.PRIVACY_URL}">Política de Privacidade</a>.</muted-text-micro>`,
         help: 'Ajuda',
         whatIsNew: 'Novidades',
         accountSettings: 'Configurações da conta',
         account: 'Conta',
         general: 'Geral',
-        helpPage: {
-            title: 'Ajuda e suporte',
-            description: 'Estamos aqui para ajudar, 24 horas por dia.',
-            helpSite: 'Site de ajuda',
-            helpSiteDescription: 'Artigos, tutoriais e mais',
-            conciergeChat: 'Concierge',
-            conciergeChatDescription: 'Seu agente de IA pessoal',
-            accountManager: 'Gerente de Conta',
-            yourAccountManager: 'Seu gerente de conta',
-            accountManagerDescription: 'Faça perguntas e receba suporte ao cliente',
-            partnerManager: 'Gerente de Parcerias',
-            yourPartnerManager: 'Seu gerente de parcerias',
-            partnerManagerDescription: 'Maximize sua parceria e aumente as indicações',
-            guideDescription: 'Seu executivo de contas',
-            approvedPartnerTeamTitle: 'Conheça sua equipe parceira Approved!',
-            approvedPartnerTeamDescription:
-                'Uma equipe dedicada focada em ajudar sua empresa a crescer, integrar clientes mais rápido e receber suporte especializado sempre que você precisar.',
-            accountExecutive: 'Executivo de Contas',
-            accountExecutiveDescription: 'Configurar clientes com sucesso',
-            moreResources: 'Mais recursos',
-        },
     },
     closeAccountPage: {
         closeAccount: 'Encerrar conta',
@@ -2220,12 +2000,10 @@ const translations: TranslationDeepObject<typeof en> = {
         lockAccount: 'Bloquear conta',
         unlockAccount: 'Desbloquear conta',
         compromisedDescription:
-            'Percebeu algo estranho na sua conta? Ao denunciar, sua conta será imediatamente bloqueada, novas transações com o Cartão Expensify serão impedidas e qualquer alteração na conta será bloqueada.',
-        domainAdminsDescription: 'Para admins de domínio: isso também pausa todas as atividades do Cartão Expensify e ações de administração em todo(s) o(s) seu(s) domínio(s).',
+            'Percebeu algo estranho na sua conta? Ao reportar, sua conta será imediatamente bloqueada, novas transações com o Cartão Expensify serão impedidas e quaisquer alterações na conta serão evitadas.',
+        domainAdminsDescription: 'Para administradores de domínio: isso também pausa toda a atividade do Cartão Expensify e as ações de administrador em todo(s) o(s) seu(s) domínio(s).',
         areYouSure: 'Tem certeza de que deseja bloquear sua conta Expensify?',
         onceLocked: 'Depois de bloqueada, sua conta ficará restrita até que seja feita uma solicitação de desbloqueio e uma revisão de segurança',
-        unlockTitle: 'Recebemos sua solicitação',
-        unlockDescription: 'Vamos revisar a conta para verificar se é seguro desbloqueá-la e entraremos em contato via Concierge caso haja dúvidas.',
     },
     failedToLockAccountPage: {
         failedToLockAccount: 'Falha ao bloquear a conta',
@@ -2238,35 +2016,28 @@ const translations: TranslationDeepObject<typeof en> = {
         chatToConciergeToUnlock: 'Converse com o Concierge para resolver questões de segurança e desbloquear sua conta.',
         chatWithConcierge: 'Converse com o Concierge',
     },
-    deviceManagementPage: {
-        title: 'Gerenciamento de dispositivos',
-        description:
-            'Gerencie todos os dispositivos nos quais você fez login com sua conta Expensify. <a href="https://help.expensify.com/articles/new-expensify/settings/Manage-Logged-in-Devices">Saiba mais</a>.',
-        revoke: 'Revogar',
-        unknownDevice: 'Dispositivo Desconhecido',
-    },
     twoFactorAuth: {
         headerTitle: 'Autenticação de dois fatores',
         twoFactorAuthEnabled: 'Autenticação em duas etapas ativada',
         whatIsTwoFactorAuth:
             'A autenticação em duas etapas (2FA) ajuda a manter sua conta segura. Ao fazer login, você precisará inserir um código gerado pelo seu aplicativo autenticador preferido.',
         disableTwoFactorAuth: 'Desativar autenticação em duas etapas',
-        explainProcessToRemove: 'Para desativar a autenticação em duas etapas (2FA), insira um código válido do seu app de autenticação.',
-        explainProcessToRemoveWithRecovery: 'Para desativar a autenticação em duas etapas (2FA), insira um código de recuperação válido.',
+        explainProcessToRemove: 'Para desativar a autenticação de dois fatores (2FA), insira um código válido do seu app de autenticação.',
+        explainProcessToRemoveWithRecovery: 'Para desativar a autenticação de dois fatores (2FA), insira um código de recuperação válido.',
         disabled: 'A autenticação em duas etapas está desativada agora',
         noAuthenticatorApp: 'Você não vai mais precisar de um app autenticador para entrar no Expensify.',
         stepCodes: 'Códigos de recuperação',
-        keepCodesSafe: 'Mantenha estes códigos em segurança!',
+        keepCodesSafe: 'Mantenha estes códigos de recuperação em segurança!',
         codesLoseAccess: dedent(`
-            Se você perder o acesso ao seu app autenticador e não tiver esses códigos, ficará bloqueado fora da sua conta.<br><br>
-            <strong>Observação</strong>: Ativar a 2FA desconecta você de todas as outras sessões.
+            Se você perder o acesso ao seu app autenticador e não tiver esses códigos, perderá o acesso à sua conta.
+
+            Observação: Configurar a autenticação em duas etapas desconectará você de todas as outras sessões ativas.
         `),
         errorStepCodes: 'Copie ou faça o download dos códigos antes de continuar',
         stepVerify: 'Verificar',
         scanCode: 'Escaneie o código QR usando seu',
         authenticatorApp: 'aplicativo autenticador',
         addKey: 'Ou adicione esta chave secreta ao seu app autenticador:',
-        secretKey: 'chave secreta',
         enterCode: 'Em seguida, insira o código de seis dígitos gerado pelo seu app autenticador.',
         stepSuccess: 'Concluído',
         enabled: 'Autenticação em duas etapas ativada',
@@ -2282,14 +2053,6 @@ const translations: TranslationDeepObject<typeof en> = {
         twoFactorAuthIsRequiredCompany: 'Sua empresa exige autenticação em duas etapas.',
         twoFactorAuthCannotDisable: 'Não é possível desativar a 2FA',
         twoFactorAuthRequired: 'A autenticação em duas etapas (2FA) é obrigatória para sua conexão com o Xero e não pode ser desativada.',
-        replaceDevice: 'Substituir dispositivo',
-        replaceDeviceTitle: 'Substituir dispositivo de dois fatores',
-        verifyOldDeviceTitle: 'Verificar dispositivo antigo',
-        verifyOldDeviceDescription: 'Digite o código de seis dígitos do seu aplicativo autenticador atual para confirmar que você tem acesso a ele.',
-        verifyNewDeviceTitle: 'Configurar novo dispositivo',
-        verifyNewDeviceDescription: 'Escaneie o código QR com seu novo dispositivo e depois insira o código para concluir a configuração.',
-        downloadCodes: 'Baixar códigos',
-        copyCodes: 'Copiar códigos',
     },
     recoveryCodeForm: {
         error: {
@@ -2377,39 +2140,6 @@ const translations: TranslationDeepObject<typeof en> = {
             password: 'Insira sua senha do Expensify',
         },
     },
-    personalCard: {
-        addPersonalCard: 'Adicionar cartão pessoal',
-        addCompanyCard: 'Adicionar cartão corporativo',
-        lookingForCompanyCards: 'Precisa adicionar cartões corporativos?',
-        lookingForCompanyCardsDescription: 'Conecte seus próprios cartões de mais de 10.000 bancos no mundo todo.',
-        personalCardAdded: 'Cartão pessoal adicionado!',
-        personalCardAddedDescription: 'Parabéns, começaremos a importar transações do seu cartão.',
-        isPersonalCard: 'Este é um cartão pessoal?',
-        thisIsPersonalCard: 'Este é um cartão pessoal',
-        thisIsCompanyCard: 'Este é um cartão corporativo',
-        askAdmin: 'Pergunte ao administrador',
-        warningDescription: ({isAdmin}: {isAdmin?: boolean}) =>
-            `Se sim, ótimo! Mas se for um cartão <strong>corporativo</strong>, ${isAdmin ? 'atribua-o no seu espaço de trabalho.' : 'peça ao administrador para atribuí-lo a você no espaço de trabalho.'}`,
-        bankConnectionError: 'Problema de conexão com o banco',
-        bankConnectionDescription: 'Tente adicionar seus cartões novamente. Caso contrário, você pode',
-        connectWithPlaid: 'conectar via Plaid.',
-        fixCard: 'Corrigir cartão',
-        brokenConnection: 'A conexão do seu cartão está com problema.',
-        conciergeBrokenConnection: ({cardName, connectionLink}: ConciergeBrokenCardConnectionParams) =>
-            connectionLink
-                ? `A conexão do seu cartão ${cardName} está com problemas. <a href="${connectionLink}">Acesse seu banco</a> para corrigir o cartão.`
-                : `A conexão do seu cartão ${cardName} está com problemas. Acesse seu banco para corrigir o cartão.`,
-        addAdditionalCards: 'Adicionar outros cartões',
-        upgradeDescription: 'Precisa adicionar mais cartões? Crie um espaço de trabalho para adicionar cartões pessoais ou atribuir cartões corporativos a toda a equipe.',
-        onlyAvailableOnPlan: ({formattedPrice}: {formattedPrice: string}) =>
-            `<muted-text>Disponível no plano Collect por <strong>${formattedPrice}</strong> por membro por mês.</muted-text>`,
-        note: (subscriptionLink: string) =>
-            `<muted-text>Crie um espaço de trabalho para acessar este recurso ou <a href="${subscriptionLink}">saiba mais</a> sobre nossos planos e preços.</muted-text>`,
-        workspaceCreated: 'Espaço de trabalho criado',
-        newWorkspace: 'Você criou um espaço de trabalho!',
-        successMessage: ({subscriptionLink}: {subscriptionLink: string}) =>
-            `<centered-text>Tudo pronto para adicionar outros cartões. <a href="${subscriptionLink}">Ver sua assinatura</a> para mais detalhes.</centered-text>`,
-    },
     walletPage: {
         balance: 'Saldo',
         paymentMethodsTitle: 'Formas de pagamento',
@@ -2437,9 +2167,8 @@ const translations: TranslationDeepObject<typeof en> = {
         enableWallet: 'Ativar carteira',
         addBankAccountToSendAndReceive: 'Adicione uma conta bancária para fazer ou receber pagamentos.',
         addDebitOrCreditCard: 'Adicionar cartão de débito ou crédito',
-        cardInactive: 'Inativo',
-        assignedCards: 'Cartões',
-        assignedCardsDescription: 'As transações de cartões atribuídos são sincronizadas automaticamente.',
+        assignedCards: 'Cartões atribuídos',
+        assignedCardsDescription: 'As transações desses cartões são sincronizadas automaticamente.',
         expensifyCard: 'Cartão Expensify',
         walletActivationPending: 'Estamos analisando suas informações. Volte a conferir em alguns minutos!',
         walletActivationFailed: 'Infelizmente, sua carteira não pode ser ativada neste momento. Converse com o Concierge para obter mais ajuda.',
@@ -2463,13 +2192,8 @@ const translations: TranslationDeepObject<typeof en> = {
         unshareBankAccountDescription:
             'Todas as pessoas abaixo têm acesso a esta conta bancária. Você pode remover o acesso a qualquer momento. Ainda concluiremos quaisquer pagamentos em andamento.',
         unshareBankAccountWarning: ({admin}: {admin?: string | null}) => `${admin} perderá o acesso a esta conta bancária empresarial. Ainda concluiremos quaisquer pagamentos em andamento.`,
-        reachOutForHelp: 'Ele está sendo usado com o Cartão Expensify. <concierge-link>Entre em contato com o Concierge</concierge-link> se você precisar parar de compartilhá-lo.',
+        reachOutForHelp: 'Ela está sendo usada com o Cartão Expensify. <concierge-link>Entre em contato com o Concierge</concierge-link> se precisar parar de compartilhá-la.',
         unshareErrorModalTitle: 'Não é possível parar de compartilhar a conta bancária',
-        travelCVV: {
-            title: 'CVV de viagem',
-            subtitle: 'Use isto ao reservar viagens',
-            description: 'Use este cartão para suas reservas no Expensify Travel. Ele aparecerá como “Travel Card” no checkout.',
-        },
         chaseAccountNumberDifferent: 'Por que meu número de conta é diferente?',
     },
     cardPage: {
@@ -2478,15 +2202,17 @@ const translations: TranslationDeepObject<typeof en> = {
         availableSpend: 'Limite restante',
         smartLimit: {
             name: 'Limite inteligente',
-            title: (formattedLimit: string) => `Você pode gastar até ${formattedLimit} neste cartão, e o limite será redefinido conforme suas despesas enviadas forem aprovadas.`,
+            title: ({formattedLimit}: ViolationsOverLimitParams) =>
+                `Você pode gastar até ${formattedLimit} neste cartão, e o limite será redefinido conforme suas despesas enviadas forem aprovadas.`,
         },
         fixedLimit: {
             name: 'Limite fixo',
-            title: (formattedLimit: string) => `Você pode gastar até ${formattedLimit} neste cartão e, depois disso, ele será desativado.`,
+            title: ({formattedLimit}: ViolationsOverLimitParams) => `Você pode gastar até ${formattedLimit} neste cartão e, depois disso, ele será desativado.`,
         },
         monthlyLimit: {
             name: 'Limite mensal',
-            title: (formattedLimit: string) => `Você pode gastar até ${formattedLimit} neste cartão por mês. O limite será reiniciado no 1º dia de cada mês do calendário.`,
+            title: ({formattedLimit}: ViolationsOverLimitParams) =>
+                `Você pode gastar até ${formattedLimit} neste cartão por mês. O limite será reiniciado no 1º dia de cada mês do calendário.`,
         },
         virtualCardNumber: 'Número do cartão virtual',
         travelCardCvv: 'CVV do cartão de viagem',
@@ -2507,17 +2233,16 @@ const translations: TranslationDeepObject<typeof en> = {
             expiration: 'Validade',
             cvv: 'CVV',
             address: 'Endereço',
-            reveal: 'Revelar',
             revealDetails: 'Revelar detalhes',
             revealCvv: 'Revelar código CVV',
             copyCardNumber: 'Copiar número do cartão',
-            copyCvv: 'Copiar CVV',
             updateAddress: 'Atualizar endereço',
         },
         cardAddedToWallet: ({platform}: {platform: 'Google' | 'Apple'}) => `Adicionado à carteira ${platform}`,
         cardDetailsLoadingFailure: 'Ocorreu um erro ao carregar os detalhes do cartão. Verifique sua conexão com a internet e tente novamente.',
         validateCardTitle: 'Vamos garantir que é você',
         enterMagicCode: (contactMethod: string) => `Insira o código mágico enviado para ${contactMethod} para visualizar os detalhes do seu cartão. Ele deve chegar em um ou dois minutos.`,
+        missingPrivateDetails: ({missingDetailsLink}: {missingDetailsLink: string}) => `Por favor, <a href="${missingDetailsLink}">adicione seus dados pessoais</a> e tente novamente.`,
         unexpectedError: 'Ocorreu um erro ao tentar obter os detalhes do seu cartão Expensify. Tente novamente.',
         cardFraudAlert: {
             confirmButtonText: 'Sim, eu quero',
@@ -2538,42 +2263,6 @@ const translations: TranslationDeepObject<typeof en> = {
 
 ${amount} para ${merchant} - ${date}`,
         },
-        setYourPin: 'Defina seu PIN.',
-        confirmYourPin: 'Confirme seu PIN.',
-        changeYourPin: 'Digite um novo PIN para o seu cartão.',
-        confirmYourChangedPin: 'Confirme seu novo PIN.',
-        pinMustBeFourDigits: 'O PIN deve ter exatamente 4 dígitos.',
-        invalidPin: 'Escolha um PIN mais seguro.',
-        pinMismatch: 'Os PINs não coincidem. Tente novamente.',
-        revealPin: 'Revelar PIN',
-        hidePin: 'Ocultar PIN',
-        pin: 'PIN',
-        changePin: 'Alterar PIN',
-        pinChanged: 'PIN alterado!',
-        pinChangedHeader: 'PIN alterado',
-        pinChangedDescription: 'Tudo pronto para você usar seu PIN agora.',
-        changePinAtATM: 'Altere seu PIN em qualquer caixa eletrônico',
-        changePinAtATMDescription: 'Isso é obrigatório na sua região. <concierge-link>Falar com a Concierge</concierge-link> se você tiver alguma dúvida.',
-        freezeCard: 'Bloquear cartão',
-        unfreeze: 'Desbloquear',
-        unfreezeCard: 'Desbloquear cartão',
-        askToUnfreeze: 'Pedir desbloqueio',
-        freezeDescription: 'Um cartão bloqueado não pode ser usado para compras e transações. Você pode desbloqueá-lo a qualquer momento.',
-        unfreezeDescription: 'Ao desbloquear este cartão, compras e transações voltarão a ser permitidas. Continue apenas se tiver certeza de que o cartão é seguro para uso.',
-        frozen: 'Congelado',
-        youFroze: ({date}: {date: string}) => `Você bloqueou este cartão em ${date}.`,
-        frozenBy: ({person, date}: {person: string; date: string}) => `${person} bloqueou este cartão em ${date}.`,
-        frozenByAdminPrefix: ({date}: {date: string}) => `Este cartão foi bloqueado em ${date} por `,
-        frozenByAdminNeedsUnfreezePrefix: 'Este cartão foi bloqueado por ',
-        frozenByAdminNeedsUnfreezeSuffix: '. Entre em contato com um administrador para desbloqueá-lo.',
-        frozenByAdminNeedsUnfreeze: ({person}: {person: string}) => `Este cartão foi bloqueado por ${person}. Entre em contato com um administrador para desbloqueá-lo.`,
-        spendRules: 'Regras de gasto',
-        editSpendRules: 'Editar regras de gastos',
-        cardUnblocked: 'Cartão desbloqueado!',
-        cardUnblockedDescription: 'Pode ser que você seja solicitado a inserir o seu cartão no leitor na próxima vez que fizer uma compra.',
-        pinBlocked: 'Seu cartão foi bloqueado devido a tentativas de PIN incorretas.',
-        unblock: 'Desbloquear',
-        unblockCard: 'Desbloquear cartão',
     },
     workflowsPage: {
         workflowTitle: 'Gastos',
@@ -2585,14 +2274,9 @@ ${amount} para ${merchant} - ${date}`,
         addApprovalsTitle: 'Aprovações',
         accessibilityLabel: ({members, approvers}: {members: string; approvers: string}) => `despesas de ${members}, e o aprovador é ${approvers}`,
         addApprovalButton: 'Adicionar fluxo de aprovação',
-        editWorkflowAction: 'Editar',
-        addAgentAction: 'Adicionar agente',
-        findWorkflow: 'Buscar fluxo de trabalho',
         addApprovalTip: 'Este fluxo de trabalho padrão se aplica a todos os membros, a menos que exista um fluxo de trabalho mais específico.',
         approver: 'Aprovador',
         addApprovalsDescription: 'Exigir aprovação adicional antes de autorizar um pagamento.',
-        automateApprovalsWithAgentsTitle: 'Automatize aprovações com agentes',
-        automateApprovalsWithAgentsSubtitle: 'Adicione o agente abaixo ao fluxo de trabalho para automatizar as aprovações.',
         makeOrTrackPaymentsTitle: 'Pagamentos',
         makeOrTrackPaymentsDescription: 'Adicione um pagador autorizado para pagamentos feitos no Expensify ou acompanhe pagamentos feitos em outros lugares.',
         customApprovalWorkflowEnabled:
@@ -2637,15 +2321,7 @@ ${amount} para ${merchant} - ${date}`,
             title: 'Nenhum membro para exibir',
             expensesFromSubtitle: 'Todos os membros do espaço de trabalho já pertencem a um fluxo de aprovação existente.',
             approverSubtitle: 'Todas as pessoas aprovadoras pertencem a um fluxo de trabalho existente.',
-            bulkApproverSubtitle: 'Nenhum aprovador corresponde aos critérios para os relatórios selecionados.',
         },
-        configureViaHR: ({provider}: {provider: string}) => `Configurar via ${provider}.`,
-        hrApprovalWorkflowLockedPrompt: ({provider}: {provider: string}) =>
-            `As aprovações são gerenciadas pela sua integração com o ${provider}. Para atualizar seu fluxo de aprovação, vá até as configurações de conexão do ${provider}.`,
-        goToHRSettings: ({provider}: {provider: string}) => `Ir para as configurações do ${provider}`,
-        approverFromProvider: ({provider}: {provider: string}) => `de ${provider}`,
-        finalApprover: 'Aprovador final',
-        manager: 'Gerente',
     },
     workflowsDelayedSubmissionPage: {
         autoReportingFrequencyErrorMessage: 'Não foi possível alterar a frequência de envio. Tente novamente ou entre em contato com o suporte.',
@@ -2665,9 +2341,6 @@ ${amount} para ${merchant} - ${date}`,
     workflowsExpensesFromPage: {
         title: 'Despesas de',
         header: 'Quando os seguintes membros enviarem despesas:',
-        memberAlreadyInWorkflowTitle: 'Membro já está em um fluxo de trabalho',
-        memberAlreadyInWorkflowPrompt: ({memberName, approverName}: {memberName: string; approverName: string}) =>
-            `${memberName} já está em um fluxo de aprovação que envia para ${approverName}. Adicioná-lo aqui irá movê-lo para este fluxo de trabalho.`,
     },
     workflowsApproverPage: {
         genericErrorMessage: 'O aprovador não pôde ser alterado. Tente novamente ou entre em contato com o suporte.',
@@ -2698,16 +2371,6 @@ ${amount} para ${merchant} - ${date}`,
         admins: 'Admins',
         payer: 'Pagador',
         paymentAccount: 'Conta de pagamento',
-        shareBankAccount: {
-            shareTitle: 'Compartilhar acesso à conta bancária?',
-            shareDescription: ({admin}: {admin: string}) => `Você precisará compartilhar o acesso à conta bancária com ${admin} para torná-lo o pagador.`,
-            validationTitle: 'Conta bancária aguardando validação',
-            validationDescription: ({admin}: {admin: string}) =>
-                `Você precisa <a href="#">validar esta conta bancária</a>. Depois disso, você poderá compartilhar o acesso à conta bancária com ${admin} para torná-lo o pagador.`,
-            errorTitle: 'Não é possível alterar o pagador',
-            errorDescription: ({admin, owner}: {admin: string; owner: string}) =>
-                `${admin} não tem acesso a esta conta bancária, portanto, você não pode torná-lo o pagador. <a href="#">Converse com ${owner}</a> se a conta bancária deve ser compartilhada.`,
-        },
     },
     reportFraudPage: {
         title: 'Denunciar fraude no cartão virtual',
@@ -2719,7 +2382,6 @@ ${amount} para ${merchant} - ${date}`,
     reportFraudConfirmationPage: {
         title: 'Fraude no cartão reportada',
         description: 'Desativamos permanentemente seu cartão atual. Quando você voltar para ver os detalhes do cartão, um novo cartão virtual estará disponível.',
-        descriptionCardNotReplaced: 'Seu cartão foi desativado permanentemente. Entre em contato com um administrador para emitir um novo cartão.',
         buttonText: 'Entendido, obrigado!',
     },
     activateCardPage: {
@@ -2729,7 +2391,7 @@ ${amount} para ${merchant} - ${date}`,
         error: {
             thatDidNotMatch: 'Isso não correspondeu aos últimos 4 dígitos do seu cartão. Tente novamente.',
             throttled:
-                'Você digitou incorretamente os últimos 4 dígitos do seu Cartão Expensify muitas vezes. Se tiver certeza de que os números estão corretos, entre em contato com o Concierge para resolver. Caso contrário, tente novamente mais tarde.',
+                'Você digitou incorretamente os últimos 4 dígitos do seu Cartão Expensify muitas vezes. Se tiver certeza de que os números estão corretos, entre em contato com a Concierge para resolver. Caso contrário, tente novamente mais tarde.',
         },
     },
     getPhysicalCard: {
@@ -2754,7 +2416,7 @@ ${amount} para ${merchant} - ${date}`,
         shipCard: 'Enviar cartão',
     },
     transferAmountPage: {
-        transfer: (amount: string) => `Transferir${amount ? ` ${amount}` : ''}`,
+        transfer: ({amount}: TransferParams) => `Transferir${amount ? ` ${amount}` : ''}`,
         instant: 'Instantâneo (Cartão de débito)',
         instantSummary: (rate: string, minAmount: string) => `Taxa de ${rate}% (mínimo de ${minAmount})`,
         ach: '1–3 dias úteis (Conta bancária)',
@@ -2781,46 +2443,14 @@ ${amount} para ${merchant} - ${date}`,
         defaultPaymentMethod: 'Padrão',
         bankAccountLastFour: (lastFour: string) => `Conta bancária • ${lastFour}`,
     },
-    agentsPage: {
-        title: 'Agentes',
-        subtitle: 'Crie agentes para gerenciar seu fluxo de trabalho. Pule o trabalho manual e ganhe horas de volta no seu dia.',
-        newAgent: 'Novo agente',
-        emptyAgents: {title: 'Nenhum agente criado', subtitle: 'Pare de fazer tudo manualmente. Instrua um agente e economize muito tempo.'},
-        error: {
-            genericAdd: 'Houve um problema ao adicionar este agente',
-            genericUpdate: 'Ocorreu um problema ao atualizar este agente',
-            updateName: 'Ocorreu um problema ao atualizar o nome deste agente',
-            updatePrompt: 'Ocorreu um problema ao atualizar as instruções deste agente',
-            updateAvatar: 'Ocorreu um problema ao atualizar o avatar deste agente',
-        },
-    },
-    addAgentPage: {
-        title: 'Novo agente',
-        agentName: 'Nome do agente',
-        instructions: 'Escrever instruções personalizadas',
-        createAgent: 'Criar agente',
-        editAvatar: 'Trocar avatar',
-        defaultAgentName: (displayName: string) => `Agente de ${displayName}`,
-        defaultPrompt:
-            'Rejeite despesas relacionadas a jogos de azar, cinema ou outros motivos claramente não relacionados ao negócio.\n\nLembre o usuário de sempre incluir uma imagem do recibo em que a gorjeta fique clara.\n\nAprove o relatório se ele for muito semelhante a relatórios anteriores do mesmo usuário.\n\nRejeite relatórios com mais de US$ 500 em despesas de viagem.',
-    },
-    editAgentPage: {
-        title: 'Editar agente',
-        agentName: 'Nome do agente',
-        instructions: 'Escrever instruções personalizadas',
-        chatWithAgent: 'Conversar com o agente',
-        copilotIntoAccount: 'Copilot na conta',
-        deleteAgent: 'Excluir agente',
-        deleteAgentTitle: 'Excluir agente?',
-        deleteAgentMessage: 'Tem certeza de que quer excluir este agente? Essa ação não pode ser desfeita.',
-    },
-    editAgentAvatarPage: {title: 'Editar avatar'},
-    editAgentNamePage: {title: 'Nome do agente'},
-    editAgentPromptPage: {title: 'Escrever instruções personalizadas', error: {emptyPrompt: 'Insira as instruções para o seu agente.'}},
     expenseRulesPage: {
         title: 'Regras de despesas',
+        subtitle: 'Essas regras serão aplicadas às suas despesas. Se você enviar para um espaço de trabalho, as regras desse espaço de trabalho poderão substituí-las.',
         findRule: 'Encontrar regra',
-        emptyRules: {title: 'Ainda não há regras', subtitle: 'Adicione uma regra para automatizar o relatório de despesas.'},
+        emptyRules: {
+            title: 'Você não criou nenhuma regra',
+            subtitle: 'Adicione uma regra para automatizar o relatório de despesas.',
+        },
         changes: {
             billableUpdate: (value: boolean) => `Atualizar despesa ${value ? 'faturável' : 'não faturável'}`,
             categoryUpdate: (value: string) => `Atualizar categoria para “${value}”`,
@@ -2861,7 +2491,6 @@ ${amount} para ${merchant} - ${date}`,
             deleteSinglePrompt: 'Tem certeza de que deseja excluir esta regra?',
             deleteMultiplePrompt: 'Tem certeza de que deseja excluir essas regras?',
         },
-        subtitle: 'Essas regras serão aplicadas às suas despesas.',
     },
     preferencesPage: {
         appSection: {
@@ -2889,12 +2518,11 @@ ${amount} para ${merchant} - ${date}`,
         },
     },
     reportDetailsPage: {
-        inWorkspace: (policyName: string) => `em ${policyName}`,
+        inWorkspace: ({policyName}: ReportPolicyNameParams) => `em ${policyName}`,
         generatingPDF: 'Gerar PDF',
         waitForPDF: 'Aguarde enquanto geramos o PDF.',
         errorPDF: 'Ocorreu um erro ao tentar gerar seu PDF',
         successPDF: 'Seu PDF foi gerado! Se ele não foi baixado automaticamente, use o botão abaixo.',
-        goToRoom: 'Ir para a sala',
     },
     reportDescriptionPage: {
         roomDescription: 'Descrição do quarto',
@@ -2904,7 +2532,7 @@ ${amount} para ${merchant} - ${date}`,
     groupChat: {
         lastMemberTitle: 'Atenção!',
         lastMemberWarning: 'Como você é a última pessoa aqui, sair tornará este chat inacessível para todos os membros. Tem certeza de que deseja sair?',
-        defaultReportName: (displayName: string) => `Chat em grupo de ${displayName}`,
+        defaultReportName: ({displayName}: ReportArchiveReasonsClosedParams) => `Chat em grupo de ${displayName}`,
     },
     languagePage: {
         language: 'Idioma',
@@ -2923,25 +2551,19 @@ ${amount} para ${merchant} - ${date}`,
                 label: 'Usar configurações do dispositivo',
             },
         },
-        highContrastMode: 'Modo de alto contraste',
-        enableHighContrast: 'Ativar alto contraste',
-        disableHighContrast: 'Desativar alto contraste',
         chooseThemeBelowOrSync: 'Escolha um tema abaixo ou sincronize com as configurações do seu dispositivo.',
     },
     termsOfUse: {
         terms: `<muted-text-xs>Ao entrar, você concorda com os <a href="${CONST.OLD_DOT_PUBLIC_URLS.TERMS_URL}">Termos de Serviço</a> e a <a href="${CONST.OLD_DOT_PUBLIC_URLS.PRIVACY_URL}">Privacidade</a>.</muted-text-xs>`,
-        license: `A transmissão de dinheiro é fornecida por ${CONST.WALLET.PROGRAM_ISSUERS.EXPENSIFY_PAYMENTS} (ID NMLS:2017010) de acordo com suas <a href="${CONST.OLD_DOT_PUBLIC_URLS.LICENSES_URL}">licenças</a>.`,
+        license: `<muted-text-xs>A transmissão de dinheiro é fornecida por ${CONST.WALLET.PROGRAM_ISSUERS.EXPENSIFY_PAYMENTS} (NMLS ID:2017010) de acordo com suas <a href="${CONST.OLD_DOT_PUBLIC_URLS.LICENSES_URL}">licenças</a>.</muted-text-xs>`,
     },
     validateCodeForm: {
         magicCodeNotReceived: 'Não recebeu um código mágico?',
-        avoidScamsMessage: '<strong>Evite golpes. Não compartilhe seu código com ninguém.</strong> Nossa equipe nunca ligará, enviará SMS ou e-mail para pedir esse código.',
         enterAuthenticatorCode: 'Insira seu código do autenticador',
         enterRecoveryCode: 'Insira seu código de recuperação',
         requiredWhen2FAEnabled: 'Obrigatório quando a 2FA estiver ativada',
         requestNewCode: ({timeRemaining}: {timeRemaining: string}) => `Solicite um novo código em <a>${timeRemaining}</a>`,
         requestNewCodeAfterErrorOccurred: 'Solicitar um novo código',
-        timeRemainingAnnouncement: ({timeRemaining}) => `Tempo restante: ${timeRemaining} ${timeRemaining === 1 ? 'segundo' : 'segundos'}`,
-        timeExpiredAnnouncement: 'O tempo expirou',
         error: {
             pleaseFillMagicCode: 'Insira seu código mágico',
             incorrectMagicCode: 'Código mágico incorreto ou inválido. Tente novamente ou solicite um novo código.',
@@ -2972,7 +2594,6 @@ ${amount} para ${merchant} - ${date}`,
         phoneOrEmail: 'Telefone ou e-mail',
         error: {
             invalidFormatEmailLogin: 'O e-mail inserido é inválido. Corrija o formato e tente novamente.',
-            agentSignInBlocked: 'Contas de agente não podem ser acessadas diretamente. Para usar um agente, entre com a sua própria conta e acesse-o via Copilot.',
         },
         cannotGetAccountDetails: 'Não foi possível recuperar os detalhes da conta. Tente entrar novamente.',
         loginForm: 'Formulário de login',
@@ -2989,39 +2610,28 @@ ${amount} para ${merchant} - ${date}`,
         },
         getStarted: 'Começar',
         whatsYourName: 'Qual é o seu nome?',
-        peopleYouMayKnow: 'Veja se sua equipe está no Expensify',
-        workspaceYouMayJoin: (domain: string, email: string) => `Digite o código enviado para ${email} para verificar se alguém de ${domain} tem um workspace ao qual você possa se juntar.`,
+        peopleYouMayKnow: 'Pessoas que você talvez conheça já estão aqui! Verifique seu e-mail para se juntar a elas.',
+        workspaceYouMayJoin: ({domain, email}: WorkspaceYouMayJoin) => `Alguém de ${domain} já criou um workspace. Insira o código mágico enviado para ${email}.`,
         joinAWorkspace: 'Participar de um workspace',
-        listOfWorkspaces: 'Aqui está a lista de espaços de trabalho que você pode entrar.',
-        skipForNow: 'Pular por enquanto',
-        workspaceMemberList: (employeeCount: number, policyOwner: string) => `${employeeCount} membro${employeeCount > 1 ? 's' : ''} • ${policyOwner}`,
+        listOfWorkspaces: 'Aqui está a lista de espaços de trabalho que você pode entrar. Não se preocupe, você sempre pode entrar neles mais tarde, se preferir.',
+        workspaceMemberList: ({employeeCount, policyOwner}: WorkspaceMemberList) => `${employeeCount} membro${employeeCount > 1 ? 's' : ''} • ${policyOwner}`,
         whereYouWork: 'Onde você trabalha?',
         errorSelection: 'Selecione uma opção para continuar',
         purpose: {
             title: 'O que você quer fazer hoje?',
             errorContinue: 'Pressione continuar para concluir a configuração',
             errorBackButton: 'Conclua as perguntas de configuração para começar a usar o app',
-            [CONST.ONBOARDING_CHOICES.EMPLOYER]: 'Enviar despesas ao meu empregador',
+            [CONST.ONBOARDING_CHOICES.EMPLOYER]: 'Ser reembolsado pelo meu empregador',
             [CONST.ONBOARDING_CHOICES.MANAGE_TEAM]: 'Gerenciar as despesas da minha equipe',
-            [CONST.ONBOARDING_CHOICES.TRACK_BUSINESS]: 'Controlar despesas do meu negócio',
-            [CONST.ONBOARDING_CHOICES.TRACK_PERSONAL]: 'Organizar meus gastos pessoais',
+            [CONST.ONBOARDING_CHOICES.PERSONAL_SPEND]: 'Controle e planeje despesas',
+            [CONST.ONBOARDING_CHOICES.CHAT_SPLIT]: 'Converse e divida despesas com amigos',
             [CONST.ONBOARDING_CHOICES.LOOKING_AROUND]: 'Outra coisa',
         },
-        personalTrackGoal: {
-            title: 'O que você quer acompanhar?',
-            [CONST.ONBOARDING_PERSONAL_TRACK_GOALS.INVESTMENT_TRACKING]: 'Custos de um imóvel para investimento',
-            [CONST.ONBOARDING_PERSONAL_TRACK_GOALS.HOUSEHOLD_TRACKING]: 'Despesas domésticas',
-            [CONST.ONBOARDING_PERSONAL_TRACK_GOALS.SIDEPROJECT_TRACKING]: 'Despesas de projeto paralelo',
-            [CONST.ONBOARDING_PERSONAL_TRACK_GOALS.SOMETHING_ELSE]: 'Outra coisa',
-            somethingElsePlaceholder: 'O que você está rastreando?',
-        },
         employees: {
             title: 'Quantos funcionários você tem?',
-            [CONST.ONBOARDING_COMPANY_SIZE.MICRO_SMALL]: '1–4 funcionários',
-            [CONST.ONBOARDING_COMPANY_SIZE.MICRO_MEDIUM]: '5–10 funcionários',
-            [CONST.ONBOARDING_COMPANY_SIZE.MICRO]: '1-10 funcionários',
+            [CONST.ONBOARDING_COMPANY_SIZE.MICRO]: '1–10 funcionários',
             [CONST.ONBOARDING_COMPANY_SIZE.SMALL]: '11–50 funcionários',
-            [CONST.ONBOARDING_COMPANY_SIZE.MEDIUM_SMALL]: '51 a 100 funcionários',
+            [CONST.ONBOARDING_COMPANY_SIZE.MEDIUM_SMALL]: '51–100 funcionários',
             [CONST.ONBOARDING_COMPANY_SIZE.MEDIUM]: '101–1.000 funcionários',
             [CONST.ONBOARDING_COMPANY_SIZE.LARGE]: 'Mais de 1.000 funcionários',
         },
@@ -3049,19 +2659,16 @@ ${amount} para ${merchant} - ${date}`,
         },
         workEmailValidation: {
             title: 'Verifique seu e-mail de trabalho',
-            magicCodeSent: (workEmail: string | undefined) => `Insira o código mágico enviado para ${workEmail}. Ele deve chegar em um ou dois minutos.`,
+            magicCodeSent: ({workEmail}: WorkEmailResendCodeParams) => `Insira o código mágico enviado para ${workEmail}. Ele deve chegar em um ou dois minutos.`,
         },
         workEmailValidationError: {
             publicEmail: 'Insira um e-mail de trabalho válido de um domínio privado, por exemplo: mitch@company.com',
-            sameAsSignupEmail: 'Insira um e-mail diferente daquele com que você se cadastrou',
             offline: 'Não foi possível adicionar seu e-mail profissional, pois você parece estar offline',
         },
         mergeBlockScreen: {
             title: 'Não foi possível adicionar o e-mail de trabalho',
-            subtitle: (workEmail: string | undefined) =>
+            subtitle: ({workEmail}: WorkEmailMergingBlockedParams) =>
                 `Não foi possível adicionar ${workEmail}. Tente novamente mais tarde em Configurações ou converse com o Concierge para obter orientação.`,
-            workAccountClosedSubtitle:
-                'A conta de trabalho associada a este e-mail foi encerrada. Entre em contato com o administrador da sua empresa para reativá-la ou inscreva-se com um e-mail diferente.',
         },
         tasks: {
             testDriveAdminTask: {
@@ -3092,7 +2699,7 @@ ${amount} para ${merchant} - ${date}`,
             },
             createTestDriveAdminWorkspaceTask: {
                 title: ({workspaceConfirmationLink}) => `[Crie](${workspaceConfirmationLink}) um espaço de trabalho`,
-                description: 'Crie um workspace e configure as definições com a ajuda do seu executivo de contas!',
+                description: 'Crie um workspace e configure as definições com a ajuda do seu especialista de configuração!',
             },
             createWorkspaceTask: {
                 title: ({workspaceSettingsLink}) => `Crie um [espaço de trabalho](${workspaceSettingsLink})`,
@@ -3124,7 +2731,7 @@ ${amount} para ${merchant} - ${date}`,
                 description: dedent(`
                     *Envie uma despesa* inserindo um valor ou digitalizando um recibo.
 
-                    1. Clique no botão *+*.
+                    1. Clique no botão ${CONST.CUSTOM_EMOJIS.GLOBAL_CREATE}.
                     2. Escolha *Criar despesa*.
                     3. Insira um valor ou digitalize um recibo.
                     4. Adicione o e-mail ou telefone da sua chefia.
@@ -3138,7 +2745,7 @@ ${amount} para ${merchant} - ${date}`,
                 description: dedent(`
                     *Envie uma despesa* inserindo um valor ou escaneando um recibo.
 
-                    1. Clique no botão *+*.
+                    1. Clique no botão ${CONST.CUSTOM_EMOJIS.GLOBAL_CREATE}.
                     2. Escolha *Criar despesa*.
                     3. Insira um valor ou escaneie um recibo.
                     4. Confirme os detalhes.
@@ -3152,7 +2759,7 @@ ${amount} para ${merchant} - ${date}`,
                 description: dedent(`
                     *Acompanhe uma despesa* em qualquer moeda, com ou sem recibo.
 
-                    1. Clique no botão *+*.
+                    1. Clique no botão ${CONST.CUSTOM_EMOJIS.GLOBAL_CREATE}.
                     2. Escolha *Criar despesa*.
                     3. Informe um valor ou escaneie um recibo.
                     4. Escolha seu espaço *pessoal*.
@@ -3174,8 +2781,13 @@ ${amount} para ${merchant} - ${date}`,
                         4. Encontre ${integrationName}.
                         5. Clique em *Connect*.
 
-                        [Leve-me para a contabilidade](${workspaceAccountingLink}).
-                    `),
+${
+    integrationName && CONST.connectionsVideoPaths[integrationName]
+        ? `[Leve-me para a contabilidade](${workspaceAccountingLink}).
+
+                        ![Conectar ao ${integrationName}](${CONST.CLOUDFRONT_URL}/${CONST.connectionsVideoPaths[integrationName]})`
+        : `[Leve-me para a contabilidade](${workspaceAccountingLink}).`
+}`),
             },
             connectCorporateCardTask: {
                 title: ({corporateCardLink}) => `Conecte [seus cartões corporativos](${corporateCardLink})`,
@@ -3197,10 +2809,10 @@ ${amount} para ${merchant} - ${date}`,
                         *Convide sua equipe* para o Expensify para que possam começar a registrar despesas hoje.
 
                         1. Clique em *Workspaces*.
-                        2. Selecione seu workspace.
+                        2. Selecione o seu workspace.
                         3. Clique em *Members* > *Invite member*.
                         4. Insira e-mails ou números de telefone.
-                        5. Adicione uma mensagem de convite personalizada, se quiser!
+                        5. Adicione uma mensagem personalizada ao convite, se quiser!
 
                         [Leve-me para os membros do workspace](${workspaceMembersLink}).
                     `),
@@ -3217,16 +2829,16 @@ ${amount} para ${merchant} - ${date}`,
                 title: ({workspaceTagsLink}) => `Configurar [tags](${workspaceTagsLink})`,
                 description: ({workspaceMoreFeaturesLink}) =>
                     dedent(`
-                        Use tags para adicionar detalhes extras de despesas, como projetos, clientes, locais e departamentos. Se você precisar de vários níveis de tags, é possível fazer upgrade para o plano Control.
+                        Use tags para adicionar mais detalhes às despesas, como projetos, clientes, locais e departamentos. Se você precisar de vários níveis de tags, poderá fazer upgrade para o plano Control.
 
-                        1. Clique em *Espaços de trabalho*.
-                        2. Selecione seu espaço de trabalho.
-                        3. Clique em *Mais recursos*.
+                        1. Clique em *Workspaces*.
+                        2. Selecione seu workspace.
+                        3. Clique em *More features*.
                         4. Ative *Tags*.
-                        5. Vá até *Tags* no editor do espaço de trabalho.
-                        6. Clique em *+ Adicionar tag* para criar as suas.
+                        5. Acesse *Tags* no editor do workspace.
+                        6. Clique em *+ Add tag* para criar suas próprias tags.
 
-                        [Levar-me para Mais recursos](${workspaceMoreFeaturesLink}).
+                        [Leve-me para more features](${workspaceMoreFeaturesLink}).
 
                     `),
             },
@@ -3249,7 +2861,7 @@ ${amount} para ${merchant} - ${date}`,
                 description: dedent(`
                     *Inicie um chat* com qualquer pessoa usando o e-mail ou número de telefone dela.
 
-                    1. Clique no botão *+*.
+                    1. Clique no botão ${CONST.CUSTOM_EMOJIS.GLOBAL_CREATE}.
                     2. Escolha *Iniciar chat*.
                     3. Digite um e-mail ou número de telefone.
 
@@ -3263,7 +2875,7 @@ ${amount} para ${merchant} - ${date}`,
                 description: dedent(`
                     *Divida despesas* com uma ou mais pessoas.
 
-                    1. Clique no botão *+*.
+                    1. Clique no botão ${CONST.CUSTOM_EMOJIS.GLOBAL_CREATE}.
                     2. Escolha *Iniciar chat*.
                     3. Digite e-mails ou números de telefone.
                     4. Clique no botão cinza *+* no chat > *Dividir despesa*.
@@ -3287,7 +2899,7 @@ ${amount} para ${merchant} - ${date}`,
                 description: dedent(`
                     Veja como criar um relatório:
 
-                    1. Clique no botão *+*.
+                    1. Clique no botão ${CONST.CUSTOM_EMOJIS.GLOBAL_CREATE}.
                     2. Escolha *Criar relatório*.
                     3. Clique em *Adicionar despesa*.
                     4. Adicione sua primeira despesa.
@@ -3309,16 +2921,19 @@ ${amount} para ${merchant} - ${date}`,
             onboardingManageTeamMessage: ({isOnboardingFlow = false}: {isOnboardingFlow?: boolean}) =>
                 isOnboardingFlow
                     ? dedent(`
-                        # Seu teste gratuito começou! Vamos fazer a configuração.
-                        👋 Olá, eu sou o executivo de contas da sua conta Expensify. Eu já criei um workspace para ajudar a gerenciar os recibos e despesas da sua equipe. Para aproveitar ao máximo seus 30 dias de teste gratuito, é só seguir as etapas restantes de configuração abaixo!
+                        # Sua avaliação gratuita começou! Vamos fazer a configuração.
+                        👋 Olá! Sou seu especialista de configuração do Expensify. Já criei um workspace para ajudar a gerenciar os recibos e despesas da sua equipe. Para aproveitar ao máximo seus 30 dias de avaliação gratuita, basta seguir as etapas de configuração restantes abaixo!
                     `)
                     : dedent(`
-                        # Sua avaliação gratuita começou! Vamos configurar tudo.
-                        👋 Oi, eu sou o executivo de contas da sua conta Expensify. Agora que você criou um workspace, aproveite ao máximo seus 30 dias de avaliação gratuita seguindo as etapas abaixo!
+                        # Seu teste grátis começou! Vamos fazer a configuração.
+                        👋 Olá, sou seu especialista em configuração do Expensify. Agora que você criou um workspace, aproveite ao máximo seus 30 dias de teste grátis seguindo as etapas abaixo!
                     `),
-            onboardingTrackWorkspaceMessage: 'Para aproveitar ao máximo seus 30 dias de teste gratuito, siga as etapas restantes abaixo:',
+            onboardingTrackWorkspaceMessage:
+                '# Vamos configurar tudo para você\n👋 Olá! Sou o seu especialista de configuração do Expensify. Já criei um workspace para ajudar a gerenciar seus recibos e despesas. Para aproveitar ao máximo sua avaliação gratuita de 30 dias, basta seguir as etapas de configuração restantes abaixo!',
             onboardingChatSplitMessage: 'Dividir contas com amigos é tão fácil quanto enviar uma mensagem. Veja como.',
             onboardingAdminMessage: 'Saiba como gerenciar o workspace da sua equipe como administrador e enviar suas próprias despesas.',
+            onboardingLookingAroundMessage:
+                'A Expensify é mais conhecida por gerenciamento de despesas, viagens e cartões corporativos, mas fazemos muito mais do que isso. Me diga no que você tem interesse e vou ajudar você a começar.',
             onboardingTestDriveReceiverMessage: '*Você ganhou 3 meses grátis! Comece abaixo.*',
         },
         workspace: {
@@ -3329,7 +2944,7 @@ ${amount} para ${merchant} - ${date}`,
                 descriptionTwo: 'Classifique e categorize despesas',
                 descriptionThree: 'Criar e compartilhar relatórios',
             },
-            price: (price?: string) => `Experimente grátis por 30 dias e depois faça upgrade por apenas <strong>${price ?? 'US$5'}/usuário/mês</strong>.`,
+            price: 'Experimente grátis por 30 dias e depois faça upgrade por apenas <strong>US$5/usuário/mês</strong>.',
             createWorkspace: 'Criar espaço de trabalho',
         },
         confirmWorkspace: {
@@ -3340,8 +2955,6 @@ ${amount} para ${merchant} - ${date}`,
             title: 'Convidar membros',
             subtitle: 'Adicione sua equipe ou convide seu contador. Quanto mais gente, melhor!',
         },
-        workEmail2FAError: 'Este login é uma conta existente com a Autenticação em Duas Etapas (2FA) ativada.',
-        singleSignOnError: 'Este login é de uma conta existente com SSO/SAML ativado.',
     },
     featureTraining: {
         doNotShowAgain: 'Não mostrar isso novamente',
@@ -3361,7 +2974,6 @@ ${amount} para ${merchant} - ${date}`,
         enterPhoneNumber: 'Qual é o seu número de telefone?',
         personalDetails: 'Dados pessoais',
         privateDataMessage: 'Esses dados são usados para viagens e pagamentos. Eles nunca são exibidos no seu perfil público.',
-        basicDetails: 'Detalhes básicos',
         legalName: 'Nome legal',
         legalFirstName: 'Primeiro nome legal',
         legalLastName: 'Sobrenome legal',
@@ -3370,18 +2982,17 @@ ${amount} para ${merchant} - ${date}`,
             dateShouldBeBefore: (dateString: string) => `A data deve ser anterior a ${dateString}`,
             dateShouldBeAfter: (dateString: string) => `A data deve ser posterior a ${dateString}`,
             hasInvalidCharacter: 'O nome pode incluir apenas caracteres latinos',
-            cannotIncludeCommaOrSemicolon: 'O nome não pode conter vírgula ou ponto e vírgula',
             incorrectZipFormat: (zipFormat?: string) => `Formato de CEP incorreto${zipFormat ? `Formato aceitável: ${zipFormat}` : ''}`,
             invalidPhoneNumber: `Verifique se o número de telefone é válido (por exemplo, ${CONST.EXAMPLE_PHONE_NUMBER})`,
         },
     },
     resendValidationForm: {
         linkHasBeenResent: 'Link foi reenviado',
-        weSentYouMagicSignInLink: (login: string, loginType: string) => `Enviei um link mágico de acesso para ${login}. Verifique seu ${loginType} para entrar.`,
+        weSentYouMagicSignInLink: ({login, loginType}: WeSentYouMagicSignInLinkParams) => `Enviei um link mágico de acesso para ${login}. Verifique seu ${loginType} para entrar.`,
         resendLink: 'Reenviar link',
     },
     unlinkLoginForm: {
-        toValidateLogin: (primaryLogin: string, secondaryLogin: string) => `Para validar ${secondaryLogin}, reenvie o código mágico nas Configurações da conta de ${primaryLogin}.`,
+        toValidateLogin: ({primaryLogin, secondaryLogin}: ToValidateLoginParams) => `Para validar ${secondaryLogin}, reenvie o código mágico nas Configurações da conta de ${primaryLogin}.`,
         noLongerHaveAccess: (primaryLogin: string) => `Se você não tiver mais acesso a ${primaryLogin}, desvincule suas contas.`,
         unlink: 'Desvincular',
         linkSent: 'Link enviado!',
@@ -3438,12 +3049,14 @@ ${amount} para ${merchant} - ${date}`,
     },
     welcomeSignUpForm: {
         join: 'Participar',
-        marketingSMSConsent: 'Concordo em receber mensagens de texto de marketing da Expensify',
     },
     detailsPage: {
         localTime: 'Hora local',
     },
-    newChatPage: {startGroup: 'Iniciar grupo', addToGroup: 'Adicionar ao grupo', addUserToGroup: (username: string) => `Adicionar ${username} ao grupo`},
+    newChatPage: {
+        startGroup: 'Iniciar grupo',
+        addToGroup: 'Adicionar ao grupo',
+    },
     yearPickerPage: {
         year: 'Ano',
         selectYear: 'Selecione um ano',
@@ -3486,18 +3099,17 @@ ${amount} para ${merchant} - ${date}`,
             custom: 'Personalizado',
         },
         untilTomorrow: 'Até amanhã',
-        untilTime: (time: string) => `Até ${time}`,
+        untilTime: ({time}: UntilTimeParams) => `Até ${time}`,
         date: 'Data',
         time: 'Hora',
         clearAfter: 'Limpar após',
         whenClearStatus: 'Quando devemos limpar seu status?',
+        vacationDelegate: 'Delegado de férias',
         setVacationDelegate: `Defina um delegado de férias para aprovar relatórios em seu nome enquanto você estiver fora do escritório.`,
-        cannotSetVacationDelegate: `Você não pode definir um delegado de férias porque atualmente é o delegado dos seguintes membros:`,
-        addVacationDelegate: 'Adicionar delegado de férias',
         vacationDelegateError: 'Ocorreu um erro ao atualizar seu delegado de férias.',
-        asVacationDelegate: (nameOrEmail: string) => `como delegado de férias de ${nameOrEmail}`,
-        toAsVacationDelegate: (submittedToName: string, vacationDelegateName: string) => `para ${submittedToName} como delegado(a) de férias de ${vacationDelegateName}`,
-        vacationDelegateWarning: (nameOrEmail: string) =>
+        asVacationDelegate: ({nameOrEmail}: VacationDelegateParams) => `como delegado de férias de ${nameOrEmail}`,
+        toAsVacationDelegate: ({submittedToName, vacationDelegateName}: SubmittedToVacationDelegateParams) => `para ${submittedToName} como delegado(a) de férias de ${vacationDelegateName}`,
+        vacationDelegateWarning: ({nameOrEmail}: VacationDelegateParams) =>
             `Você está atribuindo ${nameOrEmail} como seu delegado de férias. Elu ainda não está em todos os seus espaços de trabalho. Se você decidir continuar, será enviado um e-mail a todos os admins dos seus espaços de trabalho para que elu seja adicionado.`,
     },
     stepCounter: ({step, total, text}: StepCounterParams) => {
@@ -3526,35 +3138,23 @@ ${amount} para ${merchant} - ${date}`,
         connectManually: 'Conectar manualmente',
         desktopConnection: 'Observação: para conectar com Chase, Wells Fargo, Capital One ou Bank of America, clique aqui para concluir este processo em um navegador.',
         yourDataIsSecure: 'Seus dados estão seguros',
-        toGetStarted: 'Adicione uma conta bancária para reembolsar despesas, emitir Cartões Expensify, receber pagamentos de faturas e pagar contas, tudo em um só lugar.',
+        toGetStarted: 'Adicione uma conta bancária para reembolsar despesas, emitir cartões Expensify, receber pagamentos de faturas e pagar contas, tudo em um só lugar.',
         plaidBodyCopy: 'Dê aos seus funcionários uma forma mais fácil de pagar — e ser reembolsados — pelas despesas da empresa.',
         checkHelpLine: 'Seu número de roteamento e número da conta podem ser encontrados em um cheque dessa conta.',
-        bankAccountPurposeTitle: 'O que você quer fazer com sua conta bancária?',
-        getReimbursed: 'Ser reembolsado',
-        getReimbursedDescription: 'Pelo empregador ou outros',
-        makePayments: 'Fazer pagamentos',
-        makePaymentsDescription: 'Pague despesas ou emita Cartões Expensify',
         hasPhoneLoginError: (contactMethodRoute: string) =>
             `Para conectar uma conta bancária, <a href="${contactMethodRoute}">adicione um e-mail como seu login principal</a> e tente novamente. Você pode adicionar seu número de telefone como login secundário.`,
         hasBeenThrottledError: 'Ocorreu um erro ao adicionar sua conta bancária. Aguarde alguns minutos e tente novamente.',
-        hasCurrencyError: (workspaceRoute: string) =>
+        hasCurrencyError: ({workspaceRoute}: WorkspaceRouteParams) =>
             `Ops! Parece que a moeda do seu workspace está definida como diferente de USD. Para continuar, acesse as <a href="${workspaceRoute}">configurações do seu workspace</a>, defina-a como USD e tente novamente.`,
         bbaAdded: 'Conta bancária empresarial adicionada!',
         bbaAddedDescription: 'Está pronto para ser usado para pagamentos.',
-        lockedBankAccount: 'Conta bancária bloqueada',
-        unlockBankAccount: 'Desbloquear conta bancária',
-        youCantPayThis: `Você não pode pagar este relatório porque tem uma <a href="${CONST.UNLOCK_BANK_ACCOUNT_HELP_URL}">conta bancária bloqueada</a>. Toque abaixo e o Concierge ajudará com os próximos passos para desbloqueá-la.`,
-        htmlUnlockMessage: (maskedAccountNumber: string) =>
-            `<h1>Expensify Business Bank Account ${maskedAccountNumber}</h1><p>Obrigado por enviar uma solicitação para desbloquear sua conta bancária. Solicitações de saque podem ser rejeitadas por insuficiência de fundos ou se a conta bancária não foi habilitada para débito direto. Analisaremos seu caso e entraremos em contato se precisarmos de mais informações para resolver este problema.</p>`,
-        textUnlockMessage: (maskedAccountNumber: string) =>
-            `Expensify Business Bank Account ${maskedAccountNumber}\nObrigado por enviar uma solicitação para desbloquear sua conta bancária. Solicitações de saque podem ser rejeitadas por insuficiência de fundos ou se a conta bancária não foi habilitada para débito direto. Analisaremos seu caso e entraremos em contato se precisarmos de mais informações para resolver este problema.`,
         error: {
             youNeedToSelectAnOption: 'Selecione uma opção para continuar',
             noBankAccountAvailable: 'Desculpe, não há nenhuma conta bancária disponível',
             noBankAccountSelected: 'Escolha uma conta',
             taxID: 'Insira um número de identificação fiscal válido',
             website: 'Insira um site válido',
-            zipCode: `Insira um CEP válido usando o formato: ${COMMON_CONST.COUNTRY_ZIP_REGEX_DATA.US.samples}`,
+            zipCode: `Insira um CEP válido usando o formato: ${CONST.COUNTRY_ZIP_REGEX_DATA.US.samples}`,
             phoneNumber: 'Insira um número de telefone válido',
             email: 'Insira um endereço de e-mail válido',
             companyName: 'Insira um nome comercial válido',
@@ -3581,7 +3181,7 @@ ${amount} para ${merchant} - ${date}`,
             fullName: 'Insira um nome completo válido',
             ownershipPercentage: 'Insira um número de porcentagem válido',
             deletePaymentBankAccount:
-                'Essa conta bancária não pode ser excluída porque é usada para pagamentos do Cartão Expensify. Se ainda assim quiser excluir essa conta, entre em contato com o Concierge.',
+                'Esta conta bancária não pode ser excluída porque é usada para pagamentos do Expensify Card. Se ainda assim quiser excluir esta conta, entre em contato com a Concierge.',
             sameDepositAndWithdrawalAccount: 'As contas de depósito e saque são as mesmas.',
         },
     },
@@ -3596,11 +3196,6 @@ ${amount} para ${merchant} - ${date}`,
         confirmationStepHeader: 'Verifique suas informações.',
         confirmationStepSubHeader: 'Verifique os detalhes abaixo e marque a caixa de termos para confirmar.',
         toGetStarted: 'Adicione uma conta bancária pessoal para receber reembolsos, pagar faturas ou ativar a Carteira Expensify.',
-        updatePersonalInfo: 'Atualizar conta bancária',
-        updatePersonalInfoFailure: 'Não foi possível atualizar as informações da conta bancária. Por favor, tente novamente mais tarde.',
-        updateSuccessTitle: 'Conta bancária atualizada!',
-        updateSuccessHeader: 'Conta bancária atualizada',
-        updateSuccessMessage: 'Parabéns, sua conta bancária está configurada e pronta para receber reembolsos.',
     },
     addPersonalBankAccountPage: {
         enterPassword: 'Insira a senha do Expensify',
@@ -3628,8 +3223,8 @@ ${amount} para ${merchant} - ${date}`,
     messages: {
         errorMessageInvalidPhone: `Insira um número de telefone válido sem parênteses ou traços. Se você estiver fora dos EUA, inclua o código do seu país (por exemplo, ${CONST.EXAMPLE_PHONE_NUMBER}).`,
         errorMessageInvalidEmail: 'E-mail inválido',
-        userIsAlreadyMember: (login: string, name: string) => `${login} já é membro de ${name}`,
-        userIsAlreadyAnAdmin: (login: string, name: string) => `${login} já é administrador(a) de ${name}`,
+        userIsAlreadyMember: ({login, name}: UserIsAlreadyMemberParams) => `${login} já é membro de ${name}`,
+        userIsAlreadyAnAdmin: ({login, name}: UserIsAlreadyMemberParams) => `${login} já é administrador(a) de ${name}`,
     },
     onfidoStep: {
         acceptTerms: 'Ao continuar com o pedido para ativar sua Expensify Wallet, você confirma que leu, compreende e aceita',
@@ -3675,7 +3270,7 @@ ${amount} para ${merchant} - ${date}`,
         haveReadAndAgreePlain: 'Li e concordo em receber divulgações eletrônicas.',
         haveReadAndAgree: `Li e concordo em receber <a href="${CONST.ELECTRONIC_DISCLOSURES_URL}">comunicados eletrônicos</a>.`,
         agreeToThePlain: 'Eu concordo com o contrato de Privacidade e Carteira.',
-        agreeToThe: (walletAgreementUrl: string) =>
+        agreeToThe: ({walletAgreementUrl}: WalletAgreementParams) =>
             `Concordo com a <a href="${CONST.OLD_DOT_PUBLIC_URLS.PRIVACY_URL}">Política de Privacidade</a> e com o <a href="${walletAgreementUrl}">Contrato da carteira</a>.`,
         enablePayments: 'Ativar pagamentos',
         monthlyFee: 'Taxa mensal',
@@ -3687,7 +3282,7 @@ ${amount} para ${merchant} - ${date}`,
         checkTheBoxes: 'Marque as caixas abaixo.',
         agreeToTerms: 'Concorde com os termos e você estará pronto para começar!',
         shortTermsForm: {
-            expensifyPaymentsAccount: (walletProgram: string) => `A Carteira Expensify é emitida por ${walletProgram}.`,
+            expensifyPaymentsAccount: ({walletProgram}: WalletProgramParams) => `A Carteira Expensify é emitida por ${walletProgram}.`,
             perPurchase: 'Por compra',
             atmWithdrawal: 'Saque em caixa eletrônico',
             cashReload: 'Recarga em dinheiro',
@@ -3701,7 +3296,7 @@ ${amount} para ${merchant} - ${date}`,
             generalInfo: `Para obter informações gerais sobre contas pré-pagas, visite <a href="${CONST.CFPB_PREPAID_URL}">${CONST.TERMS.CFPB_PREPAID}</a>.`,
             conditionsDetails: `Para detalhes e condições de todas as tarifas e serviços, acesse <a href="${CONST.FEES_URL}">${CONST.FEES_URL}</a> ou ligue para +1 833-400-0904.`,
             electronicFundsWithdrawalInstant: 'Débito eletrônico em conta (instantâneo)',
-            electronicFundsInstantFeeMin: (amount: string) => `(mín. ${amount})`,
+            electronicFundsInstantFeeMin: ({amount}: TermsParams) => `(mín. ${amount})`,
         },
         longTermsForm: {
             listOfAllFees: 'Uma lista de todas as tarifas da Carteira Expensify',
@@ -3721,7 +3316,7 @@ ${amount} para ${merchant} - ${date}`,
             electronicFundsInstantDetails: (percentage: string, amount: string) =>
                 'Há uma taxa para transferir fundos da sua Carteira Expensify para o seu cartão de débito vinculado usando a opção de transferência instantânea. Essa transferência geralmente é concluída em alguns minutos.' +
                 `A taxa é de ${percentage}% do valor da transferência (com uma taxa mínima de ${amount}).`,
-            fdicInsuranceBancorp: (amount: string) =>
+            fdicInsuranceBancorp: ({amount}: TermsParams) =>
                 `Seus fundos são elegíveis para o seguro do FDIC. Seus fundos serão mantidos ou transferidos para ${CONST.WALLET.PROGRAM_ISSUERS.BANCORP_BANK}, uma instituição segurada pelo FDIC.` +
                 `Uma vez lá, seus fundos serão segurados em até ${amount} pelo FDIC caso o ${CONST.WALLET.PROGRAM_ISSUERS.BANCORP_BANK} venha a falir, se requisitos específicos de seguro de depósito forem atendidos e seu cartão estiver registrado. Consulte ${CONST.TERMS.FDIC_PREPAID} para mais detalhes.`,
             contactExpensifyPayments: `Entre em contato com ${CONST.WALLET.PROGRAM_ISSUERS.EXPENSIFY_PAYMENTS} ligando para +1 833-400-0904, por e-mail em ${CONST.EMAIL.CONCIERGE} ou acessando ${CONST.NEW_EXPENSIFY_URL}.`,
@@ -3730,7 +3325,7 @@ ${amount} para ${merchant} - ${date}`,
             automated: 'Automatizado',
             liveAgent: 'Atendente ao vivo',
             instant: 'Instantâneo',
-            electronicFundsInstantFeeMin: (amount: string) => `Mín. ${amount}`,
+            electronicFundsInstantFeeMin: ({amount}: TermsParams) => `Mín. ${amount}`,
         },
     },
     activateStep: {
@@ -4015,10 +3610,6 @@ ${amount} para ${merchant} - ${date}`,
         youCanChange: 'Você pode mudar a moeda do seu workspace em seu',
         findCountry: 'Encontrar país',
         selectCountry: 'Selecione o país',
-        error: {
-            connectToWorkspace: (workspaceRoute: string) =>
-                `Esta conta bancária deve ser vinculada a um espaço de trabalho. Vá para <a href="${workspaceRoute}">Espaços de trabalho</a>, selecione seu espaço de trabalho e navegue até Fluxos de trabalho > Pagamentos > Adicionar conta bancária.`,
-        },
     },
     bankInfoStep: {
         whatAreYour: 'Quais são os dados da sua conta bancária empresarial?',
@@ -4062,7 +3653,7 @@ ${amount} para ${merchant} - ${date}`,
         pleaseUpload: 'Envie abaixo documentação adicional para nos ajudar a verificar sua identidade como diretor(a) da empresa.',
         enterSignerInfo: 'Insira as informações do assinante',
         thisStep: 'Esta etapa foi concluída',
-        isConnecting: (bankAccountLastFour: string | undefined, currency: string | undefined) =>
+        isConnecting: ({bankAccountLastFour, currency}: SignerInfoMessageParams) =>
             `está conectando uma conta bancária comercial em ${currency} terminada em ${bankAccountLastFour} ao Expensify para pagar funcionários em ${currency}. A próxima etapa exige as informações de assinatura de um diretor.`,
         error: {
             emailsMustBeDifferent: 'Os e-mails devem ser diferentes',
@@ -4074,7 +3665,7 @@ ${amount} para ${merchant} - ${date}`,
         regulationRequiresUs: 'A regulamentação exige que verifiquemos a identidade de qualquer pessoa física que possua mais de 25% do negócio.',
         iAmAuthorized: 'Estou autorizado(a) a usar a conta bancária empresarial para gastos do negócio.',
         iCertify: 'Eu certifico que as informações fornecidas são verdadeiras e corretas.',
-        iAcceptTheTermsAndConditions: `Eu aceito os <a href="https://www.corpay.com/cross-border/terms">termos e condições</a>.`,
+        iAcceptTheTermsAndConditions: `Eu aceito os <a href="https://cross-border.corpay.com/tc/">termos e condições</a>.`,
         iAcceptTheTermsAndConditionsAccessibility: 'Eu aceito os termos e condições.',
         accept: 'Aceitar e adicionar conta bancária',
         iConsentToThePrivacyNotice: 'Eu concordo com o <a href="https://payments.corpay.com/compliance">aviso de privacidade</a>.',
@@ -4106,37 +3697,6 @@ ${amount} para ${merchant} - ${date}`,
         weTake: 'Levamos sua segurança a sério. Ative a autenticação em duas etapas (2FA) agora para adicionar uma camada extra de proteção à sua conta.',
         secure: 'Proteja sua conta',
     },
-    documentsStep: {
-        beforeYouGo: 'Antes de continuar, precisamos de alguns documentos para verificar algumas informações',
-        subheader: 'Verificação',
-        verificationFailed: 'A verificação falhou, então precisaremos de documentos adicionais para verificar você e sua empresa',
-        taxIDVerification: 'Verificação de ID fiscal',
-        taxIDVerificationDescription: dedent(`
-        Envie um dos seguintes arquivos:
-        • Carta de atribuição de TIN/EIN do IRS
-        • Confirmação de solicitação de TIN/EIN do IRS (normalmente contém "Congratulations! The EIN has been successfully assigned")
-        • Carta de isenção fiscal do IRS com o nome da empresa e o EIN`),
-        nameChangeDocument: 'Documento de alteração de nome',
-        nameChangeDocumentDescription: 'Se o nome da sua empresa mudou desde a solicitação do TIN/EIN, precisamos deste documento para verificar o número de identificação fiscal informado',
-        companyAddressVerification: 'Verificação de endereço da empresa',
-        companyAddressVerificationDescription: dedent(`
-        Envie um dos seguintes arquivos:
-        • Conta recente de serviços públicos com nome e endereço da empresa
-        • Extrato bancário com nome e endereço da empresa
-        • Contrato de locação atual incluindo a página de assinatura com nome e endereço atual da empresa
-        • Apólice ou declaração de seguro com nome e endereço da empresa
-        • Documento de atribuição de TIN com nome e endereço da empresa`),
-        userAddressVerification: 'Verificação de endereço',
-        userAddressVerificationDescription: dedent(`
-        Envie um dos seguintes arquivos:
-        • Título de eleitor
-        • Carteira de motorista
-        • Extrato bancário
-        • Conta de serviços públicos`),
-        userDOBVerification: 'Verificação de data de nascimento',
-        userDOBVerificationDescription: 'Envie um documento de identidade emitido nos EUA',
-        finishViaChat: 'Finalizar pelo chat',
-    },
     reimbursementAccountLoadingAnimation: {
         oneMoment: 'Um momento',
         explanationLine: 'Estamos analisando suas informações. Você poderá continuar com as próximas etapas em breve.',
@@ -4275,15 +3835,15 @@ ${amount} para ${merchant} - ${date}`,
             flightSeatChanged: (airlineCode: string) => `Sua atribuição de assento no voo ${airlineCode} foi alterada.`,
             flightSeatCancelled: (airlineCode: string) => `Sua marcação de assento no voo ${airlineCode} foi removida.`,
             paymentDeclined: 'O pagamento da sua reserva de voo falhou. Tente novamente, por favor.',
-            bookingCancelledByTraveler: (type: string, id = '') => `Você cancelou sua reserva de ${type} ${id}.`,
-            bookingCancelledByVendor: (type: string, id = '') => `O fornecedor cancelou sua reserva de ${type} ${id}.`,
-            bookingRebooked: (type: string, id = '') => `Sua reserva de ${type} foi remarcada. Nova confirmação nº:${id}.`,
-            bookingUpdated: (type: string) => `Sua reserva de ${type} foi atualizada. Revise os novos detalhes no itinerário.`,
+            bookingCancelledByTraveler: ({type, id = ''}: TravelTypeParams) => `Você cancelou sua reserva de ${type} ${id}.`,
+            bookingCancelledByVendor: ({type, id = ''}: TravelTypeParams) => `O fornecedor cancelou sua reserva de ${type} ${id}.`,
+            bookingRebooked: ({type, id = ''}: TravelTypeParams) => `Sua reserva de ${type} foi remarcada. Nova confirmação nº:${id}.`,
+            bookingUpdated: ({type}: TravelTypeParams) => `Sua reserva de ${type} foi atualizada. Revise os novos detalhes no itinerário.`,
             railTicketRefund: (origin: string, destination: string, startDate: string) =>
                 `Sua passagem de trem de ${origin} → ${destination} em ${startDate} foi reembolsada. Um crédito será processado.`,
             railTicketExchange: (origin: string, destination: string, startDate: string) => `Sua passagem de trem de ${origin} → ${destination} em ${startDate} foi trocada.`,
             railTicketUpdate: (origin: string, destination: string, startDate: string) => `Sua passagem de trem de ${origin} → ${destination} em ${startDate} foi atualizada.`,
-            defaultUpdate: (type: string) => `Sua reserva de ${type} foi atualizada.`,
+            defaultUpdate: ({type}: TravelTypeParams) => `Sua reserva de ${type} foi atualizada.`,
         },
         flightTo: 'Voo para',
         trainTo: 'Trem para',
@@ -4300,13 +3860,13 @@ ${amount} para ${merchant} - ${date}`,
             workflows: 'Fluxos de trabalho',
             workspace: 'Espaço de trabalho',
             findWorkspace: 'Encontrar espaço de trabalho',
-            findRoom: 'Encontrar sala',
             edit: 'Editar espaço de trabalho',
             enabled: 'Ativado',
             disabled: 'Desativado',
             everyone: 'Todos',
             delete: 'Excluir workspace',
             settings: 'Configurações',
+            reimburse: 'Reembolsos',
             categories: 'Categorias',
             tags: 'Tags',
             customField1: 'Campo personalizado 1',
@@ -4316,7 +3876,6 @@ ${amount} para ${merchant} - ${date}`,
             reportFields: 'Campos do relatório',
             reportTitle: 'Título do relatório',
             reportField: 'Campo de relatório',
-            invoiceFields: 'Campos de fatura',
             taxes: 'Impostos',
             bills: 'Contas',
             invoices: 'Faturas',
@@ -4343,10 +3902,6 @@ ${amount} para ${merchant} - ${date}`,
             defaultNote: `Recibos enviados para ${CONST.EMAIL.RECEIPTS} aparecerão neste workspace.`,
             deleteConfirmation: 'Tem certeza de que deseja excluir este workspace?',
             deleteWithCardsConfirmation: 'Tem certeza de que deseja excluir este workspace? Isso removerá todos os feeds de cartão e cartões atribuídos.',
-            deleteOpenExpensifyCardsError: 'Sua empresa ainda possui cartões Expensify ativos.',
-            outstandingBalanceWarning:
-                'Você tem um saldo pendente que precisa ser quitado antes de excluir seu último espaço de trabalho. Acesse as configurações de assinatura para resolver o pagamento.',
-            settleBalance: 'Ir para a assinatura',
             unavailable: 'Espaço de trabalho indisponível',
             memberNotFound: 'Membro não encontrado. Para convidar um novo membro para o workspace, use o botão de convite acima.',
             notAuthorized: `Você não tem acesso a esta página. Se estiver tentando entrar neste workspace, peça ao proprietário do workspace para adicioná-lo como membro. Outra coisa? Fale com ${CONST.EMAIL.CONCIERGE}.`,
@@ -4357,11 +3912,8 @@ ${amount} para ${merchant} - ${date}`,
             clearFilter: 'Limpar filtro',
             workspaceName: 'Nome do workspace',
             workspaceOwner: 'Proprietário',
-            keepMeAsAdmin: 'Manter-me como administrador',
             workspaceType: 'Tipo de workspace',
             workspaceAvatar: 'Avatar do workspace',
-            clientID: 'ID do cliente',
-            clientIDInputHint: 'Insira o identificador único do cliente',
             mustBeOnlineToViewMembers: 'Você precisa estar online para visualizar os membros deste workspace.',
             moreFeatures: 'Mais recursos',
             requested: 'Solicitado',
@@ -4380,7 +3932,7 @@ ${amount} para ${merchant} - ${date}`,
             appliedOnExport: 'Não importado para o Expensify, aplicado na exportação',
             shareNote: {
                 header: 'Compartilhe seu workspace com outras pessoas',
-                content: (adminsRoomLink: string) =>
+                content: ({adminsRoomLink}: WorkspaceShareNoteParams) =>
                     `Compartilhe este código QR ou copie o link abaixo para facilitar que membros solicitem acesso ao seu espaço de trabalho. Todas as solicitações para entrar no espaço de trabalho aparecerão na sala <a href="${adminsRoomLink}">${CONST.REPORT.WORKSPACE_CHAT_ROOMS.ADMINS}</a> para sua análise.`,
             },
             connectTo: ({connectionName}: ConnectionNameParams) => `Conectar a ${CONST.POLICY.CONNECTIONS.NAME_USER_FRIENDLY[connectionName]}`,
@@ -4395,20 +3947,12 @@ ${amount} para ${merchant} - ${date}`,
             memberAlternateText: 'Enviar e aprovar relatórios.',
             adminAlternateText: 'Gerencie relatórios e configurações do espaço de trabalho.',
             auditorAlternateText: 'Visualize e comente relatórios.',
-            roleName: (role?: string) => {
+            roleName: ({role}: OptionalParam<RoleNamesParams> = {}) => {
                 switch (role) {
                     case CONST.POLICY.ROLE.ADMIN:
-                        return 'Admin do workspace';
+                        return 'Admin';
                     case CONST.POLICY.ROLE.AUDITOR:
                         return 'Auditor';
-                    case CONST.POLICY.ROLE.EDITOR:
-                        return 'Editor';
-                    case CONST.POLICY.ROLE.CARD_ADMIN:
-                        return 'Administrador do cartão';
-                    case CONST.POLICY.ROLE.PEOPLE_ADMIN:
-                        return 'Admin de pessoas';
-                    case CONST.POLICY.ROLE.PAYMENTS_ADMIN:
-                        return 'Administrador de pagamentos';
                     case CONST.POLICY.ROLE.USER:
                         return 'Membro';
                     default:
@@ -4438,22 +3982,7 @@ ${amount} para ${merchant} - ${date}`,
             budgetFrequency: {monthly: 'mensal', yearly: 'anual'},
             budgetFrequencyUnit: {monthly: 'mês', yearly: 'ano'},
             budgetTypeForNotificationMessage: {tag: 'etiqueta', category: 'categoria'},
-            deepDiveExpensifyCard: `<muted-text-label>As transações do Cartão Expensify serão exportadas automaticamente para uma “Conta de Responsabilidade do Cartão Expensify” criada com <a href="${CONST.DEEP_DIVE_EXPENSIFY_CARD}">nossa integração</a>.</muted-text-label>`,
-            travelInvoicing: 'Exportar despesas de faturamento de viagens como',
-            travelInvoicingVendor: 'Fornecedor de viagem',
-            travelInvoicingPayableAccount: 'Conta a pagar de viagens',
-            hr: 'RH',
-            rooms: 'Salas',
-            findDomain: 'Encontrar domínio',
-            cardAdminAlternateText: 'Gerenciar cartões do workspace.',
-            peopleAdminAlternateText: 'Gerencie membros e fluxos de aprovação.',
-            paymentsAdminAlternateText: 'Gerencie pagamentos de fluxo de trabalho.',
-            readOnlyActionTitle: 'Calma aí...',
-            readOnlyActionPrompt: 'Sua função no workspace pode ver essas configurações, mas não pode editá-las.',
-        },
-        createdForClient: {
-            title: 'Você criou um espaço de trabalho para seu cliente!',
-            description: 'Ótimas notícias 🎉. Entre em contato conosco se precisarem de ajuda com a configuração.',
+            deepDiveExpensifyCard: `<muted-text-label>As transações do Expensify Card serão exportadas automaticamente para uma “Conta de Passivo do Expensify Card” criada com <a href="${CONST.DEEP_DIVE_EXPENSIFY_CARD}">nossa integração</a>.</muted-text-label>`,
         },
         receiptPartners: {
             uber: {
@@ -4517,7 +4046,7 @@ ${amount} para ${merchant} - ${date}`,
             exportDescription: 'Configure como os dados do Expensify são exportados para o QuickBooks Desktop.',
             date: 'Data de exportação',
             exportInvoices: 'Exportar faturas para',
-            exportExpensifyCard: 'Exportar transações do Cartão Expensify como',
+            exportExpensifyCard: 'Exportar transações do Expensify Card como',
             account: 'Conta',
             accountDescription: 'Escolha onde lançar os lançamentos contábeis.',
             accountsPayable: 'Contas a pagar',
@@ -4638,7 +4167,7 @@ ${amount} para ${merchant} - ${date}`,
             exportDescription: 'Configure como os dados do Expensify são exportados para o QuickBooks Online.',
             date: 'Data de exportação',
             exportInvoices: 'Exportar faturas para',
-            exportExpensifyCard: 'Exportar transações do Cartão Expensify como',
+            exportExpensifyCard: 'Exportar transações do Expensify Card como',
             exportDate: {
                 label: 'Data de exportação',
                 description: 'Use esta data ao exportar relatórios para o QuickBooks Online.',
@@ -4676,9 +4205,8 @@ ${amount} para ${merchant} - ${date}`,
             notConfigured: 'Não configurado',
             bankAccountDescription: 'Escolha de onde enviar os cheques.',
             creditCardAccount: 'Conta de cartão de crédito',
-            travelInvoicingDescription: 'As despesas de viagem serão exportadas como cobranças de cartão de crédito para a conta do QuickBooks Online especificada abaixo.',
             companyCardsLocationEnabledDescription:
-                'O QuickBooks Online não oferece suporte a locais em exportações de contas de fornecedor quando os locais são importados como tags. Como você tem locais importados como tags no seu workspace, essa opção de exportação não está disponível.',
+                'O QuickBooks Online não oferece suporte a locais nas exportações de contas de fornecedor. Como você ativou locais no seu workspace, esta opção de exportação não está disponível.',
             outOfPocketTaxEnabledDescription:
                 'QuickBooks Online não oferece suporte a impostos em exportações de lançamentos contábeis. Como você tem impostos ativados no seu espaço de trabalho, essa opção de exportação não está disponível.',
             outOfPocketTaxEnabledError: 'Lançamentos de diário não estão disponíveis quando os impostos estão ativados. Escolha uma opção de exportação diferente.',
@@ -4772,7 +4300,6 @@ ${amount} para ${merchant} - ${date}`,
             exportDeepDiveCompanyCard:
                 'As despesas exportadas serão lançadas como transações bancárias na conta bancária Xero abaixo, e as datas das transações corresponderão às datas no seu extrato bancário.',
             bankTransactions: 'Transações bancárias',
-            travelInvoicingDescription: 'As despesas de viagem serão exportadas como transações bancárias para a conta do Xero especificada abaixo.',
             xeroBankAccount: 'Conta bancária Xero',
             xeroBankAccountDescription: 'Escolha onde as despesas serão lançadas como transações bancárias.',
             exportExpensesDescription: 'Os relatórios serão exportados como uma conta de compra com a data e o status selecionados abaixo.',
@@ -4867,7 +4394,6 @@ ${amount} para ${merchant} - ${date}`,
                     [CONST.SAGE_INTACCT_NON_REIMBURSABLE_EXPENSE_TYPE.VENDOR_BILL]: 'Faturas de fornecedores',
                 },
             },
-            travelInvoicingDescription: 'As despesas de viagem serão exportadas como cobranças de cartão de crédito para a conta do Sage Intacct especificada abaixo.',
             creditCardAccount: 'Conta de cartão de crédito',
             defaultVendor: 'Fornecedor padrão',
             defaultVendorDescription: (isReimbursable: boolean) =>
@@ -4899,68 +4425,6 @@ ${amount} para ${merchant} - ${date}`,
                 },
             },
         },
-        certinia: {
-            title: 'Certinia',
-            titleFFA: 'Certinia (FFA)',
-            autoSyncDescription: 'O Expensify vai sincronizar automaticamente com a Certinia todos os dias.',
-            syncReimbursedReportsDescription:
-                'Com essa opção ativada, sempre que uma Fatura a Pagar for paga no FFA, o relatório correspondente no Expensify será marcado automaticamente como reembolsado.',
-            exportDescription: 'Configure como os dados do Expensify são exportados para o Certinia.',
-            payableInvoices: 'Faturas a Pagar',
-            exportStatus: {
-                label: 'Status da fatura a pagar',
-                values: {
-                    [CONST.CERTINIA_EXPORT_STATUS.APPROVED]: 'Concluir',
-                    [CONST.CERTINIA_EXPORT_STATUS.IN_PROGRESS]: 'Em andamento',
-                    [CONST.CERTINIA_EXPORT_STATUS.SUBMITTED]: 'Enviado',
-                },
-            },
-            exportDate: {
-                label: 'Data de vencimento da fatura',
-                values: {
-                    [CONST.CERTINIA_EXPORT_DATE.LAST_EXPENSE]: 'Data da última despesa',
-                    [CONST.CERTINIA_EXPORT_DATE.REPORT_SUBMITTED]: 'Data de envio do relatório',
-                    [CONST.CERTINIA_EXPORT_DATE.REPORT_EXPORTED]: 'Data de exportação',
-                },
-            },
-            exportReimbursable: {
-                label: 'Exportar despesas reembolsáveis como',
-                helperText: 'Despesas marcadas como reembolsáveis serão exportadas como faturas a pagar emitidas em nome do funcionário.',
-            },
-            exportNonReimbursable: {label: 'Exportar despesas não reembolsáveis como'},
-            noVendorsFound: 'Nenhum fornecedor encontrado',
-            noVendorsFoundDescription: 'Sincronize a conexão novamente depois que os fornecedores forem adicionados no Certinia.',
-            prerequisites: {
-                title: 'Antes de conectar',
-                installBundle: 'Para conexões FFA',
-                installBundleDescription: ({href, version}: {href: string; version: string}) =>
-                    `Instale o pacote do Expensify no Salesforce clicando neste link: <a href="${href}">Instalar FFA Expensify Bundle (Versão ${version})</a>`,
-                installBundleConfirm: 'Eu instalei o pacote',
-                setupContacts: 'Configurar usuário e contatos',
-                setupContactsBullet1:
-                    'Crie um Usuário e um Contato para você, caso eles ainda não existam no Certinia, certificando-se de que o e-mail corresponda ao seu e-mail principal no Expensify.',
-                setupContactsBullet2:
-                    'Crie contatos para cada funcionário que for enviar relatórios de despesas e para cada aprovador de relatórios. Certifique-se de que o e-mail de cada contato corresponda ao endereço de e-mail na conta Expensify do funcionário.',
-                setupContactsBullet3: 'Defina controles de permissão para o seu usuário para cada contato/recurso.',
-                setupContactsConfirm: 'Configurei o usuário e os contatos',
-                oauth: 'Entrar pelo Salesforce',
-                oauthDescription: 'Para concluir a configuração, você precisa entrar pelo Salesforce e pela Certinia.\n\nUse o botão abaixo para continuar.',
-                connectButton: 'Conectar ao Certinia',
-            },
-            import: {
-                chartOfAccounts: 'Plano de contas',
-                chartOfAccountsDescription: 'O plano de contas é importado para o Expensify como categorias.',
-                dimensionMapping: ({n}: {n: number}) => `Dimensão ${n}`,
-                dimensions: {dimension1: 'Dimensão 1', dimension2: 'Dimensão 2', dimension3: 'Dimensão 3', dimension4: 'Dimensão 4'},
-                doNotMap: 'Não mapear',
-                doNotMapSubtitle: 'Usar recurso de funcionário por padrão',
-                mappingTypes: {
-                    [CONST.CERTINIA_MAPPING_VALUE.DEFAULT]: 'Não mapear',
-                    [CONST.CERTINIA_MAPPING_VALUE.TAG]: 'Importado como tags',
-                    [CONST.CERTINIA_MAPPING_VALUE.REPORT_FIELD]: 'Importado como campos de relatório',
-                },
-            },
-        },
         netsuite: {
             subsidiary: 'Subsidiária',
             subsidiarySelectDescription: 'Escolha a subsidiária no NetSuite da qual você gostaria de importar dados.',
@@ -4975,8 +4439,8 @@ ${amount} para ${merchant} - ${date}`,
             journalPostingPreference: {
                 label: 'Preferência de lançamento de lançamentos contábeis',
                 values: {
-                    [CONST.NETSUITE_JOURNAL_POSTING_PREFERENCE.JOURNALS_POSTING_INDIVIDUAL_LINE]: 'Lançamento único para cada despesa',
-                    [CONST.NETSUITE_JOURNAL_POSTING_PREFERENCE.JOURNALS_POSTING_TOTAL_LINE]: 'Lançamento único e detalhado para cada relatório',
+                    [CONST.NETSUITE_JOURNAL_POSTING_PREFERENCE.JOURNALS_POSTING_INDIVIDUAL_LINE]: 'Lançamento único, detalhado, para cada relatório',
+                    [CONST.NETSUITE_JOURNAL_POSTING_PREFERENCE.JOURNALS_POSTING_TOTAL_LINE]: 'Lançamento único para cada despesa',
                 },
             },
             invoiceItem: {
@@ -5042,7 +4506,6 @@ ${amount} para ${merchant} - ${date}`,
 
                             Se quiser definir um fornecedor específico para cada cartão, vá em *Configurações > Domínios > Cartões Corporativos*.
                         `),
-                        travelDescription: 'As despesas de viagem serão exportadas como lançamentos contábeis para a conta NetSuite especificada abaixo.',
                     },
                 },
                 expenseReportDestinationConfirmDescription:
@@ -5186,7 +4649,7 @@ ${amount} para ${merchant} - ${date}`,
                 importCustomFields: {
                     chooseOptionBelow: 'Escolha uma opção abaixo:',
                     label: (importedTypes: string[]) => `Importado como ${importedTypes.join('e')}`,
-                    requiredFieldError: (fieldName: string) => `Insira o(a) ${fieldName}`,
+                    requiredFieldError: ({fieldName}: RequiredFieldParams) => `Insira o(a) ${fieldName}`,
                     customSegments: {
                         title: 'Segmentos/registros personalizados',
                         addText: 'Adicionar segmento/registro personalizado',
@@ -5239,7 +4702,7 @@ _Para instruções mais detalhadas, [visite nossa central de ajuda](${CONST.NETS
 
 _Para instruções mais detalhadas, [visite nossa central de ajuda](${CONST.NETSUITE_IMPORT.HELP_LINKS.CUSTOM_SEGMENTS})_.`,
                             customSegmentScriptIDTitle: 'Qual é o ID do script?',
-                            customSegmentScriptIDFooter: `Você pode encontrar os IDs de script de segmentos personalizados no NetSuite em:
+                            customSegmentScriptIDFooter: `Você pode encontrar os IDs de script de segmentos personalizados no NetSuite em: 
 
 1. *Customization > Lists, Records, & Fields > Custom Segments*.
 2. Clique em um segmento personalizado.
@@ -5260,7 +4723,7 @@ _Para instruções mais detalhadas, [visite nossa central de ajuda](${CONST.NETS
                             customRecordMappingTitle: 'Como este registro personalizado deve ser exibido no Expensify?',
                         },
                         errors: {
-                            uniqueFieldError: (fieldName: string) => `Já existe um segmento/registro personalizado com este ${fieldName?.toLowerCase()}`,
+                            uniqueFieldError: ({fieldName}: RequiredFieldParams) => `Já existe um segmento/registro personalizado com este ${fieldName?.toLowerCase()}`,
                         },
                     },
                     customLists: {
@@ -5327,7 +4790,7 @@ _Para instruções mais detalhadas, [visite nossa central de ajuda](${CONST.NETS
             employeeDefaultDescription: 'O departamento padrão do funcionário será aplicado às despesas dele no Sage Intacct, se existir.',
             displayedAsTagDescription: 'O departamento poderá ser selecionado para cada despesa individual no relatório de um funcionário.',
             displayedAsReportFieldDescription: 'A seleção de departamento será aplicada a todas as despesas no relatório de um funcionário.',
-            toggleImportTitle: (mappingTitle: string) => `Escolha como lidar com Sage Intacct <strong>${mappingTitle}</strong> no Expensify.`,
+            toggleImportTitle: ({mappingTitle}: ToggleImportTitleParams) => `Escolha como lidar com Sage Intacct <strong>${mappingTitle}</strong> no Expensify.`,
             expenseTypes: 'Tipos de despesa',
             expenseTypesDescription: 'Seus tipos de despesa do Sage Intacct serão importados para o Expensify como categorias.',
             accountTypesDescription: 'Seu plano de contas do Sage Intacct será importado para o Expensify como categorias.',
@@ -5367,14 +4830,10 @@ _Para instruções mais detalhadas, [visite nossa central de ajuda](${CONST.NETS
             free: 'Grátis',
             control: 'Controle',
             collect: 'Cobrar',
-            submit: 'Enviar',
         },
         companyCards: {
             addCards: 'Adicionar cartões',
             selectCards: 'Selecionar cartões',
-            fromOtherWorkspaces: 'De outros workspaces',
-            addWorkEmail: 'Adicione seu e-mail de trabalho',
-            addWorkEmailDescription: 'Adicione seu e-mail de trabalho para usar os feeds existentes de outros workspaces.',
             error: {
                 workspaceFeedsCouldNotBeLoadedTitle: 'Não foi possível carregar os feeds do cartão',
                 workspaceFeedsCouldNotBeLoadedMessage: 'Ocorreu um erro ao carregar os feeds de cartões do workspace. Tente novamente ou contate o seu administrador.',
@@ -5384,11 +4843,6 @@ _Para instruções mais detalhadas, [visite nossa central de ajuda](${CONST.NETS
             },
             addNewCard: {
                 other: 'Outro',
-                fileImport: 'Importar transações do arquivo',
-                createFileFeedHelpText: `<muted-text>Siga este <a href="${CONST.COMPANY_CARDS_CREATE_FILE_FEED_HELP_URL}">guia de ajuda</a> para importar as despesas do cartão corporativo!</muted-text>`,
-                companyCardLayoutName: 'Nome do layout do cartão corporativo',
-                cardLayoutNameRequired: 'O nome do layout do cartão corporativo é obrigatório',
-                useAdvancedFields: 'Usar campos avançados (não recomendado)',
                 cardProviders: {
                     gl1025: 'Cartões Corporativos American Express',
                     cdf: 'Cartões Comerciais Mastercard',
@@ -5467,26 +4921,6 @@ _Para instruções mais detalhadas, [visite nossa central de ajuda](${CONST.NETS
                     confirmText: 'Informar problema',
                     cancelText: 'Pular',
                 },
-                csvColumns: {
-                    cardNumber: 'Número do cartão',
-                    postedDate: 'Data',
-                    merchant: 'Estabelecimento',
-                    amount: 'Valor',
-                    currency: 'Moeda',
-                    ignore: 'Ignorar',
-                    originalTransactionDate: 'Data original da transação',
-                    originalAmount: 'Valor original',
-                    originalCurrency: 'Moeda original',
-                    comment: 'Comentário',
-                    category: 'Categoria',
-                    tag: 'Etiqueta',
-                },
-                csvErrors: {
-                    requiredColumns: (missingColumns: string) => `Atribua uma coluna a cada um dos atributos: ${missingColumns}.`,
-                    duplicateColumns: (duplicateColumn: string) => `Ops! Você mapeou um único campo ("${duplicateColumn}") para várias colunas. Revise e tente novamente.`,
-                },
-                fileImportDescription: 'Uma opção manual caso seu banco não possa enviar um feed.',
-                duplicateFeedModal: {title: 'Feed do cartão já conectado', prompt: 'Você não pode adicionar o mesmo feed de cartão ao mesmo workspace duas vezes.'},
             },
             statementCloseDate: {
                 [CONST.COMPANY_CARDS.STATEMENT_CLOSE_DATE.LAST_DAY_OF_MONTH]: 'Último dia do mês',
@@ -5505,7 +4939,7 @@ _Para instruções mais detalhadas, [visite nossa central de ajuda](${CONST.NETS
             chooseCard: 'Escolha um cartão',
             chooseCardFor: (assignee: string) =>
                 `Escolha um cartão para <strong>${assignee}</strong>. Não encontra o cartão que está procurando? <concierge-link>Conte para a gente.</concierge-link>`,
-            noActiveCards: 'Não há cartões ativos neste feed',
+            noActiveCards: 'Nenhum cartão ativo neste feed',
             somethingMightBeBroken:
                 '<muted-text><centered-text>Ou talvez algo esteja com problema. De qualquer forma, se tiver alguma dúvida, é só <concierge-link>entrar em contato com a Concierge</concierge-link>.</centered-text></muted-text>',
             chooseTransactionStartDate: 'Escolha uma data de início da transação',
@@ -5537,14 +4971,12 @@ _Para instruções mais detalhadas, [visite nossa central de ajuda](${CONST.NETS
                 flipAmountSign: 'Inverter sinal do valor',
                 importButton: 'Importar transações',
             },
-            deletedCard: 'Cartão excluído',
-            assignNewCards: {title: 'Atribuir novos cartões', description: 'Obtenha do seu banco os cartões mais recentes para atribuir'},
         },
         expensifyCard: {
             issueAndManageCards: 'Emita e gerencie seus Cartões Expensify',
             getStartedIssuing: 'Comece emitindo seu primeiro cartão virtual ou físico.',
             verificationInProgress: 'Verificação em andamento...',
-            verifyingTheDetails: 'Estamos verificando alguns detalhes. O Concierge vai avisar você quando os Cartões Expensify estiverem prontos para serem emitidos.',
+            verifyingTheDetails: 'Estamos verificando alguns detalhes. A Concierge avisará quando os Cartões Expensify estiverem prontos para serem emitidos.',
             disclaimer:
                 'O Cartão Comercial Expensify Visa® é emitido pelo The Bancorp Bank, N.A., membro FDIC, de acordo com uma licença da Visa U.S.A. Inc. e pode não ser aceito em todos os estabelecimentos que aceitam cartões Visa. Apple® e o logotipo da Apple® são marcas registradas da Apple Inc., registradas nos EUA e em outros países. App Store é uma marca de serviço da Apple Inc. Google Play e o logotipo do Google Play são marcas registradas da Google LLC.',
             euUkDisclaimer:
@@ -5556,8 +4988,8 @@ _Para instruções mais detalhadas, [visite nossa central de ajuda](${CONST.NETS
             lastFour: 'Últimos 4',
             limit: 'Limite',
             currentBalance: 'Saldo atual',
-            currentBalanceDescription: 'O saldo atual é a soma de todas as transações lançadas do Cartão Expensify que ocorreram desde a última data de liquidação.',
-            balanceWillBeSettledOn: (settlementDate: string) => `O saldo será liquidado em ${settlementDate}`,
+            currentBalanceDescription: 'O saldo atual é a soma de todas as transações lançadas no cartão Expensify que ocorreram desde a última data de liquidação.',
+            balanceWillBeSettledOn: ({settlementDate}: SettlementDateParams) => `O saldo será liquidado em ${settlementDate}`,
             settleBalance: 'Quitar saldo',
             cardLimit: 'Limite do cartão',
             remainingLimit: 'Limite restante',
@@ -5565,27 +4997,26 @@ _Para instruções mais detalhadas, [visite nossa central de ajuda](${CONST.NETS
             remainingLimitDescription:
                 'Levamos em conta vários fatores ao calcular seu limite restante: seu tempo como cliente, as informações comerciais fornecidas durante o cadastro e o dinheiro disponível na conta bancária da sua empresa. Seu limite restante pode variar diariamente.',
             earnedCashback: 'Cashback',
-            earnedCashbackDescription: 'O saldo de cashback é baseado nos gastos mensais liquidados do Cartão Expensify no seu workspace.',
+            earnedCashbackDescription: 'O saldo de cashback é baseado nos gastos mensais liquidados com o Cartão Expensify em seu workspace.',
             issueNewCard: 'Emitir novo cartão',
             finishSetup: 'Concluir configuração',
             chooseBankAccount: 'Escolher conta bancária',
-            chooseExistingBank: 'Escolha uma conta bancária empresarial existente para pagar o saldo do seu Cartão Expensify ou adicione uma nova conta bancária',
+            chooseExistingBank: 'Escolha uma conta bancária comercial existente para pagar o saldo do seu Expensify Card ou adicione uma nova conta bancária',
             accountEndingIn: 'Conta com final',
             addNewBankAccount: 'Adicionar uma nova conta bancária',
             settlementAccount: 'Conta de liquidação',
             settlementAccountDescription: 'Escolha uma conta para pagar o saldo do seu Cartão Expensify.',
-            settlementAccountInfo: (reconciliationAccountSettingsLink: string, accountNumber: string) =>
+            settlementAccountInfo: ({reconciliationAccountSettingsLink, accountNumber}: SettlementAccountInfoParams) =>
                 `Certifique-se de que esta conta corresponda à sua <a href="${reconciliationAccountSettingsLink}">conta de Conciliação</a> (${accountNumber}) para que a Conciliação Contínua funcione corretamente.`,
             settlementFrequency: 'Frequência de liquidação',
-            settlementFrequencyDescription: 'Escolha com que frequência você vai pagar o saldo do seu Cartão Expensify.',
+            settlementFrequencyDescription: 'Escolha com que frequência você pagará o saldo do seu Expensify Card.',
             settlementFrequencyInfo: 'Se quiser mudar para liquidação mensal, você precisará conectar sua conta bancária via Plaid e ter um histórico de saldo positivo de 90 dias.',
-            applyCashbackToBill: 'Aplicar reembolso à minha fatura do Expensify',
-            applyCashbackToBillDescription: 'O reembolso do Cartão Expensify será usado para o pagamento da sua fatura do Expensify.',
             frequency: {
                 daily: 'Diariamente',
                 monthly: 'Mensal',
             },
             cardDetails: 'Detalhes do cartão',
+            cardPending: ({name}: {name: string}) => `O cartão está atualmente pendente e será emitido quando a conta de ${name} for validada.`,
             virtual: 'Virtual',
             physical: 'Físico',
             deactivate: 'Desativar cartão',
@@ -5602,12 +5033,12 @@ _Para instruções mais detalhadas, [visite nossa central de ajuda](${CONST.NETS
             changeCardMonthlyLimitTypeWarning: (limit: number | string) =>
                 `Se você alterar o tipo de limite deste cartão para Mensal, novas transações serão recusadas porque o limite mensal de ${limit} já foi atingido.`,
             addShippingDetails: 'Adicionar detalhes de envio',
-            issuedCard: (assignee: string) => `emitiu um Cartão Expensify para ${assignee}! O cartão chegará em 2-3 dias úteis.`,
+            issuedCard: (assignee: string) => `emitiu um Cartão Expensify para ${assignee}! O cartão chegará em 2–3 dias úteis.`,
             issuedCardNoShippingDetails: (assignee: string) => `emitiu um Cartão Expensify para ${assignee}! O cartão será enviado assim que os dados de envio forem confirmados.`,
-            issuedCardVirtual: (assignee: string, link: string) => `emitiu um Cartão Expensify virtual para ${assignee}! O ${link} já pode ser usado imediatamente.`,
-            addedShippingDetails: (assignee: string) => `${assignee} adicionou os detalhes de envio. O Cartão Expensify chegará em 2-3 dias úteis.`,
-            replacedCard: (assignee: string) => `${assignee} substituiu o Cartão Expensify. O novo cartão chegará em 2-3 dias úteis.`,
-            replacedVirtualCard: (assignee: string, link: string) => `${assignee} substituiu o cartão virtual Cartão Expensify! O ${link} já pode ser usado.`,
+            issuedCardVirtual: (assignee: string, link: string) => `emitiu um Cartão Expensify virtual para ${assignee}! O ${link} pode ser usado imediatamente.`,
+            addedShippingDetails: (assignee: string) => `${assignee} adicionou os detalhes de envio. O Expensify Card chegará em 2–3 dias úteis.`,
+            replacedCard: (assignee: string) => `${assignee} substituiu o cartão Expensify. O novo cartão chegará em 2–3 dias úteis.`,
+            replacedVirtualCard: (assignee: string, link: string) => `${assignee} substituiu o cartão virtual Expensify! O ${link} já pode ser usado.`,
             card: 'cartão',
             replacementCard: 'cartão de substituição',
             verifyingHeader: 'Verificando',
@@ -5615,15 +5046,11 @@ _Para instruções mais detalhadas, [visite nossa central de ajuda](${CONST.NETS
             verifyingBankAccount: 'Verificando conta bancária...',
             verifyingBankAccountDescription: 'Aguarde enquanto confirmamos se esta conta pode ser usada para emitir Cartões Expensify.',
             bankAccountVerified: 'Conta bancária verificada!',
-            bankAccountVerifiedDescription: 'Agora você pode emitir Cartões Expensify para os membros do seu workspace.',
+            bankAccountVerifiedDescription: 'Agora você pode emitir Expensify Cards para os membros do seu workspace.',
             oneMoreStep: 'Mais um passo...',
             oneMoreStepDescription: 'Parece que precisamos verificar sua conta bancária manualmente. Vá até o Concierge, onde as instruções estão esperando por você.',
             gotIt: 'Entendi',
             goToConcierge: 'Ir para o Concierge',
-            exportAsCSV: 'Exportar como CSV',
-            csvColumnType: 'Tipo',
-            csvColumnLimitType: 'Tipo de limite',
-            csvColumnLimit: 'Limite',
         },
         categories: {
             deleteCategories: 'Excluir categorias',
@@ -5642,10 +5069,10 @@ _Para instruções mais detalhadas, [visite nossa central de ajuda](${CONST.NETS
             needCategoryForExportToIntegration: (connectionName: string) => `Todas as despesas devem ser categorizadas para serem exportadas para ${connectionName}.`,
             subtitle: 'Tenha uma visão melhor de onde o dinheiro está sendo gasto. Use nossas categorias padrão ou adicione as suas.',
             emptyCategories: {
-                title: 'Ainda não há categorias',
+                title: 'Você não criou nenhuma categoria',
                 subtitle: 'Adicione uma categoria para organizar seus gastos.',
-                subtitleWithAccounting: (accountingPageURL: string, canManage = true) =>
-                    `<muted-text><centered-text>Suas categorias estão sendo importadas de uma conexão de contabilidade.${canManage ? ` Vá até <a href="${accountingPageURL}">contabilidade</a> para fazer qualquer alteração.` : ''}</centered-text></muted-text>`,
+                subtitleWithAccounting: (accountingPageURL: string) =>
+                    `<muted-text><centered-text>Suas categorias estão sendo importadas de uma conexão de contabilidade. Vá até <a href="${accountingPageURL}">contabilidade</a> para fazer qualquer alteração.</centered-text></muted-text>`,
             },
             updateFailureMessage: 'Ocorreu um erro ao atualizar a categoria, tente novamente',
             createFailureMessage: 'Ocorreu um erro ao criar a categoria, tente novamente.',
@@ -5700,9 +5127,6 @@ _Para instruções mais detalhadas, [visite nossa central de ajuda](${CONST.NETS
             travel: {
                 title: 'Viagens',
                 subtitle: 'Reserve, gerencie e reconcilie todas as viagens de negócios da sua empresa.',
-                disableTravelTitle: 'Desative primeiro o faturamento de viagens',
-                disableTravelPrompt: 'O faturamento de viagens está ativado para este workspace. Desative-o antes de desativar o Travel.',
-                disableTravelButton: 'Ir para as configurações de Viagem',
                 getStarted: {
                     title: 'Comece a usar o Expensify Travel',
                     subtitle: 'Só precisamos de mais algumas informações sobre sua empresa e você estará pronto para decolar.',
@@ -5714,15 +5138,9 @@ _Para instruções mais detalhadas, [visite nossa central de ajuda](${CONST.NETS
                     ctaText: 'Solicitação enviada',
                 },
                 bookOrManageYourTrip: {
-                    title: 'Reserva de viagem',
-                    subtitle: 'Parabéns! Você já está pronto para reservar e gerenciar viagens neste workspace.',
-                    ctaText: 'Gerenciar viagens',
-                },
-                settings: {
-                    autoAddTripName: {
-                        title: 'Adicionar nomes de viagem às despesas',
-                        subtitle: 'Adicione automaticamente os nomes das viagens às descrições das despesas para viagens reservadas no Expensify.',
-                    },
+                    title: 'Reserve ou gerencie sua viagem',
+                    subtitle: 'Use o Expensify Travel para obter as melhores ofertas de viagem e gerenciar todas as suas despesas de negócios em um só lugar.',
+                    ctaText: 'Reservar ou gerenciar',
                 },
                 travelInvoicing: {
                     travelBookingSection: {
@@ -5730,58 +5148,30 @@ _Para instruções mais detalhadas, [visite nossa central de ajuda](${CONST.NETS
                         subtitle: 'Parabéns! Agora você está pronto para reservar e gerenciar viagens neste workspace.',
                         manageTravelLabel: 'Gerenciar viagens',
                     },
-                    travelInvoicingSection: {
-                        title: 'Faturamento de viagens',
+                    centralInvoicingSection: {
+                        title: 'Faturamento centralizado',
                         subtitle: 'Centralize todos os gastos de viagem em uma fatura mensal em vez de pagar no momento da compra.',
                         learnHow: 'Saiba como.',
                         subsections: {
                             currentTravelSpendLabel: 'Gasto atual com viagens',
-                            currentTravelSpendPaymentQueued: (amount: string) => `O pagamento de ${amount} está na fila e será processado em breve.`,
                             currentTravelSpendCta: 'Pagar saldo',
                             currentTravelLimitLabel: 'Limite de viagem atual',
                             settlementAccountLabel: 'Conta de liquidação',
                             settlementFrequencyLabel: 'Frequência de liquidação',
                             settlementFrequencyDescription:
                                 'Com que frequência o Expensify vai debitar da sua conta bancária empresarial para liquidar as transações recentes do Expensify Travel.',
-                            monthlySpendLimitLabel: 'Limite de gastos mensal por membro',
-                            monthlySpendLimitDescription: 'O valor máximo que cada membro pode gastar em viagens por mês.',
-                            reduceLimitTitle: 'Reduzir o limite de gastos com viagens?',
-                            reduceLimitWarning: 'Se você reduzir o limite, os membros que já gastaram mais do que esse valor não poderão fazer novas reservas de viagem até o próximo mês.',
-                            provisioningError:
-                                'Não foi possível provisionar alguns dos membros do seu workspace para faturamento de viagens. Tente novamente mais tarde ou entre em contato com o Concierge para obter ajuda.',
                         },
                     },
-                    disableModal: {
-                        title: 'Desativar faturamento de viagens?',
-                        body: 'Próximas reservas de hotel e aluguel de carro podem precisar ser refeitas com um método de pagamento diferente para evitar cancelamento.',
-                        confirm: 'Desativar',
-                    },
-                    outstandingBalanceModal: {
-                        title: 'Não é possível desativar o faturamento de viagens',
-                        body: 'Você ainda tem um saldo de viagem pendente. Pague esse saldo primeiro.',
-                        confirm: 'Entendi',
-                    },
-                    payBalanceModal: {
-                        title: (amount: string) => `Pagar saldo de ${amount}?`,
-                        body: 'O pagamento será colocado em fila e processado em breve. Essa ação não poderá ser desfeita depois de iniciada.',
-                    },
-                    exportToPDF: 'Exportar para PDF',
-                    exportToCSV: 'Exportar para CSV',
-                    selectDateRangeError: 'Selecione um intervalo de datas para exportar',
-                    invalidDateRangeError: 'A data de início deve ser anterior à data de término',
-                    enabled: 'Faturamento de Viagem ativado!',
-                    enabledDescription: 'Todos os gastos de viagem neste workspace agora serão centralizados em uma fatura mensal.',
                 },
-                personalDetailsDescription: 'Para reservar viagens, insira seu nome legal exatamente como consta no documento de identificação emitido pelo governo.',
             },
             expensifyCard: {
                 title: 'Cartão Expensify',
                 subtitle: 'Obtenha insights e controle sobre os gastos.',
-                disableCardTitle: 'Desativar Cartão Expensify',
-                disableCardPrompt: 'Você não pode desativar o Cartão Expensify porque ele já está em uso. Fale com o Concierge para saber os próximos passos.',
+                disableCardTitle: 'Desativar Expensify Card',
+                disableCardPrompt: 'Você não pode desativar o Expensify Card porque ele já está em uso. Fale com o Concierge para saber os próximos passos.',
                 disableCardButton: 'Converse com o Concierge',
                 feed: {
-                    title: 'Peça o Cartão Expensify',
+                    title: 'Obtenha o Cartão Expensify',
                     subTitle: 'Otimize as despesas da sua empresa e economize até 50% na sua fatura do Expensify, além de:',
                     features: {
                         cashBack: 'Cashback em todas as compras nos EUA',
@@ -5826,10 +5216,7 @@ _Para instruções mais detalhadas, [visite nossa central de ajuda](${CONST.NETS
                 updateCard: 'Atualizar cartão',
                 unassignCard: 'Remover cartão',
                 unassign: 'Desatribuir',
-                unassignCardDescription: 'Desvincular este cartão excluirá todas as transações não enviadas.',
-                removeCard: 'Remover cartão',
-                remove: 'Remover',
-                removeCardDescription: 'Remover este cartão excluirá todas as transações não enviadas.',
+                unassignCardDescription: 'Desatribuir este cartão removerá todas as transações em relatórios em rascunho da conta do titular do cartão.',
                 assignCard: 'Atribuir cartão',
                 cardFeedName: 'Nome do feed do cartão',
                 cardFeedNameDescription: 'Dê um nome exclusivo ao feed do cartão para diferenciá-lo dos outros.',
@@ -5861,9 +5248,9 @@ _Para instruções mais detalhadas, [visite nossa central de ajuda](${CONST.NETS
                 noAccountsFound: 'Nenhuma conta encontrada',
                 defaultCard: 'Cartão padrão',
                 downgradeTitle: `Não é possível fazer downgrade do espaço de trabalho`,
-                downgradeSubTitle: `Este workspace não pode ser rebaixado porque vários feeds de cartão estão conectados (excluindo Cartões Expensify). Por favor, <a href="#">mantenha apenas um feed de cartão</a> para continuar.`,
+                downgradeSubTitle: `Este espaço de trabalho não pode ser rebaixado porque vários feeds de cartão estão conectados (exceto Expensify Cards). Por favor, <a href="#">mantenha apenas um feed de cartão</a> para continuar.`,
                 noAccountsFoundDescription: (connection: string) => `Adicione a conta em ${connection} e sincronize a conexão novamente`,
-                expensifyCardBannerTitle: 'Peça o Cartão Expensify',
+                expensifyCardBannerTitle: 'Obtenha o Cartão Expensify',
                 expensifyCardBannerSubtitle: 'Aproveite cashback em todas as compras nos EUA, até 50% de desconto na sua fatura da Expensify, cartões virtuais ilimitados e muito mais.',
                 expensifyCardBannerLearnMoreButton: 'Saiba mais',
                 statementCloseDateTitle: 'Data de fechamento do extrato',
@@ -5873,7 +5260,7 @@ _Para instruções mais detalhadas, [visite nossa central de ajuda](${CONST.NETS
                 title: 'Fluxos de trabalho',
                 subtitle: 'Configure como os gastos são aprovados e pagos.',
                 disableApprovalPrompt:
-                    'Os Cartões Expensify deste workspace atualmente dependem de aprovações para definir seus Smart Limits. Altere os tipos de limite de quaisquer Cartões Expensify com Smart Limits antes de desativar as aprovações.',
+                    'Os Cartões Expensify deste workspace atualmente dependem de aprovação para definir seus Limites Inteligentes. Ajuste os tipos de limite de quaisquer Cartões Expensify com Limites Inteligentes antes de desativar as aprovações.',
             },
             invoices: {
                 title: 'Faturas',
@@ -5918,7 +5305,7 @@ _Para instruções mais detalhadas, [visite nossa central de ajuda](${CONST.NETS
             workflowWarningModal: {
                 featureEnabledTitle: 'Não tão rápido...',
                 featureEnabledText:
-                    'Os Cartões Expensify neste workspace dependem de fluxos de aprovação para definir seus Limites Inteligentes.\n\nAltere os tipos de limite de qualquer cartão com Limites Inteligentes antes de desativar os fluxos de trabalho.',
+                    'Os Cartões Expensify neste workspace dependem de fluxos de aprovação para definir seus Limites Inteligentes.\n\nAltere os tipos de limite de quaisquer cartões com Limites Inteligentes antes de desativar os fluxos de aprovação.',
                 confirmText: 'Ir para Cartões Expensify',
             },
             rules: {
@@ -5930,7 +5317,6 @@ _Para instruções mais detalhadas, [visite nossa central de ajuda](${CONST.NETS
                 subtitle: 'Defina uma taxa horária faturável para o controle de tempo.',
                 defaultHourlyRate: 'Taxa horária padrão',
             },
-            hrWarningModal: {disconnectText: ({integration}: {integration: string}) => `Para desativar RH, desconecte primeiro a integração ${integration} deste workspace.`},
         },
         reports: {
             reportsCustomTitleExamples: 'Exemplos:',
@@ -5952,7 +5338,10 @@ _Para instruções mais detalhadas, [visite nossa central de ajuda](${CONST.NETS
             findReportField: 'Encontrar campo de relatório',
             deleteConfirmation: 'Tem certeza de que deseja excluir este campo de relatório?',
             deleteFieldsConfirmation: 'Tem certeza de que deseja excluir esses campos de relatório?',
-            emptyReportFields: {title: 'Ainda não há campos de relatório', subtitle: 'Adicione um campo personalizado (texto, data ou lista suspensa) que apareça nos relatórios.'},
+            emptyReportFields: {
+                title: 'Você não criou nenhum campo de relatório',
+                subtitle: 'Adicione um campo personalizado (texto, data ou lista suspensa) que apareça nos relatórios.',
+            },
             subtitle: 'Os campos de relatório se aplicam a todos os gastos e podem ser úteis quando você quiser solicitar informações extras.',
             disableReportFields: 'Desativar campos de relatório',
             disableReportFieldsConfirmation: 'Tem certeza? Campos de texto e data serão excluídos e listas serão desativadas.',
@@ -5976,7 +5365,10 @@ _Para instruções mais detalhadas, [visite nossa central de ajuda](${CONST.NETS
             disableValues: 'Desativar valores',
             enableValue: 'Ativar valor',
             enableValues: 'Ativar valores',
-            emptyReportFieldsValues: {title: 'Ainda não há valores na lista', subtitle: 'Adicione valores personalizados para aparecerem nos relatórios.'},
+            emptyReportFieldsValues: {
+                title: 'Você não criou nenhum valor de lista',
+                subtitle: 'Adicione valores personalizados para aparecerem nos relatórios.',
+            },
             deleteValuePrompt: 'Tem certeza de que deseja excluir este valor da lista?',
             deleteValuesPrompt: 'Tem certeza de que deseja excluir esses valores da lista?',
             listValueRequiredError: 'Insira um nome de valor de lista',
@@ -5988,33 +5380,9 @@ _Para instruções mais detalhadas, [visite nossa central de ajuda](${CONST.NETS
             reportFieldNameRequiredError: 'Insira um nome de campo de relatório',
             reportFieldTypeRequiredError: 'Escolha um tipo de campo de relatório',
             circularReferenceError: 'Este campo não pode fazer referência a si mesmo. Atualize, por favor.',
-            unsupportedFormulaValueError: ({value}: UnsupportedFormulaValueErrorParams) => `Campo de fórmula ${value} não reconhecido`,
             reportFieldInitialValueRequiredError: 'Escolha um valor inicial para o campo de relatório',
             genericFailureMessage: 'Ocorreu um erro ao atualizar o campo do relatório. Tente novamente.',
         },
-        invoiceFields: {
-            subtitle: 'Os campos da fatura podem ser úteis quando você quiser incluir informações extras.',
-            importedFromAccountingSoftware: 'Os campos da fatura abaixo são importados do seu',
-            disableInvoiceFields: 'Desativar campos da fatura',
-            disableInvoiceFieldsConfirmation: 'Tem certeza? Os campos da fatura serão desativados nas faturas.',
-            delete: 'Excluir campo da fatura',
-            deleteConfirmation: 'Tem certeza de que deseja excluir este campo da fatura?',
-            findInvoiceField: 'Encontrar campo da fatura',
-            nameInputSubtitle: 'Escolha um nome para o campo da fatura.',
-            typeInputSubtitle: 'Escolha o tipo de campo da fatura que deseja usar.',
-            initialValueInputSubtitle: 'Insira um valor inicial para mostrar no campo da fatura.',
-            listValuesInputSubtitle: 'Esses valores aparecerão no menu suspenso do campo da fatura. Valores ativados podem ser selecionados pelos membros.',
-            listInputSubtitle: 'Esses valores aparecerão na lista do campo da fatura. Valores ativados podem ser selecionados pelos membros.',
-            emptyInvoiceFieldsValues: {
-                title: 'Ainda não há valores de lista',
-                subtitle: 'Adicione valores personalizados para aparecerem nas faturas.',
-            },
-            existingInvoiceFieldNameError: 'Já existe um campo da fatura com este nome',
-            invoiceFieldNameRequiredError: 'Insira um nome para o campo da fatura',
-            invoiceFieldTypeRequiredError: 'Escolha um tipo de campo da fatura',
-            invoiceFieldInitialValueRequiredError: 'Escolha um valor inicial para o campo da fatura',
-            addField: 'Adicionar campo',
-        },
         tags: {
             tagName: 'Nome da tag',
             requiresTag: 'Membros devem marcar todas as despesas',
@@ -6032,14 +5400,14 @@ _Para instruções mais detalhadas, [visite nossa central de ajuda](${CONST.NETS
             editTags: 'Editar tags',
             findTag: 'Encontrar tag',
             subtitle: 'As tags acrescentam maneiras mais detalhadas de classificar custos.',
-            subtitleWithDependentTags: (importSpreadsheetLink: string, canReimport = true) =>
-                `<muted-text>As tags acrescentam maneiras mais detalhadas de classificar custos. Você está usando <a href="${CONST.IMPORT_TAGS_EXPENSIFY_URL_DEPENDENT_TAGS}">tags dependentes</a>.${canReimport ? ` Você pode <a href="${importSpreadsheetLink}">reimportar uma planilha</a> para atualizar suas tags.` : ''}</muted-text>`,
+            dependentMultiLevelTagsSubtitle: (importSpreadsheetLink: string) =>
+                `<muted-text>Você está usando <a href="${CONST.IMPORT_TAGS_EXPENSIFY_URL_DEPENDENT_TAGS}">tags dependentes</a>. Você pode <a href="${importSpreadsheetLink}">reimportar uma planilha</a> para atualizar suas tags.</muted-text>`,
             emptyTags: {
-                title: 'Ainda não há tags',
+                title: 'Você não criou nenhuma tag',
                 subtitle: 'Adicione uma tag para acompanhar projetos, locais, departamentos e mais.',
                 subtitleHTML: `<muted-text><centered-text>Adicione tags para acompanhar projetos, locais, departamentos e mais. <a href="${CONST.IMPORT_TAGS_EXPENSIFY_URL}">Saiba mais</a> sobre como formatar arquivos de tags para importação.</centered-text></muted-text>`,
-                subtitleWithAccounting: (accountingPageURL: string, canManage = true) =>
-                    `<muted-text><centered-text>Suas tags estão sendo importadas de uma conexão contábil.${canManage ? ` Vá até a página de <a href="${accountingPageURL}">contabilidade</a> para fazer alterações.` : ''}</centered-text></muted-text>`,
+                subtitleWithAccounting: (accountingPageURL: string) =>
+                    `<muted-text><centered-text>Suas tags estão sendo importadas de uma conexão contábil. Vá até a página de <a href="${accountingPageURL}">contabilidade</a> para fazer alterações.</centered-text></muted-text>`,
             },
             deleteTag: 'Excluir etiqueta',
             deleteTags: 'Excluir tags',
@@ -6125,7 +5493,7 @@ _Para instruções mais detalhadas, [visite nossa central de ajuda](${CONST.NETS
                 updateTaxClaimableFailureMessage: 'A parte reembolsável deve ser menor que o valor da taxa por distância',
             },
             deleteTaxConfirmation: 'Tem certeza de que deseja excluir este imposto?',
-            deleteMultipleTaxConfirmation: (taxAmount: number) => `Tem certeza de que deseja excluir ${taxAmount} impostos?`,
+            deleteMultipleTaxConfirmation: ({taxAmount}: TaxAmountParams) => `Tem certeza de que deseja excluir ${taxAmount} impostos?`,
             actions: {
                 delete: 'Excluir tarifa',
                 deleteMultiple: 'Excluir tarifas',
@@ -6153,46 +5521,10 @@ _Para instruções mais detalhadas, [visite nossa central de ajuda](${CONST.NETS
             reimbursementAccount: 'conta de reembolso',
             welcomeNote: 'Comece a usar meu novo espaço de trabalho',
             delayedSubmission: 'envio atrasado',
-            merchantRules: 'Regras do comerciante',
-            merchantRulesCount: () => ({
-                one: '1 regra do comerciante',
-                other: (count: number) => `${count} regras do comerciante`,
-            }),
             confirmTitle: ({newWorkspaceName, totalMembers}: {newWorkspaceName?: string; totalMembers?: number}) =>
                 `Você está prestes to criar e compartilhar ${newWorkspaceName ?? ''} com ${totalMembers ?? 0} membros do workspace original.`,
             error: 'Ocorreu um erro ao duplicar seu novo espaço de trabalho. Tente novamente.',
         },
-        copyPolicySettings: {
-            title: 'Copiar configurações',
-            error: 'Ocorreu um erro ao copiar as configurações do workspace. Tente novamente.',
-            selectWorkspaces: {
-                title: 'Selecionar espaços de trabalho',
-                description: 'Escolha os espaços de trabalho para os quais você quer copiar as configurações e, em seguida, selecione quais configurações deseja copiar.',
-                searchPlaceholder: 'Buscar espaços de trabalho',
-            },
-            selectSettings: {
-                title: 'Selecione os recursos para copiar',
-                description: 'Selecione as configurações que deseja sobrescrever nos seus espaços de trabalho existentes.',
-                accountingMismatch: ({part}: {part: string}) => `Você só pode copiar ${part} se todos os espaços de trabalho usarem o mesmo sistema contábil e a mesma conexão da empresa.`,
-            },
-            confirmSettings: {
-                title: 'Vamos garantir que está tudo certo.',
-                description: ({workspaceName}: {workspaceName: string}) =>
-                    `Vamos copiar as seguintes configurações de <strong>${workspaceName}</strong> para os espaços de trabalho que você especificou`,
-            },
-            confirmWorkflows: {
-                continue: 'Continuar sem membros',
-                description: 'Copiar fluxos de trabalho sem membros não copiará os fluxos de aprovação. As configurações de envio e pagamento ainda serão copiadas.',
-            },
-            progress: {
-                copyInProgressTitle: 'Cópia em andamento...',
-                copyInProgressDescription: 'Você pode esperar o processo terminar ou o Concierge pode avisar você quando estiver concluído.',
-                letMeKnowPrompt: 'Me avise quando terminar',
-                conciergeNotificationTitle: 'O Concierge vai avisar você',
-                conciergeNotificationDescription: 'Quando o processo for concluído, o Concierge vai enviar uma mensagem para você.',
-                copyCompleted: 'As configurações do seu workspace foram copiadas.',
-            },
-        },
         emptyWorkspace: {
             title: 'Você não tem nenhum workspace',
             subtitle: 'Controle recibos, reembolse despesas, gerencie viagens, envie faturas e muito mais.',
@@ -6250,12 +5582,12 @@ _Para instruções mais detalhadas, [visite nossa central de ajuda](${CONST.NETS
                 genericRemove: 'Houve um problema ao remover esse membro do workspace',
             },
             addedWithPrimary: 'Alguns membros foram adicionados com seus logins principais.',
-            invitedBySecondaryLogin: (secondaryLogin: string) => `Adicionado pelo login secundário ${secondaryLogin}.`,
-            workspaceMembersCount: (count: number) => `Total de membros no workspace: ${count}`,
+            invitedBySecondaryLogin: ({secondaryLogin}: SecondaryLoginParams) => `Adicionado pelo login secundário ${secondaryLogin}.`,
+            workspaceMembersCount: ({count}: WorkspaceMembersCountParams) => `Total de membros no workspace: ${count}`,
             importMembers: 'Importar membros',
-            removeMemberPromptApprover: (approver: string, workspaceOwner: string) =>
+            removeMemberPromptApprover: ({approver, workspaceOwner}: {approver: string; workspaceOwner: string}) =>
                 `Se você remover ${approver} deste workspace, nós o substituiremos no fluxo de aprovação por ${workspaceOwner}, o proprietário do workspace.`,
-            removeMemberPromptPendingApproval: (memberName: string) =>
+            removeMemberPromptPendingApproval: ({memberName}: {memberName: string}) =>
                 `${memberName} tem relatórios de despesas pendentes de aprovação. Peça para que os aprove ou assuma o controle dos relatórios antes de removê-lo(a) do espaço de trabalho.`,
             removeMemberPromptReimburser: ({memberName}: {memberName: string}) =>
                 `Você não pode remover ${memberName} deste workspace. Defina um novo reembolsador em Fluxos de trabalho > Fazer ou acompanhar pagamentos e tente novamente.`,
@@ -6265,20 +5597,10 @@ _Para instruções mais detalhadas, [visite nossa central de ajuda](${CONST.NETS
                 `Se você remover ${memberName} deste workspace, nós vamos substituí-lo como contato técnico por ${workspaceOwner}, o proprietário do workspace.`,
             cannotRemoveUserDueToReport: ({memberName}: {memberName: string}) =>
                 `${memberName} tem um relatório pendente de processamento que requer ação. Peça para que concluam a ação necessária antes de removê-los do workspace.`,
-            allMembers: 'Todos os membros',
-            admins: 'Administradores do workspace',
-            cardAdmins: 'Administradores de cartões',
-            approvers: 'Aprovadores',
-            auditors: 'Auditores',
-            emptyRoleFilter: {title: 'Nenhum membro corresponde a este filtro', subtitle: 'Convide um membro ou altere o filtro acima.'},
-            configureHRSync: (providerName: string) => `Configurar a sincronização do ${providerName}.`,
-            syncWithHR: (providerName: string) => `Sincronizar com ${providerName}`,
-            makeCardAdmin: () => ({one: 'Tornar admin do cartão', other: 'Tornar administradores de cartão'}),
         },
         card: {
             getStartedIssuing: 'Comece emitindo seu primeiro cartão virtual ou físico.',
             issueCard: 'Emitir cartão',
-            chooseRule: 'Escolha uma regra',
             issueNewCard: {
                 whoNeedsCard: 'Quem precisa de um cartão?',
                 inviteNewMember: 'Convidar novo membro',
@@ -6320,27 +5642,22 @@ _Para instruções mais detalhadas, [visite nossa central de ajuda](${CONST.NETS
                 enterValidDate: 'Digite uma data válida',
                 expirationDate: 'Data de validade',
                 limitAmount: 'Valor do limite',
-                setCardRules: 'Definir regras do cartão',
-                addSpendRule: 'Adicionar regra de gasto',
-                addExpirationDate: 'Adicionar data de validade',
-                addExpirationDateDescription: 'Se nenhuma data específica for definida, o cartão vai expirar com base na data de validade atual do cartão',
+                setExpiryOptions: 'Definir opções de validade',
+                setExpiryDate: 'Definir data de validade',
+                setExpiryDateDescription: 'O cartão expirará conforme indicado no cartão',
                 amount: 'Valor',
-                copyExisting: 'Copiar existente',
-                createNew: 'Criar novo',
-                spendRulesEmptyStateTitle: 'Nenhuma regra para escolher',
-                spendRulesEmptyStateSubtitle: 'Ainda não há regras. Você pode criar uma a partir da tela anterior.',
             },
             deactivateCardModal: {
                 deactivate: 'Desativar',
                 deactivateCard: 'Desativar cartão',
                 deactivateConfirmation: 'Desativar este cartão recusará todas as transações futuras e não poderá ser desfeito.',
             },
-            searchRules: 'Encontrar regra de gasto',
         },
         accounting: {
             settings: 'configurações',
             title: 'Conexões',
-            subtitle: 'Conecte seu software de contabilidade para uma sincronização automática.',
+            subtitle:
+                'Conecte-se ao seu sistema contábil para classificar transações com seu plano de contas, fazer a correspondência automática de pagamentos e manter suas finanças sincronizadas.',
             qbo: 'QuickBooks Online',
             qbd: 'QuickBooks Desktop',
             xero: 'Xero',
@@ -6349,7 +5666,7 @@ _Para instruções mais detalhadas, [visite nossa central de ajuda](${CONST.NETS
             sap: 'SAP',
             oracle: 'Oracle',
             microsoftDynamics: 'Microsoft Dynamics',
-            talkYourOnboardingSpecialist: 'Converse com seu executivo de contas.',
+            talkYourOnboardingSpecialist: 'Converse com seu especialista de configuração.',
             talkYourAccountManager: 'Converse com seu gerente de conta.',
             talkToConcierge: 'Converse com o Concierge.',
             needAnotherAccounting: 'Precisa de outro software de contabilidade?',
@@ -6424,8 +5741,6 @@ _Para instruções mais detalhadas, [visite nossa central de ajuda](${CONST.NETS
             connectPrompt: ({connectionName}: ConnectionNameParams) =>
                 `Tem certeza de que deseja conectar ${CONST.POLICY.CONNECTIONS.NAME_USER_FRIENDLY[connectionName] ?? 'esta integração contábil'}? Isso removerá quaisquer conexões contábeis existentes.`,
             enterCredentials: 'Insira suas credenciais',
-            reconnect: 'Reconectar',
-            updateCredentials: 'Atualizar credenciais',
             claimOffer: {
                 badgeText: 'Oferta disponível!',
                 xero: {
@@ -6568,26 +5883,6 @@ _Para instruções mais detalhadas, [visite nossa central de ajuda](${CONST.NETS
                             return 'Importando dimensões do Sage Intacct';
                         case 'intacctImportTitle':
                             return 'Importando dados do Sage Intacct';
-                        case 'financialForceSyncTitle':
-                            return 'Sincronizando dados do Certinia';
-                        case 'financialForceSyncStep':
-                            return 'Sincronizando conexao do Certinia';
-                        case 'financialForceSyncCategories':
-                            return 'Importando categorias';
-                        case 'financialForceSyncTags':
-                            return 'Importando tags';
-                        case 'financialForceSyncVendors':
-                            return 'Importando fornecedores';
-                        case 'financialForceSyncContacts':
-                            return 'Importando contatos';
-                        case 'financialForceSyncCompanies':
-                            return 'Importando empresas';
-                        case 'financialForceSyncUsers':
-                            return 'Importando usuarios';
-                        case 'financialForceSyncDimensions':
-                            return 'Importando dimensoes';
-                        case 'financialForceMarkAsReimbursed':
-                            return 'Marcando relatorios como reembolsados';
                         default: {
                             return `Tradução ausente para o estágio: ${stage}`;
                         }
@@ -6610,18 +5905,14 @@ _Para instruções mais detalhadas, [visite nossa central de ajuda](${CONST.NETS
             reconciliationAccount: 'Conta de reconciliação',
             continuousReconciliation: 'Conciliação Contínua',
             saveHoursOnReconciliation:
-                'Economize horas na conciliação de cada período contábil deixando a Expensify reconciliar continuamente, por você, os extratos e liquidações do Cartão Expensify.',
+                'Economize horas na conciliação de cada período contábil deixando que a Expensify faça continuamente a conciliação dos extratos e liquidações do Expensify Card em seu nome.',
             enableContinuousReconciliation: (accountingAdvancedSettingsLink: string, connectionName: string) =>
                 `<muted-text-label>Para ativar a Conciliação Contínua, ative a <a href="${accountingAdvancedSettingsLink}">sincronização automática</a> para ${connectionName}.</muted-text-label>`,
             chooseReconciliationAccount: {
                 chooseBankAccount: 'Escolha a conta bancária na qual os pagamentos do seu Cartão Expensify serão conciliados.',
-                settlementAccountReconciliation: (settlementAccountUrl: string, lastFourPAN: string) =>
-                    `Certifique-se de que esta conta corresponda à sua <a href="${settlementAccountUrl}">conta de liquidação do Cartão Expensify</a> (terminada em ${lastFourPAN}) para que a Reconciliação Contínua funcione corretamente.`,
-                chooseTravelInvoicingBankAccount: 'Escolha a conta bancária na qual os pagamentos de faturamento de viagem serão conciliados.',
-                travelInvoicingSettlementAccountReconciliation: (lastFourPAN: string) =>
-                    `Certifique-se de que esta conta corresponda à sua conta de liquidação de faturamento de viagem (terminada em ${lastFourPAN}) para que a Conciliação Contínua funcione corretamente.`,
+                settlementAccountReconciliation: ({settlementAccountUrl, lastFourPAN}: SettlementAccountReconciliationParams) =>
+                    `Certifique-se de que esta conta corresponda à sua <a href="${settlementAccountUrl}">conta de liquidação do Expensify Card</a> (terminada em ${lastFourPAN}) para que a Conciliação Contínua funcione corretamente.`,
             },
-            syncTravelInvoicingSettlements: 'Sincronizar liquidações de faturamento de viagens',
         },
         export: {
             notReadyHeading: 'Não está pronto para exportar',
@@ -6700,13 +5991,7 @@ _Para instruções mais detalhadas, [visite nossa central de ajuda](${CONST.NETS
             errors: {
                 rateNameRequired: 'Nome da tarifa é obrigatório',
                 existingRateName: 'Já existe uma tarifa de distância com este nome',
-                nameRequired: 'Nome é obrigatório',
-                startDateMustBeBeforeEndDate: 'A data de início deve ser anterior à data de término',
-                amountRequired: 'O valor é obrigatório',
             },
-            amountPerUnit: (unit: string) => `Valor por ${unit}`,
-            startDate: 'Data de início',
-            endDate: 'Data de término',
         },
         editor: {
             descriptionInputLabel: 'Descrição',
@@ -6749,7 +6034,7 @@ _Para instruções mais detalhadas, [visite nossa central de ajuda](${CONST.NETS
             updateToUSD: 'Atualizar para USD',
             updateWorkspaceCurrency: 'Atualizar moeda do espaço de trabalho',
             workspaceCurrencyNotSupported: 'Moeda do workspace não suportada',
-            yourWorkspace: `Seu workspace está configurado para uma moeda não compatível. Veja a <a href="${CONST.ENABLE_GLOBAL_REIMBURSEMENT_HELP_URL}">lista de moedas compatíveis</a>.`,
+            yourWorkspace: `Seu workspace está configurado para uma moeda não compatível. Veja a <a href="${CONST.CONNECT_A_BUSINESS_BANK_ACCOUNT_HELP_URL}">lista de moedas compatíveis</a>.`,
             chooseAnExisting: 'Escolha uma conta bancária existente para pagar despesas ou adicione uma nova.',
         },
         changeOwner: {
@@ -6786,7 +6071,7 @@ Se você quiser assumir a cobrança de toda a assinatura deles, peça para que a
             hasFailedSettlementsTitle: 'Não é possível transferir a propriedade',
             hasFailedSettlementsButtonText: 'Entendi',
             hasFailedSettlementsText: (email: string) =>
-                `Você não pode assumir a cobrança porque ${email} tem uma liquidação em atraso do Cartão Expensify. Peça para essa pessoa entrar em contato com concierge@expensify.com para resolver o problema. Depois disso, você poderá assumir a cobrança deste workspace.`,
+                `Você não pode assumir a cobrança porque ${email} tem uma liquidação em atraso do Expensify Card. Peça para essa pessoa entrar em contato com concierge@expensify.com para resolver o problema. Depois disso, você poderá assumir a cobrança deste espaço de trabalho.`,
             failedToClearBalanceTitle: 'Falha ao zerar o saldo',
             failedToClearBalanceButtonText: 'OK',
             failedToClearBalanceText: 'Não foi possível zerar o saldo. Tente novamente mais tarde.',
@@ -6815,12 +6100,6 @@ Tem certeza de que deseja exportá-los novamente?`,
                 onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
                     `<muted-text>Os campos de relatório estão disponíveis apenas no plano Control, a partir de <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `por membro por mês.` : `por membro ativo por mês.`}</muted-text>`,
             },
-            invoiceFields: {
-                title: 'Campos de fatura',
-                description: `Os campos da fatura permitem incluir detalhes extras no nível da fatura.`,
-                onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
-                    `<muted-text>Os campos da fatura estão disponíveis apenas no plano Control, a partir de <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `por membro por mês.` : `por membro ativo por mês.`}</muted-text>`,
-            },
             [CONST.POLICY.CONNECTIONS.NAME.NETSUITE]: {
                 title: 'NetSuite',
                 description: `Aproveite a sincronização automática e reduza lançamentos manuais com a integração Expensify + NetSuite. Obtenha insights financeiros profundos e em tempo real com suporte a segmentos nativos e personalizados, incluindo mapeamento de projetos e clientes.`,
@@ -6839,12 +6118,6 @@ Tem certeza de que deseja exportá-los novamente?`,
                 onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
                     `<muted-text>Nossa integração com o QuickBooks Desktop está disponível apenas no plano Control, a partir de <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `por membro por mês.` : `por membro ativo por mês.`}</muted-text>`,
             },
-            [CONST.POLICY.CONNECTIONS.NAME.CERTINIA]: {
-                title: 'Certinia',
-                description: `Aproveite a sincronização automática e reduza lançamentos manuais com a integração Expensify + Certinia. Alinhe dimensões de categorização de despesas e a sincronização de impostos à sua configuração Certinia para maior visibilidade financeira.`,
-                onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
-                    `<muted-text>Nossa integração com a Certinia está disponível apenas no plano Control, a partir de <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `por membro por mês.` : `por membro ativo por mês.`}</muted-text>`,
-            },
             [CONST.UPGRADE_FEATURE_INTRO_MAPPING.approvals.id]: {
                 title: 'Aprovações Avançadas',
                 description: `Se você quiser adicionar mais camadas de aprovação ao processo – ou apenas garantir que as maiores despesas recebam uma segunda revisão – nós ajudamos você. As aprovações avançadas ajudam a colocar os controles certos em cada nível, para manter os gastos da sua equipe sob controle.`,
@@ -6921,7 +6194,7 @@ Exija dados de despesas como recibos e descrições, defina limites e padrões e
                 onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
                     `<muted-text>Tarifas por distância estão disponíveis no plano Collect, a partir de <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `por membro por mês.` : `por membro ativo por mês.`}</muted-text>`,
             },
-            controlPolicyRoles: {
+            auditor: {
                 title: 'Auditor',
                 description: 'Auditores têm acesso somente leitura a todos os relatórios para total visibilidade e monitoramento de conformidade.',
                 onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
@@ -6938,12 +6211,13 @@ Exija dados de despesas como recibos e descrições, defina limites e padrões e
                 perActiveMember: 'por membro ativo por mês.',
                 perMember: 'por membro por mês.',
             },
-            note: (subscriptionLink: string) => `<muted-text><a href="${subscriptionLink}">Saiba mais</a> sobre nossos planos e preços.</muted-text>`,
+            note: ({subscriptionLink}: WorkspaceUpgradeNoteParams) =>
+                `<muted-text>Faça upgrade para acessar este recurso ou <a href="${subscriptionLink}">saiba mais</a> sobre nossos planos e preços.</muted-text>`,
             upgradeToUnlock: 'Desbloquear este recurso',
             completed: {
                 headline: `Você atualizou seu workspace!`,
-                successMessage: (policyName: string, planName: string, subscriptionLink: string) =>
-                    `<centered-text>Você atualizou o plano ${policyName} para o ${planName} com sucesso! <a href="${subscriptionLink}">Veja sua assinatura</a> para mais detalhes.</centered-text>`,
+                successMessage: ({policyName, subscriptionLink}: UpgradeSuccessMessageParams) =>
+                    `<centered-text>Você atualizou o plano ${policyName} para o Control com sucesso! <a href="${subscriptionLink}">Veja sua assinatura</a> para mais detalhes.</centered-text>`,
                 categorizeMessage: `Você fez upgrade com sucesso para o plano Collect. Agora você pode categorizar suas despesas!`,
                 travelMessage: `Você fez upgrade com sucesso para o plano Collect. Agora você pode começar a reservar e gerenciar viagens!`,
                 distanceRateMessage: `Você fez upgrade com sucesso para o plano Collect. Agora você pode alterar a taxa de distância!`,
@@ -6966,86 +6240,25 @@ Exija dados de despesas como recibos e descrições, defina limites e padrões e
                 upgradeWorkspaceWarning: `Não é possível atualizar o workspace`,
                 upgradeWorkspaceWarningForRestrictedPolicyCreationPrompt: 'Sua empresa restringiu a criação de espaços de trabalho. Entre em contato com um administrador para obter ajuda.',
             },
-            hr: {
-                title: 'Integrações de RH',
-                description:
-                    'Conecte seu provedor de RH para sincronizar automaticamente funcionários e gerenciar fluxos de aprovação. Mantenha a lista de integrantes da equipe e a estrutura de relatórios sempre atualizadas sem trabalho manual.',
-                onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
-                    `<muted-text>Integrações de RH estão disponíveis apenas no plano Control, a partir de <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `por membro por mês.` : `por membro ativo por mês.`}</muted-text>`,
-            },
-            approvalSubmit: {
-                title: 'Aprovações',
-                description: 'Configure centralmente para quem todos os membros enviam relatórios ativando as aprovações.',
-                onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
-                    `<muted-text>As aprovações estão disponíveis nos planos Collect e Control, a partir de <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `por membro por mês.` : `por membro ativo por mês.`}</muted-text>`,
-            },
-            companyCardSubmit: {
-                title: 'Cartões corporativos',
-                description: `Traga seu próprio cartão corporativo para o Expensify para obter importação automática, categorização automática, suporte a regras personalizáveis e reconciliação integrada.`,
-                onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
-                    `<muted-text>A importação de cartão corporativo está disponível nos planos Collect e Control, a partir de <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `por membro por mês.` : `por membro ativo por mês.`}</muted-text>`,
-            },
-            travelSubmit: {
-                title: 'Expensify Travel',
-                description: 'Reserve voos, hotéis, carros e trens com desconto no mundo todo, diretamente pelo Expensify, com relatórios de duty of care e gestão de despesas integrada.',
-                onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
-                    `<muted-text>O Expensify Travel está disponível nos planos Collect e Control, a partir de <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `por membro por mês.` : `por membro ativo por mês.`}</muted-text>`,
-            },
-            roles: {
-                title: 'Funções',
-                description: 'Defina funções diferentes para membros diferentes para aumentar ou reduzir a visibilidade e o controle conforme apropriado.',
-                onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
-                    `<muted-text>Funções estão disponíveis nos planos Collect e Control, a partir de <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `por membro por mês.` : `por membro ativo por mês.`}</muted-text>`,
-            },
-            payments: {
-                title: 'Pagamentos',
-                description: 'Reembolse funcionários diretamente da conta bancária da sua empresa.',
-                onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
-                    `<muted-text>Os pagamentos estão disponíveis nos planos Collect e Control, a partir de <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `por membro por mês.` : `por membro ativo por mês.`}</muted-text>`,
-            },
-            accounting: {
-                title: 'Contabilidade',
-                description:
-                    'Sincronize categorias, tags, taxas de imposto e muito mais do seu sistema contábil para o Expensify, além de exportar relatórios de despesas e transações de cartão – sem digitação (ou erros de digitação)!',
-                onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
-                    `<muted-text>O módulo de contabilidade está disponível nos planos Collect e Control, a partir de <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `por membro por mês.` : `por membro ativo por mês.`}</muted-text>`,
-            },
-            expensifyCard: {
-                title: 'Cartão Expensify',
-                description:
-                    'Emita cartões corporativos (incluindo cartões virtuais) diretamente da sua própria conta bancária para ter controle de gastos em tempo real com uma conexão inquebrável e até 2% de cashback!',
-                onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
-                    `<muted-text>O Cartão Expensify está disponível nos planos Collect e Control, a partir de <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `por membro por mês.` : `por membro ativo por mês.`}</muted-text>`,
-                upgradeButton: 'Fazer upgrade e ativar',
-            },
-            invoicing: {
-                title: 'Faturamento',
-                description: 'Crie, envie e acompanhe faturas profissionais, tudo dentro do Expensify. Receba mais rápido com pagamentos integrados e visibilidade em tempo real.',
-                onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
-                    `<muted-text>O faturamento está disponível nos planos Collect e Control, a partir de <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `por membro por mês.` : `por membro ativo por mês.`}</muted-text>`,
-            },
         },
         downgrade: {
             commonFeatures: {
-                title: 'Rebaixar para Collect',
-                note: 'Você perderá acesso aos seguintes recursos',
+                title: 'Fazer downgrade para o plano Collect',
+                note: 'Se você fizer o downgrade, perderá acesso a estes e outros recursos:',
                 benefits: {
-                    confirm: 'Você precisará alterar o “Tipo de plano” de todos os espaços de trabalho para “Collect” para garantir a tarifa Collect.',
-                    benefit1: 'NetSuite, Sage Intacct, QuickBooks Desktop, Oracle, Microsoft Dynamics',
-                    benefit2: 'Workday, Certinia',
-                    benefit3: 'SSO/SAML',
-                    benefit4: 'Regras inteligentes de despesas, diárias, aprovações em vários níveis, relatórios personalizados e orçamento',
+                    note: 'Para ver uma comparação completa dos nossos planos, confira nossa',
+                    pricingPage: 'página de preços',
+                    confirm: 'Tem certeza de que deseja fazer o downgrade e remover suas configurações?',
+                    warning: 'Isso não pode ser desfeito.',
+                    benefit1: 'Conexões contábeis (exceto QuickBooks Online e Xero)',
+                    benefit2: 'Regras inteligentes de despesa',
+                    benefit3: 'Fluxos de aprovação em múltiplos níveis',
+                    benefit4: 'Controles de segurança aprimorados',
                     headsUp: 'Atenção!',
                     multiWorkspaceNote:
                         'Você precisará fazer o downgrade de todos os seus espaços de trabalho antes do seu primeiro pagamento mensal para começar uma assinatura na tarifa Collect. Clique',
                     selectStep: '> selecione cada espaço de trabalho > altere o tipo de plano para',
-                    benefit1Label: 'Integrações com ERP',
-                    benefit2Label: 'Integrações de RH',
-                    benefit3Label: 'Segurança',
-                    benefit4Label: 'Avançado',
-                    important: 'IMPORTANTE:',
                 },
-                noteAndMore: 'e mais:',
             },
             completed: {
                 headline: 'Seu workspace foi rebaixado',
@@ -7065,7 +6278,7 @@ Exija dados de despesas como recibos e descrições, defina limites e padrões e
         restrictedAction: {
             restricted: 'Restrito',
             actionsAreCurrentlyRestricted: (workspaceName: string) => `As ações no workspace ${workspaceName} estão atualmente restritas`,
-            workspaceOwnerWillNeedToAddOrUpdatePaymentCard: (workspaceOwnerName: string) =>
+            workspaceOwnerWillNeedToAddOrUpdatePaymentCard: ({workspaceOwnerName}: WorkspaceOwnerWillNeedToAddOrUpdatePaymentCardParams) =>
                 `O proprietário do espaço de trabalho, ${workspaceOwnerName}, precisa adicionar ou atualizar o cartão de pagamento em arquivo para desbloquear novas atividades no espaço de trabalho.`,
             youWillNeedToAddOrUpdatePaymentCard: 'Você precisa adicionar ou atualizar o cartão de pagamento em arquivo para desbloquear novas atividades no espaço de trabalho.',
             addPaymentCardToUnlock: 'Adicione um cartão de pagamento para desbloquear!',
@@ -7118,18 +6331,16 @@ Exija dados de despesas como recibos e descrições, defina limites e padrões e
                 eReceiptsHint: `eReceipts são criados automaticamente [para a maioria das transações em crédito em USD](${CONST.DEEP_DIVE_ERECEIPTS}).`,
                 attendeeTracking: 'Controle de participantes',
                 attendeeTrackingHint: 'Acompanhe o custo por pessoa de cada despesa.',
-                prohibitedDefaultDescription: 'Marcar recibos com estes itens de linha para revisão manual.',
+                prohibitedDefaultDescription:
+                    'Marque todos os recibos em que apareçam bebidas alcoólicas, jogos de azar ou outros itens restritos. Despesas com recibos em que esses itens apareçam precisarão de revisão manual.',
                 prohibitedExpenses: 'Despesas proibidas',
                 alcohol: 'Álcool',
                 hotelIncidentals: 'Despesas diversas de hotel',
                 gambling: 'Jogos de azar',
                 tobacco: 'Tabaco',
                 adultEntertainment: 'Entretenimento adulto',
-                giftCard: 'Compras de cartão-presente',
-                handwrittenReceipt: 'Recibos manuscritos',
                 requireCompanyCard: 'Exigir cartões corporativos para todas as compras',
                 requireCompanyCardDescription: 'Sinalize todos os gastos em dinheiro, incluindo despesas com quilometragem e diárias.',
-                requireCompanyCardDisabledTooltip: 'Ative Cartões corporativos (em Mais recursos) para desbloquear.',
             },
             expenseReportRules: {
                 title: 'Avançado',
@@ -7138,8 +6349,8 @@ Exija dados de despesas como recibos e descrições, defina limites e padrões e
                 preventSelfApprovalsSubtitle: 'Impedir que membros do workspace aprovem seus próprios relatórios de despesas.',
                 autoApproveCompliantReportsTitle: 'Aprovar automaticamente relatórios em conformidade',
                 autoApproveCompliantReportsSubtitle: 'Configure quais relatórios de despesas são elegíveis para aprovação automática.',
-                autoApproveReportsUnderTitle: 'Aprovar automaticamente relatórios com todas as despesas abaixo de',
-                autoApproveReportsUnderDescription: 'Relatórios de despesas totalmente conformes em que todas as despesas estejam abaixo deste valor serão aprovados automaticamente.',
+                autoApproveReportsUnderTitle: 'Aprovar automaticamente relatórios abaixo de',
+                autoApproveReportsUnderDescription: 'Relatórios de despesas totalmente conformes abaixo deste valor serão aprovados automaticamente.',
                 randomReportAuditTitle: 'Auditoria aleatória de relatórios',
                 randomReportAuditDescription: 'Exigir que alguns relatórios sejam aprovados manualmente, mesmo que sejam elegíveis para aprovação automática.',
                 autoPayApprovedReportsTitle: 'Pagar automaticamente relatórios aprovados',
@@ -7152,11 +6363,6 @@ Exija dados de despesas como recibos e descrições, defina limites e padrões e
                 enableFeatureSubtitle: (featureName: string, moreFeaturesLink?: string) =>
                     `Vá para [mais recursos](${moreFeaturesLink}) e ative ${featureName} para desbloquear este recurso.`,
             },
-            agentsPromoBanner: {
-                title: 'Não encontrou a regra que precisa? Adicione um agente',
-                subtitle: 'Adicione regras complexas e reduza aprovações manuais com agentes personalizados.',
-                cta: 'Experimente',
-            },
             merchantRules: {
                 title: 'Estabelecimento',
                 subtitle: 'Defina as regras de estabelecimento para que as despesas cheguem corretamente classificadas e exijam menos retrabalho.',
@@ -7184,10 +6390,9 @@ Exija dados de despesas como recibos e descrições, defina limites e padrões e
                 matchTypeContains: 'Contém',
                 matchTypeExact: 'Corresponde exatamente',
                 duplicateRuleTitle: 'Já existe uma regra semelhante para este comerciante',
-                duplicateRulePrompt: (merchantName: string) => `Sua regra existente para "${merchantName}" terá prioridade sobre esta. Salvar mesmo assim?`,
+                duplicateRulePrompt: (merchantName: string) => `Você quer salvar uma nova regra para "${merchantName}" mesmo já tendo uma existente?`,
                 saveAnyway: 'Salvar mesmo assim',
                 applyToExistingUnsubmittedExpenses: 'Aplicar às despesas existentes não enviadas',
-                findRule: 'Encontrar regra de comerciante',
             },
             categoryRules: {
                 title: 'Regras de categoria',
@@ -7225,131 +6430,12 @@ Exija dados de despesas como recibos e descrições, defina limites e padrões e
                     always: 'Sempre exigir recibos detalhados',
                 },
                 defaultTaxRate: 'Taxa de imposto padrão',
-                enableWorkflows: (moreFeaturesLink: string) =>
+                enableWorkflows: ({moreFeaturesLink}: RulesEnableWorkflowsParams) =>
                     `Vá para [Mais recursos](${moreFeaturesLink}) e ative os fluxos de trabalho, depois adicione aprovações para desbloquear este recurso.`,
             },
             customRules: {
                 title: 'Política de despesas',
                 cardSubtitle: 'Aqui é onde fica a política de despesas da sua equipe, para que todo mundo esteja alinhado sobre o que é coberto.',
-                policyDocument: 'Documento de política',
-                policyText: 'Texto da política',
-            },
-            spendRules: {
-                title: 'Gasto',
-                subtitle: 'Aprove ou recuse transações do Cartão Expensify em tempo real.',
-                defaultRuleDescription: 'Todos os cartões',
-                block: 'Bloquear',
-                defaultRuleTitle: 'Categorias: Serviços adultos, caixas eletrônicos, jogos de azar, transferências de dinheiro',
-                builtInProtectionModal: {
-                    title: 'Os Cartões Expensify oferecem proteção integrada — sempre',
-                    description: `A Expensify sempre recusa estas cobranças:
-
-  • Serviços adultos
-  • Caixas eletrônicos (ATM)
-  • Jogos de azar
-  • Transferências de dinheiro
-
-Adicione mais regras de gasto para proteger o fluxo de caixa da empresa.`,
-                },
-                addSpendRule: 'Adicionar regra de gasto',
-                cardPageTitle: 'Cartão',
-                cardsSectionTitle: 'Cartões',
-                chooseCards: 'Escolher cartões',
-                saveRule: 'Salvar regra',
-                allow: 'Permitir',
-                spendRuleSectionTitle: 'Regra de gasto',
-                restrictionType: 'Tipo de restrição',
-                restrictionTypeHelpAllow: 'As cobranças são aprovadas se corresponderem a qualquer comerciante ou categoria e não excederem um valor máximo.',
-                restrictionTypeHelpBlock: 'As cobranças são recusadas se corresponderem a qualquer estabelecimento ou categoria, ou se excederem um valor máximo.',
-                addMerchant: 'Adicionar comerciante',
-                merchantContains: 'Comerciante contém',
-                merchantExactlyMatches: 'Estabelecimento corresponde exatamente',
-                noBlockedMerchants: 'Nenhum comerciante bloqueado',
-                addMerchantToBlockSpend: 'Adicionar um comerciante para bloquear gastos',
-                noAllowedMerchants: 'Nenhum comerciante permitido',
-                addMerchantToAllowSpend: 'Adicione um comerciante para permitir gastos',
-                matchType: 'Tipo de correspondência',
-                matchTypeContains: 'Contém',
-                matchTypeExact: 'Corresponde exatamente',
-                spendCategory: 'Categoria de gasto',
-                maxAmount: 'Valor máximo',
-                maxAmountHelp: 'Qualquer cobrança acima desse valor será recusada, independentemente das restrições de estabelecimento e categoria de gasto.',
-                currencyMismatchTitle: 'Incompatibilidade de moeda',
-                currencyMismatchPrompt: 'Para definir um valor máximo, selecione cartões que liquidem na mesma moeda.',
-                reviewSelectedCards: 'Revisar cartões selecionados',
-                summaryMoreCount: ({summary, count}: {summary: string; count: number}) => (count > 0 ? `${summary}, +${count} mais` : summary),
-                confirmErrorApplyAtLeastOneSpendRuleToOneCard: 'Aplicar pelo menos uma regra de gasto a um cartão',
-                confirmErrorCardRequired: 'O campo Cartão é obrigatório',
-                confirmErrorApplyAtLeastOneSpendRule: 'Aplicar pelo menos uma regra de gasto',
-                categories: 'Categorias',
-                merchants: 'Comerciantes',
-                noAvailableCards: 'Todos os cartões já têm uma regra',
-                noAvailableCardsSubtitle: 'Edite uma regra de cartão existente para fazer alterações',
-                noCardsIssuedTitle: 'Nenhum Cartão Expensify emitido',
-                noCardsIssuedSubtitle: 'Emita Cartões Expensify para criar regras de gastos',
-                max: 'Máx.',
-                categoryOptions: {
-                    [CONST.SPEND_RULES.CATEGORIES.AIRLINES]: 'Companhias aéreas',
-                    [CONST.SPEND_RULES.CATEGORIES.ALCOHOL_AND_BARS]: 'Álcool e bares',
-                    [CONST.SPEND_RULES.CATEGORIES.AMAZON_AND_BOOKSTORES]: 'Amazon e livrarias',
-                    [CONST.SPEND_RULES.CATEGORIES.AUTOMOTIVE]: 'Automotivo',
-                    [CONST.SPEND_RULES.CATEGORIES.CAR_RENTALS]: 'Aluguel de carros',
-                    [CONST.SPEND_RULES.CATEGORIES.DINING]: 'Refeições',
-                    [CONST.SPEND_RULES.CATEGORIES.FUEL_AND_GAS]: 'Combustível e gás',
-                    [CONST.SPEND_RULES.CATEGORIES.GOVERNMENT_AND_NON_PROFITS]: 'Governo e organizações sem fins lucrativos',
-                    [CONST.SPEND_RULES.CATEGORIES.GROCERIES]: 'Supermercado',
-                    [CONST.SPEND_RULES.CATEGORIES.GYMS_AND_FITNESS]: 'Academias e fitness',
-                    [CONST.SPEND_RULES.CATEGORIES.HEALTHCARE]: 'Saúde',
-                    [CONST.SPEND_RULES.CATEGORIES.HOTELS]: 'Hotéis',
-                    [CONST.SPEND_RULES.CATEGORIES.INTERNET_AND_PHONE]: 'Internet e telefone',
-                    [CONST.SPEND_RULES.CATEGORIES.OFFICE_SUPPLIES]: 'Material de escritório',
-                    [CONST.SPEND_RULES.CATEGORIES.PARKING_AND_TOLLS]: 'Estacionamento e pedágios',
-                    [CONST.SPEND_RULES.CATEGORIES.PROFESSIONAL_SERVICES]: 'Serviços profissionais',
-                    [CONST.SPEND_RULES.CATEGORIES.RETAIL]: 'Varejo',
-                    [CONST.SPEND_RULES.CATEGORIES.SHIPPING_AND_DELIVERY]: 'Envio e entrega',
-                    [CONST.SPEND_RULES.CATEGORIES.SOFTWARE]: 'Software',
-                    [CONST.SPEND_RULES.CATEGORIES.TRANSIT_AND_RIDESHARE]: 'Transporte público e carros de aplicativo',
-                    [CONST.SPEND_RULES.CATEGORIES.TRAVEL_AGENCIES]: 'Agências de viagens',
-                },
-                editRuleTitle: 'Editar regra',
-                deleteRule: 'Excluir regra',
-                deleteRuleConfirmation: 'Tem certeza de que quer excluir esta regra?',
-                summaryMerchants: ({
-                    merchants,
-                    hiddenCount,
-                    shownCount,
-                    action,
-                }: {
-                    merchants: string;
-                    hiddenCount: number;
-                    shownCount: number;
-                    action: ValueOf<typeof CONST.SPEND_RULES.ACTION>;
-                }) =>
-                    `${action === CONST.SPEND_RULES.ACTION.BLOCK ? 'Bloqueado' : 'Permitido'} ${shownCount > 1 ? 'comerciantes' : 'estabelecimento'}: ${merchants}${hiddenCount > 0 ? `, +${hiddenCount} mais` : ''}`,
-                summaryCategories: ({
-                    categories,
-                    hiddenCount,
-                    shownCount,
-                    action,
-                }: {
-                    categories: string;
-                    hiddenCount: number;
-                    shownCount: number;
-                    action: ValueOf<typeof CONST.SPEND_RULES.ACTION>;
-                }) =>
-                    `${action === CONST.SPEND_RULES.ACTION.BLOCK ? 'Bloqueado' : 'Permitido'} ${shownCount > 1 ? 'categorias' : 'categoria'}: ${categories}${hiddenCount > 0 ? `, +${hiddenCount} mais` : ''}`,
-            },
-            aiRules: {
-                title: 'Regras de IA',
-                subtitle: 'Descreva regras flexíveis que rodam quando você precisa',
-                addRule: 'Adicionar regra de IA',
-                findRule: 'Encontrar regra de IA',
-                addRuleTitle: 'Adicionar regra',
-                editRuleTitle: 'Editar regra',
-                deleteRule: 'Excluir regra',
-                deleteRuleConfirmation: 'Tem certeza de que quer excluir esta regra?',
-                describeRuleTitle: 'Descreva sua regra',
-                describeRuleSubtitle: 'Descreva sua regra e a Concierge vai criá-la',
             },
         },
         planTypePage: {
@@ -7362,105 +6448,15 @@ Adicione mais regras de gasto para proteger o fluxo de caixa da empresa.`,
                     label: 'Controle',
                     description: 'Para organizações com requisitos avançados.',
                 },
-                submit2026: {
-                    label: 'Enviar',
-                    description: 'Para funcionários que desejam enviar despesas ao empregador.',
-                },
             },
-            description: 'Escolha o plano ideal para você.',
-            subscriptionLink: 'Saiba mais',
+            description: 'Escolha o plano ideal para você. Para ver a lista detalhada de recursos e preços, confira nosso',
+            subscriptionLink: 'página de ajuda sobre tipos de plano e preços',
             lockedPlanDescription: ({count, annualSubscriptionEndDate}: WorkspaceLockedPlanTypeParams) => ({
                 one: `Você se comprometeu com 1 membro ativo no plano Control até o fim da sua assinatura anual em ${annualSubscriptionEndDate}. Você pode mudar para a assinatura pré-paga por uso e fazer downgrade para o plano Collect a partir de ${annualSubscriptionEndDate}, desativando a renovação automática em`,
                 other: `Você se comprometeu com ${count} membros ativos no plano Control até o fim da sua assinatura anual em ${annualSubscriptionEndDate}. Você pode mudar para a assinatura pós-paga e fazer downgrade para o plano Collect a partir de ${annualSubscriptionEndDate} desativando a renovação automática em`,
             }),
             subscriptions: 'Assinaturas',
         },
-        hr: {
-            title: 'RH',
-            connections: 'Conexões',
-            connectionsSubtitle:
-                'Conecte-se ao seu sistema de RH para sincronizar os dados de funcionários, associar automaticamente os reembolsos às pessoas corretas e manter as despesas da sua equipe precisas, sem trabalho manual.',
-            subtitle: 'Conecte ferramentas de RH e mantenha as aprovações de funcionários em sincronia.',
-            connect: 'Conectar',
-            syncNow: 'Sincronizar agora',
-            disconnect: 'Desconectar',
-            disconnectTitle: (providerName: string) => `Desconectar ${providerName}`,
-            disconnectPrompt: (providerName: string) => `Tem certeza de que deseja desconectar ${providerName}?`,
-            alreadyConnectedTitle: 'Não é possível conectar a várias plataformas de RH',
-            alreadyConnectedPrompt: 'Você precisa desconectar sua plataforma de RH atual antes de conectar outra.',
-            lastSync: (relativeDate: string) => `Última sincronização ${relativeDate}`,
-            syncError: (providerName: string) => `Não é possível conectar ao ${providerName}`,
-            connectionDescription: (providerName: string) => `Conecte ${providerName} para manter as aprovações de funcionários sincronizadas com seu workspace.`,
-            approvalMode: 'Modo de aprovação',
-            providerApprovalMode: (providerName: string) => `Modo de aprovação do ${providerName}`,
-            finalApprover: 'Aprovador final',
-            providerFinalApprover: (providerName: string) => `Aprovador final de ${providerName}`,
-            notSet: 'Não definido',
-            approvalModeDescription: (providerName: string) => `Membros e gerentes estão configurados para sincronizar com ${providerName}.`,
-            approvalModeWarningTitle: 'Alterar modo de aprovação?',
-            approvalModeWarningPrompt: (providerName: string, helpSiteURL: string) =>
-                `Tem certeza de que deseja alterar o modo de aprovação deste workspace? Saiba mais sobre os diferentes modos de fluxo de trabalho com ${providerName} em nosso <a href="${helpSiteURL}">site de ajuda</a>.`,
-            approvalModeWarningConfirm: 'Alterar modo de aprovação',
-            approvalModes: {
-                basic: {label: 'Aprovação básica', description: 'Todos os usuários enviam para uma única pessoa para processamento e aprovação.'},
-                manager: {
-                    label: 'Aprovação do gerente',
-                    description: (providerName: string) => `Os funcionários enviam relatórios ao gestor direto configurado no ${providerName}.`,
-                },
-                custom: {label: 'Aprovação personalizada', description: 'Vou configurar manualmente os fluxos de aprovação no Expensify.'},
-            },
-            syncStageName: ({stage}: SyncStageNameConnectionsParams) => {
-                switch (stage) {
-                    case 'gustoSyncTitle':
-                        return 'Sincronizando funcionários do Gusto';
-                    case 'gustoSyncLoadData':
-                        return 'Carregando dados do Gusto';
-                    case 'gustoSyncProvisioning':
-                        return 'Provisionamento de funcionários na política';
-                    case 'zenefitsSyncTitle':
-                        return 'Sincronizando funcionários da TriNet';
-                    case 'zenefitsSyncLoadData':
-                        return 'Carregando dados do TriNet';
-                    case 'zenefitsSyncProvisioning':
-                        return 'Provisionamento de funcionários na política';
-                    case 'jobDone':
-                        return 'Aguardando o carregamento dos dados importados';
-                    default: {
-                        return `Tradução ausente para a etapa: ${stage}`;
-                    }
-                }
-            },
-            syncResults: {
-                title: (provider: string) => `Sincronização com ${provider} concluída`,
-                successTitle: (provider: string) => `Conexão com ${provider} sincronizada com sucesso!`,
-                added: 'Adicionado',
-                removed: 'Removido',
-                skipped: 'Ignorado',
-                employeeCount: () => ({
-                    one: '1 funcionário',
-                    other: (count: number) => `${count} funcionários`,
-                }),
-            },
-            gusto: {
-                title: 'Gusto',
-            },
-            zenefits: {
-                title: 'TriNet',
-            },
-            syncingModalTitle: 'Sua conexão está sincronizando',
-            syncingModalDescription: 'A primeira conexão pode levar algum tempo. Você será notificado sobre quaisquer erros.',
-            syncing: 'Sincronizando funcionários',
-            mergeHR: {
-                completeSetup: 'Concluir configuração',
-                setupIncomplete: (setupLink: string | undefined) =>
-                    `<muted-text-label>Conectado. ${setupLink ? `<a href="${setupLink}">Concluir configuração</a>` : 'Concluir configuração'} para importar funcionários.</muted-text-label>`,
-                groups: {title: 'Grupos', description: 'Escolha os grupos de funcionários que você gostaria de sincronizar com este workspace'},
-            },
-        },
-        emptyDomain: {
-            title: 'Aumente sua segurança com domínios',
-            subtitle: 'Exija que os membros do seu domínio façam login via logon único, restrinja a criação de workspaces e muito mais.',
-        },
     },
     getAssistancePage: {
         title: 'Obter ajuda',
@@ -7488,7 +6484,6 @@ Adicione mais regras de gasto para proteger o fluxo de caixa da empresa.`,
             symbols: 'Símbolos',
             flags: 'Bandeiras',
         },
-        emojiNotSelected: 'Emoji não selecionado',
     },
     newRoomPage: {
         newRoom: 'Nova sala',
@@ -7501,7 +6496,7 @@ Adicione mais regras de gasto para proteger o fluxo de caixa da empresa.`,
         public_announceDescription: 'Qualquer pessoa pode encontrar esta sala',
         createRoom: 'Criar sala',
         roomAlreadyExistsError: 'Já existe uma sala com esse nome',
-        roomNameReservedError: (reservedName: string) => `${reservedName} é uma sala padrão em todos os espaços de trabalho. Escolha outro nome.`,
+        roomNameReservedError: ({reservedName}: RoomNameReservedErrorParams) => `${reservedName} é uma sala padrão em todos os espaços de trabalho. Escolha outro nome.`,
         roomNameInvalidError: 'Nomes de sala podem incluir apenas letras minúsculas, números e hifens',
         pleaseEnterRoomName: 'Insira um nome para a sala',
         pleaseSelectWorkspace: 'Selecione um workspace',
@@ -7509,7 +6504,7 @@ Adicione mais regras de gasto para proteger o fluxo de caixa da empresa.`,
             const actor = actorName ? `${actorName} ` : '';
             return isExpenseReport ? `${actor}renomeado para "${newName}" (antes "${oldName}")` : `${actor}renomeou esta sala para "${newName}" (anteriormente "${oldName}")`;
         },
-        roomRenamedTo: (newName: string) => `Sala renomeada para ${newName}`,
+        roomRenamedTo: ({newName}: RoomRenamedToParams) => `Sala renomeada para ${newName}`,
         social: 'social',
         selectAWorkspace: 'Selecione um workspace',
         growlMessageOnRenameError: 'Não foi possível renomear a sala do workspace. Verifique sua conexão e tente novamente.',
@@ -7549,14 +6544,14 @@ Adicione mais regras de gasto para proteger o fluxo de caixa da empresa.`,
             previousAddress ? `alterou o endereço da empresa para "${newAddress}" (antes "${previousAddress}")` : `definir o endereço da empresa como "${newAddress}"`,
         addApprovalRule: (approverEmail: string, approverName: string, field: string, name: string) => `adicionou ${approverName} (${approverEmail}) como aprovador de ${field} "${name}"`,
         deleteApprovalRule: (approverEmail: string, approverName: string, field: string, name: string) => `removeu ${approverName} (${approverEmail}) como aprovador de ${field} "${name}"`,
-        updateApprovalRule: (field: string, name: string, newApproverEmail: string, newApproverName: string | undefined, oldApproverEmail: string, oldApproverName: string | undefined) => {
+        updateApprovalRule: ({field, name, newApproverEmail, newApproverName, oldApproverEmail, oldApproverName}: UpdatedPolicyApprovalRuleParams) => {
             const formatApprover = (displayName?: string, email?: string) => (displayName ? `${displayName} (${email})` : email);
             return `alterou o aprovador de ${field} "${name}" para ${formatApprover(newApproverName, newApproverEmail)} (antes ${formatApprover(oldApproverName, oldApproverEmail)})`;
         },
-        addCategory: (categoryName: string) => `adicionou a categoria "${categoryName}"`,
-        deleteCategory: (categoryName: string) => `removeu a categoria "${categoryName}"`,
-        updateCategory: (categoryName: string, oldValue: boolean) => `${oldValue ? 'desativado' : 'ativado'} a categoria "${categoryName}"`,
-        updateCategoryPayrollCode: (categoryName: string, newValue?: string, oldValue?: string) => {
+        addCategory: ({categoryName}: UpdatedPolicyCategoryParams) => `adicionou a categoria "${categoryName}"`,
+        deleteCategory: ({categoryName}: UpdatedPolicyCategoryParams) => `removeu a categoria "${categoryName}"`,
+        updateCategory: ({oldValue, categoryName}: UpdatedPolicyCategoryParams) => `${oldValue ? 'desativado' : 'ativado'} a categoria "${categoryName}"`,
+        updateCategoryPayrollCode: ({oldValue, categoryName, newValue}: UpdatedPolicyCategoryGLCodeParams) => {
             if (!oldValue) {
                 return `adicionou o código de folha de pagamento "${newValue}" à categoria "${categoryName}"`;
             }
@@ -7565,7 +6560,7 @@ Adicione mais regras de gasto para proteger o fluxo de caixa da empresa.`,
             }
             return `alterou o código de folha de pagamento da categoria "${categoryName}" para “${newValue}” (antes “${oldValue}”)`;
         },
-        updateCategoryGLCode: (categoryName: string, newValue?: string, oldValue?: string) => {
+        updateCategoryGLCode: ({oldValue, categoryName, newValue}: UpdatedPolicyCategoryGLCodeParams) => {
             if (!oldValue) {
                 return `adicionou o código GL "${newValue}” à categoria "${categoryName}"`;
             }
@@ -7574,10 +6569,10 @@ Adicione mais regras de gasto para proteger o fluxo de caixa da empresa.`,
             }
             return `alterou o código GL da categoria “${categoryName}” para “${newValue}” (antes “${oldValue}”)`;
         },
-        updateAreCommentsRequired: (categoryName: string, oldValue: boolean) => {
+        updateAreCommentsRequired: ({oldValue, categoryName}: UpdatedPolicyCategoryParams) => {
             return `alterou a descrição da categoria "${categoryName}" para ${!oldValue ? 'obrigatório' : 'não obrigatório'} (antes ${!oldValue ? 'não obrigatório' : 'obrigatório'})`;
         },
-        updateCategoryMaxExpenseAmount: (categoryName: string, newAmount?: string, oldAmount?: string) => {
+        updateCategoryMaxExpenseAmount: ({categoryName, oldAmount, newAmount}: UpdatedPolicyCategoryMaxExpenseAmountParams) => {
             if (newAmount && !oldAmount) {
                 return `adicionou um valor máximo de ${newAmount} à categoria "${categoryName}"`;
             }
@@ -7586,26 +6581,26 @@ Adicione mais regras de gasto para proteger o fluxo de caixa da empresa.`,
             }
             return `alterou o valor máximo da categoria "${categoryName}" para ${newAmount} (antes ${oldAmount})`;
         },
-        updateCategoryExpenseLimitType: (categoryName: string, newValue: string, oldValue?: string) => {
+        updateCategoryExpenseLimitType: ({categoryName, oldValue, newValue}: UpdatedPolicyCategoryExpenseLimitTypeParams) => {
             if (!oldValue) {
                 return `adicionou um tipo de limite de ${newValue} à categoria "${categoryName}"`;
             }
             return `alterou o tipo de limite da categoria "${categoryName}" para ${newValue} (antes ${oldValue})`;
         },
-        updateCategoryMaxAmountNoReceipt: (categoryName: string, newValue: string, oldValue?: string) => {
+        updateCategoryMaxAmountNoReceipt: ({categoryName, oldValue, newValue}: UpdatedPolicyCategoryMaxAmountNoReceiptParams) => {
             if (!oldValue) {
                 return `atualizou a categoria "${categoryName}" alterando Recibos para ${newValue}`;
             }
             return `alterou a categoria "${categoryName}" para ${newValue} (antes ${oldValue})`;
         },
-        updateCategoryMaxAmountNoItemizedReceipt: (categoryName: string, oldValue: string | undefined, newValue: string) => {
+        updateCategoryMaxAmountNoItemizedReceipt: ({categoryName, oldValue, newValue}: UpdatedPolicyCategoryMaxAmountNoReceiptParams) => {
             if (!oldValue) {
                 return `atualizou a categoria "${categoryName}" alterando Recibos detalhados para ${newValue}`;
             }
             return `alterou a categoria "${categoryName}" Itens detalhados de recibos para ${newValue} (antes ${oldValue})`;
         },
-        setCategoryName: (oldName: string, newName: string) => `renomeou a categoria "${oldName}" para "${newName}"`,
-        updatedDescriptionHint: (categoryName: string, newValue?: string, oldValue?: string) => {
+        setCategoryName: ({oldName, newName}: UpdatedPolicyCategoryNameParams) => `renomeou a categoria "${oldName}" para "${newName}"`,
+        updatedDescriptionHint: ({categoryName, oldValue, newValue}: UpdatedPolicyCategoryDescriptionHintTypeParams) => {
             if (!newValue) {
                 return `removeu a dica de descrição "${oldValue}" da categoria "${categoryName}"`;
             }
@@ -7613,42 +6608,43 @@ Adicione mais regras de gasto para proteger o fluxo de caixa da empresa.`,
                 ? `adicionou a dica de descrição "${newValue}" à categoria "${categoryName}"`
                 : `alterou a dica de descrição da categoria "${categoryName}" para “${newValue}” (antes “${oldValue}”)`;
         },
-        updateTagListName: (oldName: string, newName: string) => `alterou o nome da lista de tags para "${newName}" (antes "${oldName}")`,
-        addTag: (tagListName: string, tagName?: string) => `adicionou a tag "${tagName}" à lista "${tagListName}"`,
-        updateTagName: (tagListName: string, newName: string, oldName: string) => `atualizou a lista de tags "${tagListName}" alterando a tag "${oldName}" para "${newName}"`,
-        updateTagEnabled: (tagListName: string, tagName?: string, enabled?: boolean) => `${enabled ? 'ativado' : 'desativado'} a tag "${tagName}" na lista "${tagListName}"`,
-        deleteTag: (tagListName: string, tagName?: string) => `removeu a tag "${tagName}" da lista "${tagListName}"`,
-        deleteMultipleTags: (count?: string, tagListName?: string) => `removeu "${count}" tags da lista "${tagListName}"`,
-        updateTag: (tagListName: string, newValue: string, tagName: string, updatedField: string, oldValue?: string) => {
+        updateTagListName: ({oldName, newName}: UpdatedPolicyCategoryNameParams) => `alterou o nome da lista de tags para "${newName}" (antes "${oldName}")`,
+        addTag: ({tagListName, tagName}: UpdatedPolicyTagParams) => `adicionou a tag "${tagName}" à lista "${tagListName}"`,
+        updateTagName: ({tagListName, newName, oldName}: UpdatedPolicyTagNameParams) => `atualizou a lista de tags "${tagListName}" alterando a tag "${oldName}" para "${newName}"`,
+        updateTagEnabled: ({tagListName, tagName, enabled}: UpdatedPolicyTagParams) => `${enabled ? 'ativado' : 'desativado'} a tag "${tagName}" na lista "${tagListName}"`,
+        deleteTag: ({tagListName, tagName}: UpdatedPolicyTagParams) => `removeu a tag "${tagName}" da lista "${tagListName}"`,
+        deleteMultipleTags: ({count, tagListName}: UpdatedPolicyTagParams) => `removeu "${count}" tags da lista "${tagListName}"`,
+        updateTag: ({tagListName, newValue, tagName, updatedField, oldValue}: UpdatedPolicyTagFieldParams) => {
             if (oldValue) {
                 return `atualizou a tag "${tagName}" na lista "${tagListName}" alterando ${updatedField} para "${newValue}" (antes "${oldValue}")`;
             }
             return `atualizou a tag "${tagName}" na lista "${tagListName}" adicionando um(a) ${updatedField} de "${newValue}"`;
         },
-        updateCustomUnit: (customUnitName: string, newValue: string, oldValue: string, updatedField: string) =>
+        updateCustomUnit: ({customUnitName, newValue, oldValue, updatedField}: UpdatePolicyCustomUnitParams) =>
             `alterou o campo ${updatedField} da unidade personalizada ${customUnitName} para "${newValue}" (antes "${oldValue}")`,
-        updateCustomUnitTaxEnabled: (newValue: boolean) => `rastreamento de impostos em taxas de distância ${newValue ? 'ativado' : 'desativado'}`,
-        addCustomUnitRate: (customUnitName: string, rateName: string) => `adicionou a taxa de ${customUnitName} "${rateName}"`,
-        updatedCustomUnitRate: (customUnitName: string, customUnitRateName: string, updatedField: string, newValue: string, oldValue: string) =>
+        updateCustomUnitTaxEnabled: ({newValue}: UpdatePolicyCustomUnitTaxEnabledParams) => `rastreamento de impostos em taxas de distância ${newValue ? 'ativado' : 'desativado'}`,
+        addCustomUnitRate: ({customUnitName, rateName}: AddOrDeletePolicyCustomUnitRateParams) => `adicionou uma nova taxa de ${customUnitName} "${rateName}"`,
+        updatedCustomUnitRate: ({customUnitName, customUnitRateName, newValue, oldValue, updatedField}: UpdatedPolicyCustomUnitRateParams) =>
             `alterou a taxa de ${customUnitName} ${updatedField} "${customUnitRateName}" para "${newValue}" (antes "${oldValue}")`,
-        updatedCustomUnitTaxRateExternalID: (customUnitRateName: string, newValue: string, newTaxPercentage: string, oldTaxPercentage?: string, oldValue?: string) => {
+        updatedCustomUnitTaxRateExternalID: ({customUnitRateName, newValue, newTaxPercentage, oldTaxPercentage, oldValue}: UpdatedPolicyCustomUnitTaxRateExternalIDParams) => {
             if (oldTaxPercentage && oldValue) {
                 return `alterou a alíquota de imposto na tarifa de distância "${customUnitRateName}" para "${newValue} (${newTaxPercentage})" (anteriormente "${oldValue} (${oldTaxPercentage})")`;
             }
             return `adicionou a alíquota de imposto "${newValue} (${newTaxPercentage})" à tarifa de distância "${customUnitRateName}"`;
         },
-        updatedCustomUnitTaxClaimablePercentage: (customUnitRateName: string, newValue: number, oldValue?: number) => {
+        updatedCustomUnitTaxClaimablePercentage: ({customUnitRateName, newValue, oldValue}: UpdatedPolicyCustomUnitTaxClaimablePercentageParams) => {
             if (oldValue) {
                 return `alterou a parte recuperável de impostos na taxa de distância "${customUnitRateName}" para "${newValue}" (antes "${oldValue}")`;
             }
             return `adicionou uma parte recuperável de impostos de "${newValue}" à taxa de distância "${customUnitRateName}"`;
         },
-        updatedCustomUnitRateName: (customUnitName: string, oldValue: string, newValue: string) => `renomeou a taxa de ${customUnitName} de "${oldValue}" para "${newValue}"`,
-        updatedCustomUnitRateEnabled: (customUnitName: string, customUnitRateName: string, newValue: boolean) => {
+        updatedCustomUnitRateEnabled: ({customUnitName, customUnitRateName, newValue}: UpdatedPolicyCustomUnitRateEnabledParams) => {
             return `${newValue ? 'ativado' : 'desativado'} a taxa de ${customUnitName} "${customUnitRateName}"`;
         },
-        deleteCustomUnitRate: (customUnitName: string, rateName: string) => `removeu a taxa "${rateName}" da unidade personalizada "${customUnitName}"`,
-        updateReportFieldDefaultValue: (defaultValue?: string, fieldName?: string) => `definir o valor padrão do campo de relatório "${fieldName}" como "${defaultValue}"`,
+        deleteCustomUnitRate: ({customUnitName, rateName}: AddOrDeletePolicyCustomUnitRateParams) => `removeu a taxa "${rateName}" da unidade personalizada "${customUnitName}"`,
+        addedReportField: ({fieldType, fieldName}: AddedOrDeletedPolicyReportFieldParams) => `adicionou o campo de relatório de ${fieldType} "${fieldName}"`,
+        updateReportFieldDefaultValue: ({defaultValue, fieldName}: UpdatedPolicyReportFieldDefaultValueParams) =>
+            `definir o valor padrão do campo de relatório "${fieldName}" como "${defaultValue}"`,
         addedReportFieldOption: (fieldName: string, optionName: string) => `adicionou a opção "${optionName}" ao campo de relatório "${fieldName}"`,
         removedReportFieldOption: (fieldName: string, optionName: string) => `removeu a opção "${optionName}" do campo de relatório "${fieldName}"`,
         updateReportFieldOptionDisabled: (fieldName: string, optionName: string, optionEnabled: boolean) =>
@@ -7660,20 +6656,22 @@ Adicione mais regras de gasto para proteger o fluxo de caixa da empresa.`,
             return `${allEnabled ? 'ativado' : 'desativado'} a opção "${optionName}" para o campo de relatório "${fieldName}", tornando todas as opções ${allEnabled ? 'ativado' : 'desativado'}`;
         },
         deleteReportField: ({fieldType, fieldName}: {fieldType: string; fieldName?: string}) => `removeu o campo de relatório ${fieldType} "${fieldName}"`,
-        preventSelfApproval: (oldValue: string, newValue: string) =>
+        preventSelfApproval: ({oldValue, newValue}: UpdatedPolicyPreventSelfApprovalParams) =>
             `atualizou "Impedir autoaprovação" para "${newValue === 'true' ? 'Ativado' : 'Desativado'}" (anteriormente "${oldValue === 'true' ? 'Ativado' : 'Desativado'}")`,
-        updateMonthlyOffset: (oldValue: string, newValue: string) => {
+        updateMonthlyOffset: ({oldValue, newValue}: UpdatedPolicyFieldWithNewAndOldValueParams) => {
             if (!oldValue) {
                 return `definir a data de envio do relatório mensal para "${newValue}"`;
             }
             return `atualizou a data de envio do relatório mensal para "${newValue}" (anteriormente "${oldValue}")`;
         },
-        updateDefaultBillable: (oldValue: string, newValue: string) => `atualizou "Refaturar despesas para clientes" para "${newValue}" (antes "${oldValue}")`,
-        updateDefaultReimbursable: (oldValue: string, newValue: string) => `atualizou "Padrão de despesa em dinheiro" para "${newValue}" (anteriormente "${oldValue}")`,
-        updateDefaultTitleEnforced: (value: boolean) => `ativou “Aplicar títulos padrão de relatório” ${value ? 'ativado' : 'desligado'}`,
-        changedCustomReportNameFormula: (oldValue: string, newValue: string) => `alterou a fórmula do nome do relatório personalizado para "${newValue}" (antes "${oldValue}")`,
+        updateDefaultBillable: ({oldValue, newValue}: UpdatedPolicyFieldWithNewAndOldValueParams) => `atualizou "Refaturar despesas para clientes" para "${newValue}" (antes "${oldValue}")`,
+        updateDefaultReimbursable: ({oldValue, newValue}: UpdatedPolicyFieldWithNewAndOldValueParams) =>
+            `atualizou "Padrão de despesa em dinheiro" para "${newValue}" (anteriormente "${oldValue}")`,
+        updateDefaultTitleEnforced: ({value}: UpdatedPolicyFieldWithValueParams) => `ativou “Aplicar títulos padrão de relatório” ${value ? 'ativado' : 'desligado'}`,
+        changedCustomReportNameFormula: ({newValue, oldValue}: UpdatedPolicyFieldWithNewAndOldValueParams) =>
+            `alterou a fórmula do nome do relatório personalizado para "${newValue}" (antes "${oldValue}")`,
         renamedWorkspaceNameAction: (oldName: string, newName: string) => `atualizou o nome deste workspace para "${newName}" (anteriormente "${oldName}")`,
-        updateWorkspaceDescription: (newDescription: string, oldDescription: string) =>
+        updateWorkspaceDescription: ({newDescription, oldDescription}: UpdatedPolicyDescriptionParams) =>
             !oldDescription ? `definir a descrição deste workspace como "${newDescription}"` : `atualizou a descrição deste workspace para "${newDescription}" (antes "${oldDescription}")`,
         removedFromApprovalWorkflow: ({submittersNames}: RemovedFromApprovalWorkflowParams) => {
             let joinedNames = '';
@@ -7691,42 +6689,41 @@ Adicione mais regras de gasto para proteger o fluxo de caixa da empresa.`,
         },
         demotedFromWorkspace: (policyName: string, oldRole: string) =>
             `atualizou sua função em ${policyName} de ${oldRole} para usuário. Você foi removido de todos os chats de despesas de solicitantes, exceto do seu próprio.`,
-        updatedWorkspaceCurrencyAction: (oldCurrency: string, newCurrency: string) => `atualizou a moeda padrão para ${newCurrency} (anteriormente ${oldCurrency})`,
-        updatedWorkspaceFrequencyAction: (oldFrequency: string, newFrequency: string) =>
+        updatedWorkspaceCurrencyAction: ({oldCurrency, newCurrency}: UpdatedPolicyCurrencyParams) => `atualizou a moeda padrão para ${newCurrency} (anteriormente ${oldCurrency})`,
+        updatedWorkspaceFrequencyAction: ({oldFrequency, newFrequency}: UpdatedPolicyFrequencyParams) =>
             `atualizou a frequência de preenchimento automático para "${newFrequency}" (antes "${oldFrequency}")`,
         updateApprovalMode: ({newValue, oldValue}: ChangeFieldParams) => `atualizou o modo de aprovação para "${newValue}" (antes "${oldValue}")`,
         upgradedWorkspace: 'atualizou este workspace para o plano Control',
         forcedCorporateUpgrade: `Este workspace foi atualizado para o plano Control. Clique <a href="${CONST.COLLECT_UPGRADE_HELP_URL}">aqui</a> para mais informações.`,
         downgradedWorkspace: 'rebaixou este espaço de trabalho para o plano Collect',
-        updatedAuditRate: (oldAuditRate: number, newAuditRate: number) =>
+        updatedAuditRate: ({oldAuditRate, newAuditRate}: UpdatedPolicyAuditRateParams) =>
             `alterou a taxa de relatórios encaminhados aleatoriamente para aprovação manual para ${Math.round(newAuditRate * 100)}% (antes era ${Math.round(oldAuditRate * 100)}%)`,
-        updatedManualApprovalThreshold: (oldLimit: string, newLimit: string) => `alterou o limite de aprovação manual para todas as despesas para ${newLimit} (anteriormente ${oldLimit})`,
+        updatedManualApprovalThreshold: ({oldLimit, newLimit}: UpdatedPolicyManualApprovalThresholdParams) =>
+            `alterou o limite de aprovação manual para todas as despesas para ${newLimit} (anteriormente ${oldLimit})`,
         updatedFeatureEnabled: ({enabled, featureName}: {enabled: boolean; featureName: string}) => {
             switch (featureName) {
                 case 'categories':
                     return `${enabled ? 'ativado' : 'desativado'} categorias`;
                 case 'tags':
-                    return `${enabled ? 'ativado' : 'desativado'} etiquetas`;
+                    return `${enabled ? 'ativado' : 'desativado'} tags`;
                 case 'workflows':
-                    return `${enabled ? 'ativado' : 'desativado'} fluxos de trabalho`;
+                    return `fluxos de trabalho ${enabled ? 'ativado' : 'desativado'}`;
                 case 'distance rates':
-                    return `${enabled ? 'ativado' : 'desativado'} tarifas de distância`;
+                    return `Tarifas de distância ${enabled ? 'ativado' : 'desativado'}`;
                 case 'accounting':
-                    return `Contabilidade ${enabled ? 'ativado' : 'desativado'}`;
+                    return `${enabled ? 'ativado' : 'desativado'} contabilidade`;
                 case 'Expensify Cards':
                     return `${enabled ? 'ativado' : 'desativado'} Cartões Expensify`;
-                case 'travel invoicing':
-                    return `Faturamento de viagens ${enabled ? 'ativado' : 'desativado'}`;
                 case 'company cards':
                     return `${enabled ? 'ativado' : 'desativado'} cartões corporativos`;
                 case 'invoicing':
                     return `Faturamento de ${enabled ? 'ativado' : 'desativado'}`;
                 case 'per diem':
-                    return `${enabled ? 'ativado' : 'desativado'} de diária`;
+                    return `${enabled ? 'ativado' : 'desativado'} por dia`;
                 case 'receipt partners':
                     return `${enabled ? 'ativado' : 'desativado'} parceiros de recibos`;
                 case 'rules':
-                    return `Regras ${enabled ? 'ativado' : 'desativado'}`;
+                    return `${enabled ? 'ativado' : 'desativado'} regras`;
                 case 'tax tracking':
                     return `Rastreamento de impostos ${enabled ? 'ativado' : 'desativado'}`;
                 default:
@@ -7797,15 +6794,12 @@ Adicione mais regras de gasto para proteger o fluxo de caixa da empresa.`,
             oldValue ? `alterou o nome da empresa da fatura para "${newValue}" (antes "${oldValue}")` : `definir o nome da empresa na fatura como "${newValue}"`,
         changedInvoiceCompanyWebsite: ({newValue, oldValue}: {newValue: string; oldValue?: string}) =>
             oldValue ? `alterou o site da empresa da fatura para "${newValue}" (antes "${oldValue}")` : `definir o site da empresa da fatura como "${newValue}"`,
-        changedReimburser: (newReimburser: string, previousReimburser?: string) =>
+        changedReimburser: ({newReimburser, previousReimburser}: UpdatedPolicyReimburserParams) =>
             previousReimburser ? `alterou o pagador autorizado para "${newReimburser}" (anteriormente "${previousReimburser}")` : `alterou o pagador autorizado para "${newReimburser}"`,
-        updateReimbursementEnabled: (enabled: boolean) => `reembolsos ${enabled ? 'ativado' : 'desativado'}`,
-        updateCustomTaxName: (oldName: string, newName: string) => `alterou o nome do imposto personalizado para "${newName}" (antes "${oldName}")`,
-        updateCurrencyDefaultTax: (oldName: string, newName: string) => `alterou a taxa de imposto padrão da moeda do workspace para "${newName}" (anteriormente "${oldName}")`,
-        updateForeignCurrencyDefaultTax: (oldName: string, newName: string) => `alterou a alíquota de imposto padrão em moeda estrangeira para "${newName}" (anteriormente "${oldName}")`,
-        addTax: (taxName: string) => `adicionou o imposto "${taxName}"`,
-        deleteTax: (taxName: string) => `removeu o imposto "${taxName}"`,
-        updateTax: (oldValue?: string | boolean | number, taxName?: string, updatedField?: string, newValue?: string | boolean | number) => {
+        updateReimbursementEnabled: ({enabled}: UpdatedPolicyReimbursementEnabledParams) => `reembolsos ${enabled ? 'ativado' : 'desativado'}`,
+        addTax: ({taxName}: UpdatedPolicyTaxParams) => `adicionou o imposto "${taxName}"`,
+        deleteTax: ({taxName}: UpdatedPolicyTaxParams) => `removeu o imposto "${taxName}"`,
+        updateTax: ({oldValue, taxName, updatedField, newValue}: UpdatedPolicyTaxParams) => {
             if (!updatedField) {
                 return '';
             }
@@ -7827,31 +6821,29 @@ Adicione mais regras de gasto para proteger o fluxo de caixa da empresa.`,
                 }
             }
         },
-        setReceiptRequiredAmount: (newValue: string) => `definir valor exigido do recibo como "${newValue}"`,
-        changedReceiptRequiredAmount: (oldValue: string, newValue: string) => `alterou o valor obrigatório do recibo para "${newValue}" (antes "${oldValue}")`,
-        removedReceiptRequiredAmount: (oldValue: string) => `removeu o valor obrigatório do recibo (antes era "${oldValue}")`,
-        setItemizedReceiptRequiredAmount: (newValue: string) => `definir o valor obrigatório do recibo detalhado como "${newValue}"`,
-        changedItemizedReceiptRequiredAmount: (oldValue: string, newValue: string) => `alterou o valor obrigatório do recibo detalhado para "${newValue}" (antes "${oldValue}")`,
-        removedItemizedReceiptRequiredAmount: (oldValue: string) => `removeu o valor exigido de recibo detalhado (antes era "${oldValue}")`,
-        setMaxExpenseAmount: (newValue: string) => `definir valor máximo da despesa como "${newValue}"`,
-        changedMaxExpenseAmount: (oldValue: string, newValue: string) => `alterou o valor máximo da despesa para "${newValue}" (antes "${oldValue}")`,
-        removedMaxExpenseAmount: (oldValue: string) => `removeu o valor máximo de despesa (anteriormente "${oldValue}")`,
-        setMaxExpenseAge: (newValue: string) => `definir idade máxima da despesa como "${newValue}" dias`,
-        changedMaxExpenseAge: (oldValue: string, newValue: string) => `alterou a idade máxima da despesa para "${newValue}" dias (antes "${oldValue}")`,
-        removedMaxExpenseAge: (oldValue: string) => `removeu a idade máxima de despesa (anteriormente "${oldValue}" dias)`,
-        updateCategories: (count: number) => `atualizou ${count} categorias`,
-        updateTagList: (tagListName: string) => `atualizou as tags na lista "${tagListName}"`,
-        updateTagListRequired: (tagListsName: string, isRequired: boolean) => `alterou a lista de tags "${tagListsName}" para ${isRequired ? 'obrigatório' : 'não obrigatório'}`,
+        setReceiptRequiredAmount: ({newValue}: UpdatedPolicyFieldWithNewAndOldValueParams) => `definir valor exigido do recibo como "${newValue}"`,
+        changedReceiptRequiredAmount: ({oldValue, newValue}: UpdatedPolicyFieldWithNewAndOldValueParams) => `alterou o valor obrigatório do recibo para "${newValue}" (antes "${oldValue}")`,
+        removedReceiptRequiredAmount: ({oldValue}: UpdatedPolicyFieldWithNewAndOldValueParams) => `removeu o valor obrigatório do recibo (antes era "${oldValue}")`,
+        setMaxExpenseAmount: ({newValue}: UpdatedPolicyFieldWithNewAndOldValueParams) => `definir valor máximo da despesa como "${newValue}"`,
+        changedMaxExpenseAmount: ({oldValue, newValue}: UpdatedPolicyFieldWithNewAndOldValueParams) => `alterou o valor máximo da despesa para "${newValue}" (antes "${oldValue}")`,
+        removedMaxExpenseAmount: ({oldValue}: UpdatedPolicyFieldWithNewAndOldValueParams) => `removeu o valor máximo de despesa (anteriormente "${oldValue}")`,
+        setMaxExpenseAge: ({newValue}: UpdatedPolicyFieldWithNewAndOldValueParams) => `definir idade máxima da despesa como "${newValue}" dias`,
+        changedMaxExpenseAge: ({oldValue, newValue}: UpdatedPolicyFieldWithNewAndOldValueParams) => `alterou a idade máxima da despesa para "${newValue}" dias (antes "${oldValue}")`,
+        removedMaxExpenseAge: ({oldValue}: UpdatedPolicyFieldWithNewAndOldValueParams) => `removeu a idade máxima de despesa (anteriormente "${oldValue}" dias)`,
+        updateCategories: ({count}: UpdatedPolicyCategoriesParams) => `atualizou ${count} categorias`,
+        updateTagList: ({tagListName}: UpdatedPolicyTagListParams) => `atualizou as tags na lista "${tagListName}"`,
+        updateTagListRequired: ({tagListsName, isRequired}: UpdatedPolicyTagListRequiredParams) =>
+            `alterou a lista de tags "${tagListsName}" para ${isRequired ? 'obrigatório' : 'não obrigatório'}`,
         importTags: 'importou tags de uma planilha',
         deletedAllTags: 'excluiu todas as tags',
-        updateCustomUnitDefaultCategory: (customUnitName: string, newValue?: string, oldValue?: string) =>
+        updateCustomUnitDefaultCategory: ({customUnitName, newValue, oldValue}: UpdatePolicyCustomUnitDefaultCategoryParams) =>
             `alterou a categoria padrão de ${customUnitName} para "${newValue}" ${oldValue ? `(antes "${oldValue}")` : ''}`,
-        importCustomUnitRates: (customUnitName: string) => `taxas importadas para a unidade personalizada "${customUnitName}"`,
-        updateCustomUnitSubRate: (customUnitName: string, customUnitRateName: string, customUnitSubRateName: string, oldValue: string, newValue: string, updatedField: string) =>
+        importCustomUnitRates: ({customUnitName}: ImportPolicyCustomUnitRatesParams) => `taxas importadas para a unidade personalizada "${customUnitName}"`,
+        updateCustomUnitSubRate: ({customUnitName, customUnitRateName, customUnitSubRateName, oldValue, newValue, updatedField}: UpdatedPolicyCustomUnitSubRateParams) =>
             `alterou a tarifa "${customUnitName}" taxa "${customUnitRateName}" sub‑taxa "${customUnitSubRateName}" ${updatedField} para "${newValue}" (antes "${oldValue}")`,
-        removedCustomUnitSubRate: (customUnitName: string, customUnitRateName: string, removedSubRateName: string) =>
+        removedCustomUnitSubRate: ({customUnitName, customUnitRateName, removedSubRateName}: RemovedPolicyCustomUnitSubRateParams) =>
             `removeu a tarifa "${customUnitName}" tarifa "${customUnitRateName}" subtarifa "${removedSubRateName}"`,
-        addBudget: (frequency: string, entityName: string, entityType: string, shared?: string, individual?: string, notificationThreshold?: number) => {
+        addBudget: ({frequency, entityName, entityType, shared, individual, notificationThreshold}: AddBudgetParams) => {
             const thresholdSuffix = typeof notificationThreshold === 'number' ? `com limite de notificação de “${notificationThreshold}%”` : '';
             if (typeof shared !== 'undefined' && typeof individual !== 'undefined') {
                 return `adicionou ${frequency} orçamento individual de "${individual}" e ${frequency} orçamento compartilhado de "${shared}"${thresholdSuffix} ao(à) ${entityType} "${entityName}"`;
@@ -7861,18 +6853,18 @@ Adicione mais regras de gasto para proteger o fluxo de caixa da empresa.`,
             }
             return `adicionou orçamento compartilhado ${frequency} de "${shared}"${thresholdSuffix} ao/à ${entityType} "${entityName}"`;
         },
-        updateBudget: (
-            entityType: string,
-            entityName: string,
-            oldFrequency?: string,
-            newFrequency?: string,
-            oldIndividual?: string,
-            newIndividual?: string,
-            oldShared?: string,
-            newShared?: string,
-            oldNotificationThreshold?: number,
-            newNotificationThreshold?: number,
-        ) => {
+        updateBudget: ({
+            entityType,
+            entityName,
+            oldFrequency,
+            newFrequency,
+            oldIndividual,
+            newIndividual,
+            oldShared,
+            newShared,
+            oldNotificationThreshold,
+            newNotificationThreshold,
+        }: UpdatedBudgetParams) => {
             const frequencyChanged = !!(newFrequency && oldFrequency !== newFrequency);
             const sharedChanged = !!(newShared && oldShared !== newShared);
             const individualChanged = !!(newIndividual && oldIndividual !== newIndividual);
@@ -7907,7 +6899,7 @@ Adicione mais regras de gasto para proteger o fluxo de caixa da empresa.`,
             }
             return `orçamento atualizado para ${entityType} "${entityName}": ${changesList.join('; ')}`;
         },
-        deleteBudget: (entityType: string, entityName: string, frequency?: string, individual?: string, shared?: string, notificationThreshold?: number) => {
+        deleteBudget: ({entityType, entityName, frequency, individual, shared, notificationThreshold}: DeleteBudgetParams) => {
             const thresholdSuffix = typeof notificationThreshold === 'number' ? `com limite de notificação de “${notificationThreshold}%”` : '';
             if (shared && individual) {
                 return `removeu o orçamento compartilhado de ${frequency} "${shared}" e o orçamento individual de "${individual}"${thresholdSuffix} do(a) ${entityType} "${entityName}"`;
@@ -7920,125 +6912,48 @@ Adicione mais regras de gasto para proteger o fluxo de caixa da empresa.`,
             }
             return `removeu o orçamento do(a) ${entityType} "${entityName}"`;
         },
-        updatedTimeEnabled: (enabled?: boolean) => {
+        updatedTimeEnabled: ({enabled}: UpdatedPolicyTimeEnabledParams) => {
             return `${enabled ? 'ativado' : 'desativado'} controle de tempo`;
         },
-        updatedTimeRate: (newRate?: string, oldRate?: string) => {
+        updatedTimeRate: ({newRate, oldRate}: UpdatedPolicyTimeRateParams) => {
             return `alterou a tarifa horária para "${newRate}" (antes "${oldRate}")`;
         },
         addedProhibitedExpense: ({prohibitedExpense}: {prohibitedExpense: string}) => `adicionou "${prohibitedExpense}" às despesas proibidas`,
         removedProhibitedExpense: ({prohibitedExpense}: {prohibitedExpense: string}) => `removeu "${prohibitedExpense}" das despesas proibidas`,
-        updatedReimbursementChoice: (newReimbursementChoice: string, oldReimbursementChoice: string) =>
+        updatedReimbursementChoice: ({newReimbursementChoice, oldReimbursementChoice}: UpdatedPolicyReimbursementChoiceParams) =>
             `alterou o método de reembolso para "${newReimbursementChoice}" (antes "${oldReimbursementChoice}")`,
         setAutoJoin: ({enabled}: {enabled: boolean}) => `${enabled ? 'ativado' : 'desativado'} pré-aprovação de solicitações para entrar no workspace`,
-        updatedDefaultTitle: (newDefaultTitle: string, oldDefaultTitle: string) =>
+        updatedDefaultTitle: ({newDefaultTitle, oldDefaultTitle}: UpdatedPolicyDefaultTitleParams) =>
             `alterou a fórmula do nome do relatório personalizado para "${newDefaultTitle}" (antes "${oldDefaultTitle}")`,
-        updatedOwnership: (oldOwnerEmail: string, oldOwnerName: string, policyName: string) => `assumiu a propriedade de ${policyName} de ${oldOwnerName} (${oldOwnerEmail})`,
-        updatedAutoHarvesting: (enabled: boolean) => `Envio agendado ${enabled ? 'ativado' : 'desativado'}`,
-        updatedIndividualBudgetNotification: (
-            budgetAmount: string,
-            budgetFrequency: string,
-            budgetName: string,
-            budgetTypeForNotificationMessage: string,
-            thresholdPercentage: number,
-            totalSpend: number,
-            unsubmittedSpend: number,
-            awaitingApprovalSpend: number,
-            approvedReimbursedClosedSpend: number,
-            summaryLink?: string,
-            userEmail?: string,
-        ) =>
+        updatedOwnership: ({oldOwnerEmail, oldOwnerName, policyName}: UpdatedPolicyOwnershipParams) => `assumiu a propriedade de ${policyName} de ${oldOwnerName} (${oldOwnerEmail})`,
+        updatedAutoHarvesting: ({enabled}: UpdatedPolicyAutoHarvestingParams) => `Envio agendado ${enabled ? 'ativado' : 'desativado'}`,
+        updatedIndividualBudgetNotification: ({
+            budgetAmount,
+            budgetFrequency,
+            budgetName,
+            budgetTypeForNotificationMessage,
+            summaryLink,
+            thresholdPercentage,
+            totalSpend,
+            unsubmittedSpend,
+            userEmail,
+            awaitingApprovalSpend,
+            approvedReimbursedClosedSpend,
+        }: UpdatedPolicyBudgetNotificationParams) =>
             `Atenção! Este espaço de trabalho tem um orçamento ${budgetFrequency} de “${budgetAmount}” para o ${budgetTypeForNotificationMessage} “${budgetName}”. ${userEmail} está atualmente em ${approvedReimbursedClosedSpend}, o que ultrapassa ${thresholdPercentage}% do orçamento. Também há ${awaitingApprovalSpend} aguardando aprovação e ${unsubmittedSpend} que ainda não foi enviado, totalizando ${totalSpend}.${summaryLink ? `<a href="${summaryLink}">Aqui está um relatório</a> com todas essas despesas para o seu controle!` : ''}`,
-        updatedSharedBudgetNotification: (
-            budgetAmount: string,
-            budgetFrequency: string,
-            budgetName: string,
-            budgetTypeForNotificationMessage: string,
-            summaryLink: string | undefined,
-            thresholdPercentage: number,
-            totalSpend: number,
-            unsubmittedSpend: number,
-            awaitingApprovalSpend: number,
-            approvedReimbursedClosedSpend: number,
-        ) =>
+        updatedSharedBudgetNotification: ({
+            budgetAmount,
+            budgetFrequency,
+            budgetName,
+            budgetTypeForNotificationMessage,
+            summaryLink,
+            thresholdPercentage,
+            totalSpend,
+            unsubmittedSpend,
+            awaitingApprovalSpend,
+            approvedReimbursedClosedSpend,
+        }: UpdatedPolicyBudgetNotificationParams) =>
             `Atenção! Este workspace tem um orçamento ${budgetFrequency} de "${budgetAmount}" para o(a) ${budgetTypeForNotificationMessage} "${budgetName}". No momento você está em ${approvedReimbursedClosedSpend}, o que está acima de ${thresholdPercentage}% do orçamento. Há também ${awaitingApprovalSpend} aguardando aprovação e ${unsubmittedSpend} que ainda não foi enviado, totalizando ${totalSpend}. ${summaryLink ? `<a href="${summaryLink}">Aqui está um relatório</a> com todas essas despesas para o seu controle!` : ''}`,
-        addedCardFeed: (feedName: string) => `adicionou o feed de cartão "${feedName}"`,
-        removedCardFeed: (feedName: string) => `removeu o feed de cartão "${feedName}"`,
-        renamedCardFeed: (newName: string, oldName: string) => `renomeou o feed de cartão para "${newName}" (antes "${oldName}")`,
-        assignedCompanyCard: (email: string, feedName: string, cardLastFour: string) => `atribuiu ${email} ${feedName ? `"${feedName}" ` : ''}cartão empresarial com final ${cardLastFour}`,
-        unassignedCompanyCard: (email: string, feedName: string, cardLastFour: string) =>
-            `cartão corporativo ${feedName ? `"${feedName}" ` : ''}${email} não atribuído com final ${cardLastFour}`,
-        updatedCardFeedLiability: (feedName: string, enabled: boolean) =>
-            `${enabled ? 'ativado' : 'desativado'} titulares de cartão para excluir transações de cartão para o feed de cartão "${feedName}"`,
-        updatedCardFeedStatementPeriod: (feedName: string, newValue?: string, previousValue?: string) =>
-            `changed card feed "${feedName}" statement period end day${newValue ? ` para "${newValue}"` : ''}${previousValue ? `(antes " ${previousValue}")` : ''}`,
-        addedReportField: (fieldType: string, fieldName?: string, defaultValue?: string) =>
-            `adicionou o campo de relatório ${fieldType} "${fieldName}"${defaultValue ? ` com valor padrão "${defaultValue}"` : ''}`,
-        updatedMccGroupCategory: ({mccGroupName, oldCategory, newCategory}: {mccGroupName: string; oldCategory: string; newCategory: string}) =>
-            `alterou a categoria de gasto padrão de "${mccGroupName}" para "${newCategory}" (antes "${oldCategory}")`,
-        updatedRequireCompanyCards: ({enabled}: {enabled: boolean}) => `${enabled ? 'ativado' : 'desativado'} o requisito de compras com cartão corporativo`,
-        expensifyCardRule: {
-            actionVerb: {block: 'bloqueado', allow: 'permitido'},
-            amountOperator: {over: 'acima', under: 'abaixo'},
-            amountFilter: ({operator, amount}: {operator: string; amount: string}) => `valores ${operator} ${amount}`,
-            theCard: 'o cartão',
-            multipleCards: ({count}: {count: number}) => ({
-                one: '1 cartão',
-                other: `${count} cartões`,
-            }),
-            addRule: ({verb, filters, cards}: {verb: string; filters: string; cards: string}) => {
-                let text = verb;
-                if (filters !== '') {
-                    text += ` ${filters}`;
-                }
-                text += ` em ${cards}`;
-                return text;
-            },
-            removeRule: ({cards}: {cards: string}) => `removeu a regra de gasto de ${cards}`,
-            restrictionVerb: {block: 'bloquear', allow: 'permitir apenas'},
-            update: {
-                modeChange: ({fromAction, toAction, cards}: {fromAction: string; toAction: string; cards: string}) =>
-                    `alterou a regra de gasto de ${fromAction} para ${toAction} em ${cards}`,
-                appliedToAdditionalCards: ({count}: {count: number}) => ({
-                    one: 'regra de gasto aplicada a mais 1 cartão',
-                    other: `regra de gasto aplicada a mais ${count} cartões`,
-                }),
-                phraseVerb: {added: 'adicionado', removed: 'removido', changed: 'alterado', set: 'definir', applied: 'aplicado'},
-                bodyMerchant: ({adjective, value}: {adjective: string; value: string}) => (adjective !== '' ? `comerciante ${adjective} '${value}'` : `estabelecimento comercial '${value}'`),
-                bodyMerchantChange: ({adjective, oldValue, newValue}: {adjective: string; oldValue: string; newValue: string}) =>
-                    adjective !== '' ? `${adjective} comerciante de '${oldValue}' para '${newValue}'` : `estabelecimento comercial de '${oldValue}' para '${newValue}'`,
-                bodySpendCategory: ({adjective, value}: {adjective: string; value: string}) =>
-                    adjective !== '' ? `Categoria de gasto ${adjective} '${value}'` : `categoria de gastos '${value}'`,
-                bodySpendCategoryChange: ({adjective, oldValue, newValue}: {adjective: string; oldValue: string; newValue: string}) =>
-                    adjective !== '' ? `Categoria de gasto ${adjective} de '${oldValue}' para '${newValue}'` : `categoria de gasto de '${oldValue}' para '${newValue}'`,
-                bodyMaxAmount: 'valor máximo',
-                bodyMaxAmountSet: ({value}: {value: string}) => `valor máximo até ${value}`,
-                bodyMaxAmountChange: ({oldValue, newValue}: {oldValue: string; newValue: string}) => `valor máximo de ${oldValue} para ${newValue}`,
-                bodyAppliedToAdditionalCards: ({count}: {count: number}) => ({
-                    one: 'regra de gasto para mais 1 cartão',
-                    other: `regra de gasto para mais ${count} cartões`,
-                }),
-                bodyRemovedFromCards: ({cards}: {cards: string}) => `regra de gasto de ${cards}`,
-                composeOnCards: ({content, cards}: {content: string; cards: string}) => `${content} em ${cards}`,
-                composeFromCards: ({content, cards}: {content: string; cards: string}) => `${content} de ${cards}`,
-            },
-        },
-        addCustomUnitRateWithAmount: (rateName: string, rateValue: string) => `adicionou a taxa "${rateName}" de ${rateValue}`,
-        addCustomUnitRateWithAmountAndStartDate: (rateName: string, rateValue: string, startDate: string) =>
-            `adicionou a taxa "${rateName}" de ${rateValue}, válida a partir de ${startDate}`,
-        addCustomUnitRateWithAmountAndEndDate: (rateName: string, rateValue: string, endDate: string) => `adicionou a taxa "${rateName}" de ${rateValue}, válida até ${endDate}`,
-        addCustomUnitRateWithAmountAndDates: (rateName: string, rateValue: string, startDate: string, endDate: string) =>
-            `adicionou a tarifa "${rateName}" de ${rateValue}, válida de ${startDate} a ${endDate}`,
-        updatedCustomUnitRateStartDate: (rateName: string, newDate: string, oldDate?: string) =>
-            oldDate ? `atualizou a data de início da tarifa "${rateName}" para ${newDate} (antes ${oldDate})` : `definir data de início da tarifa "${rateName}" para ${newDate}`,
-        updatedCustomUnitRateEndDate: (rateName: string, newDate: string, oldDate?: string) =>
-            oldDate ? `atualizou a data de término da tarifa "${rateName}" para ${newDate} (antes ${oldDate})` : `definir data de término da tarifa "${rateName}" para ${newDate}`,
-        updatedCustomUnitRateStartAndEndDate: (rateName: string, newStartDate: string, newEndDate: string, oldStartDate?: string, oldEndDate?: string) =>
-            oldStartDate && oldEndDate
-                ? `atualizou a data de início e término da tarifa "${rateName}" para ${newStartDate} - ${newEndDate} (antes ${oldStartDate} - ${oldEndDate})`
-                : `define a data de início e de término da tarifa "${rateName}" para ${newStartDate} - ${newEndDate}`,
-        removedCustomUnitRateStartDate: (rateName: string, oldDate: string) => `removeu a data de início da tarifa "${rateName}" (antes ${oldDate})`,
-        removedCustomUnitRateEndDate: (rateName: string, oldDate: string) => `removeu a data de término da tarifa "${rateName}" (anteriormente ${oldDate})`,
     },
     roomMembersPage: {
         memberNotFound: 'Membro não encontrado.',
@@ -8070,7 +6985,7 @@ Adicione mais regras de gasto para proteger o fluxo de caixa da empresa.`,
         completed: 'Concluído',
         action: 'Concluir',
         messages: {
-            created: (title: string) => `tarefa para ${title}`,
+            created: ({title}: TaskCreatedActionParams) => `tarefa para ${title}`,
             completed: 'marcado como concluído',
             canceled: 'tarefa excluída',
             reopened: 'marcado como incompleto',
@@ -8084,7 +6999,7 @@ Adicione mais regras de gasto para proteger o fluxo de caixa da empresa.`,
         deleteConfirmation: 'Tem certeza de que deseja excluir esta tarefa?',
     },
     statementPage: {
-        title: (year: number | string, monthName: string) => `Extrato de ${monthName} de ${year}`,
+        title: ({year, monthName}: StatementTitleParams) => `Extrato de ${monthName} de ${year}`,
     },
     keyboardShortcutsPage: {
         title: 'Atalhos de teclado',
@@ -8097,8 +7012,6 @@ Adicione mais regras de gasto para proteger o fluxo de caixa da empresa.`,
             newChat: 'Nova tela de chat',
             copy: 'Copiar comentário',
             openDebug: 'Abrir caixa de diálogo de preferências de teste',
-            expenseReportSearch: 'Buscar relatórios de despesas',
-            goToWorkspace: 'Ir para o workspace do relatório atual',
         },
     },
     guides: {
@@ -8108,8 +7021,6 @@ Adicione mais regras de gasto para proteger o fluxo de caixa da empresa.`,
     search: {
         resultsAreLimited: 'Os resultados da pesquisa são limitados.',
         viewResults: 'Ver resultados',
-        applyFilters: 'Aplicar filtros',
-        appliedFilters: 'Filtros aplicados',
         resetFilters: 'Redefinir filtros',
         searchResults: {
             emptyResults: {
@@ -8117,23 +7028,28 @@ Adicione mais regras de gasto para proteger o fluxo de caixa da empresa.`,
                 subtitle: `Tente ajustar seus critérios de pesquisa ou criar algo com o botão +.`,
             },
             emptyExpenseResults: {
-                title: 'Ainda não há despesas',
+                title: 'Você ainda não criou nenhuma despesa',
                 subtitle: 'Crie uma despesa ou faça um test drive do Expensify para saber mais.',
                 subtitleWithOnlyCreateButton: 'Use o botão verde abaixo para criar uma despesa.',
             },
             emptyReportResults: {
-                title: 'Nenhum relatório ainda',
+                title: 'Você ainda não criou nenhum relatório',
                 subtitle: 'Crie um relatório ou faça um test drive do Expensify para saber mais.',
                 subtitleWithOnlyCreateButton: 'Use o botão verde abaixo para criar um relatório.',
             },
             emptyInvoiceResults: {
-                title: 'Ainda não há faturas',
+                title: dedent(`
+                    Você ainda não criou nenhuma
+                    fatura
+                `),
                 subtitle: 'Envie uma fatura ou faça um test drive do Expensify para saber mais.',
                 subtitleWithOnlyCreateButton: 'Use o botão verde abaixo para enviar uma fatura.',
-                subtitleCannotSend: 'Você precisa de um espaço de trabalho com Invoices habilitado para enviar faturas.',
-                subtitleCannotSendWithTestDrive: 'Você precisa de um espaço de trabalho com Invoices habilitado para enviar faturas. Faça um test drive do Expensify para saber mais.',
             },
-            emptyTripResults: {title: 'Nenhuma viagem ainda', subtitle: 'Comece reservando sua primeira viagem abaixo.', buttonText: 'Reservar uma viagem'},
+            emptyTripResults: {
+                title: 'Nenhuma viagem para exibir',
+                subtitle: 'Comece reservando sua primeira viagem abaixo.',
+                buttonText: 'Reservar uma viagem',
+            },
             emptySubmitResults: {
                 title: 'Nenhuma despesa para enviar',
                 subtitle: 'Está tudo certo. Pode comemorar!',
@@ -8161,31 +7077,30 @@ Adicione mais regras de gasto para proteger o fluxo de caixa da empresa.`,
             },
         },
         columns: 'Colunas',
-        editColumns: 'Editar colunas',
         resetColumns: 'Redefinir colunas',
         groupColumns: 'Agrupar colunas',
         expenseColumns: 'Colunas de despesas',
-        saveView: 'Salvar visualização',
+        statements: 'Extratos',
+        unapprovedCash: 'Dinheiro não aprovado',
+        unapprovedCard: 'Cartão não aprovado',
+        reconciliation: 'Conciliação',
+        topSpenders: 'Maiores gastadores',
+        saveSearch: 'Salvar pesquisa',
         deleteSavedSearch: 'Excluir pesquisa salva',
         deleteSavedSearchConfirm: 'Tem certeza de que deseja excluir esta pesquisa?',
         searchName: 'Pesquisar nome',
         savedSearchesMenuItemTitle: 'Salvo',
-        urlCopied: 'URL copiado',
+        topCategories: 'Categorias principais',
+        topMerchants: 'Principais comerciantes',
         groupedExpenses: 'despesas agrupadas',
         bulkActions: {
-            editMultiple: 'Editar múltiplos',
-            editMultipleTitle: 'Editar múltiplas despesas',
-            editMultipleDescription: 'As alterações serão aplicadas a todas as despesas selecionadas e substituirão quaisquer valores definidos anteriormente.',
             approve: 'Aprovar',
             pay: 'Pagar',
             delete: 'Excluir',
             hold: 'Reter',
             unhold: 'Remover bloqueio',
             reject: 'Rejeitar',
-            duplicateExpense: ({count}: {count: number}) => `Duplicar ${count === 1 ? 'despesa' : 'despesas'}`,
             noOptionsAvailable: 'Nenhuma opção disponível para o grupo de despesas selecionado.',
-            undelete: 'Restaurar',
-            duplicateReport: ({count}: {count: number}) => `Duplicar ${count === 1 ? 'relatório' : 'relatórios'}`,
         },
         filtersHeader: 'Filtros',
         filters: {
@@ -8193,14 +7108,11 @@ Adicione mais regras de gasto para proteger o fluxo de caixa da empresa.`,
                 before: (date?: string) => `Antes de ${date ?? ''}`,
                 after: (date?: string) => `Depois de ${date ?? ''}`,
                 on: (date?: string) => `Em ${date ?? ''}`,
-                customDate: 'Data personalizada',
-                customRange: 'Intervalo personalizado',
                 presets: {
                     [CONST.SEARCH.DATE_PRESETS.NEVER]: 'Nunca',
                     [CONST.SEARCH.DATE_PRESETS.LAST_MONTH]: 'Mês passado',
                     [CONST.SEARCH.DATE_PRESETS.THIS_MONTH]: 'Este mês',
-                    [CONST.SEARCH.DATE_PRESETS.YEAR_TO_DATE]: 'Ano até agora',
-                    [CONST.SEARCH.DATE_PRESETS.LAST_12_MONTHS]: 'Últimos 12 meses',
+                    [CONST.SEARCH.DATE_PRESETS.YEAR_TO_DATE]: 'Ano até a data',
                     [CONST.SEARCH.DATE_PRESETS.LAST_STATEMENT]: 'Último extrato',
                 },
             },
@@ -8212,15 +7124,10 @@ Adicione mais regras de gasto para proteger o fluxo de caixa da empresa.`,
             currency: 'Moeda',
             completed: 'Concluído',
             amount: {
-                lessThan: (amount?: string) => `Menos de ${amount ?? ''}`,
-                greaterThan: (amount?: string) => `Maior que ${amount ?? ''}`,
-                between: (greaterThan?: string, lessThan?: string) => {
-                    if (greaterThan && lessThan) {
-                        return `Entre ${greaterThan} e ${lessThan}`;
-                    }
-                    return 'Entre';
-                },
-                equalTo: (amount?: string) => `Igual a ${amount ?? ''}`,
+                lessThan: ({amount}: OptionalParam<RequestAmountParams> = {}) => `Menos de ${amount ?? ''}`,
+                greaterThan: ({amount}: OptionalParam<RequestAmountParams> = {}) => `Maior que ${amount ?? ''}`,
+                between: (greaterThan: string, lessThan: string) => `Entre ${greaterThan} e ${lessThan}`,
+                equalTo: ({amount}: OptionalParam<RequestAmountParams> = {}) => `Igual a ${amount ?? ''}`,
             },
             card: {
                 expensify: 'Expensify',
@@ -8230,9 +7137,8 @@ Adicione mais regras de gasto para proteger o fluxo de caixa da empresa.`,
                 cardFeedName: ({cardFeedBankName, cardFeedLabel}: {cardFeedBankName: string; cardFeedLabel?: string}) =>
                     `Todos os ${cardFeedBankName}${cardFeedLabel ? ` - ${cardFeedLabel}` : ''}`,
                 cardFeedNameCSV: ({cardFeedLabel}: {cardFeedLabel?: string}) => `Todos os cartões CSV importados${cardFeedLabel ? ` - ${cardFeedLabel}` : ''}`,
-                travelInvoicing: 'Faturamento de viagens',
             },
-            reportField: (name: string, value: string) => `${name} é ${value}`,
+            reportField: ({name, value}: OptionalParam<ReportFieldParams>) => `${name} é ${value}`,
             current: 'Atual',
             past: 'Passado',
             submitted: 'Enviado',
@@ -8244,10 +7150,6 @@ Adicione mais regras de gasto para proteger o fluxo de caixa da empresa.`,
             billable: 'Faturável',
             reimbursable: 'Reembolsável',
             purchaseCurrency: 'Moeda de compra',
-            sortOrder: {
-                [CONST.SEARCH.SORT_ORDER.ASC]: 'Ascendente',
-                [CONST.SEARCH.SORT_ORDER.DESC]: 'Descendo',
-            },
             groupBy: {
                 [CONST.SEARCH.GROUP_BY.FROM]: 'De',
                 [CONST.SEARCH.GROUP_BY.CARD]: 'Cartão',
@@ -8264,7 +7166,6 @@ Adicione mais regras de gasto para proteger o fluxo de caixa da empresa.`,
             withdrawalType: {
                 [CONST.SEARCH.WITHDRAWAL_TYPE.EXPENSIFY_CARD]: 'Cartão Expensify',
                 [CONST.SEARCH.WITHDRAWAL_TYPE.REIMBURSEMENT]: 'Reembolso',
-                [CONST.SEARCH.WITHDRAWAL_TYPE.CENTRAL_TRAVEL_INVOICING]: 'Faturamento de viagens',
             },
             is: 'É',
             action: {
@@ -8274,53 +7175,13 @@ Adicione mais regras de gasto para proteger o fluxo de caixa da empresa.`,
                 [CONST.SEARCH.ACTION_FILTERS.EXPORT]: 'Exportar',
             },
         },
-        display: {
-            label: 'Exibir',
-            sortBy: 'Ordenar por',
-            sortOrder: 'Ordem de classificação',
-            groupBy: 'Agrupar por',
-            limitResults: 'Limitar resultados',
-        },
         has: 'Tem',
+        groupBy: 'Agrupar por',
         view: {
             label: 'Visualizar',
             table: 'Tabela',
             bar: 'Bar',
             line: 'Linha',
-            pie: 'Torta',
-        },
-        noCategory: 'Sem categoria',
-        noMerchant: 'Sem comerciante',
-        noTag: 'Sem tag',
-        expenseType: 'Tipo de despesa',
-        withdrawalType: 'Tipo de saque',
-        recentSearches: 'Pesquisas recentes',
-        recentChats: 'Chats recentes',
-        serverResults: 'Resultados da pesquisa',
-        searchIn: 'Pesquisar em',
-        askConcierge: (message: string) => `Perguntar ao Concierge “${message}”`,
-        searchPlaceholder: 'Pesquisar algo...',
-        suggestions: 'Sugestões',
-        suggestionsAvailable: (
-            {
-                count,
-            }: {
-                count: number;
-            },
-            query = '',
-        ) => ({
-            one: `Sugestões disponíveis${query ? ` para ${query}` : ''}. ${count} resultado.`,
-            other: (resultCount: number) => `Sugestões disponíveis${query ? ` para ${query}` : ''}. ${resultCount} resultados.`,
-        }),
-        exportSearchResults: {
-            title: 'Criar exportação',
-            description: 'Uau, são muitos itens! Vamos agrupá-los e o Concierge enviará um arquivo para você em breve.',
-        },
-        exportedTo: 'Exportado para',
-        exportAll: {
-            selectAllMatchingItems: 'Selecionar todos os itens correspondentes',
-            allMatchingItemsSelected: 'Todos os itens correspondentes selecionados',
-            selectAllOnThisPage: 'Selecionar tudo nesta página',
         },
         chartTitles: {
             [CONST.SEARCH.GROUP_BY.FROM]: 'De',
@@ -8338,27 +7199,24 @@ Adicione mais regras de gasto para proteger o fluxo de caixa da empresa.`,
             emptyStateTitle: 'Este relatório não tem despesas.',
             accessPlaceHolder: 'Abrir para ver detalhes',
         },
-        errors: {
-            pleaseSelectDatesForBothFromAndTo: 'Selecione datas para De e Até',
+        noCategory: 'Sem categoria',
+        noMerchant: 'Nenhum estabelecimento',
+        noTag: 'Sem tag',
+        expenseType: 'Tipo de despesa',
+        withdrawalType: 'Tipo de saque',
+        recentSearches: 'Pesquisas recentes',
+        recentChats: 'Conversas recentes',
+        searchIn: 'Pesquisar em',
+        searchPlaceholder: 'Pesquise algo',
+        suggestions: 'Sugestões',
+        exportSearchResults: {
+            title: 'Criar exportação',
+            description: 'Uau, são muitos itens! Vamos agrupá-los e a Concierge enviará um arquivo para você em breve.',
         },
-        spendOverTime: 'Gastos ao longo do tempo',
-        tabs: {
-            expenseReports: 'Relatórios de despesas',
-            reports: 'Relatórios',
-            expenses: 'Despesas',
-            submit: 'Rascunhos',
-            approve: 'Precisa de aprovação',
-            pay: 'Pronto para pagar',
-            accounting: 'Contabilidade',
-            export: 'Aguardando exportação',
-            unapprovedCash: 'Provisões de caixa',
-            unapprovedCard: 'Provisões de cartão',
-            statements: 'Extratos do cartão',
-            reconciliation: 'Conciliação bancária',
-            insights: 'Insights',
-            topSpenders: 'Maiores gastadores',
-            topCategories: 'Principais categorias',
-            topMerchants: 'Principais estabelecimentos',
+        exportedTo: 'Exportado para',
+        exportAll: {
+            selectAllMatchingItems: 'Selecione todos os itens correspondentes',
+            allMatchingItemsSelected: 'Todos os itens correspondentes selecionados',
         },
     },
     genericErrorPage: {
@@ -8415,6 +7273,7 @@ Adicione mais regras de gasto para proteger o fluxo de caixa da empresa.`,
             emptyReportConfirmationTitle: 'Você já tem um relatório em branco',
             emptyReportConfirmationPrompt: ({workspaceName}: {workspaceName: string}) =>
                 `Tem certeza de que deseja criar outro relatório em ${workspaceName}? Você pode acessar seus relatórios em branco em`,
+            emptyReportConfirmationPromptLink: 'Relatórios',
             emptyReportConfirmationDontShowAgain: 'Não mostrar isso novamente',
             genericWorkspaceName: 'este workspace',
         },
@@ -8452,7 +7311,6 @@ Adicione mais regras de gasto para proteger o fluxo de caixa da empresa.`,
                     reimburseableLink: 'despesas reembolsáveis',
                     nonReimbursableLink: 'despesas com cartão corporativo',
                     pending: (label: string) => `iniciou a exportação deste relatório para ${label}...`,
-                    travelCardLink: 'despesas do cartão de viagem',
                 },
                 integrationsMessage: (errorMessage: string, label: string, linkText?: string, linkURL?: string) =>
                     `falha ao exportar este relatório para ${label} ("${errorMessage}${linkText ? `<a href="${linkURL}">${linkText}</a>` : ''}")`,
@@ -8461,8 +7319,7 @@ Adicione mais regras de gasto para proteger o fluxo de caixa da empresa.`,
                 markedReimbursed: (amount: string, currency: string) => `pagou ${currency}${amount} em outro lugar`,
                 markedReimbursedFromIntegration: ({amount, currency}: MarkReimbursedFromIntegrationParams) => `pagou ${currency}${amount} via integração`,
                 outdatedBankAccount: `não foi possível processar o pagamento devido a um problema com a conta bancária do pagador`,
-                reimbursementACHBounceDefault: `não foi possível processar o pagamento devido a um número de roteamento/conta incorreto ou conta encerrada`,
-                reimbursementACHBounceWithReason: ({returnReason}: {returnReason: string}) => `não foi possível processar o pagamento: ${returnReason}`,
+                reimbursementACHBounce: `não foi possível processar o pagamento devido a um problema com a conta bancária`,
                 reimbursementACHCancelled: `cancelou o pagamento`,
                 reimbursementAccountChanged: `não foi possível processar o pagamento, pois o pagador alterou a conta bancária`,
                 reimbursementDelayed: `processou o pagamento, mas ele será atrasado em mais 1–2 dias úteis`,
@@ -8470,22 +7327,17 @@ Adicione mais regras de gasto para proteger o fluxo de caixa da empresa.`,
                 selectedForRandomAuditMarkdown: `[selecionado aleatoriamente](https://help.expensify.com/articles/expensify-classic/reports/Set-a-random-report-audit-schedule) para revisão`,
                 share: ({to}: ShareParams) => `convidou o membro ${to}`,
                 unshare: ({to}: UnshareParams) => `removeu o membro ${to}`,
-                stripePaid: (amount: string, currency: string) => `pagou ${currency}${amount}`,
+                stripePaid: ({amount, currency}: StripePaidParams) => `pagou ${currency}${amount}`,
                 takeControl: `assumiu o controle`,
                 integrationSyncFailed: (label: string, errorMessage: string, workspaceAccountingLink?: string) =>
                     `houve um problema ao sincronizar com ${label}${errorMessage ? ` ("${errorMessage}")` : ''}. Corrija o problema em <a href="${workspaceAccountingLink}">configurações do workspace</a>.`,
-                integrationSyncFailedRecurrence: ({count}: {count: number}) => `(Repetido ${count} vezes.)`,
                 companyCardConnectionBroken: ({feedName, workspaceCompanyCardRoute}: {feedName: string; workspaceCompanyCardRoute: string}) =>
                     `A conexão de ${feedName} está interrompida. Para restaurar as importações do cartão, <a href='${workspaceCompanyCardRoute}'>faça login no seu banco</a>.`,
                 plaidBalanceFailure: ({maskedAccountNumber, walletRoute}: {maskedAccountNumber: string; walletRoute: string}) =>
-                    `a conexão Plaid com a sua conta bancária empresarial foi interrompida. Por favor, <a href='${walletRoute}'>reconecte sua conta bancária ${maskedAccountNumber}</a> para continuar usando seus Cartões Expensify.`,
-                addEmployee: (email: string, role: string, didJoinPolicy?: boolean) => {
-                    const translatedRole = String(translations.workspace.common.roleName(role)).toLowerCase();
-                    const article = role === CONST.POLICY.ROLE.AUDITOR ? 'um' : 'um';
-                    return didJoinPolicy ? `${email} entrou pelo link de convite do workspace` : `adicionou ${email} como ${article} ${translatedRole}`;
-                },
+                    `a conexão do Plaid com a sua conta bancária empresarial foi interrompida. Por favor, <a href='${walletRoute}'>reconecte sua conta bancária ${maskedAccountNumber}</a> para continuar usando seus Cartões Expensify.`,
+                addEmployee: (email: string, role: string) => `adicionou ${email} como ${role === 'member' ? 'a' : 'um'} ${role}`,
                 updateRole: ({email, currentRole, newRole}: UpdateRoleParams) => `atualizou a função de ${email} para ${newRole} (anteriormente ${currentRole})`,
-                updatedCustomField1: (email: string, newValue: string, previousValue: string) => {
+                updatedCustomField1: ({email, previousValue, newValue}: UpdatedCustomFieldParams) => {
                     if (!newValue) {
                         return `removeu o campo personalizado 1 de ${email} (antes "${previousValue}")`;
                     }
@@ -8493,7 +7345,7 @@ Adicione mais regras de gasto para proteger o fluxo de caixa da empresa.`,
                         ? `adicionou "${newValue}" ao campo personalizado 1 de ${email}`
                         : `alterou o campo personalizado 1 de ${email} para "${newValue}" (antes "${previousValue}")`;
                 },
-                updatedCustomField2: (email: string, newValue: string, previousValue: string) => {
+                updatedCustomField2: ({email, previousValue, newValue}: UpdatedCustomFieldParams) => {
                     if (!newValue) {
                         return `removeu o campo personalizado 2 de ${email} (anteriormente "${previousValue}")`;
                     }
@@ -8507,12 +7359,8 @@ Adicione mais regras de gasto para proteger o fluxo de caixa da empresa.`,
                 addedConnection: ({connectionName}: ConnectionNameParams) => `conectado a ${CONST.POLICY.CONNECTIONS.NAME_USER_FRIENDLY[connectionName]}`,
                 leftTheChat: 'saiu do chat',
                 settlementAccountLocked: ({maskedBankAccountNumber}: OriginalMessageSettlementAccountLocked, linkURL: string) =>
-                    `a conta bancária empresarial ${maskedBankAccountNumber} foi bloqueada automaticamente devido a um problema com Reembolso ou liquidação do Cartão Expensify. Corrija o problema nas suas <a href="${linkURL}">configurações de workspace</a>.`,
+                    `a conta bancária empresarial ${maskedBankAccountNumber} foi bloqueada automaticamente devido a um problema com o reembolso ou a liquidação do Cartão Expensify. Corrija o problema nas <a href="${linkURL}">configurações do workspace</a>.`,
                 leftTheChatWithName: (nameOrEmail: string) => `${nameOrEmail ? `${nameOrEmail}: ` : ''}saiu do chat`,
-                actionableCard3DSTransactionApproval: (amount: string, merchant: string | undefined) => {
-                    const amountAndMerchantText = [amount, merchant].filter((s) => !!s?.length).join(' ');
-                    return `Abra o app móvel da Expensify para revisar sua transação de${amountAndMerchantText ? ` ${amountAndMerchantText}` : ''}`;
-                },
             },
             error: {
                 invalidCredentials: 'Credenciais inválidas, verifique a configuração da sua conexão.',
@@ -8522,23 +7370,6 @@ Adicione mais regras de gasto para proteger o fluxo de caixa da empresa.`,
     chronos: {
         oooEventSummaryFullDay: (summary: string, dayCount: number, date: string) => `${summary} por ${dayCount} ${dayCount === 1 ? 'dia' : 'dias'} até ${date}`,
         oooEventSummaryPartialDay: (summary: string, timePeriod: string, date: string) => `${summary} de ${timePeriod} em ${date}`,
-        startTimer: 'Iniciar cronômetro',
-        stopTimer: (duration: string) => `Parar cronômetro (${duration})`,
-        scheduleOOO: 'Agendar ausência',
-        scheduleOOOTitle: 'Agendar ausência do escritório',
-        date: 'Data',
-        time: 'Horário (formato de 24 horas)',
-        durationAmount: 'Duração',
-        durationUnit: 'Unidade',
-        reason: 'Motivo',
-        workingPercentage: 'Porcentagem de trabalho',
-        dateRequired: 'A data é obrigatória.',
-        invalidTimeFormat: 'Insira um horário válido no formato 24 horas (por exemplo, 14:30).',
-        enterANumber: 'Insira um número.',
-        hour: 'horas',
-        day: 'dias',
-        week: 'semanas',
-        month: 'meses',
     },
     footer: {
         features: 'Recursos',
@@ -8581,24 +7412,8 @@ Adicione mais regras de gasto para proteger o fluxo de caixa da empresa.`,
         workspaceName: 'Nome do workspace',
         chatUserDisplayNames: 'Nomes de exibição dos membros do chat',
         scrollToNewestMessages: 'Rolar até as mensagens mais recentes',
-        scrollToActionBadgeTarget: 'Rolar até a ação que requer atenção',
         preStyledText: 'Texto pré-formatado',
         viewAttachment: 'Ver anexo',
-        contextMenuAvailable: 'Menu de contexto disponível. Pressione Shift+F10 para abrir.',
-        contextMenuAvailableMacOS: 'Menu de contexto disponível. Pressione VO-Shift-M para abrir.',
-        contextMenuAvailableNative: 'Menu de contexto disponível. Toque duas vezes e mantenha pressionado para abrir.',
-        selectAllFeatures: 'Selecionar todos os recursos',
-        selectAllTransactions: 'Selecionar todas as transações',
-        selectAllItems: 'Selecionar todos os itens',
-        openActionsMenu: 'Abrir menu de ações',
-        selectAllCategories: 'Selecionar todas as categorias',
-        selectAllDistanceRates: 'Selecionar todas as tarifas de distância',
-        selectAllTags: 'Selecionar todas as tags',
-        selectAllTaxes: 'Selecionar todos os impostos',
-        selectAllPerDiemRates: 'Selecionar todas as diárias',
-        selectAllMembers: 'Selecionar todos os membros',
-        selectAllValues: 'Selecionar todos os valores',
-        selectAllRules: 'Selecionar todas as regras',
     },
     parentReportAction: {
         deletedReport: 'Relatório excluído',
@@ -8617,7 +7432,6 @@ Adicione mais regras de gasto para proteger o fluxo de caixa da empresa.`,
         parentNavigationSummary: ({reportName, workspaceName}: ParentNavigationSummaryParams) => `De ${reportName}${workspaceName ? `em ${workspaceName}` : ''}`,
     },
     qrCodes: {
-        qrCode: 'Código QR',
         copy: 'Copiar URL',
         copied: 'Copiado!',
     },
@@ -8664,11 +7478,6 @@ Adicione mais regras de gasto para proteger o fluxo de caixa da empresa.`,
             'Junte-se à Expensify.org para eliminar as injustiças ao redor do mundo. A atual campanha “Teachers Unite” apoia educadores em todos os lugares ao dividir os custos de materiais escolares essenciais.',
         iKnowATeacher: 'Eu conheço um professor',
         iAmATeacher: 'Sou professor(a)',
-        personalKarma: {
-            title: 'Ativar Karma pessoal',
-            description: 'Doe US$ 1 para Expensify.org a cada US$ 500 que você gastar por mês',
-            stopDonationsPrompt: 'Tem certeza de que deseja parar de doar para Expensify.org?',
-        },
         getInTouch: 'Excelente! Compartilhe as informações deles para que possamos entrar em contato.',
         introSchoolPrincipal: 'Apresentação ao diretor da sua escola',
         schoolPrincipalVerifyExpense:
@@ -8691,11 +7500,6 @@ Adicione mais regras de gasto para proteger o fluxo de caixa da empresa.`,
         notActivated: 'Não ativado',
         outOfPocket: 'Reembolsável',
         companySpend: 'Não reembolsável',
-        personalCard: 'Cartão pessoal',
-        companyCard: 'Cartão corporativo',
-        expensifyCard: 'Cartão Expensify',
-        travelInvoicing: 'Faturamento de viagens',
-        travelCard: 'Cartão de viagem',
     },
     distance: {
         addStop: 'Adicionar parada',
@@ -8719,18 +7523,14 @@ Adicione mais regras de gasto para proteger o fluxo de caixa da empresa.`,
             endReading: 'Finalizar leitura',
             saveForLater: 'Salvar para depois',
             totalDistance: 'Distância total',
+            startTitle: 'Foto inicial do hodômetro',
+            endTitle: 'Foto do hodômetro final',
             startMessageWeb: 'Adicione uma foto do hodômetro do <strong>início</strong> da sua viagem. Arraste um arquivo aqui ou escolha um para enviar.',
             endMessageWeb: 'Adicione uma foto do hodômetro do <strong>final</strong> da sua viagem. Arraste um arquivo aqui ou escolha um para enviar.',
-            startTitle: 'Foto inicial do hodômetro',
-            endTitle: 'Foto final do hodômetro',
-            deleteOdometerPhoto: 'Excluir foto do odômetro',
-            deleteOdometerPhotoConfirmation: 'Tem certeza de que deseja excluir esta foto do odômetro?',
-            cameraAccessRequired: 'É necessário acessar a câmera para tirar fotos.',
-            snapPhotoStart: '<muted-text-label>Tire uma foto do odômetro no <strong>início</strong> da sua viagem.</muted-text-label>',
-            snapPhotoEnd: '<muted-text-label>Tire uma foto do odômetro no <strong>final</strong> da sua viagem.</muted-text-label>',
         },
     },
     gps: {
+        disclaimer: 'Use o GPS para criar uma despesa a partir da sua viagem. Toque em Iniciar abaixo para começar a rastrear.',
         error: {
             failedToStart: 'Falha ao iniciar o rastreamento de localização.',
             failedToGetPermissions: 'Falha ao obter as permissões de localização necessárias.',
@@ -8739,9 +7539,13 @@ Adicione mais regras de gasto para proteger o fluxo de caixa da empresa.`,
         stopped: 'Parado',
         start: 'Iniciar',
         stop: 'Parar',
-        save: 'Salvar',
-        resume: 'Currículo',
         discard: 'Descartar',
+        stopGpsTrackingModal: {
+            title: 'Parar rastreamento por GPS',
+            prompt: 'Tem certeza? Isso encerrará sua jornada atual.',
+            cancel: 'Retomar rastreamento',
+            confirm: 'Parar rastreamento por GPS',
+        },
         discardDistanceTrackingModal: {
             title: 'Descartar rastreamento de distância',
             prompt: 'Tem certeza? Isso vai descartar sua jornada atual e não poderá ser desfeito.',
@@ -8789,18 +7593,12 @@ Adicione mais regras de gasto para proteger o fluxo de caixa da empresa.`,
             prompt: 'Tem certeza de que deseja parar o rastreamento por GPS e mudar para o Expensify Classic?',
             confirm: 'Parar e mudar',
         },
-        switchAccountWarningTripInProgress: {
-            title: 'Rastreamento por GPS em andamento',
-            prompt: 'Tem certeza de que quer parar o rastreamento por GPS e mudar de conta?',
-            confirm: 'Parar e trocar',
-        },
         locationServicesRequiredModal: {
             title: 'Acesso à localização necessário',
             confirm: 'Abrir configurações',
             prompt: 'Permita o acesso à localização nas configurações do seu dispositivo para iniciar o rastreamento de distância por GPS.',
         },
-        gpsFloatingPillText: 'Rastreamento por GPS em andamento...',
-        liveActivity: {subtitle: 'Rastreamento de distância', button: 'Ver progresso', lockScreenBadgeText: 'Distância', lockScreenTrackingText: 'Rastreando...'},
+        fabGpsTripExplained: 'Ir para a tela de GPS (Ação flutuante)',
     },
     reportCardLostOrDamaged: {
         screenTitle: 'Boletim perdido ou danificado',
@@ -8827,13 +7625,11 @@ Adicione mais regras de gasto para proteger o fluxo de caixa da empresa.`,
         [CONST.REFERRAL_PROGRAM.CONTENT_TYPES.START_CHAT]: {
             buttonText: 'Inicie um chat, <success><strong>indique um amigo</strong></success>.',
             header: 'Inicie um chat, indique um amigo',
-            closeAccessibilityLabel: 'Fechar, iniciar um chat, indicar um amigo, banner',
             body: 'Quer que seus amigos também usem o Expensify? É só começar um chat com eles e nós cuidamos do resto.',
         },
         [CONST.REFERRAL_PROGRAM.CONTENT_TYPES.SUBMIT_EXPENSE]: {
             buttonText: 'Envie uma despesa, <success><strong>indique sua equipe</strong></success>.',
             header: 'Envie uma despesa, indique sua equipe',
-            closeAccessibilityLabel: 'Fechar, enviar uma despesa, indicar sua equipe, banner',
             body: 'Quer que sua equipe também use o Expensify? Basta enviar uma despesa para eles e nós cuidaremos do resto.',
         },
         [CONST.REFERRAL_PROGRAM.CONTENT_TYPES.REFER_FRIEND]: {
@@ -8849,27 +7645,26 @@ Adicione mais regras de gasto para proteger o fluxo de caixa da empresa.`,
     },
     systemChatFooterMessage: {
         [CONST.INTRO_CHOICES.MANAGE_TEAM]: ({adminReportName, href}: {adminReportName: string; href: string}) =>
-            `Converse com seu executivo de contas em <a href="${href}">${adminReportName}</a> para obter ajuda`,
+            `Converse com seu especialista de configuração em <a href="${href}">${adminReportName}</a> para obter ajuda`,
         default: `Envie uma mensagem para <concierge-link>${CONST.CONCIERGE_CHAT_NAME}</concierge-link> para obter ajuda com a configuração`,
     },
     violations: {
         allTagLevelsRequired: 'Todas as tags são obrigatórias',
         autoReportedRejectedExpense: 'Esta despesa foi rejeitada.',
         billableExpense: 'Faturável não é mais válido',
-        cashExpenseWithNoReceipt: (formattedLimit?: string) => `Recibo obrigatório${formattedLimit ? `acima de ${formattedLimit}` : ''}`,
+        cashExpenseWithNoReceipt: ({formattedLimit}: ViolationsCashExpenseWithNoReceiptParams = {}) => `Recibo obrigatório${formattedLimit ? `acima de ${formattedLimit}` : ''}`,
         categoryOutOfPolicy: 'Categoria não é mais válida',
-        conversionSurcharge: (surcharge: number) => `Aplicado sobretaxa de conversão de ${surcharge}%`,
+        conversionSurcharge: ({surcharge}: ViolationsConversionSurchargeParams) => `Aplicado sobretaxa de conversão de ${surcharge}%`,
         customUnitOutOfPolicy: 'Tarifa inválida para este espaço de trabalho',
         duplicatedTransaction: 'Possível duplicata',
         fieldRequired: 'Os campos do relatório são obrigatórios',
         futureDate: 'Data futura não permitida',
-        inactiveVendor: 'Fornecedor não é mais válido',
-        invoiceMarkup: (invoiceMarkup: number) => `Reajustado em ${invoiceMarkup}%`,
-        maxAge: (maxAge: number) => `Data anterior a ${maxAge} dias`,
+        invoiceMarkup: ({invoiceMarkup}: ViolationsInvoiceMarkupParams) => `Reajustado em ${invoiceMarkup}%`,
+        maxAge: ({maxAge}: ViolationsMaxAgeParams) => `Data anterior a ${maxAge} dias`,
         missingCategory: 'Categoria ausente',
         missingComment: 'Descrição obrigatória para a categoria selecionada',
         missingAttendees: 'Vários participantes são obrigatórios para esta categoria',
-        missingTag: (tagName?: string) => `Faltando ${tagName ?? 'etiqueta'}`,
+        missingTag: ({tagName}: ViolationsMissingTagParams = {}) => `Faltando ${tagName ?? 'etiqueta'}`,
         modifiedAmount: ({type, displayPercentVariance}: ViolationsModifiedAmountParams) => {
             switch (type) {
                 case 'distance':
@@ -8884,17 +7679,15 @@ Adicione mais regras de gasto para proteger o fluxo de caixa da empresa.`,
             }
         },
         modifiedDate: 'Data diferente do recibo digitalizado',
-        increasedDistance: ({formattedRouteDistance}: ViolationsIncreasedDistanceParams) =>
-            formattedRouteDistance ? `A distância excede a rota calculada de ${formattedRouteDistance}` : 'A distância excede a rota calculada',
         nonExpensiworksExpense: 'Despesa fora do Expensiworks',
-        overAutoApprovalLimit: (formattedLimit: string) => `Despesa excede o limite de aprovação automática de ${formattedLimit}`,
-        overCategoryLimit: (formattedLimit: string) => `Valor acima do limite de categoria de ${formattedLimit}/pessoa`,
-        overLimit: (formattedLimit: string) => `Valor acima do limite de ${formattedLimit}/pessoa`,
-        overTripLimit: (formattedLimit: string) => `Valor acima do limite de ${formattedLimit}/viagem`,
-        overLimitAttendee: (formattedLimit: string) => `Valor acima do limite de ${formattedLimit}/pessoa`,
-        perDayLimit: (formattedLimit: string) => `Valor acima do limite diário de categoria de ${formattedLimit}/pessoa`,
+        overAutoApprovalLimit: ({formattedLimit}: ViolationsOverLimitParams) => `Despesa excede o limite de aprovação automática de ${formattedLimit}`,
+        overCategoryLimit: ({formattedLimit}: ViolationsOverCategoryLimitParams) => `Valor acima do limite de categoria de ${formattedLimit}/pessoa`,
+        overLimit: ({formattedLimit}: ViolationsOverLimitParams) => `Valor acima do limite de ${formattedLimit}/pessoa`,
+        overTripLimit: ({formattedLimit}: ViolationsOverLimitParams) => `Valor acima do limite de ${formattedLimit}/viagem`,
+        overLimitAttendee: ({formattedLimit}: ViolationsOverLimitParams) => `Valor acima do limite de ${formattedLimit}/pessoa`,
+        perDayLimit: ({formattedLimit}: ViolationsPerDayLimitParams) => `Valor acima do limite diário de categoria de ${formattedLimit}/pessoa`,
         receiptNotSmartScanned: 'Recibo e detalhes da despesa adicionados manualmente.',
-        receiptRequired: (formattedLimit?: string, category?: string) => {
+        receiptRequired: ({formattedLimit, category}: ViolationsReceiptRequiredParams) => {
             if (formattedLimit && category) {
                 return `Recibo obrigatório acima do limite de categoria de ${formattedLimit}`;
             }
@@ -8906,8 +7699,8 @@ Adicione mais regras de gasto para proteger o fluxo de caixa da empresa.`,
             }
             return 'Recibo obrigatório';
         },
-        itemizedReceiptRequired: (formattedLimit?: string) => `Recibo detalhado obrigatório${formattedLimit ? `acima de ${formattedLimit}` : ''}`,
-        prohibitedExpense: (prohibitedExpenseTypes: string | string[]) => {
+        itemizedReceiptRequired: ({formattedLimit}: {formattedLimit?: string}) => `Recibo detalhado obrigatório${formattedLimit ? `acima de ${formattedLimit}` : ''}`,
+        prohibitedExpense: ({prohibitedExpenseTypes}: ViolationsProhibitedExpenseParams) => {
             const preMessage = 'Despesa proibida:';
             const getProhibitedExpenseTypeText = (prohibitedExpenseType: string) => {
                 switch (prohibitedExpenseType) {
@@ -8921,10 +7714,6 @@ Adicione mais regras de gasto para proteger o fluxo de caixa da empresa.`,
                         return `entretenimento adulto`;
                     case 'hotelIncidentals':
                         return `despesas incidentais de hotel`;
-                    case 'giftCard':
-                        return `compras de cartão-presente`;
-                    case 'handwrittenReceipt':
-                        return `recibos manuscritos`;
                     default:
                         return `${prohibitedExpenseType}`;
                 }
@@ -8940,37 +7729,19 @@ Adicione mais regras de gasto para proteger o fluxo de caixa da empresa.`,
             }
             return `${preMessage} ${types.map(getProhibitedExpenseTypeText).join(', ')}`;
         },
-        customRules: (message: string) => message,
+        customRules: ({message}: ViolationsCustomRulesParams) => message,
         reviewRequired: 'Revisão necessária',
-        rter: (
-            brokenBankConnection: boolean,
-            isAdmin: boolean,
-            isTransactionOlderThan7Days: boolean,
-            member?: string,
-            rterType?: string,
-            companyCardPageURL?: string,
-            connectionLink?: string,
-            isPersonalCard?: boolean,
-            isMarkAsCash?: boolean,
-        ) => {
+        rter: ({brokenBankConnection, isAdmin, isTransactionOlderThan7Days, member, rterType, companyCardPageURL}: ViolationsRterParams) => {
             if (rterType === CONST.RTER_VIOLATION_TYPES.BROKEN_CARD_CONNECTION_530) {
-                return 'Não é possível conciliar automaticamente o recibo devido a uma conexão bancária com erro.';
-            }
-            if (isPersonalCard && (rterType === CONST.RTER_VIOLATION_TYPES.BROKEN_CARD_CONNECTION || brokenBankConnection)) {
-                if (!connectionLink) {
-                    return 'Não é possível conciliar automaticamente o recibo devido a uma conexão bancária com erro.';
-                }
-                return isMarkAsCash
-                    ? `Não é possível corresponder automaticamente o recibo devido a uma conexão de cartão com problema. Marque como dinheiro para ignorar ou <a href="${connectionLink}">corrija o cartão</a> para corresponder o recibo.`
-                    : `Não é possível corresponder automaticamente o recibo devido a uma conexão quebrada com o cartão. <a href="${connectionLink}">Corrigir o cartão</a> para corresponder o recibo.`;
+                return 'Não é possível associar automaticamente o recibo devido à conexão bancária interrompida';
             }
             if (brokenBankConnection || rterType === CONST.RTER_VIOLATION_TYPES.BROKEN_CARD_CONNECTION) {
                 return isAdmin
                     ? `Conexão bancária interrompida. <a href="${companyCardPageURL}">Reconectar para corresponder ao recibo</a>`
-                    : 'Conexão bancária interrompida. Peça para um administrador reconectar para corresponder ao recibo.';
+                    : 'Conexão bancária quebrada. Peça para um administrador reconectar para coincidir com o recibo.';
             }
             if (!isTransactionOlderThan7Days) {
-                return isAdmin ? `Peça para ${member} marcar como dinheiro ou aguarde 7 dias e tente novamente` : 'Aguardando associação com a transação do cartão.';
+                return isAdmin ? `Peça para ${member} marcar como pagamento em dinheiro ou aguarde 7 dias e tente novamente` : 'Aguardando mesclagem com a transação do cartão.';
             }
             return '';
         },
@@ -8979,20 +7750,12 @@ Adicione mais regras de gasto para proteger o fluxo de caixa da empresa.`,
             `<muted-text-label>Recibo pendente devido a uma conexão bancária interrompida. Resolva em <a href="${workspaceCompanyCardRoute}">Cartões corporativos</a>.</muted-text-label>`,
         memberBrokenConnectionError: 'Recibo pendente devido à conexão bancária com problemas. Peça a um administrador do workspace para resolver.',
         markAsCashToIgnore: 'Marcar como dinheiro para ignorar e solicitar pagamento.',
-        smartscanFailed: ({canEdit = true, missingFields = []}: {canEdit?: boolean; missingFields?: string[]}) => {
-            if (missingFields.length > 0) {
-                const fieldNames: Record<string, string> = {merchant: 'estabelecimento', date: 'data', amount: 'valor'};
-                const translated = missingFields.map((f) => fieldNames[f] ?? f);
-                const fieldList = translated.join(translated.length > 2 ? ', ' : ' e ');
-                return `A digitalização do recibo falhou — faltando ${fieldList}.${canEdit ? ' Insira os detalhes manualmente.' : ''}`;
-            }
-            return `A digitalização do recibo falhou.${canEdit ? 'Insira os detalhes manualmente.' : ''}`;
-        },
+        smartscanFailed: ({canEdit = true}) => `A digitalização do recibo falhou.${canEdit ? 'Insira os detalhes manualmente.' : ''}`,
         receiptGeneratedWithAI: 'Recibo possivelmente gerado por IA',
-        someTagLevelsRequired: (tagName?: string) => `Faltando ${tagName ?? 'Etiqueta'}`,
-        tagOutOfPolicy: (tagName?: string) => `${tagName ?? 'Etiqueta'} não é mais válido`,
+        someTagLevelsRequired: ({tagName}: ViolationsTagOutOfPolicyParams = {}) => `Faltando ${tagName ?? 'Etiqueta'}`,
+        tagOutOfPolicy: ({tagName}: ViolationsTagOutOfPolicyParams = {}) => `${tagName ?? 'Etiqueta'} não é mais válido`,
         taxAmountChanged: 'O valor do imposto foi modificado',
-        taxOutOfPolicy: (taxName?: string) => `${taxName ?? 'Imposto'} não é mais válido`,
+        taxOutOfPolicy: ({taxName}: ViolationsTaxOutOfPolicyParams = {}) => `${taxName ?? 'Imposto'} não é mais válido`,
         taxRateChanged: 'A alíquota de imposto foi modificada',
         taxRequired: 'Alíquota de imposto ausente',
         none: 'Nenhum',
@@ -9012,7 +7775,7 @@ Adicione mais regras de gasto para proteger o fluxo de caixa da empresa.`,
         noRoute: 'Selecione um endereço válido',
     },
     reportViolations: {
-        [CONST.REPORT_VIOLATIONS.FIELD_REQUIRED]: (fieldName: string) => `${fieldName} é obrigatório`,
+        [CONST.REPORT_VIOLATIONS.FIELD_REQUIRED]: ({fieldName}: RequiredFieldParams) => `${fieldName} é obrigatório`,
         reportContainsExpensesWithViolations: 'O relatório contém despesas com violações.',
     },
     violationDismissal: {
@@ -9069,7 +7832,6 @@ Adicione mais regras de gasto para proteger o fluxo de caixa da empresa.`,
         bookACallTextBottom:
             'Ficaríamos muito animados em fazer uma ligação com você para entender o motivo. Você pode agendar uma chamada com um de nossos gerentes de produto sêniores para discutir suas necessidades.',
         takeMeToExpensifyClassic: 'Leve-me para o Expensify Classic',
-        goBackJustOnce: 'Voltar apenas desta vez',
     },
     listBoundary: {
         errorMessage: 'Ocorreu um erro ao carregar mais mensagens',
@@ -9142,7 +7904,7 @@ Adicione mais regras de gasto para proteger o fluxo de caixa da empresa.`,
                 subtitle: 'Como próximo passo, <a href="#">conclua sua lista de verificação de configuração</a> para que sua equipe possa começar a registrar despesas.',
             },
             trialStarted: {
-                title: (numOfDays: number) => `Teste: restam ${numOfDays} ${numOfDays === 1 ? 'dia' : 'dias'}!`,
+                title: ({numOfDays}: TrialStartedTitleParams) => `Teste: restam ${numOfDays} ${numOfDays === 1 ? 'dia' : 'dias'}!`,
                 subtitle: 'Adicione um cartão de pagamento para continuar usando todos os seus recursos favoritos.',
             },
             trialEnded: {
@@ -9180,15 +7942,15 @@ Adicione mais regras de gasto para proteger o fluxo de caixa da empresa.`,
             title: 'Seu plano',
             exploreAllPlans: 'Explorar todos os planos',
             customPricing: 'Preço personalizado',
-            asLowAs: (price: string) => `a partir de ${price} por membro ativo/mês`,
-            pricePerMemberMonth: (price: string) => `${price} por membro/mês`,
-            pricePerMemberPerMonth: (price: string) => `${price} por membro por mês`,
+            asLowAs: ({price}: YourPlanPriceValueParams) => `a partir de ${price} por membro ativo/mês`,
+            pricePerMemberMonth: ({price}: YourPlanPriceValueParams) => `${price} por membro/mês`,
+            pricePerMemberPerMonth: ({price}: YourPlanPriceValueParams) => `${price} por membro por mês`,
             perMemberMonth: 'por membro/mês',
             collect: {
                 title: 'Cobrar',
                 description: 'O plano para pequenas empresas que oferece despesas, viagens e chat.',
-                priceAnnual: ({lower, upper}: YourPlanPriceParams) => `De membro ${lower}/ativo com o Cartão Expensify a membro ${upper}/ativo sem o Cartão Expensify.`,
-                pricePayPerUse: ({lower, upper}: YourPlanPriceParams) => `De membro ${lower}/ativo com o Cartão Expensify a membro ${upper}/ativo sem o Cartão Expensify.`,
+                priceAnnual: ({lower, upper}: YourPlanPriceParams) => `De ${lower}/membro ativo com o Cartão Expensify, até ${upper}/membro ativo sem o Cartão Expensify.`,
+                pricePayPerUse: ({lower, upper}: YourPlanPriceParams) => `De ${lower}/membro ativo com o Cartão Expensify, até ${upper}/membro ativo sem o Cartão Expensify.`,
                 benefit1: 'Digitalização de recibos',
                 benefit2: 'Reembolsos',
                 benefit3: 'Gerenciamento de cartão corporativo',
@@ -9201,8 +7963,8 @@ Adicione mais regras de gasto para proteger o fluxo de caixa da empresa.`,
             control: {
                 title: 'Controle',
                 description: 'Despesas, viagens e chat para grandes empresas.',
-                priceAnnual: ({lower, upper}: YourPlanPriceParams) => `De membro ${lower}/ativo com o Cartão Expensify a membro ${upper}/ativo sem o Cartão Expensify.`,
-                pricePayPerUse: ({lower, upper}: YourPlanPriceParams) => `De membro ${lower}/ativo com o Cartão Expensify a membro ${upper}/ativo sem o Cartão Expensify.`,
+                priceAnnual: ({lower, upper}: YourPlanPriceParams) => `De ${lower}/membro ativo com o Cartão Expensify, até ${upper}/membro ativo sem o Cartão Expensify.`,
+                pricePayPerUse: ({lower, upper}: YourPlanPriceParams) => `De ${lower}/membro ativo com o Cartão Expensify, até ${upper}/membro ativo sem o Cartão Expensify.`,
                 benefit1: 'Tudo no plano Collect',
                 benefit2: 'Fluxos de aprovação em múltiplos níveis',
                 benefit3: 'Regras de despesa personalizadas',
@@ -9217,7 +7979,7 @@ Adicione mais regras de gasto para proteger o fluxo de caixa da empresa.`,
             upgrade: 'Fazer upgrade para o Control',
             addMembers: 'Adicionar membros',
             saveWithExpensifyTitle: 'Economize com o Cartão Expensify',
-            saveWithExpensifyDescription: 'Use nossa calculadora de economia para ver como o cashback do Cartão Expensify pode reduzir sua fatura do Expensify.',
+            saveWithExpensifyDescription: 'Use nossa calculadora de economia para ver como o cashback do Expensify Card pode reduzir sua fatura do Expensify.',
             saveWithExpensifyButton: 'Saiba mais',
         },
         compareModal: {
@@ -9227,7 +7989,6 @@ Adicione mais regras de gasto para proteger o fluxo de caixa da empresa.`,
         details: {
             title: 'Detalhes da assinatura',
             annual: 'Assinatura anual',
-            creditBalance: 'Saldo de crédito',
             taxExempt: 'Solicitar isenção de impostos',
             taxExemptEnabled: 'Isento de impostos',
             taxExemptStatus: 'Status de isenção de impostos',
@@ -9245,10 +8006,10 @@ Adicione mais regras de gasto para proteger o fluxo de caixa da empresa.`,
             note: 'Observação: Um membro ativo é qualquer pessoa que criou, editou, enviou, aprovou, reembolsou ou exportou dados de despesas vinculados ao espaço de trabalho da sua empresa.',
             confirmDetails: 'Confirme os detalhes da sua nova assinatura anual:',
             subscriptionSize: 'Tamanho da assinatura',
-            activeMembers: (size: number) => `${size} membros ativos/mês`,
+            activeMembers: ({size}: SubscriptionSizeParams) => `${size} membros ativos/mês`,
             subscriptionRenews: 'A assinatura é renovada',
             youCantDowngrade: 'Você não pode fazer downgrade durante a sua assinatura anual.',
-            youAlreadyCommitted: (size: number, date: string) =>
+            youAlreadyCommitted: ({size, date}: SubscriptionCommitmentParams) =>
                 `Você já contratou uma assinatura anual de ${size} membros ativos por mês até ${date}. Você pode mudar para uma assinatura por uso em ${date} desativando a renovação automática.`,
             error: {
                 size: 'Insira um tamanho de assinatura válido',
@@ -9261,50 +8022,37 @@ Adicione mais regras de gasto para proteger o fluxo de caixa da empresa.`,
             security: 'O Expensify é compatível com PCI-DSS, usa criptografia em nível bancário e utiliza infraestrutura redundante para proteger seus dados.',
             learnMoreAboutSecurity: 'Saiba mais sobre nossa segurança.',
         },
-        expensifyCode: {
-            title: 'Código Expensify',
-            discountCode: 'Código de desconto',
-            enterCode: 'Insira um código Expensify para aplicar à sua assinatura.',
-            discountMessage: (promoDiscount: string, validBillingCycles: string) =>
-                `Você receberá ${promoDiscount}% de desconto nas próximas ${validBillingCycles ? `${validBillingCycles} ` : ''}cobranças de faturamento.`,
-            apply: 'Aplicar',
-            error: {
-                invalid: 'Este código é inválido',
-            },
-        },
         subscriptionSettings: {
             title: 'Configurações de assinatura',
-            summary: (subscriptionType: string, subscriptionSize: string, expensifyCode: string, autoRenew: string, autoIncrease: string) =>
-                `Tipo de assinatura: ${subscriptionType}, Tamanho da assinatura: ${subscriptionSize}${expensifyCode ? `, Código Expensify: ${expensifyCode}` : ''}, Renovação automática: ${autoRenew}, Aumento automático de assentos anuais: ${autoIncrease}`,
+            summary: ({subscriptionType, subscriptionSize, autoRenew, autoIncrease}: SubscriptionSettingsSummaryParams) =>
+                `Tipo de assinatura: ${subscriptionType}, Tamanho da assinatura: ${subscriptionSize}, Renovação automática: ${autoRenew}, Aumento automático de assentos anuais: ${autoIncrease}`,
             none: 'nenhum',
             on: 'ativado',
             off: 'desligado',
             annual: 'Anual',
             autoRenew: 'Renovação automática',
             autoIncrease: 'Aumentar automaticamente as licenças anuais',
-            saveUpTo: (amountWithCurrency: string) => `Economize até ${amountWithCurrency}/mês por membro ativo`,
+            saveUpTo: ({amountWithCurrency}: SubscriptionSettingsSaveUpToParams) => `Economize até ${amountWithCurrency}/mês por membro ativo`,
             automaticallyIncrease:
                 'Aumente automaticamente seus assentos anuais para acomodar membros ativos que excederem o tamanho da sua assinatura. Observação: isso estenderá a data de término da sua assinatura anual.',
             disableAutoRenew: 'Desativar renovação automática',
             helpUsImprove: 'Ajude-nos a melhorar o Expensify',
             whatsMainReason: 'Qual é o principal motivo para desativar a renovação automática?',
-            renewsOn: (date: string) => `Renova em ${date}.`,
-            pricingConfiguration: 'O preço depende da configuração. Para pagar menos, escolha uma assinatura anual e peça o Cartão Expensify.',
-            learnMore: (hasAdminsRoom: boolean) =>
+            renewsOn: ({date}: SubscriptionSettingsRenewsOnParams) => `Renova em ${date}.`,
+            pricingConfiguration: 'O preço depende da configuração. Para o menor valor, escolha uma assinatura anual e obtenha o Expensify Card.',
+            learnMore: ({hasAdminsRoom}: SubscriptionSettingsLearnMoreParams) =>
                 `<muted-text>Saiba mais na nossa <a href="${CONST.PRICING}">página de preços</a> ou converse com nossa equipe no seu ${hasAdminsRoom ? `<a href="adminsRoom">Sala #admins.</a>` : 'Sala #admins.'}</muted-text>`,
             estimatedPrice: 'Preço estimado',
-            changesBasedOn: 'Isso muda de acordo com o uso do seu Cartão Expensify e as opções de assinatura abaixo.',
-            collectBillingDescription: 'Os espaços de trabalho Collect são cobrados mensalmente por membro, sem compromisso anual.',
-            pricing: 'Preços',
+            changesBasedOn: 'Isso muda com base no uso do seu Cartão Expensify e nas opções de assinatura abaixo.',
         },
-        cancelSubscription: {
-            title: 'Cancelar assinatura',
-            subtitle: 'Qual é o principal motivo pelo qual você está deseja cancelar sua assinatura?',
+        requestEarlyCancellation: {
+            title: 'Solicitar cancelamento antecipado',
+            subtitle: 'Qual é o principal motivo pelo qual você está solicitando o cancelamento antecipado?',
             subscriptionCanceled: {
                 title: 'Assinatura cancelada',
                 subtitle: 'Sua assinatura anual foi cancelada.',
                 info: 'Se você quiser continuar usando seu(s) espaço(s) de trabalho com pagamento por uso, está tudo pronto.',
-                preventFutureActivity: (workspacesListRoute: string) =>
+                preventFutureActivity: ({workspacesListRoute}: WorkspacesListRouteParams) =>
                     `Se você quiser evitar atividades e cobranças futuras, você deve <a href="${workspacesListRoute}">excluir seu(s) workspace(s)</a>. Observe que, ao excluir seu(s) workspace(s), será cobrado qualquer valor pendente referente à atividade ocorrida durante o mês calendário atual.`,
             },
             requestSubmitted: {
@@ -9312,7 +8060,7 @@ Adicione mais regras de gasto para proteger o fluxo de caixa da empresa.`,
                 subtitle:
                     'Obrigado por nos informar que você está interessado em cancelar sua assinatura. Estamos analisando sua solicitação e entraremos em contato em breve pelo seu chat com o <concierge-link>Concierge</concierge-link>.',
             },
-            acknowledgement: `Ao solicitar o cancelamento, reconheço e concordo que a Expensify não tem obrigação de conceder tal solicitação de acordo com os <a href=${CONST.OLD_DOT_PUBLIC_URLS.TERMS_URL}>Termos de Serviço</a> da Expensify ou outro contrato de serviços aplicável entre mim e a Expensify, e que a Expensify mantém total discricionariedade quanto à concessão de qualquer solicitação desse tipo.`,
+            acknowledgement: `Ao solicitar o cancelamento antecipado, reconheço e concordo que a Expensify não tem obrigação de conceder tal solicitação de acordo com os <a href=${CONST.OLD_DOT_PUBLIC_URLS.TERMS_URL}>Termos de Serviço</a> da Expensify ou outro contrato de serviços aplicável entre mim e a Expensify, e que a Expensify mantém total discricionariedade quanto à concessão de qualquer solicitação desse tipo.`,
         },
     },
     feedbackSurvey: {
@@ -9331,14 +8079,11 @@ Adicione mais regras de gasto para proteger o fluxo de caixa da empresa.`,
     },
     delegate: {
         switchAccount: 'Trocar de conta:',
-        switch: 'Trocar',
-        copilot: 'Copilot',
         copilotDelegatedAccess: 'Copilot: Acesso delegado',
         copilotDelegatedAccessDescription: 'Permitir que outros membros acessem sua conta.',
-        learnMoreAboutDelegatedAccess: 'Saiba mais sobre acesso delegado',
-        addCopilot: 'Adicionar um copiloto',
+        addCopilot: 'Adicionar copiloto',
         membersCanAccessYourAccount: 'Esses membros podem acessar sua conta:',
-        youCanAccessTheseAccounts: 'Você pode acessar essas contas:',
+        youCanAccessTheseAccounts: 'Você pode acessar essas contas pelo alternador de conta:',
         role: ({role}: OptionalParam<DelegateRoleParams> = {}) => {
             switch (role) {
                 case CONST.DELEGATE_ROLE.ALL:
@@ -9457,7 +8202,6 @@ Adicione mais regras de gasto para proteger o fluxo de caixa da empresa.`,
             theresWasAProblemDuringAWorkspaceConnectionSync: 'Houve um problema durante a sincronização da conexão do workspace',
             theresAProblemWithYourWallet: 'Há um problema com sua carteira',
             theresAProblemWithYourWalletTerms: 'Há um problema com os termos da sua carteira',
-            aBankAccountIsLocked: 'Uma conta bancária está bloqueada',
         },
     },
     emptySearchView: {
@@ -9478,10 +8222,15 @@ Adicione mais regras de gasto para proteger o fluxo de caixa da empresa.`,
         conciergeLHNGBR: '<tooltip>Comece <strong>aqui!</strong></tooltip>',
         saveSearchTooltip: '<tooltip><strong>Renomeie suas buscas salvas</strong> aqui!</tooltip>',
         accountSwitcher: '<tooltip>Acesse suas <strong>contas Copilot</strong> aqui</tooltip>',
+        scanTestTooltip: {
+            main: '<tooltip><strong>Escaneie nosso recibo de teste</strong> para ver como funciona!</tooltip>',
+            manager: '<tooltip>Escolha nosso <strong>gerente de teste</strong> para experimentar!</tooltip>',
+            confirmation: '<tooltip>Agora, <strong>envie sua despesa</strong> e veja a mágica acontecer!</tooltip>',
+            tryItOut: 'Experimente',
+        },
         outstandingFilter: '<tooltip>Filtrar despesas\nque <strong>precisam de aprovação</strong></tooltip>',
         scanTestDriveTooltip: '<tooltip>Envie este recibo para\n<strong>concluir o test drive!</strong></tooltip>',
         gpsTooltip: '<tooltip>Rastreamento por GPS em andamento! Quando terminar, pare o rastreamento abaixo.</tooltip>',
-        hasFilterNegation: '<tooltip>Pesquise despesas sem recibos usando <strong>-has:receipt</strong>.</tooltip>',
     },
     discardChangesConfirmation: {
         title: 'Descartar alterações?',
@@ -9497,7 +8246,7 @@ Adicione mais regras de gasto para proteger o fluxo de caixa da empresa.`,
         confirmation: {
             title: 'Confirmar chamada',
             description: 'Verifique se os detalhes abaixo estão corretos para você. Assim que você confirmar a chamada, enviaremos um convite com mais informações.',
-            setupSpecialist: 'Seu executivo de contas',
+            setupSpecialist: 'Seu especialista de configuração',
             meetingLength: 'Duração da reunião',
             dateTime: 'Data e hora',
             minutes: '30 minutos',
@@ -9545,20 +8294,6 @@ Aqui está um *comprovante de teste* para mostrar como funciona:`,
         exportInProgress: 'Exportação em andamento',
         conciergeWillSend: 'O Concierge enviará o arquivo para você em breve.',
     },
-    exportDownload: {
-        preparingTitle: 'Preparing download...',
-        preparingBody: 'You can either wait for the download to finish or Concierge can send it to you via chat.',
-        sendFromConcierge: "Send me the file when it's ready",
-        conciergeTitle: 'You bet!',
-        conciergeBody: 'Concierge will send you a message when the file is ready.',
-        goToConcierge: 'Go to Concierge',
-        dismiss: 'Dismiss',
-        readyTitle: 'Your file is ready!',
-        readyBody: "If it didn't automatically download, use the button below.",
-        downloadFile: 'Download file',
-        failedTitle: 'Export failed',
-        close: 'Close',
-    },
     domain: {
         notVerified: 'Não verificado',
         retry: 'Tentar novamente',
@@ -9592,7 +8327,7 @@ Aqui está um *comprovante de teste* para mostrar como funciona:`,
         goToDomain: 'Ir para o domínio',
         samlLogin: {
             title: 'Login SAML',
-            subtitle: `<muted-text>Configure o login de membros com <a href="${CONST.SAML_HELP_URL}">logon único SAML (SSO)</a>.</muted-text>`,
+            subtitle: `<muted-text>Configure o login de membros com <a href="${CONST.SAML_HELP_URL}">logon único SAML (SSO).</a></muted-text>`,
             enableSamlLogin: 'Ativar login SAML',
             allowMembers: 'Permitir que membros façam login com SAML.',
             requireSamlLogin: 'Exigir login SAML',
@@ -9602,8 +8337,6 @@ Aqui está um *comprovante de teste* para mostrar como funciona:`,
             disableSamlRequired: 'Desativar SAML obrigatório',
             oktaWarningPrompt: 'Tem certeza? Isso também desativará o Okta SCIM.',
             requireWithEmptyMetadataError: 'Adicione abaixo os metadados do Provedor de Identidade para ativar',
-            pleaseDisableTwoFactorAuth: (twoFactorAuthSettingsUrl: string) =>
-                `<muted-text>Desative a opção <a href="${twoFactorAuthSettingsUrl}">exigir autenticação em duas etapas</a> para ativar o login SAML.</muted-text>`,
         },
         samlConfigurationDetails: {
             title: 'Detalhes da configuração SAML',
@@ -9652,6 +8385,7 @@ Aqui está um *comprovante de teste* para mostrar como funciona:`,
             primaryContact: 'Contato principal',
             addPrimaryContact: 'Adicionar contato principal',
             setPrimaryContactError: 'Não foi possível definir o contato principal. Tente novamente mais tarde.',
+            settings: 'Configurações',
             consolidatedDomainBilling: 'Faturamento de domínio consolidado',
             consolidatedDomainBillingDescription: (domainName: string) =>
                 `<comment><muted-text-label>Quando ativado, o contato principal pagará por todos os espaços de trabalho pertencentes aos membros de <strong>${domainName}</strong> e receberá todos os recibos de cobrança.</muted-text-label></comment>`,
@@ -9668,107 +8402,25 @@ Aqui está um *comprovante de teste* para mostrar como funciona:`,
             resetDomain: 'Redefinir domínio',
             resetDomainExplanation: ({domainName}: {domainName?: string}) => `Digite <strong>${domainName}</strong> para confirmar a redefinição do domínio.`,
             enterDomainName: 'Insira seu nome de domínio aqui',
-            resetDomainInfo: `Esta ação é <strong>permanente</strong> e os seguintes dados serão excluídos: <br/> <bullet-list><bullet-item>Conexões de cartões corporativos e quaisquer despesas não lançadas desses cartões</bullet-item><bullet-item>Configurações de SAML e de grupos</bullet-item><bullet-item>Dados de viagem e acesso ao Expensify Travel</bullet-item></bullet-list> Todas as contas, workspaces, relatórios, despesas e outros dados serão mantidos. <br/><br/>Observação: você pode remover este domínio da sua lista de domínios excluindo o e-mail associado em seus <a href="#">métodos de contato</a>.`,
+            resetDomainInfo: `Esta ação é <strong>permanente</strong> e os seguintes dados serão excluídos: <br/> <ul><li>Conexões de cartões corporativos e quaisquer despesas não informadas desses cartões</li> <li>Configurações de SAML e de grupo</li> </ul> Todas as contas, workspaces, relatórios, despesas e outros dados serão mantidos. <br/><br/>Observação: você pode remover este domínio da sua lista de domínios removendo o e-mail associado dos seus <a href="#">métodos de contato</a>.`,
         },
         domainMembers: 'Membros do domínio',
         members: {
             title: 'Membros',
             findMember: 'Encontrar membro',
             addMember: 'Adicionar membro',
-            allMembers: 'Todos os membros',
             email: 'Endereço de e-mail',
-            closeAccount: () => ({
-                one: 'Encerrar conta',
-                other: 'Encerrar contas',
-            }),
+            closeAccount: 'Encerrar conta',
             closeAccountPrompt: 'Tem certeza? Esta ação é permanente.',
-            forceCloseAccount: () => ({one: 'Forçar encerramento da conta', other: 'Forçar encerramento das contas'}),
-            safeCloseAccount: () => ({
-                one: 'Fechar conta com segurança',
-                other: 'Fechar contas com segurança',
-            }),
-            closeAccountInfo: () => ({
-                one: 'Recomendamos fechar a conta com segurança para evitar o fechamento caso haja: <bullet-list><bullet-item>aprovações pendentes</bullet-item><bullet-item>reembolsos ativos</bullet-item><bullet-item>nenhum método de login alternativo</bullet-item></bullet-list>Caso contrário, você pode ignorar as precauções de segurança acima e forçar o fechamento da conta selecionada.',
-                other: 'Recomendamos fechar as contas com segurança para evitar o fechamento caso haja: <bullet-list><bullet-item>aprovações pendentes</bullet-item><bullet-item>reembolsos ativos</bullet-item><bullet-item>nenhum método de login alternativo</bullet-item></bullet-list>Caso contrário, você pode ignorar as precauções de segurança acima e forçar o fechamento das contas selecionadas.',
-            }),
+            forceCloseAccount: 'Forçar encerramento da conta',
+            safeCloseAccount: 'Fechar conta com segurança',
+            closeAccountInfo:
+                'Recomendamos fechar a conta com segurança para evitar o fechamento caso haja: <ul><li>aprovações pendentes</li><li>reembolsos ativos</li><li>nenhum método de login alternativo</li></ul>Caso contrário, você pode ignorar as precauções de segurança acima e forçar o fechamento da conta selecionada.',
             error: {
                 removeMember: 'Não foi possível remover este usuário. Tente novamente.',
                 addMember: 'Não foi possível adicionar este membro. Tente novamente.',
-                vacationDelegate: 'Não foi possível definir este usuário como delegado de férias. Tente novamente.',
-                moveMember: 'Não foi possível mover este membro. Tente novamente.',
-                moveMemberNotPolicyAdmin:
-                    'Não é possível mover o membro para o grupo de domínio. Você deve ser Administrador de Política para a Política Preferencial definida no grupo de domínio para o qual está tentando mover este usuário.',
-            },
-            cannotSetVacationDelegateForMember: (email: string) => `Você não pode definir um procurador de férias para ${email} porque esta pessoa já é procuradora dos seguintes membros:`,
-            reportSuspiciousActivityPrompt: (email: string) =>
-                `Tem certeza? Isso irá bloquear a conta de <strong>${email}</strong>. <br /><br /> Nossa equipe irá então analisar a conta e remover qualquer acesso não autorizado. Para recuperar o acesso, será necessário que trabalhem com a Concierge.`,
-            reportSuspiciousActivityConfirmationPrompt: 'Vamos revisar a conta para verificar se é seguro desbloqueá-la e entraremos em contato via Concierge caso haja dúvidas.',
-            emptyMembers: {title: 'Nenhum membro neste grupo', subtitle: 'Adicione um membro ou tente mudar o filtro acima.'},
-            moveToGroup: 'Mover para grupo',
-            chooseWhereToMove: ({count}: {count: number}) => `Escolha para onde mover ${count} ${count === 1 ? 'membro' : 'membros'}.`,
-            domainGroup: 'Grupo de domínio',
-            chooseWhereToMoveName: ({name}: {name: string}) => `Escolha para onde mover ${name}.`,
-            membersFeatureList: {
-                subtitle: ({domainName}: {domainName: string}) =>
-                    `<muted-text>Verifique seu domínio para ter mais controle sobre os membros de <strong>${domainName}</strong> no Expensify.</muted-text>`,
-                controlPolicyCreation: 'Restringir criação de espaço de trabalho',
-                enableSamlSso: 'Ativar SSO SAML',
-                enforce2FA: 'Exigir 2FA',
             },
         },
-        common: {
-            settings: 'Configurações',
-            forceTwoFactorAuth: 'Forçar autenticação em duas etapas',
-            forceTwoFactorAuthSAMLEnabledDescription: (samlPageUrl: string) =>
-                `<muted-text>Desative o <a href="${samlPageUrl}">SAML</a> para forçar a autenticação em duas etapas.</muted-text>`,
-            forceTwoFactorAuthDescription: `<muted-text>Exigir autenticação em duas etapas para todos os membros deste domínio. Os membros do domínio serão solicitados a configurar a autenticação em duas etapas na conta ao fazer login.</muted-text>`,
-            forceTwoFactorAuthError: 'Não foi possível alterar a exigência de autenticação em duas etapas. Tente novamente mais tarde.',
-            resetTwoFactorAuth: 'Redefinir autenticação de dois fatores',
-            error: 'Não foi possível salvar esta alteração. Tente novamente.',
-        },
-        groups: {
-            title: 'Grupos',
-            memberCount: () => ({one: '1 membro', other: (count: number) => `${count} membros`}),
-            defaultGroup: 'Grupo padrão para novos membros',
-            defaultGroupPrompt: (currentName: string, newName: string) =>
-                `Tem certeza de que deseja tornar ${newName} o grupo padrão? Novos membros serão convidados para este grupo em vez do grupo padrão anterior (${currentName}). `,
-            makeDefault: 'Tornar padrão',
-            neverMind: 'Deixa pra lá',
-            createGroupError: 'Não foi possível criar este grupo. Tente novamente.',
-            permissions: 'Permissões do grupo',
-            createNewGroupButton: 'Novo grupo',
-            createGroupSubmitButton: 'Criar grupo',
-            expensifyCardPreferredWorkspace: 'Espaço de trabalho preferido para o cartão Expensify',
-            expensifyCardPreferredWorkspaceDescription:
-                'Todas as transações do Expensify Card serão criadas no espaço de trabalho preferido do Expensify Card em vez do espaço de trabalho preferido.',
-            strictlyEnforceWorkspaceRules: 'Aplicar rigorosamente as regras do espaço de trabalho',
-            strictlyEnforceWorkspaceRulesDescription: 'Todas as regras do espaço de trabalho devem ser atendidas antes de enviar um relatório. Não são permitidas exceções manuais.',
-            restrictExpenseWorkspaceCreation: 'Restringir a criação/remoção de espaços de trabalho de despesas',
-            restrictExpenseWorkspaceCreationDescription:
-                'Impede que os membros possam criar um espaço de trabalho de despesas ou se removerem de um espaço de trabalho de despesas. Isso é útil para impedir que as pessoas usem o Expensify para enviar relatórios destinados ao uso fora do seu domínio, quando combinado com a aplicação rigorosa de espaços de trabalho.',
-            deleteGroup: 'Excluir grupo',
-            deleteGroupDangerConfirmationModal: 'Excluir grupo',
-            deleteGroupDangerConfirmationModalDescription: (defaultGroupName: string) =>
-                `Tem certeza? Isso reatribuirá todos os membros ao grupo padrão (${defaultGroupName}) e não poderá ser desfeito.`,
-            deleteGroupError: 'Não foi possível excluir este grupo. Tente novamente.',
-            preferredWorkspace: 'Espaço de trabalho preferido',
-            preferredWorkspaceDescription: (enabled: boolean) =>
-                `Todos os novos relatórios e despesas serão criados ${enabled ? 'no espaço de trabalho preferido selecionado' : 'neste espaço de trabalho'}.`,
-            preferredWorkspaceSelectDescription: 'Todas as novas despesas e relatórios serão criados neste espaço de trabalho.',
-            noWorkspacesMessage: 'Não há espaços de trabalho neste domínio. Um espaço de trabalho é necessário para ativar esta restrição.',
-            restrictDefaultLoginSelection: 'Restringir seleção de login padrão',
-            restrictDefaultLoginSelectionDescription:
-                'Impede que os membros alterem o e-mail de login para um endereço fora do domínio da empresa, evitando que burlem restrições de políticas.',
-            expensifyCardPreferredWorkspaceDisabledMessage: 'Para ativar esta configuração, primeiro ative um workspace preferido e configure os Cartões Expensify no seu domínio.',
-            findGroup: 'Encontrar grupo',
-        },
-    },
-    proactiveAppReview: {
-        title: 'Curtindo o novo Expensify?',
-        description: 'Avise-nos para que possamos ajudar a tornar sua experiência com despesas ainda melhor.',
-        positiveButton: 'Sim!',
-        negativeButton: 'Na verdade, não',
-    },
-    monthPickerPage: {month: 'Mês', selectMonth: 'Selecione um mês por favor'},
+    },
 };
 export default translations;
diff --git a/src/languages/types.ts b/src/languages/types.ts
index 3451d91310d6..afcea14b78a9 100644
--- a/src/languages/types.ts
+++ b/src/languages/types.ts
@@ -21,6 +21,7 @@ type TranslationLeafValue<TStringOrFunction> = TStringOrFunction extends (...arg
  * Translation object is a recursive object that can contain other objects or string/function values
  */
 type TranslationDeepObject<TTranslations = any> = {
+    // eslint-disable-next-line @typescript-eslint/no-explicit-any
     [Path in keyof TTranslations]: TTranslations[Path] extends string | ((...args: any[]) => any)
         ? TranslationLeafValue<TTranslations[Path]>
         : TTranslations[Path] extends number | boolean | null | undefined | unknown[]
diff --git a/src/languages/zh-hans.ts b/src/languages/zh-hans.ts
index 0c04f865a8d2..d3f31e877a6c 100644
--- a/src/languages/zh-hans.ts
+++ b/src/languages/zh-hans.ts
@@ -11,52 +11,189 @@
  */
 import {CONST as COMMON_CONST} from 'expensify-common';
 import startCase from 'lodash/startCase';
-import type {ValueOf} from 'type-fest';
 import type {OnboardingTask} from '@libs/actions/Welcome/OnboardingFlow';
 import StringUtils from '@libs/StringUtils';
 import dedent from '@libs/StringUtils/dedent';
 import CONST from '@src/CONST';
 import type {Country} from '@src/CONST';
 import type OriginalMessage from '@src/types/onyx/OriginalMessage';
-import type {OriginalMessageSettlementAccountLocked, PersonalRulesModifiedFields, PolicyRulesModifiedFields} from '@src/types/onyx/OriginalMessage';
+import type {OriginalMessageSettlementAccountLocked, PolicyRulesModifiedFields} from '@src/types/onyx/OriginalMessage';
+import ObjectUtils from '@src/types/utils/ObjectUtils';
 import type en from './en';
 import type {
+    AddBudgetParams,
+    AddedOrDeletedPolicyReportFieldParams,
+    AddOrDeletePolicyCustomUnitRateParams,
     ChangeFieldParams,
-    ConciergeBrokenCardConnectionParams,
     ConnectionNameParams,
+    CreatedReportForUnapprovedTransactionsParams,
     DelegateRoleParams,
     DeleteActionParams,
+    DeleteBudgetParams,
     DeleteConfirmationParams,
     EditActionParams,
     ExportAgainModalDescriptionParams,
     ExportIntegrationSelectedParams,
+    ImportPolicyCustomUnitRatesParams,
     IntacctMappingTitleParams,
     InvalidPropertyParams,
     InvalidValueParams,
     MarkReimbursedFromIntegrationParams,
     MissingPropertyParams,
     MovedFromPersonalSpaceParams,
+    MultifactorAuthenticationTranslationParams,
+    NextStepParams,
     NotAllowedExtensionParams,
     OptionalParam,
     PaidElsewhereParams,
     ParentNavigationSummaryParams,
     RemovedFromApprovalWorkflowParams,
+    RemovedPolicyCustomUnitSubRateParams,
     ReportArchiveReasonsClosedParams,
     ReportArchiveReasonsInvoiceReceiverPolicyDeletedParams,
     ReportArchiveReasonsMergedParams,
     ReportArchiveReasonsRemovedFromPolicyParams,
+    ReportFieldParams,
+    ReportPolicyNameParams,
+    RequestAmountParams,
+    RequiredFieldParams,
     ResolutionConstraintsParams,
+    ReviewParams,
+    RoleNamesParams,
+    RoomNameReservedErrorParams,
+    RoomRenamedToParams,
+    RoutedDueToDEWParams,
+    RulesEnableWorkflowsParams,
+    SecondaryLoginParams,
+    SetTheDistanceMerchantParams,
+    SetTheRequestParams,
+    SettledAfterAddedBankAccountParams,
+    SettleExpensifyCardParams,
+    SettlementAccountInfoParams,
+    SettlementAccountReconciliationParams,
+    SettlementDateParams,
     ShareParams,
+    SignerInfoMessageParams,
+    SignUpNewFaceCodeParams,
     SizeExceededParams,
+    SplitAmountParams,
+    SplitDateRangeParams,
+    SplitExpenseEditTitleParams,
+    SplitExpenseSubtitleParams,
+    StatementTitleParams,
     StepCounterParams,
+    StripePaidParams,
+    SubmitsToParams,
+    SubmittedToVacationDelegateParams,
+    SubmittedWithMemoParams,
+    SubscriptionCommitmentParams,
+    SubscriptionSettingsLearnMoreParams,
+    SubscriptionSettingsRenewsOnParams,
+    SubscriptionSettingsSaveUpToParams,
+    SubscriptionSettingsSummaryParams,
+    SubscriptionSizeParams,
     SyncStageNameConnectionsParams,
+    TaskCreatedActionParams,
+    TaxAmountParams,
+    TermsParams,
+    ThreadRequestReportNameParams,
+    ThreadSentMoneyReportNameParams,
+    ToggleImportTitleParams,
+    TotalAmountGreaterOrLessThanOriginalParams,
+    ToValidateLoginParams,
+    TransferParams,
+    TravelTypeParams,
+    TrialStartedTitleParams,
+    UnapproveWithIntegrationWarningParams,
     UnshareParams,
-    UnsupportedFormulaValueErrorParams,
+    UntilTimeParams,
+    UpdatedBudgetParams,
+    UpdatedCustomFieldParams,
+    UpdatedPolicyApprovalRuleParams,
+    UpdatedPolicyAuditRateParams,
+    UpdatedPolicyAutoHarvestingParams,
+    UpdatedPolicyBudgetNotificationParams,
+    UpdatedPolicyCategoriesParams,
+    UpdatedPolicyCategoryDescriptionHintTypeParams,
+    UpdatedPolicyCategoryExpenseLimitTypeParams,
+    UpdatedPolicyCategoryGLCodeParams,
+    UpdatedPolicyCategoryMaxAmountNoReceiptParams,
+    UpdatedPolicyCategoryMaxExpenseAmountParams,
+    UpdatedPolicyCategoryNameParams,
+    UpdatedPolicyCategoryParams,
+    UpdatedPolicyCurrencyParams,
+    UpdatedPolicyCustomUnitRateEnabledParams,
+    UpdatedPolicyCustomUnitRateParams,
+    UpdatedPolicyCustomUnitSubRateParams,
+    UpdatedPolicyCustomUnitTaxClaimablePercentageParams,
+    UpdatedPolicyCustomUnitTaxRateExternalIDParams,
+    UpdatedPolicyDefaultTitleParams,
+    UpdatedPolicyDescriptionParams,
+    UpdatedPolicyFieldWithNewAndOldValueParams,
+    UpdatedPolicyFieldWithValueParams,
+    UpdatedPolicyFrequencyParams,
+    UpdatedPolicyManualApprovalThresholdParams,
+    UpdatedPolicyOwnershipParams,
+    UpdatedPolicyPreventSelfApprovalParams,
+    UpdatedPolicyReimbursementChoiceParams,
+    UpdatedPolicyReimbursementEnabledParams,
+    UpdatedPolicyReimburserParams,
+    UpdatedPolicyReportFieldDefaultValueParams,
+    UpdatedPolicyTagFieldParams,
+    UpdatedPolicyTagListParams,
+    UpdatedPolicyTagListRequiredParams,
+    UpdatedPolicyTagNameParams,
+    UpdatedPolicyTagParams,
+    UpdatedPolicyTaxParams,
+    UpdatedPolicyTimeEnabledParams,
+    UpdatedPolicyTimeRateParams,
+    UpdatedTheDistanceMerchantParams,
+    UpdatedTheRequestParams,
+    UpdatePolicyCustomUnitDefaultCategoryParams,
+    UpdatePolicyCustomUnitParams,
+    UpdatePolicyCustomUnitTaxEnabledParams,
     UpdateRoleParams,
-    ViolationsIncreasedDistanceParams,
+    UpgradeSuccessMessageParams,
+    UsePlusButtonParams,
+    UserIsAlreadyMemberParams,
+    UserSplitParams,
+    VacationDelegateParams,
+    ViolationsCashExpenseWithNoReceiptParams,
+    ViolationsConversionSurchargeParams,
+    ViolationsCustomRulesParams,
+    ViolationsInvoiceMarkupParams,
+    ViolationsMaxAgeParams,
+    ViolationsMissingTagParams,
     ViolationsModifiedAmountParams,
+    ViolationsOverCategoryLimitParams,
+    ViolationsOverLimitParams,
+    ViolationsPerDayLimitParams,
+    ViolationsProhibitedExpenseParams,
+    ViolationsReceiptRequiredParams,
+    ViolationsRterParams,
+    ViolationsTagOutOfPolicyParams,
+    ViolationsTaxOutOfPolicyParams,
+    WaitingOnBankAccountParams,
+    WalletAgreementParams,
+    WalletProgramParams,
+    WelcomeEnterMagicCodeParams,
+    WelcomeToRoomParams,
+    WeSentYouMagicSignInLinkParams,
+    WorkEmailMergingBlockedParams,
+    WorkEmailResendCodeParams,
+    WorkflowSettingsParam,
     WorkspaceLockedPlanTypeParams,
+    WorkspaceMemberList,
+    WorkspaceMembersCountParams,
+    WorkspaceOwnerWillNeedToAddOrUpdatePaymentCardParams,
+    WorkspaceRouteParams,
+    WorkspaceShareNoteParams,
+    WorkspacesListRouteParams,
+    WorkspaceUpgradeNoteParams,
+    WorkspaceYouMayJoin,
     YourPlanPriceParams,
+    YourPlanPriceValueParams,
+    ZipCodeExampleFormatParams,
 } from './params';
 import type {TranslationDeepObject} from './types';
 
@@ -90,10 +227,8 @@ const translations: TranslationDeepObject<typeof en> = {
         optional: '可选',
         new: '新',
         newFeature: '新功能',
-        beta: '测试版',
         search: '搜索',
         reports: '报表',
-        spend: '支出',
         find: '查找',
         searchWithThreeDots: '搜索…',
         next: '下一步',
@@ -118,14 +253,6 @@ const translations: TranslationDeepObject<typeof en> = {
         workspaces: '工作区',
         home: '主页',
         inbox: '收件箱',
-        yourReviewIsRequired: '需要您的审核',
-        actionBadge: {
-            submit: '提交',
-            approve: '批准',
-            pay: '支付',
-            fix: '修复',
-            task: '任务',
-        },
         success: '成功',
         group: '群组',
         profile: '个人资料',
@@ -135,7 +262,7 @@ const translations: TranslationDeepObject<typeof en> = {
         wallet: '钱包',
         preferences: '偏好设置',
         view: '查看',
-        review: (amount?: string) => `审核${amount ? ` ${amount}` : ''}`,
+        review: (reviewParams?: ReviewParams) => `审核${reviewParams?.amount ? ` ${reviewParams?.amount}` : ''}`,
         not: '否',
         signIn: '登录',
         signInWithGoogle: '使用 Google 登录',
@@ -146,7 +273,6 @@ const translations: TranslationDeepObject<typeof en> = {
         lastName: '姓氏',
         scanning: '正在扫描',
         analyzing: '正在分析…',
-        thinking: 'Concierge 正在思考...',
         addCardTermsOfService: 'Expensify 服务条款',
         perPerson: '每人',
         phone: '电话',
@@ -208,12 +334,10 @@ const translations: TranslationDeepObject<typeof en> = {
         admin: '管理员',
         owner: '所有者',
         dateFormat: 'YYYY-MM-DD',
-        calendarOpened: '日历已打开',
         send: '发送',
         na: '不适用',
         noResultsFound: '未找到结果',
-        noResultsFoundMatching: (searchString: string) => `未找到与”${searchString}”匹配的结果`,
-        suggestionsAvailableFor: (searchString: string) => (searchString ? `”${searchString}”的建议可用。` : '建议可用。'),
+        noResultsFoundMatching: (searchString: string) => `未找到与“${searchString}”匹配的结果`,
         recentDestinations: '最近目的地',
         timePrefix: '它是',
         conjunctionFor: '用于',
@@ -224,7 +348,6 @@ const translations: TranslationDeepObject<typeof en> = {
         conjunctionTo: '至',
         genericErrorMessage: '哎呀……出现问题，无法完成您的请求。请稍后重试。',
         percentage: '百分比',
-        progressBarLabel: '入门进度',
         converted: '已转换',
         error: {
             invalidAmount: '金额无效',
@@ -263,7 +386,6 @@ const translations: TranslationDeepObject<typeof en> = {
         reset: '重置',
         done: '完成',
         more: '更多',
-        other: '其他',
         debitCard: '借记卡',
         bankAccount: '银行账户',
         personalBankAccount: '个人银行账户',
@@ -289,7 +411,7 @@ const translations: TranslationDeepObject<typeof en> = {
         verify: '验证',
         yesContinue: '是，继续',
         websiteExample: '例如：https://www.expensify.com',
-        zipCodeExampleFormat: (zipSampleFormat: string) => (zipSampleFormat ? `例如：${zipSampleFormat}` : ''),
+        zipCodeExampleFormat: ({zipSampleFormat}: ZipCodeExampleFormatParams) => (zipSampleFormat ? `例如：${zipSampleFormat}` : ''),
         description: '描述',
         title: '标题',
         assignee: '受托人',
@@ -300,8 +422,6 @@ const translations: TranslationDeepObject<typeof en> = {
         per: '每',
         mi: '英里',
         km: '千米',
-        milesAbbreviated: '英里',
-        kilometersAbbreviated: '千米',
         copied: '已复制！',
         someone: '某人',
         total: '总计',
@@ -310,7 +430,6 @@ const translations: TranslationDeepObject<typeof en> = {
         letsStart: `开始吧`,
         showMore: '显示更多',
         showLess: '收起',
-        plusMore: ({count}: {count: number}) => `+${count}个`,
         merchant: '商户',
         change: '更改',
         category: '类别',
@@ -334,11 +453,8 @@ const translations: TranslationDeepObject<typeof en> = {
         selectCurrency: '选择货币',
         selectSymbolOrCurrency: '选择符号或货币',
         card: '卡片',
-        mcc: 'MCC',
-        categoryGLCode: '类别总账科目代码',
         whyDoWeAskForThis: '我们为什么要询问这个？',
         required: '必填',
-        automatic: '自动',
         showing: '正在显示',
         of: '的',
         default: '默认',
@@ -346,7 +462,6 @@ const translations: TranslationDeepObject<typeof en> = {
         member: '成员',
         auditor: '审计员',
         role: '角色',
-        roleCannotBeChanged: (workflowsLinkPage: string) => `该角色无法更改，因为此成员是此工作区中的<a href="${workflowsLinkPage}">付款人</a>。`,
         currency: '货币',
         groupCurrency: '群组货币',
         rate: '评分',
@@ -384,7 +499,6 @@ const translations: TranslationDeepObject<typeof en> = {
         reportID: '报销单编号',
         longReportID: '长报表 ID',
         withdrawalID: '提现编号',
-        withdrawalStatus: '提现状态',
         bankAccounts: '银行账户',
         chooseFile: '选择文件',
         chooseFiles: '选择文件',
@@ -418,25 +532,26 @@ const translations: TranslationDeepObject<typeof en> = {
         validate: '验证',
         downloadAsPDF: '下载为 PDF',
         downloadAsCSV: '下载为 CSV',
-        print: '打印',
         help: '帮助',
-        collapsed: '已折叠',
-        expanded: '已展开',
         expenseReport: '报销报告',
+        expenseReports: '报销报告',
         rateOutOfPolicy: '超出政策的费率',
         leaveWorkspace: '离开工作区',
         leaveWorkspaceConfirmation: '如果你离开此工作区，将无法再向其提交报销。',
         leaveWorkspaceConfirmationAuditor: '如果你离开此工作区，将无法查看其报表和设置。',
         leaveWorkspaceConfirmationAdmin: '如果你离开此工作区，将无法管理其设置。',
-        leaveWorkspaceConfirmationApprover: (workspaceOwner: string) => `如果你离开此工作区，你在审批流程中的角色将由工作区所有者 ${workspaceOwner} 接替。`,
-        leaveWorkspaceConfirmationExporter: (workspaceOwner: string) => `如果你离开此工作区，你将被工作区所有者 ${workspaceOwner} 取代，成为首选导出人。`,
-        leaveWorkspaceConfirmationTechContact: (workspaceOwner: string) => `如果你离开此工作区，你将由工作区所有者 ${workspaceOwner} 接任技术联系人。`,
+        leaveWorkspaceConfirmationApprover: ({workspaceOwner}: {workspaceOwner: string}) => `如果你离开此工作区，你在审批流程中的角色将由工作区所有者 ${workspaceOwner} 接替。`,
+        leaveWorkspaceConfirmationExporter: ({workspaceOwner}: {workspaceOwner: string}) => `如果你离开此工作区，你将被工作区所有者 ${workspaceOwner} 取代，成为首选导出人。`,
+        leaveWorkspaceConfirmationTechContact: ({workspaceOwner}: {workspaceOwner: string}) => `如果你离开此工作区，你将由工作区所有者 ${workspaceOwner} 接任技术联系人。`,
         leaveWorkspaceReimburser: '作为报销人，您无法离开此工作区。请前往“工作区”>“进行或跟踪付款”中设置新的报销人，然后重试。',
         reimbursable: '可报销',
         editYourProfile: '编辑个人资料',
         comments: '评论',
         sharedIn: '共享于',
         unreported: '未报销',
+        explore: '探索',
+        insights: '洞察',
+        todo: '待办事项',
         invoice: '发票',
         expense: '报销',
         chat: '聊天',
@@ -447,15 +562,12 @@ const translations: TranslationDeepObject<typeof en> = {
         on: '开打开',
         before: '之前',
         after: '之后',
-        range: '范围',
         reschedule: '重新安排',
         general: '常规',
         workspacesTabTitle: '工作区',
         headsUp: '注意！',
         submitTo: '提交给',
         forwardTo: '转发至',
-        approvalLimit: '审批限额',
-        overLimitForwardTo: '超出限额时转发至',
         merge: '合并',
         none: '无',
         unstableInternetConnection: '网络连接不稳定。请检查您的网络后重试。',
@@ -476,47 +588,19 @@ const translations: TranslationDeepObject<typeof en> = {
         exchangeRate: '汇率',
         reimbursableTotal: '可报销总额',
         nonReimbursableTotal: '不可报销总额',
-        opensInNewTab: '在新标签页中打开',
         locked: '已锁定',
         month: '月',
         week: '周',
         year: '年份',
         quarter: '季度',
-        vacationDelegate: '休假代理',
-        expensifyLogo: 'Expensify徽标',
-        concierge: {greeting: '你好，我能帮你做什么？', showHistory: '显示历史'},
-        duplicateReport: '重复报销单',
-        approver: '审批人',
-        goToConcierge: '前往 Concierge',
-        allSet: '全部就绪！',
-        enterDigitLabel: ({digitIndex, totalDigits}: {digitIndex: number; totalDigits: number}) => `输入第 ${digitIndex} 位数字，共 ${totalDigits} 位`,
-        copyOfReportName: (reportName: string) => `${reportName} 的副本`,
-        previousMonth: '上个月',
-        nextMonth: '下个月',
-        previousYear: '上一年',
-        nextYear: '明年',
-        avatar: '头像',
-        editor: '编辑',
-        restrictions: '限制',
-    },
-    socials: {
-        podcast: '在播客上关注我们',
-        twitter: '在Twitter上关注我们',
-        instagram: '在Instagram上关注我们',
-        facebook: '在Facebook上关注我们',
-        linkedin: '在LinkedIn上关注我们',
-    },
-    concierge: {
-        collapseReasoning: '收起推理',
-        expandReasoning: '展开推理',
-        enableNotifications: {
-            prompt: '希望在Concierge回复时收到通知吗？',
-            cta: '通知',
-        },
     },
     supportalNoAccess: {
         title: '先别急',
-        descriptionWithCommand: (command?: string) => `当以支持身份登录时，你无权执行此操作（命令：${command ?? ''}）。如果你认为 Success 应该能够执行此操作，请在 Slack 中发起一次会话。`,
+        descriptionWithCommand: ({
+            command,
+        }: {
+            command?: string;
+        } = {}) => `当以支持身份登录时，你无权执行此操作（命令：${command ?? ''}）。如果你认为 Success 应该能够执行此操作，请在 Slack 中发起一次会话。`,
     },
     lockedAccount: {
         title: '账户已锁定',
@@ -551,7 +635,7 @@ const translations: TranslationDeepObject<typeof en> = {
         chooseDocument: '选择文件',
         attachmentTooLarge: '附件过大',
         sizeExceeded: '附件大小超过 24 MB 上限',
-        sizeExceededWithLimit: (maxUploadSizeInMB: number) => `附件大小超过 ${maxUploadSizeInMB} MB 的限制`,
+        sizeExceededWithLimit: ({maxUploadSizeInMB}: SizeExceededParams) => `附件大小超过 ${maxUploadSizeInMB} MB 的限制`,
         attachmentTooSmall: '附件太小',
         sizeNotMet: '附件大小必须大于 240 字节',
         wrongFileType: '文件类型无效',
@@ -562,9 +646,9 @@ const translations: TranslationDeepObject<typeof en> = {
         attachmentImageTooLarge: '此图片过大，无法在上传前预览。',
         imageDimensionsTooLarge: '图片尺寸过大，无法处理。请使用较小的图片。',
         tooManyFiles: (fileLimit: number) => `您一次最多只能上传 ${fileLimit} 个文件。`,
-        sizeExceededWithValue: (maxUploadSizeInMB: number) => `文件超过 ${maxUploadSizeInMB} MB。请重试。`,
+        sizeExceededWithValue: ({maxUploadSizeInMB}: SizeExceededParams) => `文件超过 ${maxUploadSizeInMB} MB。请重试。`,
         someFilesCantBeUploaded: '某些文件无法上传',
-        sizeLimitExceeded: (maxUploadSizeInMB: number) => `文件大小必须小于 ${maxUploadSizeInMB} MB。更大的文件将不会被上传。`,
+        sizeLimitExceeded: ({maxUploadSizeInMB}: SizeExceededParams) => `文件大小必须小于 ${maxUploadSizeInMB} MB。更大的文件将不会被上传。`,
         maxFileLimitExceeded: '您一次最多可上传 30 张收据，超出的将不会被上传。',
         unsupportedFileType: (fileType: string) => `不支持 ${fileType} 文件。只有受支持的文件类型会被上传。`,
         learnMoreAboutSupportedFiles: '了解支持的格式详情。',
@@ -604,44 +688,17 @@ const translations: TranslationDeepObject<typeof en> = {
         signIn: '请重新登录。',
     },
     multifactorAuthentication: {
-        reviewTransaction: {
-            reviewTransaction: '查看交易',
-            pleaseReview: '请审核此交易',
-            requiresYourReview: '需要您在下方审核一笔 Expensify Card 交易。',
-            transactionDetails: '交易详情',
-            deny: '拒绝',
-            approve: '批准',
-            denyTransaction: '拒绝交易',
-            transactionDenied: '交易被拒绝',
-            transactionApproved: '交易已批准！',
-            areYouSureToDeny: '您确定吗？如果关闭此界面，这笔交易将被拒绝。',
-            youCanTryAgainAtMerchantOrReachOut: '您可以在商家处重试。如果您没有发起此交易，请<concierge-link>联系 Concierge</concierge-link>报告潜在欺诈。',
-            youNeedToTryAgainAtMerchant: '此交易未通过验证，因此已被拒绝。请在商户处重新尝试。',
-            goBackToTheMerchant: '返回商家网站以继续完成交易。',
-            attemptedTransaction: '已尝试的交易',
-            transactionFailed: '交易失败',
-            transactionCouldNotBeCompleted: '您的交易未能完成。请在商户处重试。',
-            transactionCouldNotBeCompletedReachOut: '您的交易无法完成。如果您未尝试进行此笔交易，请<concierge-link>联系 Concierge</concierge-link>报告潜在欺诈。',
-            reviewFailed: '审核失败',
-            alreadyReviewedSubtitle:
-                '您已审核过此交易。请查看您的<transaction-history-link>交易记录</transaction-history-link>，或联系<concierge-link>Concierge</concierge-link>报告任何问题。',
-        },
         biometricsTest: {
             biometricsTest: '生物识别测试',
-            authenticationSuccessful: '认证成功',
-            successfullyAuthenticatedUsing: (authType?: string) => `您已成功使用 ${authType} 完成验证。`,
-            troubleshootBiometricsStatus: ({status}: {status?: string}) => `生物识别（${status}）`,
+            authenticationSuccessful: '验证成功',
+            successfullyAuthenticatedUsing: ({authType}: MultifactorAuthenticationTranslationParams) => `您已成功使用 ${authType} 完成验证。`,
+            troubleshootBiometricsStatus: ({registered}: MultifactorAuthenticationTranslationParams) => `生物识别（${registered ? '已注册' : '未注册'}）`,
             yourAttemptWasUnsuccessful: '您的身份验证尝试未成功。',
             youCouldNotBeAuthenticated: '无法验证您的身份',
             areYouSureToReject: '您确定吗？如果您关闭此界面，此次身份验证尝试将被拒绝。',
             rejectAuthentication: '拒绝认证',
             test: '测试',
             biometricsAuthentication: '生物识别认证',
-            authType: {unknown: '未知', none: '无', credentials: '凭据', biometrics: '生物识别', faceId: 'Face ID', touchId: 'Touch ID', opticId: 'Optic ID', passkey: 'Passkey'},
-            statusNeverRegistered: '从未注册',
-            statusNotRegistered: '未注册',
-            statusRegisteredThisDevice: '已注册',
-            statusRegisteredOtherDevice: () => ({one: '已注册另一台设备', other: '已注册的其他设备'}),
         },
         pleaseEnableInSystemSettings: {
             start: '请在您的设备中启用面部/指纹验证或设置设备密码',
@@ -654,38 +711,26 @@ const translations: TranslationDeepObject<typeof en> = {
         letsVerifyItsYou: '让我们验证一下您的身份',
         nowLetsAuthenticateYou: '现在，让我们为你进行身份验证…',
         letsAuthenticateYou: '正在验证您的身份…',
-        verifyYourself: {biometrics: '使用面部或指纹验证您的身份', passkeys: '使用通行密钥验证您的身份'},
-        enableQuickVerification: {biometrics: '使用面部或指纹即可进行快速、安全的验证，无需密码或验证码。', passkeys: '启用使用通行密钥进行快速、安全的验证，无需密码或验证码。'},
+        verifyYourself: {
+            biometrics: '使用面部或指纹验证您的身份',
+        },
+        enableQuickVerification: {
+            biometrics: '使用面部或指纹即可进行快速、安全的验证，无需密码或验证码。',
+        },
         revoke: {
+            remove: '移除',
             title: '面容/指纹和通行密钥',
-            explanation: '一个或多个设备已启用面容/指纹或通行密钥验证。撤销访问权限后，该设备下次验证时将需要输入魔法验证码。',
-            confirmationPrompt: '你确定吗？你下次在该设备上验证时需要使用魔法验证码。',
+            explanation: '在一台或多台设备上已启用面容/指纹或通行密钥验证。撤销访问后，下次在任何设备上进行验证时都需要输入魔法验证码。',
+            confirmationPrompt: '确定吗？下一次在任何设备上进行验证时，你都需要输入魔法码。',
             cta: '撤销访问权限',
-            noDevices: '你还没有注册用于人脸 / 指纹或通行密钥验证的任何设备。如果你注册了设备，就可以在这里撤销其访问权限。',
-            dismiss: '知道了',
+            noDevices: '您尚未注册用于面部 / 指纹或通行密钥验证的任何设备。如果您注册了设备，之后可以在此撤销该访问权限。',
+            dismiss: '明白了',
             error: '请求失败。请稍后重试。',
-            revoke: '撤销',
-            confirmationPromptAll: '您确定吗？您在任何设备上进行下一次验证时都需要输入魔法验证码。',
-            ctaAll: '全部撤销',
-            thisDevice: '此设备',
-            otherDevices: (otherDeviceCount?: number) => {
-                const numberWords = ['一', '二', '三', '四', '五', '六', '七', '八', '九'];
-                const displayCount = otherDeviceCount !== undefined && otherDeviceCount >= 1 && otherDeviceCount <= 9 ? numberWords.at(otherDeviceCount - 1) : `${otherDeviceCount}`;
-                return `${displayCount} 个其他 ${otherDeviceCount === 1 ? '设备' : '设备'}`;
-            },
-            confirmationPromptThisDevice: '确定要这样做吗？下次在此设备上进行验证时，您需要输入魔法验证码。',
-            confirmationPromptMultiple: '确定吗？你下次在这些设备上验证时需要输入魔法验证码。',
         },
         unsupportedDevice: {
             unsupportedDevice: '不支持的设备',
-            pleaseDownloadMobileApp: `您的设备不支持此操作。请从<a href="${CONST.APP_DOWNLOAD_LINKS.IOS}">App Store</a>或<a href="${CONST.APP_DOWNLOAD_LINKS.ANDROID}">Google Play 商店</a>下载 Expensify 应用，然后重试。`,
-            pleaseUseWebApp: `您的设备不支持此操作。请使用<a href="${CONST.NEW_EXPENSIFY_URL}">Expensify 网页应用</a>重试。`,
+            pleaseDownloadMobileApp: `<centered-text><muted-text> 您的设备不支持此操作。请从<a href="${CONST.APP_DOWNLOAD_LINKS.IOS}">App Store</a>或<a href="${CONST.APP_DOWNLOAD_LINKS.ANDROID}">Google Play 商店</a>下载 Expensify 应用，然后重试。</muted-text></centered-text>`,
         },
-        verificationFailed: '验证失败',
-        setPin: {didNotShipCard: '我们未能寄出您的卡。请重试。'},
-        revealPin: {couldNotReveal: '我们无法显示您的 PIN。请重试。'},
-        changePin: {didNotChange: '我们未更改您的 PIN。请重试。'},
-        revealCardDetail: {couldNotReveal: '我们无法显示您的卡片详情。请重试。'},
     },
     validateCodeModal: {
         successfulSignInTitle: dedent(`
@@ -722,7 +767,11 @@ const translations: TranslationDeepObject<typeof en> = {
         nameEmailOrPhoneNumber: '姓名、电子邮件或电话号码',
         findMember: '查找成员',
         searchForSomeone: '搜索联系人',
-        userSelected: (username: string) => `已选择 ${username}`,
+    },
+    customApprovalWorkflow: {
+        title: '自定义审批流程',
+        description: '您的公司在此工作区使用自定义审批流程。请在 Expensify Classic 中执行此操作',
+        goToExpensifyClassic: '切换到 Expensify 经典版',
     },
     emptyList: {
         [CONST.IOU.TYPE.CREATE]: {
@@ -744,8 +793,8 @@ const translations: TranslationDeepObject<typeof en> = {
         phrase2: '金钱会说话。现在聊天和支付集于一处，一切也变得简单。',
         phrase3: '只要你把理由说清楚，款项就能同样快地到你手中。',
         enterPassword: '请输入您的密码',
-        welcomeNewFace: (login: string) => `${login}，很高兴在这里见到新面孔！`,
-        welcomeEnterMagicCode: (login: string) => `请输入发送到 ${login} 的魔法验证码。它应会在一两分钟内送达。`,
+        welcomeNewFace: ({login}: SignUpNewFaceCodeParams) => `${login}，很高兴在这里见到新面孔！`,
+        welcomeEnterMagicCode: ({login}: WelcomeEnterMagicCodeParams) => `请输入发送到 ${login} 的魔法验证码。它应会在一两分钟内送达。`,
     },
     login: {
         hero: {
@@ -773,9 +822,6 @@ const translations: TranslationDeepObject<typeof en> = {
         emoji: '表情符号',
         collapse: '折叠',
         expand: '展开',
-        askConciergeToUpdate: '试试“更新一笔报销”…',
-        askConciergeToCorrect: '尝试搜索“更正一笔报销”…',
-        askConciergeForHelp: '向 Concierge AI 寻求帮助…',
     },
     reportActionContextMenu: {
         copyMessage: '复制消息',
@@ -837,9 +883,9 @@ const translations: TranslationDeepObject<typeof en> = {
         askMeAnything: '尽管问我任何问题！',
         sayHello: '打个招呼！',
         yourSpace: '你的空间',
-        welcomeToRoom: (roomName: string) => `欢迎来到 ${roomName}！`,
-        usePlusButton: (additionalText: string) => `使用 + 按钮来${additionalText}一笔费用。`,
-        askConcierge: 'Concierge 可以回答问题、更新报销等。',
+        welcomeToRoom: ({roomName}: WelcomeToRoomParams) => `欢迎来到 ${roomName}！`,
+        usePlusButton: ({additionalText}: UsePlusButtonParams) => `使用 + 按钮来${additionalText}一笔费用。`,
+        askConcierge: '尽管问我任何问题！',
         conciergeSupport: '您的专属AI助手',
         create: '创建',
         iouTypes: {
@@ -851,14 +897,11 @@ const translations: TranslationDeepObject<typeof en> = {
         },
     },
     adminOnlyCanPost: '只有管理员可以在此房间中发送消息。',
-    readOnlyConversation: '此对话仅可查看。',
     reportAction: {
         asCopilot: '作为副驾驶，用于',
-        assistedBy: (agentName: string) => `由${agentName}协助`,
-        humanSupportAgent: '人工客服',
         harvestCreatedExpenseReport: (reportUrl: string, reportName: string) => `创建了此报销单，用于保存所有来自 <a href="${reportUrl}">${reportName}</a> 且无法按照你选择的频率提交的费用`,
-        createdReportForUnapprovedTransactions: (reportUrl: string, reportName: string, reportID: string, isReportDeleted: boolean) =>
-            isReportDeleted ? `为已删除报销单 #${reportID} 中的所有暂挂报销创建了此报销单` : `为从<a href="${reportUrl}">${reportName}</a>中被暂挂的任何报销创建了此报表`,
+        createdReportForUnapprovedTransactions: ({reportUrl, reportName}: CreatedReportForUnapprovedTransactionsParams) =>
+            `从<a href="${reportUrl}">${reportName}</a>创建了此报表，用于查看任何被暂扣的报销费用`,
     },
     mentionSuggestions: {
         hereAlternateText: '通知此会话中的所有人',
@@ -895,6 +938,7 @@ const translations: TranslationDeepObject<typeof en> = {
         buttonFind: '查找内容…',
         buttonMySettings: '我的设置',
         fabNewChat: '开始聊天',
+        fabNewChatExplained: '打开操作菜单',
         fabScanReceiptExplained: '扫描收据',
         chatPinned: '聊天已置顶',
         draftedMessage: '已起草的消息',
@@ -902,41 +946,37 @@ const translations: TranslationDeepObject<typeof en> = {
         listOfChats: '聊天列表',
         saveTheWorld: '拯救世界',
         tooltip: '从这里开始！',
+        redirectToExpensifyClassicModal: {
+            title: '即将推出',
+            description: '我们正在对新版 Expensify 做最后的一些细节调整，以适配你的特定设置。与此同时，请先前往 Expensify 经典版。',
+        },
     },
     homePage: {
         forYou: '为你',
         timeSensitiveSection: {
             title: '时间敏感',
-            addShippingAddress: {title: '我们需要您的收货地址', subtitle: '请提供一个地址以接收您的 Expensify 卡。', cta: '添加地址'},
-            addPaymentCard: {title: '添加支付卡以继续使用 Expensify', subtitle: '账户 ＞ 订阅', cta: '添加'},
-            activateCard: {title: '激活你的 Expensify 卡', subtitle: '验证您的银行卡并开始消费。', cta: '启用'},
-            reviewCardFraud: {
-                title: '审查您 Expensify 卡上的潜在欺诈交易',
-                titleWithDetails: ({amount, merchant}: {amount: string; merchant: string}) => `查看 ${merchant} 可能存在的 ${amount} 欺诈交易`,
-                subtitle: 'Expensify 卡',
-                cta: '审核',
+            cta: '报销申请',
+            offer50off: {
+                title: '首年立享 5 折优惠！',
+                subtitle: ({formattedTime}: {formattedTime: string}) => `剩余 ${formattedTime}`,
+            },
+            offer25off: {
+                title: '首年立享 75 折优惠！',
+                subtitle: ({days}: {days: number}) => `剩余 ${days} ${days === 1 ? '天' : '天'}`,
+            },
+            addShippingAddress: {
+                title: '我们需要您的收货地址',
+                subtitle: '请提供一个地址以接收您的 Expensify 卡。',
+                cta: '添加地址',
+            },
+            activateCard: {
+                title: '激活你的 Expensify 卡',
+                subtitle: '验证您的银行卡并开始消费。',
+                cta: '启用',
             },
             ctaFix: '修复',
-            fixCompanyCardConnection: {
-                title: ({feedName}: {feedName: string}) => (feedName ? `修复 ${feedName} 公司卡连接` : '修复公司卡连接'),
-                defaultSubtitle: '工作区',
-                subtitle: ({policyName}: {policyName: string}) => `${policyName} > 公司卡片`,
-            },
-            fixPersonalCardConnection: {title: ({cardName}: {cardName?: string}) => (cardName ? `修复 ${cardName} 个人卡连接` : '修复个人银行卡连接'), subtitle: '钱包'},
-            fixPolicyConnection: {
-                title: ({integrationName}: {integrationName: string}) => `修复 ${integrationName} 连接`,
-                defaultSubtitle: '工作区',
-                subtitle: ({policyName}: {policyName: string}) => `${policyName} > 会计`,
-            },
-            validateAccount: {title: '验证您的账户', subtitle: '账户', cta: '验证'},
-            fixFailedBilling: {title: '我们无法向您档案中的银行卡收费', subtitle: '订阅'},
-            unlockBankAccount: {
-                workspaceTitle: '您的企业银行账户已被锁定',
-                personalTitle: '您的银行账户已被锁定',
-                workspaceSubtitle: ({policyName}: {policyName: string}) => policyName,
-                personalSubtitle: '钱包',
-            },
-            enterSignerInfo: {title: '需要签署人信息', subtitle: ({bankAccountLastFour}: {bankAccountLastFour: string}) => `银行账户 ${bankAccountLastFour}`},
+            fixCompanyCardConnection: {title: ({feedName}: {feedName: string}) => (feedName ? `修复 ${feedName} 公司卡连接` : '修复公司卡连接'), subtitle: '工作区 > 公司卡片'},
+            fixAccountingConnection: {title: ({integrationName}: {integrationName: string}) => `修复 ${integrationName} 连接`, subtitle: '工作区 > 会计'},
         },
         announcements: '公告',
         discoverSection: {
@@ -952,73 +992,12 @@ const translations: TranslationDeepObject<typeof en> = {
             export: ({count}: {count: number}) => `导出 ${count} 个 ${count === 1 ? '报表' : '报表'}`,
             begin: '开始',
             emptyStateMessages: {
-                thumbsUpStarsTitle: '你已完成！',
-                thumbsUpStarsDescription: '为你点赞，请留意更多任务。',
-                smallRocketTitle: '全部完成',
-                smallRocketDescription: '即将推出的待办事项会在此显示。',
-                cowboyHatTitle: '你已完成！',
-                cowboyHatDescription: '所有任务都已处理完毕，请留意更多任务。',
-                trophy1Title: '暂无内容展示',
-                trophy1Description: '你成功了！请留意更多待办事项。',
-                palmTreeTitle: '全部完成',
-                palmTreeDescription: '是时候放松一下了，但请留意未来的任务。',
-                fishbowlBlueTitle: '你已完成！',
-                fishbowlBlueDescription: '未来的任务会在这里显示。',
-                targetTitle: '全部完成',
-                targetDescription: '保持专注。稍后再来查看更多任务！',
-                chairTitle: '暂无内容展示',
-                chairDescription: '去放松一下吧，我们会在这里列出即将到来的待办事项。',
-                broomTitle: '你已完成！',
-                broomDescription: '任务已清理完毕，但请留意更多待办事项。',
-                houseTitle: '全部完成',
-                houseDescription: '这里是你即将处理的待办事项的大本营。',
-                conciergeBotTitle: '暂无内容展示',
-                conciergeBotDescription: '哔哔啵啵，稍后再来查看更多任务！',
-                checkboxTextTitle: '全部完成',
-                checkboxTextDescription: '在这里勾选完成你即将要做的事项。',
-                flashTitle: '你已完成！',
-                flashDescription: '我们会在这里快速显示你未来的任务。',
-                sunglassesTitle: '暂无内容展示',
-                sunglassesDescription: '是时候放松一下了，但请留意接下来的动态！',
-                f1FlagsTitle: '全部完成',
-                f1FlagsDescription: '你已完成所有未完成的待办事项。',
-            },
-        },
-        upcomingTravel: '即将出行',
-        upcomingTravelSection: {
-            flightTo: ({destination}: {destination: string}) => `飞往 ${destination} 的航班`,
-            trainTo: ({destination}: {destination: string}) => `前往 ${destination} 的火车`,
-            hotelIn: ({destination}: {destination: string}) => `${destination}的酒店`,
-            carRentalIn: ({destination}: {destination: string}) => `在 ${destination} 租车`,
-            inOneWeek: '1 周后',
-            inDays: () => ({one: '1 天后', other: (count: number) => `在 ${count} 天后`}),
-            today: '今天',
-        },
-        freeTrialSection: {
-            title: ({days}: {days: number}) => `免费试用：剩余 ${days} ${days === 1 ? '天' : '天'} 天！`,
-            offer50Body: '首年可享受五折优惠',
-            offer25Body: '首年可享 75 折优惠',
-            addCardBody: '添加付款卡',
-            ctaClaim: '报销申请',
-            ctaAdd: '添加卡片',
-            timeRemaining: ({formattedTime}: {formattedTime: string}) => `剩余时间：${formattedTime}`,
-            timeRemainingDays: () => ({
-                one: '剩余时间：1天',
-                other: (pluralCount: number) => `剩余时间：${pluralCount}天`,
-            }),
-        },
-        gettingStartedSection: {
-            title: '入门',
-            createWorkspace: '创建工作区',
-            connectAccounting: ({integrationName}: {integrationName: string}) => `连接到 ${integrationName}`,
-            connectAccountingDefault: '连接会计系统',
-            customizeCategories: '自定义会计类别',
-            linkCompanyCards: '关联公司卡',
-            setupRules: '设置消费规则',
-            inviteAccountant: '邀请你的会计',
+                nicelyDone: '做得好',
+                keepAnEyeOut: '留意接下来会发生的事情！',
+                allCaughtUp: '全部处理完毕',
+                upcomingTodos: '即将到来的待办事项会显示在这里。',
+            },
         },
-        yourSpend: {title: '您的支出', awaitingApproval: '等待审批', repaidLast30Days: '过去30天内已偿还', recentTransactions: ({lastFour}: {lastFour: string}) => `最近交易 • ${lastFour}`},
-        seeMore: ({count}: {count: number}) => `再查看 ${count} 个`,
     },
     allSettingsScreen: {
         subscription: '订阅',
@@ -1047,19 +1026,7 @@ const translations: TranslationDeepObject<typeof en> = {
         singleFieldMultipleColumns: (fieldName: string) => `哎呀！你已将单个字段（“${fieldName}”）映射到多个列。请检查后重试。`,
         emptyMappedField: (fieldName: string) => `哎呀！字段（“${fieldName}”）包含一个或多个空值。请检查后重试。`,
         importSuccessfulTitle: '导入成功',
-        importCategoriesSuccessfulDescription: ({added, updated}: {added: number; updated: number}) => {
-            if (!added && !updated) {
-                return '尚未添加或更新任何类别。';
-            }
-            if (added && updated) {
-                return `已添加 ${added} 个，${added === 1 ? '类别' : '类别'} 新增；已更新 ${updated} 个，${updated === 1 ? '类别' : '类别'} 更新。`;
-            }
-            if (added) {
-                return added === 1 ? '已添加 1 个类别。' : `已添加 ${added} 个类别。`;
-            }
-            return updated === 1 ? '1 个类别已更新。' : `已更新 ${updated} 个类别。`;
-        },
-        importCompanyCardTransactionsSuccessfulDescription: ({transactions}: {transactions: number}) => (transactions > 1 ? `已添加 ${transactions} 笔交易。` : '已添加 1 笔交易。'),
+        importCategoriesSuccessfulDescription: ({categories}: {categories: number}) => (categories > 1 ? `已添加 ${categories} 个类别。` : '已添加 1 个类别。'),
         importMembersSuccessfulDescription: ({added, updated}: {added: number; updated: number}) => {
             if (!added && !updated) {
                 return '尚未添加或更新任何成员。';
@@ -1088,7 +1055,6 @@ const translations: TranslationDeepObject<typeof en> = {
             one: `请确认以下新工作区成员的详细信息，该成员将作为此次上传的一部分被添加。现有成员不会收到任何角色更新或邀请消息。`,
             other: (count: number) => `请确认以下有关将通过本次上传添加的 ${count} 位新工作区成员的详细信息。现有成员将不会收到任何角色更新或邀请消息。`,
         }),
-        importCompanyCardTransactionsPendingMessage: '新卡片和交易可能需要一些时间才会显示，请耐心等待。',
     },
     receipt: {
         upload: '上传收据',
@@ -1120,9 +1086,7 @@ const translations: TranslationDeepObject<typeof en> = {
         deleteReceipt: '删除收据',
         deleteConfirmation: '确定要删除这张收据吗？',
         addReceipt: '添加收据',
-        addAdditionalReceipt: '添加额外收据',
         scanFailed: '无法扫描此收据，因为缺少商家、日期或金额。',
-        crop: '裁剪',
         addAReceipt: {
             phrase1: '添加收据',
             phrase2: '或将文件拖放到此处',
@@ -1142,7 +1106,6 @@ const translations: TranslationDeepObject<typeof en> = {
         noLongerHaveReportAccess: '您已无法访问之前的快捷操作目标。请在下方选择一个新的目标。',
         updateDestination: '更新目的地',
         createReport: '创建报表',
-        createTimeExpense: '创建工时报销',
     },
     iou: {
         amount: '金额',
@@ -1162,18 +1125,18 @@ const translations: TranslationDeepObject<typeof en> = {
         split: '拆分',
         splitExpense: '拆分报销',
         splitDates: '拆分日期',
-        splitDateRange: (startDate: string, endDate: string, count: number) => `${startDate} 至 ${endDate}（${count} 天）`,
-        splitExpenseSubtitle: (amount: string, merchant: string) => `来自 ${merchant} 的 ${amount}`,
+        splitDateRange: ({startDate, endDate, count}: SplitDateRangeParams) => `${startDate} 至 ${endDate}（${count} 天）`,
+        splitExpenseSubtitle: ({amount, merchant}: SplitExpenseSubtitleParams) => `来自 ${merchant} 的 ${amount}`,
         splitByPercentage: '按百分比分摊',
         splitByDate: '按日期拆分',
         addSplit: '添加拆分',
         makeSplitsEven: '平均拆分',
         editSplits: '编辑分摊',
-        totalAmountGreaterThanOriginal: (amount: string) => `总金额比原始报销多出 ${amount}。`,
-        totalAmountLessThanOriginal: (amount: string) => `总金额比原始报销少 ${amount}。`,
+        totalAmountGreaterThanOriginal: ({amount}: TotalAmountGreaterOrLessThanOriginalParams) => `总金额比原始报销多出 ${amount}。`,
+        totalAmountLessThanOriginal: ({amount}: TotalAmountGreaterOrLessThanOriginalParams) => `总金额比原始报销少 ${amount}。`,
         splitExpenseZeroAmount: '请在继续之前输入有效金额。',
         splitExpenseOneMoreSplit: '尚未添加拆分。请至少添加一项以保存。',
-        splitExpenseEditTitle: (amount: string, merchant: string) => `编辑 ${merchant} 的 ${amount}`,
+        splitExpenseEditTitle: ({amount, merchant}: SplitExpenseEditTitleParams) => `编辑 ${merchant} 的 ${amount}`,
         removeSplit: '移除拆分',
         splitExpenseCannotBeEditedModalTitle: '此报销无法编辑',
         splitExpenseCannotBeEditedModalDescription: '已批准或已支付的报销无法编辑',
@@ -1204,12 +1167,9 @@ const translations: TranslationDeepObject<typeof en> = {
         deleteReceipt: '删除收据',
         findExpense: '查找报销',
         deletedTransaction: (amount: string, merchant: string) => `已删除一笔报销（${merchant} 的 ${amount}）`,
-        movedFromReport: (reportName: string) => `已从${reportName}中移出一笔费用`,
-        movedFromReportNoName: '移动了一笔报销',
-        movedTransactionTo: (reportUrl: string, reportName: string) => `已将此报销移动到 <a href="${reportUrl}">${reportName}</a>`,
-        movedTransactionToAnotherReport: '已将此报销移动到另一份报表',
-        movedTransactionFrom: (reportUrl: string, reportName: string) => `已将此报销从 <a href="${reportUrl}">${reportName}</a> 中移出`,
-        movedTransactionFromAnotherReport: '已将此报销从另一份报表中移出',
+        movedFromReport: (reportName: string) => `已移动一笔报销${reportName ? `来自${reportName}` : ''}`,
+        movedTransactionTo: (reportUrl: string, reportName?: string) => `已移动此报销${reportName ? `到 <a href="${reportUrl}">${reportName}</a>` : ''}`,
+        movedTransactionFrom: (reportUrl: string, reportName?: string) => `已移动此报销${reportName ? `来自 <a href="${reportUrl}">${reportName}</a>` : ''}`,
         unreportedTransaction: (reportUrl: string) => `已将此报销移动到你的<a href="${reportUrl}">个人空间</a>`,
         movedAction: (shouldHideMovedReportUrl: boolean, movedReportUrl: string, newParentReportUrl: string, toPolicyName: string) => {
             if (shouldHideMovedReportUrl) {
@@ -1221,10 +1181,7 @@ const translations: TranslationDeepObject<typeof en> = {
         pendingMatch: '待匹配',
         pendingMatchWithCreditCardDescription: '收据正在等待与卡片交易匹配。将其标记为现金以取消。',
         markAsCash: '标记为现金',
-        pendingMatchSubmitTitle: '提交报告',
-        pendingMatchSubmitDescription: '部分费用正在等待与信用卡交易匹配。您要将它们标记为现金吗？',
         routePending: '路由处理中…',
-        automaticallyEnterExpenseDetails: 'Concierge 会帮你填写详细信息。',
         receiptScanning: () => ({
             one: '正在扫描收据…',
             other: '正在扫描收据…',
@@ -1248,7 +1205,7 @@ const translations: TranslationDeepObject<typeof en> = {
         receiptStatusTitle: '正在扫描…',
         receiptStatusText: '扫描期间只有你自己能看到这张收据。稍后再来查看，或立即输入详细信息。',
         receiptScanningFailed: '收据扫描失败。请手动输入详细信息。',
-        allTransactionsPendingNextStep: '所有交易都在待处理状态。在几天后这些交易入账之前，你无法提交此报表。',
+        transactionPendingDescription: '交易待处理。入账可能需要几天时间。',
         companyInfo: '公司信息',
         companyInfoDescription: '在您发送第一张发票之前，我们还需要一些详细信息。',
         yourCompanyName: '您的公司名称',
@@ -1283,18 +1240,20 @@ const translations: TranslationDeepObject<typeof en> = {
         settledElsewhere: '在其他地方支付',
         individual: '个人',
         business: '商务',
-        settlePersonal: (formattedAmount?: string) => (formattedAmount ? `以个人身份支付 ${formattedAmount}` : `使用个人账户付款`),
-        settleWallet: (formattedAmount?: string) => (formattedAmount ? `用钱包支付 ${formattedAmount}` : `使用钱包支付`),
-        settlePayment: (formattedAmount: string) => `支付 ${formattedAmount}`,
-        settleBusiness: (formattedAmount?: string) => (formattedAmount ? `以企业身份支付 ${formattedAmount}` : `使用公司账户付款`),
-        payElsewhere: (formattedAmount?: string) => (formattedAmount ? `将 ${formattedAmount} 标记为已支付` : `标记为已支付`),
-        confirmPaymentReceivedModalTitle: '确认已收到付款',
-        receivedPayment: '已收到付款',
-        receivedPaymentConfirmation: '仅当您已在 Expensify 之外收到付款时才继续。',
-        confirmReceivedPayment: '是的，我已收到付款。',
+        settleExpensify: ({formattedAmount}: SettleExpensifyCardParams) => (formattedAmount ? `使用 Expensify 支付 ${formattedAmount}` : `使用 Expensify 付款`),
+        settlePersonal: ({formattedAmount}: SettleExpensifyCardParams) => (formattedAmount ? `以个人身份支付 ${formattedAmount}` : `使用个人账户付款`),
+        settleWallet: ({formattedAmount}: SettleExpensifyCardParams) => (formattedAmount ? `用钱包支付 ${formattedAmount}` : `使用钱包支付`),
+        settlePayment: ({formattedAmount}: SettleExpensifyCardParams) => `支付 ${formattedAmount}`,
+        settleBusiness: ({formattedAmount}: SettleExpensifyCardParams) => (formattedAmount ? `以企业身份支付 ${formattedAmount}` : `使用公司账户付款`),
+        payElsewhere: ({formattedAmount}: SettleExpensifyCardParams) => (formattedAmount ? `将 ${formattedAmount} 标记为已支付` : `标记为已支付`),
         settleInvoicePersonal: (amount?: string, last4Digits?: string) => (amount ? `使用个人账户 ${last4Digits} 支付了 ${amount}` : `使用个人账户支付`),
         settleInvoiceBusiness: (amount?: string, last4Digits?: string) => (amount ? `已使用商务账户 ${last4Digits} 支付 ${amount}` : `使用公司账户支付`),
-        payWithPolicy: (policyName: string, formattedAmount?: string) => (formattedAmount ? `通过 ${policyName} 支付 ${formattedAmount}` : `通过 ${policyName} 支付`),
+        payWithPolicy: ({
+            formattedAmount,
+            policyName,
+        }: SettleExpensifyCardParams & {
+            policyName: string;
+        }) => (formattedAmount ? `通过 ${policyName} 支付 ${formattedAmount}` : `通过 ${policyName} 支付`),
         businessBankAccount: (amount?: string, last4Digits?: string) => (amount ? `使用银行账户尾号为 ${last4Digits} 支付了 ${amount}` : `通过银行账户 ${last4Digits} 支付`),
         automaticallyPaidWithBusinessBankAccount: (amount?: string, last4Digits?: string) =>
             `已通过<a href="${CONST.CONFIGURE_EXPENSE_REPORT_RULES_HELP_URL}">工作区规则</a>使用尾号为 ${last4Digits} 的银行账户支付了 ${amount ? `${amount} ` : ''}`,
@@ -1303,16 +1262,16 @@ const translations: TranslationDeepObject<typeof en> = {
         nextStep: '后续步骤',
         finished: '已完成',
         flip: '翻转',
-        sendInvoice: (amount: string) => `发送 ${amount} 发票`,
+        sendInvoice: ({amount}: RequestAmountParams) => `发送 ${amount} 发票`,
         expenseAmount: (formattedAmount: string, comment?: string) => `${formattedAmount}${comment ? `用于 ${comment}` : ''}`,
-        submitted: (memo?: string) => `已提交${memo ? `，备注为 ${memo}` : ''}`,
+        submitted: ({memo}: SubmittedWithMemoParams) => `已提交${memo ? `，备注为 ${memo}` : ''}`,
         automaticallySubmitted: `通过<a href="${CONST.SELECT_WORKFLOWS_HELP_URL}">延迟提交</a>提交`,
         queuedToSubmitViaDEW: '已排队，待通过自定义审批流程提交',
         queuedToApproveViaDEW: '已排队，等待通过自定义审批流程批准',
         trackedAmount: (formattedAmount: string, comment?: string) => `跟踪 ${formattedAmount}${comment ? `用于 ${comment}` : ''}`,
-        splitAmount: (amount: string) => `拆分 ${amount}`,
-        didSplitAmount: (formattedAmount: string, comment?: string) => `拆分 ${formattedAmount}${comment ? `用于 ${comment}` : ''}`,
-        yourSplit: (amount: string) => `您分摊的${amount}`,
+        splitAmount: ({amount}: SplitAmountParams) => `拆分 ${amount}`,
+        didSplitAmount: (formattedAmount: string, comment: string) => `拆分 ${formattedAmount}${comment ? `用于 ${comment}` : ''}`,
+        yourSplit: ({amount}: UserSplitParams) => `您分摊的${amount}`,
         payerOwesAmount: (amount: number | string, payer: string, comment?: string) => `${payer} 欠款 ${amount}${comment ? `用于 ${comment}` : ''}`,
         payerOwes: (payer: string) => `${payer} 应付：`,
         payerPaidAmount: (amount: number | string, payer?: string) => `${payer ? `${payer} ` : ''}已支付 ${amount}`,
@@ -1328,68 +1287,30 @@ const translations: TranslationDeepObject<typeof en> = {
         approvedMessage: `已批准`,
         unapproved: `未批准`,
         automaticallyForwarded: `通过<a href="${CONST.CONFIGURE_EXPENSE_REPORT_RULES_HELP_URL}">工作区规则</a>批准`,
-        forwarded: (memo?: string) => `已批准${memo ? `，备注为 ${memo}` : ''}`,
-        rejectedThisReport: '已拒绝',
-        waitingOnBankAccount: (submitterDisplayName: string) => `已开始付款，但正在等待${submitterDisplayName}添加银行账户。`,
+        forwarded: `已批准`,
+        rejectedThisReport: '已拒绝此报表',
+        waitingOnBankAccount: ({submitterDisplayName}: WaitingOnBankAccountParams) => `已开始付款，但正在等待${submitterDisplayName}添加银行账户。`,
         adminCanceledRequest: '已取消付款',
         canceledRequest: (amount: string, submitterDisplayName: string) => `已取消金额为 ${amount} 的付款，因为 ${submitterDisplayName} 未在 30 天内启用其 Expensify 钱包`,
-        settledAfterAddedBankAccount: (submitterDisplayName: string, amount: string) => `${submitterDisplayName} 已添加了一个银行账户。已完成 ${amount} 付款。`,
+        settledAfterAddedBankAccount: ({submitterDisplayName, amount}: SettledAfterAddedBankAccountParams) => `${submitterDisplayName} 已添加了一个银行账户。已完成 ${amount} 付款。`,
         paidElsewhere: ({payer, comment}: PaidElsewhereParams = {}) => `${payer ? `${payer} ` : ''}标记为已支付${comment ? `，内容为“${comment}”` : ''}`,
         paidWithExpensify: (payer?: string) => `${payer ? `${payer} ` : ''}用钱包支付`,
         automaticallyPaidWithExpensify: (payer?: string) => `${payer ? `${payer} ` : ''}已通过<a href="${CONST.CONFIGURE_EXPENSE_REPORT_RULES_HELP_URL}">工作区规则</a>使用 Expensify 支付`,
-        reimbursedThisReport: '已报销此报表',
-        paidThisBill: '已支付此账单',
-        reimbursedOnBehalfOf: (actor: string) => `代表 ${actor}`,
-        reimbursedFromBankAccount: (debitBankAccount: string) => `从尾号为 ${debitBankAccount} 的银行账户`,
-        reimbursedSubmitterAddedBankAccount: (submitter: string) => `${submitter} 已添加银行账户，报告已解除挂起。已发起报销`,
-        reimbursedWithFastACH: ({
-            isCurrentUser,
-            submitterLogin,
-            creditBankAccount,
-            expectedDate,
-        }: {
-            isCurrentUser: boolean;
-            submitterLogin: string;
-            creditBankAccount: string;
-            expectedDate: string;
-        }) =>
-            isCurrentUser
-                ? `. 款项正在汇往您的${creditBankAccount ? `尾号为 ${creditBankAccount} 的银行账户` : '账户'}。预计将在 ${expectedDate} 前完成报销。`
-                : `。款项正在汇往 ${submitterLogin} 的${creditBankAccount ? `尾号为 ${creditBankAccount} 的银行账户` : '账户'}。预计于 ${expectedDate} 完成报销。`,
-        reimbursedWithCheck: '通过支票。',
-        reimbursedWithStripeConnect: ({
-            isCurrentUser,
-            submitterLogin,
-            creditBankAccount,
-            isCard,
-        }: {
-            isCurrentUser: boolean;
-            submitterLogin: string;
-            creditBankAccount: string;
-            isCard: boolean;
-        }) => {
-            const paymentMethod = isCard ? '卡' : '银行账户';
-            return isCurrentUser
-                ? `. 款项正在汇往您的${creditBankAccount ? `尾号为 ${creditBankAccount} 的银行账户` : '账户'}（通过 ${paymentMethod} 支付）。这可能需要最多 10 个工作日。`
-                : `. 资金正在汇往 ${submitterLogin} 的 ${creditBankAccount ? `尾号为 ${creditBankAccount} 的银行账户` : '账户'}（通过 ${paymentMethod} 支付）。这可能需要最多 10 个工作日。`;
-        },
-        reimbursedWithACH: ({creditBankAccount, expectedDate}: {creditBankAccount?: string; expectedDate?: string}) =>
-            `使用直接存款（ACH）${creditBankAccount ? `至尾号为 ${creditBankAccount} 的银行账户。` : '. '}${expectedDate ? `预计将在 ${expectedDate} 前完成报销。` : '这通常需要 4–5 个工作日。'}`,
         noReimbursableExpenses: '此报表的金额无效',
         pendingConversionMessage: '当你重新联网时，总金额会更新',
         changedTheExpense: '更改了报销单',
-        setTheRequest: (valueName: string, newValueToDisplay: string) => `将 ${valueName} 更改为 ${newValueToDisplay}`,
-        setTheDistanceMerchant: (translatedChangedField: string, newMerchant: string, newAmountToDisplay: string) =>
+        setTheRequest: ({valueName, newValueToDisplay}: SetTheRequestParams) => `将 ${valueName} 更改为 ${newValueToDisplay}`,
+        setTheDistanceMerchant: ({translatedChangedField, newMerchant, newAmountToDisplay}: SetTheDistanceMerchantParams) =>
             `将 ${translatedChangedField} 设置为 ${newMerchant}，这会将金额设置为 ${newAmountToDisplay}`,
         removedTheRequest: (valueName: string, oldValueToDisplay: string) => `${valueName}（之前为 ${oldValueToDisplay}）`,
-        updatedTheRequest: (valueName: string, newValueToDisplay: string, oldValueToDisplay: string) => `将${valueName}更改为${newValueToDisplay}（原为${oldValueToDisplay}）`,
-        updatedTheDistanceMerchant: (translatedChangedField: string, newMerchant: string, oldMerchant: string, newAmountToDisplay: string, oldAmountToDisplay: string) =>
+        updatedTheRequest: ({valueName, newValueToDisplay, oldValueToDisplay}: UpdatedTheRequestParams) => `将${valueName}更改为${newValueToDisplay}（原为${oldValueToDisplay}）`,
+        updatedTheDistanceMerchant: ({translatedChangedField, newMerchant, oldMerchant, newAmountToDisplay, oldAmountToDisplay}: UpdatedTheDistanceMerchantParams) =>
             `将 ${translatedChangedField} 更改为 ${newMerchant}（之前为 ${oldMerchant}），从而将金额更新为 ${newAmountToDisplay}（之前为 ${oldAmountToDisplay}）`,
         basedOnAI: '基于过去的活动',
         basedOnMCC: ({rulesLink}: {rulesLink: string}) => (rulesLink ? `基于<a href="${rulesLink}">工作区规则</a>` : '基于工作区规则'),
-        threadExpenseReportName: (formattedAmount: string, comment?: string) => `${formattedAmount} ${comment ? `用于 ${comment}` : '报销'}`,
+        threadExpenseReportName: ({formattedAmount, comment}: ThreadRequestReportNameParams) => `${formattedAmount} ${comment ? `用于 ${comment}` : '报销'}`,
         invoiceReportName: ({linkedReportID}: OriginalMessage<typeof CONST.REPORT.ACTIONS.TYPE.REPORT_PREVIEW>) => `发票报告 #${linkedReportID}`,
-        threadPaySomeoneReportName: (formattedAmount: string, comment?: string) => `已发送 ${formattedAmount}${comment ? `用于 ${comment}` : ''}`,
+        threadPaySomeoneReportName: ({formattedAmount, comment}: ThreadSentMoneyReportNameParams) => `已发送 ${formattedAmount}${comment ? `用于 ${comment}` : ''}`,
         movedFromPersonalSpace: ({workspaceName, reportName}: MovedFromPersonalSpaceParams) => `已将报销从个人空间移动到 ${workspaceName ?? `与 ${reportName} 聊天`}`,
         movedToPersonalSpace: '已将报销移动到个人空间',
         error: {
@@ -1397,14 +1318,10 @@ const translations: TranslationDeepObject<typeof en> = {
             invalidTagLength: '标签名称超过了 255 个字符。请缩短它或选择其他标签。',
             invalidAmount: '请在继续之前输入有效金额',
             invalidDistance: '请在继续之前输入有效的距离',
-            invalidReadings: '请在继续之前输入起始读数和结束读数',
+            invalidReadings: '请输入起始读数和结束读数',
             negativeDistanceNotAllowed: '结束读数必须大于开始读数',
-            distanceAmountTooLarge: '总金额过大。请减少距离或降低费率。',
-            distanceAmountTooLargeReduceDistance: '总金额过大。请减少距离。',
-            distanceAmountTooLargeReduceRate: '总金额过大。请降低费率。',
-            odometerReadingTooLarge: (formattedMax: string) => `里程表读数不能超过${formattedMax}。`,
             invalidIntegerAmount: '请在继续之前输入一个整数美元金额',
-            invalidTaxAmount: (amount: string) => `最高税额为 ${amount}`,
+            invalidTaxAmount: ({amount}: RequestAmountParams) => `最高税额为 ${amount}`,
             invalidSplit: '拆分金额之和必须等于总金额',
             invalidSplitParticipants: '请为至少两位参与者输入大于零的金额',
             invalidSplitYourself: '请输入一个非零金额用于分摊',
@@ -1417,8 +1334,6 @@ const translations: TranslationDeepObject<typeof en> = {
             receiptDeleteFailureError: '删除此收据时发生意外错误。请稍后再试。',
             receiptFailureMessage: '<rbr>上传您的收据时出错。请<a href="download">保存收据</a>并在稍后<a href="retry">重试</a>。</rbr>',
             receiptFailureMessageShort: '上传您的收据时出错。',
-            receiptUploadFailedMessage: '收据上传失败。保存收据，或删除该支出并失去它。',
-            saveReceipt: '保存收据',
             genericDeleteFailureMessage: '删除此报销时发生意外错误。请稍后重试。',
             genericEditFailureMessage: '编辑此报销时发生意外错误。请稍后再试。',
             genericSmartscanFailureMessage: '交易缺少字段',
@@ -1435,14 +1350,10 @@ const translations: TranslationDeepObject<typeof en> = {
             endDateSameAsStartDate: '结束日期不能与开始日期相同',
             manySplitsProvided: `允许的最大拆分数为 ${CONST.IOU.SPLITS_LIMIT}。`,
             dateRangeExceedsMaxDays: `日期范围不能超过 ${CONST.IOU.SPLITS_LIMIT} 天。`,
-            unableToSubmitReport: '无法提交报表',
-            allTransactionsPendingDescription: '您无法提交此报表，因为所有交易都在待处理。它们可能需要几天时间才会入账。',
-            stitchOdometerImagesFailed: '合并里程表图片失败。请稍后重试。',
-            failedToSaveOdometerDraft: '无法保存你的里程表草稿。请重试。',
         },
         dismissReceiptError: '忽略错误',
         dismissReceiptErrorConfirmation: '提醒：关闭此错误将彻底删除你上传的收据。确定要继续吗？',
-        waitingOnEnabledWallet: (submitterDisplayName: string) => `已开始结算。在 ${submitterDisplayName} 启用其钱包之前，付款将被暂挂。`,
+        waitingOnEnabledWallet: ({submitterDisplayName}: WaitingOnBankAccountParams) => `已开始结算。在 ${submitterDisplayName} 启用其钱包之前，付款将被暂挂。`,
         enableWallet: '启用钱包',
         hold: '暂挂',
         unhold: '解除保留',
@@ -1454,20 +1365,16 @@ const translations: TranslationDeepObject<typeof en> = {
         heldExpense: '已搁置此报销费用',
         unheldExpense: '已取消冻结此报销费用',
         moveUnreportedExpense: '移动未报销费用',
-        addExistingExpense: '添加现有费用',
-        selectExistingExpense: '请选择至少一笔报销添加到报表中。',
-        emptyStateExistingExpenseTitle: '没有现有费用',
-        emptyStateExistingExpenseSubtitle: '看起来你没有任何现有的费用。请在下方创建一笔。',
-        addExistingExpenseConfirm: '添加到报表',
+        addUnreportedExpense: '添加未报销费用',
+        selectUnreportedExpense: '请选择至少一笔报销添加到报表中。',
+        emptyStateUnreportedExpenseTitle: '没有未报销的报销单',
+        emptyStateUnreportedExpenseSubtitle: '看起来你没有任何未报销的费用。请在下方创建一笔。',
+        addUnreportedExpenseConfirm: '添加到报表',
         newReport: '新报表',
         explainHold: () => ({
             one: '请解释你为何暂时保留这笔报销。',
             other: '请说明你为何保留这些报销。',
         }),
-        explainHoldApprover: () => ({
-            one: '请说明在批准这笔报销之前你需要什么。',
-            other: '请说明在批准这些报销之前你需要什么。',
-        }),
         retracted: '已撤回',
         retract: '撤回',
         reopened: '已重新打开',
@@ -1479,12 +1386,9 @@ const translations: TranslationDeepObject<typeof en> = {
         expenseOnHold: '此报销已被搁置。请查看评论以了解下一步操作。',
         expensesOnHold: '所有报销都已被搁置。请查看评论以了解下一步操作。',
         expenseDuplicate: '此报销与另一笔报销的明细相似。请查看可能重复的报销后再继续。',
-        someDuplicatesArePaid: '其中一些重复项已被批准或支付。',
-        reviewDuplicates: '审核重复项',
+        someDuplicatesArePaid: '其中有些重复项已经被批准或支付。',
+        reviewDuplicates: '查看重复项',
         keepAll: '全部保留',
-        keepSelected: '保留所选项',
-        noDuplicatesTitle: '全部完成！',
-        noDuplicatesDescription: '这里没有需要审核的重复交易。',
         confirmApprove: '确认批准金额',
         confirmApprovalAmount: '仅批准合规报销，或批准整份报销报告。',
         confirmApprovalAllHoldAmount: () => ({
@@ -1518,7 +1422,8 @@ const translations: TranslationDeepObject<typeof en> = {
         unapprove: '取消批准',
         unapproveReport: '取消批准报销单',
         headsUp: '注意！',
-        unapproveWithIntegrationWarning: (accountingIntegration: string) => `此报表已导出至 ${accountingIntegration}。更改它可能会导致数据不一致。确定要取消批准此报表吗？`,
+        unapproveWithIntegrationWarning: ({accountingIntegration}: UnapproveWithIntegrationWarningParams) =>
+            `此报表已导出至 ${accountingIntegration}。更改它可能会导致数据不一致。确定要取消批准此报表吗？`,
         reimbursable: '可报销',
         nonReimbursable: '不可报销',
         bookingPending: '此预订待处理',
@@ -1526,7 +1431,6 @@ const translations: TranslationDeepObject<typeof en> = {
         bookingArchived: '此预订已归档',
         bookingArchivedDescription: '此预订已归档，因为行程日期已过。如有需要，请为最终金额添加一笔报销。',
         attendees: '参与者',
-        totalPerAttendee: '每位参与者',
         whoIsYourAccountant: '你的会计是谁？',
         paymentComplete: '付款完成',
         time: '时间',
@@ -1553,7 +1457,7 @@ const translations: TranslationDeepObject<typeof en> = {
         }),
         dates: '日期',
         rates: '费率',
-        submitsTo: (name: string) => `提交给 ${name}`,
+        submitsTo: ({name}: SubmitsToParams) => `提交给 ${name}`,
         reject: {
             educationalTitle: '你应该暂缓还是拒绝？',
             educationalText: '如果你还没准备好批准或支付一笔报销，你可以暂缓处理或拒绝它。',
@@ -1562,7 +1466,7 @@ const translations: TranslationDeepObject<typeof en> = {
             heldExpenseLeftBehindTitle: '当你批准整份报销报告时，已搁置的报销会被保留在报告之外。',
             rejectExpenseTitle: '拒绝你不打算批准或报销的报销单。',
             reasonPageTitle: '拒绝报销',
-            reasonPageDescription: '请说明你为何不会批准这笔报销。',
+            reasonPageDescription: '请说明你拒绝此报销的原因。',
             rejectReason: '拒绝原因',
             markAsResolved: '标记为已解决',
             rejectedStatus: '该报销已被拒绝。请先修复问题并标记为已解决，然后才能提交。',
@@ -1571,25 +1475,13 @@ const translations: TranslationDeepObject<typeof en> = {
                 markedAsResolved: '已将拒绝原因标记为已解决',
             },
         },
-        rejectReport: {
-            title: '拒绝报表',
-            description: '请说明你为何不会批准此报告：',
-            rejectReason: '拒绝原因',
-            selectTarget: '选择要将此报表退回给哪位成员以供审核：',
-            lastApprover: '最后审批人',
-            submitter: '提交人',
-            rejectedReportMessage: '此报告已被拒绝。',
-            rejectedNextStep: '此报表已被拒绝。等待你修复问题并手动重新提交。',
-            selectMemberError: '选择一位成员将此报表退回给 TA。',
-            couldNotReject: '无法拒绝该报表。请重试。',
-        },
-        moveExpenses: '移动到报告',
+        moveExpenses: () => ({one: '移动报销', other: '移动报销费用'}),
         moveExpensesError: '您无法将每日津贴报销移动到其他工作区的报表中，因为不同工作区的每日津贴标准可能不同。',
         changeApprover: {
             title: '更改审批人',
-            header: (workflowSettingLink: string) => `选择一个选项来更改此报表的审批人。（更新你的<a href="${workflowSettingLink}">工作区设置</a>，以将其永久应用于所有报表。）`,
+            header: ({workflowSettingLink}: WorkflowSettingsParam) =>
+                `选择一个选项来更改此报表的审批人。（更新你的<a href="${workflowSettingLink}">工作区设置</a>，以将其永久应用于所有报表。）`,
             changedApproverMessage: (managerID: number) => `已将审批人更改为 <mention-user accountID="${managerID}"/>`,
-            reassignedApproverMessage: (managerID: number) => `已通过工作流更新将审批人重新分配给 <mention-user accountID="${managerID}"/>`,
             actions: {
                 addApprover: '添加审批人',
                 addApproverSubtitle: '向现有工作流程添加额外审批人。',
@@ -1598,12 +1490,10 @@ const translations: TranslationDeepObject<typeof en> = {
             },
             addApprover: {
                 subtitle: '在将此报表提交到其余审批流程之前，请选择一位额外的审批人。',
-                bulkSubtitle: '在我们将这些报表提交给其余审批流程之前，请为其选择一位额外审批人。',
             },
-            bulkSubtitle: '选择一个选项来更改这些报表的审批人。',
         },
         chooseWorkspace: '选择工作区',
-        routedDueToDEW: (to: string, reason?: string) => `报销单已转交给 ${to}${reason ? ` 因为 ${reason}` : ''}`,
+        routedDueToDEW: ({to}: RoutedDueToDEWParams) => `报表因自定义审批流程被转交给 ${to}`,
         timeTracking: {
             hoursAt: (hours: number, rate: string) => `${hours} ${hours === 1 ? '小时' : '小时'}，按 ${rate} / 小时`,
             hrs: '小时',
@@ -1611,29 +1501,34 @@ const translations: TranslationDeepObject<typeof en> = {
             ratePreview: (rate: string) => `${rate} / 小时`,
             amountTooLargeError: '总金额过大。请减少工时或降低费率。',
         },
-        correctRateError: '修复费率错误后请重试。',
-        AskToExplain: `。<a href="${CONST.CONCIERGE_EXPLAIN_LINK_PATH}">说明<sparkles-icon/></a>`,
-        duplicateNonDefaultWorkspacePerDiemError: '您无法在不同工作区之间复制每日津贴报销，因为各工作区的补贴标准可能不同。',
-        rulesModifiedFields: {
-            reimbursable: (value: boolean) => (value ? '将该报销单标记为“可报销”' : '将该报销单标记为“不可报销”'),
-            billable: (value: boolean) => (value ? '将该报销标记为“可计费”' : '将该报销标记为“不可计费”'),
-            tax: (value: string, isFirst: boolean) => (isFirst ? `将税率设置为“${value}”` : `税率为“${value}”`),
-            reportName: (value: string) => `已将此报销移至报销单“${value}”`,
-            common: (key: keyof PolicyRulesModifiedFields | keyof PersonalRulesModifiedFields, value: string, isFirst: boolean) => {
-                const field = translations.common[key].toLowerCase();
-                return isFirst ? `将 ${field} 设置为“${value}”` : `${field} 至 “${value}”`;
-            },
-            formatPersonalRules: (fragments: string, route: string) => `${fragments} 通过 <a href="${route}">个人报销规则</a>`,
-            formatPolicyRules: (fragments: string, route: string) => `${fragments} 通过 <a href="${route}">工作区规则</a>`,
-        },
-        failedToAutoSubmitViaDEW: (reason: string) => `通过<a href="${CONST.SELECT_WORKFLOWS_HELP_URL}">延迟提交</a>提交报表失败。${reason}`,
-        failedToSubmitViaDEW: (reason: string) => `报表提交失败。${reason}`,
-        failedToAutoApproveViaDEW: (reason: string) => `未能通过<a href="${CONST.CONFIGURE_EXPENSE_REPORT_RULES_HELP_URL}">工作区规则</a>批准。${reason}`,
-        failedToApproveViaDEW: (reason: string) => `批准失败。${reason}`,
-        cannotDuplicateDistanceExpense: '你无法在不同工作区之间复制里程报销，因为各个工作区的费率可能不同。',
-        taxDisabledAlert: {title: '税费已禁用', prompt: '请在工作区中启用税费跟踪，以便编辑此报销的详细信息或从该报销中删除税费。', confirmText: '删除税费'},
-        bulkDuplicateLimit: `您一次最多可以复制 ${CONST.SEARCH.BULK_DUPLICATE_LIMIT} 笔报销。请减少选择的报销数量后重试。`,
-        deleted: '已删除',
+        correctDistanceRateError: '修复距离费率错误后请重试。',
+        AskToExplain: `。<a href="${CONST.CONCIERGE_EXPLAIN_LINK_PATH}"><strong>说明</strong></a> ✨`,
+        policyRulesModifiedFields: (policyRulesModifiedFields: PolicyRulesModifiedFields, policyRulesRoute: string, formatList: (list: string[]) => string) => {
+            const entries = ObjectUtils.typedEntries(policyRulesModifiedFields);
+            const fragments = entries.map(([key, value], i) => {
+                const isFirst = i === 0;
+                if (key === 'reimbursable') {
+                    return value ? '已将该报销单标记为“可报销”' : '将该报销单标记为“不可报销”';
+                }
+                if (key === 'billable') {
+                    return value ? '将该报销标记为“可计费”' : '将该报销标记为“不可计费”';
+                }
+                if (key === 'tax') {
+                    const taxEntry = value as PolicyRulesModifiedFields['tax'];
+                    const taxRateName = taxEntry?.field_id_TAX.name ?? '';
+                    if (isFirst) {
+                        return `将税率设置为“${taxRateName}”`;
+                    }
+                    return `税率为“${taxRateName}”`;
+                }
+                const updatedValue = value as string | boolean;
+                if (isFirst) {
+                    return `将 ${translations.common[key].toLowerCase()} 设置为“${updatedValue}”`;
+                }
+                return `${translations.common[key].toLowerCase()} 至 “${updatedValue}”`;
+            });
+            return `${formatList(fragments)} 通过 <a href="${policyRulesRoute}">工作区规则</a>`;
+        },
     },
     transactionMerge: {
         listPage: {
@@ -1706,48 +1601,28 @@ const translations: TranslationDeepObject<typeof en> = {
     },
     nextStep: {
         message: {
-            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_TO_ADD_TRANSACTIONS]: (
-                actor: string,
-                actorType: ValueOf<typeof CONST.NEXT_STEP.ACTOR_TYPE>,
-                _eta?: string,
-                _etaType?: ValueOf<typeof CONST.NEXT_STEP.ETA_TYPE>,
-            ) => {
+            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_TO_ADD_TRANSACTIONS]: ({actor, actorType}: NextStepParams) => {
                 switch (actorType) {
                     case CONST.NEXT_STEP.ACTOR_TYPE.CURRENT_USER:
                         return `正在等待<strong>你</strong>添加报销。`;
                     case CONST.NEXT_STEP.ACTOR_TYPE.OTHER_USER:
-                        return `正在等待<strong>${actor}</strong>添加报销。`;
+                        return `正在等待 <strong>${actor}</strong> 添加报销。`;
                     case CONST.NEXT_STEP.ACTOR_TYPE.UNSPECIFIED_ADMIN:
                         return `正在等待管理员添加报销。`;
                 }
             },
-            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_TO_SUBMIT]: (
-                actor: string,
-                actorType: ValueOf<typeof CONST.NEXT_STEP.ACTOR_TYPE>,
-                _eta?: string,
-                _etaType?: ValueOf<typeof CONST.NEXT_STEP.ETA_TYPE>,
-            ) => {
+            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_TO_SUBMIT]: ({actor, actorType}: NextStepParams) => {
                 switch (actorType) {
                     case CONST.NEXT_STEP.ACTOR_TYPE.CURRENT_USER:
-                        return `正在等待<strong>你</strong>提交报销。`;
+                        return `正在等待<strong>您</strong>提交报销。`;
                     case CONST.NEXT_STEP.ACTOR_TYPE.OTHER_USER:
-                        return `正在等待<strong>${actor}</strong>提交报销。`;
+                        return `正在等待 <strong>${actor}</strong> 提交报销。`;
                     case CONST.NEXT_STEP.ACTOR_TYPE.UNSPECIFIED_ADMIN:
                         return `正在等待管理员提交报销。`;
                 }
             },
-            [CONST.NEXT_STEP.MESSAGE_KEY.NO_FURTHER_ACTION]: (
-                _actor: string,
-                _actorType: ValueOf<typeof CONST.NEXT_STEP.ACTOR_TYPE>,
-                _eta?: string,
-                _etaType?: ValueOf<typeof CONST.NEXT_STEP.ETA_TYPE>,
-            ) => `无需执行其他操作！`,
-            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_FOR_SUBMITTER_ACCOUNT]: (
-                actor: string,
-                actorType: ValueOf<typeof CONST.NEXT_STEP.ACTOR_TYPE>,
-                _eta?: string,
-                _etaType?: ValueOf<typeof CONST.NEXT_STEP.ETA_TYPE>,
-            ) => {
+            [CONST.NEXT_STEP.MESSAGE_KEY.NO_FURTHER_ACTION]: (_: NextStepParams) => `无需进一步操作！`,
+            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_FOR_SUBMITTER_ACCOUNT]: ({actor, actorType}: NextStepParams) => {
                 switch (actorType) {
                     case CONST.NEXT_STEP.ACTOR_TYPE.CURRENT_USER:
                         return `正在等待<strong>你</strong>添加银行账户。`;
@@ -1757,134 +1632,79 @@ const translations: TranslationDeepObject<typeof en> = {
                         return `正在等待管理员添加银行账户。`;
                 }
             },
-            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_FOR_AUTOMATIC_SUBMIT]: (
-                actor: string,
-                actorType: ValueOf<typeof CONST.NEXT_STEP.ACTOR_TYPE>,
-                eta?: string,
-                etaType?: ValueOf<typeof CONST.NEXT_STEP.ETA_TYPE>,
-            ) => {
+            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_FOR_AUTOMATIC_SUBMIT]: ({actor, actorType, eta, etaType}: NextStepParams) => {
                 let formattedETA = '';
                 if (eta) {
-                    formattedETA = etaType === CONST.NEXT_STEP.ETA_TYPE.DATE_TIME ? `在每个月的 ${eta} 日` : ` ${eta}`;
+                    formattedETA = etaType === CONST.NEXT_STEP.ETA_TYPE.DATE_TIME ? `于 ${eta}` : ` ${eta}`;
                 }
                 switch (actorType) {
                     case CONST.NEXT_STEP.ACTOR_TYPE.CURRENT_USER:
                         return `正在等待<strong>你的</strong>报销费用自动提交${formattedETA}。`;
                     case CONST.NEXT_STEP.ACTOR_TYPE.OTHER_USER:
-                        return `正在等待<strong>${actor}</strong>的报销费用在${formattedETA}自动提交。`;
+                        return `正在等待<strong>${actor}</strong>的费用在${formattedETA}自动提交。`;
                     case CONST.NEXT_STEP.ACTOR_TYPE.UNSPECIFIED_ADMIN:
                         return `正在等待管理员的报销在${formattedETA}自动提交。`;
                 }
             },
-            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_TO_FIX_ISSUES]: (
-                actor: string,
-                actorType: ValueOf<typeof CONST.NEXT_STEP.ACTOR_TYPE>,
-                _eta?: string,
-                _etaType?: ValueOf<typeof CONST.NEXT_STEP.ETA_TYPE>,
-            ) => {
+            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_TO_FIX_ISSUES]: ({actor, actorType}: NextStepParams) => {
                 switch (actorType) {
                     case CONST.NEXT_STEP.ACTOR_TYPE.CURRENT_USER:
                         return `正在等待<strong>你</strong>来解决这些问题。`;
                     case CONST.NEXT_STEP.ACTOR_TYPE.OTHER_USER:
-                        return `正在等待 <strong>${actor}</strong> 解决这些问题。`;
+                        return `正在等待<strong>${actor}</strong>修复这些问题。`;
                     case CONST.NEXT_STEP.ACTOR_TYPE.UNSPECIFIED_ADMIN:
                         return `正在等待管理员修复这些问题。`;
                 }
             },
-            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_TO_APPROVE]: (
-                actor: string,
-                actorType: ValueOf<typeof CONST.NEXT_STEP.ACTOR_TYPE>,
-                _eta?: string,
-                _etaType?: ValueOf<typeof CONST.NEXT_STEP.ETA_TYPE>,
-            ) => {
+            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_TO_APPROVE]: ({actor, actorType}: NextStepParams) => {
                 switch (actorType) {
                     case CONST.NEXT_STEP.ACTOR_TYPE.CURRENT_USER:
-                        return `正在等待<strong>你</strong>审批报销。`;
+                        return `等待<strong>你</strong>批准报销。`;
                     case CONST.NEXT_STEP.ACTOR_TYPE.OTHER_USER:
-                        return `正在等待<strong>${actor}</strong>审批报销。`;
+                        return `正在等待<strong>${actor}</strong>批准报销。`;
                     case CONST.NEXT_STEP.ACTOR_TYPE.UNSPECIFIED_ADMIN:
                         return `正在等待管理员批准报销。`;
                 }
             },
-            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_TO_EXPORT]: (
-                actor: string,
-                actorType: ValueOf<typeof CONST.NEXT_STEP.ACTOR_TYPE>,
-                _eta?: string,
-                _etaType?: ValueOf<typeof CONST.NEXT_STEP.ETA_TYPE>,
-            ) => {
+            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_TO_EXPORT]: ({actor, actorType}: NextStepParams) => {
                 switch (actorType) {
                     case CONST.NEXT_STEP.ACTOR_TYPE.CURRENT_USER:
-                        return `正在等待<strong>你</strong>导出此报表。`;
+                        return `正在等待<strong>你</strong>导出此报告。`;
                     case CONST.NEXT_STEP.ACTOR_TYPE.OTHER_USER:
-                        return `正在等待 <strong>${actor}</strong> 导出此报告。`;
+                        return `正在等待<strong>${actor}</strong>导出此报表。`;
                     case CONST.NEXT_STEP.ACTOR_TYPE.UNSPECIFIED_ADMIN:
-                        return `正在等待管理员导出此报表。`;
+                        return `正在等待管理员导出此报告。`;
                 }
             },
-            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_TO_PAY]: (
-                actor: string,
-                actorType: ValueOf<typeof CONST.NEXT_STEP.ACTOR_TYPE>,
-                _eta?: string,
-                _etaType?: ValueOf<typeof CONST.NEXT_STEP.ETA_TYPE>,
-            ) => {
+            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_TO_PAY]: ({actor, actorType}: NextStepParams) => {
                 switch (actorType) {
                     case CONST.NEXT_STEP.ACTOR_TYPE.CURRENT_USER:
                         return `正在等待<strong>你</strong>报销费用。`;
                     case CONST.NEXT_STEP.ACTOR_TYPE.OTHER_USER:
-                        return `正在等待<strong>${actor}</strong>支付报销费用。`;
+                        return `正在等待<strong>${actor}</strong>报销费用。`;
                     case CONST.NEXT_STEP.ACTOR_TYPE.UNSPECIFIED_ADMIN:
                         return `正在等待管理员报销费用。`;
                 }
             },
-            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_FOR_POLICY_BANK_ACCOUNT]: (
-                actor: string,
-                actorType: ValueOf<typeof CONST.NEXT_STEP.ACTOR_TYPE>,
-                _eta?: string,
-                _etaType?: ValueOf<typeof CONST.NEXT_STEP.ETA_TYPE>,
-            ) => {
+            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_FOR_POLICY_BANK_ACCOUNT]: ({actor, actorType}: NextStepParams) => {
                 switch (actorType) {
                     case CONST.NEXT_STEP.ACTOR_TYPE.CURRENT_USER:
-                        return `正在等待<strong>你</strong>完成设置企业银行账户。`;
+                        return `正在等待<strong>你</strong>完成公司银行账户的设置。`;
                     case CONST.NEXT_STEP.ACTOR_TYPE.OTHER_USER:
-                        return `正在等待<strong>${actor}</strong>完成企业银行账户的设置。`;
+                        return `正在等待 <strong>${actor}</strong> 完成企业银行账户的设置。`;
                     case CONST.NEXT_STEP.ACTOR_TYPE.UNSPECIFIED_ADMIN:
                         return `正在等待管理员完成企业银行账户的设置。`;
                 }
             },
-            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_FOR_PAYMENT]: (
-                _actor: string,
-                _actorType: ValueOf<typeof CONST.NEXT_STEP.ACTOR_TYPE>,
-                eta?: string,
-                etaType?: ValueOf<typeof CONST.NEXT_STEP.ETA_TYPE>,
-            ) => {
+            [CONST.NEXT_STEP.MESSAGE_KEY.WAITING_FOR_PAYMENT]: ({eta, etaType}: NextStepParams) => {
                 let formattedETA = '';
                 if (eta) {
-                    formattedETA = etaType === CONST.NEXT_STEP.ETA_TYPE.DATE_TIME ? `于 ${eta} 前` : ` ${eta}`;
+                    formattedETA = etaType === CONST.NEXT_STEP.ETA_TYPE.DATE_TIME ? `截至 ${eta}` : ` ${eta}`;
                 }
                 return `正在等待付款完成${formattedETA}。`;
             },
-            [CONST.NEXT_STEP.MESSAGE_KEY.SUBMITTING_TO_SELF]: (
-                _actor: string,
-                _actorType: ValueOf<typeof CONST.NEXT_STEP.ACTOR_TYPE>,
-                _eta?: string,
-                _etaType?: ValueOf<typeof CONST.NEXT_STEP.ETA_TYPE>,
-            ) =>
-                `哎呀！看起来你正在将报销单提交给<strong>自己</strong>。根据你的工作区规定，审批自己的报销单是<strong>禁止的</strong>。请将此报销单提交给其他人，或联系管理员更改你提交报销单的审批人。`,
-            [CONST.NEXT_STEP.MESSAGE_KEY.REJECTED_REPORT]: (
-                actor: string,
-                actorType: ValueOf<typeof CONST.NEXT_STEP.ACTOR_TYPE>,
-                _eta?: string,
-                _etaType?: ValueOf<typeof CONST.NEXT_STEP.ETA_TYPE>,
-            ) => {
-                switch (actorType) {
-                    case CONST.NEXT_STEP.ACTOR_TYPE.CURRENT_USER:
-                        return `此报表已被拒绝。正在等待<strong>你</strong>修复问题并手动重新提交。`;
-                    case CONST.NEXT_STEP.ACTOR_TYPE.OTHER_USER:
-                        return `此报表已被拒绝。正在等待<strong>${actor}</strong>修复问题并手动重新提交。`;
-                    case CONST.NEXT_STEP.ACTOR_TYPE.UNSPECIFIED_ADMIN:
-                        return `该报表已被拒绝。正在等待管理员修复问题并手动重新提交。`;
-                }
-            },
+            [CONST.NEXT_STEP.MESSAGE_KEY.SUBMITTING_TO_SELF]: (_: NextStepParams) =>
+                `哎呀！看起来你正在将报告提交给<strong>自己</strong>。你的工作区<strong>禁止</strong>审批自己的报销报告。请将此报销报告提交给其他人，或联系管理员更改你的提交对象。`,
         },
         eta: {
             [CONST.NEXT_STEP.ETA_KEY.SHORTLY]: '很快',
@@ -1910,8 +1730,6 @@ const translations: TranslationDeepObject<typeof en> = {
         offline: '离线',
         syncing: '正在同步',
         profileAvatar: '个人头像',
-        customInstructions: '自定义指令',
-        copilotIntoAccount: 'Copilot 到账户',
         publicSection: {
             title: '公开',
             subtitle: '这些详细信息会显示在你的公开资料中，任何人都可以看到。',
@@ -1920,16 +1738,12 @@ const translations: TranslationDeepObject<typeof en> = {
             title: '私人',
             subtitle: '这些详细信息用于旅行和付款。它们绝不会显示在你的公开资料中。',
         },
-        aiPromptSection: {
-            title: 'AI 提示',
-            subtitle: '编写自定义说明',
-            prompt: '提示',
-            editPrompt: '编辑提示',
-            promptCannotBeEmpty: '提示不能为空',
-            saved: '已保存',
-        },
     },
-    securityPage: {title: '安全', subtitle: '保障您的账户安全。', goToSecurity: '返回安全页面'},
+    securityPage: {
+        title: '安全选项',
+        subtitle: '启用双重身份验证以保护您的账户安全。',
+        goToSecurity: '返回安全页面',
+    },
     shareCodePage: {
         title: '你的代码',
         subtitle: '通过分享你的个人二维码或推荐链接邀请成员加入 Expensify。',
@@ -1966,7 +1780,6 @@ const translations: TranslationDeepObject<typeof en> = {
         },
         newContactMethod: '新联系方式',
         goBackContactMethods: '返回联系方式',
-        yourDefaultContactMethodRestrictedSwitch: '这是你当前的默认联系方式。你的公司已限制移除或更改它。',
     },
     pronouns: {
         coCos: '公司/成本',
@@ -2026,6 +1839,8 @@ const translations: TranslationDeepObject<typeof en> = {
         },
         troubleshoot: {
             clearCacheAndRestart: '清除缓存并重启',
+            viewConsole: '查看调试控制台',
+            debugConsole: '调试控制台',
             description: '<muted-text>使用下方工具来帮助排查 Expensify 使用中的问题。如果遇到任何问题，请<concierge-link>提交错误报告</concierge-link>。</muted-text>',
             confirmResetDescription: '所有未发送的草稿消息都会丢失，但你的其他数据是安全的。',
             resetAndRefresh: '重置并刷新',
@@ -2056,46 +1871,35 @@ const translations: TranslationDeepObject<typeof en> = {
             invalidateWithDelay: '延迟失效',
             leftHandNavCache: '左侧导航缓存',
             clearleftHandNavCache: '清除',
+            recordTroubleshootData: '记录故障排查数据',
             softKillTheApp: '软关闭应用程序',
             kill: '终止',
             sentryDebug: 'Sentry 调试',
-            sentrySendDescription: '向 Sentry 发送数据',
             sentryDebugDescription: '将 Sentry 请求记录到控制台',
             sentryHighlightedSpanOps: '高亮的跨度名称',
             sentryHighlightedSpanOpsPlaceholder: 'ui.interaction.click，navigation，ui.load',
-            showBranchNameInTitle: '在浏览器标题中显示分支名称',
+        },
+        debugConsole: {
+            saveLog: '保存日志',
+            shareLog: '分享日志',
+            enterCommand: '输入命令',
+            execute: '执行',
+            noLogsAvailable: '无可用日志',
+            logSizeTooLarge: (size: number) => `日志大小超过 ${size} MB 限制。请使用“保存日志”来下载日志文件。`,
+            logs: '日志',
+            viewConsole: '查看控制台',
         },
         security: '安全',
         signOut: '退出登录',
         restoreStashed: '恢复暂存的登录',
         signOutConfirmationText: '如果你退出登录，所有离线更改都会丢失。',
         versionLetter: 'v',
-        readTheTermsAndPrivacy: `阅读<a href="${CONST.OLD_DOT_PUBLIC_URLS.TERMS_URL}">服务条款</a>和<a href="${CONST.OLD_DOT_PUBLIC_URLS.PRIVACY_URL}">隐私政策</a>。`,
+        readTheTermsAndPrivacy: `<muted-text-micro>阅读<a href="${CONST.OLD_DOT_PUBLIC_URLS.TERMS_URL}">服务条款</a>和<a href="${CONST.OLD_DOT_PUBLIC_URLS.PRIVACY_URL}">隐私政策</a>。</muted-text-micro>`,
         help: '帮助',
         whatIsNew: '最新动态',
         accountSettings: '账户设置',
         account: '账户',
         general: '常规',
-        helpPage: {
-            title: '帮助与支持',
-            description: '我们全天候为您提供帮助。',
-            helpSite: '帮助网站',
-            helpSiteDescription: '文章、教程等',
-            conciergeChat: 'Concierge',
-            conciergeChatDescription: '你的个人 AI 助理',
-            accountManager: '客户经理',
-            yourAccountManager: '您的客户经理',
-            accountManagerDescription: '提问并获得客户支持',
-            partnerManager: '合作伙伴经理',
-            yourPartnerManager: '您的合作伙伴经理',
-            partnerManagerDescription: '充分发挥合作伙伴关系，提升推荐量',
-            guideDescription: '您的客户经理',
-            approvedPartnerTeamTitle: '认识你的 Approved! 合作团队',
-            approvedPartnerTeamDescription: '一支专注于帮助您的公司成长、更快为客户完成上线，并在您需要时随时提供专家支持的专属团队。',
-            accountExecutive: '客户经理',
-            accountExecutiveDescription: '帮助客户成功完成设置',
-            moreResources: '更多资源',
-        },
     },
     closeAccountPage: {
         closeAccount: '关闭账户',
@@ -2167,12 +1971,10 @@ const translations: TranslationDeepObject<typeof en> = {
         reportSuspiciousActivity: '举报可疑活动',
         lockAccount: '锁定账户',
         unlockAccount: '解锁账户',
-        compromisedDescription: '发现账户有异常？提交报告后将立即锁定账户、阻止新的 Expensify 卡交易，并禁止任何账户更改。',
-        domainAdminsDescription: '针对域管理员：这也会暂停您所有域中的所有 Expensify 卡活动和管理员操作。',
+        compromisedDescription: '发现账户有异常？提交报告后会立即锁定您的账户、阻止新的 Expensify Card 交易，并禁止任何账户更改。',
+        domainAdminsDescription: '针对域管理员：这也会暂停您域中的所有 Expensify Card 活动和管理员操作。',
         areYouSure: '你确定要锁定你的 Expensify 账户吗？',
         onceLocked: '一旦被锁定，您的账户将受到限制，直至提交解锁请求并完成安全审查',
-        unlockTitle: '我们已收到您的请求',
-        unlockDescription: '我们会审核账户以确认解锁是否安全，如有任何问题将通过 Concierge 与您联系。',
     },
     failedToLockAccountPage: {
         failedToLockAccount: '锁定账号失败',
@@ -2185,33 +1987,27 @@ const translations: TranslationDeepObject<typeof en> = {
         chatToConciergeToUnlock: '与 Concierge 聊天以解决安全问题并解锁您的账户。',
         chatWithConcierge: '与 Concierge 聊天',
     },
-    deviceManagementPage: {
-        title: '设备管理',
-        description: '管理所有已使用你的 Expensify 账户登录的设备。<a href="https://help.expensify.com/articles/new-expensify/settings/Manage-Logged-in-Devices">了解详情</a>.',
-        revoke: '撤销',
-        unknownDevice: '未知设备',
-    },
     twoFactorAuth: {
         headerTitle: '双重身份验证',
         twoFactorAuthEnabled: '已启用双重身份验证',
         whatIsTwoFactorAuth: '双重身份验证（2FA）有助于保护您的账户安全。登录时，您需要输入由首选身份验证应用生成的验证码。',
         disableTwoFactorAuth: '禁用双重身份验证',
-        explainProcessToRemove: '要禁用双重身份验证（2FA），请输入来自您身份验证应用的有效验证码。',
-        explainProcessToRemoveWithRecovery: '要禁用双重身份验证（2FA），请输入有效的恢复代码。',
+        explainProcessToRemove: '若要禁用双重身份验证 (2FA)，请在验证器应用中输入有效验证码。',
+        explainProcessToRemoveWithRecovery: '若要停用双重身份验证（2FA），请输入有效的恢复代码。',
         disabled: '已关闭双重身份验证',
         noAuthenticatorApp: '你今后登录 Expensify 时将不再需要验证器应用程序。',
         stepCodes: '恢复代码',
-        keepCodesSafe: '妥善保管这些验证码！',
+        keepCodesSafe: '请妥善保管这些恢复代码！',
         codesLoseAccess: dedent(`
-            如果你无法使用验证器应用且没有这些代码，你将无法登录你的账户。<br><br>
-            <strong>注意</strong>：启用双重验证会将你登出所有其他会话。
+            如果你无法访问身份验证应用并且没有这些代码，你将无法访问你的帐户。
+
+            注意：设置双重身份验证会将你从所有其他活动会话中登出。
         `),
         errorStepCodes: '请在继续之前复制或下载这些代码',
         stepVerify: '验证',
         scanCode: '使用你的 扫描二维码',
         authenticatorApp: '身份验证器应用',
         addKey: '或者将此密钥添加到你的验证器应用：',
-        secretKey: '密钥',
         enterCode: '然后输入您的身份验证器应用生成的六位数字代码。',
         stepSuccess: '已完成',
         enabled: '已启用双重身份验证',
@@ -2227,14 +2023,6 @@ const translations: TranslationDeepObject<typeof en> = {
         twoFactorAuthIsRequiredCompany: '您的公司要求使用双重身份验证。',
         twoFactorAuthCannotDisable: '无法禁用双重验证',
         twoFactorAuthRequired: '您的 Xero 连接需要启用双重身份验证（2FA），且无法将其禁用。',
-        replaceDevice: '更换设备',
-        replaceDeviceTitle: '更换双重验证设备',
-        verifyOldDeviceTitle: '验证旧设备',
-        verifyOldDeviceDescription: '请输入您当前身份验证器应用中的六位数验证码，以确认您仍可访问该应用。',
-        verifyNewDeviceTitle: '设置新设备',
-        verifyNewDeviceDescription: '使用新设备扫描二维码，然后输入代码完成设置。',
-        downloadCodes: '下载代码',
-        copyCodes: '复制代码',
     },
     recoveryCodeForm: {
         error: {
@@ -2322,35 +2110,6 @@ const translations: TranslationDeepObject<typeof en> = {
             password: '请输入您的 Expensify 密码',
         },
     },
-    personalCard: {
-        addPersonalCard: '添加个人卡',
-        addCompanyCard: '添加公司卡',
-        lookingForCompanyCards: '需要添加公司卡？',
-        lookingForCompanyCardsDescription: '从全球 10,000 多家银行添加您自己的卡。',
-        personalCardAdded: '个人卡已添加！',
-        personalCardAddedDescription: '恭喜，我们将开始导入您卡的交易记录。',
-        isPersonalCard: '这是个人卡吗？',
-        thisIsPersonalCard: '这是个人卡',
-        thisIsCompanyCard: '这是公司卡',
-        askAdmin: '请咨询您的管理员',
-        warningDescription: ({isAdmin}: {isAdmin?: boolean}) =>
-            `如果是，那就太好了！但如果是<strong>公司</strong>卡，请 ${isAdmin ? '请从您的工作区分配。' : '请您的管理员从工作区将其分配给您。'}`,
-        bankConnectionError: '银行连接问题',
-        bankConnectionDescription: '请尝试重新添加您的银行卡。否则，您将无法',
-        connectWithPlaid: '通过 Plaid 连接。',
-        fixCard: '修复卡片',
-        brokenConnection: '您的银行卡连接已断开。',
-        conciergeBrokenConnection: ({cardName, connectionLink}: ConciergeBrokenCardConnectionParams) =>
-            connectionLink ? `您的 ${cardName} 卡连接已中断。<a href="${connectionLink}">登录您的网上银行</a>以修复该卡。` : `您的 ${cardName} 卡连接已中断。登录您的网上银行以修复该卡。`,
-        addAdditionalCards: '添加其他卡片',
-        upgradeDescription: '需要添加更多卡片吗？创建工作区以添加其他个人卡片或将公司卡片分配给整个团队。',
-        onlyAvailableOnPlan: ({formattedPrice}: {formattedPrice: string}) => `<muted-text>此功能在 Collect 套餐中可用，每位成员每月费用为 <strong>${formattedPrice}</strong>。</muted-text>`,
-        note: (subscriptionLink: string) => `<muted-text>创建工作区以使用此功能，或<a href="${subscriptionLink}">了解更多关于我们的套餐和定价的信息</a>。</muted-text>`,
-        workspaceCreated: '工作区已创建',
-        newWorkspace: '您已创建工作区！',
-        successMessage: ({subscriptionLink}: {subscriptionLink: string}) =>
-            `<centered-text>您现在可以添加其他卡片了。<a href="${subscriptionLink}">查看您的订阅</a>了解更多详情。</centered-text>`,
-    },
     walletPage: {
         balance: '余额',
         paymentMethodsTitle: '付款方式',
@@ -2377,9 +2136,8 @@ const translations: TranslationDeepObject<typeof en> = {
         enableWallet: '启用钱包',
         addBankAccountToSendAndReceive: '添加银行账户以进行或接收付款。',
         addDebitOrCreditCard: '添加借记卡或信用卡',
-        cardInactive: '未激活',
-        assignedCards: '卡片',
-        assignedCardsDescription: '已分配卡片的交易会自动同步。',
+        assignedCards: '已分配的卡片',
+        assignedCardsDescription: '这些银行卡的交易会自动同步。',
         expensifyCard: 'Expensify 卡',
         walletActivationPending: '我们正在审核您的信息。请几分钟后再回来查看！',
         walletActivationFailed: '很遗憾，您的钱包目前无法启用。请与 Concierge 聊天以获取进一步帮助。',
@@ -2402,9 +2160,8 @@ const translations: TranslationDeepObject<typeof en> = {
         unshareBankAccount: '取消共享银行账户',
         unshareBankAccountDescription: '以下所有人都可以访问此银行账户。您可以随时移除他们的访问权限。我们仍会完成任何正在处理中的付款。',
         unshareBankAccountWarning: ({admin}: {admin?: string | null}) => `${admin} 将失去对此企业银行账户的访问权限。我们仍会完成任何正在处理中的付款。`,
-        reachOutForHelp: '它正在与 Expensify 卡一起使用。如需取消共享，请<concierge-link>联系 Concierge</concierge-link>。',
+        reachOutForHelp: '它正在与 Expensify Card 一起使用。若需要取消共享，请<concierge-link>联系 Concierge</concierge-link>。',
         unshareErrorModalTitle: '无法取消共享银行账户',
-        travelCVV: {title: '旅行 CVV', subtitle: '预订差旅时使用此选项', description: '使用此卡预订 Expensify Travel 行程。结账时它会显示为“Travel Card”。'},
         chaseAccountNumberDifferent: '为什么我的账户号码不同？',
     },
     cardPage: {
@@ -2413,15 +2170,15 @@ const translations: TranslationDeepObject<typeof en> = {
         availableSpend: '剩余额度',
         smartLimit: {
             name: '智能限额',
-            title: (formattedLimit: string) => `您可以在此卡上消费最高 ${formattedLimit}，当您提交的报销获得批准后，该额度将重置。`,
+            title: ({formattedLimit}: ViolationsOverLimitParams) => `您可以在此卡上消费最高 ${formattedLimit}，当您提交的报销获得批准后，该额度将重置。`,
         },
         fixedLimit: {
             name: '固定限额',
-            title: (formattedLimit: string) => `您可以在此卡上消费最高 ${formattedLimit}，之后此卡将被停用。`,
+            title: ({formattedLimit}: ViolationsOverLimitParams) => `您可以在此卡上消费最高 ${formattedLimit}，之后此卡将被停用。`,
         },
         monthlyLimit: {
             name: '月度限额',
-            title: (formattedLimit: string) => `您每月最多可在此卡上消费 ${formattedLimit}。额度将在每个日历月的第 1 天重置。`,
+            title: ({formattedLimit}: ViolationsOverLimitParams) => `您每月最多可在此卡上消费 ${formattedLimit}。额度将在每个日历月的第 1 天重置。`,
         },
         virtualCardNumber: '虚拟卡号',
         travelCardCvv: '差旅卡验证码（CVV）',
@@ -2442,17 +2199,16 @@ const translations: TranslationDeepObject<typeof en> = {
             expiration: '到期日期',
             cvv: 'CVV',
             address: '地址',
-            reveal: '显示',
             revealDetails: '显示详细信息',
             revealCvv: '显示 CVV',
             copyCardNumber: '复制卡号',
-            copyCvv: '复制 CVV',
             updateAddress: '更新地址',
         },
         cardAddedToWallet: ({platform}: {platform: 'Google' | 'Apple'}) => `已添加到 ${platform} 钱包`,
         cardDetailsLoadingFailure: '加载卡片详情时出错。请检查您的网络连接，然后重试。',
         validateCardTitle: '让我们确认一下是你本人',
         enterMagicCode: (contactMethod: string) => `请输入发送到 ${contactMethod} 的魔法验证码以查看您的卡片详情。验证码应会在一两分钟内送达。`,
+        missingPrivateDetails: ({missingDetailsLink}: {missingDetailsLink: string}) => `请<a href="${missingDetailsLink}">添加您的个人信息</a>，然后重试。`,
         unexpectedError: '尝试获取您的 Expensify 卡片详情时出错。请重试。',
         cardFraudAlert: {
             confirmButtonText: '是的，我愿意',
@@ -2473,42 +2229,6 @@ const translations: TranslationDeepObject<typeof en> = {
 
 ${amount}，商户：${merchant} - 日期：${date}`,
         },
-        setYourPin: '设置您的 PIN.',
-        confirmYourPin: '确认您的 PIN.',
-        changeYourPin: '为您的银行卡输入新 PIN 码。',
-        confirmYourChangedPin: '确认您的新 PIN。',
-        pinMustBeFourDigits: 'PIN 必须正好为 4 位数字。',
-        invalidPin: '请选择一个更安全的 PIN。',
-        pinMismatch: 'PIN 不匹配。请重试。',
-        revealPin: '显示 PIN',
-        hidePin: '隐藏 PIN',
-        pin: 'PIN',
-        changePin: '更改 PIN',
-        pinChanged: 'PIN 已更改！',
-        pinChangedHeader: 'PIN 已更改',
-        pinChangedDescription: '现在您可以开始使用您的 PIN 了。',
-        changePinAtATM: '在任意 ATM 更改您的 PIN',
-        changePinAtATMDescription: '这是您所在地区的必填项。如果你有任何问题，请<concierge-link>联系 Concierge</concierge-link>。',
-        freezeCard: '冻结卡片',
-        unfreeze: '解冻',
-        unfreezeCard: '解冻卡片',
-        askToUnfreeze: '申请解冻',
-        freezeDescription: '冻结的卡片无法用于购买和交易。你可以随时解冻。',
-        unfreezeDescription: '解冻此卡后，将重新允许购买和交易。仅当你确定该卡可以安全使用时再继续。',
-        frozen: '已冻结',
-        youFroze: ({date}: {date: string}) => `你于${date}冻结了此卡。`,
-        frozenBy: ({person, date}: {person: string; date: string}) => `${person}于${date}冻结了此卡。`,
-        frozenByAdminPrefix: ({date}: {date: string}) => `此卡于${date}被冻结，操作人是`,
-        frozenByAdminNeedsUnfreezePrefix: '此卡已被',
-        frozenByAdminNeedsUnfreezeSuffix: '冻结。请联系管理员解冻。',
-        frozenByAdminNeedsUnfreeze: ({person}: {person: string}) => `此卡已被${person}冻结。请联系管理员解冻。`,
-        spendRules: '支出规则',
-        editSpendRules: '编辑支出规则',
-        cardUnblocked: '卡已解除冻结！',
-        cardUnblockedDescription: '下次消费时，系统可能会提示你将银行卡插入读卡器。',
-        pinBlocked: '由于多次输入错误 PIN，您的银行卡已被停用。',
-        unblock: '取消屏蔽',
-        unblockCard: '解除卡片冻结',
     },
     workflowsPage: {
         workflowTitle: '支出',
@@ -2520,14 +2240,9 @@ ${amount}，商户：${merchant} - 日期：${date}`,
         addApprovalsTitle: '审批',
         accessibilityLabel: ({members, approvers}: {members: string; approvers: string}) => `来自${members}的报销，审批人是${approvers}`,
         addApprovalButton: '添加审批工作流',
-        editWorkflowAction: '编辑',
-        addAgentAction: '添加代理',
-        findWorkflow: '查找工作流',
         addApprovalTip: '除非存在更具体的工作流程，否则此默认工作流程适用于所有成员。',
         approver: '审批人',
         addApprovalsDescription: '在付款前需要额外审批。',
-        automateApprovalsWithAgentsTitle: '使用代理自动化审批',
-        automateApprovalsWithAgentsSubtitle: '在下方添加代理到工作流程中以自动化审批。',
         makeOrTrackPaymentsTitle: '付款',
         makeOrTrackPaymentsDescription: '为在 Expensify 中进行的付款添加授权付款人，或跟踪在其他地方进行的付款。',
         customApprovalWorkflowEnabled:
@@ -2571,14 +2286,7 @@ ${amount}，商户：${merchant} - 日期：${date}`,
             title: '没有可显示的成员',
             expensesFromSubtitle: '所有工作区成员已经属于现有的审批流程。',
             approverSubtitle: '所有审批人都属于一个现有的工作流。',
-            bulkApproverSubtitle: '所选报表中没有符合条件的审批人。',
         },
-        configureViaHR: ({provider}: {provider: string}) => `通过 ${provider} 配置。`,
-        hrApprovalWorkflowLockedPrompt: ({provider}: {provider: string}) => `审批由你的 ${provider} 集成管理。若要更新审批流程，请前往 ${provider} 连接设置。`,
-        goToHRSettings: ({provider}: {provider: string}) => `前往 ${provider} 设置`,
-        approverFromProvider: ({provider}: {provider: string}) => `来自 ${provider}`,
-        finalApprover: '最终审批人',
-        manager: '经理',
     },
     workflowsDelayedSubmissionPage: {
         autoReportingFrequencyErrorMessage: '提交频率无法更改。请重试或联系支持团队。',
@@ -2598,9 +2306,6 @@ ${amount}，商户：${merchant} - 日期：${date}`,
     workflowsExpensesFromPage: {
         title: '支出起始于',
         header: '当以下成员提交报销时：',
-        memberAlreadyInWorkflowTitle: '成员已在工作流中',
-        memberAlreadyInWorkflowPrompt: ({memberName, approverName}: {memberName: string; approverName: string}) =>
-            `${memberName}已在提交给${approverName}的审批流程中。在此处添加将把该成员移动到此工作流。`,
     },
     workflowsApproverPage: {
         genericErrorMessage: '无法更改审批人。请重试或联系支持。',
@@ -2628,15 +2333,6 @@ ${amount}，商户：${merchant} - 日期：${date}`,
         admins: '管理员',
         payer: '付款人',
         paymentAccount: '支付账户',
-        shareBankAccount: {
-            shareTitle: '共享银行账户访问权限？',
-            shareDescription: ({admin}: {admin: string}) => `您需要与 ${admin} 共享银行账户访问权限，才能将其设置为付款人。`,
-            validationTitle: '银行账户等待验证',
-            validationDescription: ({admin}: {admin: string}) => `您需要<a href="#">验证此银行账户</a>。验证完成后，您可以将银行账户访问权限分享给 ${admin}，使其成为付款人。`,
-            errorTitle: '无法更改付款人',
-            errorDescription: ({admin, owner}: {admin: string; owner: string}) =>
-                `${admin} 没有此银行账户的访问权限，因此您无法将其设置为付款人。<a href="#">请联系 ${owner}</a> 了解是否需要共享此银行账户。`,
-        },
     },
     reportFraudPage: {
         title: '报告虚拟卡欺诈',
@@ -2647,7 +2343,6 @@ ${amount}，商户：${merchant} - 日期：${date}`,
     reportFraudConfirmationPage: {
         title: '已报告卡片欺诈',
         description: '我们已永久停用你的现有卡片。当你返回查看卡片详情时，你将会看到一张新的虚拟卡片可用。',
-        descriptionCardNotReplaced: '您的卡已被永久停用。请联系管理员以发行新卡。',
         buttonText: '明白了，谢谢！',
     },
     activateCardPage: {
@@ -2656,7 +2351,7 @@ ${amount}，商户：${merchant} - 日期：${date}`,
         activatePhysicalCard: '激活实体卡',
         error: {
             thatDidNotMatch: '这与您卡片的最后 4 位数字不匹配。请重试。',
-            throttled: '您多次错误输入 Expensify 卡的末 4 位数字。如果您确定数字无误，请联系 Concierge 解决。否则，请稍后再试。',
+            throttled: '您多次错误输入 Expensify Card 的末4位数字。如果您确定号码无误，请联系 Concierge 以解决问题。否则请稍后再试。',
         },
     },
     getPhysicalCard: {
@@ -2681,7 +2376,7 @@ ${amount}，商户：${merchant} - 日期：${date}`,
         shipCard: '寄送卡片',
     },
     transferAmountPage: {
-        transfer: (amount: string) => `转账${amount ? ` ${amount}` : ''}`,
+        transfer: ({amount}: TransferParams) => `转账${amount ? ` ${amount}` : ''}`,
         instant: '即时（借记卡）',
         instantSummary: (rate: string, minAmount: string) => `${rate}% 手续费（最低 ${minAmount}）`,
         ach: '1-3 个工作日（银行账户）',
@@ -2708,46 +2403,14 @@ ${amount}，商户：${merchant} - 日期：${date}`,
         defaultPaymentMethod: '默认',
         bankAccountLastFour: (lastFour: string) => `银行账户 • ${lastFour}`,
     },
-    agentsPage: {
-        title: '代理人',
-        subtitle: '通过自定义智能体自动化处理任务。',
-        newAgent: '新代理人',
-        emptyAgents: {title: '尚未创建代理', subtitle: '别再手动处理这些事情了。交给智能代理去执行，为自己节省大量时间。'},
-        error: {
-            genericAdd: '添加此智能体时出现了问题',
-            genericUpdate: '更新此代理时出现问题',
-            updateName: '更新此代理名称时出现问题',
-            updatePrompt: '更新此代理的说明时出现问题',
-            updateAvatar: '更新此代理的头像时出现问题',
-        },
-    },
-    addAgentPage: {
-        title: '新代理',
-        agentName: '代理名称',
-        instructions: '编写自定义说明',
-        createAgent: '创建代理',
-        editAvatar: '切换头像',
-        defaultAgentName: (displayName: string) => `${displayName} 的代理人`,
-        defaultPrompt:
-            '拒绝与赌博、电影或其他明显非商务原因相关的报销。\n\n提醒用户务必附上一张能清楚显示小费金额的收据图片。\n\n如果报销报告与同一用户之前的报告非常相似，则批准该报告。\n\n拒绝包含超过 500 美元差旅费用的报销报告。',
-    },
-    editAgentPage: {
-        title: '编辑代理',
-        agentName: '代理人姓名',
-        instructions: '编写自定义说明',
-        chatWithAgent: '与代理聊天',
-        copilotIntoAccount: 'Copilot 进入账户',
-        deleteAgent: '删除代理',
-        deleteAgentTitle: '删除代理？',
-        deleteAgentMessage: '确定要删除此代理吗？此操作无法撤销。',
-    },
-    editAgentAvatarPage: {title: '编辑头像'},
-    editAgentNamePage: {title: '代理人姓名'},
-    editAgentPromptPage: {title: '编写自定义说明', error: {emptyPrompt: '请输入给您代理的指示。'}},
     expenseRulesPage: {
         title: '报销规则',
+        subtitle: '这些规则将适用于你的报销。如果你提交到某个工作区，则该工作区的规则可能会覆盖这些规则。',
         findRule: '查找规则',
-        emptyRules: {title: '尚未设置规则', subtitle: '添加规则以自动生成报销报告。'},
+        emptyRules: {
+            title: '您尚未创建任何规则',
+            subtitle: '添加规则以自动生成报销报告。',
+        },
         changes: {
             billableUpdate: (value: boolean) => `更新报销 ${value ? '可计费' : '不可计费'}`,
             categoryUpdate: (value: string) => `将类别更新为“${value}”`,
@@ -2788,7 +2451,6 @@ ${amount}，商户：${merchant} - 日期：${date}`,
             deleteSinglePrompt: '确定要删除此规则吗？',
             deleteMultiplePrompt: '确定要删除这些规则吗？',
         },
-        subtitle: '这些规则将适用于你的报销费用。',
     },
     preferencesPage: {
         appSection: {
@@ -2816,12 +2478,11 @@ ${amount}，商户：${merchant} - 日期：${date}`,
         },
     },
     reportDetailsPage: {
-        inWorkspace: (policyName: string) => `在 ${policyName} 中`,
+        inWorkspace: ({policyName}: ReportPolicyNameParams) => `在 ${policyName} 中`,
         generatingPDF: '生成 PDF',
         waitForPDF: '正在生成 PDF，请稍候。',
         errorPDF: '尝试生成您的 PDF 时出错',
         successPDF: '您的 PDF 已生成！如果没有自动下载，请使用下面的按钮。',
-        goToRoom: '进入房间',
     },
     reportDescriptionPage: {
         roomDescription: '房间描述',
@@ -2831,7 +2492,7 @@ ${amount}，商户：${merchant} - 日期：${date}`,
     groupChat: {
         lastMemberTitle: '注意！',
         lastMemberWarning: '由于你是这里的最后一位成员，一旦离开，所有成员都将无法再访问此聊天。确定要离开吗？',
-        defaultReportName: (displayName: string) => `${displayName} 的群聊`,
+        defaultReportName: ({displayName}: ReportArchiveReasonsClosedParams) => `${displayName} 的群聊`,
     },
     languagePage: {
         language: '语言',
@@ -2850,25 +2511,19 @@ ${amount}，商户：${merchant} - 日期：${date}`,
                 label: '使用设备设置',
             },
         },
-        highContrastMode: '高对比度模式',
-        enableHighContrast: '启用高对比度',
-        disableHighContrast: '关闭高对比度',
         chooseThemeBelowOrSync: '请选择下方的主题，或与您的设备设置同步。',
     },
     termsOfUse: {
         terms: `<muted-text-xs>登录即表示你同意<a href="${CONST.OLD_DOT_PUBLIC_URLS.TERMS_URL}">服务条款</a>和<a href="${CONST.OLD_DOT_PUBLIC_URLS.PRIVACY_URL}">隐私政策</a>。</muted-text-xs>`,
-        license: `资金汇款服务由 ${CONST.WALLET.PROGRAM_ISSUERS.EXPENSIFY_PAYMENTS}（NMLS ID:2017010）根据其<a href="${CONST.OLD_DOT_PUBLIC_URLS.LICENSES_URL}">许可证</a>提供。`,
+        license: `<muted-text-xs>资金传输服务由 ${CONST.WALLET.PROGRAM_ISSUERS.EXPENSIFY_PAYMENTS}（NMLS ID:2017010）根据其<a href="${CONST.OLD_DOT_PUBLIC_URLS.LICENSES_URL}">执照</a>提供。</muted-text-xs>`,
     },
     validateCodeForm: {
         magicCodeNotReceived: '没有收到验证码？',
-        avoidScamsMessage: '<strong>谨防诈骗。不要与任何人分享您的验证码。</strong> 我们的团队绝不会打电话、发短信或发送电子邮件向您索取此验证码。',
         enterAuthenticatorCode: '请输入您的认证器验证码',
         enterRecoveryCode: '请输入您的恢复代码',
         requiredWhen2FAEnabled: '启用双重验证时必填',
         requestNewCode: ({timeRemaining}: {timeRemaining: string}) => `在<a>${timeRemaining}</a>后请求新代码`,
         requestNewCodeAfterErrorOccurred: '请求新验证码',
-        timeRemainingAnnouncement: ({timeRemaining}) => `剩余时间：${timeRemaining}秒`,
-        timeExpiredAnnouncement: '时间已到期',
         error: {
             pleaseFillMagicCode: '请输入你的魔法验证码',
             incorrectMagicCode: '魔术验证码不正确或无效。请重试或请求新的验证码。',
@@ -2899,7 +2554,6 @@ ${amount}，商户：${merchant} - 日期：${date}`,
         phoneOrEmail: '电话或邮箱',
         error: {
             invalidFormatEmailLogin: '输入的邮箱无效。请修正格式后重试。',
-            agentSignInBlocked: '代理帐户无法直接登录。要使用代理，请先登录您自己的帐户，然后通过 Copilot 访问该代理。',
         },
         cannotGetAccountDetails: '无法获取账户详情。请尝试重新登录。',
         loginForm: '登录表单',
@@ -2916,39 +2570,28 @@ ${amount}，商户：${merchant} - 日期：${date}`,
         },
         getStarted: '开始使用',
         whatsYourName: '你叫什么名字？',
-        peopleYouMayKnow: '查看你的团队是否已在 Expensify 中',
-        workspaceYouMayJoin: (domain: string, email: string) => `请输入发送到 ${email} 的验证码，以检查是否有来自 ${domain} 的成员已创建可供你加入的工作区。`,
+        peopleYouMayKnow: '你可能认识的人已经在这里了！验证你的邮箱以加入他们。',
+        workspaceYouMayJoin: ({domain, email}: WorkspaceYouMayJoin) => `${domain} 中的某位成员已经创建了一个工作区。请输入发送到 ${email} 的魔法验证码。`,
         joinAWorkspace: '加入工作区',
-        listOfWorkspaces: '以下是你可以加入的工作区列表。',
-        skipForNow: '暂时跳过',
-        workspaceMemberList: (employeeCount: number, policyOwner: string) => `${employeeCount} 位成员${employeeCount > 1 ? '秒' : ''} • ${policyOwner}`,
+        listOfWorkspaces: '以下是你可以加入的工作空间列表。别担心，如果你愿意，你随时都可以稍后再加入。',
+        workspaceMemberList: ({employeeCount, policyOwner}: WorkspaceMemberList) => `${employeeCount} 位成员${employeeCount > 1 ? '秒' : ''} • ${policyOwner}`,
         whereYouWork: '你在哪里工作？',
         errorSelection: '选择一个选项以继续',
         purpose: {
             title: '你今天想做什么？',
             errorContinue: '请按“继续”完成设置',
             errorBackButton: '请完成设置问题以开始使用此应用程序',
-            [CONST.ONBOARDING_CHOICES.EMPLOYER]: '向雇主提交费用',
+            [CONST.ONBOARDING_CHOICES.EMPLOYER]: '由我的雇主报销',
             [CONST.ONBOARDING_CHOICES.MANAGE_TEAM]: '管理我团队的报销',
-            [CONST.ONBOARDING_CHOICES.TRACK_BUSINESS]: '跟踪我的商务开销',
-            [CONST.ONBOARDING_CHOICES.TRACK_PERSONAL]: '管理我的个人支出',
+            [CONST.ONBOARDING_CHOICES.PERSONAL_SPEND]: '跟踪和预算开销',
+            [CONST.ONBOARDING_CHOICES.CHAT_SPLIT]: '与朋友聊天并平摊费用',
             [CONST.ONBOARDING_CHOICES.LOOKING_AROUND]: '其他原因',
         },
-        personalTrackGoal: {
-            title: '您想跟踪什么？',
-            [CONST.ONBOARDING_PERSONAL_TRACK_GOALS.INVESTMENT_TRACKING]: '投资物业成本',
-            [CONST.ONBOARDING_PERSONAL_TRACK_GOALS.HOUSEHOLD_TRACKING]: '家庭开支',
-            [CONST.ONBOARDING_PERSONAL_TRACK_GOALS.SIDEPROJECT_TRACKING]: '副业报销',
-            [CONST.ONBOARDING_PERSONAL_TRACK_GOALS.SOMETHING_ELSE]: '其他原因',
-            somethingElsePlaceholder: '你在跟踪什么？',
-        },
         employees: {
             title: '您有多少名员工？',
-            [CONST.ONBOARDING_COMPANY_SIZE.MICRO_SMALL]: '1–4 名员工',
-            [CONST.ONBOARDING_COMPANY_SIZE.MICRO_MEDIUM]: '5–10 名员工',
-            [CONST.ONBOARDING_COMPANY_SIZE.MICRO]: '1-10 名员工',
-            [CONST.ONBOARDING_COMPANY_SIZE.SMALL]: '11–50 名员工',
-            [CONST.ONBOARDING_COMPANY_SIZE.MEDIUM_SMALL]: '51–100 名员工',
+            [CONST.ONBOARDING_COMPANY_SIZE.MICRO]: '1–10 名员工',
+            [CONST.ONBOARDING_COMPANY_SIZE.SMALL]: '11-50 名员工',
+            [CONST.ONBOARDING_COMPANY_SIZE.MEDIUM_SMALL]: '51-100 名员工',
             [CONST.ONBOARDING_COMPANY_SIZE.MEDIUM]: '101–1,000 名员工',
             [CONST.ONBOARDING_COMPANY_SIZE.LARGE]: '超过 1,000 名员工',
         },
@@ -2976,17 +2619,15 @@ ${amount}，商户：${merchant} - 日期：${date}`,
         },
         workEmailValidation: {
             title: '验证你的工作邮箱',
-            magicCodeSent: (workEmail: string | undefined) => `请输入发送到 ${workEmail} 的验证码。它应会在一两分钟内送达。`,
+            magicCodeSent: ({workEmail}: WorkEmailResendCodeParams) => `请输入发送到 ${workEmail} 的验证码。它应会在一两分钟内送达。`,
         },
         workEmailValidationError: {
             publicEmail: '请输入来自私有域的有效工作邮箱，例如：mitch@company.com',
-            sameAsSignupEmail: '请输入与注册时不同的邮箱',
             offline: '由于您似乎处于离线状态，我们无法添加您的工作邮箱',
         },
         mergeBlockScreen: {
             title: '无法添加工作邮箱',
-            subtitle: (workEmail: string | undefined) => `我们无法添加 ${workEmail}。请稍后在设置中重试，或与 Concierge 聊天以获取指导。`,
-            workAccountClosedSubtitle: '与此邮箱关联的工作账户已被关闭。请联系您公司的管理员以重新激活该账户，或使用其他邮箱注册。',
+            subtitle: ({workEmail}: WorkEmailMergingBlockedParams) => `我们无法添加 ${workEmail}。请稍后在设置中重试，或与 Concierge 聊天以获取指导。`,
         },
         tasks: {
             testDriveAdminTask: {
@@ -3017,7 +2658,7 @@ ${amount}，商户：${merchant} - 日期：${date}`,
             },
             createTestDriveAdminWorkspaceTask: {
                 title: ({workspaceConfirmationLink}) => `[创建](${workspaceConfirmationLink}) 一个工作区`,
-                description: '在客户经理的帮助下创建工作区并配置相关设置！',
+                description: '在设置专家的帮助下创建工作区并配置相关设置！',
             },
             createWorkspaceTask: {
                 title: ({workspaceSettingsLink}) => `创建一个[工作区](${workspaceSettingsLink})`,
@@ -3033,7 +2674,7 @@ ${amount}，商户：${merchant} - 日期：${date}`,
                 title: ({workspaceCategoriesLink}) => `设置[类别](${workspaceCategoriesLink})`,
                 description: ({workspaceCategoriesLink}) =>
                     dedent(`
-                        *设置类别*，以便你的团队可以为报销分类，方便生成报表。
+                        *设置类别*，让你的团队可以为报销分类，方便出具报表。
 
                         1. 点击 *工作区*。
                         2. 选择你的工作区。
@@ -3049,7 +2690,7 @@ ${amount}，商户：${merchant} - 日期：${date}`,
                 description: dedent(`
                     通过输入金额或扫描收据来*提交一笔报销*。
 
-                    1. 点击 *+* 按钮。
+                    1. 点击 ${CONST.CUSTOM_EMOJIS.GLOBAL_CREATE} 按钮。
                     2. 选择 *创建报销*。
                     3. 输入金额或扫描收据。
                     4. 添加你老板的邮箱或电话号码。
@@ -3063,7 +2704,7 @@ ${amount}，商户：${merchant} - 日期：${date}`,
                 description: dedent(`
                     通过输入金额或扫描收据来*提交报销*。
 
-                    1. 点击 *+* 按钮。
+                    1. 点击 ${CONST.CUSTOM_EMOJIS.GLOBAL_CREATE} 按钮。
                     2. 选择*创建报销*。
                     3. 输入金额或扫描收据。
                     4. 确认详细信息。
@@ -3077,7 +2718,7 @@ ${amount}，商户：${merchant} - 日期：${date}`,
                 description: dedent(`
                     *以任意货币*记录一笔报销，无论你是否有收据。
 
-                    1. 点击 *+* 按钮。
+                    1. 点击 ${CONST.CUSTOM_EMOJIS.GLOBAL_CREATE} 按钮。
                     2. 选择 *创建报销*。
                     3. 输入金额或扫描收据。
                     4. 选择你的*个人*空间。
@@ -3099,8 +2740,13 @@ ${amount}，商户：${merchant} - 日期：${date}`,
                         4. 找到 ${integrationName}。
                         5. 点击 *Connect*。
 
-                        [带我前往会计页面](${workspaceAccountingLink})。
-                    `),
+${
+    integrationName && CONST.connectionsVideoPaths[integrationName]
+        ? `[带我去会计页面](${workspaceAccountingLink}).
+
+                        ![连接到 ${integrationName}](${CONST.CLOUDFRONT_URL}/${CONST.connectionsVideoPaths[integrationName]})`
+        : `[带我前往会计页面](${workspaceAccountingLink})。`
+}`),
             },
             connectCorporateCardTask: {
                 title: ({corporateCardLink}) => `连接[您的公司卡](${corporateCardLink})`,
@@ -3119,12 +2765,12 @@ ${amount}，商户：${merchant} - 日期：${date}`,
                 title: ({workspaceMembersLink}) => `邀请[您的团队](${workspaceMembersLink})`,
                 description: ({workspaceMembersLink}) =>
                     dedent(`
-                        *邀请您的团队*加入 Expensify，让他们从今天开始跟踪报销费用。
+                        *邀请您的团队* 使用 Expensify，这样他们今天就能开始记录报销。
 
-                        1. 点击 *工作区*。
+                        1. 点击 *Workspaces*。
                         2. 选择您的工作区。
-                        3. 点击 *成员* > *邀请成员*。
-                        4. 输入邮箱或电话号码。
+                        3. 点击 *Members* > *Invite member*。
+                        4. 输入邮箱地址或电话号码。
                         5. 如有需要，可添加自定义邀请消息！
 
                         [带我前往工作区成员页面](${workspaceMembersLink})。
@@ -3142,14 +2788,14 @@ ${amount}，商户：${merchant} - 日期：${date}`,
                 title: ({workspaceTagsLink}) => `设置[标签](${workspaceTagsLink})`,
                 description: ({workspaceMoreFeaturesLink}) =>
                     dedent(`
-                        使用标签添加更多报销详情，例如项目、客户、地点和部门。如果你需要多级标签，可以升级到 Control 方案。
+                        使用标签来添加额外的报销明细，如项目、客户、地点和部门。如果你需要多级标签，可以升级到 Control 方案。
 
                         1. 点击 *工作区*。
                         2. 选择你的工作区。
                         3. 点击 *更多功能*。
                         4. 启用 *标签*。
                         5. 在工作区编辑器中前往 *标签*。
-                        6. 点击 *+ 添加标签* 创建你自己的标签。
+                        6. 点击 *+ 添加标签* 来创建你自己的标签。
 
                         [带我前往更多功能](${workspaceMoreFeaturesLink})。
 
@@ -3174,7 +2820,7 @@ ${amount}，商户：${merchant} - 日期：${date}`,
                 description: dedent(`
                     *开始聊天*，只需输入对方的邮箱或电话号码。
 
-                    1. 点击 *+* 按钮。
+                    1. 点击 ${CONST.CUSTOM_EMOJIS.GLOBAL_CREATE} 按钮。
                     2. 选择 *开始聊天*。
                     3. 输入邮箱或电话号码。
 
@@ -3188,7 +2834,7 @@ ${amount}，商户：${merchant} - 日期：${date}`,
                 description: dedent(`
                     与一人或多人*平摊费用*。
 
-                    1. 点击 *+* 按钮。
+                    1. 点击 ${CONST.CUSTOM_EMOJIS.GLOBAL_CREATE} 按钮。
                     2. 选择 *开始聊天*。
                     3. 输入邮箱或电话号码。
                     4. 在聊天中点击灰色的 *+* 按钮 > *分摊费用*。
@@ -3212,7 +2858,7 @@ ${amount}，商户：${merchant} - 日期：${date}`,
                 description: dedent(`
                     创建报表步骤如下：
 
-                    1. 点击 *+* 按钮。
+                    1. 点击 ${CONST.CUSTOM_EMOJIS.GLOBAL_CREATE} 按钮。
                     2. 选择 *创建报表*。
                     3. 点击 *添加报销*。
                     4. 添加你的第一笔报销。
@@ -3234,16 +2880,18 @@ ${amount}，商户：${merchant} - 日期：${date}`,
             onboardingManageTeamMessage: ({isOnboardingFlow = false}: {isOnboardingFlow?: boolean}) =>
                 isOnboardingFlow
                     ? dedent(`
-                        # 您的免费试用已开始！让我们来完成设置。
-                        👋 您好，我是负责您 Expensify 账号的客户经理。我已经为您创建了一个工作区，帮助管理您团队的收据和报销。要充分利用这 30 天的免费试用，请按照下面剩余的设置步骤进行操作！
+                        # 您的免费试用已开始！让我们开始设置吧。
+                        👋 您好，我是您的 Expensify 设置专员。我已为您创建了一个工作区，帮助管理您团队的收据和费用。要充分利用这 30 天的免费试用，只需按照下面剩余的设置步骤完成即可！
                     `)
                     : dedent(`
-                        # 您的免费试用已开始！让我们来为您完成设置。
-                        👋 您好，我是您的 Expensify 客户经理。现在您已经创建了一个工作区，请按照以下步骤操作，充分利用这 30 天的免费试用期！
+                        # 您的免费试用已开始！让我们帮您完成设置。
+                        👋 您好，我是您的 Expensify 设置专员。现在您已经创建了一个工作区，请按照下面的步骤操作，充分利用这 30 天的免费试用期！
                     `),
-            onboardingTrackWorkspaceMessage: '要充分利用您的 30 天免费试用，请完成以下剩余步骤：',
+            onboardingTrackWorkspaceMessage:
+                '# 让我们开始为你进行设置\n👋 你好，我是你的 Expensify 设置专家。我已经为你创建了一个工作区，用来管理你的收据和报销。要充分利用你的 30 天免费试用，只需按照下面剩余的设置步骤操作即可！',
             onboardingChatSplitMessage: '和朋友分摊账单就像发条消息一样简单。操作方法如下。',
             onboardingAdminMessage: '了解如何以管理员身份管理您团队的工作区，并提交您自己的报销。',
+            onboardingLookingAroundMessage: 'Expensify 以报销、差旅和公司卡管理而闻名，但我们的功能远不止于此。告诉我你感兴趣的内容，我会帮你开始使用。',
             onboardingTestDriveReceiverMessage: '*您已获得 3 个月的免费使用！请从下面开始。*',
         },
         workspace: {
@@ -3254,7 +2902,7 @@ ${amount}，商户：${merchant} - 日期：${date}`,
                 descriptionTwo: '分类并标记报销费用',
                 descriptionThree: '创建并分享报告',
             },
-            price: (price?: string) => `免费试用 30 天，之后仅需 <strong>${price ?? '$5'}/用户/月</strong> 即可升级。`,
+            price: '免费试用 30 天，之后仅需 <strong>$5/用户/月</strong> 即可升级。',
             createWorkspace: '创建工作区',
         },
         confirmWorkspace: {
@@ -3265,8 +2913,6 @@ ${amount}，商户：${merchant} - 日期：${date}`,
             title: '邀请成员',
             subtitle: '添加你的团队或邀请你的会计。人越多越热闹！',
         },
-        workEmail2FAError: '此登录使用的是已启用双重身份验证（2FA）的现有账户。',
-        singleSignOnError: '此登录使用的是已启用 SSO/SAML 的现有账户。',
     },
     featureTraining: {
         doNotShowAgain: '不再显示此内容',
@@ -3286,7 +2932,6 @@ ${amount}，商户：${merchant} - 日期：${date}`,
         enterPhoneNumber: '你的电话号码是多少？',
         personalDetails: '个人信息',
         privateDataMessage: '这些详细信息将用于出行和付款，绝不会显示在你的公开个人资料中。',
-        basicDetails: '基本信息',
         legalName: '法定姓名',
         legalFirstName: '法定名（名）',
         legalLastName: '法定姓氏',
@@ -3295,18 +2940,17 @@ ${amount}，商户：${merchant} - 日期：${date}`,
             dateShouldBeBefore: (dateString: string) => `日期应早于 ${dateString}`,
             dateShouldBeAfter: (dateString: string) => `日期应晚于 ${dateString}`,
             hasInvalidCharacter: '姓名只能包含拉丁字符',
-            cannotIncludeCommaOrSemicolon: '名称不能包含逗号或分号',
             incorrectZipFormat: (zipFormat?: string) => `邮政编码格式不正确${zipFormat ? `可接受的格式：${zipFormat}` : ''}`,
             invalidPhoneNumber: `请确保电话号码有效（例如：${CONST.EXAMPLE_PHONE_NUMBER}）`,
         },
     },
     resendValidationForm: {
         linkHasBeenResent: '链接已重新发送',
-        weSentYouMagicSignInLink: (login: string, loginType: string) => `我已向 ${login} 发送了魔法登录链接。请检查你的 ${loginType} 以登录。`,
+        weSentYouMagicSignInLink: ({login, loginType}: WeSentYouMagicSignInLinkParams) => `我已向 ${login} 发送了魔法登录链接。请检查你的 ${loginType} 以登录。`,
         resendLink: '重新发送链接',
     },
     unlinkLoginForm: {
-        toValidateLogin: (primaryLogin: string, secondaryLogin: string) => `若要验证 ${secondaryLogin}，请从 ${primaryLogin} 的账户设置中重新发送魔法验证码。`,
+        toValidateLogin: ({primaryLogin, secondaryLogin}: ToValidateLoginParams) => `若要验证 ${secondaryLogin}，请从 ${primaryLogin} 的账户设置中重新发送魔法验证码。`,
         noLongerHaveAccess: (primaryLogin: string) => `如果你已无法访问 ${primaryLogin}，请先解除账户关联。`,
         unlink: '取消关联',
         linkSent: '链接已发送！',
@@ -3362,12 +3006,14 @@ ${amount}，商户：${merchant} - 日期：${date}`,
     },
     welcomeSignUpForm: {
         join: '加入',
-        marketingSMSConsent: '我同意接收来自 Expensify 的营销短信',
     },
     detailsPage: {
         localTime: '本地时间',
     },
-    newChatPage: {startGroup: '开始群组', addToGroup: '添加到群组', addUserToGroup: (username: string) => `将 ${username} 添加到群组`},
+    newChatPage: {
+        startGroup: '开始群组',
+        addToGroup: '添加到群组',
+    },
     yearPickerPage: {
         year: '年份',
         selectYear: '请选择年份',
@@ -3409,18 +3055,17 @@ ${amount}，商户：${merchant} - 日期：${date}`,
             custom: '自定义',
         },
         untilTomorrow: '直到明天',
-        untilTime: (time: string) => `直到 ${time}`,
+        untilTime: ({time}: UntilTimeParams) => `直到 ${time}`,
         date: '日期',
         time: '时间',
         clearAfter: '多久后清除',
         whenClearStatus: '我们应在何时清除你的状态？',
+        vacationDelegate: '休假代理',
         setVacationDelegate: `设置一个休假代理人在你不在办公室时代你审批报销报告。`,
-        cannotSetVacationDelegate: `由于你目前是以下成员的代理人，因此无法设置休假代理人：`,
-        addVacationDelegate: '添加休假代理人',
         vacationDelegateError: '更新你的休假代理时出错。',
-        asVacationDelegate: (nameOrEmail: string) => `作为 ${nameOrEmail} 的休假代理`,
-        toAsVacationDelegate: (submittedToName: string, vacationDelegateName: string) => `作为 ${vacationDelegateName} 的休假代理人提交给 ${submittedToName}`,
-        vacationDelegateWarning: (nameOrEmail: string) =>
+        asVacationDelegate: ({nameOrEmail}: VacationDelegateParams) => `作为 ${nameOrEmail} 的休假代理`,
+        toAsVacationDelegate: ({submittedToName, vacationDelegateName}: SubmittedToVacationDelegateParams) => `作为 ${vacationDelegateName} 的休假代理人提交给 ${submittedToName}`,
+        vacationDelegateWarning: ({nameOrEmail}: VacationDelegateParams) =>
             `您正在将 ${nameOrEmail} 设为您的休假代理人。TA 还未加入您所有的工作区。如果继续操作，将会向您所有工作区的管理员发送一封邮件，请他们将 TA 添加进来。`,
     },
     stepCounter: ({step, total, text}: StepCounterParams) => {
@@ -3449,34 +3094,23 @@ ${amount}，商户：${merchant} - 日期：${date}`,
         connectManually: '手动连接',
         desktopConnection: '注意：如需连接 Chase、Wells Fargo、Capital One 或 Bank of America，请点击此处在浏览器中完成此流程。',
         yourDataIsSecure: '您的数据已被安全保护',
-        toGetStarted: '添加一个银行账户，在一个地方报销费用、发放 Expensify 卡、收取发票款项并支付账单。',
+        toGetStarted: '添加一个银行账户，用于报销费用、发放 Expensify 卡、收取发票款项并在同一处支付账单。',
         plaidBodyCopy: '为员工提供更便捷的方式来支付并报销公司费用。',
         checkHelpLine: '您的路由号码和账号可以在该账户的支票上找到。',
-        bankAccountPurposeTitle: '您想用您的银行账户做什么？',
-        getReimbursed: '获得报销',
-        getReimbursedDescription: '由雇主或其他人报销',
-        makePayments: '进行付款',
-        makePaymentsDescription: '支付报销款或发放 Expensify 卡',
         hasPhoneLoginError: (contactMethodRoute: string) =>
             `要连接银行账户，请先<a href="${contactMethodRoute}">添加一个邮箱作为您的主要登录方式</a>，然后重试。您可以将手机号添加为次要登录方式。`,
         hasBeenThrottledError: '添加您的银行账户时出错。请稍等几分钟后重试。',
-        hasCurrencyError: (workspaceRoute: string) => `哎呀！看起来您的工作区货币不是 USD。要继续操作，请前往<a href="${workspaceRoute}">工作区设置</a>将其设置为 USD，然后再试一次。`,
+        hasCurrencyError: ({workspaceRoute}: WorkspaceRouteParams) =>
+            `哎呀！看起来您的工作区货币不是 USD。要继续操作，请前往<a href="${workspaceRoute}">工作区设置</a>将其设置为 USD，然后再试一次。`,
         bbaAdded: '已添加企业银行账户！',
         bbaAddedDescription: '它已准备好用于付款。',
-        lockedBankAccount: '已锁定的银行账户',
-        unlockBankAccount: '解锁银行账户',
-        youCantPayThis: `您无法支付此报告，因为您有一个<a href="${CONST.UNLOCK_BANK_ACCOUNT_HELP_URL}">已锁定的银行账户</a>。请点击下方，礼宾服务将协助您完成解锁步骤。`,
-        htmlUnlockMessage: (maskedAccountNumber: string) =>
-            `<h1>Expensify Business Bank Account ${maskedAccountNumber}</h1><p>感谢您提交解锁银行账户的请求。提款请求可能因余额不足或银行账户未启用直接借记而被拒绝。我们将审核您的情况，如需更多信息来解决此问题，我们会与您联系。</p>`,
-        textUnlockMessage: (maskedAccountNumber: string) =>
-            `Expensify Business Bank Account ${maskedAccountNumber}\n感谢您提交解锁银行账户的请求。提款请求可能因余额不足或银行账户未启用直接借记而被拒绝。我们将审核您的情况，如需更多信息来解决此问题，我们会与您联系。`,
         error: {
             youNeedToSelectAnOption: '请选择一个选项以继续',
             noBankAccountAvailable: '抱歉，没有可用的银行账户',
             noBankAccountSelected: '请选择一个账户',
             taxID: '请输入有效的税号',
             website: '请输入有效的网站',
-            zipCode: `请输入有效的邮政编码，格式为：${COMMON_CONST.COUNTRY_ZIP_REGEX_DATA.US.samples}`,
+            zipCode: `请输入有效的邮政编码，格式为：${CONST.COUNTRY_ZIP_REGEX_DATA.US.samples}`,
             phoneNumber: '请输入有效的电话号码',
             email: '请输入有效的邮箱地址',
             companyName: '请输入有效的公司名称',
@@ -3502,7 +3136,7 @@ ${amount}，商户：${merchant} - 日期：${date}`,
             validationAmounts: '您输入的验证金额不正确。请仔细核对您的银行对账单后再试一次。',
             fullName: '请输入有效的全名',
             ownershipPercentage: '请输入有效的百分比数字',
-            deletePaymentBankAccount: '此银行账户无法删除，因为它被用于 Expensify 卡付款。如果您仍希望删除此账户，请联系 Concierge。',
+            deletePaymentBankAccount: '此银行账户无法删除，因为它用于 Expensify Card 付款。如果您仍希望删除此账户，请联系 Concierge。',
             sameDepositAndWithdrawalAccount: '存款账户和取款账户相同。',
         },
     },
@@ -3517,11 +3151,6 @@ ${amount}，商户：${merchant} - 日期：${date}`,
         confirmationStepHeader: '请检查您的信息。',
         confirmationStepSubHeader: '请仔细核对以下详细信息，并勾选条款复选框以确认。',
         toGetStarted: '添加个人银行账户以接收报销、支付发票或启用 Expensify 钱包。',
-        updatePersonalInfo: '更新银行账户',
-        updatePersonalInfoFailure: '无法更新银行账户信息。请稍后重试。',
-        updateSuccessTitle: '银行账户已更新!',
-        updateSuccessHeader: '银行账户已更新',
-        updateSuccessMessage: '恭喜,您的银行账户已设置完成,可以开始接收报销款了。',
     },
     addPersonalBankAccountPage: {
         enterPassword: '输入 Expensify 密码',
@@ -3549,8 +3178,8 @@ ${amount}，商户：${merchant} - 日期：${date}`,
     messages: {
         errorMessageInvalidPhone: `请输入有效的电话号码，不要包含括号或短横线。如果您在美国境外，请包含您的国家代码（例如：${CONST.EXAMPLE_PHONE_NUMBER}）。`,
         errorMessageInvalidEmail: '电子邮箱无效',
-        userIsAlreadyMember: (login: string, name: string) => `${login} 已经是 ${name} 的成员`,
-        userIsAlreadyAnAdmin: (login: string, name: string) => `${login} 已经是 ${name} 的管理员了`,
+        userIsAlreadyMember: ({login, name}: UserIsAlreadyMemberParams) => `${login} 已经是 ${name} 的成员`,
+        userIsAlreadyAnAdmin: ({login, name}: UserIsAlreadyMemberParams) => `${login} 已经是 ${name} 的管理员了`,
     },
     onfidoStep: {
         acceptTerms: '继续申请激活您的 Expensify 钱包，即表示您确认已阅读、理解并接受',
@@ -3594,7 +3223,7 @@ ${amount}，商户：${merchant} - 日期：${date}`,
         haveReadAndAgreePlain: '我已阅读并同意接收电子披露文件。',
         haveReadAndAgree: `我已阅读并同意接收<a href="${CONST.ELECTRONIC_DISCLOSURES_URL}">电子披露文件</a>。`,
         agreeToThePlain: '我同意《隐私和钱包协议》。',
-        agreeToThe: (walletAgreementUrl: string) => `我同意<a href="${CONST.OLD_DOT_PUBLIC_URLS.PRIVACY_URL}">隐私政策</a>和<a href="${walletAgreementUrl}">钱包协议</a>。`,
+        agreeToThe: ({walletAgreementUrl}: WalletAgreementParams) => `我同意<a href="${CONST.OLD_DOT_PUBLIC_URLS.PRIVACY_URL}">隐私政策</a>和<a href="${walletAgreementUrl}">钱包协议</a>。`,
         enablePayments: '启用付款',
         monthlyFee: '月费',
         inactivity: '不活跃',
@@ -3605,7 +3234,7 @@ ${amount}，商户：${merchant} - 日期：${date}`,
         checkTheBoxes: '请勾选下面的复选框。',
         agreeToTerms: '同意条款后，你就可以开始使用了！',
         shortTermsForm: {
-            expensifyPaymentsAccount: (walletProgram: string) => `Expensify 钱包由 ${walletProgram} 发行。`,
+            expensifyPaymentsAccount: ({walletProgram}: WalletProgramParams) => `Expensify 钱包由 ${walletProgram} 发行。`,
             perPurchase: '按次购买',
             atmWithdrawal: 'ATM 取款',
             cashReload: '现金充值',
@@ -3619,7 +3248,7 @@ ${amount}，商户：${merchant} - 日期：${date}`,
             generalInfo: `有关预付账户的一般信息，请访问 <a href="${CONST.CFPB_PREPAID_URL}">${CONST.TERMS.CFPB_PREPAID}</a>。`,
             conditionsDetails: `有关所有费用和服务的详细信息和条款，请访问 <a href="${CONST.FEES_URL}">${CONST.FEES_URL}</a> 或致电 +1 833-400-0904。`,
             electronicFundsWithdrawalInstant: '电子资金取款（即时）',
-            electronicFundsInstantFeeMin: (amount: string) => `（最低 ${amount}）`,
+            electronicFundsInstantFeeMin: ({amount}: TermsParams) => `（最低 ${amount}）`,
         },
         longTermsForm: {
             listOfAllFees: '所有 Expensify 电子钱包费用列表',
@@ -3638,7 +3267,7 @@ ${amount}，商户：${merchant} - 日期：${date}`,
             electronicFundsInstantDetails: (percentage: string, amount: string) =>
                 '使用即时转账选项将资金从您的 Expensify 钱包转入已关联的借记卡需要支付手续费。此类转账通常会在几分钟内完成。' +
                 `手续费为转账金额的 ${percentage}%，（最低收费为 ${amount}）。`,
-            fdicInsuranceBancorp: (amount: string) =>
+            fdicInsuranceBancorp: ({amount}: TermsParams) =>
                 `您的资金符合 FDIC 保险资格。您的资金将被存放在或转移至 ${CONST.WALLET.PROGRAM_ISSUERS.BANCORP_BANK}，这是一家受 FDIC 保险保障的机构。` +
                 `在资金存入后，如满足特定存款保险要求并已为您的卡片完成注册，在${CONST.WALLET.PROGRAM_ISSUERS.BANCORP_BANK}倒闭的情况下，您的资金将由 FDIC 为您提供最高 ${amount} 的保险保障。详情请参阅 ${CONST.TERMS.FDIC_PREPAID}。`,
             contactExpensifyPayments: `请通过拨打 +1 833-400-0904、发送电子邮件至 ${CONST.EMAIL.CONCIERGE}，或登录 ${CONST.NEW_EXPENSIFY_URL} 联系 ${CONST.WALLET.PROGRAM_ISSUERS.EXPENSIFY_PAYMENTS}。`,
@@ -3647,7 +3276,7 @@ ${amount}，商户：${merchant} - 日期：${date}`,
             automated: '自动处理',
             liveAgent: '人工客服',
             instant: '即时',
-            electronicFundsInstantFeeMin: (amount: string) => `最低 ${amount}`,
+            electronicFundsInstantFeeMin: ({amount}: TermsParams) => `最低 ${amount}`,
         },
     },
     activateStep: {
@@ -3930,10 +3559,6 @@ ${amount}，商户：${merchant} - 日期：${date}`,
         youCanChange: '您可以在您的中更改工作区货币',
         findCountry: '查找国家',
         selectCountry: '选择国家',
-        error: {
-            connectToWorkspace: (workspaceRoute: string) =>
-                `此银行账户必须关联到工作区。请前往<a href="${workspaceRoute}">工作区</a>，选择您的工作区，然后导航至工作流 > 付款 > 添加银行账户。`,
-        },
     },
     bankInfoStep: {
         whatAreYour: '您的企业银行账户信息是什么？',
@@ -3977,7 +3602,7 @@ ${amount}，商户：${merchant} - 日期：${date}`,
         pleaseUpload: '请在下方上传更多证明文件，以帮助我们核实您作为该企业董事的身份。',
         enterSignerInfo: '输入签署人信息',
         thisStep: '此步骤已完成',
-        isConnecting: (bankAccountLastFour: string | undefined, currency: string | undefined) =>
+        isConnecting: ({bankAccountLastFour, currency}: SignerInfoMessageParams) =>
             `正在连接一 个以 ${bankAccountLastFour} 结尾的 ${currency} 企业银行账户到 Expensify，以便以 ${currency} 支付员工。下一步需要一位董事的签署人信息。`,
         error: {
             emailsMustBeDifferent: '电子邮箱地址必须不同',
@@ -3989,7 +3614,7 @@ ${amount}，商户：${merchant} - 日期：${date}`,
         regulationRequiresUs: '法规要求我们核实任何持有该企业超过 25% 股权的个人身份。',
         iAmAuthorized: '我已被授权使用该公司银行账户进行业务支出。',
         iCertify: '本人证明所提供的信息真实且准确。',
-        iAcceptTheTermsAndConditions: `我接受<a href="https://www.corpay.com/cross-border/terms">条款和条件</a>。`,
+        iAcceptTheTermsAndConditions: `我接受<a href="https://cross-border.corpay.com/tc/">条款和条件</a>。`,
         iAcceptTheTermsAndConditionsAccessibility: '我接受条款和条件。',
         accept: '接受并添加银行账户',
         iConsentToThePrivacyNotice: '我同意<a href="https://payments.corpay.com/compliance">隐私声明</a>。',
@@ -4018,37 +3643,6 @@ ${amount}，商户：${merchant} - 日期：${date}`,
         weTake: '我们非常重视您的安全。请立即设置双重验证，为您的账户增加一层额外保护。',
         secure: '保护你的账户',
     },
-    documentsStep: {
-        beforeYouGo: '在继续之前，我们需要一些文件来验证相关信息',
-        subheader: '验证',
-        verificationFailed: '验证失败，因此我们需要额外的文件来验证你及你的企业',
-        taxIDVerification: '税务识别号验证',
-        taxIDVerificationDescription: dedent(`
-        请上传以下任一文件：
-        • IRS TIN/EIN 分配函
-        • IRS TIN/EIN 申请确认函（通常包含“Congratulations! The EIN has been successfully assigned”）
-        • 显示公司名称和 EIN 的 IRS 免税函`),
-        nameChangeDocument: '名称变更文件',
-        nameChangeDocumentDescription: '如果你的公司名称在申请 TIN/EIN 后发生更改，我们需要此文件来验证你提供的税务识别号',
-        companyAddressVerification: '公司地址验证',
-        companyAddressVerificationDescription: dedent(`
-        请上传以下任一文件：
-        • 显示公司名称和地址的近期水电账单
-        • 显示公司名称和地址的银行对账单
-        • 包含签字页的有效租赁协议，显示公司名称和当前地址
-        • 显示公司名称和地址的保险声明
-        • 显示公司名称和地址的 TIN 分配文件`),
-        userAddressVerification: '地址验证',
-        userAddressVerificationDescription: dedent(`
-        请上传以下任一文件：
-        • 选民登记卡
-        • 驾驶证
-        • 银行对账单
-        • 水电账单`),
-        userDOBVerification: '出生日期验证',
-        userDOBVerificationDescription: '请上传美国签发的身份证件',
-        finishViaChat: '通过聊天完成',
-    },
     reimbursementAccountLoadingAnimation: {
         oneMoment: '请稍候',
         explanationLine: '我们正在查看您的信息。您很快就可以继续进行下一步了。',
@@ -4183,14 +3777,14 @@ ${amount}，商户：${merchant} - 日期：${date}`,
             flightSeatChanged: (airlineCode: string) => `您在航班 ${airlineCode} 上的座位已被更改。`,
             flightSeatCancelled: (airlineCode: string) => `您在航班 ${airlineCode} 上的座位分配已被移除。`,
             paymentDeclined: '您的机票预订付款失败。请重试。',
-            bookingCancelledByTraveler: (type: string, id = '') => `您已取消您的${type}预订 ${id}。`,
-            bookingCancelledByVendor: (type: string, id = '') => `供应商已取消您的${type}预订 ${id}。`,
-            bookingRebooked: (type: string, id = '') => `您的${type}预订已重新预订。新的确认号：${id}。`,
-            bookingUpdated: (type: string) => `您的${type}预订已更新。请在行程中查看新的详细信息。`,
+            bookingCancelledByTraveler: ({type, id = ''}: TravelTypeParams) => `您已取消您的${type}预订 ${id}。`,
+            bookingCancelledByVendor: ({type, id = ''}: TravelTypeParams) => `供应商已取消您的${type}预订 ${id}。`,
+            bookingRebooked: ({type, id = ''}: TravelTypeParams) => `您的${type}预订已重新预订。新的确认号：${id}。`,
+            bookingUpdated: ({type}: TravelTypeParams) => `您的${type}预订已更新。请在行程中查看新的详细信息。`,
             railTicketRefund: (origin: string, destination: string, startDate: string) => `您从${origin}前往${destination}的${startDate}火车票已退款。将为您处理一笔抵扣款。`,
             railTicketExchange: (origin: string, destination: string, startDate: string) => `您从 ${origin} 到 ${destination} 的 ${startDate} 火车票已成功改签。`,
             railTicketUpdate: (origin: string, destination: string, startDate: string) => `您在 ${startDate} 从 ${origin} 前往 ${destination} 的火车票已更新。`,
-            defaultUpdate: (type: string) => `您的${type}预订已更新。`,
+            defaultUpdate: ({type}: TravelTypeParams) => `您的${type}预订已更新。`,
         },
         flightTo: '飞往',
         trainTo: '火车前往',
@@ -4207,13 +3801,13 @@ ${amount}，商户：${merchant} - 日期：${date}`,
             workflows: '工作流程',
             workspace: '工作区',
             findWorkspace: '查找工作区',
-            findRoom: '查找房间',
             edit: '编辑工作区',
             enabled: '已启用',
             disabled: '已禁用',
             everyone: '所有人',
             delete: '删除工作区',
             settings: '设置',
+            reimburse: '报销',
             categories: '类别',
             tags: '标签',
             customField1: '自定义字段 1',
@@ -4221,7 +3815,6 @@ ${amount}，商户：${merchant} - 日期：${date}`,
             customFieldHint: '为该成员的所有支出添加适用的自定义编码。',
             reports: '报表',
             reportFields: '报表字段',
-            invoiceFields: '发票字段',
             reportTitle: '报表标题',
             reportField: '报表字段',
             taxes: '税费',
@@ -4250,9 +3843,6 @@ ${amount}，商户：${merchant} - 日期：${date}`,
             defaultNote: `发送到 ${CONST.EMAIL.RECEIPTS} 的收据将显示在此工作区中。`,
             deleteConfirmation: '确定要删除此工作区吗？',
             deleteWithCardsConfirmation: '确定要删除此工作区吗？这将移除所有卡片数据源和已分配的卡片。',
-            deleteOpenExpensifyCardsError: '您的公司仍有未关闭的 Expensify 卡。',
-            outstandingBalanceWarning: '您有一笔未结清的余额，必须在删除最后一个工作区之前结清。请前往订阅设置以解决付款问题。',
-            settleBalance: '前往订阅',
             unavailable: '工作区不可用',
             memberNotFound: '未找到成员。要邀请新成员加入此工作区，请使用上方的邀请按钮。',
             notAuthorized: `您无权访问此页面。如果您正尝试加入此工作区，请联系工作区所有者将您添加为成员。还有其他问题？请联系 ${CONST.EMAIL.CONCIERGE}。`,
@@ -4263,11 +3853,8 @@ ${amount}，商户：${merchant} - 日期：${date}`,
             clearFilter: '清除筛选器',
             workspaceName: '工作区名称',
             workspaceOwner: '所有者',
-            keepMeAsAdmin: '保留我为管理员',
             workspaceType: '工作区类型',
             workspaceAvatar: '工作区头像',
-            clientID: '客户ID',
-            clientIDInputHint: '请输入客户的唯一标识符',
             mustBeOnlineToViewMembers: '您需要联网才能查看此工作区的成员。',
             moreFeatures: '更多功能',
             requested: '已请求',
@@ -4286,7 +3873,7 @@ ${amount}，商户：${merchant} - 日期：${date}`,
             appliedOnExport: '未导入 Expensify，在导出时应用',
             shareNote: {
                 header: '与其他成员共享你的工作区',
-                content: (adminsRoomLink: string) =>
+                content: ({adminsRoomLink}: WorkspaceShareNoteParams) =>
                     `将此二维码分享给他人或复制下方链接，方便成员请求访问你的工作区。所有加入工作区的请求都会显示在 <a href="${adminsRoomLink}">${CONST.REPORT.WORKSPACE_CHAT_ROOMS.ADMINS}</a> 聊天室中，供你审核。`,
             },
             connectTo: ({connectionName}: ConnectionNameParams) => `连接到 ${CONST.POLICY.CONNECTIONS.NAME_USER_FRIENDLY[connectionName]}`,
@@ -4301,20 +3888,12 @@ ${amount}，商户：${merchant} - 日期：${date}`,
             memberAlternateText: '提交并审批报销报告。',
             adminAlternateText: '管理报表和工作区设置。',
             auditorAlternateText: '查看并评论报表。',
-            roleName: (role?: string) => {
+            roleName: ({role}: OptionalParam<RoleNamesParams> = {}) => {
                 switch (role) {
                     case CONST.POLICY.ROLE.ADMIN:
-                        return '工作区管理员';
+                        return '管理员';
                     case CONST.POLICY.ROLE.AUDITOR:
                         return '审计员';
-                    case CONST.POLICY.ROLE.EDITOR:
-                        return '编辑';
-                    case CONST.POLICY.ROLE.CARD_ADMIN:
-                        return '卡片管理员';
-                    case CONST.POLICY.ROLE.PEOPLE_ADMIN:
-                        return '人员管理员';
-                    case CONST.POLICY.ROLE.PAYMENTS_ADMIN:
-                        return '付款管理员';
                     case CONST.POLICY.ROLE.USER:
                         return '成员';
                     default:
@@ -4343,22 +3922,7 @@ ${amount}，商户：${merchant} - 日期：${date}`,
             budgetFrequencyUnit: {monthly: '月', yearly: '年'},
             budgetTypeForNotificationMessage: {tag: '标签', category: '类别'},
             policyExpenseChatName: (displayName: string) => `${displayName} 的报销费用`,
-            deepDiveExpensifyCard: `<muted-text-label>Expensify 卡交易将自动导出到使用<a href="${CONST.DEEP_DIVE_EXPENSIFY_CARD}">我们的集成</a>创建的“Expensify 卡负债账户”。</muted-text-label>`,
-            travelInvoicing: '将差旅开票费用导出为',
-            travelInvoicingVendor: '差旅供应商',
-            travelInvoicingPayableAccount: '差旅应付账户',
-            hr: '人力资源',
-            rooms: '房间',
-            findDomain: '查找域名',
-            cardAdminAlternateText: '管理工作区卡片。',
-            peopleAdminAlternateText: '管理成员和审批流程。',
-            paymentsAdminAlternateText: '管理工作流付款。',
-            readOnlyActionTitle: '别急……',
-            readOnlyActionPrompt: '你的工作区角色可以查看这些设置，但不能编辑。',
-        },
-        createdForClient: {
-            title: '您已为客户创建了工作区！',
-            description: '好消息 🎉。如果他们在设置方面需要帮助，请联系我们。',
+            deepDiveExpensifyCard: `<muted-text-label>Expensify Card 交易将通过<a href="${CONST.DEEP_DIVE_EXPENSIFY_CARD}">我们的集成</a>自动导出到一个名为“Expensify Card Liability Account”的账户中。</muted-text-label>`,
         },
         receiptPartners: {
             uber: {
@@ -4573,8 +4137,7 @@ ${amount}，商户：${merchant} - 日期：${date}`,
             notConfigured: '未配置',
             bankAccountDescription: '选择从哪里寄送支票。',
             creditCardAccount: '信用卡账户',
-            travelInvoicingDescription: '差旅费用将作为信用卡费用导出到下面指定的 QuickBooks Online 账户。',
-            companyCardsLocationEnabledDescription: '当地点作为标签导入时，QuickBooks Online 不支持在供应商账单导出中使用地点。由于你的工作区中已将地点作为标签导入，因此此导出选项不可用。',
+            companyCardsLocationEnabledDescription: 'QuickBooks Online 不支持在供应商账单导出中使用地点。由于您在工作区中启用了地点功能，该导出选项不可用。',
             outOfPocketTaxEnabledDescription: 'QuickBooks Online 不支持在日记账分录导出中包含税费。由于你已在工作区中启用税费功能，因此无法使用此导出选项。',
             outOfPocketTaxEnabledError: '启用税费时无法使用日记账分录。请选择其他导出选项。',
             advancedConfig: {
@@ -4662,7 +4225,6 @@ ${amount}，商户：${merchant} - 日期：${date}`,
             purchaseBill: '采购账单',
             exportDeepDiveCompanyCard: '导出的报销将作为银行交易记入下方的 Xero 银行账户，且交易日期将与您的银行对账单上的日期一致。',
             bankTransactions: '银行交易',
-            travelInvoicingDescription: '差旅费用将作为银行交易导出到下面指定的 Xero 账户。',
             xeroBankAccount: 'Xero 银行账户',
             xeroBankAccountDescription: '选择报销费用将作为银行交易入账的位置。',
             exportExpensesDescription: '报表将按照在下方选择的日期和状态导出为采购账单。',
@@ -4757,7 +4319,6 @@ ${amount}，商户：${merchant} - 日期：${date}`,
                     [CONST.SAGE_INTACCT_NON_REIMBURSABLE_EXPENSE_TYPE.VENDOR_BILL]: '供应商账单',
                 },
             },
-            travelInvoicingDescription: '差旅费用将作为信用卡费用导出到下面指定的 Sage Intacct 账户。',
             creditCardAccount: '信用卡账户',
             defaultVendor: '默认供应商',
             defaultVendorDescription: (isReimbursable: boolean) => `为没有在 Sage Intacct 中匹配供应商的${isReimbursable ? '' : '非'}可报销费用设置一个默认供应商。`,
@@ -4786,62 +4347,6 @@ ${amount}，商户：${merchant} - 日期：${date}`,
                 },
             },
         },
-        certinia: {
-            title: 'Certinia',
-            titleFFA: 'Certinia (FFA)',
-            autoSyncDescription: 'Expensify 将每天自动与 Certinia 同步。',
-            syncReimbursedReportsDescription: '启用此选项后，每当在 FFA 中支付应付发票时，关联的 Expensify 报告将自动标记为已报销。',
-            exportDescription: '配置 Expensify 数据导出到 Certinia 的方式。',
-            payableInvoices: '应付发票',
-            exportStatus: {
-                label: '应付发票状态',
-                values: {
-                    [CONST.CERTINIA_EXPORT_STATUS.APPROVED]: '完成',
-                    [CONST.CERTINIA_EXPORT_STATUS.IN_PROGRESS]: '进行中',
-                    [CONST.CERTINIA_EXPORT_STATUS.SUBMITTED]: '已提交',
-                },
-            },
-            exportDate: {
-                label: '应付发票日期',
-                values: {
-                    [CONST.CERTINIA_EXPORT_DATE.LAST_EXPENSE]: '上次报销日期',
-                    [CONST.CERTINIA_EXPORT_DATE.REPORT_SUBMITTED]: '报表提交日期',
-                    [CONST.CERTINIA_EXPORT_DATE.REPORT_EXPORTED]: '导出日期',
-                },
-            },
-            exportReimbursable: {label: '导出可报销费用为', helperText: '标记为可报销的费用将作为应付账单导出，并开具给员工。'},
-            exportNonReimbursable: {label: '将不可报销的报销单导出为'},
-            noVendorsFound: '未找到供应商',
-            noVendorsFoundDescription: '在 Certinia 中添加供应商后，请再次同步连接。',
-            prerequisites: {
-                title: '在你连接之前',
-                installBundle: '用于 FFA 连接',
-                installBundleDescription: ({href, version}: {href: string; version: string}) =>
-                    `通过点击此链接在 Salesforce 中安装 Expensify 组件包：<a href="${href}">安装 FFA Expensify 组件包（版本 ${version}）</a>`,
-                installBundleConfirm: '我已安装此捆绑包',
-                setupContacts: '设置用户和联系人',
-                setupContactsBullet1: '如果 Certinia 中尚未为你创建用户和联系人，请为自己分别创建一个用户和一个联系人，并确保其电子邮箱与你在 Expensify 中的主要邮箱一致。',
-                setupContactsBullet2: '为每位将提交报销报告的员工以及每位报销审批人创建联系人。请确保每个联系人的电子邮箱地址与该员工的 Expensify 账户中的邮箱地址一致。',
-                setupContactsBullet3: '为每位联系人/资源设置用户的权限控制。',
-                setupContactsConfirm: '我已设置用户和联系人',
-                oauth: '通过 Salesforce 登录',
-                oauthDescription: '要完成设置，您需要通过 Salesforce 和 Certinia 登录。\n\n请使用下方按钮继续。',
-                connectButton: '连接到 Certinia',
-            },
-            import: {
-                chartOfAccounts: '会计科目表',
-                chartOfAccountsDescription: '会计科目表会作为类别导入 Expensify。',
-                dimensionMapping: ({n}: {n: number}) => `维度 ${n}`,
-                dimensions: {dimension1: '维度 1', dimension2: '维度 2', dimension3: '维度 3', dimension4: '维度 4'},
-                doNotMap: '不要映射',
-                doNotMapSubtitle: '默认使用员工资源',
-                mappingTypes: {
-                    [CONST.CERTINIA_MAPPING_VALUE.DEFAULT]: '不要映射',
-                    [CONST.CERTINIA_MAPPING_VALUE.TAG]: '已作为标签导入',
-                    [CONST.CERTINIA_MAPPING_VALUE.REPORT_FIELD]: '已作为报表字段导入',
-                },
-            },
-        },
         netsuite: {
             subsidiary: '子公司',
             subsidiarySelectDescription: '选择要从中导入数据的 NetSuite 子公司。',
@@ -4856,8 +4361,8 @@ ${amount}，商户：${merchant} - 日期：${date}`,
             journalPostingPreference: {
                 label: '日记账分录过账偏好',
                 values: {
-                    [CONST.NETSUITE_JOURNAL_POSTING_PREFERENCE.JOURNALS_POSTING_INDIVIDUAL_LINE]: '每笔报销仅一条记录',
-                    [CONST.NETSUITE_JOURNAL_POSTING_PREFERENCE.JOURNALS_POSTING_TOTAL_LINE]: '每份报表使用单一分项明细记录',
+                    [CONST.NETSUITE_JOURNAL_POSTING_PREFERENCE.JOURNALS_POSTING_INDIVIDUAL_LINE]: '每个报表使用单独的分项条目',
+                    [CONST.NETSUITE_JOURNAL_POSTING_PREFERENCE.JOURNALS_POSTING_TOTAL_LINE]: '每笔报销一条记录',
                 },
             },
             invoiceItem: {
@@ -4923,7 +4428,6 @@ ${amount}，商户：${merchant} - 日期：${date}`,
 
                             如果你希望为每张卡设置特定供应商，请前往 *设置 > 域 > 公司卡*。
                         `),
-                        travelDescription: '差旅报销将作为日记账分录导出到下方指定的 NetSuite 账户。',
                     },
                 },
                 expenseReportDestinationConfirmDescription:
@@ -5061,7 +4565,7 @@ ${amount}，商户：${merchant} - 日期：${date}`,
                 importCustomFields: {
                     chooseOptionBelow: '请选择以下选项：',
                     label: (importedTypes: string[]) => `已作为 ${importedTypes.join('和')} 导入`,
-                    requiredFieldError: (fieldName: string) => `请输入${fieldName}`,
+                    requiredFieldError: ({fieldName}: RequiredFieldParams) => `请输入${fieldName}`,
                     customSegments: {
                         title: '自定义分类/记录',
                         addText: '添加自定义分段/记录',
@@ -5114,13 +4618,13 @@ _如需更详细的说明，请[访问我们的帮助网站](${CONST.NETSUITE_IM
 
 _如需更详细的说明，请[访问我们的帮助网站](${CONST.NETSUITE_IMPORT.HELP_LINKS.CUSTOM_SEGMENTS})_。`,
                             customSegmentScriptIDTitle: '脚本 ID 是什么？',
-                            customSegmentScriptIDFooter: `您可以在 NetSuite 中通过以下路径找到自定义段脚本 ID：
+                            customSegmentScriptIDFooter: `您可以在 NetSuite 中通过以下路径找到自定义段脚本 ID：  
 
-1. 进入 *Customization > Lists, Records, & Fields > Custom Segments*。
-2. 点击进入某个自定义段。
-3. 在页面底部附近点击 *Application and Sourcing* 选项卡，然后：
-   a. 如果您希望在 Expensify 中将自定义段显示为*标签*（行项目级别），请点击 *Transaction Columns* 子选项卡，并使用其中的 *Field ID*。
-   b. 如果您希望在 Expensify 中将自定义段显示为*报表字段*（报表级别），请点击 *Transactions* 子选项卡，并使用其中的 *Field ID*。
+1. 进入 *Customization > Lists, Records, & Fields > Custom Segments*。  
+2. 点击进入某个自定义段。  
+3. 在页面底部附近点击 *Application and Sourcing* 选项卡，然后：  
+   a. 如果您希望在 Expensify 中将自定义段显示为*标签*（行项目级别），请点击 *Transaction Columns* 子选项卡，并使用其中的 *Field ID*。  
+   b. 如果您希望在 Expensify 中将自定义段显示为*报表字段*（报表级别），请点击 *Transactions* 子选项卡，并使用其中的 *Field ID*。  
 
 _如需更详细的说明，[请访问我们的帮助网站](${CONST.NETSUITE_IMPORT.HELP_LINKS.CUSTOM_LISTS})_。`,
                             customRecordScriptIDTitle: '交易列的 ID 是什么？',
@@ -5135,7 +4639,7 @@ _如需更详细的说明，请[访问我们的帮助网站](${CONST.NETSUITE_IM
                             customRecordMappingTitle: '此自定义记录应在 Expensify 中如何显示？',
                         },
                         errors: {
-                            uniqueFieldError: (fieldName: string) => `已存在使用此 ${fieldName?.toLowerCase()} 的自定义分段/记录`,
+                            uniqueFieldError: ({fieldName}: RequiredFieldParams) => `已存在使用此 ${fieldName?.toLowerCase()} 的自定义分段/记录`,
                         },
                     },
                     customLists: {
@@ -5201,7 +4705,7 @@ _如需更详细的说明，请[访问我们的帮助网站](${CONST.NETSUITE_IM
             employeeDefaultDescription: '如果员工在 Sage Intacct 中设有默认部门，该部门将应用于其报销。',
             displayedAsTagDescription: '在员工报表中的每笔费用上都可以选择部门。',
             displayedAsReportFieldDescription: '部门选择将应用于员工报表中的所有报销。',
-            toggleImportTitle: (mappingTitle: string) => `选择在 Expensify 中如何处理 Sage Intacct <strong>${mappingTitle}</strong>。`,
+            toggleImportTitle: ({mappingTitle}: ToggleImportTitleParams) => `选择在 Expensify 中如何处理 Sage Intacct <strong>${mappingTitle}</strong>。`,
             expenseTypes: '报销类型',
             expenseTypesDescription: '您的 Sage Intacct 费用类型将作为类别导入到 Expensify 中。',
             accountTypesDescription: '您的 Sage Intacct 科目表将作为类别导入到 Expensify 中。',
@@ -5241,14 +4745,10 @@ _如需更详细的说明，请[访问我们的帮助网站](${CONST.NETSUITE_IM
             free: '免费',
             control: '控制',
             collect: '收款',
-            submit: '提交',
         },
         companyCards: {
             addCards: '添加卡片',
             selectCards: '选择卡片',
-            fromOtherWorkspaces: '来自其他工作区',
-            addWorkEmail: '添加您的工作邮箱',
-            addWorkEmailDescription: '请添加您的工作邮箱以使用其他工作区的现有流水。',
             error: {
                 workspaceFeedsCouldNotBeLoadedTitle: '无法加载卡片流水',
                 workspaceFeedsCouldNotBeLoadedMessage: '加载工作区卡片动态时发生错误。请重试或联系管理员。',
@@ -5258,11 +4758,6 @@ _如需更详细的说明，请[访问我们的帮助网站](${CONST.NETSUITE_IM
             },
             addNewCard: {
                 other: '其他',
-                fileImport: '从文件导入交易',
-                createFileFeedHelpText: `<muted-text>请按照此<a href="${CONST.COMPANY_CARDS_CREATE_FILE_FEED_HELP_URL}">帮助指南</a>操作，将您的公司卡费用导入！</muted-text>`,
-                companyCardLayoutName: '公司卡片布局名称',
-                cardLayoutNameRequired: '公司卡片布局名称是必填的',
-                useAdvancedFields: '使用高级字段（不推荐）',
                 cardProviders: {
                     gl1025: 'American Express 公司卡',
                     cdf: '万事达商业卡',
@@ -5340,26 +4835,6 @@ _如需更详细的说明，请[访问我们的帮助网站](${CONST.NETSUITE_IM
                     confirmText: '报告问题',
                     cancelText: '跳过',
                 },
-                csvColumns: {
-                    cardNumber: '卡号',
-                    postedDate: '日期',
-                    merchant: '商家',
-                    amount: '金额',
-                    currency: '货币',
-                    ignore: '忽略',
-                    originalTransactionDate: '原始交易日期',
-                    originalAmount: '原始金额',
-                    originalCurrency: '原始货币',
-                    comment: '评论',
-                    category: '类别',
-                    tag: '标签',
-                },
-                csvErrors: {
-                    requiredColumns: (missingColumns: string) => `请为以下每个属性分配一列：${missingColumns}`,
-                    duplicateColumns: (duplicateColumn: string) => `哎呀！你已将单个字段（“${duplicateColumn}”）映射到了多个列。请检查后重试。`,
-                },
-                fileImportDescription: '如果您的银行无法发送数据馈送时的手动选项。',
-                duplicateFeedModal: {title: '卡片流水已连接', prompt: '您不能将同一张卡片流水两次添加到同一个工作区。'},
             },
             statementCloseDate: {
                 [CONST.COMPANY_CARDS.STATEMENT_CLOSE_DATE.LAST_DAY_OF_MONTH]: '月末最后一天',
@@ -5377,7 +4852,7 @@ _如需更详细的说明，请[访问我们的帮助网站](${CONST.NETSUITE_IM
             chooseTheCardholder: '选择持卡人',
             chooseCard: '选择一张卡片',
             chooseCardFor: (assignee: string) => `为 <strong>${assignee}</strong> 选择一张卡片。找不到需要的卡片？<concierge-link>告诉我们。</concierge-link>`,
-            noActiveCards: '此信息源中没有活动卡片',
+            noActiveCards: '此订阅源中没有可用的卡片',
             somethingMightBeBroken:
                 '<muted-text><centered-text>或者可能出了点问题。不管怎样，如果你有任何疑问，请<concierge-link>联系 Concierge</concierge-link>。</centered-text></muted-text>',
             chooseTransactionStartDate: '选择交易开始日期',
@@ -5409,14 +4884,12 @@ _如需更详细的说明，请[访问我们的帮助网站](${CONST.NETSUITE_IM
                 flipAmountSign: '翻转金额符号',
                 importButton: '导入交易',
             },
-            deletedCard: '已删除的卡片',
-            assignNewCards: {title: '分配新卡', description: '从您的银行获取可分配的最新银行卡'},
         },
         expensifyCard: {
-            issueAndManageCards: '发放并管理您的 Expensify 卡',
+            issueAndManageCards: '发放和管理您的 Expensify 卡片',
             getStartedIssuing: '从发放您的第一张虚拟卡或实体卡开始使用。',
             verificationInProgress: '正在验证中…',
-            verifyingTheDetails: '我们正在核实一些信息。Expensify 卡可以发行时，Concierge 会通知你。',
+            verifyingTheDetails: '我们正在核实一些详细信息。Concierge 会在 Expensify 卡可以发放时通知你。',
             disclaimer:
                 'Expensify Visa® 商务卡由 The Bancorp Bank, N.A. 发行，该银行是美国联邦存款保险公司（FDIC）成员，依据 Visa U.S.A. Inc. 的许可发行，且可能无法在所有接受 Visa 卡的商户处使用。Apple® 和 Apple 标志® 是 Apple Inc. 在美国及其他国家注册的商标。App Store 是 Apple Inc. 的服务标志。Google Play 和 Google Play 标志是 Google LLC 的商标。',
             euUkDisclaimer:
@@ -5428,8 +4901,8 @@ _如需更详细的说明，请[访问我们的帮助网站](${CONST.NETSUITE_IM
             lastFour: '最后 4 位',
             limit: '限额',
             currentBalance: '当前余额',
-            currentBalanceDescription: '当前余额是上次结算日期以来已入账的所有 Expensify 卡交易的总和。',
-            balanceWillBeSettledOn: (settlementDate: string) => `余额将于 ${settlementDate} 结清`,
+            currentBalanceDescription: '当前余额是自上次结算日期以来所有已入账 Expensify Card 交易的总和。',
+            balanceWillBeSettledOn: ({settlementDate}: SettlementDateParams) => `余额将于 ${settlementDate} 结清`,
             settleBalance: '结清余额',
             cardLimit: '卡片限额',
             remainingLimit: '剩余额度',
@@ -5437,27 +4910,26 @@ _如需更详细的说明，请[访问我们的帮助网站](${CONST.NETSUITE_IM
             remainingLimitDescription:
                 '在计算您的剩余额度时，我们会考虑多个因素：您作为客户的合作年限、您在注册过程中提供的与业务相关的信息，以及您企业银行账户中的可用现金。您的剩余额度可能会每天发生变化。',
             earnedCashback: '返现',
-            earnedCashbackDescription: '返现余额基于您工作区内每月已结算的 Expensify 卡消费金额计算。',
+            earnedCashbackDescription: '返现余额基于您工作区内每月已结算的 Expensify Card 消费金额。',
             issueNewCard: '发新卡',
             finishSetup: '完成设置',
             chooseBankAccount: '选择银行账户',
-            chooseExistingBank: '选择一个现有的企业银行账户来支付您的 Expensify 卡余额，或添加一个新的银行账户',
+            chooseExistingBank: '选择一个现有的公司银行账户来支付你的 Expensify 卡余额，或添加一个新的银行账户',
             accountEndingIn: '账号末尾为',
             addNewBankAccount: '添加新银行账户',
             settlementAccount: '结算账户',
-            settlementAccountDescription: '选择一个账户来支付你的 Expensify 卡欠款余额。',
-            settlementAccountInfo: (reconciliationAccountSettingsLink: string, accountNumber: string) =>
+            settlementAccountDescription: '选择一个账户来支付您的 Expensify 卡余额。',
+            settlementAccountInfo: ({reconciliationAccountSettingsLink, accountNumber}: SettlementAccountInfoParams) =>
                 `请确保此账户与您的<a href="${reconciliationAccountSettingsLink}">对账账户</a>（${accountNumber}）一致，以确保持续对账功能正常运行。`,
             settlementFrequency: '结算频率',
             settlementFrequencyDescription: '选择支付 Expensify 卡余额的频率。',
             settlementFrequencyInfo: '如果你想切换为按月结算，你需要通过 Plaid 连接你的银行账户，并且拥有过去 90 天为正数的余额记录。',
-            applyCashbackToBill: '将返现用于抵扣我的 Expensify 账单',
-            applyCashbackToBillDescription: 'Expensify 卡的返现将用于支付你的 Expensify 账单。',
             frequency: {
                 daily: '每日',
                 monthly: '每月',
             },
             cardDetails: '卡片详情',
+            cardPending: ({name}: {name: string}) => `卡片目前处于待处理状态，将在验证完 ${name} 的账户后发行。`,
             virtual: '虚拟',
             physical: '实体',
             deactivate: '停用卡片',
@@ -5471,28 +4943,24 @@ _如需更详细的说明，请[访问我们的帮助网站](${CONST.NETSUITE_IM
             changeCardSmartLimitTypeWarning: (limit: number | string) => `如果将此卡的限额类型更改为智能限额，新交易将被拒绝，因为未批准的 ${limit} 限额已达到上限。`,
             changeCardMonthlyLimitTypeWarning: (limit: number | string) => `如果您将此卡的限额类型更改为每月，新交易将被拒绝，因为已达到每月 ${limit} 的限额。`,
             addShippingDetails: '添加收货详情',
-            issuedCard: (assignee: string) => `已为 ${assignee} 发放了一张 Expensify 卡！该卡将在 2–3 个工作日内送达。`,
-            issuedCardNoShippingDetails: (assignee: string) => `已为 ${assignee} 发放了一张 Expensify 卡！在确认邮寄详情后将寄出该卡。`,
-            issuedCardVirtual: (assignee: string, link: string) => `已向 ${assignee} 发放一张虚拟 Expensify 卡！${link} 可立即使用。`,
-            addedShippingDetails: (assignee: string) => `${assignee} 已添加运输详情。Expensify 卡将在 2-3 个工作日内送达。`,
-            replacedCard: (assignee: string) => `${assignee} 已更换了他们的 Expensify 卡。新卡将在 2–3 个工作日内送达。`,
-            replacedVirtualCard: (assignee: string, link: string) => `${assignee} 已更换其虚拟 Expensify 卡！现在就可以使用 ${link}。`,
+            issuedCard: (assignee: string) => `已向 ${assignee} 发放一张 Expensify 卡！该卡将在 2–3 个工作日内送达。`,
+            issuedCardNoShippingDetails: (assignee: string) => `已向 ${assignee} 发放 Expensify 卡！一旦收货信息确认，卡片将寄出。`,
+            issuedCardVirtual: (assignee: string, link: string) => `已为 ${assignee} 发放一张虚拟 Expensify 卡！${link} 可立即使用。`,
+            addedShippingDetails: (assignee: string) => `${assignee} 已添加邮寄详情。Expensify 卡将在 2-3 个工作日内送达。`,
+            replacedCard: (assignee: string) => `${assignee} 已更换他们的 Expensify 卡。新卡将在 2–3 个工作日内送达。`,
+            replacedVirtualCard: (assignee: string, link: string) => `${assignee} 已更换他们的虚拟 Expensify 卡！${link} 可以立即使用。`,
             card: '卡片',
             replacementCard: '替换卡',
             verifyingHeader: '正在验证',
             bankAccountVerifiedHeader: '银行账户已验证',
             verifyingBankAccount: '正在验证银行账户…',
-            verifyingBankAccountDescription: '请稍候，我们正在确认此账户是否可用于发行 Expensify 卡。',
+            verifyingBankAccountDescription: '请稍候，我们正在确认此账户是否可用于开通 Expensify 卡。',
             bankAccountVerified: '银行账户已验证！',
-            bankAccountVerifiedDescription: '您现在可以向工作区成员发放 Expensify 卡。',
+            bankAccountVerifiedDescription: '您现在可以向工作区成员发放 Expensify Card。',
             oneMoreStep: '还有一步……',
             oneMoreStepDescription: '看起来我们需要手动验证您的银行账户。请前往 Concierge 查看为您准备的操作说明。',
             gotIt: '明白了',
             goToConcierge: '前往 Concierge',
-            exportAsCSV: '导出为 CSV',
-            csvColumnType: '类型',
-            csvColumnLimitType: '限额类型',
-            csvColumnLimit: '限额',
         },
         categories: {
             deleteCategories: '删除类别',
@@ -5511,10 +4979,10 @@ _如需更详细的说明，请[访问我们的帮助网站](${CONST.NETSUITE_IM
             needCategoryForExportToIntegration: (connectionName: string) => `要导出到 ${connectionName}，所有报销都必须先进行分类。`,
             subtitle: '更好地了解资金的支出去向。使用我们的默认类别或添加你自己的类别。',
             emptyCategories: {
-                title: '尚无类别',
+                title: '你还没有创建任何类别',
                 subtitle: '添加类别来整理您的支出。',
-                subtitleWithAccounting: (accountingPageURL: string, canManage = true) =>
-                    `<muted-text><centered-text>您的类别目前正从会计连接中导入。${canManage ? `前往<a href="${accountingPageURL}">会计</a>页面进行任何更改。` : ''}</centered-text></muted-text>`,
+                subtitleWithAccounting: (accountingPageURL: string) =>
+                    `<muted-text><centered-text>您的类别目前正从会计连接中导入。前往<a href="${accountingPageURL}">会计</a>页面进行任何更改。</centered-text></muted-text>`,
             },
             updateFailureMessage: '更新类别时出错，请重试',
             createFailureMessage: '创建类别时出错，请重试',
@@ -5569,9 +5037,6 @@ _如需更详细的说明，请[访问我们的帮助网站](${CONST.NETSUITE_IM
             travel: {
                 title: '差旅',
                 subtitle: '预订、管理并对账您所有的商务差旅。',
-                disableTravelTitle: '请先关闭差旅开票',
-                disableTravelPrompt: '此工作区已启用差旅开票。要禁用差旅功能，请先将其关闭。',
-                disableTravelButton: '前往差旅设置',
                 getStarted: {
                     title: '开始使用 Expensify Travel',
                     subtitle: '我们只需要再获取一些关于您企业的信息，之后您就可以准备起飞了。',
@@ -5582,53 +5047,40 @@ _如需更详细的说明，请[访问我们的帮助网站](${CONST.NETSUITE_IM
                     subtitle: '我们正在审核你启用 Expensify Travel 的请求。别担心，准备好后我们会通知你。',
                     ctaText: '请求已发送',
                 },
-                bookOrManageYourTrip: {title: '差旅预订', subtitle: '恭喜！您现在可以在此工作区预订和管理差旅了。', ctaText: '管理差旅'},
-                settings: {autoAddTripName: {title: '将行程名称添加到报销单', subtitle: '为在 Expensify 中预订的行程，自动将行程名称添加到报销事由描述中。'}},
+                bookOrManageYourTrip: {
+                    title: '预订或管理您的行程',
+                    subtitle: '使用 Expensify Travel 获取最优出行优惠，并在一个地方管理您所有的商务费用。',
+                    ctaText: '预订或管理',
+                },
                 travelInvoicing: {
                     travelBookingSection: {
                         title: '差旅预订',
                         subtitle: '恭喜！您已经可以在此工作区预订和管理差旅了。',
                         manageTravelLabel: '管理差旅',
                     },
-                    travelInvoicingSection: {
-                        title: '差旅开票',
+                    centralInvoicingSection: {
+                        title: '集中开票',
                         subtitle: '将所有差旅支出集中到每月发票中，而不是在购买时即时支付。',
                         learnHow: '了解方法。',
                         subsections: {
                             currentTravelSpendLabel: '当前差旅支出',
-                            currentTravelSpendPaymentQueued: (amount: string) => `金额为 ${amount} 的付款已排队，稍后将被处理。`,
                             currentTravelSpendCta: '支付余额',
                             currentTravelLimitLabel: '当前出行限额',
                             settlementAccountLabel: '结算账户',
                             settlementFrequencyLabel: '结算频率',
                             settlementFrequencyDescription: 'Expensify 从您的企业银行账户中扣款以结算最近 Expensify Travel 交易的频率。',
-                            monthlySpendLimitLabel: '每位成员的月度支出限额',
-                            monthlySpendLimitDescription: '每位成员每月可用于出差的最高金额。',
-                            reduceLimitTitle: '降低出差支出限额？',
-                            reduceLimitWarning: '如果您降低限额，已超出该金额的成员将无法进行新的出差预订，直至下个月。',
-                            provisioningError: '我们无法为您的工作区中的部分成员开通差旅开票功能。请稍后重试或联系 Concierge 获取帮助。',
                         },
                     },
-                    disableModal: {title: '关闭差旅开票？', body: '即将到来的酒店和汽车租赁预订可能需要使用不同的付款方式重新预订，以避免被取消。', confirm: '关闭'},
-                    outstandingBalanceModal: {title: '无法关闭差旅开票', body: '你仍有未结清的差旅余额。请先支付该余额。', confirm: '明白了'},
-                    payBalanceModal: {title: (amount: string) => `支付 ${amount} 的余额？`, body: '付款将被加入队列，并会在稍后处理。此操作一旦开始将无法撤销。'},
-                    exportToPDF: '导出为 PDF',
-                    exportToCSV: '导出为 CSV',
-                    selectDateRangeError: '请选择要导出的日期范围',
-                    invalidDateRangeError: '开始日期必须早于结束日期',
-                    enabled: '差旅开票已启用！',
-                    enabledDescription: '此工作区的所有差旅支出现在将集中在一张月度发票中。',
                 },
-                personalDetailsDescription: '为预订行程，请输入您在政府签发的身份证件上显示的法定姓名。',
             },
             expensifyCard: {
                 title: 'Expensify 卡',
                 subtitle: '深入洞察并掌控支出。',
                 disableCardTitle: '停用 Expensify 卡',
-                disableCardPrompt: '你无法停用 Expensify 卡，因为它已在使用中。请联系 Concierge 了解下一步操作。',
+                disableCardPrompt: '你无法停用 Expensify Card，因为它正在使用中。请联系 Concierge 了解下一步操作。',
                 disableCardButton: '与 Concierge 聊天',
                 feed: {
-                    title: '申领 Expensify 卡',
+                    title: '获取 Expensify 卡',
                     subTitle: '简化您的业务报销流程，最多可节省 50% 的 Expensify 账单费用，另外还可：',
                     features: {
                         cashBack: '每一笔美国消费都可返现',
@@ -5673,10 +5125,7 @@ _如需更详细的说明，请[访问我们的帮助网站](${CONST.NETSUITE_IM
                 updateCard: '更新卡片',
                 unassignCard: '取消分配卡片',
                 unassign: '取消分配',
-                unassignCardDescription: '取消分配此卡将删除所有未提交的交易。',
-                removeCard: '移除卡片',
-                remove: '移除',
-                removeCardDescription: '移除此卡片将删除所有未提交的交易。',
+                unassignCardDescription: '取消分配此卡将从持卡人的账户中移除所有处于草稿报表中的交易。',
                 assignCard: '分配卡片',
                 cardFeedName: '卡片交易源名称',
                 cardFeedNameDescription: '为该卡片流水命名一个唯一名称，以便与其他区分。',
@@ -5708,9 +5157,9 @@ _如需更详细的说明，请[访问我们的帮助网站](${CONST.NETSUITE_IM
                 noAccountsFound: '未找到账户',
                 defaultCard: '默认卡片',
                 downgradeTitle: `无法降级工作区`,
-                downgradeSubTitle: `无法降级此工作区，因为已连接多个银行卡流水（不包括 Expensify 卡）。请<a href="#">仅保留一个银行卡流水</a>后继续操作。`,
+                downgradeSubTitle: `此工作区无法降级，因为已连接了多个银行卡流水（不包括 Expensify Cards）。请<a href="#">仅保留一个银行卡流水</a>以继续。`,
                 noAccountsFoundDescription: (connection: string) => `请在 ${connection} 中添加该账户，然后再次同步该连接`,
-                expensifyCardBannerTitle: '申领 Expensify 卡',
+                expensifyCardBannerTitle: '获取 Expensify 卡',
                 expensifyCardBannerSubtitle: '美国境内每笔消费均可享受现金返现，Expensify 账单最高可减免 50%，无限虚拟卡等更多优惠。',
                 expensifyCardBannerLearnMoreButton: '了解详情',
                 statementCloseDateTitle: '账单结算日',
@@ -5719,7 +5168,7 @@ _如需更详细的说明，请[访问我们的帮助网站](${CONST.NETSUITE_IM
             workflows: {
                 title: '工作流程',
                 subtitle: '配置支出审批和付款方式。',
-                disableApprovalPrompt: '此工作区中的 Expensify 卡目前依赖审批来设定其智能限额。请在停用审批之前，先修改所有使用智能限额的 Expensify 卡的限额类型。',
+                disableApprovalPrompt: '此工作区中的 Expensify Card 目前依赖审批来设定其 Smart Limit。请在禁用审批前，先修改所有带有 Smart Limit 的 Expensify Card 的限额类型。',
             },
             invoices: {
                 title: '发票',
@@ -5763,8 +5212,8 @@ _如需更详细的说明，请[访问我们的帮助网站](${CONST.NETSUITE_IM
             },
             workflowWarningModal: {
                 featureEnabledTitle: '别急……',
-                featureEnabledText: '此工作区中的 Expensify 卡依赖审批流程来设定其智能限额。\n\n在停用审批流程之前，请先更改所有已启用智能限额的卡片的限额类型。',
-                confirmText: '前往 Expensify 卡',
+                featureEnabledText: '此工作区中的 Expensify Cards 依赖审批流程来定义其智能限额。\n\n在停用流程之前，请先更改所有使用智能限额的卡片的限额类型。',
+                confirmText: '前往 Expensify 卡片',
             },
             rules: {
                 title: '规则',
@@ -5775,7 +5224,6 @@ _如需更详细的说明，请[访问我们的帮助网站](${CONST.NETSUITE_IM
                 subtitle: '为时间跟踪设置可计费的小时费率。',
                 defaultHourlyRate: '默认时薪',
             },
-            hrWarningModal: {disconnectText: ({integration}: {integration: string}) => `若要禁用人力资源功能，请先将此工作区与 ${integration} 断开连接。`},
         },
         reports: {
             reportsCustomTitleExamples: '示例：',
@@ -5797,7 +5245,10 @@ _如需更详细的说明，请[访问我们的帮助网站](${CONST.NETSUITE_IM
             findReportField: '查找报表字段',
             deleteConfirmation: '确定要删除此报表字段吗？',
             deleteFieldsConfirmation: '确定要删除这些报表字段吗？',
-            emptyReportFields: {title: '尚无报表字段', subtitle: '添加一个自定义字段（文本、日期或下拉菜单），用于显示在报表上。'},
+            emptyReportFields: {
+                title: '你还没有创建任何报表字段',
+                subtitle: '添加一个自定义字段（文本、日期或下拉菜单），用于显示在报表上。',
+            },
             subtitle: '报表字段适用于所有支出，当你想提示填写额外信息时会很有帮助。',
             disableReportFields: '禁用报表字段',
             disableReportFieldsConfirmation: '确定要这样做吗？文本和日期字段将被删除，列表将被禁用。',
@@ -5821,7 +5272,10 @@ _如需更详细的说明，请[访问我们的帮助网站](${CONST.NETSUITE_IM
             disableValues: '禁用值',
             enableValue: '启用值',
             enableValues: '启用值',
-            emptyReportFieldsValues: {title: '尚无列表值', subtitle: '添加自定义值以显示在报表中。'},
+            emptyReportFieldsValues: {
+                title: '你尚未创建任何列表值',
+                subtitle: '添加自定义值以显示在报表中。',
+            },
             deleteValuePrompt: '确定要删除此列表值吗？',
             deleteValuesPrompt: '确定要删除这些列表值吗？',
             listValueRequiredError: '请输入列表值名称',
@@ -5833,33 +5287,9 @@ _如需更详细的说明，请[访问我们的帮助网站](${CONST.NETSUITE_IM
             reportFieldNameRequiredError: '请输入报表字段名称',
             reportFieldTypeRequiredError: '请选择报表字段类型',
             circularReferenceError: '此字段不能引用自身。请更新。',
-            unsupportedFormulaValueError: ({value}: UnsupportedFormulaValueErrorParams) => `无法识别公式字段 ${value}`,
             reportFieldInitialValueRequiredError: '请选择报表字段的初始值',
             genericFailureMessage: '更新报表字段时出错。请重试。',
         },
-        invoiceFields: {
-            subtitle: '当你想添加更多信息时，发票字段会很有帮助。',
-            importedFromAccountingSoftware: '以下发票字段是从你的',
-            disableInvoiceFields: '禁用发票字段',
-            disableInvoiceFieldsConfirmation: '确定吗？发票字段将在发票中被禁用。',
-            delete: '删除发票字段',
-            deleteConfirmation: '确定要删除此发票字段吗？',
-            findInvoiceField: '查找发票字段',
-            nameInputSubtitle: '为发票字段选择一个名称。',
-            typeInputSubtitle: '选择要使用的发票字段类型。',
-            initialValueInputSubtitle: '输入要在发票字段中显示的起始值。',
-            listValuesInputSubtitle: '这些值将显示在你的发票字段下拉菜单中。成员可以选择已启用的值。',
-            listInputSubtitle: '这些值将显示在你的发票字段列表中。成员可以选择已启用的值。',
-            emptyInvoiceFieldsValues: {
-                title: '还没有列表值',
-                subtitle: '添加要显示在发票上的自定义值。',
-            },
-            existingInvoiceFieldNameError: '已存在同名发票字段',
-            invoiceFieldNameRequiredError: '请输入发票字段名称',
-            invoiceFieldTypeRequiredError: '请选择发票字段类型',
-            invoiceFieldInitialValueRequiredError: '请选择发票字段的初始值',
-            addField: '添加字段',
-        },
         tags: {
             tagName: '标签名称',
             requiresTag: '成员必须为所有报销添加标签',
@@ -5877,14 +5307,14 @@ _如需更详细的说明，请[访问我们的帮助网站](${CONST.NETSUITE_IM
             editTags: '编辑标签',
             findTag: '查找标签',
             subtitle: '标签可用于以更细致的方式分类成本。',
-            subtitleWithDependentTags: (importSpreadsheetLink: string, canReimport = true) =>
-                `<muted-text>标签可用于以更细致的方式分类成本。您正在使用<a href="${CONST.IMPORT_TAGS_EXPENSIFY_URL_DEPENDENT_TAGS}">依赖标签</a>。${canReimport ? `您可以<a href="${importSpreadsheetLink}">重新导入电子表格</a>来更新您的标签。` : ''}</muted-text>`,
+            dependentMultiLevelTagsSubtitle: (importSpreadsheetLink: string) =>
+                `<muted-text>您正在使用<a href="${CONST.IMPORT_TAGS_EXPENSIFY_URL_DEPENDENT_TAGS}">依赖标签</a>。您可以<a href="${importSpreadsheetLink}">重新导入电子表格</a>来更新您的标签。</muted-text>`,
             emptyTags: {
-                title: '尚无标签',
+                title: '你还没有创建任何标签',
                 subtitle: '添加标签，以跟踪项目、地点、部门等。',
                 subtitleHTML: `<muted-text><centered-text>添加标签以跟踪项目、地点、部门等。<a href="${CONST.IMPORT_TAGS_EXPENSIFY_URL}">了解更多</a>关于用于导入的标签文件格式。</centered-text></muted-text>`,
-                subtitleWithAccounting: (accountingPageURL: string, canManage = true) =>
-                    `<muted-text><centered-text>您的标签目前正从会计连接中导入。${canManage ? `前往<a href="${accountingPageURL}">会计</a>以进行任何更改。` : ''}</centered-text></muted-text>`,
+                subtitleWithAccounting: (accountingPageURL: string) =>
+                    `<muted-text><centered-text>您的标签目前正从会计连接中导入。前往<a href="${accountingPageURL}">会计</a>以进行任何更改。</centered-text></muted-text>`,
             },
             deleteTag: '删除标签',
             deleteTags: '删除标签',
@@ -5970,7 +5400,7 @@ _如需更详细的说明，请[访问我们的帮助网站](${CONST.NETSUITE_IM
                 updateTaxClaimableFailureMessage: '可报销部分必须小于里程费率金额',
             },
             deleteTaxConfirmation: '确定要删除此税项吗？',
-            deleteMultipleTaxConfirmation: (taxAmount: number) => `确定要删除 ${taxAmount} 个税额吗？`,
+            deleteMultipleTaxConfirmation: ({taxAmount}: TaxAmountParams) => `确定要删除 ${taxAmount} 个税额吗？`,
             actions: {
                 delete: '删除费率',
                 deleteMultiple: '删除费率',
@@ -5998,45 +5428,10 @@ _如需更详细的说明，请[访问我们的帮助网站](${CONST.NETSUITE_IM
             reimbursementAccount: '报销账户',
             welcomeNote: '请开始使用我的新工作区',
             delayedSubmission: '延迟提交',
-            merchantRules: '商家规则',
-            merchantRulesCount: () => ({
-                one: '1 商家规则',
-                other: (count: number) => `${count} 商家规则`,
-            }),
             confirmTitle: ({newWorkspaceName, totalMembers}: {newWorkspaceName?: string; totalMembers?: number}) =>
                 `您即将创建并共享 ${newWorkspaceName ?? ''}，其中包含来自原始工作区的 ${totalMembers ?? 0} 位成员。`,
             error: '复制您的新工作区时发生错误。请重试。',
         },
-        copyPolicySettings: {
-            title: '复制设置',
-            error: '复制工作区设置时发生错误。请重试。',
-            selectWorkspaces: {
-                title: '选择工作区',
-                description: '选择要复制设置到的工作区，然后选择你想复制的设置。',
-                searchPlaceholder: '搜索工作区',
-            },
-            selectSettings: {
-                title: '选择要复制的功能',
-                description: '选择要在现有工作区中覆盖的设置。',
-                accountingMismatch: ({part}: {part: string}) => `仅当所有工作区使用相同的会计系统和公司连接时，您才能复制 ${part}。`,
-            },
-            confirmSettings: {
-                title: '让我们确认一切都正确无误。',
-                description: ({workspaceName}: {workspaceName: string}) => `我们会将以下设置从 <strong>${workspaceName}</strong> 复制到你指定的工作区`,
-            },
-            confirmWorkflows: {
-                continue: '继续且无成员',
-                description: '在不包含成员的情况下复制工作流时，将不会复制审批工作流。但提交和付款设置仍会被复制。',
-            },
-            progress: {
-                copyInProgressTitle: '正在复制中…',
-                copyInProgressDescription: '你可以选择等待流程完成，或者由 Concierge 在完成后通知你。',
-                letMeKnowPrompt: '完成后告诉我',
-                conciergeNotificationTitle: 'Concierge 会通知你',
-                conciergeNotificationDescription: '流程完成后，Concierge 会向你发送一条消息。',
-                copyCompleted: '您的工作区设置已复制。',
-            },
-        },
         emptyWorkspace: {
             title: '你还没有工作区',
             subtitle: '跟踪收据、报销费用、管理差旅、发送发票等。',
@@ -6051,7 +5446,7 @@ _如需更详细的说明，请[访问我们的帮助网站](${CONST.NETSUITE_IM
         },
         new: {
             newWorkspace: '新工作区',
-            getTheExpensifyCardAndMore: '获取 Expensify 卡及更多',
+            getTheExpensifyCardAndMore: '获取 Expensify 卡及更多服务',
             confirmWorkspace: '确认工作区',
             myGroupWorkspace: ({workspaceNumber}: {workspaceNumber?: number}) => `我的群组工作区${workspaceNumber ? ` ${workspaceNumber}` : ''}`,
             workspaceName: (userName: string, workspaceNumber?: number) => `${userName} 的工作区${workspaceNumber ? ` ${workspaceNumber}` : ''}`,
@@ -6094,31 +5489,22 @@ _如需更详细的说明，请[访问我们的帮助网站](${CONST.NETSUITE_IM
                 genericRemove: '移除该工作区成员时出现问题',
             },
             addedWithPrimary: '某些成员已通过其主登录名添加。',
-            invitedBySecondaryLogin: (secondaryLogin: string) => `由次要登录账号 ${secondaryLogin} 添加。`,
-            workspaceMembersCount: (count: number) => `工作区成员总数：${count}`,
+            invitedBySecondaryLogin: ({secondaryLogin}: SecondaryLoginParams) => `由次要登录账号 ${secondaryLogin} 添加。`,
+            workspaceMembersCount: ({count}: WorkspaceMembersCountParams) => `工作区成员总数：${count}`,
             importMembers: '导入成员',
-            removeMemberPromptApprover: (approver: string, workspaceOwner: string) => `如果你将 ${approver} 从此工作区中移除，我们会在审批流程中用工作区所有者 ${workspaceOwner} 替换 TA。`,
-            removeMemberPromptPendingApproval: (memberName: string) => `${memberName} 还有待审批的报销报告。请先让 TA 审批，或在将其从工作区中移除之前接管 TA 的报告。`,
+            removeMemberPromptApprover: ({approver, workspaceOwner}: {approver: string; workspaceOwner: string}) =>
+                `如果你将 ${approver} 从此工作区中移除，我们会在审批流程中用工作区所有者 ${workspaceOwner} 替换 TA。`,
+            removeMemberPromptPendingApproval: ({memberName}: {memberName: string}) => `${memberName} 还有待审批的报销报告。请先让 TA 审批，或在将其从工作区中移除之前接管 TA 的报告。`,
             removeMemberPromptReimburser: ({memberName}: {memberName: string}) => `您无法将${memberName}从此工作区中移除。请在“工作流”>“进行或跟踪付款”中设置新的报销人，然后重试。`,
             removeMemberPromptExporter: ({memberName, workspaceOwner}: {memberName: string; workspaceOwner: string}) =>
                 `如果您将 ${memberName} 从此工作区中移除，我们会将其首选导出人替换为工作区所有者 ${workspaceOwner}。`,
             removeMemberPromptTechContact: ({memberName, workspaceOwner}: {memberName: string; workspaceOwner: string}) =>
                 `如果您将 ${memberName} 从此工作区中移除，我们会将其技术联系人替换为工作区所有者 ${workspaceOwner}。`,
             cannotRemoveUserDueToReport: ({memberName}: {memberName: string}) => `${memberName} 还有一份待处理报告需要处理。请在将其从工作区中移除之前，先让 TA 完成所需操作。`,
-            allMembers: '所有成员',
-            admins: '工作区管理员',
-            cardAdmins: '卡管理员',
-            approvers: '审批人',
-            auditors: '审计员',
-            emptyRoleFilter: {title: '没有成员符合此筛选条件', subtitle: '邀请成员或更改上方的筛选条件。'},
-            configureHRSync: (providerName: string) => `配置 ${providerName} 同步。`,
-            syncWithHR: (providerName: string) => `与 ${providerName} 同步`,
-            makeCardAdmin: () => ({one: '设为卡片管理员', other: '设为卡片管理员'}),
         },
         card: {
             getStartedIssuing: '从发放您的第一张虚拟卡或实体卡开始使用。',
             issueCard: '发卡',
-            chooseRule: '选择规则',
             issueNewCard: {
                 whoNeedsCard: '谁需要一张卡？',
                 inviteNewMember: '邀请新成员',
@@ -6160,27 +5546,21 @@ _如需更详细的说明，请[访问我们的帮助网站](${CONST.NETSUITE_IM
                 enterValidDate: '请输入有效日期',
                 expirationDate: '过期日期',
                 limitAmount: '限额金额',
-                setCardRules: '设置卡片规则',
-                addSpendRule: '添加消费规则',
-                addExpirationDate: '添加到期日期',
-                addExpirationDateDescription: '如果未设置特定日期，卡片将按照当前卡片上的到期日失效',
+                setExpiryOptions: '设置过期选项',
+                setExpiryDate: '设置过期日期',
+                setExpiryDateDescription: '卡片将按照卡片上列出的日期过期',
                 amount: '金额',
-                copyExisting: '复制现有设置',
-                createNew: '新建',
-                spendRulesEmptyStateTitle: '没有可供选择的规则',
-                spendRulesEmptyStateSubtitle: '尚未创建规则。您可以在上一屏创建一个。',
             },
             deactivateCardModal: {
                 deactivate: '停用',
                 deactivateCard: '停用卡片',
                 deactivateConfirmation: '停用此卡将拒绝所有未来交易，且此操作无法撤销。',
             },
-            searchRules: '查找支出规则',
         },
         accounting: {
             settings: '设置',
             title: '连接',
-            subtitle: '连接您的会计软件以自动同步。',
+            subtitle: '连接到您的会计系统，以使用科目表为交易编码、自动匹配付款，并保持财务数据同步。',
             qbo: 'QuickBooks Online',
             qbd: 'QuickBooks Desktop',
             xero: 'Xero',
@@ -6189,7 +5569,7 @@ _如需更详细的说明，请[访问我们的帮助网站](${CONST.NETSUITE_IM
             sap: 'SAP',
             oracle: 'Oracle',
             microsoftDynamics: 'Microsoft Dynamics',
-            talkYourOnboardingSpecialist: '与您的客户经理聊天。',
+            talkYourOnboardingSpecialist: '与您的设置专家聊天。',
             talkYourAccountManager: '与您的客户经理聊天。',
             talkToConcierge: '与 Concierge 聊天。',
             needAnotherAccounting: '需要其他会计软件吗？',
@@ -6262,8 +5642,6 @@ _如需更详细的说明，请[访问我们的帮助网站](${CONST.NETSUITE_IM
             connectPrompt: ({connectionName}: ConnectionNameParams) =>
                 `确定要连接 ${CONST.POLICY.CONNECTIONS.NAME_USER_FRIENDLY[connectionName] ?? '此会计集成'} 吗？这将删除所有现有的会计连接。`,
             enterCredentials: '请输入您的凭证',
-            reconnect: '重新连接',
-            updateCredentials: '更新凭证',
             claimOffer: {
                 badgeText: '优惠可用！',
                 xero: {
@@ -6406,26 +5784,6 @@ _如需更详细的说明，请[访问我们的帮助网站](${CONST.NETSUITE_IM
                             return '导入 Sage Intacct 维度';
                         case 'intacctImportTitle':
                             return '导入 Sage Intacct 数据';
-                        case 'financialForceSyncTitle':
-                            return '正在同步 Certinia 数据';
-                        case 'financialForceSyncStep':
-                            return '正在同步 Certinia 连接';
-                        case 'financialForceSyncCategories':
-                            return '正在导入类别';
-                        case 'financialForceSyncTags':
-                            return '正在导入标签';
-                        case 'financialForceSyncVendors':
-                            return '正在导入供应商';
-                        case 'financialForceSyncContacts':
-                            return '正在导入联系人';
-                        case 'financialForceSyncCompanies':
-                            return '正在导入公司';
-                        case 'financialForceSyncUsers':
-                            return '正在导入用户';
-                        case 'financialForceSyncDimensions':
-                            return '正在导入维度';
-                        case 'financialForceMarkAsReimbursed':
-                            return '正在将报告标记为已报销';
                         default: {
                             return `缺少以下阶段的翻译：${stage}`;
                         }
@@ -6446,17 +5804,14 @@ _如需更详细的说明，请[访问我们的帮助网站](${CONST.NETSUITE_IM
             cardReconciliation: '卡片对账',
             reconciliationAccount: '对账科目',
             continuousReconciliation: '持续对账',
-            saveHoursOnReconciliation: '让 Expensify 持续为你对 Expensify 卡的对账单和结算进行核对，每个会计期间都能节省数小时的对账时间。',
+            saveHoursOnReconciliation: '每个会计期间，借助 Expensify 持续为你对账 Expensify Card 对账单和结算，可节省数小时的对账时间。',
             enableContinuousReconciliation: (accountingAdvancedSettingsLink: string, connectionName: string) =>
                 `<muted-text-label>要启用持续对账，请为 ${connectionName} 启用<a href="${accountingAdvancedSettingsLink}">自动同步</a>。</muted-text-label>`,
             chooseReconciliationAccount: {
-                chooseBankAccount: '选择用于对账 Expensify 卡付款的银行账户。',
-                settlementAccountReconciliation: (settlementAccountUrl: string, lastFourPAN: string) =>
-                    `请确保此账户与您的<a href="${settlementAccountUrl}">Expensify 卡结算账户</a>（末尾为 ${lastFourPAN}）一致，以便持续对账功能正常运行。`,
-                chooseTravelInvoicingBankAccount: '选择用于核对差旅开票付款的银行账户。',
-                travelInvoicingSettlementAccountReconciliation: (lastFourPAN: string) => `请确保此账户与您的差旅发票结算账户（以 ${lastFourPAN} 结尾）一致，以确保持续对账功能正常运行。`,
+                chooseBankAccount: '选择要用于核对 Expensify Card 付款的银行账户。',
+                settlementAccountReconciliation: ({settlementAccountUrl, lastFourPAN}: SettlementAccountReconciliationParams) =>
+                    `请确保此账户与您的<a href="${settlementAccountUrl}">Expensify Card 结算账户</a>（卡号末四位为 ${lastFourPAN}）一致，以便持续对账功能正常运行。`,
             },
-            syncTravelInvoicingSettlements: '同步差旅开票结算',
         },
         export: {
             notReadyHeading: '尚未准备好导出',
@@ -6534,13 +5889,7 @@ _如需更详细的说明，请[访问我们的帮助网站](${CONST.NETSUITE_IM
             errors: {
                 rateNameRequired: '费率名称为必填项',
                 existingRateName: '已存在同名的里程费率',
-                nameRequired: '姓名为必填项',
-                startDateMustBeBeforeEndDate: '开始日期必须早于结束日期',
-                amountRequired: '金额为必填项',
             },
-            amountPerUnit: (unit: string) => `每${unit}金额`,
-            startDate: '开始日期',
-            endDate: '结束日期',
         },
         editor: {
             descriptionInputLabel: '描述',
@@ -6582,7 +5931,7 @@ _如需更详细的说明，请[访问我们的帮助网站](${CONST.NETSUITE_IM
             updateToUSD: '更新为 USD',
             updateWorkspaceCurrency: '更新工作区货币',
             workspaceCurrencyNotSupported: '不支持工作区货币',
-            yourWorkspace: `您的工作区当前使用不受支持的货币。请查看<a href="${CONST.ENABLE_GLOBAL_REIMBURSEMENT_HELP_URL}">支持的货币列表</a>。`,
+            yourWorkspace: `您的工作区当前使用不受支持的货币。请查看<a href="${CONST.CONNECT_A_BUSINESS_BANK_ACCOUNT_HELP_URL}">支持的货币列表</a>。`,
             chooseAnExisting: '选择现有银行账户来支付报销，或添加新账户。',
         },
         changeOwner: {
@@ -6616,7 +5965,7 @@ _如需更详细的说明，请[访问我们的帮助网站](${CONST.NETSUITE_IM
             hasFailedSettlementsTitle: '无法转移所有权',
             hasFailedSettlementsButtonText: '明白了',
             hasFailedSettlementsText: (email: string) =>
-                `你无法接管账单，因为 ${email} 有一笔逾期未结清的 Expensify 卡结算。请让 TA 联系 concierge@expensify.com 解决该问题。问题解决后，你就可以为此工作区接管账单。`,
+                `你无法接管账单管理，因为 ${email} 存在逾期未结清的 Expensify Card 对账。请让 TA 联系 concierge@expensify.com 解决此问题。问题解决后，你就可以接管此工作区的账单管理。`,
             failedToClearBalanceTitle: '清除余额失败',
             failedToClearBalanceButtonText: 'OK',
             failedToClearBalanceText: '我们无法清除该余额。请稍后重试。',
@@ -6642,12 +5991,6 @@ ${reportName}
                 onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
                     `<muted-text>报表字段仅在 Control 方案中提供，起价为 <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `每位成员每月。` : `每位活跃成员每月。`}</muted-text>`,
             },
-            invoiceFields: {
-                title: '发票字段',
-                description: `发票字段可用于在发票上包含额外的发票级别详情。`,
-                onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
-                    `<muted-text>发票字段仅在 Control 方案中提供，起价为 <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `每位成员每月。` : `每位活跃成员每月。`}</muted-text>`,
-            },
             [CONST.POLICY.CONNECTIONS.NAME.NETSUITE]: {
                 title: 'NetSuite',
                 description: `通过 Expensify + NetSuite 集成实现自动同步，减少手动录入。借助对原生和自定义维度的支持（包括项目和客户映射），获取深入的实时财务洞察。`,
@@ -6666,12 +6009,6 @@ ${reportName}
                 onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
                     `<muted-text>我们的 QuickBooks Desktop 集成仅适用于 Control 方案，起价为 <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `每位成员每月。` : `每位活跃成员每月。`}</muted-text>`,
             },
-            [CONST.POLICY.CONNECTIONS.NAME.CERTINIA]: {
-                title: 'Certinia',
-                description: `通过 Expensify 与 Certinia 的集成，享受自动同步，减少手动录入。将费用编码维度与税务同步与您的 Certinia 配置对齐，以获得更清晰的财务可见性。`,
-                onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
-                    `<muted-text>我们的 Certinia 集成仅适用于 Control 方案，起价为 <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `每位成员每月。` : `每位活跃成员每月。`}</muted-text>`,
-            },
             [CONST.UPGRADE_FEATURE_INTRO_MAPPING.approvals.id]: {
                 title: '高级审批',
                 description: `如果你想在审批流程中增加更多层级，或者只是想确保金额最大的报销能再多一道审核，我们都能满足你的需求。高级审批功能帮助你在各个层级设置合适的审批规则，从而有效控制团队支出。`,
@@ -6747,7 +6084,7 @@ ${reportName}
                 onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
                     `<muted-text>里程费率适用于 Collect 方案，起始价格为 <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `每位成员每月。` : `每位活跃成员每月。`}</muted-text>`,
             },
-            controlPolicyRoles: {
+            auditor: {
                 title: '审计员',
                 description: '审计员将获得所有报表的只读访问权限，以实现全面可见性和合规监控。',
                 onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
@@ -6763,12 +6100,12 @@ ${reportName}
                 perActiveMember: '每位活跃成员每月。',
                 perMember: '每位成员每月。',
             },
-            note: (subscriptionLink: string) => `<muted-text><a href="${subscriptionLink}">了解详情</a>，包括我们的方案和价格。</muted-text>`,
+            note: ({subscriptionLink}: WorkspaceUpgradeNoteParams) => `<muted-text>升级以使用此功能，或<a href="${subscriptionLink}">了解更多</a>我们的方案和价格。</muted-text>`,
             upgradeToUnlock: '解锁此功能',
             completed: {
                 headline: `您已升级您的工作区！`,
-                successMessage: (policyName: string, planName: string, subscriptionLink: string) =>
-                    `<centered-text>您已成功将 ${policyName} 升级到 ${planName} 方案！有关更多详情，请<a href="${subscriptionLink}">查看您的订阅</a>。</centered-text>`,
+                successMessage: ({policyName, subscriptionLink}: UpgradeSuccessMessageParams) =>
+                    `<centered-text>您已成功将 ${policyName} 升级到 Control 方案！有关更多详情，请<a href="${subscriptionLink}">查看您的订阅</a>。</centered-text>`,
                 categorizeMessage: `您已成功升级至 Collect 方案。现在您可以为报销费用分类了！`,
                 travelMessage: `您已成功升级到 Collect 方案。现在可以开始预订和管理行程了！`,
                 distanceRateMessage: `您已成功升级到 Collect 方案。现在您可以修改里程费率了！`,
@@ -6791,82 +6128,24 @@ ${reportName}
                 upgradeWorkspaceWarning: `无法升级工作空间`,
                 upgradeWorkspaceWarningForRestrictedPolicyCreationPrompt: '您的公司已限制创建工作区。请联系管理员获取帮助。',
             },
-            hr: {
-                title: '人力资源集成',
-                description: '连接你的 HR 提供商，自动同步员工并管理审批流程。无需手动操作，即可保持团队成员名单和汇报结构的最新状态。',
-                onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
-                    `<muted-text>人力资源集成功能仅在 Control 方案中提供，起价为 <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `每位成员每月。` : `每位活跃成员每月。`}</muted-text>`,
-            },
-            approvalSubmit: {
-                title: '审批',
-                description: '启用审批功能，以集中配置所有成员向谁提交。',
-                onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
-                    `<muted-text>审批功能适用于 Collect 和 Control 方案，起价为 <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `每位成员每月。` : `每位活跃成员每月。`}</muted-text>`,
-            },
-            companyCardSubmit: {
-                title: '公司卡枚',
-                description: `将你自己的公司卡片连接到 Expensify，可享受自动导入、自动分类、自定义规则支持以及集成对账功能。`,
-                onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
-                    `<muted-text>公司信用卡导入功能适用于 Collect 和 Control 方案，起价为 <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `每位成员每月。` : `每位活跃成员每月。`}</muted-text>`,
-            },
-            travelSubmit: {
-                title: 'Expensify 差旅',
-                description: '通过 Expensify 在全球预订折扣机票、酒店、租车和火车，并享受差旅关怀报告和集成费用管理。',
-                onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
-                    `<muted-text>Expensify Travel 适用于 Collect 和 Control 方案，起价为 <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `每位成员每月。` : `每位活跃成员每月。`}</muted-text>`,
-            },
-            roles: {
-                title: '角色',
-                description: '为不同成员分配不同角色，以根据需要提高或降低可见性和控制权。',
-                onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
-                    `<muted-text>角色可在 Collect 和 Control 方案中使用，起价为 <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `每位成员每月。` : `每位活跃成员每月。`}</muted-text>`,
-            },
-            payments: {
-                title: '付款',
-                description: '直接从您的企业银行账户向员工报销。',
-                onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
-                    `<muted-text>付款功能适用于 Collect 和 Control 方案，起价为 <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `每位成员每月。` : `每位活跃成员每月。`}</muted-text>`,
-            },
-            accounting: {
-                title: '会计',
-                description: '从您的会计系统同步类别、标签、税率等信息到 Expensify，并导出费用报表和卡片交易记录——全程无需手动输入，也不用担心输入错误！',
-                onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
-                    `<muted-text>会计功能适用于 Collect 和 Control 方案，起价为 <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `每位成员每月。` : `每位活跃成员每月。`}</muted-text>`,
-            },
-            expensifyCard: {
-                title: 'Expensify 卡',
-                description: '直接从您自己的银行账户发放公司卡（包括虚拟卡），通过牢不可破的连接实现实时消费管控，并享受最高 2% 返现！',
-                onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
-                    `<muted-text>Expensify 卡适用于 Collect 和 Control 方案，起价为 <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `每位成员每月。` : `每位活跃成员每月。`}</muted-text>`,
-                upgradeButton: '升级并启用',
-            },
-            invoicing: {
-                title: '开具发票',
-                description: '在 Expensify 中创建、发送并跟踪专业发票。通过集成付款和实时可见性，让收款更快捷。',
-                onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
-                    `<muted-text>开票功能适用于 Collect 和 Control 方案，起价为 <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `每位成员每月。` : `每位活跃成员每月。`}</muted-text>`,
-            },
         },
         downgrade: {
             commonFeatures: {
-                title: '降级为 Collect',
-                note: '您将无法再使用以下功能',
+                title: '降级到 Collect 方案',
+                note: '如果您降级，您将失去对以下这些功能及更多功能的访问权限：',
                 benefits: {
-                    confirm: '你需要将每个工作区的“套餐类型”更改为“Collect”，才能锁定 Collect 费率。',
-                    benefit1: 'NetSuite、Sage Intacct、QuickBooks Desktop、Oracle、Microsoft Dynamics',
-                    benefit2: 'Workday、Certinia',
-                    benefit3: 'SSO/SAML',
-                    benefit4: '智能报销规则、日津贴、多级审批、自定义报表和预算管理',
+                    note: '如需完整比较我们的套餐，请查看我们的',
+                    pricingPage: '定价页面',
+                    confirm: '确定要降级并删除您的配置吗？',
+                    warning: '此操作无法撤销。',
+                    benefit1: '会计连接（QuickBooks Online 和 Xero 除外）',
+                    benefit2: '智能报销规则',
+                    benefit3: '多级审批工作流程',
+                    benefit4: '增强的安全控制',
                     headsUp: '注意！',
                     multiWorkspaceNote: '在首次月度付款前，您需要将所有工作区降级，才能以 Collect 费率开始订阅。点击',
                     selectStep: '> 选择每个工作区 > 将套餐类型更改为',
-                    benefit1Label: 'ERP 集成',
-                    benefit2Label: '人力资源集成',
-                    benefit3Label: '安全',
-                    benefit4Label: '高级',
-                    important: '重要：',
                 },
-                noteAndMore: '以及更多：',
             },
             completed: {
                 headline: '您的工作区已被降级',
@@ -6885,7 +6164,8 @@ ${reportName}
         restrictedAction: {
             restricted: '受限',
             actionsAreCurrentlyRestricted: (workspaceName: string) => `当前对 ${workspaceName} 工作区的操作受到限制`,
-            workspaceOwnerWillNeedToAddOrUpdatePaymentCard: (workspaceOwnerName: string) => `工作区所有者 ${workspaceOwnerName} 需要新增或更新已保存的付款卡，才能解锁新的工作区活动。`,
+            workspaceOwnerWillNeedToAddOrUpdatePaymentCard: ({workspaceOwnerName}: WorkspaceOwnerWillNeedToAddOrUpdatePaymentCardParams) =>
+                `工作区所有者 ${workspaceOwnerName} 需要新增或更新已保存的付款卡，才能解锁新的工作区活动。`,
             youWillNeedToAddOrUpdatePaymentCard: '您需要新增或更新档案中的付款卡片，才能解锁新的工作区活动。',
             addPaymentCardToUnlock: '添加付款卡以解锁！',
             addPaymentCardToContinueUsingWorkspace: '添加付款卡以继续使用此工作区',
@@ -6936,18 +6216,15 @@ ${reportName}
                 eReceiptsHint: `电子收据会自动为[大多数美元信用卡交易](${CONST.DEEP_DIVE_ERECEIPTS})创建。`,
                 attendeeTracking: '参会者跟踪',
                 attendeeTrackingHint: '跟踪每笔报销的单人费用。',
-                prohibitedDefaultDescription: '将包含这些明细项目的收据标记为人工审核。',
+                prohibitedDefaultDescription: '标记所有包含酒精、赌博或其他受限项目的收据。含有这些项目的收据报销将需要人工审核。',
                 prohibitedExpenses: '禁止报销的费用',
                 alcohol: '酒精',
                 hotelIncidentals: '酒店杂费',
                 gambling: '赌博',
                 tobacco: '烟草',
                 adultEntertainment: '成人娱乐',
-                giftCard: '礼品卡购买',
-                handwrittenReceipt: '手写收据',
                 requireCompanyCard: '所有消费均需使用公司卡',
                 requireCompanyCardDescription: '标记所有现金支出，包括里程和每日津贴报销。',
-                requireCompanyCardDisabledTooltip: '启用“公司卡”（位于“更多功能”下）以解锁。',
             },
             expenseReportRules: {
                 title: '高级',
@@ -6956,8 +6233,8 @@ ${reportName}
                 preventSelfApprovalsSubtitle: '防止工作区成员审批自己的报销报告。',
                 autoApproveCompliantReportsTitle: '自动批准合规报表',
                 autoApproveCompliantReportsSubtitle: '配置符合条件可自动审批的报销单。',
-                autoApproveReportsUnderTitle: '自动批准所有费用低于此金额的报表',
-                autoApproveReportsUnderDescription: '所有费用均低于此金额且完全合规的报销报告将自动获批。',
+                autoApproveReportsUnderTitle: '自动批准低于此金额的报表',
+                autoApproveReportsUnderDescription: '低于此金额且完全合规的报销报告将自动获批。',
                 randomReportAuditTitle: '随机报销报告审核',
                 randomReportAuditDescription: '即使符合自动审批条件，也要求部分报销单必须人工审批。',
                 autoPayApprovedReportsTitle: '自动支付已批准报销单',
@@ -6969,7 +6246,6 @@ ${reportName}
                 unlockFeatureEnableWorkflowsSubtitle: (featureName: string) => `添加 ${featureName} 以解锁此功能。`,
                 enableFeatureSubtitle: (featureName: string, moreFeaturesLink?: string) => `前往[更多功能](${moreFeaturesLink})并启用 ${featureName} 以解锁此功能。`,
             },
-            agentsPromoBanner: {title: '找不到需要的规则？添加代理人', subtitle: '添加复杂规则，并通过自定义代理减少人工审批。', cta: '试用一下'},
             merchantRules: {
                 title: '商户',
                 subtitle: '设置商户规则，使报销费用自动使用正确的编码，并减少后期清理工作。',
@@ -6997,10 +6273,9 @@ ${reportName}
                 matchTypeContains: '包含',
                 matchTypeExact: '完全匹配',
                 duplicateRuleTitle: '已存在类似的商家规则',
-                duplicateRulePrompt: (merchantName: string) => `您现有针对“${merchantName}”的规则将优先于此规则。仍要保存吗？`,
+                duplicateRulePrompt: (merchantName: string) => `即使已经有一条适用于“${merchantName}”的规则，是否仍要保存新规则？`,
                 saveAnyway: '仍然保存',
                 applyToExistingUnsubmittedExpenses: '应用到现有未提交的报销费用',
-                findRule: '查找商户规则',
             },
             categoryRules: {
                 title: '类别规则',
@@ -7037,130 +6312,11 @@ ${reportName}
                     always: '始终要求明细收据',
                 },
                 defaultTaxRate: '默认税率',
-                enableWorkflows: (moreFeaturesLink: string) => `前往 [更多功能](${moreFeaturesLink}) 并启用工作流，然后添加审批以解锁此功能。`,
+                enableWorkflows: ({moreFeaturesLink}: RulesEnableWorkflowsParams) => `前往 [更多功能](${moreFeaturesLink}) 并启用工作流，然后添加审批以解锁此功能。`,
             },
             customRules: {
                 title: '报销政策',
                 cardSubtitle: '这是你们团队的报销政策所在之处，让所有人都清楚哪些内容在报销范围之内。',
-                policyDocument: '政策文件',
-                policyText: '政策文本',
-            },
-            spendRules: {
-                title: '支出',
-                subtitle: '实时批准或拒绝 Expensify 卡交易。',
-                defaultRuleDescription: '所有卡片',
-                block: '屏蔽',
-                defaultRuleTitle: '类别：成人服务、ATM、赌博、转账',
-                builtInProtectionModal: {
-                    title: 'Expensify 卡始终提供内置保护',
-                    description: `Expensify 始终会拒绝以下消费：
-
-  • 成人服务
-  • ATM
-  • 赌博
-  • 转账
-
-添加更多消费规则以保护公司现金流。`,
-                },
-                addSpendRule: '添加支出规则',
-                cardPageTitle: '卡',
-                cardsSectionTitle: '卡片',
-                chooseCards: '选择卡片',
-                saveRule: '保存规则',
-                allow: '允许',
-                spendRuleSectionTitle: '支出规则',
-                restrictionType: '限制类型',
-                restrictionTypeHelpAllow: '如果符合任一商户或类别，且不超过最大金额，则费用会被批准。',
-                restrictionTypeHelpBlock: '如果交易符合任一商户或类别，或超过最高金额，都会被拒付。',
-                addMerchant: '添加商家',
-                merchantContains: '商家包含',
-                merchantExactlyMatches: '商户完全匹配',
-                noBlockedMerchants: '没有被屏蔽的商户',
-                addMerchantToBlockSpend: '添加商家以阻止消费',
-                noAllowedMerchants: '没有允许的商家',
-                addMerchantToAllowSpend: '添加商户以允许消费',
-                matchType: '匹配类型',
-                matchTypeContains: '包含',
-                matchTypeExact: '完全匹配',
-                spendCategory: '支出类别',
-                maxAmount: '最高金额',
-                maxAmountHelp: '无论商家或消费类别限制如何，任何超过此金额的消费都会被拒绝。',
-                currencyMismatchTitle: '货币不匹配',
-                currencyMismatchPrompt: '若要设置最高金额，请选择以相同货币结算的卡片。',
-                reviewSelectedCards: '检查所选卡片',
-                summaryMoreCount: ({summary, count}: {summary: string; count: number}) => (count > 0 ? `${summary}，还有 +${count} 项` : summary),
-                confirmErrorApplyAtLeastOneSpendRuleToOneCard: '至少将一条支出规则应用到一张卡上',
-                confirmErrorCardRequired: '“卡”是必填字段',
-                confirmErrorApplyAtLeastOneSpendRule: '至少应用一条支出规则',
-                categories: '类别',
-                merchants: '商家',
-                noAvailableCards: '所有卡片已具有规则',
-                noAvailableCardsSubtitle: '编辑现有的卡片规则以进行更改',
-                noCardsIssuedTitle: '尚未发放 Expensify 卡',
-                noCardsIssuedSubtitle: '发放 Expensify 卡以创建支出规则',
-                max: '最大',
-                categoryOptions: {
-                    [CONST.SPEND_RULES.CATEGORIES.AIRLINES]: '航空公司',
-                    [CONST.SPEND_RULES.CATEGORIES.ALCOHOL_AND_BARS]: '酒精和酒吧',
-                    [CONST.SPEND_RULES.CATEGORIES.AMAZON_AND_BOOKSTORES]: 'Amazon 和书店',
-                    [CONST.SPEND_RULES.CATEGORIES.AUTOMOTIVE]: '汽车',
-                    [CONST.SPEND_RULES.CATEGORIES.CAR_RENTALS]: '租车',
-                    [CONST.SPEND_RULES.CATEGORIES.DINING]: '餐饮',
-                    [CONST.SPEND_RULES.CATEGORIES.FUEL_AND_GAS]: '燃料和汽油',
-                    [CONST.SPEND_RULES.CATEGORIES.GOVERNMENT_AND_NON_PROFITS]: '政府和非营利组织',
-                    [CONST.SPEND_RULES.CATEGORIES.GROCERIES]: '杂货',
-                    [CONST.SPEND_RULES.CATEGORIES.GYMS_AND_FITNESS]: '健身房和健身',
-                    [CONST.SPEND_RULES.CATEGORIES.HEALTHCARE]: '医疗保健',
-                    [CONST.SPEND_RULES.CATEGORIES.HOTELS]: '酒店',
-                    [CONST.SPEND_RULES.CATEGORIES.INTERNET_AND_PHONE]: '网络和电话',
-                    [CONST.SPEND_RULES.CATEGORIES.OFFICE_SUPPLIES]: '办公用品',
-                    [CONST.SPEND_RULES.CATEGORIES.PARKING_AND_TOLLS]: '停车和过路费',
-                    [CONST.SPEND_RULES.CATEGORIES.PROFESSIONAL_SERVICES]: '专业服务',
-                    [CONST.SPEND_RULES.CATEGORIES.RETAIL]: '零售',
-                    [CONST.SPEND_RULES.CATEGORIES.SHIPPING_AND_DELIVERY]: '配送与交付',
-                    [CONST.SPEND_RULES.CATEGORIES.SOFTWARE]: '软件',
-                    [CONST.SPEND_RULES.CATEGORIES.TRANSIT_AND_RIDESHARE]: '公共交通和网约车',
-                    [CONST.SPEND_RULES.CATEGORIES.TRAVEL_AGENCIES]: '旅行社',
-                },
-                editRuleTitle: '编辑规则',
-                deleteRule: '删除规则',
-                deleteRuleConfirmation: '确定要删除此规则吗？',
-                summaryMerchants: ({
-                    merchants,
-                    hiddenCount,
-                    shownCount,
-                    action,
-                }: {
-                    merchants: string;
-                    hiddenCount: number;
-                    shownCount: number;
-                    action: ValueOf<typeof CONST.SPEND_RULES.ACTION>;
-                }) =>
-                    `${action === CONST.SPEND_RULES.ACTION.BLOCK ? '已屏蔽' : '已允许'} ${shownCount > 1 ? '商户' : '商家'}: ${merchants}${hiddenCount > 0 ? `，还有 +${hiddenCount} 个` : ''}`,
-                summaryCategories: ({
-                    categories,
-                    hiddenCount,
-                    shownCount,
-                    action,
-                }: {
-                    categories: string;
-                    hiddenCount: number;
-                    shownCount: number;
-                    action: ValueOf<typeof CONST.SPEND_RULES.ACTION>;
-                }) =>
-                    `${action === CONST.SPEND_RULES.ACTION.BLOCK ? '已屏蔽' : '已允许'} ${shownCount > 1 ? '类别' : '类别'}: ${categories}${hiddenCount > 0 ? `，还有 +${hiddenCount} 个` : ''}`,
-            },
-            aiRules: {
-                title: 'AI 规则',
-                subtitle: '描述在你需要时运行的灵活规则',
-                addRule: '添加 AI 规则',
-                findRule: '查找 AI 规则',
-                addRuleTitle: '添加规则',
-                editRuleTitle: '编辑规则',
-                deleteRule: '删除规则',
-                deleteRuleConfirmation: '确定要删除此规则吗？',
-                describeRuleTitle: '描述你的规则',
-                describeRuleSubtitle: '描述你的规则，我们会由 Concierge 为你创建',
             },
         },
         planTypePage: {
@@ -7173,101 +6329,15 @@ ${reportName}
                     label: '控制',
                     description: '适用于具有高级需求的组织。',
                 },
-                submit2026: {
-                    label: '提交',
-                    description: '适用于希望向雇主提交费用的员工。',
-                },
             },
-            description: '选择适合你的方案。',
-            subscriptionLink: '了解详情',
+            description: '选择适合您的方案。要查看详细的功能和价格列表，请访问我们的',
+            subscriptionLink: '方案类型和价格帮助页面',
             lockedPlanDescription: ({count, annualSubscriptionEndDate}: WorkspaceLockedPlanTypeParams) => ({
                 one: `在 Control 方案中，你已承诺在年度订阅到期（${annualSubscriptionEndDate}）前保持 1 位活跃成员。你可以在 ${annualSubscriptionEndDate} 起关闭自动续订，以改为按使用付费订阅并降级到 Collect 方案，操作入口在`,
                 other: `在年费订阅于${annualSubscriptionEndDate}结束之前，你已承诺在 Control 方案中保留 ${count} 名活跃成员。你可以在${annualSubscriptionEndDate}起，通过关闭自动续订，改为按使用量付费订阅并降级到 Collect 方案，操作入口在`,
             }),
             subscriptions: '订阅',
         },
-        hr: {
-            title: '人力资源',
-            connections: '连接',
-            connectionsSubtitle: '连接您的 HR 系统以同步员工数据，自动将报销匹配到正确的员工，并在无需手动操作的情况下保持团队报销的准确性。',
-            subtitle: '连接人力资源工具，保持员工审批同步。',
-            connect: '连接',
-            syncNow: '立即同步',
-            disconnect: '断开连接',
-            disconnectTitle: (providerName: string) => `断开 ${providerName}`,
-            disconnectPrompt: (providerName: string) => `确定要断开 ${providerName} 吗？`,
-            alreadyConnectedTitle: '无法连接到多个人力资源平台',
-            alreadyConnectedPrompt: '在连接其他人力资源平台之前，您必须先断开当前的人力资源平台。',
-            lastSync: (relativeDate: string) => `上次同步 ${relativeDate}`,
-            syncError: (providerName: string) => `无法连接到 ${providerName}`,
-            connectionDescription: (providerName: string) => `连接 ${providerName}，以在您的工作区中同步员工审批。`,
-            approvalMode: '审批模式',
-            providerApprovalMode: (providerName: string) => `${providerName} 审批模式`,
-            finalApprover: '最终审批人',
-            providerFinalApprover: (providerName: string) => `${providerName} 最终审批人`,
-            notSet: '未设置',
-            approvalModeDescription: (providerName: string) => `成员和管理员已设置为与 ${providerName} 同步。`,
-            approvalModeWarningTitle: '更改审批模式？',
-            approvalModeWarningPrompt: (providerName: string, helpSiteURL: string) =>
-                `您确定要更改此工作区的审批模式吗？在我们的<a href="${helpSiteURL}">帮助网站</a>中了解更多关于不同 ${providerName} 启用的工作流模式的信息。`,
-            approvalModeWarningConfirm: '更改审批模式',
-            approvalModes: {
-                basic: {label: '基本审批', description: '所有用户都提交给同一个人进行处理和审批。'},
-                manager: {
-                    label: '经理审批',
-                    description: (providerName: string) => `员工会将报销单提交给在 ${providerName} 中配置的直属经理。`,
-                },
-                custom: {label: '自定义审批', description: '我将在 Expensify 中手动设置审批工作流程。'},
-            },
-            syncStageName: ({stage}: SyncStageNameConnectionsParams) => {
-                switch (stage) {
-                    case 'gustoSyncTitle':
-                        return '同步 Gusto 员工';
-                    case 'gustoSyncLoadData':
-                        return '正在从 Gusto 加载数据';
-                    case 'gustoSyncProvisioning':
-                        return '在政策中为员工开通账号';
-                    case 'zenefitsSyncTitle':
-                        return '正在同步 TriNet 员工';
-                    case 'zenefitsSyncLoadData':
-                        return '正在从 TriNet 加载数据';
-                    case 'zenefitsSyncProvisioning':
-                        return '在政策中为员工开通账号';
-                    case 'jobDone':
-                        return '正在加载导入的数据';
-                    default: {
-                        return `阶段缺少翻译：${stage}`;
-                    }
-                }
-            },
-            syncResults: {
-                title: (provider: string) => `${provider} 同步完成`,
-                successTitle: (provider: string) => `已成功同步您的 ${provider} 连接！`,
-                added: '已添加',
-                removed: '已移除',
-                skipped: '已跳过',
-                employeeCount: () => ({
-                    one: '1 员工',
-                    other: (count: number) => `${count} 员工`,
-                }),
-            },
-            gusto: {
-                title: 'Gusto',
-            },
-            zenefits: {
-                title: 'TriNet',
-            },
-            syncingModalTitle: '您的连接正在同步',
-            syncingModalDescription: '首次连接可能需要一些时间。若发生任何错误，我们会通知你。',
-            syncing: '正在同步员工',
-            mergeHR: {
-                completeSetup: '完成设置',
-                setupIncomplete: (setupLink: string | undefined) =>
-                    `<muted-text-label>已连接。${setupLink ? `<a href="${setupLink}">完成设置</a>` : '完成设置'} 用于导入员工。</muted-text-label>`,
-                groups: {title: '群组', description: '选择要与此工作区同步的员工分组'},
-            },
-        },
-        emptyDomain: {title: '通过域名提升安全性', subtitle: '要求您域中的成员通过单点登录登录、限制工作区创建等。'},
     },
     getAssistancePage: {
         title: '获取帮助',
@@ -7295,7 +6365,6 @@ ${reportName}
             symbols: '符号',
             flags: '标记',
         },
-        emojiNotSelected: '未选择表情符号',
     },
     newRoomPage: {
         newRoom: '新房间',
@@ -7308,7 +6377,7 @@ ${reportName}
         public_announceDescription: '任何人都可以找到此房间',
         createRoom: '创建聊天室',
         roomAlreadyExistsError: '已存在同名房间',
-        roomNameReservedError: (reservedName: string) => `${reservedName} 是所有工作区中的默认聊天室名称。请选择其他名称。`,
+        roomNameReservedError: ({reservedName}: RoomNameReservedErrorParams) => `${reservedName} 是所有工作区中的默认聊天室名称。请选择其他名称。`,
         roomNameInvalidError: '房间名称只能包含小写字母、数字和连字符',
         pleaseEnterRoomName: '请输入房间名称',
         pleaseSelectWorkspace: '请选择一个工作区',
@@ -7316,7 +6385,7 @@ ${reportName}
             const actor = actorName ? `${actorName} ` : '';
             return isExpenseReport ? `${actor}已重命名为“${newName}”（原为“${oldName}”）` : `${actor}将此房间重命名为“${newName}”（原名“${oldName}”）`;
         },
-        roomRenamedTo: (newName: string) => `房间已重命名为 ${newName}`,
+        roomRenamedTo: ({newName}: RoomRenamedToParams) => `房间已重命名为 ${newName}`,
         social: '社交',
         selectAWorkspace: '选择工作区',
         growlMessageOnRenameError: '无法重命名工作区房间。请检查您的网络连接并重试。',
@@ -7356,14 +6425,14 @@ ${reportName}
             previousAddress ? `已将公司地址更改为“${newAddress}”（原为“${previousAddress}”）` : `将公司地址设置为“${newAddress}”`,
         addApprovalRule: (approverEmail: string, approverName: string, field: string, name: string) => `已添加 ${approverName}（${approverEmail}）作为字段 ${field}“${name}”的审批人`,
         deleteApprovalRule: (approverEmail: string, approverName: string, field: string, name: string) => `已将 ${approverName}（${approverEmail}）从 ${field}“${name}”的审批人中移除`,
-        updateApprovalRule: (field: string, name: string, newApproverEmail: string, newApproverName: string | undefined, oldApproverEmail: string, oldApproverName: string | undefined) => {
+        updateApprovalRule: ({field, name, newApproverEmail, newApproverName, oldApproverEmail, oldApproverName}: UpdatedPolicyApprovalRuleParams) => {
             const formatApprover = (displayName?: string, email?: string) => (displayName ? `${displayName} (${email})` : email);
             return `已将${field}“${name}”的审批人更改为${formatApprover(newApproverName, newApproverEmail)}（之前为${formatApprover(oldApproverName, oldApproverEmail)}）`;
         },
-        addCategory: (categoryName: string) => `已添加类别“${categoryName}”`,
-        deleteCategory: (categoryName: string) => `已移除类别 “${categoryName}”`,
-        updateCategory: (categoryName: string, oldValue: boolean) => `${oldValue ? '已禁用' : '已启用'} 类别“${categoryName}”`,
-        updateCategoryPayrollCode: (categoryName: string, newValue?: string, oldValue?: string) => {
+        addCategory: ({categoryName}: UpdatedPolicyCategoryParams) => `已添加类别“${categoryName}”`,
+        deleteCategory: ({categoryName}: UpdatedPolicyCategoryParams) => `已移除类别 “${categoryName}”`,
+        updateCategory: ({oldValue, categoryName}: UpdatedPolicyCategoryParams) => `${oldValue ? '已禁用' : '已启用'} 类别“${categoryName}”`,
+        updateCategoryPayrollCode: ({oldValue, categoryName, newValue}: UpdatedPolicyCategoryGLCodeParams) => {
             if (!oldValue) {
                 return `已将工资代码“${newValue}”添加到类别“${categoryName}”`;
             }
@@ -7372,7 +6441,7 @@ ${reportName}
             }
             return `已将“${categoryName}”类别的工资代码更改为“${newValue}”（之前为“${oldValue}”）`;
         },
-        updateCategoryGLCode: (categoryName: string, newValue?: string, oldValue?: string) => {
+        updateCategoryGLCode: ({oldValue, categoryName, newValue}: UpdatedPolicyCategoryGLCodeParams) => {
             if (!oldValue) {
                 return `已将科目代码“${newValue}”添加到类别“${categoryName}”`;
             }
@@ -7381,10 +6450,10 @@ ${reportName}
             }
             return `已将“${categoryName}”类别的总账科目代码更改为“${newValue}”（原为“${oldValue}”）`;
         },
-        updateAreCommentsRequired: (categoryName: string, oldValue: boolean) => {
+        updateAreCommentsRequired: ({oldValue, categoryName}: UpdatedPolicyCategoryParams) => {
             return `已将“${categoryName}”类别的描述更改为 ${!oldValue ? '必填' : '非必填'}（之前为 ${!oldValue ? '非必填' : '必填'}）`;
         },
-        updateCategoryMaxExpenseAmount: (categoryName: string, newAmount?: string, oldAmount?: string) => {
+        updateCategoryMaxExpenseAmount: ({categoryName, oldAmount, newAmount}: UpdatedPolicyCategoryMaxExpenseAmountParams) => {
             if (newAmount && !oldAmount) {
                 return `已为类别“${categoryName}”添加最高金额 ${newAmount}`;
             }
@@ -7393,69 +6462,69 @@ ${reportName}
             }
             return `将“${categoryName}”类别的最高金额更改为 ${newAmount}（此前为 ${oldAmount}）`;
         },
-        updateCategoryExpenseLimitType: (categoryName: string, newValue: string, oldValue?: string) => {
+        updateCategoryExpenseLimitType: ({categoryName, oldValue, newValue}: UpdatedPolicyCategoryExpenseLimitTypeParams) => {
             if (!oldValue) {
                 return `已将类别“${categoryName}”的限额类型设置为 ${newValue}`;
             }
             return `已将“${categoryName}”类别限额类型更改为 ${newValue}（先前为 ${oldValue}）`;
         },
-        updateCategoryMaxAmountNoReceipt: (categoryName: string, newValue: string, oldValue?: string) => {
+        updateCategoryMaxAmountNoReceipt: ({categoryName, oldValue, newValue}: UpdatedPolicyCategoryMaxAmountNoReceiptParams) => {
             if (!oldValue) {
                 return `通过将收据更改为 ${newValue}，已更新类别“${categoryName}”`;
             }
             return `将“${categoryName}”类别更改为 ${newValue}（之前为 ${oldValue}）`;
         },
-        updateCategoryMaxAmountNoItemizedReceipt: (categoryName: string, oldValue: string | undefined, newValue: string) => {
+        updateCategoryMaxAmountNoItemizedReceipt: ({categoryName, oldValue, newValue}: UpdatedPolicyCategoryMaxAmountNoReceiptParams) => {
             if (!oldValue) {
                 return `通过将“逐项列示收据”更改为 ${newValue}，更新了类别“${categoryName}”`;
             }
             return `将“${categoryName}”类别的分项收据更改为 ${newValue}（之前为 ${oldValue}）`;
         },
-        setCategoryName: (oldName: string, newName: string) => `已将类别“${oldName}”重命名为“${newName}”`,
-        updatedDescriptionHint: (categoryName: string, newValue?: string, oldValue?: string) => {
+        setCategoryName: ({oldName, newName}: UpdatedPolicyCategoryNameParams) => `已将类别“${oldName}”重命名为“${newName}”`,
+        updatedDescriptionHint: ({categoryName, oldValue, newValue}: UpdatedPolicyCategoryDescriptionHintTypeParams) => {
             if (!newValue) {
                 return `已从类别“${categoryName}”中移除描述提示“${oldValue}”`;
             }
             return !oldValue ? `已为类别“${categoryName}”添加描述提示“${newValue}”` : `已将“${categoryName}”类别的描述提示更改为“${newValue}”（之前为“${oldValue}”）`;
         },
-        updateTagListName: (oldName: string, newName: string) => `已将标签列表名称更改为“${newName}”（原为“${oldName}”）`,
-        addTag: (tagListName: string, tagName?: string) => `已将标签“${tagName}”添加到列表“${tagListName}”`,
-        updateTagName: (tagListName: string, newName: string, oldName: string) => `通过将标签“${oldName}”更改为“${newName}”更新了标签列表“${tagListName}”`,
-        updateTagEnabled: (tagListName: string, tagName?: string, enabled?: boolean) => `${enabled ? '已启用' : '已禁用'} 列表“${tagListName}”上的标签“${tagName}”`,
-        deleteTag: (tagListName: string, tagName?: string) => `已从列表“${tagListName}”中移除标签“${tagName}”`,
-        deleteMultipleTags: (count?: string, tagListName?: string) => `已从列表“${tagListName}”中移除“${count}”个标签`,
-        updateTag: (tagListName: string, newValue: string, tagName: string, updatedField: string, oldValue?: string) => {
+        updateTagListName: ({oldName, newName}: UpdatedPolicyCategoryNameParams) => `已将标签列表名称更改为“${newName}”（原为“${oldName}”）`,
+        addTag: ({tagListName, tagName}: UpdatedPolicyTagParams) => `已将标签“${tagName}”添加到列表“${tagListName}”`,
+        updateTagName: ({tagListName, newName, oldName}: UpdatedPolicyTagNameParams) => `通过将标签“${oldName}”更改为“${newName}”更新了标签列表“${tagListName}”`,
+        updateTagEnabled: ({tagListName, tagName, enabled}: UpdatedPolicyTagParams) => `${enabled ? '已启用' : '已禁用'} 列表“${tagListName}”上的标签“${tagName}”`,
+        deleteTag: ({tagListName, tagName}: UpdatedPolicyTagParams) => `已从列表“${tagListName}”中移除标签“${tagName}”`,
+        deleteMultipleTags: ({count, tagListName}: UpdatedPolicyTagParams) => `已从列表“${tagListName}”中移除“${count}”个标签`,
+        updateTag: ({tagListName, newValue, tagName, updatedField, oldValue}: UpdatedPolicyTagFieldParams) => {
             if (oldValue) {
                 return `通过将${updatedField}从“${oldValue}”更改为“${newValue}”，更新了列表“${tagListName}”中的标签“${tagName}”`;
             }
             return `通过添加 ${updatedField} 为“${newValue}”，已更新列表“${tagListName}”中的标签“${tagName}”`;
         },
-        updateCustomUnit: (customUnitName: string, newValue: string, oldValue: string, updatedField: string) =>
+        updateCustomUnit: ({customUnitName, newValue, oldValue, updatedField}: UpdatePolicyCustomUnitParams) =>
             `已将${customUnitName}的${updatedField}更改为“${newValue}”（之前为“${oldValue}”）`,
-        updateCustomUnitTaxEnabled: (newValue: boolean) => `${newValue ? '已启用' : '已禁用'} 距离费率的税务跟踪`,
-        addCustomUnitRate: (customUnitName: string, rateName: string) => `已添加自定义单位 ${customUnitName} 费率“${rateName}”`,
-        updatedCustomUnitRate: (customUnitName: string, customUnitRateName: string, updatedField: string, newValue: string, oldValue: string) =>
+        updateCustomUnitTaxEnabled: ({newValue}: UpdatePolicyCustomUnitTaxEnabledParams) => `${newValue ? '已启用' : '已禁用'} 距离费率的税务跟踪`,
+        addCustomUnitRate: ({customUnitName, rateName}: AddOrDeletePolicyCustomUnitRateParams) => `已添加新的 ${customUnitName} 费率“${rateName}”`,
+        updatedCustomUnitRate: ({customUnitName, customUnitRateName, newValue, oldValue, updatedField}: UpdatedPolicyCustomUnitRateParams) =>
             `将 ${customUnitName} 的 ${updatedField} 费率“${customUnitRateName}”更改为“${newValue}”（之前为“${oldValue}”）`,
-        updatedCustomUnitTaxRateExternalID: (customUnitRateName: string, newValue: string, newTaxPercentage: string, oldTaxPercentage?: string, oldValue?: string) => {
+        updatedCustomUnitTaxRateExternalID: ({customUnitRateName, newValue, newTaxPercentage, oldTaxPercentage, oldValue}: UpdatedPolicyCustomUnitTaxRateExternalIDParams) => {
             if (oldTaxPercentage && oldValue) {
                 return `已将距离费率“${customUnitRateName}”的税率更改为“${newValue}（${newTaxPercentage}）”（之前为“${oldValue}（${oldTaxPercentage}）”）`;
             }
             return `已将税率“${newValue}（${newTaxPercentage}）”添加到距离费率“${customUnitRateName}”`;
         },
-        updatedCustomUnitTaxClaimablePercentage: (customUnitRateName: string, newValue: number, oldValue?: number) => {
+        updatedCustomUnitTaxClaimablePercentage: ({customUnitRateName, newValue, oldValue}: UpdatedPolicyCustomUnitTaxClaimablePercentageParams) => {
             if (oldValue) {
                 return `已将距离费率“${customUnitRateName}”的可退税部分更改为“${newValue}”（之前为“${oldValue}”）`;
             }
             return `已将“${newValue}”的可退税部分添加到距离费率“${customUnitRateName}”中`;
         },
-        updatedCustomUnitRateName: (customUnitName: string, oldValue: string, newValue: string) => `已将 ${customUnitName} 费率名称从“${oldValue}”重命名为“${newValue}”`,
-        updatedCustomUnitRateEnabled: (customUnitName: string, customUnitRateName: string, newValue: boolean) => {
+        updatedCustomUnitRateEnabled: ({customUnitName, customUnitRateName, newValue}: UpdatedPolicyCustomUnitRateEnabledParams) => {
             return `${newValue ? '已启用' : '已禁用'}${customUnitName}费率“${customUnitRateName}”`;
         },
-        deleteCustomUnitRate: (customUnitName: string, rateName: string) => `已删除“${customUnitName}”费率“${rateName}”`,
-        updateReportFieldDefaultValue: (defaultValue?: string, fieldName?: string) => `将报表字段“${fieldName}”的默认值设置为“${defaultValue}”`,
-        addedReportFieldOption: (fieldName: string, optionName: string) => `已将选项“${optionName}”添加到报表字段“${fieldName}”`,
-        removedReportFieldOption: (fieldName: string, optionName: string) => `已从报表字段“${fieldName}”中移除选项“${optionName}”`,
+        deleteCustomUnitRate: ({customUnitName, rateName}: AddOrDeletePolicyCustomUnitRateParams) => `已删除“${customUnitName}”费率“${rateName}”`,
+        addedReportField: ({fieldType, fieldName}: AddedOrDeletedPolicyReportFieldParams) => `已添加${fieldType}报表字段“${fieldName}”`,
+        updateReportFieldDefaultValue: ({defaultValue, fieldName}: UpdatedPolicyReportFieldDefaultValueParams) => `将报表字段“${fieldName}”的默认值设置为“${defaultValue}”`,
+        addedReportFieldOption: (fieldName: any, optionName: string) => `已将选项“${optionName}”添加到报表字段“${fieldName}”`,
+        removedReportFieldOption: (fieldName: any, optionName: string) => `已从报表字段“${fieldName}”中移除选项“${optionName}”`,
         updateReportFieldOptionDisabled: (fieldName: string, optionName: string, optionEnabled: boolean) =>
             `${optionEnabled ? '已启用' : '已禁用'} 报表字段“${fieldName}”的选项“${optionName}”`,
         updateReportFieldAllOptionsDisabled: (fieldName: string, optionName: string, allEnabled: boolean, toggledOptionsCount?: number) => {
@@ -7465,20 +6534,20 @@ ${reportName}
             return `将报表字段“${fieldName}”的选项“${optionName}”设置为${allEnabled ? '已启用' : '已禁用'}，使所有选项均为${allEnabled ? '已启用' : '已禁用'}`;
         },
         deleteReportField: ({fieldType, fieldName}: {fieldType: string; fieldName?: string}) => `已移除 ${fieldType} 报告字段“${fieldName}”`,
-        preventSelfApproval: (oldValue: string, newValue: string) =>
+        preventSelfApproval: ({oldValue, newValue}: UpdatedPolicyPreventSelfApprovalParams) =>
             `已将“禁止自我审批”更新为“${newValue === 'true' ? '已启用' : '已禁用'}”（之前为“${oldValue === 'true' ? '已启用' : '已禁用'}”）`,
-        updateMonthlyOffset: (oldValue: string, newValue: string) => {
+        updateMonthlyOffset: ({oldValue, newValue}: UpdatedPolicyFieldWithNewAndOldValueParams) => {
             if (!oldValue) {
                 return `将月度报告提交日期设置为“${newValue}”`;
             }
             return `将月度报表提交日期更新为“${newValue}”（之前为“${oldValue}”）`;
         },
-        updateDefaultBillable: (oldValue: string, newValue: string) => `已将“向客户重新计费报销”更新为“${newValue}”（之前为“${oldValue}”）`,
-        updateDefaultReimbursable: (oldValue: string, newValue: string) => `已将“现金报销默认值”更新为“${newValue}”（之前为“${oldValue}”）`,
-        updateDefaultTitleEnforced: (value: boolean) => `已将“强制使用默认报表标题”设置为开启 ${value ? '开' : '关'}`,
-        changedCustomReportNameFormula: (oldValue: string, newValue: string) => `将自定义报表名称公式更改为“${newValue}”（先前为“${oldValue}”）`,
+        updateDefaultBillable: ({oldValue, newValue}: UpdatedPolicyFieldWithNewAndOldValueParams) => `已将“向客户重新计费报销”更新为“${newValue}”（之前为“${oldValue}”）`,
+        updateDefaultReimbursable: ({oldValue, newValue}: UpdatedPolicyFieldWithNewAndOldValueParams) => `已将“现金报销默认值”更新为“${newValue}”（之前为“${oldValue}”）`,
+        updateDefaultTitleEnforced: ({value}: UpdatedPolicyFieldWithValueParams) => `已将“强制使用默认报表标题”设置为开启 ${value ? '开' : '关'}`,
+        changedCustomReportNameFormula: ({newValue, oldValue}: UpdatedPolicyFieldWithNewAndOldValueParams) => `将自定义报表名称公式更改为“${newValue}”（先前为“${oldValue}”）`,
         renamedWorkspaceNameAction: (oldName: string, newName: string) => `已将此工作区的名称更新为“${newName}”（原为“${oldName}”）`,
-        updateWorkspaceDescription: (newDescription: string, oldDescription: string) =>
+        updateWorkspaceDescription: ({newDescription, oldDescription}: UpdatedPolicyDescriptionParams) =>
             !oldDescription ? `将此工作区的描述设置为“${newDescription}”` : `已将此工作区的描述更新为“${newDescription}”（之前为“${oldDescription}”）`,
         removedFromApprovalWorkflow: ({submittersNames}: RemovedFromApprovalWorkflowParams) => {
             let joinedNames = '';
@@ -7495,15 +6564,15 @@ ${reportName}
             };
         },
         demotedFromWorkspace: (policyName: string, oldRole: string) => `已将你在 ${policyName} 中的角色从 ${oldRole} 更新为用户。你已从所有报销人费用聊天中移除，但你自己的除外。`,
-        updatedWorkspaceCurrencyAction: (oldCurrency: string, newCurrency: string) => `已将默认货币更新为 ${newCurrency}（之前为 ${oldCurrency}）`,
-        updatedWorkspaceFrequencyAction: (oldFrequency: string, newFrequency: string) => `已将自动报表频率更新为“${newFrequency}”（此前为“${oldFrequency}”）`,
+        updatedWorkspaceCurrencyAction: ({oldCurrency, newCurrency}: UpdatedPolicyCurrencyParams) => `已将默认货币更新为 ${newCurrency}（之前为 ${oldCurrency}）`,
+        updatedWorkspaceFrequencyAction: ({oldFrequency, newFrequency}: UpdatedPolicyFrequencyParams) => `已将自动报表频率更新为“${newFrequency}”（此前为“${oldFrequency}”）`,
         updateApprovalMode: ({newValue, oldValue}: ChangeFieldParams) => `将审批模式更新为“${newValue}”（之前为“${oldValue}”）`,
         upgradedWorkspace: '已将此工作区升级到 Control 方案',
         forcedCorporateUpgrade: `此工作区已升级为 Control 方案。点击<a href="${CONST.COLLECT_UPGRADE_HELP_URL}">此处</a>了解更多信息。`,
         downgradedWorkspace: '将此工作区降级为 Collect 方案',
-        updatedAuditRate: (oldAuditRate: number, newAuditRate: number) =>
+        updatedAuditRate: ({oldAuditRate, newAuditRate}: UpdatedPolicyAuditRateParams) =>
             `已将随机路由进行人工审批的报销单比例更改为 ${Math.round(newAuditRate * 100)}%（之前为 ${Math.round(oldAuditRate * 100)}%）`,
-        updatedManualApprovalThreshold: (oldLimit: string, newLimit: string) => `将所有报销的人工审批限额更改为 ${newLimit}（此前为 ${oldLimit}）`,
+        updatedManualApprovalThreshold: ({oldLimit, newLimit}: UpdatedPolicyManualApprovalThresholdParams) => `将所有报销的人工审批限额更改为 ${newLimit}（此前为 ${oldLimit}）`,
         updatedFeatureEnabled: ({enabled, featureName}: {enabled: boolean; featureName: string}) => {
             switch (featureName) {
                 case 'categories':
@@ -7517,21 +6586,19 @@ ${reportName}
                 case 'accounting':
                     return `${enabled ? '已启用' : '已禁用'} 会计`;
                 case 'Expensify Cards':
-                    return `${enabled ? '已启用' : '已禁用'} Expensify 卡`;
-                case 'travel invoicing':
-                    return `${enabled ? '已启用' : '已禁用'} 差旅发票`;
+                    return `${enabled ? '已启用' : '已禁用'} Expensify 卡片`;
                 case 'company cards':
                     return `${enabled ? '已启用' : '已禁用'} 张公司卡`;
                 case 'invoicing':
                     return `${enabled ? '已启用' : '已禁用'} 开具发票`;
                 case 'per diem':
-                    return `${enabled ? '已启用' : '已禁用'} 每日津贴`;
+                    return `${enabled ? '已启用' : '已禁用'} 日津贴`;
                 case 'receipt partners':
                     return `${enabled ? '已启用' : '已禁用'} 个收据合作伙伴`;
                 case 'rules':
                     return `${enabled ? '已启用' : '已禁用'} 条规则`;
                 case 'tax tracking':
-                    return `${enabled ? '已启用' : '已禁用'} 税务追踪`;
+                    return `${enabled ? '已启用' : '已禁用'} 税务跟踪`;
                 default:
                     return `${enabled ? '已启用' : '已禁用'} ${featureName}`;
             }
@@ -7595,15 +6662,12 @@ ${reportName}
             oldValue ? `将发票公司名称更改为“${newValue}”（原为“${oldValue}”）` : `将发票公司名称设置为“${newValue}”`,
         changedInvoiceCompanyWebsite: ({newValue, oldValue}: {newValue: string; oldValue?: string}) =>
             oldValue ? `将发票公司的网站更改为“${newValue}”（原为“${oldValue}”）` : `将发票公司网站设置为“${newValue}”`,
-        changedReimburser: (newReimburser: string, previousReimburser?: string) =>
+        changedReimburser: ({newReimburser, previousReimburser}: UpdatedPolicyReimburserParams) =>
             previousReimburser ? `将授权付款人更改为“${newReimburser}”（之前为“${previousReimburser}”）` : `已将授权付款人更改为“${newReimburser}”`,
-        updateReimbursementEnabled: (enabled: boolean) => `${enabled ? '已启用' : '已禁用'} 笔报销`,
-        updateCustomTaxName: (oldName: string, newName: string) => `将自定义税种名称更改为"${newName}"（之前为"${oldName}"）`,
-        updateCurrencyDefaultTax: (oldName: string, newName: string) => `将工作区货币的默认税率更改为"${newName}"（之前为"${oldName}"）`,
-        updateForeignCurrencyDefaultTax: (oldName: string, newName: string) => `将外币默认税率更改为"${newName}"（之前为"${oldName}"）`,
-        addTax: (taxName: string) => `已添加税费"${taxName}"`,
-        deleteTax: (taxName: string) => `已移除税费“${taxName}”`,
-        updateTax: (oldValue?: string | boolean | number, taxName?: string, updatedField?: string, newValue?: string | boolean | number) => {
+        updateReimbursementEnabled: ({enabled}: UpdatedPolicyReimbursementEnabledParams) => `${enabled ? '已启用' : '已禁用'} 笔报销`,
+        addTax: ({taxName}: UpdatedPolicyTaxParams) => `已添加税费“${taxName}”`,
+        deleteTax: ({taxName}: UpdatedPolicyTaxParams) => `已移除税费“${taxName}”`,
+        updateTax: ({oldValue, taxName, updatedField, newValue}: UpdatedPolicyTaxParams) => {
             if (!updatedField) {
                 return '';
             }
@@ -7625,31 +6689,28 @@ ${reportName}
                 }
             }
         },
-        setReceiptRequiredAmount: (newValue: string) => `将需要收据的金额设置为“${newValue}”`,
-        changedReceiptRequiredAmount: (oldValue: string, newValue: string) => `已将所需收据金额更改为“${newValue}”（之前为“${oldValue}”）`,
-        removedReceiptRequiredAmount: (oldValue: string) => `已移除所需收据金额（先前为“${oldValue}”）`,
-        setItemizedReceiptRequiredAmount: (newValue: string) => `将分项收据所需金额设置为”${newValue}”`,
-        changedItemizedReceiptRequiredAmount: (oldValue: string, newValue: string) => `将逐项列示收据的必填金额更改为 “${newValue}”（之前为 “${oldValue}”）`,
-        removedItemizedReceiptRequiredAmount: (oldValue: string) => `已移除按项目明细收据所需金额（先前为”${oldValue}”）`,
-        setMaxExpenseAmount: (newValue: string) => `将最高报销金额设置为”${newValue}”`,
-        changedMaxExpenseAmount: (oldValue: string, newValue: string) => `将最高报销金额更改为 “${newValue}”（之前为 “${oldValue}”）`,
-        removedMaxExpenseAmount: (oldValue: string) => `已移除最⾼报销金额（原为“${oldValue}”）`,
-        setMaxExpenseAge: (newValue: string) => `将最大报销天数设置为“${newValue}”天`,
-        changedMaxExpenseAge: (oldValue: string, newValue: string) => `将最大报销单据天数更改为 “${newValue}” 天（之前为 “${oldValue}”）`,
-        removedMaxExpenseAge: (oldValue: string) => `已移除费用最长期限（之前为“${oldValue}”天）`,
-        updateCategories: (count: number) => `已更新 ${count} 个类别`,
-        updateTagList: (tagListName: string) => `已更新列表“${tagListName}”上的标签`,
-        updateTagListRequired: (tagListsName: string, isRequired: boolean) => `将标签列表“${tagListsName}”更改为 ${isRequired ? '必填' : '非必填'}`,
+        setReceiptRequiredAmount: ({newValue}: UpdatedPolicyFieldWithNewAndOldValueParams) => `将需要收据的金额设置为“${newValue}”`,
+        changedReceiptRequiredAmount: ({oldValue, newValue}: UpdatedPolicyFieldWithNewAndOldValueParams) => `已将所需收据金额更改为“${newValue}”（之前为“${oldValue}”）`,
+        removedReceiptRequiredAmount: ({oldValue}: UpdatedPolicyFieldWithNewAndOldValueParams) => `已移除所需收据金额（先前为“${oldValue}”）`,
+        setMaxExpenseAmount: ({newValue}: UpdatedPolicyFieldWithNewAndOldValueParams) => `将最高报销金额设置为“${newValue}”`,
+        changedMaxExpenseAmount: ({oldValue, newValue}: UpdatedPolicyFieldWithNewAndOldValueParams) => `将最高报销金额更改为 “${newValue}”（之前为 “${oldValue}”）`,
+        removedMaxExpenseAmount: ({oldValue}: UpdatedPolicyFieldWithNewAndOldValueParams) => `已移除最⾼报销金额（原为“${oldValue}”）`,
+        setMaxExpenseAge: ({newValue}: UpdatedPolicyFieldWithNewAndOldValueParams) => `将最大报销天数设置为“${newValue}”天`,
+        changedMaxExpenseAge: ({oldValue, newValue}: UpdatedPolicyFieldWithNewAndOldValueParams) => `将最大报销单据天数更改为 “${newValue}” 天（之前为 “${oldValue}”）`,
+        removedMaxExpenseAge: ({oldValue}: UpdatedPolicyFieldWithNewAndOldValueParams) => `已移除费用最长期限（之前为“${oldValue}”天）`,
+        updateCategories: ({count}: UpdatedPolicyCategoriesParams) => `已更新 ${count} 个类别`,
+        updateTagList: ({tagListName}: UpdatedPolicyTagListParams) => `已更新列表“${tagListName}”上的标签`,
+        updateTagListRequired: ({tagListsName, isRequired}: UpdatedPolicyTagListRequiredParams) => `将标签列表“${tagListsName}”更改为 ${isRequired ? '必填' : '非必填'}`,
         importTags: '已从电子表格导入标签',
         deletedAllTags: '已删除所有标签',
-        updateCustomUnitDefaultCategory: (customUnitName: string, newValue?: string, oldValue?: string) =>
+        updateCustomUnitDefaultCategory: ({customUnitName, newValue, oldValue}: UpdatePolicyCustomUnitDefaultCategoryParams) =>
             `已将${customUnitName}的默认类别更改为“${newValue}” ${oldValue ? `（原为“${oldValue}”）` : ''}`,
-        importCustomUnitRates: (customUnitName: string) => `已导入自定义单位“${customUnitName}”的费率`,
-        updateCustomUnitSubRate: (customUnitName: string, customUnitRateName: string, customUnitSubRateName: string, oldValue: string, newValue: string, updatedField: string) =>
+        importCustomUnitRates: ({customUnitName}: ImportPolicyCustomUnitRatesParams) => `已导入自定义单位“${customUnitName}”的费率`,
+        updateCustomUnitSubRate: ({customUnitName, customUnitRateName, customUnitSubRateName, oldValue, newValue, updatedField}: UpdatedPolicyCustomUnitSubRateParams) =>
             `已将“${customUnitName}”费率“${customUnitRateName}”子费率“${customUnitSubRateName}”的${updatedField}修改为“${newValue}”（之前为“${oldValue}”）`,
-        removedCustomUnitSubRate: (customUnitName: string, customUnitRateName: string, removedSubRateName: string) =>
+        removedCustomUnitSubRate: ({customUnitName, customUnitRateName, removedSubRateName}: RemovedPolicyCustomUnitSubRateParams) =>
             `已移除“${customUnitName}”费率“${customUnitRateName}”子费率“${removedSubRateName}”`,
-        addBudget: (frequency: string, entityName: string, entityType: string, shared?: string, individual?: string, notificationThreshold?: number) => {
+        addBudget: ({frequency, entityName, entityType, shared, individual, notificationThreshold}: AddBudgetParams) => {
             const thresholdSuffix = typeof notificationThreshold === 'number' ? `，通知阈值为“${notificationThreshold}%”` : '';
             if (typeof shared !== 'undefined' && typeof individual !== 'undefined') {
                 return `已向${entityType}“${entityName}”添加${frequency}个个人预算“${individual}”和${frequency}个共享预算“${shared}”${thresholdSuffix}`;
@@ -7659,18 +6720,18 @@ ${reportName}
             }
             return `已将 ${frequency} 共享预算“${shared}”${thresholdSuffix} 添加到 ${entityType}“${entityName}”中`;
         },
-        updateBudget: (
-            entityType: string,
-            entityName: string,
-            oldFrequency?: string,
-            newFrequency?: string,
-            oldIndividual?: string,
-            newIndividual?: string,
-            oldShared?: string,
-            newShared?: string,
-            oldNotificationThreshold?: number,
-            newNotificationThreshold?: number,
-        ) => {
+        updateBudget: ({
+            entityType,
+            entityName,
+            oldFrequency,
+            newFrequency,
+            oldIndividual,
+            newIndividual,
+            oldShared,
+            newShared,
+            oldNotificationThreshold,
+            newNotificationThreshold,
+        }: UpdatedBudgetParams) => {
             const frequencyChanged = !!(newFrequency && oldFrequency !== newFrequency);
             const sharedChanged = !!(newShared && oldShared !== newShared);
             const individualChanged = !!(newIndividual && oldIndividual !== newIndividual);
@@ -7705,7 +6766,7 @@ ${reportName}
             }
             return `已更新 ${entityType}“${entityName}”的预算：${changesList.join('; ')}`;
         },
-        deleteBudget: (entityType: string, entityName: string, frequency?: string, individual?: string, shared?: string, notificationThreshold?: number) => {
+        deleteBudget: ({entityType, entityName, frequency, individual, shared, notificationThreshold}: DeleteBudgetParams) => {
             const thresholdSuffix = typeof notificationThreshold === 'number' ? `，通知阈值为“${notificationThreshold}%”` : '';
             if (shared && individual) {
                 return `已从${entityType}“${entityName}”中移除${frequency}共享预算“${shared}”和个人预算“${individual}”${thresholdSuffix}`;
@@ -7718,117 +6779,47 @@ ${reportName}
             }
             return `已从${entityType}“${entityName}”中移除预算`;
         },
-        updatedTimeEnabled: (enabled?: boolean) => {
+        updatedTimeEnabled: ({enabled}: UpdatedPolicyTimeEnabledParams) => {
             return `${enabled ? '已启用' : '已禁用'} 时间追踪`;
         },
-        updatedTimeRate: (newRate?: string, oldRate?: string) => {
+        updatedTimeRate: ({newRate, oldRate}: UpdatedPolicyTimeRateParams) => {
             return `将时薪更改为“${newRate}”（之前为“${oldRate}”）`;
         },
         addedProhibitedExpense: ({prohibitedExpense}: {prohibitedExpense: string}) => `已将“${prohibitedExpense}”添加到禁止报销的费用中`,
         removedProhibitedExpense: ({prohibitedExpense}: {prohibitedExpense: string}) => `已从禁用报销类别中移除“${prohibitedExpense}”`,
-        updatedReimbursementChoice: (newReimbursementChoice: string, oldReimbursementChoice: string) => `将报销方式更改为“${newReimbursementChoice}”（原为“${oldReimbursementChoice}”）`,
+        updatedReimbursementChoice: ({newReimbursementChoice, oldReimbursementChoice}: UpdatedPolicyReimbursementChoiceParams) =>
+            `将报销方式更改为“${newReimbursementChoice}”（原为“${oldReimbursementChoice}”）`,
         setAutoJoin: ({enabled}: {enabled: boolean}) => `${enabled ? '已启用' : '已禁用'} 预先批准加入工作区的请求`,
-        updatedDefaultTitle: (newDefaultTitle: string, oldDefaultTitle: string) => `将自定义报表名称公式更改为“${newDefaultTitle}”（之前为“${oldDefaultTitle}”）`,
-        updatedOwnership: (oldOwnerEmail: string, oldOwnerName: string, policyName: string) => `从 ${oldOwnerName}（${oldOwnerEmail}）接管了 ${policyName} 的所有权`,
-        updatedAutoHarvesting: (enabled: boolean) => `已计划提交 ${enabled ? '已启用' : '已禁用'}`,
-        updatedIndividualBudgetNotification: (
-            budgetAmount: string,
-            budgetFrequency: string,
-            budgetName: string,
-            budgetTypeForNotificationMessage: string,
-            thresholdPercentage: number,
-            totalSpend: number,
-            unsubmittedSpend: number,
-            awaitingApprovalSpend: number,
-            approvedReimbursedClosedSpend: number,
-            summaryLink?: string,
-            userEmail?: string,
-        ) =>
+        updatedDefaultTitle: ({newDefaultTitle, oldDefaultTitle}: UpdatedPolicyDefaultTitleParams) => `将自定义报表名称公式更改为“${newDefaultTitle}”（之前为“${oldDefaultTitle}”）`,
+        updatedOwnership: ({oldOwnerEmail, oldOwnerName, policyName}: UpdatedPolicyOwnershipParams) => `从 ${oldOwnerName}（${oldOwnerEmail}）接管了 ${policyName} 的所有权`,
+        updatedAutoHarvesting: ({enabled}: UpdatedPolicyAutoHarvestingParams) => `已计划提交 ${enabled ? '已启用' : '已禁用'}`,
+        updatedIndividualBudgetNotification: ({
+            budgetAmount,
+            budgetFrequency,
+            budgetName,
+            budgetTypeForNotificationMessage,
+            summaryLink,
+            thresholdPercentage,
+            totalSpend,
+            unsubmittedSpend,
+            userEmail,
+            awaitingApprovalSpend,
+            approvedReimbursedClosedSpend,
+        }: UpdatedPolicyBudgetNotificationParams) =>
             `注意！此工作区的「${budgetTypeForNotificationMessage}：${budgetName}」有一项${budgetFrequency}预算，金额为「${budgetAmount}」。${userEmail} 当前支出为 ${approvedReimbursedClosedSpend}，已超过预算的 ${thresholdPercentage}%。另外还有 ${awaitingApprovalSpend} 正在等待审批，以及 ${unsubmittedSpend} 尚未提交，总计为 ${totalSpend}。${summaryLink ? `<a href="${summaryLink}">这里有一份报表</a>，包含了所有这些报销，供你留档！` : ''}`,
-        updatedSharedBudgetNotification: (
-            budgetAmount: string,
-            budgetFrequency: string,
-            budgetName: string,
-            budgetTypeForNotificationMessage: string,
-            summaryLink: string | undefined,
-            thresholdPercentage: number,
-            totalSpend: number,
-            unsubmittedSpend: number,
-            awaitingApprovalSpend: number,
-            approvedReimbursedClosedSpend: number,
-        ) =>
+        updatedSharedBudgetNotification: ({
+            budgetAmount,
+            budgetFrequency,
+            budgetName,
+            budgetTypeForNotificationMessage,
+            summaryLink,
+            thresholdPercentage,
+            totalSpend,
+            unsubmittedSpend,
+            awaitingApprovalSpend,
+            approvedReimbursedClosedSpend,
+        }: UpdatedPolicyBudgetNotificationParams) =>
             `提醒！此工作区的${budgetTypeForNotificationMessage}“${budgetName}”设有${budgetFrequency}预算“${budgetAmount}”。你当前已花费${approvedReimbursedClosedSpend}，已超过预算的${thresholdPercentage}%。另外还有${awaitingApprovalSpend}在等待审批，以及${unsubmittedSpend}尚未提交，总计${totalSpend}。${summaryLink ? `<a href="${summaryLink}">这里有一份报表</a>，包含了所有相关报销记录，供你留档保存！` : ''}`,
-        addedCardFeed: (feedName: string) => `已添加卡片流水“${feedName}”`,
-        removedCardFeed: (feedName: string) => `已移除卡片流水 “${feedName}”`,
-        renamedCardFeed: (newName: string, oldName: string) => `已将卡片流水从“${oldName}”重命名为“${newName}”`,
-        assignedCompanyCard: (email: string, feedName: string, cardLastFour: string) => `已分配以 ${cardLastFour} 结尾的${feedName ? `"${feedName}"` : ''}公司卡给 ${email}`,
-        unassignedCompanyCard: (email: string, feedName: string, cardLastFour: string) => `未分配的 ${email} ${feedName ? `"${feedName}"` : ''}公司卡（末尾为 ${cardLastFour}）`,
-        updatedCardFeedLiability: (feedName: string, enabled: boolean) => `允许 ${enabled ? '已启用' : '已禁用'} 持卡人删除卡片交易（卡片流水来源：“${feedName}”）`,
-        updatedCardFeedStatementPeriod: (feedName: string, newValue?: string, previousValue?: string) =>
-            `已更改卡片流水“${feedName}”的账单周期截止日${newValue ? ` 为“${newValue}”` : ''}${previousValue ? ` （先前为“${previousValue}”）` : ''}`,
-        updatedMccGroupCategory: ({mccGroupName, oldCategory, newCategory}: {mccGroupName: string; oldCategory: string; newCategory: string}) =>
-            `已将“${mccGroupName}”的默认支出类别更改为“${newCategory}”（此前为“${oldCategory}”）`,
-        addedReportField: (fieldType: string, fieldName?: string, defaultValue?: string) => `已添加 ${fieldType} 报告字段“${fieldName}”${defaultValue ? ` 默认值为“${defaultValue}”` : ''}`,
-        updatedRequireCompanyCards: ({enabled}: {enabled: boolean}) => `${enabled ? '已启用' : '已禁用'} 公司商务卡消费要求`,
-        expensifyCardRule: {
-            actionVerb: {block: '已阻止', allow: '允许'},
-            amountOperator: {over: '结束', under: '在……之下'},
-            amountFilter: ({operator, amount}: {operator: string; amount: string}) => `金额 ${operator} ${amount}`,
-            theCard: '该卡',
-            multipleCards: ({count}: {count: number}) => ({
-                one: '1 张卡片',
-                other: `${count} 张卡片`,
-            }),
-            addRule: ({verb, filters, cards}: {verb: string; filters: string; cards: string}) => {
-                let text = verb;
-                if (filters !== '') {
-                    text += ` ${filters}`;
-                }
-                text += ` 在 ${cards}`;
-                return text;
-            },
-            removeRule: ({cards}: {cards: string}) => `已从 ${cards} 中移除消费规则`,
-            restrictionVerb: {block: '阻止', allow: '仅允许'},
-            update: {
-                modeChange: ({fromAction, toAction, cards}: {fromAction: string; toAction: string; cards: string}) => `已将 ${cards} 的消费规则从 ${fromAction} 更改为 ${toAction}`,
-                appliedToAdditionalCards: ({count}: {count: number}) => ({
-                    one: '已将支出规则应用于另外 1 张卡片',
-                    other: `已将支出规则应用于另外 ${count} 张卡片`,
-                }),
-                phraseVerb: {added: '已添加', removed: '已移除', changed: '已更改', set: '设置', applied: '已应用'},
-                bodyMerchant: ({adjective, value}: {adjective: string; value: string}) => (adjective !== '' ? `${adjective} 商家“${value}”` : `商户“${value}”`),
-                bodyMerchantChange: ({adjective, oldValue, newValue}: {adjective: string; oldValue: string; newValue: string}) =>
-                    adjective !== '' ? `将商家 ${adjective} 从“${oldValue}”更改为“${newValue}”` : `商户从“${oldValue}”变更为“${newValue}”`,
-                bodySpendCategory: ({adjective, value}: {adjective: string; value: string}) => (adjective !== '' ? `${adjective}支出类别“${value}”` : `支出类别「${value}」`),
-                bodySpendCategoryChange: ({adjective, oldValue, newValue}: {adjective: string; oldValue: string; newValue: string}) =>
-                    adjective !== '' ? `将${adjective}支出类别从“${oldValue}”修改为“${newValue}”` : `支出类别从“${oldValue}”更改为“${newValue}”`,
-                bodyMaxAmount: '最大金额',
-                bodyMaxAmountSet: ({value}: {value: string}) => `最大金额至 ${value}`,
-                bodyMaxAmountChange: ({oldValue, newValue}: {oldValue: string; newValue: string}) => `最大金额从 ${oldValue} 变为 ${newValue}`,
-                bodyAppliedToAdditionalCards: ({count}: {count: number}) => ({
-                    one: '将消费规则应用到另外 1 张卡片',
-                    other: `将消费规则应用到另外 ${count} 张卡片`,
-                }),
-                bodyRemovedFromCards: ({cards}: {cards: string}) => `来自 ${cards} 的消费规则`,
-                composeOnCards: ({content, cards}: {content: string; cards: string}) => `${cards} 上的 ${content}`,
-                composeFromCards: ({content, cards}: {content: string; cards: string}) => `来自 ${cards} 的 ${content}`,
-            },
-        },
-        addCustomUnitRateWithAmount: (rateName: string, rateValue: string) => `已添加“${rateName}”汇率，数值为 ${rateValue}`,
-        addCustomUnitRateWithAmountAndStartDate: (rateName: string, rateValue: string, startDate: string) => `已添加“${rateName}”费率 ${rateValue}，自 ${startDate} 起生效`,
-        addCustomUnitRateWithAmountAndEndDate: (rateName: string, rateValue: string, endDate: string) => `已添加“${rateName}”费率 ${rateValue}，有效期至 ${endDate}`,
-        addCustomUnitRateWithAmountAndDates: (rateName: string, rateValue: string, startDate: string, endDate: string) =>
-            `已添加“${rateName}”费率 ${rateValue}，有效期为 ${startDate} - ${endDate}`,
-        updatedCustomUnitRateStartDate: (rateName: string, newDate: string, oldDate?: string) =>
-            oldDate ? `将“${rateName}”费率的开始日期更新为 ${newDate}（之前为 ${oldDate}）` : `将“${rateName}”费率的开始日期设置为 ${newDate}`,
-        updatedCustomUnitRateEndDate: (rateName: string, newDate: string, oldDate?: string) =>
-            oldDate ? `已将“${rateName}”费率的结束日期更新为 ${newDate}（之前为 ${oldDate}）` : `将“${rateName}”费率的结束日期设置为 ${newDate}`,
-        updatedCustomUnitRateStartAndEndDate: (rateName: string, newStartDate: string, newEndDate: string, oldStartDate?: string, oldEndDate?: string) =>
-            oldStartDate && oldEndDate
-                ? `已将“${rateName}”费率的起止日期更新为 ${newStartDate} - ${newEndDate}（此前为 ${oldStartDate} - ${oldEndDate}）`
-                : `将“${rateName}”费率的开始和结束日期设为 ${newStartDate} - ${newEndDate}`,
-        removedCustomUnitRateStartDate: (rateName: string, oldDate: string) => `已从“${rateName}”费率中移除开始日期（原为 ${oldDate}）`,
-        removedCustomUnitRateEndDate: (rateName: string, oldDate: string) => `已从“${rateName}”费率中移除结束日期（之前为 ${oldDate}）`,
     },
     roomMembersPage: {
         memberNotFound: '未找到成员。',
@@ -7860,7 +6851,7 @@ ${reportName}
         completed: '已完成',
         action: '完成',
         messages: {
-            created: (title: string) => `${title} 的任务`,
+            created: ({title}: TaskCreatedActionParams) => `${title} 的任务`,
             completed: '标记为已完成',
             canceled: '已删除的任务',
             reopened: '标记为未完成',
@@ -7874,7 +6865,7 @@ ${reportName}
         deleteConfirmation: '确定要删除此任务吗？',
     },
     statementPage: {
-        title: (year: number | string, monthName: string) => `${year}年${monthName}对账单`,
+        title: ({year, monthName}: StatementTitleParams) => `${year}年${monthName}对账单`,
     },
     keyboardShortcutsPage: {
         title: '键盘快捷键',
@@ -7887,8 +6878,6 @@ ${reportName}
             newChat: '新聊天界面',
             copy: '复制评论',
             openDebug: '打开测试首选项对话框',
-            expenseReportSearch: '搜索报销报告',
-            goToWorkspace: '前往当前报表的工作区',
         },
     },
     guides: {
@@ -7898,24 +6887,34 @@ ${reportName}
     search: {
         resultsAreLimited: '搜索结果已受限制。',
         viewResults: '查看结果',
-        applyFilters: '应用筛选条件',
-        appliedFilters: '已应用的筛选条件',
         resetFilters: '重置筛选条件',
         searchResults: {
             emptyResults: {
                 title: '暂无内容',
                 subtitle: `请尝试调整搜索条件，或使用 “+” 按钮创建新项目。`,
             },
-            emptyExpenseResults: {title: '还没有报销费用', subtitle: '创建一笔报销，或试用 Expensify 以了解更多。', subtitleWithOnlyCreateButton: '使用下面的绿色按钮来创建一笔报销。'},
-            emptyReportResults: {title: '尚无报表', subtitle: '创建报表或试用 Expensify，了解更多信息。', subtitleWithOnlyCreateButton: '使用下方的绿色按钮创建报表。'},
+            emptyExpenseResults: {
+                title: '你还没有创建任何报销记录',
+                subtitle: '创建一笔报销，或试用 Expensify 以了解更多。',
+                subtitleWithOnlyCreateButton: '使用下面的绿色按钮来创建一笔报销。',
+            },
+            emptyReportResults: {
+                title: '你还没有创建任何报销报告',
+                subtitle: '创建报表或试用 Expensify，了解更多信息。',
+                subtitleWithOnlyCreateButton: '使用下方的绿色按钮创建报表。',
+            },
             emptyInvoiceResults: {
-                title: '还没有发票',
+                title: dedent(`
+                    你还没有创建任何发票
+                `),
                 subtitle: '发送发票或试用 Expensify，了解更多信息。',
                 subtitleWithOnlyCreateButton: '使用下方的绿色按钮发送发票。',
-                subtitleCannotSend: '您需要一个启用了Invoices的工作区才能发送发票。',
-                subtitleCannotSendWithTestDrive: '您需要一个启用了Invoices的工作区才能发送发票。试用 Expensify，了解更多信息。',
             },
-            emptyTripResults: {title: '暂无行程', subtitle: '从下面开始预订您的第一趟行程。', buttonText: '预订行程'},
+            emptyTripResults: {
+                title: '没有行程可显示',
+                subtitle: '从下面开始预订您的第一趟行程。',
+                buttonText: '预订行程',
+            },
             emptySubmitResults: {
                 title: '没有可提交的报销',
                 subtitle: '一切就绪，庆祝一下你的胜利吧！',
@@ -7943,31 +6942,30 @@ ${reportName}
             },
         },
         columns: '列',
-        editColumns: '编辑列',
         resetColumns: '重置列',
         groupColumns: '分组列',
         expenseColumns: '报销列',
-        saveView: '保存视图',
+        statements: '对账单',
+        unapprovedCash: '未批准现金',
+        unapprovedCard: '未批准的卡片',
+        reconciliation: '对账',
+        topSpenders: '最高支出者',
+        saveSearch: '保存搜索',
         deleteSavedSearch: '删除已保存的搜索',
         deleteSavedSearchConfirm: '确定要删除此搜索吗？',
         searchName: '搜索名称',
         savedSearchesMenuItemTitle: '已保存',
-        urlCopied: 'URL 已复制',
+        topCategories: '热门类别',
+        topMerchants: '热门商家',
         groupedExpenses: '已分组的报销费用',
         bulkActions: {
-            editMultiple: '批量编辑',
-            editMultipleTitle: '编辑多个费用',
-            editMultipleDescription: '更改将应用于所有选中的报销，并覆盖任何先前设置的值。',
             approve: '批准',
             pay: '支付',
             delete: '删除',
             hold: '暂挂',
             unhold: '解除保留',
             reject: '拒绝',
-            duplicateExpense: ({count}: {count: number}) => `复制${count === 1 ? '报销' : '报销费用'}`,
             noOptionsAvailable: '所选报销的费用组没有可用选项。',
-            undelete: '取消删除',
-            duplicateReport: ({count}: {count: number}) => `重复 ${count === 1 ? '报表' : '报表'}`,
         },
         filtersHeader: '筛选器',
         filters: {
@@ -7975,14 +6973,11 @@ ${reportName}
                 before: (date?: string) => `在 ${date ?? ''} 之前`,
                 after: (date?: string) => `在 ${date ?? ''} 之后`,
                 on: (date?: string) => `在 ${date ?? ''} 上`,
-                customDate: '自定义日期',
-                customRange: '自定义范围',
                 presets: {
                     [CONST.SEARCH.DATE_PRESETS.NEVER]: '从不',
                     [CONST.SEARCH.DATE_PRESETS.LAST_MONTH]: '上个月',
                     [CONST.SEARCH.DATE_PRESETS.THIS_MONTH]: '本月',
                     [CONST.SEARCH.DATE_PRESETS.YEAR_TO_DATE]: '本年度至今',
-                    [CONST.SEARCH.DATE_PRESETS.LAST_12_MONTHS]: '过去 12 个月',
                     [CONST.SEARCH.DATE_PRESETS.LAST_STATEMENT]: '上一期对账单',
                 },
             },
@@ -7994,15 +6989,10 @@ ${reportName}
             currency: '货币',
             completed: '已完成',
             amount: {
-                lessThan: (amount?: string) => `少于 ${amount ?? ''}`,
-                greaterThan: (amount?: string) => `大于 ${amount ?? ''}`,
-                between: (greaterThan?: string, lessThan?: string) => {
-                    if (greaterThan && lessThan) {
-                        return `介于 ${greaterThan} 和 ${lessThan} 之间`;
-                    }
-                    return '之间';
-                },
-                equalTo: (amount?: string) => `等于 ${amount ?? ''}`,
+                lessThan: ({amount}: OptionalParam<RequestAmountParams> = {}) => `少于 ${amount ?? ''}`,
+                greaterThan: ({amount}: OptionalParam<RequestAmountParams> = {}) => `大于 ${amount ?? ''}`,
+                between: (greaterThan: string, lessThan: string) => `介于 ${greaterThan} 和 ${lessThan} 之间`,
+                equalTo: ({amount}: OptionalParam<RequestAmountParams> = {}) => `等于 ${amount ?? ''}`,
             },
             card: {
                 expensify: 'Expensify',
@@ -8012,9 +7002,8 @@ ${reportName}
                 cardFeedName: ({cardFeedBankName, cardFeedLabel}: {cardFeedBankName: string; cardFeedLabel?: string}) =>
                     `所有 ${cardFeedBankName}${cardFeedLabel ? ` - ${cardFeedLabel}` : ''}`,
                 cardFeedNameCSV: ({cardFeedLabel}: {cardFeedLabel?: string}) => `所有导入的 CSV 卡片${cardFeedLabel ? ` - ${cardFeedLabel}` : ''}`,
-                travelInvoicing: '差旅开票',
             },
-            reportField: (name: string, value: string) => `${name} 为 ${value}`,
+            reportField: ({name, value}: OptionalParam<ReportFieldParams>) => `${name} 为 ${value}`,
             current: '当前',
             past: '过去',
             submitted: '已提交',
@@ -8026,10 +7015,6 @@ ${reportName}
             billable: '可计费',
             reimbursable: '可报销',
             purchaseCurrency: '购买货币',
-            sortOrder: {
-                [CONST.SEARCH.SORT_ORDER.ASC]: '升序',
-                [CONST.SEARCH.SORT_ORDER.DESC]: '降序',
-            },
             groupBy: {
                 [CONST.SEARCH.GROUP_BY.FROM]: '来自',
                 [CONST.SEARCH.GROUP_BY.CARD]: '卡片',
@@ -8046,7 +7031,6 @@ ${reportName}
             withdrawalType: {
                 [CONST.SEARCH.WITHDRAWAL_TYPE.EXPENSIFY_CARD]: 'Expensify 卡',
                 [CONST.SEARCH.WITHDRAWAL_TYPE.REIMBURSEMENT]: '报销',
-                [CONST.SEARCH.WITHDRAWAL_TYPE.CENTRAL_TRAVEL_INVOICING]: '差旅开票',
             },
             is: '是',
             action: {
@@ -8056,15 +7040,14 @@ ${reportName}
                 [CONST.SEARCH.ACTION_FILTERS.EXPORT]: '导出',
             },
         },
-        display: {
-            label: '显示',
-            sortBy: '按排序',
-            sortOrder: '排序顺序',
-            groupBy: '分组依据',
-            limitResults: '限制结果',
-        },
         has: '有',
-        view: {label: '查看', table: '表格', bar: '栏', line: '折线', pie: '饼图'},
+        groupBy: '分组依据',
+        view: {
+            label: '查看',
+            table: '表',
+            bar: '栏',
+            line: '折线',
+        },
         chartTitles: {
             [CONST.SEARCH.GROUP_BY.FROM]: '来自',
             [CONST.SEARCH.GROUP_BY.CARD]: '卡片',
@@ -8088,49 +7071,17 @@ ${reportName}
         withdrawalType: '提款类型',
         recentSearches: '最近搜索',
         recentChats: '最近聊天',
-        serverResults: '搜索结果',
         searchIn: '搜索范围',
-        askConcierge: (message: string) => `询问 Concierge“${message}”`,
-        searchPlaceholder: '搜索内容...',
+        searchPlaceholder: '搜索内容',
         suggestions: '建议',
-        suggestionsAvailable: (
-            {
-                count,
-            }: {
-                count: number;
-            },
-            query = '',
-        ) => ({
-            one: `有可用建议${query ? `：${query}` : ''}。共${count}条结果。`,
-            other: (resultCount: number) => `有可用建议${query ? `：${query}` : ''}。共${resultCount}条结果。`,
-        }),
         exportSearchResults: {
             title: '创建导出',
             description: '哇，项目真不少！我们会把它们打包好，Concierge 很快就会给你发送一个文件。',
         },
         exportedTo: '已导出到',
-        exportAll: {selectAllMatchingItems: '选择所有匹配的项目', allMatchingItemsSelected: '已选择所有匹配的项目', selectAllOnThisPage: '选择本页全部内容'},
-        errors: {
-            pleaseSelectDatesForBothFromAndTo: '请选择起始和结束日期',
-        },
-        spendOverTime: '随时间支出',
-        tabs: {
-            expenseReports: '报销报告',
-            reports: '报表',
-            expenses: '报销费用',
-            submit: '草稿',
-            approve: '待审批',
-            pay: '准备付款',
-            accounting: '会计',
-            export: '等待导出',
-            unapprovedCash: '现金应计',
-            unapprovedCard: '卡应计费用',
-            statements: '卡片对账单',
-            reconciliation: '银行对账',
-            insights: '洞察',
-            topSpenders: '最高消费者',
-            topCategories: '热门类别',
-            topMerchants: '热门商家',
+        exportAll: {
+            selectAllMatchingItems: '选择所有匹配的项目',
+            allMatchingItemsSelected: '已选中所有匹配项',
         },
     },
     genericErrorPage: {
@@ -8185,6 +7136,7 @@ ${reportName}
             chooseWorkspace: '为此报表选择一个工作区。',
             emptyReportConfirmationTitle: '你已经有一份空报表了',
             emptyReportConfirmationPrompt: ({workspaceName}: {workspaceName: string}) => `您确定要在 ${workspaceName} 中创建另一份报表吗？您可以在以下位置访问您的空报表`,
+            emptyReportConfirmationPromptLink: '报表',
             emptyReportConfirmationDontShowAgain: '不再显示此内容',
             genericWorkspaceName: '此工作区',
         },
@@ -8222,7 +7174,6 @@ ${reportName}
                     reimburseableLink: '自付报销费用',
                     nonReimbursableLink: '公司卡消费',
                     pending: (label: string) => `已开始将此报表导出到 ${label}…`,
-                    travelCardLink: '差旅卡费用',
                 },
                 integrationsMessage: (errorMessage: string, label: string, linkText?: string, linkURL?: string) =>
                     `未能将此报表导出到 ${label}（“${errorMessage}${linkText ? `<a href="${linkURL}">${linkText}</a>` : ''}”）`,
@@ -8231,8 +7182,7 @@ ${reportName}
                 markedReimbursed: (amount: string, currency: string) => `在其他地方已支付${currency}${amount}`,
                 markedReimbursedFromIntegration: ({amount, currency}: MarkReimbursedFromIntegrationParams) => `通过集成支付了 ${currency}${amount}`,
                 outdatedBankAccount: `由于付款方的银行账户出现问题，无法处理该付款`,
-                reimbursementACHBounceDefault: `由于路由号/账户号不正确或账户已关闭，无法处理付款`,
-                reimbursementACHBounceWithReason: ({returnReason}: {returnReason: string}) => `无法处理付款：${returnReason}`,
+                reimbursementACHBounce: `由于银行账户问题，无法处理付款`,
                 reimbursementACHCancelled: `已取消付款`,
                 reimbursementAccountChanged: `由于付款人更换了银行账户，无法处理该付款`,
                 reimbursementDelayed: `已处理付款，但将再延迟 1–2 个工作日`,
@@ -8240,28 +7190,23 @@ ${reportName}
                 selectedForRandomAuditMarkdown: `[随机选择](https://help.expensify.com/articles/expensify-classic/reports/Set-a-random-report-audit-schedule)进行审核`,
                 share: ({to}: ShareParams) => `已邀请成员 ${to}`,
                 unshare: ({to}: UnshareParams) => `已移除成员 ${to}`,
-                stripePaid: (amount: string, currency: string) => `已支付 ${currency}${amount}`,
+                stripePaid: ({amount, currency}: StripePaidParams) => `已支付 ${currency}${amount}`,
                 takeControl: `取得控制权`,
                 integrationSyncFailed: (label: string, errorMessage: string, workspaceAccountingLink?: string) =>
                     `与 ${label}${errorMessage ? ` ("${errorMessage}")` : ''} 同步时出现问题。请在<a href="${workspaceAccountingLink}">工作区设置</a>中修复此问题。`,
-                integrationSyncFailedRecurrence: ({count}: {count: number}) => `（重复 ${count} 次。）`,
                 companyCardConnectionBroken: ({feedName, workspaceCompanyCardRoute}: {feedName: string; workspaceCompanyCardRoute: string}) =>
                     `${feedName} 连接已中断。要恢复银行卡导入，请<a href='${workspaceCompanyCardRoute}'>登录您的银行账户</a>。`,
                 plaidBalanceFailure: ({maskedAccountNumber, walletRoute}: {maskedAccountNumber: string; walletRoute: string}) =>
                     `您与企业银行账户的 Plaid 连接已中断。请<a href='${walletRoute}'>重新连接您的银行账户 ${maskedAccountNumber}</a>，以便继续使用 Expensify 卡。`,
-                addEmployee: (email: string, role: string, didJoinPolicy?: boolean) => {
-                    const translatedRole = String(translations.workspace.common.roleName(role)).toLowerCase();
-                    const article = role === CONST.POLICY.ROLE.AUDITOR ? '一' : 'a';
-                    return didJoinPolicy ? `${email} 通过工作区邀请链接加入` : `已将 ${email} 添加为 ${article} ${translatedRole}`;
-                },
+                addEmployee: (email: string, role: string) => `已将 ${email} 添加为 ${role === 'member' ? 'a' : '一个'} 的 ${role}`,
                 updateRole: ({email, currentRole, newRole}: UpdateRoleParams) => `已将 ${email} 的角色更新为 ${newRole}（先前为 ${currentRole}）`,
-                updatedCustomField1: (email: string, newValue: string, previousValue: string) => {
+                updatedCustomField1: ({email, previousValue, newValue}: UpdatedCustomFieldParams) => {
                     if (!newValue) {
                         return `已移除 ${email} 的自定义字段 1（先前为“${previousValue}”）`;
                     }
                     return !previousValue ? `已将“${newValue}”添加到${email}的自定义字段1` : `将 ${email} 的自定义字段 1 更改为 “${newValue}”（之前为 “${previousValue}”）`;
                 },
-                updatedCustomField2: (email: string, newValue: string, previousValue: string) => {
+                updatedCustomField2: ({email, previousValue, newValue}: UpdatedCustomFieldParams) => {
                     if (!newValue) {
                         return `已移除 ${email} 的自定义字段 2（原为“${previousValue}”）`;
                     }
@@ -8273,12 +7218,8 @@ ${reportName}
                 addedConnection: ({connectionName}: ConnectionNameParams) => `已连接到 ${CONST.POLICY.CONNECTIONS.NAME_USER_FRIENDLY[connectionName]}`,
                 leftTheChat: '已离开聊天',
                 settlementAccountLocked: ({maskedBankAccountNumber}: OriginalMessageSettlementAccountLocked, linkURL: string) =>
-                    `由于报销或 Expensify 卡结算问题，企业银行账户 ${maskedBankAccountNumber} 已被自动锁定。请在<a href="${linkURL}">工作区设置</a>中解决该问题。`,
+                    `由于报销或 Expensify Card 结算出现问题，企业银行账户 ${maskedBankAccountNumber} 已被自动锁定。请在<a href="${linkURL}">工作区设置</a>中修复该问题。`,
                 leftTheChatWithName: (nameOrEmail: string) => `${nameOrEmail ? `${nameOrEmail}: ` : ''}离开了聊天`,
-                actionableCard3DSTransactionApproval: (amount: string, merchant: string | undefined) => {
-                    const amountAndMerchantText = [amount, merchant].filter((s) => !!s?.length).join(' ');
-                    return `打开 Expensify 移动应用以查看你${amountAndMerchantText ? `的 ${amountAndMerchantText} ` : '的 '}交易`;
-                },
             },
             error: {
                 invalidCredentials: '凭证无效，请检查您的连接配置。',
@@ -8288,23 +7229,6 @@ ${reportName}
     chronos: {
         oooEventSummaryFullDay: (summary: string, dayCount: number, date: string) => `${summary}，共计 ${dayCount} ${dayCount === 1 ? '天' : '天'}，截至 ${date}`,
         oooEventSummaryPartialDay: (summary: string, timePeriod: string, date: string) => `${summary}，时间范围：${timePeriod}，日期：${date}`,
-        startTimer: '开始计时',
-        stopTimer: (duration: string) => `停止计时器 (${duration})`,
-        scheduleOOO: '安排外出办公',
-        scheduleOOOTitle: '安排外出办公',
-        date: '日期',
-        time: '时间（请使用24小时制）',
-        durationAmount: '时长',
-        durationUnit: '单位',
-        reason: '原因',
-        workingPercentage: '工作百分比',
-        dateRequired: '日期为必填项。',
-        invalidTimeFormat: '请输入有效的 24 小时制时间（例如：14:30）。',
-        enterANumber: '请输入一个数字。',
-        hour: '小时',
-        day: '天',
-        week: '周',
-        month: '个月',
     },
     footer: {
         features: '功能',
@@ -8347,24 +7271,8 @@ ${reportName}
         workspaceName: '工作区名称',
         chatUserDisplayNames: '聊天成员显示名称',
         scrollToNewestMessages: '滚动到最新消息',
-        scrollToActionBadgeTarget: '滚动到需要关注的操作',
         preStyledText: '预设样式文本',
         viewAttachment: '查看附件',
-        contextMenuAvailable: '上下文菜单可用。按 Shift+F10 打开。',
-        contextMenuAvailableMacOS: '上下文菜单可用。按 VO-Shift-M 打开。',
-        contextMenuAvailableNative: '上下文菜单可用。双击并按住即可打开。',
-        selectAllFeatures: '选择所有功能',
-        selectAllTransactions: '选择所有交易',
-        selectAllItems: '全选所有项目',
-        openActionsMenu: '打开操作菜单',
-        selectAllCategories: '选择所有类别',
-        selectAllDistanceRates: '选择所有距离费率',
-        selectAllTags: '选择所有标签',
-        selectAllTaxes: '全选所有税种',
-        selectAllPerDiemRates: '选择所有每日津贴费率',
-        selectAllMembers: '全选所有成员',
-        selectAllValues: '选择所有值',
-        selectAllRules: '选择所有规则',
     },
     parentReportAction: {
         deletedReport: '已删除的报告',
@@ -8383,7 +7291,6 @@ ${reportName}
         parentNavigationSummary: ({reportName, workspaceName}: ParentNavigationSummaryParams) => `来自${reportName}${workspaceName ? `在 ${workspaceName} 中` : ''}`,
     },
     qrCodes: {
-        qrCode: '二维码',
         copy: '复制 URL',
         copied: '已复制！',
     },
@@ -8429,11 +7336,6 @@ ${reportName}
         joinExpensifyOrg: '加入 Expensify.org，一起消除世界各地的不公现象。当前的“教师联合”活动通过分担基本学习用品的费用来支持全世界的教育工作者。',
         iKnowATeacher: '我认识一位老师',
         iAmATeacher: '我是老师',
-        personalKarma: {
-            title: '启用个人 Karma',
-            description: '您每月每消费 500 美元，就向 Expensify.org 捐赠 1 美元',
-            stopDonationsPrompt: '确定要停止向 Expensify.org 捐款吗？',
-        },
         getInTouch: '太好了！请分享他们的联系方式，以便我们与他们取得联系。',
         introSchoolPrincipal: '向你们学校校长的介绍',
         schoolPrincipalVerifyExpense: 'Expensify.org 会分摊基本学习用品的费用，让来自低收入家庭的学生能够拥有更好的学习体验。我们会请你的校长核实你的报销。',
@@ -8455,11 +7357,6 @@ ${reportName}
         notActivated: '未激活',
         outOfPocket: '可报销',
         companySpend: '不可报销',
-        personalCard: '个人银行卡',
-        companyCard: '公司卡',
-        expensifyCard: 'Expensify 卡',
-        travelInvoicing: '差旅开票',
-        travelCard: '旅行卡',
     },
     distance: {
         addStop: '添加站点',
@@ -8483,18 +7380,14 @@ ${reportName}
             endReading: '结束阅读',
             saveForLater: '稍后保存',
             totalDistance: '总距离',
+            startTitle: '里程表起始照片',
+            endTitle: '里程表结束照片',
             startMessageWeb: '从行程<strong>开始</strong>时添加一张里程表照片。将文件拖到此处或选择一个文件上传。',
             endMessageWeb: '在行程<strong>结束</strong>时添加一张里程表照片。将文件拖到此处或选择一个文件上传。',
-            startTitle: '起始里程表照片',
-            endTitle: '结束里程表照片',
-            deleteOdometerPhoto: '删除里程表照片',
-            deleteOdometerPhotoConfirmation: '确定要删除这个里程表照片吗？',
-            cameraAccessRequired: '拍照需要启用相机访问权限。',
-            snapPhotoStart: '<muted-text-label>在行程<strong>开始</strong>时拍一张里程表照片。</muted-text-label>',
-            snapPhotoEnd: '<muted-text-label>在行程<strong>结束</strong>时拍一张里程表的照片。</muted-text-label>',
         },
     },
     gps: {
+        disclaimer: '使用 GPS 根据您的行程创建报销。点击下方的“开始”以开始跟踪。',
         error: {
             failedToStart: '启动位置跟踪失败。',
             failedToGetPermissions: '获取必要的位置信息权限失败。',
@@ -8503,9 +7396,13 @@ ${reportName}
         stopped: '已停止',
         start: '开始',
         stop: '停止',
-        save: '保存',
-        resume: '简历',
         discard: '丢弃',
+        stopGpsTrackingModal: {
+            title: '停止 GPS 跟踪',
+            prompt: '你确定吗？这将结束你当前的流程。',
+            cancel: '恢复跟踪',
+            confirm: '停止 GPS 跟踪',
+        },
         discardDistanceTrackingModal: {
             title: '放弃距离跟踪',
             prompt: '确定要继续吗？这将放弃你当前的行程，且无法撤销。',
@@ -8549,14 +7446,12 @@ ${reportName}
             confirm: '放弃并退出登录',
         },
         switchToODWarningTripInProgress: {title: '正在进行 GPS 跟踪', prompt: '您确定要停止 GPS 追踪并切换到 Expensify Classic 吗？', confirm: '停止并切换'},
-        switchAccountWarningTripInProgress: {title: '正在进行 GPS 跟踪', prompt: '确定要停止 GPS 追踪并切换账户吗？', confirm: '停止并切换'},
         locationServicesRequiredModal: {
             title: '需要访问位置信息',
             confirm: '打开设置',
             prompt: '请在设备设置中允许访问位置信息，以开始使用 GPS 距离跟踪。',
         },
-        gpsFloatingPillText: '正在进行 GPS 跟踪…',
-        liveActivity: {subtitle: '跟踪距离', button: '查看进度', lockScreenBadgeText: '距离', lockScreenTrackingText: '正在跟踪…'},
+        fabGpsTripExplained: '前往 GPS 页面（浮动操作）',
     },
     reportCardLostOrDamaged: {
         screenTitle: '成绩单遗失或损坏',
@@ -8583,13 +7478,11 @@ ${reportName}
         [CONST.REFERRAL_PROGRAM.CONTENT_TYPES.START_CHAT]: {
             buttonText: '开始聊天，<success><strong>推荐好友</strong></success>。',
             header: '开始聊天，推荐好友',
-            closeAccessibilityLabel: '关闭、开始聊天、推荐朋友、横幅',
             body: '也想让你的朋友使用 Expensify 吗？只需与他们开始一个聊天，剩下的交给我们。',
         },
         [CONST.REFERRAL_PROGRAM.CONTENT_TYPES.SUBMIT_EXPENSE]: {
             buttonText: '提交报销，<success><strong>推荐你的团队</strong></success>。',
             header: '报销一笔费用，推荐你的团队',
-            closeAccessibilityLabel: '关闭、提交费用、邀请团队、横幅',
             body: '也想让你的团队使用 Expensify 吗？只需向他们提交一笔报销，我们会帮你处理剩下的一切。',
         },
         [CONST.REFERRAL_PROGRAM.CONTENT_TYPES.REFER_FRIEND]: {
@@ -8604,28 +7497,26 @@ ${reportName}
         copyReferralLink: '复制邀请链接',
     },
     systemChatFooterMessage: {
-        [CONST.INTRO_CHOICES.MANAGE_TEAM]: ({adminReportName, href}: {adminReportName: string; href: string}) =>
-            `如需帮助，请在 <a href="${href}">${adminReportName}</a> 中与您的客户经理聊天`,
-        default: `如需设置帮助，请联系 <concierge-link>${CONST.CONCIERGE_CHAT_NAME}</concierge-link>`,
+        [CONST.INTRO_CHOICES.MANAGE_TEAM]: ({adminReportName, href}: {adminReportName: string; href: string}) => `在 <a href="${href}">${adminReportName}</a> 中与您的设置专员聊天以获取帮助`,
+        default: `向 <concierge-link>${CONST.CONCIERGE_CHAT_NAME}</concierge-link> 发送消息以获取设置帮助`,
     },
     violations: {
         allTagLevelsRequired: '所有标签为必填项',
         autoReportedRejectedExpense: '此报销已被拒绝。',
         billableExpense: '可计费项不再有效',
-        cashExpenseWithNoReceipt: (formattedLimit?: string) => `需要收据${formattedLimit ? `超过 ${formattedLimit}` : ''}`,
+        cashExpenseWithNoReceipt: ({formattedLimit}: ViolationsCashExpenseWithNoReceiptParams = {}) => `需要收据${formattedLimit ? `超过 ${formattedLimit}` : ''}`,
         categoryOutOfPolicy: '类别不再有效',
-        conversionSurcharge: (surcharge: number) => `已应用 ${surcharge}% 的转换附加费`,
+        conversionSurcharge: ({surcharge}: ViolationsConversionSurchargeParams) => `已应用 ${surcharge}% 的转换附加费`,
         customUnitOutOfPolicy: '此工作区的费率无效',
         duplicatedTransaction: '可能重复',
         fieldRequired: '报表字段为必填项',
         futureDate: '不允许使用未来日期',
-        inactiveVendor: '供应商不再有效',
-        invoiceMarkup: (invoiceMarkup: number) => `加价 ${invoiceMarkup}%`,
-        maxAge: (maxAge: number) => `日期早于 ${maxAge} 天`,
+        invoiceMarkup: ({invoiceMarkup}: ViolationsInvoiceMarkupParams) => `加价 ${invoiceMarkup}%`,
+        maxAge: ({maxAge}: ViolationsMaxAgeParams) => `日期早于 ${maxAge} 天`,
         missingCategory: '缺少类别',
         missingComment: '所选类别需要填写说明',
         missingAttendees: '此类别需要多个参与者',
-        missingTag: (tagName?: string) => `缺少 ${tagName ?? '标签'}`,
+        missingTag: ({tagName}: ViolationsMissingTagParams = {}) => `缺少 ${tagName ?? '标签'}`,
         modifiedAmount: ({type, displayPercentVariance}: ViolationsModifiedAmountParams) => {
             switch (type) {
                 case 'distance':
@@ -8640,17 +7531,15 @@ ${reportName}
             }
         },
         modifiedDate: '日期与已扫描收据不符',
-        increasedDistance: ({formattedRouteDistance}: ViolationsIncreasedDistanceParams) =>
-            formattedRouteDistance ? `距离超过计算出的路线 ${formattedRouteDistance}` : '距离超过计算的路线',
         nonExpensiworksExpense: '非 Expensiworks 报销',
-        overAutoApprovalLimit: (formattedLimit: string) => `报销金额超出自动审批上限 ${formattedLimit}`,
-        overCategoryLimit: (formattedLimit: string) => `金额超出每人 ${formattedLimit} 的类别限额`,
-        overLimit: (formattedLimit: string) => `超出每人限额 ${formattedLimit} 的金额`,
-        overTripLimit: (formattedLimit: string) => `超出每次行程限额 ${formattedLimit} 的金额`,
-        overLimitAttendee: (formattedLimit: string) => `超出每人限额 ${formattedLimit} 的金额`,
-        perDayLimit: (formattedLimit: string) => `金额超过每日 ${formattedLimit}/人类别限额`,
+        overAutoApprovalLimit: ({formattedLimit}: ViolationsOverLimitParams) => `报销金额超出自动审批上限 ${formattedLimit}`,
+        overCategoryLimit: ({formattedLimit}: ViolationsOverCategoryLimitParams) => `金额超出每人 ${formattedLimit} 的类别限额`,
+        overLimit: ({formattedLimit}: ViolationsOverLimitParams) => `超出每人限额 ${formattedLimit} 的金额`,
+        overTripLimit: ({formattedLimit}: ViolationsOverLimitParams) => `超出每次行程限额 ${formattedLimit} 的金额`,
+        overLimitAttendee: ({formattedLimit}: ViolationsOverLimitParams) => `超出每人限额 ${formattedLimit} 的金额`,
+        perDayLimit: ({formattedLimit}: ViolationsPerDayLimitParams) => `金额超过每日 ${formattedLimit}/人类别限额`,
         receiptNotSmartScanned: '已手动添加收据和报销详情。',
-        receiptRequired: (formattedLimit?: string, category?: string) => {
+        receiptRequired: ({formattedLimit, category}: ViolationsReceiptRequiredParams) => {
             if (formattedLimit && category) {
                 return `超过${formattedLimit}类别限额需提供收据`;
             }
@@ -8662,8 +7551,8 @@ ${reportName}
             }
             return '需要收据';
         },
-        itemizedReceiptRequired: (formattedLimit?: string) => `需要逐项明细收据${formattedLimit ? `超过 ${formattedLimit}` : ''}`,
-        prohibitedExpense: (prohibitedExpenseTypes: string | string[]) => {
+        itemizedReceiptRequired: ({formattedLimit}: {formattedLimit?: string}) => `需要逐项明细收据${formattedLimit ? `超过 ${formattedLimit}` : ''}`,
+        prohibitedExpense: ({prohibitedExpenseTypes}: ViolationsProhibitedExpenseParams) => {
             const preMessage = '禁止报销的费用：';
             const getProhibitedExpenseTypeText = (prohibitedExpenseType: string) => {
                 switch (prohibitedExpenseType) {
@@ -8677,10 +7566,6 @@ ${reportName}
                         return `成人娱乐`;
                     case 'hotelIncidentals':
                         return `酒店杂费`;
-                    case 'giftCard':
-                        return `礼品卡购买`;
-                    case 'handwrittenReceipt':
-                        return `手写收据`;
                     default:
                         return `${prohibitedExpenseType}`;
                 }
@@ -8696,35 +7581,17 @@ ${reportName}
             }
             return `${preMessage} ${types.map(getProhibitedExpenseTypeText).join(', ')}`;
         },
-        customRules: (message: string) => message,
+        customRules: ({message}: ViolationsCustomRulesParams) => message,
         reviewRequired: '需要审核',
-        rter: (
-            brokenBankConnection: boolean,
-            isAdmin: boolean,
-            isTransactionOlderThan7Days: boolean,
-            member?: string,
-            rterType?: string,
-            companyCardPageURL?: string,
-            connectionLink?: string,
-            isPersonalCard?: boolean,
-            isMarkAsCash?: boolean,
-        ) => {
+        rter: ({brokenBankConnection, isAdmin, isTransactionOlderThan7Days, member, rterType, companyCardPageURL}: ViolationsRterParams) => {
             if (rterType === CONST.RTER_VIOLATION_TYPES.BROKEN_CARD_CONNECTION_530) {
-                return '由于银行连接中断，无法自动匹配收据。';
-            }
-            if (isPersonalCard && (rterType === CONST.RTER_VIOLATION_TYPES.BROKEN_CARD_CONNECTION || brokenBankConnection)) {
-                if (!connectionLink) {
-                    return '由于银行连接中断，无法自动匹配收据。';
-                }
-                return isMarkAsCash
-                    ? `由于银行卡连接异常，无法自动匹配收据。标记为现金以忽略，或<a href="${connectionLink}">修复银行卡</a>以匹配收据。`
-                    : `由于银行卡连接异常，无法自动匹配收据。请<a href="${connectionLink}">修复银行卡</a>以匹配该收据。`;
+                return '由于银行连接中断，无法自动匹配收据';
             }
             if (brokenBankConnection || rterType === CONST.RTER_VIOLATION_TYPES.BROKEN_CARD_CONNECTION) {
-                return isAdmin ? `银行连接已断开。<a href="${companyCardPageURL}">重新连接以匹配收据</a>` : '银行连接已断开。请让管理员重新连接以匹配收据。';
+                return isAdmin ? `银行连接已断开。<a href="${companyCardPageURL}">重新连接以匹配收据</a>` : '银行连接已中断。请联系管理员重新连接以匹配收据。';
             }
             if (!isTransactionOlderThan7Days) {
-                return isAdmin ? `请让 ${member} 将其标记为现金，或等待 7 天后再试` : '正在等待与信用卡交易合并。';
+                return isAdmin ? `请让 ${member} 标记为现金，或等待 7 天后再试` : '正在等待与银行卡交易合并。';
             }
             return '';
         },
@@ -8733,27 +7600,12 @@ ${reportName}
             `<muted-text-label>由于银行连接中断，收据暂时待处理。请前往<a href="${workspaceCompanyCardRoute}">公司卡</a>中解决。</muted-text-label>`,
         memberBrokenConnectionError: '由于银行连接中断，收据处于待处理状态。请联系工作区管理员解决。',
         markAsCashToIgnore: '标记为现金以忽略并请求付款。',
-        smartscanFailed: ({canEdit = true, missingFields = []}: {canEdit?: boolean; missingFields?: string[]}) => {
-            if (missingFields.length > 0) {
-                const fieldNames: Record<string, string> = {merchant: '商家', date: '日期', amount: '金额'};
-                const translated = missingFields.map((f) => fieldNames[f] ?? f);
-                let fieldList = '';
-                if (translated.length === 1) {
-                    fieldList = translated.at(0) ?? '';
-                } else if (translated.length === 2) {
-                    fieldList = translated.join('和');
-                } else {
-                    fieldList = translated.join('、');
-                }
-                return `收据扫描失败 — 缺少${fieldList}。${canEdit ? '手动输入详细信息。' : ''}`;
-            }
-            return `收据扫描失败。${canEdit ? '手动输入详细信息。' : ''}`;
-        },
+        smartscanFailed: ({canEdit = true}) => `收据扫描失败。${canEdit ? '手动输入详细信息。' : ''}`,
         receiptGeneratedWithAI: '可能由 AI 生成的收据',
-        someTagLevelsRequired: (tagName?: string) => `缺少 ${tagName ?? '标签'}`,
-        tagOutOfPolicy: (tagName?: string) => `${tagName ?? '标签'} 不再有效`,
+        someTagLevelsRequired: ({tagName}: ViolationsTagOutOfPolicyParams = {}) => `缺少 ${tagName ?? '标签'}`,
+        tagOutOfPolicy: ({tagName}: ViolationsTagOutOfPolicyParams = {}) => `${tagName ?? '标签'} 不再有效`,
         taxAmountChanged: '税额已被修改',
-        taxOutOfPolicy: (taxName?: string) => `${taxName ?? '税'} 不再有效`,
+        taxOutOfPolicy: ({taxName}: ViolationsTaxOutOfPolicyParams = {}) => `${taxName ?? '税'} 不再有效`,
         taxRateChanged: '税率已被修改',
         taxRequired: '缺少税率',
         none: '无',
@@ -8773,7 +7625,7 @@ ${reportName}
         noRoute: '请选择一个有效地址',
     },
     reportViolations: {
-        [CONST.REPORT_VIOLATIONS.FIELD_REQUIRED]: (fieldName: string) => `${fieldName} 为必填项`,
+        [CONST.REPORT_VIOLATIONS.FIELD_REQUIRED]: ({fieldName}: RequiredFieldParams) => `${fieldName} 为必填项`,
         reportContainsExpensesWithViolations: '报表包含有违规的报销。',
     },
     violationDismissal: {
@@ -8828,7 +7680,6 @@ ${reportName}
         bookACallTextTop: '切换回 Expensify 经典版后，您将无法享受：',
         bookACallTextBottom: '我们非常期待与您通话以了解原因。您可以预约与我们的一位资深产品经理通话，讨论您的需求。',
         takeMeToExpensifyClassic: '带我前往 Expensify 经典版',
-        goBackJustOnce: '仅此一次返回',
     },
     listBoundary: {
         errorMessage: '加载更多消息时出错',
@@ -8897,7 +7748,7 @@ ${reportName}
                 subtitle: '下一步，请<a href="#">完成设置清单</a>，以便您的团队可以开始报销费用。',
             },
             trialStarted: {
-                title: (numOfDays: number) => `试用期：剩余 ${numOfDays} ${numOfDays === 1 ? '天' : '天'} 天！`,
+                title: ({numOfDays}: TrialStartedTitleParams) => `试用期：剩余 ${numOfDays} ${numOfDays === 1 ? '天' : '天'} 天！`,
                 subtitle: '添加一张付款卡片以继续使用您所有喜爱的功能。',
             },
             trialEnded: {
@@ -8934,15 +7785,15 @@ ${reportName}
             title: '您的方案',
             exploreAllPlans: '查看所有方案',
             customPricing: '自定义定价',
-            asLowAs: (price: string) => `每位活跃成员每月最低 ${price}`,
-            pricePerMemberMonth: (price: string) => `每位成员每月 ${price}`,
-            pricePerMemberPerMonth: (price: string) => `每位成员每月 ${price}`,
+            asLowAs: ({price}: YourPlanPriceValueParams) => `每位活跃成员每月最低 ${price}`,
+            pricePerMemberMonth: ({price}: YourPlanPriceValueParams) => `每位成员每月 ${price}`,
+            pricePerMemberPerMonth: ({price}: YourPlanPriceValueParams) => `每位成员每月 ${price}`,
             perMemberMonth: '每位成员/月',
             collect: {
                 title: '收款',
                 description: '为您提供报销、差旅和聊天功能的小型企业方案。',
-                priceAnnual: ({lower, upper}: YourPlanPriceParams) => `从使用 Expensify 卡的每位活跃成员 ${lower} 起，到未使用 Expensify 卡的每位活跃成员 ${upper}。`,
-                pricePayPerUse: ({lower, upper}: YourPlanPriceParams) => `从使用 Expensify 卡的每位活跃成员 ${lower} 起，到未使用 Expensify 卡的每位活跃成员 ${upper}。`,
+                priceAnnual: ({lower, upper}: YourPlanPriceParams) => `拥有 Expensify Card 的${lower}/活跃成员，未拥有 Expensify Card 的${upper}/活跃成员。`,
+                pricePayPerUse: ({lower, upper}: YourPlanPriceParams) => `拥有 Expensify Card 的${lower}/活跃成员，未拥有 Expensify Card 的${upper}/活跃成员。`,
                 benefit1: '收据扫描',
                 benefit2: '报销',
                 benefit3: '公司卡管理',
@@ -8955,8 +7806,8 @@ ${reportName}
             control: {
                 title: '控制',
                 description: '适用于大型企业的报销、差旅和聊天。',
-                priceAnnual: ({lower, upper}: YourPlanPriceParams) => `从使用 Expensify 卡的每位活跃成员 ${lower} 起，到未使用 Expensify 卡的每位活跃成员 ${upper}。`,
-                pricePayPerUse: ({lower, upper}: YourPlanPriceParams) => `从使用 Expensify 卡的每位活跃成员 ${lower} 起，到未使用 Expensify 卡的每位活跃成员 ${upper}。`,
+                priceAnnual: ({lower, upper}: YourPlanPriceParams) => `拥有 Expensify Card 的${lower}/活跃成员，未拥有 Expensify Card 的${upper}/活跃成员。`,
+                pricePayPerUse: ({lower, upper}: YourPlanPriceParams) => `拥有 Expensify Card 的${lower}/活跃成员，未拥有 Expensify Card 的${upper}/活跃成员。`,
                 benefit1: 'Collect 方案中的所有内容',
                 benefit2: '多级审批工作流程',
                 benefit3: '自定义报销规则',
@@ -8971,7 +7822,7 @@ ${reportName}
             upgrade: '升级到 Control',
             addMembers: '添加成员',
             saveWithExpensifyTitle: '使用 Expensify 卡省钱',
-            saveWithExpensifyDescription: '使用我们的省钱计算器，查看 Expensify 卡带来的返现如何减少你的 Expensify 账单。',
+            saveWithExpensifyDescription: '使用我们的省钱计算器，看看 Expensify 卡返现如何减少你的 Expensify 账单。',
             saveWithExpensifyButton: '了解详情',
         },
         compareModal: {
@@ -8981,7 +7832,6 @@ ${reportName}
         details: {
             title: '订阅详情',
             annual: '年度订阅',
-            creditBalance: '积分余额',
             taxExempt: '申请免税状态',
             taxExemptEnabled: '免税',
             taxExemptStatus: '免税状态',
@@ -8998,10 +7848,10 @@ ${reportName}
             note: '注意：活跃成员指的是在您的公司工作区中创建、编辑、提交、批准、报销或导出过费用数据的任何人。',
             confirmDetails: '确认您的新年度订阅详情：',
             subscriptionSize: '订阅规模',
-            activeMembers: (size: number) => `${size} 名活跃成员/月`,
+            activeMembers: ({size}: SubscriptionSizeParams) => `${size} 名活跃成员/月`,
             subscriptionRenews: '订阅续订',
             youCantDowngrade: '在年度订阅期间，你无法降级。',
-            youAlreadyCommitted: (size: number, date: string) =>
+            youAlreadyCommitted: ({size, date}: SubscriptionCommitmentParams) =>
                 `您已经承诺在 ${date} 之前，每月享受 ${size} 名活跃成员的年度订阅。您可以在 ${date} 通过关闭自动续订来切换为按使用量付费的订阅。`,
             error: {
                 size: '请输入有效的订阅数量',
@@ -9014,56 +7864,43 @@ ${reportName}
             security: 'Expensify 符合 PCI-DSS 标准，使用银行级加密，并采用冗余基础设施来保护您的数据。',
             learnMoreAboutSecurity: '详细了解我们的安全措施。',
         },
-        expensifyCode: {
-            title: 'Expensify代码',
-            discountCode: '折扣代码',
-            enterCode: '输入Expensify代码以应用于您的订阅。',
-            discountMessage: (promoDiscount: string, validBillingCycles: string) =>
-                `在接下来的${validBillingCycles ? `${validBillingCycles}次` : ''}账单中，你将获得${promoDiscount}%的折扣。`,
-            apply: '应用',
-            error: {
-                invalid: '此代码无效',
-            },
-        },
         subscriptionSettings: {
             title: '订阅设置',
-            summary: (subscriptionType: string, subscriptionSize: string, expensifyCode: string, autoRenew: string, autoIncrease: string) =>
-                `订阅类型：${subscriptionType}，订阅规模：${subscriptionSize}${expensifyCode ? `，Expensify代码：${expensifyCode}` : ''}，自动续订：${autoRenew}，年度席位自动增加：${autoIncrease}`,
+            summary: ({subscriptionType, subscriptionSize, autoRenew, autoIncrease}: SubscriptionSettingsSummaryParams) =>
+                `订阅类型：${subscriptionType}，订阅规模：${subscriptionSize}，自动续订：${autoRenew}，年度席位自动增加：${autoIncrease}`,
             none: '无',
             on: '开在',
             off: '关关闭',
             annual: '每年',
             autoRenew: '自动续订',
             autoIncrease: '自动增加年度席位',
-            saveUpTo: (amountWithCurrency: string) => `每位活跃成员每月最多可节省 ${amountWithCurrency}`,
+            saveUpTo: ({amountWithCurrency}: SubscriptionSettingsSaveUpToParams) => `每位活跃成员每月最多可节省 ${amountWithCurrency}`,
             automaticallyIncrease: '当活跃成员人数超过当前订阅席位数时，自动增加您的年度席位数量以进行容纳。注意：这将延长您的年度订阅结束日期。',
             disableAutoRenew: '禁用自动续订',
             helpUsImprove: '帮助我们改进 Expensify',
             whatsMainReason: '您关闭自动续订的主要原因是什么？',
-            renewsOn: (date: string) => `将在 ${date} 续订。`,
+            renewsOn: ({date}: SubscriptionSettingsRenewsOnParams) => `将在 ${date} 续订。`,
             pricingConfiguration: '价格取决于配置。要获得最低价格，请选择年度订阅并申领 Expensify 卡。',
-            learnMore: (hasAdminsRoom: boolean) =>
+            learnMore: ({hasAdminsRoom}: SubscriptionSettingsLearnMoreParams) =>
                 `<muted-text>在我们的<a href="${CONST.PRICING}">定价页面</a>了解更多，或在您的${hasAdminsRoom ? `<a href="adminsRoom">#admins 房间。</a>` : '#admins 房间。'}中与我们的团队聊天</muted-text>`,
             estimatedPrice: '预估价格',
-            changesBasedOn: '这会根据你使用 Expensify 卡的情况以及下方的订阅选项而变化。',
-            collectBillingDescription: 'Collect 工作区按每位成员每月计费，无需年度承诺。',
-            pricing: '定价',
+            changesBasedOn: '这将根据你使用 Expensify Card 的情况以及下面的订阅选项而变化。',
         },
-        cancelSubscription: {
-            title: '取消订阅',
-            subtitle: '您取消订阅的主要原因是什么？',
+        requestEarlyCancellation: {
+            title: '请求提前取消',
+            subtitle: '您申请提前取消的主要原因是什么？',
             subscriptionCanceled: {
                 title: '订阅已取消',
                 subtitle: '您的年度订阅已被取消。',
                 info: '如果你想按次付费继续使用你的工作区，你就都准备好了。',
-                preventFutureActivity: (workspacesListRoute: string) =>
+                preventFutureActivity: ({workspacesListRoute}: WorkspacesListRouteParams) =>
                     `如果你想阻止未来的活动和收费，你必须<a href="${workspacesListRoute}">删除你的工作区</a>。请注意，当你删除工作区时，你将被收取在当前日历月内产生的所有未结活动费用。`,
             },
             requestSubmitted: {
                 title: '请求已提交',
                 subtitle: '感谢你告知我们你有意取消订阅。我们正在审核你的请求，并会很快通过你与<concierge-link>Concierge</concierge-link>的聊天与你联系。',
             },
-            acknowledgement: `通过请求取消，我确认并同意：根据 Expensify 的<a href=${CONST.OLD_DOT_PUBLIC_URLS.TERMS_URL}>服务条款</a>或我与 Expensify 之间适用的其他服务协议，Expensify 没有义务批准此类请求，并且 Expensify 保留对是否批准任何此类请求的完全自主决定权。`,
+            acknowledgement: `通过请求提前取消，我确认并同意：根据 Expensify 的<a href=${CONST.OLD_DOT_PUBLIC_URLS.TERMS_URL}>服务条款</a>或我与 Expensify 之间适用的其他服务协议，Expensify 没有义务批准此类请求，并且 Expensify 保留对是否批准任何此类请求的完全自主决定权。`,
         },
     },
     feedbackSurvey: {
@@ -9082,14 +7919,11 @@ ${reportName}
     },
     delegate: {
         switchAccount: '切换账户：',
-        switch: '切换',
-        copilot: 'Copilot',
         copilotDelegatedAccess: 'Copilot：委托访问',
         copilotDelegatedAccessDescription: '允许其他成员访问你的账户。',
-        learnMoreAboutDelegatedAccess: '了解更多关于委托访问的信息',
-        addCopilot: '添加副驾驶',
+        addCopilot: '添加副驾',
         membersCanAccessYourAccount: '这些成员可以访问你的账户：',
-        youCanAccessTheseAccounts: '您可以访问这些账户：',
+        youCanAccessTheseAccounts: '您可以通过账户切换器访问这些账户：',
         role: ({role}: OptionalParam<DelegateRoleParams> = {}) => {
             switch (role) {
                 case CONST.DELEGATE_ROLE.ALL:
@@ -9206,7 +8040,6 @@ ${reportName}
             theresWasAProblemDuringAWorkspaceConnectionSync: '在工作区连接同步过程中出现问题',
             theresAProblemWithYourWallet: '您的钱包出现问题',
             theresAProblemWithYourWalletTerms: '您的钱包条款存在问题',
-            aBankAccountIsLocked: '银行账户已锁定',
         },
     },
     emptySearchView: {
@@ -9227,10 +8060,15 @@ ${reportName}
         conciergeLHNGBR: '<tooltip>从<strong>这里</strong>开始！</tooltip>',
         saveSearchTooltip: '<tooltip>在这里<strong>重命名已保存的搜索</strong>！</tooltip>',
         accountSwitcher: '<tooltip>在此访问你的<strong>Copilot 账户</strong></tooltip>',
+        scanTestTooltip: {
+            main: '<tooltip><strong>扫描我们的测试收据</strong>，看看它如何运作！</tooltip>',
+            manager: '<tooltip>选择我们的<strong>测试管理员</strong>来试用吧！</tooltip>',
+            confirmation: '<tooltip>现在<strong>提交报销</strong>，见证奇迹发生！</tooltip>',
+            tryItOut: '试用一下',
+        },
         outstandingFilter: '<tooltip>筛选<strong>待审批</strong>的报销</tooltip>',
         scanTestDriveTooltip: '<tooltip>发送此收据以\n<strong>完成试用体验！</strong></tooltip>',
         gpsTooltip: '<tooltip>正在进行 GPS 跟踪！完成后，请在下方停止跟踪。</tooltip>',
-        hasFilterNegation: '<tooltip>使用 <strong>-has:receipt</strong> 搜索没有收据的报销。</tooltip>',
     },
     discardChangesConfirmation: {
         title: '放弃更改？',
@@ -9246,7 +8084,7 @@ ${reportName}
         confirmation: {
             title: '确认通话',
             description: '请确认以下详情是否正确。确认通话后，我们会发送一封包含更多信息的邀请。',
-            setupSpecialist: '您的客户经理',
+            setupSpecialist: '您的设置专员',
             meetingLength: '会议时长',
             dateTime: '日期和时间',
             minutes: '30 分钟',
@@ -9293,20 +8131,6 @@ ${reportName}
         exportInProgress: '导出进行中',
         conciergeWillSend: 'Concierge 将很快把文件发送给你。',
     },
-    exportDownload: {
-        preparingTitle: 'Preparing download...',
-        preparingBody: 'You can either wait for the download to finish or Concierge can send it to you via chat.',
-        sendFromConcierge: "Send me the file when it's ready",
-        conciergeTitle: 'You bet!',
-        conciergeBody: 'Concierge will send you a message when the file is ready.',
-        goToConcierge: 'Go to Concierge',
-        dismiss: 'Dismiss',
-        readyTitle: 'Your file is ready!',
-        readyBody: "If it didn't automatically download, use the button below.",
-        downloadFile: 'Download file',
-        failedTitle: 'Export failed',
-        close: 'Close',
-    },
     domain: {
         notVerified: '未验证',
         retry: '重试',
@@ -9349,8 +8173,6 @@ ${reportName}
             disableSamlRequired: '禁用 SAML 要求',
             oktaWarningPrompt: '确定要这样做吗？这也会禁用 Okta SCIM。',
             requireWithEmptyMetadataError: '请在下方添加身份提供商元数据以启用',
-            pleaseDisableTwoFactorAuth: (twoFactorAuthSettingsUrl: string) =>
-                `<muted-text>请先停用<a href="${twoFactorAuthSettingsUrl}">强制启用双重验证</a>，然后再启用 SAML 登录。</muted-text>`,
         },
         samlConfigurationDetails: {
             title: 'SAML 配置详情',
@@ -9399,6 +8221,7 @@ ${reportName}
             primaryContact: '主要联系人',
             addPrimaryContact: '添加主要联系人',
             setPrimaryContactError: '无法设置主要联系人。请稍后重试。',
+            settings: '设置',
             consolidatedDomainBilling: '合并域名账单',
             consolidatedDomainBillingDescription: (domainName: string) =>
                 `<comment><muted-text-label>启用后，主要联系人将为所有由 <strong>${domainName}</strong> 成员拥有的工作区付款，并接收所有账单收据。</muted-text-label></comment>`,
@@ -9415,94 +8238,25 @@ ${reportName}
             resetDomain: '重置域名',
             resetDomainExplanation: ({domainName}: {domainName?: string}) => `请输入要重置的域名 <strong>${domainName}</strong> 以确认。`,
             enterDomainName: '在此输入您的域名',
-            resetDomainInfo: `此操作为<strong>永久性</strong>，并将删除以下数据：<br/> <bullet-list><bullet-item>公司卡关联以及这些卡上任何未报销的费用</bullet-item><bullet-item>SAML 和群组设置</bullet-item><bullet-item>差旅数据以及对 Expensify Travel 的访问权限</bullet-item></bullet-list> 所有账户、工作区、报表、费用和其他数据将保留。<br/><br/>注意：您可以通过在<a href="#">联系方式</a>中移除关联邮箱，将此域从您的域列表中清除。`,
+            resetDomainInfo: `此操作<strong>无法撤销</strong>，并将删除以下数据：<br/> <ul><li>公司卡关联以及这些卡上所有未报销的费用</li> <li>SAML 和群组设置</li> </ul> 所有账户、工作区、报表、费用和其他数据将保留。<br/><br/>注意：您可以通过从<a href="#">联系方法</a>中移除关联的邮箱，将此域从您的域名列表中清除。`,
         },
         domainMembers: '域成员',
         members: {
             title: '成员',
             findMember: '查找成员',
             addMember: '添加成员',
-            allMembers: '所有成员',
             email: '电子邮箱地址',
-            closeAccount: () => ({
-                one: '关闭账户',
-                other: '关闭账户',
-            }),
+            closeAccount: '关闭账户',
             closeAccountPrompt: '您确定吗？此操作是永久性的。',
-            forceCloseAccount: () => ({one: '强制关闭账户', other: '强制关闭账户'}),
-            safeCloseAccount: () => ({
-                one: '安全关闭账户',
-                other: '安全关闭账户',
-            }),
-            closeAccountInfo: () => ({
-                one: '我们建议安全地关闭该账户，以便在存在以下情况时跳过关闭操作：<bullet-list><bullet-item>待处理的审批</bullet-item><bullet-item>正在进行的报销</bullet-item><bullet-item>没有其他登录方式</bullet-item></bullet-list>否则，您可以忽略上述安全预防措施并强制关闭所选账户。',
-                other: '我们建议安全地关闭该账户，以便在存在以下情况时跳过关闭操作：<bullet-list><bullet-item>待处理的审批</bullet-item><bullet-item>正在进行的报销</bullet-item><bullet-item>没有其他登录方式</bullet-item></bullet-list>否则，您可以忽略上述安全预防措施并强制关闭所选账户。',
-            }),
+            forceCloseAccount: '强制关闭账户',
+            safeCloseAccount: '安全关闭账户',
+            closeAccountInfo:
+                '我们建议安全地关闭该账户，以便在存在以下情况时跳过关闭操作：<ul><li>待处理的审批</li><li>正在进行的报销</li><li>没有其他登录方式</li></ul>否则，您可以忽略上述安全预防措施并强制关闭所选账户。',
             error: {
                 removeMember: '无法移除此用户。请重试。',
                 addMember: '无法添加此成员。请重试。',
-                vacationDelegate: '无法将此用户设置为休假代理人。请重试。',
-                moveMember: '无法移动此成员。请重试。',
-                moveMemberNotPolicyAdmin: '无法将成员移动到域组。您必须是您尝试将此用户移动到的域组上设置的首选策略的策略管理员。',
-            },
-            cannotSetVacationDelegateForMember: (email: string) => `您无法为 ${email} 设置休假代理人，因为 TA 当前是以下成员的代理人：`,
-            reportSuspiciousActivityPrompt: (email: string) =>
-                `你确定要这样做吗？这将锁定 <strong>${email}</strong> 的账户。<br /><br />我们的团队随后会审核该账户并移除任何未经授权的访问。若要重新获得访问权限，他们需要与 Concierge 配合处理。`,
-            reportSuspiciousActivityConfirmationPrompt: '我们会审核账户以确认解锁是否安全，如有任何问题将通过 Concierge 与您联系。',
-            emptyMembers: {title: '此群组中没有成员', subtitle: '添加成员或尝试更改上方的筛选条件。'},
-            moveToGroup: '移至群组',
-            chooseWhereToMove: ({count}: {count: number}) => `选择将 ${count} 个 ${count === 1 ? '成员' : '成员'} 移动到哪里。`,
-            domainGroup: '域名组',
-            chooseWhereToMoveName: ({name}: {name: string}) => `选择将 ${name} 移动到哪里。`,
-            membersFeatureList: {
-                subtitle: ({domainName}: {domainName: string}) => `<muted-text>验证你的域，以便在 Expensify 中更好地管理 <strong>${domainName}</strong> 成员。</muted-text>`,
-                controlPolicyCreation: '限制创建工作区',
-                enableSamlSso: '启用 SAML 单点登录',
-                enforce2FA: '强制启用双重验证',
             },
         },
-        common: {
-            settings: '设置',
-            forceTwoFactorAuth: '强制启用双重身份验证',
-            forceTwoFactorAuthSAMLEnabledDescription: (samlPageUrl: string) => `<muted-text>请禁用<a href="${samlPageUrl}">SAML</a>以强制启用双重身份验证。</muted-text>`,
-            forceTwoFactorAuthDescription: `<muted-text>要求此域的所有成员使用双重身份验证。域成员在登录时将被提示为其账户设置双重身份验证。</muted-text>`,
-            forceTwoFactorAuthError: '无法更改强制启用双重身份验证设置。请稍后再试。',
-            resetTwoFactorAuth: '重置双重身份验证',
-            error: '无法保存此更改。请重试。',
-        },
-        groups: {
-            title: '群组',
-            memberCount: () => ({one: '1 名成员', other: (count: number) => `${count} 名成员`}),
-            defaultGroup: '新成员的默认群组',
-            defaultGroupPrompt: (currentName: string, newName: string) => `您确定要将 ${newName} 设为默认群组吗？新成员将被邀请加入此群组，而不是之前的默认群组（${currentName}）。`,
-            makeDefault: '设为默认',
-            neverMind: '算了',
-            createGroupError: '无法创建此群组。请重试。',
-            permissions: '群组权限',
-            createNewGroupButton: '新建群组',
-            createGroupSubmitButton: '创建群组',
-            expensifyCardPreferredWorkspace: 'Expensify Card 首选工作区',
-            expensifyCardPreferredWorkspaceDescription: '所有Expensify Card交易将在Expensify Card首选工作区而非首选工作区中创建。',
-            strictlyEnforceWorkspaceRules: '严格执行工作空间规则',
-            strictlyEnforceWorkspaceRulesDescription: '提交报告前必须满足所有工作空间规则。不允许手动例外。',
-            restrictExpenseWorkspaceCreation: '限制创建/删除费用工作区',
-            restrictExpenseWorkspaceCreationDescription:
-                '阻止成员创建费用工作区或将自己从费用工作区中移除。当与严格的工作区执行相结合时，这有助于防止他人使用 Expensify 提交用于您域外的报表。',
-            deleteGroup: '删除群组',
-            deleteGroupDangerConfirmationModal: '删除群组',
-            deleteGroupDangerConfirmationModalDescription: (defaultGroupName: string) => `您确定吗？这将把所有成员重新分配到默认群组（${defaultGroupName}），并且无法撤销。`,
-            deleteGroupError: '无法删除此群组。请重试。',
-            preferredWorkspace: '首选工作区',
-            preferredWorkspaceDescription: (enabled: boolean) => `所有新报告和费用将在${enabled ? '选定的首选' : '此'}工作区中创建。`,
-            preferredWorkspaceSelectDescription: '所有新费用和报告将在此工作区中创建。',
-            noWorkspacesMessage: '此域上没有工作区。启用此限制需要一个工作区。',
-            restrictDefaultLoginSelection: '限制默认登录选择',
-            restrictDefaultLoginSelectionDescription: '防止成员将登录邮箱更改为公司域名以外的地址，以规避政策限制。',
-            expensifyCardPreferredWorkspaceDisabledMessage: '要启用此设置，请先启用一个首选工作区，并在您的域上完成 Expensify Cards 的设置。',
-            findGroup: '查找群组',
-        },
-    },
-    proactiveAppReview: {title: '喜欢全新的 Expensify 吗？', description: '请告诉我们，这样我们就能帮助您让报销体验变得更好。', positiveButton: '太棒了！', negativeButton: '不太是'},
-    monthPickerPage: {month: '月份', selectMonth: '请选择月份'},
+    },
 };
 export default translations;

From 16d00bb217563487eeb3de1dcd82b4ae7c017b33 Mon Sep 17 00:00:00 2001
From: ShridharGoel <35566748+ShridharGoel@users.noreply.github.com>
Date: Thu, 11 Jun 2026 21:55:50 +0530
Subject: [PATCH 377/435] Revert language helper changes

---
 src/languages/IntlStore.ts | 2 +-
 src/languages/types.ts     | 1 -
 2 files changed, 1 insertion(+), 2 deletions(-)

diff --git a/src/languages/IntlStore.ts b/src/languages/IntlStore.ts
index 345ccefb887a..b4870c4fb813 100644
--- a/src/languages/IntlStore.ts
+++ b/src/languages/IntlStore.ts
@@ -24,7 +24,7 @@ import type zhHans from './zh-hans';
 // This function was added here to avoid circular dependencies
 function setAreTranslationsLoading(areTranslationsLoading: boolean) {
     // eslint-disable-next-line rulesdir/prefer-actions-set-data
-    Onyx.set(ONYXKEYS.ARE_TRANSLATIONS_LOADING, areTranslationsLoading);
+    Onyx.set(ONYXKEYS.RAM_ONLY_ARE_TRANSLATIONS_LOADING, areTranslationsLoading);
 }
 
 class IntlStore {
diff --git a/src/languages/types.ts b/src/languages/types.ts
index afcea14b78a9..3451d91310d6 100644
--- a/src/languages/types.ts
+++ b/src/languages/types.ts
@@ -21,7 +21,6 @@ type TranslationLeafValue<TStringOrFunction> = TStringOrFunction extends (...arg
  * Translation object is a recursive object that can contain other objects or string/function values
  */
 type TranslationDeepObject<TTranslations = any> = {
-    // eslint-disable-next-line @typescript-eslint/no-explicit-any
     [Path in keyof TTranslations]: TTranslations[Path] extends string | ((...args: any[]) => any)
         ? TranslationLeafValue<TTranslations[Path]>
         : TTranslations[Path] extends number | boolean | null | undefined | unknown[]

From b00b27716f37899a99bcdf7b5f91c18f40ab492f Mon Sep 17 00:00:00 2001
From: Carlos Martins <cmartins@expensify.com>
Date: Thu, 11 Jun 2026 10:47:12 -0600
Subject: [PATCH 378/435] fix bug

---
 .../ListItem/ActionCell/PayActionCell.tsx      |  6 ++++--
 .../SearchList/ListItem/ActionCell/index.tsx   |  5 +++++
 .../ListItem/ExpenseReportListItem.tsx         | 11 ++++++-----
 .../ExpenseReportListItemRowWide.tsx           |  2 ++
 .../ExpenseReportListItemRow/index.tsx         |  1 +
 .../ListItem/ExpenseReportListItemRow/types.ts |  4 +++-
 .../ListItem/ReportListItemHeader.tsx          | 18 +++++++++++++++---
 7 files changed, 36 insertions(+), 11 deletions(-)

diff --git a/src/components/Search/SearchList/ListItem/ActionCell/PayActionCell.tsx b/src/components/Search/SearchList/ListItem/ActionCell/PayActionCell.tsx
index b30b63392457..094a994f7fdc 100644
--- a/src/components/Search/SearchList/ListItem/ActionCell/PayActionCell.tsx
+++ b/src/components/Search/SearchList/ListItem/ActionCell/PayActionCell.tsx
@@ -1,4 +1,5 @@
 import React from 'react';
+import type {OnyxEntry} from 'react-native-onyx';
 import {useDelegateNoAccessActions, useDelegateNoAccessState} from '@components/DelegateNoAccessModalProvider';
 import {SearchScopeProvider} from '@components/Search/SearchScopeProvider';
 import SettlementButton from '@components/SettlementButton';
@@ -17,6 +18,7 @@ import {isInvoiceReport} from '@libs/ReportUtils';
 import CONST from '@src/CONST';
 import ONYXKEYS from '@src/ONYXKEYS';
 import ROUTES from '@src/ROUTES';
+import type {Report} from '@src/types/onyx';
 
 type PayActionCellProps = {
     isLoading: boolean;
@@ -26,9 +28,10 @@ type PayActionCellProps = {
     amount?: number;
     extraSmall: boolean;
     shouldDisablePointerEvents?: boolean;
+    chatReport: OnyxEntry<Report>;
 };
 
-function PayActionCell({isLoading, policyID, reportID, hash, amount, extraSmall, shouldDisablePointerEvents}: PayActionCellProps) {
+function PayActionCell({isLoading, policyID, reportID, hash, amount, extraSmall, shouldDisablePointerEvents, chatReport}: PayActionCellProps) {
     const styles = useThemeStyles();
     const {convertToDisplayString} = useCurrencyListActions();
     const {isOffline} = useNetwork();
@@ -37,7 +40,6 @@ function PayActionCell({isLoading, policyID, reportID, hash, amount, extraSmall,
     const [iouReport, transactions] = useReportWithTransactionsAndViolations(reportID);
     const policy = usePolicy(policyID);
     const [bankAccountList] = useOnyx(ONYXKEYS.BANK_ACCOUNT_LIST);
-    const [chatReport] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${iouReport?.chatReportID}`);
     const invoiceReceiverPolicyID = chatReport?.invoiceReceiver && 'policyID' in chatReport.invoiceReceiver ? chatReport.invoiceReceiver.policyID : undefined;
     const invoiceReceiverPolicy = usePolicy(invoiceReceiverPolicyID);
     const {
diff --git a/src/components/Search/SearchList/ListItem/ActionCell/index.tsx b/src/components/Search/SearchList/ListItem/ActionCell/index.tsx
index 97c1fe4ceda5..99e822d72677 100644
--- a/src/components/Search/SearchList/ListItem/ActionCell/index.tsx
+++ b/src/components/Search/SearchList/ListItem/ActionCell/index.tsx
@@ -1,10 +1,12 @@
 import React from 'react';
+import type {OnyxEntry} from 'react-native-onyx';
 import Button from '@components/Button';
 import useLocalize from '@hooks/useLocalize';
 import useNetwork from '@hooks/useNetwork';
 import useThemeStyles from '@hooks/useThemeStyles';
 import type {ModifiedMouseEvent} from '@libs/Navigation/helpers/openInternalRouteInNewTab';
 import CONST from '@src/CONST';
+import type {Report} from '@src/types/onyx';
 import type {SearchTransactionAction} from '@src/types/onyx/SearchResults';
 import actionTranslationsMap from './actionTranslationsMap';
 import PayActionCell from './PayActionCell';
@@ -21,6 +23,7 @@ type ActionCellProps = {
     amount?: number;
     extraSmall?: boolean;
     shouldDisablePointerEvents?: boolean;
+    chatReport?: OnyxEntry<Report>;
 };
 
 function ActionCell({
@@ -35,6 +38,7 @@ function ActionCell({
     amount,
     extraSmall = false,
     shouldDisablePointerEvents,
+    chatReport,
 }: ActionCellProps) {
     const {translate} = useLocalize();
     const styles = useThemeStyles();
@@ -75,6 +79,7 @@ function ActionCell({
                 amount={amount}
                 extraSmall={extraSmall}
                 shouldDisablePointerEvents={shouldDisablePointerEvents}
+                chatReport={chatReport}
             />
         );
     }
diff --git a/src/components/Search/SearchList/ListItem/ExpenseReportListItem.tsx b/src/components/Search/SearchList/ListItem/ExpenseReportListItem.tsx
index 9eeb51f6645d..65253d13f89c 100644
--- a/src/components/Search/SearchList/ListItem/ExpenseReportListItem.tsx
+++ b/src/components/Search/SearchList/ListItem/ExpenseReportListItem.tsx
@@ -101,6 +101,8 @@ function ExpenseReportListItem<TItem extends ListItem>({
         return searchData?.[`${ONYXKEYS.COLLECTION.REPORT}${reportItem.parentReportID}`];
     }, [searchData, reportItem.parentReportID]);
 
+    const chatReport = parentChatReport ?? snapshotChatReport;
+
     const snapshotPolicy = useMemo(() => {
         return (searchData?.[`${ONYXKEYS.COLLECTION.POLICY}${reportItem.policyID}`] ?? {}) as Policy;
     }, [searchData, reportItem.policyID]);
@@ -171,7 +173,7 @@ function ExpenseReportListItem<TItem extends ListItem>({
     const liveReportTransactions = useMemo(() => Object.values(reportTransactions), [reportTransactions]);
     const {currentUserAccountID, currentUserLogin, introSelected, betas, isSelfTourViewed, activePolicy, nextStep, chatReportPolicy, amountOwed} = useReportPaymentContext({
         reportID: reportItem.reportID,
-        chatReportPolicyID: parentChatReport?.policyID ?? snapshotChatReport?.policyID,
+        chatReportPolicyID: chatReport?.policyID,
     });
 
     const handleOnButtonPress = useCallback(() => {
@@ -192,7 +194,6 @@ function ExpenseReportListItem<TItem extends ListItem>({
                 // Search rows render from a snapshot; the report may not exist in the main
                 // collection yet. Fall back to the snapshot so the modal can submit.
                 const moneyRequestReport = parentReport ?? snapshotReport;
-                const chatReport = parentChatReport ?? snapshotChatReport;
                 const transactionsForHoldMenu = liveReportTransactions.length > 0 ? liveReportTransactions : holdItem.transactions;
                 const {nonHeldAmount, fullAmount, hasValidNonHeldAmount} = getNonHeldAndFullAmount(moneyRequestReport, holdItem.canPay ?? false, transactionsForHoldMenu);
                 const hasNonHeldExpenses = transactionsForHoldMenu.some((t) => !isOnHold(t));
@@ -218,7 +219,7 @@ function ExpenseReportListItem<TItem extends ListItem>({
             betas,
             isSelfTourViewed,
             activePolicy,
-            chatReport: parentChatReport ?? snapshotChatReport,
+            chatReport,
             chatReportPolicy,
             iouReportCurrentNextStepDeprecated: nextStep,
             searchData,
@@ -230,11 +231,10 @@ function ExpenseReportListItem<TItem extends ListItem>({
         onSelectRow,
         searchData,
         snapshotReport,
-        snapshotChatReport,
+        chatReport,
         snapshotPolicy,
         parentPolicy,
         parentReport,
-        parentChatReport,
         lastPaymentMethod,
         userBillingGracePeriodEnds,
         personalPolicyID,
@@ -402,6 +402,7 @@ function ExpenseReportListItem<TItem extends ListItem>({
                         canSelectMultiple={canSelectMultiple}
                         onCheckboxPress={handleSelectionButtonPress}
                         onButtonPress={handleOnButtonPress}
+                        chatReport={chatReport}
                         isSelectAllChecked={isSelected}
                         isIndeterminate={false}
                         isDisabledCheckbox={isDisabledCheckbox}
diff --git a/src/components/Search/SearchList/ListItem/ExpenseReportListItemRow/ExpenseReportListItemRowWide.tsx b/src/components/Search/SearchList/ListItem/ExpenseReportListItemRow/ExpenseReportListItemRowWide.tsx
index ab301d389d58..3c2aecdc285a 100644
--- a/src/components/Search/SearchList/ListItem/ExpenseReportListItemRow/ExpenseReportListItemRowWide.tsx
+++ b/src/components/Search/SearchList/ListItem/ExpenseReportListItemRow/ExpenseReportListItemRowWide.tsx
@@ -27,6 +27,7 @@ function ExpenseReportListItemRowWide({
     onCheckboxPress = () => {},
     onButtonPress = () => {},
     isActionLoading,
+    chatReport,
     containerStyle,
     showTooltip,
     canSelectMultiple,
@@ -199,6 +200,7 @@ function ExpenseReportListItemRowWide({
                     reportID={item.reportID}
                     hash={item.hash}
                     amount={item.total}
+                    chatReport={chatReport}
                     shouldDisablePointerEvents={isPendingDelete}
                 />
             </View>
diff --git a/src/components/Search/SearchList/ListItem/ExpenseReportListItemRow/index.tsx b/src/components/Search/SearchList/ListItem/ExpenseReportListItemRow/index.tsx
index 30e4854a6291..487a65fbb8ba 100644
--- a/src/components/Search/SearchList/ListItem/ExpenseReportListItemRow/index.tsx
+++ b/src/components/Search/SearchList/ListItem/ExpenseReportListItemRow/index.tsx
@@ -17,6 +17,7 @@ function ExpenseReportListItemRow(props: ExpenseReportListItemRowProps) {
                 isActionLoading={props.isActionLoading}
                 onButtonPress={props.onButtonPress}
                 onCheckboxPress={props.onCheckboxPress}
+                chatReport={props.chatReport}
                 containerStyle={props.containerStyle}
                 isSelectAllChecked={props.isSelectAllChecked}
                 isIndeterminate={props.isIndeterminate}
diff --git a/src/components/Search/SearchList/ListItem/ExpenseReportListItemRow/types.ts b/src/components/Search/SearchList/ListItem/ExpenseReportListItemRow/types.ts
index 6a405152939a..7d60df18a7a0 100644
--- a/src/components/Search/SearchList/ListItem/ExpenseReportListItemRow/types.ts
+++ b/src/components/Search/SearchList/ListItem/ExpenseReportListItemRow/types.ts
@@ -1,7 +1,8 @@
 import type {StyleProp, ViewStyle} from 'react-native';
 import type {ExpenseReportListItemType} from '@components/Search/SearchList/ListItem/types';
 import type {SearchColumnType} from '@components/Search/types';
-import type {ReportAction} from '@src/types/onyx';
+import type {Report, ReportAction} from '@src/types/onyx';
+import type {OnyxEntry} from 'react-native-onyx';
 
 type ExpenseReportListItemRowNarrowProps = {
     item: ExpenseReportListItemType;
@@ -17,6 +18,7 @@ type ExpenseReportListItemRowWideProps = ExpenseReportListItemRowNarrowProps & {
     showTooltip: boolean;
     isActionLoading?: boolean;
     onButtonPress?: () => void;
+    chatReport?: OnyxEntry<Report>;
     containerStyle?: StyleProp<ViewStyle>;
     isHovered?: boolean;
     isFocused?: boolean;
diff --git a/src/components/Search/SearchList/ListItem/ReportListItemHeader.tsx b/src/components/Search/SearchList/ListItem/ReportListItemHeader.tsx
index 8e97f79ed7b2..5efc2955d351 100644
--- a/src/components/Search/SearchList/ListItem/ReportListItemHeader.tsx
+++ b/src/components/Search/SearchList/ListItem/ReportListItemHeader.tsx
@@ -1,5 +1,6 @@
 import React, {useMemo} from 'react';
 import type {ColorValue} from 'react-native';
+import type {OnyxEntry} from 'react-native-onyx';
 import {View} from 'react-native';
 import Checkbox from '@components/Checkbox';
 import {useDelegateNoAccessActions, useDelegateNoAccessState} from '@components/DelegateNoAccessModalProvider';
@@ -96,6 +97,9 @@ type FirstRowReportHeaderProps<TItem extends ListItem> = {
 
     /** Whether the down arrow is expanded */
     isExpanded?: boolean;
+
+    /** Parent chat report resolved from live Onyx with search snapshot fallback */
+    chatReport?: OnyxEntry<Report>;
 };
 
 function HeaderFirstRow<TItem extends ListItem>({
@@ -109,6 +113,7 @@ function HeaderFirstRow<TItem extends ListItem>({
     isIndeterminate,
     onDownArrowClick,
     isExpanded,
+    chatReport,
 }: FirstRowReportHeaderProps<TItem>) {
     const icons = useMemoizedLazyExpensifyIcons(['DownArrow', 'UpArrow']);
     const styles = useThemeStyles();
@@ -190,6 +195,7 @@ function HeaderFirstRow<TItem extends ListItem>({
                         hash={reportItem.hash}
                         amount={reportItem.total}
                         extraSmall={!isLargeScreenWidth}
+                        chatReport={chatReport}
                     />
                 </View>
             )}
@@ -228,11 +234,16 @@ function ReportListItemHeader<TItem extends ListItem>({
     const snapshotPolicy = useMemo(() => {
         return (snapshot?.data?.[`${ONYXKEYS.COLLECTION.POLICY}${reportItem.policyID}`] ?? {}) as Policy;
     }, [snapshot, reportItem.policyID]);
+    const snapshotChatReport = useMemo(() => {
+        const chatReportID = snapshotReport?.chatReportID ?? reportItem.parentReportID;
+        return chatReportID ? snapshot?.data?.[`${ONYXKEYS.COLLECTION.REPORT}${chatReportID}`] : undefined;
+    }, [snapshot, snapshotReport?.chatReportID, reportItem.parentReportID]);
     const [parentPolicy] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY}${getNonEmptyStringOnyxID(snapshotReport?.policyID ?? reportItem.policyID)}`);
-    const [parentChatReport] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${getNonEmptyStringOnyxID(snapshotReport?.chatReportID)}`);
+    const [parentChatReport] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${getNonEmptyStringOnyxID(snapshotReport?.chatReportID ?? reportItem.parentReportID)}`);
+    const chatReport = parentChatReport ?? snapshotChatReport;
     const {currentUserAccountID, currentUserLogin, introSelected, betas, isSelfTourViewed, activePolicy, nextStep, chatReportPolicy, amountOwed} = useReportPaymentContext({
         reportID: reportItem.reportID,
-        chatReportPolicyID: parentChatReport?.policyID,
+        chatReportPolicyID: chatReport?.policyID,
     });
     const {isDelegateAccessRestricted} = useDelegateNoAccessState();
     const {showDelegateNoAccessModal} = useDelegateNoAccessActions();
@@ -265,7 +276,7 @@ function ReportListItemHeader<TItem extends ListItem>({
             betas,
             isSelfTourViewed,
             activePolicy,
-            chatReport: parentChatReport,
+            chatReport,
             chatReportPolicy,
             iouReportCurrentNextStepDeprecated: nextStep,
             searchData: snapshot?.data,
@@ -306,6 +317,7 @@ function ReportListItemHeader<TItem extends ListItem>({
                 isIndeterminate={isIndeterminate}
                 onDownArrowClick={onDownArrowClick}
                 isExpanded={isExpanded}
+                chatReport={chatReport}
             />
         </View>
     );

From ad699c5f2f42f2789be7df148195ab699cfe7c01 Mon Sep 17 00:00:00 2001
From: Carlos Martins <cmartins@expensify.com>
Date: Thu, 11 Jun 2026 10:54:55 -0600
Subject: [PATCH 379/435] fix prettier

---
 .../SearchList/ListItem/ExpenseReportListItemRow/types.ts       | 2 +-
 .../Search/SearchList/ListItem/ReportListItemHeader.tsx         | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/components/Search/SearchList/ListItem/ExpenseReportListItemRow/types.ts b/src/components/Search/SearchList/ListItem/ExpenseReportListItemRow/types.ts
index 7d60df18a7a0..a40897ce8171 100644
--- a/src/components/Search/SearchList/ListItem/ExpenseReportListItemRow/types.ts
+++ b/src/components/Search/SearchList/ListItem/ExpenseReportListItemRow/types.ts
@@ -1,8 +1,8 @@
 import type {StyleProp, ViewStyle} from 'react-native';
+import type {OnyxEntry} from 'react-native-onyx';
 import type {ExpenseReportListItemType} from '@components/Search/SearchList/ListItem/types';
 import type {SearchColumnType} from '@components/Search/types';
 import type {Report, ReportAction} from '@src/types/onyx';
-import type {OnyxEntry} from 'react-native-onyx';
 
 type ExpenseReportListItemRowNarrowProps = {
     item: ExpenseReportListItemType;
diff --git a/src/components/Search/SearchList/ListItem/ReportListItemHeader.tsx b/src/components/Search/SearchList/ListItem/ReportListItemHeader.tsx
index 5efc2955d351..5596e7c933bc 100644
--- a/src/components/Search/SearchList/ListItem/ReportListItemHeader.tsx
+++ b/src/components/Search/SearchList/ListItem/ReportListItemHeader.tsx
@@ -1,7 +1,7 @@
 import React, {useMemo} from 'react';
 import type {ColorValue} from 'react-native';
-import type {OnyxEntry} from 'react-native-onyx';
 import {View} from 'react-native';
+import type {OnyxEntry} from 'react-native-onyx';
 import Checkbox from '@components/Checkbox';
 import {useDelegateNoAccessActions, useDelegateNoAccessState} from '@components/DelegateNoAccessModalProvider';
 import Icon from '@components/Icon';

From 9a900d8b0be84b6639a866949402edc22ee0aaf8 Mon Sep 17 00:00:00 2001
From: OSBotify <infra+osbotify@expensify.com>
Date: Thu, 11 Jun 2026 16:56:13 +0000
Subject: [PATCH 380/435] Update version to 9.4.5-1

---
 android/app/build.gradle                    | 4 ++--
 ios/NewExpensify/Info.plist                 | 2 +-
 ios/NotificationServiceExtension/Info.plist | 2 +-
 ios/ShareViewController/Info.plist          | 2 +-
 package-lock.json                           | 4 ++--
 package.json                                | 2 +-
 6 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/android/app/build.gradle b/android/app/build.gradle
index c7a7c6045cb9..99f1fcfe0153 100644
--- a/android/app/build.gradle
+++ b/android/app/build.gradle
@@ -111,8 +111,8 @@ android {
         minSdkVersion rootProject.ext.minSdkVersion
         targetSdkVersion rootProject.ext.targetSdkVersion
         multiDexEnabled rootProject.ext.multiDexEnabled
-        versionCode 1009040500
-        versionName "9.4.5-0"
+        versionCode 1009040501
+        versionName "9.4.5-1"
         // Supported language variants must be declared here to avoid from being removed during the compilation.
         // This also helps us to not include unnecessary language variants in the APK.
         resConfigs "en", "es"
diff --git a/ios/NewExpensify/Info.plist b/ios/NewExpensify/Info.plist
index f21fb37f5600..120d4f4ee0d1 100644
--- a/ios/NewExpensify/Info.plist
+++ b/ios/NewExpensify/Info.plist
@@ -44,7 +44,7 @@
 		</dict>
 	</array>
 	<key>CFBundleVersion</key>
-	<string>9.4.5.0</string>
+	<string>9.4.5.1</string>
 	<key>FullStory</key>
 	<dict>
 		<key>OrgId</key>
diff --git a/ios/NotificationServiceExtension/Info.plist b/ios/NotificationServiceExtension/Info.plist
index f0541fc79c1c..d6bad0afb8d8 100644
--- a/ios/NotificationServiceExtension/Info.plist
+++ b/ios/NotificationServiceExtension/Info.plist
@@ -13,7 +13,7 @@
 	<key>CFBundleShortVersionString</key>
 	<string>9.4.5</string>
 	<key>CFBundleVersion</key>
-	<string>9.4.5.0</string>
+	<string>9.4.5.1</string>
 	<key>NSExtension</key>
 	<dict>
 		<key>NSExtensionPointIdentifier</key>
diff --git a/ios/ShareViewController/Info.plist b/ios/ShareViewController/Info.plist
index 44d8056abf00..2495b937d2ef 100644
--- a/ios/ShareViewController/Info.plist
+++ b/ios/ShareViewController/Info.plist
@@ -13,7 +13,7 @@
 	<key>CFBundleShortVersionString</key>
 	<string>9.4.5</string>
 	<key>CFBundleVersion</key>
-	<string>9.4.5.0</string>
+	<string>9.4.5.1</string>
 	<key>NSExtension</key>
 	<dict>
 		<key>NSExtensionAttributes</key>
diff --git a/package-lock.json b/package-lock.json
index 620ab9bee353..2af6b38fcfb3 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,12 +1,12 @@
 {
   "name": "new.expensify",
-  "version": "9.4.5-0",
+  "version": "9.4.5-1",
   "lockfileVersion": 3,
   "requires": true,
   "packages": {
     "": {
       "name": "new.expensify",
-      "version": "9.4.5-0",
+      "version": "9.4.5-1",
       "hasInstallScript": true,
       "license": "MIT",
       "workspaces": [
diff --git a/package.json b/package.json
index a6238f2779c4..5da687572737 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
   "name": "new.expensify",
-  "version": "9.4.5-0",
+  "version": "9.4.5-1",
   "author": "Expensify, Inc.",
   "homepage": "https://new.expensify.com",
   "description": "New Expensify is the next generation of Expensify: a reimagination of payments based atop a foundation of chat.",

From 0e950276edb170a6974e33e76ea8e640be49dc5d Mon Sep 17 00:00:00 2001
From: OSBotify <infra+osbotify@expensify.com>
Date: Thu, 11 Jun 2026 16:56:13 +0000
Subject: [PATCH 381/435] Update Mobile-Expensify submodule version to 9.4.5-1

---
 Mobile-Expensify | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Mobile-Expensify b/Mobile-Expensify
index 42ad9da8bfde..72db9b980cb7 160000
--- a/Mobile-Expensify
+++ b/Mobile-Expensify
@@ -1 +1 @@
-Subproject commit 42ad9da8bfde582b57b2e66dc30e22757e06deea
+Subproject commit 72db9b980cb71f6b582b962807824e21be9fa0a0

From 970ff731f68f5df525ebebc70ac4daced7fa94d4 Mon Sep 17 00:00:00 2001
From: krishna2323 <belivethatkg@gmail.com>
Date: Thu, 11 Jun 2026 22:39:44 +0530
Subject: [PATCH 382/435] Hide date columns when no rate has date bounds and
 remove unused EmptyStateComponent prop

Signed-off-by: krishna2323 <belivethatkg@gmail.com>
---
 .../Tables/WorkspaceDistanceRatesTable/index.tsx   | 14 +++++++++-----
 1 file changed, 9 insertions(+), 5 deletions(-)

diff --git a/src/components/Tables/WorkspaceDistanceRatesTable/index.tsx b/src/components/Tables/WorkspaceDistanceRatesTable/index.tsx
index 92ab782a1d46..bc82503b42f3 100644
--- a/src/components/Tables/WorkspaceDistanceRatesTable/index.tsx
+++ b/src/components/Tables/WorkspaceDistanceRatesTable/index.tsx
@@ -19,7 +19,6 @@ type WorkspaceDistanceRatesTableProps = {
     selectionEnabled: boolean;
     selectedKeys: string[];
     onRowSelectionChange: (selectedRowKeys: string[]) => void;
-    EmptyStateComponent?: React.ReactElement;
 };
 
 const STATUS_ORDER: Record<string, number> = {
@@ -29,12 +28,14 @@ const STATUS_ORDER: Record<string, number> = {
     [CONST.CUSTOM_UNITS.RATE_STATUS.INACTIVE]: 3,
 };
 
-function WorkspaceDistanceRatesTable({ratesData, selectionEnabled, selectedKeys, onRowSelectionChange, EmptyStateComponent}: WorkspaceDistanceRatesTableProps) {
+function WorkspaceDistanceRatesTable({ratesData, selectionEnabled, selectedKeys, onRowSelectionChange}: WorkspaceDistanceRatesTableProps) {
     const styles = useThemeStyles();
     const {translate, localeCompare} = useLocalize();
     const {shouldUseNarrowLayout, isMediumScreenWidth} = useResponsiveLayout();
     const shouldUseNarrowTableLayout = shouldUseNarrowLayout || isMediumScreenWidth;
 
+    const hasAnyDateBound = ratesData.some((item) => !!item.rate.startDate || !!item.rate.endDate);
+
     const columns: Array<TableColumn<DistanceRatesTableColumnKey>> = [
         {
             key: 'status',
@@ -45,8 +46,12 @@ function WorkspaceDistanceRatesTable({ratesData, selectionEnabled, selectedKeys,
         },
         {key: 'name', label: translate('common.name'), sortable: true},
         {key: 'rate', label: translate('workspace.distanceRates.rate'), sortable: true},
-        {key: 'startDate', label: translate('workspace.distanceRates.startDate'), sortable: true},
-        {key: 'endDate', label: translate('workspace.distanceRates.endDate'), sortable: true},
+        ...(hasAnyDateBound
+            ? ([
+                  {key: 'startDate', label: translate('workspace.distanceRates.startDate'), sortable: true},
+                  {key: 'endDate', label: translate('workspace.distanceRates.endDate'), sortable: true},
+              ] as const)
+            : []),
         {key: 'enabled', label: translate('common.enabled'), sortable: true, width: variables.tableSwitchColumnWidth, styling: {containerStyles: [styles.justifyContentEnd]}},
         {key: 'actions', label: '', sortable: false, width: variables.tableCaretColumnWidth},
     ];
@@ -130,7 +135,6 @@ function WorkspaceDistanceRatesTable({ratesData, selectionEnabled, selectedKeys,
             narrowLayoutSortColumn="name"
             title={translate('workspace.common.distanceRates')}
         >
-            {isEmpty && EmptyStateComponent}
             {!isEmpty && (
                 <>
                     {shouldShowSearchBar && <Table.SearchBar label={translate('workspace.distanceRates.findRate')} />}

From 9b1a2aaac4ba86047db51064aae5e66047c8f590 Mon Sep 17 00:00:00 2001
From: FitseTLT <engfitsum@gmail.com>
Date: Thu, 11 Jun 2026 20:16:31 +0300
Subject: [PATCH 383/435] filter guide emails for share bank recipients

---
 src/libs/PolicyUtils.ts       |  10 +++-
 tests/unit/PolicyUtilsTest.ts | 109 ++++++++++++++++++++++++++++++++++
 2 files changed, 117 insertions(+), 2 deletions(-)

diff --git a/src/libs/PolicyUtils.ts b/src/libs/PolicyUtils.ts
index 58572eb23285..8d50926f0b68 100644
--- a/src/libs/PolicyUtils.ts
+++ b/src/libs/PolicyUtils.ts
@@ -331,7 +331,13 @@ function getEligibleBankAccountShareRecipients(policies: OnyxCollection<Policy>
         for (const admin of getAdminEmployees(policy)) {
             const email = admin?.email;
             // Check if the email is for the active user or an existing user in the sharees array or admins list to avoid extra iterations
-            if (!email || email === currentUserLogin || adminMap.has(email) || shareesSet.has(email)) {
+            if (
+                !email ||
+                email === currentUserLogin ||
+                adminMap.has(email) ||
+                shareesSet.has(email) ||
+                (isExpensifyTeam(email) && shouldFilterExpensifyTeam(policy.owner, currentUserLogin))
+            ) {
                 continue;
             }
             const personalDetails = getPersonalDetailByEmail(email);
@@ -371,7 +377,7 @@ function hasEligibleActiveAdminFromWorkspaces(policies: OnyxCollection<Policy> |
         const admins = getAdminEmployees(policy);
         for (const admin of admins) {
             const email = admin?.email;
-            if (!email || email === currentUserLogin || alreadySharedSharees.has(email)) {
+            if (!email || email === currentUserLogin || alreadySharedSharees.has(email) || (isExpensifyTeam(email) && shouldFilterExpensifyTeam(policy.owner, currentUserLogin))) {
                 continue;
             }
 
diff --git a/tests/unit/PolicyUtilsTest.ts b/tests/unit/PolicyUtilsTest.ts
index 02c76022fb8f..bfed2eda7ec7 100644
--- a/tests/unit/PolicyUtilsTest.ts
+++ b/tests/unit/PolicyUtilsTest.ts
@@ -34,6 +34,7 @@ import {
     hasConfiguredRules,
     hasDependentTags,
     hasDynamicExternalWorkflow,
+    hasEligibleActiveAdminFromWorkspaces,
     hasIndependentTags,
     hasOnlyPersonalPolicies,
     hasOtherControlWorkspaces,
@@ -128,6 +129,8 @@ const employeeEmail = 'employee@test.com';
 const adminEmail = 'admin@test.com';
 const categoryApprover1Email = 'categoryapprover1@test.com';
 const approverEmail = 'approver@test.com';
+const guideEmail = 'guide@expensify.com';
+const guideAccountID = 9;
 
 const personalDetails: PersonalDetailsList = {
     '1': {
@@ -162,6 +165,10 @@ const personalDetails: PersonalDetailsList = {
         accountID: approverAccountID,
         login: approverEmail,
     },
+    '9': {
+        accountID: guideAccountID,
+        login: guideEmail,
+    },
 };
 
 const rules = {
@@ -1754,6 +1761,108 @@ describe('PolicyUtils', () => {
             const result = getEligibleBankAccountShareRecipients(policies, adminEmail, bankAccountID);
             expect(result).toHaveLength(1);
         });
+        it('should not return Expensify guide when policy owner is not Expensify team', () => {
+            const policies = {
+                '1': {
+                    ...createRandomPolicy(1, CONST.POLICY.TYPE.TEAM),
+                    pendingAction: undefined,
+                    role: CONST.POLICY.ROLE.ADMIN,
+                    owner: 'normalowner@test.com',
+                    employeeList: {
+                        [guideEmail]: {email: guideEmail, role: CONST.POLICY.ROLE.ADMIN},
+                    },
+                },
+            };
+            const result = getEligibleBankAccountShareRecipients(policies, adminEmail, '1');
+            expect(result).toHaveLength(0);
+        });
+        it('should return Expensify guide when policy owner is Expensify team', () => {
+            const policies = {
+                '1': {
+                    ...createRandomPolicy(1, CONST.POLICY.TYPE.TEAM),
+                    pendingAction: undefined,
+                    role: CONST.POLICY.ROLE.ADMIN,
+                    owner: 'owner@expensify.com',
+                    employeeList: {
+                        [guideEmail]: {email: guideEmail, role: CONST.POLICY.ROLE.ADMIN},
+                    },
+                },
+            };
+            const result = getEligibleBankAccountShareRecipients(policies, adminEmail, '1');
+            expect(result).toHaveLength(1);
+        });
+        it('should return Expensify guide when current user is Expensify team', () => {
+            const policies = {
+                '1': {
+                    ...createRandomPolicy(1, CONST.POLICY.TYPE.TEAM),
+                    pendingAction: undefined,
+                    role: CONST.POLICY.ROLE.ADMIN,
+                    owner: 'normalowner@test.com',
+                    employeeList: {
+                        [guideEmail]: {email: guideEmail, role: CONST.POLICY.ROLE.ADMIN},
+                    },
+                },
+            };
+            const result = getEligibleBankAccountShareRecipients(policies, 'someone@expensify.com', '1');
+            expect(result).toHaveLength(1);
+        });
+    });
+
+    describe('hasEligibleActiveAdminFromWorkspaces', () => {
+        beforeEach(() => {
+            wrapOnyxWithWaitForBatchedUpdates(Onyx);
+            Onyx.set(ONYXKEYS.PERSONAL_DETAILS_LIST, personalDetails);
+        });
+        afterEach(async () => {
+            await Onyx.clear();
+            await waitForBatchedUpdatesWithAct();
+        });
+        it('should return false when the only admin is an Expensify guide on a non-Expensify policy', () => {
+            const policies = {
+                '1': {
+                    ...createRandomPolicy(1, CONST.POLICY.TYPE.TEAM),
+                    pendingAction: undefined,
+                    role: CONST.POLICY.ROLE.ADMIN,
+                    owner: 'normalowner@test.com',
+                    employeeList: {
+                        [guideEmail]: {email: guideEmail, role: CONST.POLICY.ROLE.ADMIN},
+                    },
+                },
+            };
+            const result = hasEligibleActiveAdminFromWorkspaces(policies, adminEmail, '1');
+            expect(result).toBe(false);
+        });
+        it('should return true when there is a non-guide admin', () => {
+            const policies = {
+                '1': {
+                    ...createRandomPolicy(1, CONST.POLICY.TYPE.TEAM),
+                    pendingAction: undefined,
+                    role: CONST.POLICY.ROLE.ADMIN,
+                    owner: 'normalowner@test.com',
+                    employeeList: {
+                        [guideEmail]: {email: guideEmail, role: CONST.POLICY.ROLE.ADMIN},
+                        [approverEmail]: {email: approverEmail, role: CONST.POLICY.ROLE.ADMIN},
+                    },
+                },
+            };
+            const result = hasEligibleActiveAdminFromWorkspaces(policies, adminEmail, '1');
+            expect(result).toBe(true);
+        });
+        it('should return true when the guide is on an Expensify-owned policy', () => {
+            const policies = {
+                '1': {
+                    ...createRandomPolicy(1, CONST.POLICY.TYPE.TEAM),
+                    pendingAction: undefined,
+                    role: CONST.POLICY.ROLE.ADMIN,
+                    owner: 'owner@expensify.com',
+                    employeeList: {
+                        [guideEmail]: {email: guideEmail, role: CONST.POLICY.ROLE.ADMIN},
+                    },
+                },
+            };
+            const result = hasEligibleActiveAdminFromWorkspaces(policies, adminEmail, '1');
+            expect(result).toBe(true);
+        });
     });
 
     describe('hasOtherControlWorkspaces', () => {

From 1d9228776adb7f51b64d93b147ba57f07946b7fd Mon Sep 17 00:00:00 2001
From: Rushat Gabhane <rushatgabhane@gmail.com>
Date: Thu, 11 Jun 2026 19:19:58 +0200
Subject: [PATCH 384/435] add a11y state

---
 src/components/DatePicker/index.tsx | 1 +
 1 file changed, 1 insertion(+)

diff --git a/src/components/DatePicker/index.tsx b/src/components/DatePicker/index.tsx
index 01f0d72a8b71..64563214a97f 100644
--- a/src/components/DatePicker/index.tsx
+++ b/src/components/DatePicker/index.tsx
@@ -184,6 +184,7 @@ function DatePicker({
                     label={label}
                     accessibilityLabel={label}
                     role={CONST.ROLE.COMBOBOX}
+                    accessibilityState={{expanded: isModalVisible}}
                     value={selectedDate}
                     placeholder={placeholder ?? translate('common.dateFormat')}
                     errorText={errorText}

From a251fd450952100d101fd999a5dfc0f8c4d5532c Mon Sep 17 00:00:00 2001
From: Rushat Gabhane <rushatgabhane@gmail.com>
Date: Thu, 11 Jun 2026 19:31:02 +0200
Subject: [PATCH 385/435] add current step

---
 src/components/InteractiveStepSubHeader.tsx     | 2 ++
 src/components/InteractiveStepSubPageHeader.tsx | 2 ++
 2 files changed, 4 insertions(+)

diff --git a/src/components/InteractiveStepSubHeader.tsx b/src/components/InteractiveStepSubHeader.tsx
index 9afed89c7233..2c0fd86ba028 100644
--- a/src/components/InteractiveStepSubHeader.tsx
+++ b/src/components/InteractiveStepSubHeader.tsx
@@ -106,6 +106,8 @@ function InteractiveStepSubHeader({stepNames, startStepIndex = 0, currentStepAcc
                             disabled={isLockedStep || !onStepSelected}
                             onPress={moveToStep}
                             role={CONST.ROLE.GROUP}
+                            aria-current={currentStep === index ? 'step' : undefined}
+                            accessibilityState={{selected: currentStep === index}}
                             accessibilityLabel={translate('stepCounter', {
                                 step: index + 1,
                                 total: stepNames.length,
diff --git a/src/components/InteractiveStepSubPageHeader.tsx b/src/components/InteractiveStepSubPageHeader.tsx
index 0aef9f4b81a0..e46d9818d2ff 100644
--- a/src/components/InteractiveStepSubPageHeader.tsx
+++ b/src/components/InteractiveStepSubPageHeader.tsx
@@ -71,6 +71,8 @@ function InteractiveStepSubPageHeader({stepNames, currentStepIndex, currentStepA
                             onPress={() => handleStepPress(isLockedStep, index)}
                             accessible
                             role={CONST.ROLE.GROUP}
+                            aria-current={currentStepIndex === index ? 'step' : undefined}
+                            accessibilityState={{selected: currentStepIndex === index}}
                             accessibilityLabel={translate('stepCounter', {
                                 step: index + 1,
                                 total: stepNames.length,

From e59f1d061c5c2e74ce4ee32d89d951ea081fe603 Mon Sep 17 00:00:00 2001
From: OSBotify <infra+osbotify@expensify.com>
Date: Thu, 11 Jun 2026 17:31:12 +0000
Subject: [PATCH 386/435] Auto-tighten eslint-seatbelt baseline

---
 config/eslint/eslint.seatbelt.tsv | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/config/eslint/eslint.seatbelt.tsv b/config/eslint/eslint.seatbelt.tsv
index f8ef1b0fa88f..87437e198fbd 100644
--- a/config/eslint/eslint.seatbelt.tsv
+++ b/config/eslint/eslint.seatbelt.tsv
@@ -531,7 +531,7 @@
 "../../src/hooks/useDomainGroupFilter.ts"	"react-hooks/set-state-in-effect"	1
 "../../src/hooks/useDragAndDrop/types.ts"	"@typescript-eslint/no-deprecated/React.MutableRefObject"	1
 "../../src/hooks/useDynamicBackPath.ts"	"@typescript-eslint/no-unsafe-type-assertion"	1
-"../../src/hooks/useExpenseActions.ts"	"@typescript-eslint/no-deprecated/InteractionManager.runAfterInteractions"	3
+"../../src/hooks/useExpenseActions.ts"	"@typescript-eslint/no-deprecated/InteractionManager.runAfterInteractions"	1
 "../../src/hooks/useExportActions.ts"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../src/hooks/useExportedToFilterOptions.ts"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../src/hooks/useFilesValidation.tsx"	"@typescript-eslint/no-deprecated/ConfirmModal"	1

From 4ce92b93af7db59dafe7ae00424b439e47b76420 Mon Sep 17 00:00:00 2001
From: Yehor Kharchenko <yehorkharchenko4@gmail.com>
Date: Thu, 11 Jun 2026 19:38:29 +0200
Subject: [PATCH 387/435] remove last one eslint disable

---
 src/hooks/useHRSyncResultsModal.ts | 1 -
 1 file changed, 1 deletion(-)

diff --git a/src/hooks/useHRSyncResultsModal.ts b/src/hooks/useHRSyncResultsModal.ts
index af9ca2ba372d..e7ef15042448 100644
--- a/src/hooks/useHRSyncResultsModal.ts
+++ b/src/hooks/useHRSyncResultsModal.ts
@@ -3,7 +3,6 @@ import {useEffect, useEffectEvent, useRef} from 'react';
 import type {OnyxEntry} from 'react-native-onyx';
 import HRSyncResultsModal from '@components/HRSyncResultsModal';
 import {useModal} from '@components/Modal/Global/ModalContext';
-// eslint-disable-next-line no-restricted-imports -- the hook delays a global modal until the existing modal/navigation transitions complete to avoid stacked native modal races.
 import TransitionTracker from '@libs/Navigation/TransitionTracker';
 import CONST from '@src/CONST';
 import ONYXKEYS from '@src/ONYXKEYS';

From 23405f4ceb97f839f54ecd4702394235fa621d2a Mon Sep 17 00:00:00 2001
From: OSBotify <infra+osbotify@expensify.com>
Date: Thu, 11 Jun 2026 17:51:23 +0000
Subject: [PATCH 388/435] Update Mobile-Expensify submodule to 2c3e1fb

---
 Mobile-Expensify | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Mobile-Expensify b/Mobile-Expensify
index 72db9b980cb7..2c3e1fb325b1 160000
--- a/Mobile-Expensify
+++ b/Mobile-Expensify
@@ -1 +1 @@
-Subproject commit 72db9b980cb71f6b582b962807824e21be9fa0a0
+Subproject commit 2c3e1fb325b1fd979e7d5cc1bfd5f727f528be73

From cd33034901f36ec5f8491dc8f7c408156fc70879 Mon Sep 17 00:00:00 2001
From: Carlos Martins <cmartins@expensify.com>
Date: Thu, 11 Jun 2026 11:58:24 -0600
Subject: [PATCH 389/435] add fallback report

---
 .../Search/SearchList/ListItem/ExpenseReportListItem.tsx  | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/src/components/Search/SearchList/ListItem/ExpenseReportListItem.tsx b/src/components/Search/SearchList/ListItem/ExpenseReportListItem.tsx
index 65253d13f89c..c409d37b3624 100644
--- a/src/components/Search/SearchList/ListItem/ExpenseReportListItem.tsx
+++ b/src/components/Search/SearchList/ListItem/ExpenseReportListItem.tsx
@@ -88,7 +88,6 @@ function ExpenseReportListItem<TItem extends ListItem>({
     // Fetch live policy categories from Onyx to sync violations at render time
     const [parentPolicy] = originalUseOnyx(`${ONYXKEYS.COLLECTION.POLICY}${getNonEmptyStringOnyxID(reportItem.policyID)}`);
     const [parentReport] = originalUseOnyx(`${ONYXKEYS.COLLECTION.REPORT}${getNonEmptyStringOnyxID(reportItem.reportID)}`);
-    const [parentChatReport] = originalUseOnyx(`${ONYXKEYS.COLLECTION.REPORT}${getNonEmptyStringOnyxID(reportItem.parentReportID)}`);
     const [policyCategories] = originalUseOnyx(`${ONYXKEYS.COLLECTION.POLICY_CATEGORIES}${getNonEmptyStringOnyxID(reportItem.policyID)}`);
 
     const searchData = currentSearchResults?.data;
@@ -97,9 +96,12 @@ function ExpenseReportListItem<TItem extends ListItem>({
         return (searchData?.[`${ONYXKEYS.COLLECTION.REPORT}${reportItem.reportID}`] ?? {}) as Report;
     }, [searchData, reportItem.reportID]);
 
+    const [parentChatReport] = originalUseOnyx(`${ONYXKEYS.COLLECTION.REPORT}${getNonEmptyStringOnyxID(snapshotReport?.chatReportID ?? reportItem.parentReportID)}`);
+
     const snapshotChatReport = useMemo(() => {
-        return searchData?.[`${ONYXKEYS.COLLECTION.REPORT}${reportItem.parentReportID}`];
-    }, [searchData, reportItem.parentReportID]);
+        const chatReportID = snapshotReport?.chatReportID ?? reportItem.parentReportID;
+        return chatReportID ? searchData?.[`${ONYXKEYS.COLLECTION.REPORT}${chatReportID}`] : undefined;
+    }, [searchData, snapshotReport?.chatReportID, reportItem.parentReportID]);
 
     const chatReport = parentChatReport ?? snapshotChatReport;
 

From 8aa4065ac1d2f14f2061a32d1e0f9f7744cd0499 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Nicol=C3=A1s=20Bonet=20=28via=20MelvinBot=29?=
 <infra+melvinbot@expensify.com>
Date: Thu, 11 Jun 2026 18:05:35 +0000
Subject: [PATCH 390/435] Swap AI Rules badge from New feature to Beta
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Co-authored-by: Nicolás Bonet <NicolasBonet@users.noreply.github.com>
---
 src/pages/workspace/rules/AIRulesSection.tsx | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/pages/workspace/rules/AIRulesSection.tsx b/src/pages/workspace/rules/AIRulesSection.tsx
index e2f2929ac86f..8c133275f332 100644
--- a/src/pages/workspace/rules/AIRulesSection.tsx
+++ b/src/pages/workspace/rules/AIRulesSection.tsx
@@ -52,7 +52,7 @@ function AIRulesSection({policyID, canWriteRules, showReadOnlyModal}: AIRulesSec
         <View style={[styles.flexRow, styles.alignItemsCenter]}>
             <Text style={[styles.textHeadline, styles.cardSectionTitle, styles.accountSettingsSectionTitle, {color: theme.text}]}>{translate('workspace.rules.aiRules.title')}</Text>
             <Badge
-                text={translate('common.newFeature')}
+                text={translate('common.beta')}
                 isCondensed
                 success
             />

From 4d8ef24a8b98c73bb500e8ea9e52e0d5b571e877 Mon Sep 17 00:00:00 2001
From: krishna2323 <belivethatkg@gmail.com>
Date: Thu, 11 Jun 2026 23:39:56 +0530
Subject: [PATCH 391/435] Fix row cells rendering when date columns are hidden

Signed-off-by: krishna2323 <belivethatkg@gmail.com>
---
 .../WorkspaceDistanceRatesTableRow.tsx                     | 7 ++++---
 .../Tables/WorkspaceDistanceRatesTable/index.tsx           | 1 +
 2 files changed, 5 insertions(+), 3 deletions(-)

diff --git a/src/components/Tables/WorkspaceDistanceRatesTable/WorkspaceDistanceRatesTableRow.tsx b/src/components/Tables/WorkspaceDistanceRatesTable/WorkspaceDistanceRatesTableRow.tsx
index 19372d5021e6..5e4eb71e49fd 100644
--- a/src/components/Tables/WorkspaceDistanceRatesTable/WorkspaceDistanceRatesTableRow.tsx
+++ b/src/components/Tables/WorkspaceDistanceRatesTable/WorkspaceDistanceRatesTableRow.tsx
@@ -37,6 +37,7 @@ type WorkspaceDistanceRatesTableRowProps = {
     item: DistanceRateTableItemData;
     rowIndex: number;
     shouldUseNarrowTableLayout: boolean;
+    shouldShowDateColumns: boolean;
     statusLabels: Record<string, string>;
 };
 
@@ -61,7 +62,7 @@ function getRateStatusColors(status: string, theme: ReturnType<typeof useTheme>,
     }
 }
 
-function WorkspaceDistanceRatesTableRow({item, rowIndex, shouldUseNarrowTableLayout, statusLabels}: WorkspaceDistanceRatesTableRowProps) {
+function WorkspaceDistanceRatesTableRow({item, rowIndex, shouldUseNarrowTableLayout, shouldShowDateColumns, statusLabels}: WorkspaceDistanceRatesTableRowProps) {
     const theme = useTheme();
     const styles = useThemeStyles();
     const {translate} = useLocalize();
@@ -147,7 +148,7 @@ function WorkspaceDistanceRatesTableRow({item, rowIndex, shouldUseNarrowTableLay
                         </View>
                     )}
 
-                    {!shouldUseNarrowTableLayout && (
+                    {!shouldUseNarrowTableLayout && shouldShowDateColumns && (
                         <View style={[styles.flex1]}>
                             <TextWithTooltip
                                 numberOfLines={1}
@@ -157,7 +158,7 @@ function WorkspaceDistanceRatesTableRow({item, rowIndex, shouldUseNarrowTableLay
                         </View>
                     )}
 
-                    {!shouldUseNarrowTableLayout && (
+                    {!shouldUseNarrowTableLayout && shouldShowDateColumns && (
                         <View style={[styles.flex1]}>
                             <TextWithTooltip
                                 numberOfLines={1}
diff --git a/src/components/Tables/WorkspaceDistanceRatesTable/index.tsx b/src/components/Tables/WorkspaceDistanceRatesTable/index.tsx
index bc82503b42f3..9f978e980a97 100644
--- a/src/components/Tables/WorkspaceDistanceRatesTable/index.tsx
+++ b/src/components/Tables/WorkspaceDistanceRatesTable/index.tsx
@@ -113,6 +113,7 @@ function WorkspaceDistanceRatesTable({ratesData, selectionEnabled, selectedKeys,
             item={item}
             rowIndex={index}
             shouldUseNarrowTableLayout={shouldUseNarrowTableLayout}
+            shouldShowDateColumns={hasAnyDateBound}
             statusLabels={statusLabels}
         />
     );

From 0e3ed56c31c1a8e0b168824a3a32bb9f4b954a44 Mon Sep 17 00:00:00 2001
From: OSBotify <infra+osbotify@expensify.com>
Date: Thu, 11 Jun 2026 18:40:43 +0000
Subject: [PATCH 392/435] Auto-tighten eslint-seatbelt baseline

---
 config/eslint/eslint.seatbelt.tsv | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/config/eslint/eslint.seatbelt.tsv b/config/eslint/eslint.seatbelt.tsv
index 87437e198fbd..1fff655feac8 100644
--- a/config/eslint/eslint.seatbelt.tsv
+++ b/config/eslint/eslint.seatbelt.tsv
@@ -1439,7 +1439,7 @@
 "../../src/pages/workspace/accounting/xero/import/XeroCustomerConfigurationPage.tsx"	"no-restricted-syntax"	3
 "../../src/pages/workspace/accounting/xero/import/XeroCustomerConfigurationPage.tsx"	"rulesdir/no-default-id-values"	1
 "../../src/pages/workspace/categories/CategorySettingsPage.tsx"	"react-hooks/preserve-manual-memoization"	1
-"../../src/pages/workspace/categories/WorkspaceCategoriesPage.tsx"	"react-hooks/set-state-in-effect"	2
+"../../src/pages/workspace/categories/WorkspaceCategoriesPage.tsx"	"react-hooks/set-state-in-effect"	1
 "../../src/pages/workspace/companyCards/BankConnection/index.tsx"	"react-hooks/set-state-in-effect"	1
 "../../src/pages/workspace/companyCards/WorkspaceCompanyCardAddWorkEmailPage.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	2
 "../../src/pages/workspace/companyCards/WorkspaceCompanyCardDetailsPage.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1

From 59faf605f014184e6e6c0a56c7e5ef469ada5386 Mon Sep 17 00:00:00 2001
From: OSBotify <infra+osbotify@expensify.com>
Date: Thu, 11 Jun 2026 19:07:16 +0000
Subject: [PATCH 393/435] Update version to 9.4.5-2

---
 android/app/build.gradle                    | 4 ++--
 ios/NewExpensify/Info.plist                 | 2 +-
 ios/NotificationServiceExtension/Info.plist | 2 +-
 ios/ShareViewController/Info.plist          | 2 +-
 package-lock.json                           | 4 ++--
 package.json                                | 2 +-
 6 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/android/app/build.gradle b/android/app/build.gradle
index 99f1fcfe0153..a9b0db007444 100644
--- a/android/app/build.gradle
+++ b/android/app/build.gradle
@@ -111,8 +111,8 @@ android {
         minSdkVersion rootProject.ext.minSdkVersion
         targetSdkVersion rootProject.ext.targetSdkVersion
         multiDexEnabled rootProject.ext.multiDexEnabled
-        versionCode 1009040501
-        versionName "9.4.5-1"
+        versionCode 1009040502
+        versionName "9.4.5-2"
         // Supported language variants must be declared here to avoid from being removed during the compilation.
         // This also helps us to not include unnecessary language variants in the APK.
         resConfigs "en", "es"
diff --git a/ios/NewExpensify/Info.plist b/ios/NewExpensify/Info.plist
index 120d4f4ee0d1..bc4f83ffa630 100644
--- a/ios/NewExpensify/Info.plist
+++ b/ios/NewExpensify/Info.plist
@@ -44,7 +44,7 @@
 		</dict>
 	</array>
 	<key>CFBundleVersion</key>
-	<string>9.4.5.1</string>
+	<string>9.4.5.2</string>
 	<key>FullStory</key>
 	<dict>
 		<key>OrgId</key>
diff --git a/ios/NotificationServiceExtension/Info.plist b/ios/NotificationServiceExtension/Info.plist
index d6bad0afb8d8..0ca5c65db42c 100644
--- a/ios/NotificationServiceExtension/Info.plist
+++ b/ios/NotificationServiceExtension/Info.plist
@@ -13,7 +13,7 @@
 	<key>CFBundleShortVersionString</key>
 	<string>9.4.5</string>
 	<key>CFBundleVersion</key>
-	<string>9.4.5.1</string>
+	<string>9.4.5.2</string>
 	<key>NSExtension</key>
 	<dict>
 		<key>NSExtensionPointIdentifier</key>
diff --git a/ios/ShareViewController/Info.plist b/ios/ShareViewController/Info.plist
index 2495b937d2ef..e07414831f48 100644
--- a/ios/ShareViewController/Info.plist
+++ b/ios/ShareViewController/Info.plist
@@ -13,7 +13,7 @@
 	<key>CFBundleShortVersionString</key>
 	<string>9.4.5</string>
 	<key>CFBundleVersion</key>
-	<string>9.4.5.1</string>
+	<string>9.4.5.2</string>
 	<key>NSExtension</key>
 	<dict>
 		<key>NSExtensionAttributes</key>
diff --git a/package-lock.json b/package-lock.json
index c7d3719ca24c..837e387ab935 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,12 +1,12 @@
 {
   "name": "new.expensify",
-  "version": "9.4.5-1",
+  "version": "9.4.5-2",
   "lockfileVersion": 3,
   "requires": true,
   "packages": {
     "": {
       "name": "new.expensify",
-      "version": "9.4.5-1",
+      "version": "9.4.5-2",
       "hasInstallScript": true,
       "license": "MIT",
       "workspaces": [
diff --git a/package.json b/package.json
index d3d55741fee2..6909b24e9868 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
   "name": "new.expensify",
-  "version": "9.4.5-1",
+  "version": "9.4.5-2",
   "author": "Expensify, Inc.",
   "homepage": "https://new.expensify.com",
   "description": "New Expensify is the next generation of Expensify: a reimagination of payments based atop a foundation of chat.",

From c06c0b55aa581dcd2ebf631a44a669b0ceca0ade Mon Sep 17 00:00:00 2001
From: OSBotify <infra+osbotify@expensify.com>
Date: Thu, 11 Jun 2026 19:07:16 +0000
Subject: [PATCH 394/435] Update Mobile-Expensify submodule version to 9.4.5-2

---
 Mobile-Expensify | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Mobile-Expensify b/Mobile-Expensify
index 2c3e1fb325b1..ba698f53f0ba 160000
--- a/Mobile-Expensify
+++ b/Mobile-Expensify
@@ -1 +1 @@
-Subproject commit 2c3e1fb325b1fd979e7d5cc1bfd5f727f528be73
+Subproject commit ba698f53f0ba205804541c0bcff6fbe51025a592

From b137cc994f164d73b9fa335fb859d5cd272a460f Mon Sep 17 00:00:00 2001
From: jayeshmangwani <jayeshmangwani@gmail.com>
Date: Fri, 12 Jun 2026 01:27:06 +0530
Subject: [PATCH 395/435] updated no-unsafe-type-assertion to test files

---
 config/eslint/eslint.seatbelt.tsv | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/config/eslint/eslint.seatbelt.tsv b/config/eslint/eslint.seatbelt.tsv
index 1fff655feac8..9d5a8d7a0f24 100644
--- a/config/eslint/eslint.seatbelt.tsv
+++ b/config/eslint/eslint.seatbelt.tsv
@@ -1890,7 +1890,7 @@
 "../../tests/unit/ReportTitleUtilsTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	3
 "../../tests/unit/ReportTitleUtilsTest.ts"	"no-restricted-imports"	1
 "../../tests/unit/ReportUtilsGetIconsTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	1
-"../../tests/unit/ReportUtilsTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	98
+"../../tests/unit/ReportUtilsTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	105
 "../../tests/unit/ReportUtilsTest.ts"	"no-restricted-imports"	1
 "../../tests/unit/ReportWelcomeTextTest.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../tests/unit/RequestConflictUtilsTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	11
@@ -1915,7 +1915,7 @@
 "../../tests/unit/SelectFeaturesEmptyTagGroupTest.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../tests/unit/SettlementButtonUtilsTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	4
 "../../tests/unit/SidebarTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	2
-"../../tests/unit/SidebarUtilsTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	31
+"../../tests/unit/SidebarUtilsTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	38
 "../../tests/unit/SidebarUtilsTest.ts"	"no-restricted-imports"	1
 "../../tests/unit/SplitExpenseAutoAdjustmentTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../tests/unit/SubscriptionUtilsTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	2

From 9646b33e427104c1763101980eef031b443da263 Mon Sep 17 00:00:00 2001
From: jayeshmangwani <jayeshmangwani@gmail.com>
Date: Fri, 12 Jun 2026 01:28:22 +0530
Subject: [PATCH 396/435] revert Mobile-Expensify changes

---
 Mobile-Expensify | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Mobile-Expensify b/Mobile-Expensify
index 42ad9da8bfde..ba698f53f0ba 160000
--- a/Mobile-Expensify
+++ b/Mobile-Expensify
@@ -1 +1 @@
-Subproject commit 42ad9da8bfde582b57b2e66dc30e22757e06deea
+Subproject commit ba698f53f0ba205804541c0bcff6fbe51025a592

From 2538fda12a6f3843c70ebce0cbc963425049c50c Mon Sep 17 00:00:00 2001
From: OSBotify <infra+osbotify@expensify.com>
Date: Thu, 11 Jun 2026 19:59:09 +0000
Subject: [PATCH 397/435] Auto-tighten eslint-seatbelt baseline

---
 config/eslint/eslint.seatbelt.tsv | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/config/eslint/eslint.seatbelt.tsv b/config/eslint/eslint.seatbelt.tsv
index 1fff655feac8..da9a300134a5 100644
--- a/config/eslint/eslint.seatbelt.tsv
+++ b/config/eslint/eslint.seatbelt.tsv
@@ -250,7 +250,7 @@
 "../../src/components/MapView/MapViewImpl.web.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../src/components/MapView/MapViewImpl.web.tsx"	"react-hooks/set-state-in-effect"	1
 "../../src/components/MapView/ToggleDistanceUnitButton/index.android.tsx"	"no-restricted-syntax"	1
-"../../src/components/MenuItem.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	4
+"../../src/components/MenuItem.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	3
 "../../src/components/Modal/BaseModal.tsx"	"react-hooks/set-state-in-effect"	1
 "../../src/components/Modal/Global/ConfirmModalWrapper.tsx"	"@typescript-eslint/no-deprecated/ConfirmModal"	1
 "../../src/components/Modal/Global/ModalContext.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	2

From e66ed4c228d13670b649b38dfaf19ad98ccd3b02 Mon Sep 17 00:00:00 2001
From: jayeshmangwani <jayeshmangwani@gmail.com>
Date: Fri, 12 Jun 2026 01:40:56 +0530
Subject: [PATCH 398/435] revert Mobile-Expensify changes

---
 Mobile-Expensify | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Mobile-Expensify b/Mobile-Expensify
index ba698f53f0ba..2fafa98308e2 160000
--- a/Mobile-Expensify
+++ b/Mobile-Expensify
@@ -1 +1 @@
-Subproject commit ba698f53f0ba205804541c0bcff6fbe51025a592
+Subproject commit 2fafa98308e2e225ead719099a947fbcc89e4141

From 52763a15d6670c61f6bf4d304ef8bdedbfe1974b Mon Sep 17 00:00:00 2001
From: jayeshmangwani <jayeshmangwani@gmail.com>
Date: Fri, 12 Jun 2026 01:43:39 +0530
Subject: [PATCH 399/435] revert Mobile-Expensify changes

---
 Mobile-Expensify | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Mobile-Expensify b/Mobile-Expensify
index 2fafa98308e2..ba698f53f0ba 160000
--- a/Mobile-Expensify
+++ b/Mobile-Expensify
@@ -1 +1 @@
-Subproject commit 2fafa98308e2e225ead719099a947fbcc89e4141
+Subproject commit ba698f53f0ba205804541c0bcff6fbe51025a592

From 5989b2f74d3effedade34f047f2ea755458bd313 Mon Sep 17 00:00:00 2001
From: Puneet Lath <puneet@expensify.com>
Date: Thu, 11 Jun 2026 16:14:55 -0400
Subject: [PATCH 400/435] Remove workflows agent banner, Add agent pill, and
 reconciliation hooks

Strip the "Automate approvals with agents" promo banner and Add agent UI
from Workspace Workflows, along with the hooks that powered them.

Co-authored-by: Cursor <cursoragent@cursor.com>
---
 src/components/ApprovalWorkflowSection.tsx    |  37 +---
 src/hooks/useAddAgentToApprovalWorkflow.ts    |  96 ----------
 .../useDeferredAgentWorkflowReconciliation.ts | 176 ------------------
 .../workflows/WorkspaceWorkflowsPage.tsx      |  62 +-----
 src/types/onyx/DeferredAgentWorkflowSave.ts   |  46 -----
 src/types/onyx/index.ts                       |   2 -
 6 files changed, 7 insertions(+), 412 deletions(-)
 delete mode 100644 src/hooks/useAddAgentToApprovalWorkflow.ts
 delete mode 100644 src/hooks/useDeferredAgentWorkflowReconciliation.ts
 delete mode 100644 src/types/onyx/DeferredAgentWorkflowSave.ts

diff --git a/src/components/ApprovalWorkflowSection.tsx b/src/components/ApprovalWorkflowSection.tsx
index bc08e6e96b65..efad2f0081df 100644
--- a/src/components/ApprovalWorkflowSection.tsx
+++ b/src/components/ApprovalWorkflowSection.tsx
@@ -4,7 +4,6 @@ import {View} from 'react-native';
 import {useCurrencyListActions} from '@hooks/useCurrencyList';
 import {useMemoizedLazyExpensifyIcons} from '@hooks/useLazyAsset';
 import useLocalize from '@hooks/useLocalize';
-import usePermissions from '@hooks/usePermissions';
 import useResponsiveLayout from '@hooks/useResponsiveLayout';
 import useTheme from '@hooks/useTheme';
 import useThemeStyles from '@hooks/useThemeStyles';
@@ -31,22 +30,6 @@ type ApprovalWorkflowSectionProps = {
     /** Called when the "+X more" text inside the members row is pressed — deep-links to the members list (skips the Edit RHP). */
     onShowAllMembersPress?: () => void;
 
-    /** A function that is called when the Add agent pill is pressed */
-    onAddAgentPress?: () => void;
-
-    /**
-     * Called when the X is clicked on an approver row that carries `approver.errors`. The page
-     * uses this to discard the failed optimistic agent (clears the deferred-save entry, the
-     * optimistic personal detail / prompt, and the policy-level addAgent error).
-     */
-    onDismissApproverError?: (approver: Approver) => void;
-
-    /**
-     * Whether the Add agent pill is allowed on this card. It is still gated by the
-     * customAgent beta on top of this flag.
-     */
-    canAddAgent?: boolean;
-
     /** Currency used for formatting approval limits */
     currency?: string;
 
@@ -67,25 +50,18 @@ function ApprovalWorkflowSection({
     approvalWorkflow,
     onPress,
     onShowAllMembersPress,
-    onAddAgentPress,
-    onDismissApproverError,
-    canAddAgent = false,
     currency = CONST.CURRENCY.USD,
     isDisabled = false,
     hrProviderName,
     isHRAdvancedMode = false,
     hrFinalApproverEmail,
 }: ApprovalWorkflowSectionProps) {
-    const icons = useMemoizedLazyExpensifyIcons(['ArrowRight', 'Bot', 'Lightbulb', 'Pencil', 'Users', 'UserCheck']);
+    const icons = useMemoizedLazyExpensifyIcons(['ArrowRight', 'Lightbulb', 'Pencil', 'Users', 'UserCheck']);
     const styles = useThemeStyles();
     const theme = useTheme();
     const {translate, toLocaleOrdinal, localeCompare} = useLocalize();
     const {convertToDisplayString} = useCurrencyListActions();
     const {shouldUseNarrowLayout} = useResponsiveLayout();
-    const {isBetaEnabled} = usePermissions();
-    const isCustomAgentEnabled = isBetaEnabled(CONST.BETAS.CUSTOM_AGENT);
-    const shouldShowAddAgentButton = canAddAgent && isCustomAgentEnabled && !isDisabled && !!onAddAgentPress;
-
     const approverTitle = (index: number) => {
         if (isHRAdvancedMode) {
             const isLast = index === approvalWorkflow.approvers.length - 1;
@@ -179,7 +155,6 @@ function ApprovalWorkflowSection({
                         key={`approver-${approver.email || approver.accountID}-${index}`}
                         pendingAction={approver.pendingAction}
                         errors={approver.errors}
-                        onClose={approver.errors && onDismissApproverError ? () => onDismissApproverError(approver) : undefined}
                     >
                         <View>
                             <View style={styles.workflowApprovalVerticalLine} />
@@ -225,16 +200,6 @@ function ApprovalWorkflowSection({
                         accessibilityLabel={translate('workflowsPage.editWorkflowAction')}
                         sentryLabel={CONST.SENTRY_LABEL.WORKSPACE.APPROVAL_WORKFLOW_SECTION}
                     />
-                    {shouldShowAddAgentButton && (
-                        <Button
-                            small
-                            icon={icons.Bot}
-                            text={translate('workflowsPage.addAgentAction')}
-                            onPress={onAddAgentPress}
-                            accessibilityLabel={translate('workflowsPage.addAgentAction')}
-                            sentryLabel={CONST.SENTRY_LABEL.WORKSPACE.APPROVAL_WORKFLOW_SECTION}
-                        />
-                    )}
                 </View>
             )}
         </View>
diff --git a/src/hooks/useAddAgentToApprovalWorkflow.ts b/src/hooks/useAddAgentToApprovalWorkflow.ts
deleted file mode 100644
index e34bc1cac936..000000000000
--- a/src/hooks/useAddAgentToApprovalWorkflow.ts
+++ /dev/null
@@ -1,96 +0,0 @@
-import type {OnyxEntry} from 'react-native-onyx';
-import Navigation from '@libs/Navigation/Navigation';
-import {getMemberAccountIDsForWorkspace} from '@libs/PolicyUtils';
-import type {AvatarSource} from '@libs/UserAvatarUtils';
-import {addMembersToWorkspace} from '@userActions/Policy/Member';
-import CONST from '@src/CONST';
-import ONYXKEYS from '@src/ONYXKEYS';
-import ROUTES from '@src/ROUTES';
-import type {Policy} from '@src/types/onyx';
-import type ApprovalWorkflow from '@src/types/onyx/ApprovalWorkflow';
-import useAllPolicyExpenseChatReportActions from './useAllPolicyExpenseChatReportActions';
-import useCurrentUserPersonalDetails from './useCurrentUserPersonalDetails';
-import useLocalize from './useLocalize';
-import useOnyx from './useOnyx';
-
-type OwnedAgent = {accountID: number; email: string; displayName: string; avatar?: AvatarSource};
-
-/**
- * Returns a handler that seeds an approval workflow with the current user's first available
- * owned agent and navigates to the approver edit screen. When every owned agent is already
- * an approver on the workflow, the handler routes the admin to the create-agent screen so
- * we don't duplicate an existing agent.
- */
-function useAddAgentToApprovalWorkflow(policy: OnyxEntry<Policy>, policyID: string) {
-    const {formatPhoneNumber} = useLocalize();
-    const currentUserPersonalDetails = useCurrentUserPersonalDetails();
-    const [personalDetails] = useOnyx(ONYXKEYS.PERSONAL_DETAILS_LIST);
-    const [agentPrompts] = useOnyx(ONYXKEYS.COLLECTION.SHARED_NVP_AGENT_PROMPT);
-    const filteredReportActions = useAllPolicyExpenseChatReportActions();
-
-    const ownedAgents: OwnedAgent[] = (() => {
-        if (!agentPrompts || !personalDetails) {
-            return [];
-        }
-        return Object.keys(agentPrompts)
-            .map<OwnedAgent | null>((key) => {
-                const accountID = Number(key.slice(ONYXKEYS.COLLECTION.SHARED_NVP_AGENT_PROMPT.length));
-                const details = personalDetails[accountID];
-                if (!details?.login) {
-                    return null;
-                }
-                return {
-                    accountID,
-                    email: details.login,
-                    displayName: details.displayName ?? details.login,
-                    avatar: details.avatar,
-                };
-            })
-            .filter((agent): agent is OwnedAgent => !!agent);
-    })();
-
-    return (workflow: ApprovalWorkflow) => {
-        const workflowApproverEmail = workflow.approvers.at(0)?.email ?? '';
-
-        // Prefer the first owned agent that isn't already an approver on this workflow.
-        // If every owned agent is already in the workflow there's nothing to seed, so we
-        // route the admin to create a new agent instead of duplicating an existing one.
-        const agentToSeed = ownedAgents.find((candidate) => !workflow.approvers.some((approver) => approver.email === candidate.email));
-        if (!agentToSeed) {
-            Navigation.navigate(
-                ROUTES.WORKSPACE_WORKFLOWS_ADD_AGENT.getRoute({
-                    policyID,
-                    workflowApproverEmail,
-                }),
-            );
-            return;
-        }
-
-        // Ensure the agent is a workspace member before they show up as an approver. The
-        // server makes this idempotent so it's safe to call even if the agent was added via
-        // the API's `policyID` parameter when CREATE_AGENT was first called.
-        const isAlreadyMember = !!policy?.employeeList?.[agentToSeed.email];
-        if (!isAlreadyMember && policy) {
-            const policyMemberAccountIDs = Object.values(getMemberAccountIDsForWorkspace(policy.employeeList, false, false));
-            addMembersToWorkspace(
-                {[agentToSeed.email]: agentToSeed.accountID},
-                '',
-                policy,
-                policyMemberAccountIDs,
-                CONST.POLICY.ROLE.USER,
-                formatPhoneNumber,
-                {
-                    accountID: currentUserPersonalDetails.accountID,
-                    displayName: currentUserPersonalDetails.displayName,
-                    email: currentUserPersonalDetails.login,
-                    avatar: currentUserPersonalDetails.avatar,
-                },
-                filteredReportActions,
-            );
-        }
-
-        Navigation.navigate(ROUTES.WORKSPACE_WORKFLOWS_APPROVALS_EDIT.getRoute(policyID, workflowApproverEmail, agentToSeed.email));
-    };
-}
-
-export default useAddAgentToApprovalWorkflow;
diff --git a/src/hooks/useDeferredAgentWorkflowReconciliation.ts b/src/hooks/useDeferredAgentWorkflowReconciliation.ts
deleted file mode 100644
index dc1fc17da549..000000000000
--- a/src/hooks/useDeferredAgentWorkflowReconciliation.ts
+++ /dev/null
@@ -1,176 +0,0 @@
-import {useEffect, useRef} from 'react';
-import type {OnyxEntry} from 'react-native-onyx';
-import {buildDeferredAgentWorkflowSaveKey, clearDeferredAgentWorkflowSave, updateApprovalWorkflow} from '@libs/actions/Workflow';
-import {resolveOptimisticAgent} from '@libs/WorkflowUtils';
-import CONST from '@src/CONST';
-import ONYXKEYS from '@src/ONYXKEYS';
-import type {Policy} from '@src/types/onyx';
-import type ApprovalWorkflow from '@src/types/onyx/ApprovalWorkflow';
-import {isEmptyObject} from '@src/types/utils/EmptyObject';
-import useOnyx from './useOnyx';
-
-type ApprovalWorkflowWithRouting = ApprovalWorkflow & {routingFirstApproverEmail: string};
-
-/**
- * Overlays deferred-save approval workflows on top of the server's view and reconciles them
- * once the pending agent's real identity lands.
- *
- * - Overlay: when the admin saves an Edit Approvers page while CREATE_AGENT is still in
- *   flight, we stash the workflow in `DEFERRED_AGENT_WORKFLOW_SAVES`. This hook merges that
- *   stashed approver chain into the workflows list so the new agent shows up faded in the
- *   workflow card. Each workflow also gets a `routingFirstApproverEmail` so the edit route /
- *   list key keep using the original (pre-overlay) email even when the overlaid `approvers[0]`
- *   is a pending agent with an empty `email` placeholder. A failed `CREATE_AGENT` surfaces
- *   `policy.errorFields[ADD_AGENT]` on the pending approver row so the admin sees an RBR
- *   right where the optimistic agent is shown.
- * - Reconcile: once the pending agent has a real email (the personal detail at
- *   `pendingAgentAccountID` gains a login OR `OPTIMISTIC_AGENT_ACCOUNT_ID_MAPPING` echoes a
- *   real accountID OR a prompt-match resolves to a known member), we swap that email into
- *   the workflow, fire the real `updateApprovalWorkflow`, and clear the entry.
- */
-function useDeferredAgentWorkflowReconciliation(rawApprovalWorkflows: ApprovalWorkflow[], policy: OnyxEntry<Policy>, policyID: string): ApprovalWorkflowWithRouting[] {
-    const [deferredAgentWorkflowSaves] = useOnyx(ONYXKEYS.DEFERRED_AGENT_WORKFLOW_SAVES);
-    const [agentPrompts] = useOnyx(ONYXKEYS.COLLECTION.SHARED_NVP_AGENT_PROMPT);
-    const [optimisticAgentAccountIDMapping] = useOnyx(ONYXKEYS.OPTIMISTIC_AGENT_ACCOUNT_ID_MAPPING);
-    const [personalDetails] = useOnyx(ONYXKEYS.PERSONAL_DETAILS_LIST);
-
-    const addAgentErrors = policy?.errorFields?.[CONST.POLICY.COLLECTION_KEYS.ADD_AGENT];
-
-    const approvalWorkflows: ApprovalWorkflowWithRouting[] = (() => {
-        if (!deferredAgentWorkflowSaves || isEmptyObject(deferredAgentWorkflowSaves)) {
-            return rawApprovalWorkflows.map((workflow) => ({...workflow, routingFirstApproverEmail: workflow.approvers.at(0)?.email ?? ''}));
-        }
-        return rawApprovalWorkflows.map((workflow) => {
-            const firstApproverEmail = workflow.approvers.at(0)?.email ?? '';
-            if (!firstApproverEmail) {
-                return {...workflow, routingFirstApproverEmail: firstApproverEmail};
-            }
-            const deferredEntry = deferredAgentWorkflowSaves[buildDeferredAgentWorkflowSaveKey(policyID, firstApproverEmail)];
-            if (!deferredEntry) {
-                return {...workflow, routingFirstApproverEmail: firstApproverEmail};
-            }
-            const overlaidApprovers = deferredEntry.approvalWorkflow.approvers
-                .filter((approver): approver is NonNullable<typeof approver> => !!approver)
-                .map((approver) =>
-                    addAgentErrors && approver.accountID === deferredEntry.pendingAgentAccountID && approver.pendingAction === CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD
-                        ? {...approver, errors: addAgentErrors}
-                        : approver,
-                );
-            return {
-                ...workflow,
-                approvers: overlaidApprovers,
-                routingFirstApproverEmail: firstApproverEmail,
-            };
-        });
-    })();
-
-    // Tracks deferred-save keys we've already reconciled in this mount. `updateApprovalWorkflow`'s
-    // optimistic write to `policy.employeeList` re-renders the page before the matching
-    // `clearDeferredAgentWorkflowSave` Onyx merge settles; without this guard the effect would
-    // fire `updateApprovalWorkflow` (and the underlying `UPDATE_WORKSPACE_APPROVAL` API call)
-    // a second time for the same entry on that intermediate render.
-    const reconciledDeferredKeysRef = useRef<Set<string>>(new Set());
-
-    useEffect(() => {
-        // Drop any tracked keys whose Onyx entries are gone (clear has settled or the entry was
-        // removed elsewhere) so the same key can be reconciled again if it ever reappears.
-        if (reconciledDeferredKeysRef.current.size > 0) {
-            for (const key of [...reconciledDeferredKeysRef.current]) {
-                if (!deferredAgentWorkflowSaves?.[key]) {
-                    reconciledDeferredKeysRef.current.delete(key);
-                }
-            }
-        }
-        if (!deferredAgentWorkflowSaves || isEmptyObject(deferredAgentWorkflowSaves) || !policy || !personalDetails) {
-            return;
-        }
-        for (const deferredEntry of Object.values(deferredAgentWorkflowSaves)) {
-            if (!deferredEntry || deferredEntry.policyID !== policyID) {
-                continue;
-            }
-            const deferredKey = buildDeferredAgentWorkflowSaveKey(deferredEntry.policyID, deferredEntry.firstApproverEmail);
-            if (reconciledDeferredKeysRef.current.has(deferredKey)) {
-                continue;
-            }
-            const pendingApprover = deferredEntry.approvalWorkflow.approvers.find(
-                (approver) => approver?.pendingAction === CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD && approver.accountID === deferredEntry.pendingAgentAccountID,
-            );
-            if (!pendingApprover) {
-                // Nothing left to wait on — the save can fire as-is (or was already fired).
-                reconciledDeferredKeysRef.current.add(deferredKey);
-                clearDeferredAgentWorkflowSave(deferredEntry.policyID, deferredEntry.firstApproverEmail);
-                continue;
-            }
-            const knownEmails = new Set(
-                deferredEntry.approvalWorkflow.approvers
-                    .filter((approver): approver is NonNullable<typeof approver> => !!approver?.email && approver.accountID !== deferredEntry.pendingAgentAccountID)
-                    .map((approver) => approver.email),
-            );
-            const resolved = resolveOptimisticAgent({
-                optimisticAccountID: deferredEntry.pendingAgentAccountID,
-                pendingAgentPrompt: deferredEntry.pendingAgentPrompt,
-                personalDetails,
-                employeeList: policy.employeeList,
-                agentPrompts,
-                optimisticAccountIDMapping: optimisticAgentAccountIDMapping,
-                knownApproverEmails: knownEmails,
-            });
-            if (!resolved) {
-                continue;
-            }
-            const {accountID: resolvedAccountID, email: resolvedEmail} = resolved;
-            // Upgrade the deferred workflow with the real email, then fire the save action.
-            // `updateApprovalWorkflow` expects `ApprovalWorkflow` (approvers required, no
-            // editor-only fields), so filter out the holes in the Onyx representation and
-            // hand off only the fields it cares about.
-            const upgradedApprovers = deferredEntry.approvalWorkflow.approvers
-                .filter((approver): approver is NonNullable<typeof approver> => !!approver)
-                .map((approver) =>
-                    approver === pendingApprover
-                        ? {
-                              ...approver,
-                              email: resolvedEmail,
-                              accountID: resolvedAccountID,
-                              pendingAction: undefined,
-                          }
-                        : approver,
-                );
-            // When the saved workflow is the default one, the new agent becomes the new default
-            // approver. The deferred snapshot's `members` list was captured before CREATE_AGENT
-            // resolved, so the agent isn't in it — and `convertApprovalWorkflowToPolicyEmployees`
-            // only rewrites `submitsTo` for emails present in `members`. Without the agent in
-            // that list their `submitsTo` (set to the previous default approver by
-            // `shareWithEmployees` in CreateAgent.cpp) is never overwritten, leaving them as
-            // their own orphan submission group in the workflows list. Injecting them here
-            // mirrors the online editor's behaviour (where the agent is already in employeeList
-            // when the editor renders and falls naturally into the "Everyone" members list) so
-            // the agent ends up submitting to themselves like every other default approver.
-            const upgradedMembers =
-                deferredEntry.approvalWorkflow.isDefault && !deferredEntry.approvalWorkflow.members.some((member) => member.email === resolvedEmail)
-                    ? [
-                          ...deferredEntry.approvalWorkflow.members,
-                          {
-                              email: resolvedEmail,
-                              displayName: pendingApprover.displayName,
-                              avatar: pendingApprover.avatar,
-                          },
-                      ]
-                    : deferredEntry.approvalWorkflow.members;
-            const upgradedWorkflow = {
-                members: upgradedMembers,
-                approvers: upgradedApprovers,
-                isDefault: deferredEntry.approvalWorkflow.isDefault,
-            };
-            const initialApprovers = deferredEntry.initialApprovalWorkflow.approvers.filter((approver): approver is NonNullable<typeof approver> => !!approver);
-            const membersToRemove = deferredEntry.initialApprovalWorkflow.members.filter((initialMember) => !upgradedWorkflow.members.some((member) => member.email === initialMember.email));
-            const approversToRemove = initialApprovers.filter((initialApprover) => !upgradedWorkflow.approvers.some((approver) => approver.email === initialApprover.email));
-            reconciledDeferredKeysRef.current.add(deferredKey);
-            updateApprovalWorkflow(upgradedWorkflow, membersToRemove, approversToRemove, policy);
-            clearDeferredAgentWorkflowSave(deferredEntry.policyID, deferredEntry.firstApproverEmail);
-        }
-    }, [deferredAgentWorkflowSaves, policy, personalDetails, policyID, agentPrompts, optimisticAgentAccountIDMapping]);
-
-    return approvalWorkflows;
-}
-
-export default useDeferredAgentWorkflowReconciliation;
diff --git a/src/pages/workspace/workflows/WorkspaceWorkflowsPage.tsx b/src/pages/workspace/workflows/WorkspaceWorkflowsPage.tsx
index 0949c5fdcd2a..b496201f7bb6 100644
--- a/src/pages/workspace/workflows/WorkspaceWorkflowsPage.tsx
+++ b/src/pages/workspace/workflows/WorkspaceWorkflowsPage.tsx
@@ -5,7 +5,6 @@ import React, {useCallback, useEffect, useMemo} from 'react';
 import {InteractionManager, View} from 'react-native';
 import type {OnyxEntry} from 'react-native-onyx';
 import type {TupleToUnion} from 'type-fest';
-import AgentPromotionalBanner from '@components/AgentPromotionalBanner';
 import ApprovalWorkflowSection from '@components/ApprovalWorkflowSection';
 import Icon from '@components/Icon';
 import getBankIcon from '@components/Icon/BankIcons';
@@ -20,12 +19,10 @@ import SearchBar from '@components/SearchBar';
 import Section from '@components/Section';
 import Text from '@components/Text';
 import TextLink from '@components/TextLink';
-import useAddAgentToApprovalWorkflow from '@hooks/useAddAgentToApprovalWorkflow';
 import useCardFeeds from '@hooks/useCardFeeds';
 import useConfirmModal from '@hooks/useConfirmModal';
 import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails';
 import useDebouncedAccessibilityAnnouncement from '@hooks/useDebouncedAccessibilityAnnouncement';
-import useDeferredAgentWorkflowReconciliation from '@hooks/useDeferredAgentWorkflowReconciliation';
 import useDelegateAccountID from '@hooks/useDelegateAccountID';
 import {useMemoizedLazyExpensifyIcons, useMemoizedLazyIllustrations} from '@hooks/useLazyAsset';
 import useLocalize from '@hooks/useLocalize';
@@ -38,7 +35,6 @@ import useSearchResults from '@hooks/useSearchResults';
 import useTheme from '@hooks/useTheme';
 import useThemeStyles from '@hooks/useThemeStyles';
 import useWorkspaceDocumentTitle from '@hooks/useWorkspaceDocumentTitle';
-import {clearPendingAgentFromApprovalWorkflow} from '@libs/actions/Agent';
 import {
     clearPolicyErrorField,
     isCurrencySupportedForDirectReimbursement,
@@ -48,7 +44,6 @@ import {
     setWorkspaceAutoHarvesting,
     setWorkspaceReimbursement,
 } from '@libs/actions/Policy/Policy';
-import {dismissProductTraining} from '@libs/actions/Welcome';
 import {clearApprovalWorkflow, selectApprovalWorkflowForEdit, setApprovalWorkflow} from '@libs/actions/Workflow';
 import {isBankAccountPartiallySetup} from '@libs/BankAccountUtils';
 import {getAllCardsForWorkspace, isSmartLimitEnabled as isSmartLimitEnabledUtil} from '@libs/CardUtils';
@@ -85,7 +80,6 @@ import ONYXKEYS from '@src/ONYXKEYS';
 import ROUTES from '@src/ROUTES';
 import type SCREENS from '@src/SCREENS';
 import type ApprovalWorkflow from '@src/types/onyx/ApprovalWorkflow';
-import type DismissedProductTraining from '@src/types/onyx/DismissedProductTraining';
 import type {ToggleSettingOptionRowProps} from './ToggleSettingsOptionRow';
 import ToggleSettingOptionRow from './ToggleSettingsOptionRow';
 import {getAutoReportingFrequencyDisplayNames} from './WorkspaceAutoReportingFrequencyPage';
@@ -93,8 +87,6 @@ import {getAutoReportingFrequencyDisplayNames} from './WorkspaceAutoReportingFre
 type WorkspaceWorkflowsPageProps = WithPolicyProps & PlatformStackScreenProps<WorkspaceSplitNavigatorParamList, typeof SCREENS.WORKSPACE.WORKFLOWS>;
 type CurrencyType = TupleToUnion<typeof CONST.DIRECT_REIMBURSEMENT_CURRENCIES>;
 
-const agentsWorkflowsBannerDismissedSelector = (value: OnyxEntry<DismissedProductTraining>): boolean => !!value?.[CONST.AGENTS_WORKFLOWS_BANNER];
-
 function WorkflowNoResultsView({message, shouldShow, searchValue}: {message: string; shouldShow: boolean; searchValue: string}) {
     const styles = useThemeStyles();
 
@@ -132,11 +124,8 @@ function WorkspaceWorkflowsPage({policy, route}: WorkspaceWorkflowsPageProps) {
     const [allReportNextSteps] = useOnyx(ONYXKEYS.COLLECTION.NEXT_STEP);
     const [transactionViolations] = useOnyx(ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS);
     const [betas] = useOnyx(ONYXKEYS.BETAS);
-    const [deferredAgentWorkflowSaves] = useOnyx(ONYXKEYS.DEFERRED_AGENT_WORKFLOW_SAVES);
     const {isBetaEnabled} = usePermissions();
     const isSubmit2026BetaEnabled = isBetaEnabled(CONST.BETAS.SUBMIT_2026);
-    const isCustomAgentBetaEnabled = isBetaEnabled(CONST.BETAS.CUSTOM_AGENT);
-    const [isAgentsWorkflowsBannerDismissed = false] = useOnyx(ONYXKEYS.NVP_DISMISSED_PRODUCT_TRAINING, {selector: agentsWorkflowsBannerDismissedSelector});
     const [bankAccountList] = useOnyx(ONYXKEYS.BANK_ACCOUNT_LIST);
     const workspaceCards = getAllCardsForWorkspace(workspaceAccountID, cardList, cardFeeds);
     const {showConfirmModal} = useConfirmModal();
@@ -152,7 +141,7 @@ function WorkspaceWorkflowsPage({policy, route}: WorkspaceWorkflowsPageProps) {
     const {accountID: currentUserAccountID, email: currentUserEmail = '', login: currentUserLogin = ''} = useCurrentUserPersonalDetails();
     const isUserReimburser = policy?.achAccount?.reimburser !== undefined && account?.primaryLogin !== undefined && policy?.achAccount?.reimburser === account?.primaryLogin;
     const {
-        approvalWorkflows: rawApprovalWorkflows,
+        approvalWorkflows,
         availableMembers,
         usedApproverEmails,
     } = convertPolicyEmployeesToApprovalWorkflows({
@@ -162,7 +151,6 @@ function WorkspaceWorkflowsPage({policy, route}: WorkspaceWorkflowsPageProps) {
         currentUserLogin,
     });
 
-    const approvalWorkflows = useDeferredAgentWorkflowReconciliation(rawApprovalWorkflows, policy, route.params.policyID);
     const canAccessSubmit2026Features = canAccessSubmitWorkspaceFeatures(policy, isSubmit2026BetaEnabled);
     const hasValidExistingAccounts = getEligibleExistingBusinessBankAccounts(bankAccountList, policy?.outputCurrency, true).length > 0;
 
@@ -182,21 +170,10 @@ function WorkspaceWorkflowsPage({policy, route}: WorkspaceWorkflowsPageProps) {
 
     const onPressAutoReportingFrequency = useCallback(() => Navigation.navigate(ROUTES.WORKSPACE_WORKFLOWS_AUTOREPORTING_FREQUENCY.getRoute(route.params.policyID)), [route.params.policyID]);
 
-    const hasPendingDeferredAgentSave = useMemo(
-        () => Object.values(deferredAgentWorkflowSaves ?? {}).some((entry) => entry?.policyID === route.params.policyID),
-        [deferredAgentWorkflowSaves, route.params.policyID],
-    );
-
     const fetchData = useCallback(() => {
-        // Skip the workflows refetch while a freshly-added offline agent's deferred workflow save is still
-        // pending reconciliation: the READ returns the pre-approval-update employeeList (workspace owner is
-        // still the approver), which would clobber the optimistic agent-as-approver overlay and briefly
-        // flicker the approver row when the connection is restored.
-        if (!hasPendingDeferredAgentSave) {
-            openPolicyWorkflowsPage(route.params.policyID, true);
-        }
+        openPolicyWorkflowsPage(route.params.policyID, true);
         getPaymentMethods();
-    }, [route.params.policyID, hasPendingDeferredAgentSave]);
+    }, [route.params.policyID]);
 
     const confirmCurrencyChangeAndHideModal = useCallback(() => {
         if (!policy) {
@@ -283,7 +260,6 @@ function WorkspaceWorkflowsPage({policy, route}: WorkspaceWorkflowsPageProps) {
         Navigation.navigate(ROUTES.WORKSPACE_WORKFLOWS_APPROVALS_EXPENSES_FROM.getRoute(route.params.policyID));
     }, [policy, route.params.policyID, availableMembers, usedApproverEmails, canAccessSubmit2026Features, navigateToSubmitWorkspaceApprovalsUpgrade]);
 
-    const handleAddAgentPress = useAddAgentToApprovalWorkflow(policy, route.params.policyID);
     const isHRAdvancedModeEnabled = isHRAdvancedMode(policy);
     const hrFinalApproverEmail = getHRFinalApprover(policy) ?? undefined;
 
@@ -485,15 +461,6 @@ function WorkspaceWorkflowsPage({policy, route}: WorkspaceWorkflowsPageProps) {
                                 </View>
                             </View>
                         )}
-                        {isCustomAgentBetaEnabled && !isAgentsWorkflowsBannerDismissed && (
-                            <AgentPromotionalBanner
-                                title={translate('workflowsPage.automateApprovalsWithAgentsTitle')}
-                                subtitle={translate('workflowsPage.automateApprovalsWithAgentsSubtitle')}
-                                onDismiss={() => dismissProductTraining(CONST.AGENTS_WORKFLOWS_BANNER, true)}
-                                dismissSentryLabel={CONST.SENTRY_LABEL.AGENTS_WORKFLOWS_BANNER.DISMISS}
-                                style={styles.mt6}
-                            />
-                        )}
                         {filteredApprovalWorkflows.length > CONST.SEARCH_BAR_THRESHOLD && (
                             <SearchBar
                                 label={translate('workflowsPage.findWorkflow')}
@@ -509,7 +476,7 @@ function WorkspaceWorkflowsPage({policy, route}: WorkspaceWorkflowsPageProps) {
                         />
                         {searchFilteredWorkflows.map((workflow) => (
                             <OfflineWithFeedback
-                                key={workflow.routingFirstApproverEmail}
+                                key={workflow.approvers.at(0)?.email ?? ''}
                                 pendingAction={workflow.pendingAction}
                             >
                                 <ApprovalWorkflowSection
@@ -520,19 +487,14 @@ function WorkspaceWorkflowsPage({policy, route}: WorkspaceWorkflowsPageProps) {
                                             : () => {
                                                   // Discard stale onyx edits or the Edit page's resume check would surface a prior abandoned session.
                                                   clearApprovalWorkflow();
-                                                  Navigation.navigate(ROUTES.WORKSPACE_WORKFLOWS_APPROVALS_EDIT.getRoute(route.params.policyID, workflow.routingFirstApproverEmail));
+                                                  Navigation.navigate(ROUTES.WORKSPACE_WORKFLOWS_APPROVALS_EDIT.getRoute(route.params.policyID, workflow.approvers.at(0)?.email ?? ''));
                                               }
                                     }
                                     onShowAllMembersPress={
                                         shouldBlockApprovalWorkflowEditing
                                             ? undefined
                                             : () => {
-                                                  // Use the raw workflow (pre-overlay) — a deferred-agent overlay can blank approvers[0].email, breaking ExpensesFromPage's Edit-route backTo.
-                                                  const rawWorkflow = rawApprovalWorkflows.find((w) => w.approvers.at(0)?.email === workflow.routingFirstApproverEmail);
-                                                  if (!rawWorkflow) {
-                                                      return;
-                                                  }
-                                                  selectApprovalWorkflowForEdit({workflow: rawWorkflow, defaultWorkflowMembers: availableMembers, usedApproverEmails});
+                                                  selectApprovalWorkflowForEdit({workflow, defaultWorkflowMembers: availableMembers, usedApproverEmails});
                                                   Navigation.navigate(
                                                       ROUTES.WORKSPACE_WORKFLOWS_APPROVALS_EXPENSES_FROM.getRoute(
                                                           route.params.policyID,
@@ -541,14 +503,6 @@ function WorkspaceWorkflowsPage({policy, route}: WorkspaceWorkflowsPageProps) {
                                                   );
                                               }
                                     }
-                                    onAddAgentPress={() => handleAddAgentPress(workflow)}
-                                    onDismissApproverError={(approver) => {
-                                        if (approver.accountID === undefined) {
-                                            return;
-                                        }
-                                        clearPendingAgentFromApprovalWorkflow(route.params.policyID, workflow.routingFirstApproverEmail, approver.accountID);
-                                    }}
-                                    canAddAgent={!shouldBlockApprovalWorkflowEditing && isPolicyAdmin}
                                     currency={policy?.outputCurrency}
                                     isDisabled={shouldBlockApprovalWorkflowEditing || !canWriteApprovals}
                                     hrProviderName={isHRConnected ? hrProviderName : undefined}
@@ -781,7 +735,6 @@ function WorkspaceWorkflowsPage({policy, route}: WorkspaceWorkflowsPageProps) {
         approvalSubtitle,
         availableMembers,
         usedApproverEmails,
-        rawApprovalWorkflows,
         navigateToSubmitWorkspaceApprovalsUpgrade,
         promptConfigureApprovalsInHR,
         isDEWEnabled,
@@ -789,8 +742,6 @@ function WorkspaceWorkflowsPage({policy, route}: WorkspaceWorkflowsPageProps) {
         expensifyIcons.Info,
         expensifyIcons.Plus,
         expensifyIcons.DotIndicator,
-        isCustomAgentBetaEnabled,
-        isAgentsWorkflowsBannerDismissed,
         theme.textSupporting,
         accountManagerReportID,
         filteredApprovalWorkflows.length,
@@ -828,7 +779,6 @@ function WorkspaceWorkflowsPage({policy, route}: WorkspaceWorkflowsPageProps) {
         withPaymentsReadOnlyFallback,
         withWorkflowsReadOnlyFallback,
         showReadOnlyModal,
-        handleAddAgentPress,
     ]);
 
     const renderOptionItem = (item: ToggleSettingOptionRowProps, index: number) => (
diff --git a/src/types/onyx/DeferredAgentWorkflowSave.ts b/src/types/onyx/DeferredAgentWorkflowSave.ts
deleted file mode 100644
index de31043ce8dd..000000000000
--- a/src/types/onyx/DeferredAgentWorkflowSave.ts
+++ /dev/null
@@ -1,46 +0,0 @@
-import type ApprovalWorkflow from './ApprovalWorkflow';
-import type {ApprovalWorkflowOnyx} from './ApprovalWorkflow';
-
-/**
- * A workflow save the admin committed while a freshly-created agent was still pending. We
- * stash the edited workflow here when the user clicks "Save" on the Edit Approvers page
- * before `CREATE_AGENT` resolves; the WorkspaceWorkflowsPage watcher reconciles each entry
- * once the agent gets its real email/accountID and fires the actual API write.
- */
-type DeferredAgentWorkflowSave = {
-    /** Workspace this save belongs to */
-    policyID: string;
-
-    /** Email of the workflow's primary approver (the route's `firstApproverEmail`) */
-    firstApproverEmail: string;
-
-    /**
-     * Snapshot of the workflow as it appeared in the editor at the time of save (using the
-     * Onyx editor shape — approvers may include `undefined` placeholders for empty rows).
-     */
-    approvalWorkflow: ApprovalWorkflowOnyx;
-
-    /**
-     * Snapshot of the workflow BEFORE the edit. Matches the shape of the value stored in
-     * `useState<ApprovalWorkflow>` on the Edit Approvers page (approvers required).
-     */
-    initialApprovalWorkflow: ApprovalWorkflow;
-
-    /**
-     * Optimistic accountID of the pending agent we're waiting on. When the personal detail
-     * at this accountID gains a `login` (or a corresponding employeeList entry shows up on
-     * the policy), the watcher swaps that login into the workflow and fires the real save.
-     */
-    pendingAgentAccountID: number;
-
-    /**
-     * Prompt of the pending agent, captured at save time from the optimistic
-     * `SHARED_NVP_AGENT_PROMPT` entry. The reconciliation watcher uses this as a stable
-     * identifier to find the resolved agent (a new collection entry with the same prompt at
-     * a different, server-assigned accountID) instead of falling back to a displayName match,
-     * which can collide in workspaces with duplicate names.
-     */
-    pendingAgentPrompt: string;
-};
-
-export default DeferredAgentWorkflowSave;
diff --git a/src/types/onyx/index.ts b/src/types/onyx/index.ts
index 73d114a88216..00421d36a3a5 100644
--- a/src/types/onyx/index.ts
+++ b/src/types/onyx/index.ts
@@ -46,7 +46,6 @@ import type Credentials from './Credentials';
 import type Currency from './Currency';
 import type {CurrencyList} from './Currency';
 import type CustomStatusDraft from './CustomStatusDraft';
-import type DeferredAgentWorkflowSave from './DeferredAgentWorkflowSave';
 import type {
     CardFeedErrorsDerivedValue,
     NonPersonalAndWorkspaceCardListDerivedValue,
@@ -366,7 +365,6 @@ export type {
     BillingStatus,
     CancellationDetails,
     ApprovalWorkflowOnyx,
-    DeferredAgentWorkflowSave,
     CardFeeds,
     CardFeedsStatus,
     CardFeedsStatusByDomainID,

From 5012bda01a03606a4d499e4b5a28466a096e4cb8 Mon Sep 17 00:00:00 2001
From: Puneet Lath <puneet@expensify.com>
Date: Thu, 11 Jun 2026 16:15:18 -0400
Subject: [PATCH 401/435] Remove workflows add-agent flow from edit and create
 agent pages

Drop deferred-save, seed-approver, and reconciliation logic from the
approval workflow edit page, and limit AddAgentPage to Settings > Agents.

Co-authored-by: Cursor <cursoragent@cursor.com>
---
 src/pages/settings/Agents/AddAgentPage.tsx    |  26 +--
 .../WorkspaceWorkflowsApprovalsEditPage.tsx   | 170 +-----------------
 2 files changed, 10 insertions(+), 186 deletions(-)

diff --git a/src/pages/settings/Agents/AddAgentPage.tsx b/src/pages/settings/Agents/AddAgentPage.tsx
index 312c6fcd250a..a5d0762418a1 100644
--- a/src/pages/settings/Agents/AddAgentPage.tsx
+++ b/src/pages/settings/Agents/AddAgentPage.tsx
@@ -20,7 +20,7 @@ import {isMobile} from '@libs/Browser';
 import type {CustomRNImageManipulatorResult} from '@libs/cropOrRotateImage/types';
 import Navigation from '@libs/Navigation/Navigation';
 import type {PlatformStackScreenProps} from '@libs/Navigation/PlatformStackNavigation/types';
-import type {SettingsNavigatorParamList, WorkspaceSplitNavigatorParamList} from '@libs/Navigation/types';
+import type {SettingsNavigatorParamList} from '@libs/Navigation/types';
 import type {AvatarSource} from '@libs/UserAvatarUtils';
 import {createAgent} from '@userActions/Agent';
 import CONST from '@src/CONST';
@@ -31,14 +31,10 @@ import INPUT_IDS from '@src/types/form/AddAgentForm';
 import type {Errors} from '@src/types/onyx/OnyxCommon';
 import {clearPendingAvatar, getPendingAvatar, setInitialPresetID, setNavigationToken, setReturnRoute} from './pendingAgentAvatarStore';
 
-type AddAgentPageProps =
-    | PlatformStackScreenProps<SettingsNavigatorParamList, typeof SCREENS.SETTINGS.AGENTS.ADD>
-    | PlatformStackScreenProps<WorkspaceSplitNavigatorParamList, typeof SCREENS.WORKSPACE.WORKFLOWS_ADD_AGENT>;
+type AddAgentPageProps = PlatformStackScreenProps<SettingsNavigatorParamList, typeof SCREENS.SETTINGS.AGENTS.ADD>;
 
 function AddAgentPage({route}: AddAgentPageProps) {
     const policyID = route.params?.policyID;
-    const workflowApproverEmail = route.params?.workflowApproverEmail;
-    const isWorkflowSeedFlow = !!policyID && !!workflowApproverEmail;
     const {translate} = useLocalize();
     const styles = useThemeStyles();
     const {windowWidth, windowHeight} = useWindowDimensions();
@@ -77,7 +73,7 @@ function AddAgentPage({route}: AddAgentPageProps) {
     const handleAvatarPress = () => {
         setInitialPresetID(selectedPresetID ?? undefined);
         setNavigationToken();
-        setReturnRoute(isWorkflowSeedFlow ? ROUTES.WORKSPACE_WORKFLOWS_ADD_AGENT.getRoute({policyID, workflowApproverEmail}) : ROUTES.SETTINGS_AGENTS_ADD.getRoute());
+        setReturnRoute(ROUTES.SETTINGS_AGENTS_ADD.getRoute());
         Navigation.navigate(ROUTES.SETTINGS_AGENTS_ADD_AVATAR);
     };
 
@@ -97,18 +93,10 @@ function AddAgentPage({route}: AddAgentPageProps) {
         // Pure optimistic flow — no waiting on the server, online or offline. `createAgent`
         // returns the optimistic accountID it wrote into Onyx so we can hand it to the next
         // screen and let it render the agent with opacity until CREATE_AGENT resolves.
-        const {optimisticAccountID} = pendingFile
-            ? createAgent(firstName, prompt, undefined, pendingFile.file, pendingFile.uri, policyID)
-            : createAgent(firstName, prompt, selectedPresetID ?? undefined, undefined, undefined, policyID);
-
-        if (isWorkflowSeedFlow && policyID && workflowApproverEmail) {
-            // Drop the user on the Edit Approvers screen for the workflow they came from, with
-            // the optimistic agent already seeded as approver[0]. The Edit Approvers page reads
-            // the optimistic personal detail by accountID, renders it with reduced opacity
-            // (via `pendingAction`), and reconciles the email/accountID once CREATE_AGENT lands.
-            Navigation.goBack();
-            Navigation.navigate(ROUTES.WORKSPACE_WORKFLOWS_APPROVALS_EDIT.getRoute(policyID, workflowApproverEmail, undefined, Number(optimisticAccountID)));
-            return;
+        if (pendingFile) {
+            createAgent(firstName, prompt, undefined, pendingFile.file, pendingFile.uri, policyID);
+        } else {
+            createAgent(firstName, prompt, selectedPresetID ?? undefined, undefined, undefined, policyID);
         }
 
         Navigation.goBack();
diff --git a/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsEditPage.tsx b/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsEditPage.tsx
index ce7eaa4c09ae..fd0f78f5bc90 100644
--- a/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsEditPage.tsx
+++ b/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsEditPage.tsx
@@ -17,15 +17,13 @@ import {isAnyHRReadOnlyWorkflowMode} from '@libs/HRUtils';
 import Navigation from '@libs/Navigation/Navigation';
 import type {PlatformStackScreenProps} from '@libs/Navigation/PlatformStackNavigation/types';
 import type {WorkspaceSplitNavigatorParamList} from '@libs/Navigation/types';
-import {getPersonalDetailByEmail} from '@libs/PersonalDetailsUtils';
 import {canEditWorkspaceSettings, goBackFromInvalidPolicy, isControlPolicy, isPendingDeletePolicy} from '@libs/PolicyUtils';
-import {convertPolicyEmployeesToApprovalWorkflows, resolveOptimisticAgent} from '@libs/WorkflowUtils';
+import {convertPolicyEmployeesToApprovalWorkflows} from '@libs/WorkflowUtils';
 import AccessOrNotFoundWrapper from '@pages/workspace/AccessOrNotFoundWrapper';
 import withPolicyAndFullscreenLoading from '@pages/workspace/withPolicyAndFullscreenLoading';
 import type {WithPolicyAndFullscreenLoadingProps} from '@pages/workspace/withPolicyAndFullscreenLoading';
 import {
     clearApprovalWorkflow,
-    queueDeferredAgentWorkflowSave,
     removeApprovalWorkflow,
     selectApprovalWorkflowForEdit,
     setApprovalWorkflow,
@@ -35,7 +33,6 @@ import {
 import CONST from '@src/CONST';
 import ONYXKEYS from '@src/ONYXKEYS';
 import type SCREENS from '@src/SCREENS';
-import type {Approver} from '@src/types/onyx/ApprovalWorkflow';
 import type ApprovalWorkflow from '@src/types/onyx/ApprovalWorkflow';
 import {isEmptyObject} from '@src/types/utils/EmptyObject';
 import isLoadingOnyxValue from '@src/types/utils/isLoadingOnyxValue';
@@ -50,34 +47,12 @@ function WorkspaceWorkflowsApprovalsEditPage({policy, isLoadingReportData = true
     const [personalDetails] = useOnyx(ONYXKEYS.PERSONAL_DETAILS_LIST);
     const [approvalWorkflow, approvalWorkflowMetadata] = useOnyx(ONYXKEYS.APPROVAL_WORKFLOW);
     const isLoadingApprovalWorkflow = isLoadingOnyxValue(approvalWorkflowMetadata);
-    const [agentPrompts] = useOnyx(ONYXKEYS.COLLECTION.SHARED_NVP_AGENT_PROMPT);
-    const [optimisticAgentAccountIDMapping] = useOnyx(ONYXKEYS.OPTIMISTIC_AGENT_ACCOUNT_ID_MAPPING);
     const currentUserPersonalDetails = useCurrentUserPersonalDetails();
     const [initialApprovalWorkflow, setInitialApprovalWorkflow] = useState<ApprovalWorkflow | undefined>();
     const formRef = useRef<ScrollView>(null);
     const {showConfirmModal} = useConfirmModal();
     const isDeleting = useRef(false);
 
-    // Capture the pending agent's prompt the moment we see it on the optimistic record. The
-    // `SHARED_NVP_AGENT_PROMPT_<optimisticID>` entry is wiped from Onyx as part of CREATE_AGENT's
-    // successData, so once the server responds we'd lose the chance to read it. Stash it in a
-    // ref keyed by the optimistic accountID so the reconciliation effect (and the deferred-save
-    // queue) can match the resolved agent by prompt — a stable identifier that doesn't collide
-    // the way displayName does in workspaces with duplicate names.
-    const capturedPendingAgentPromptsRef = useRef<Map<number, string>>(new Map());
-    const pendingApproverAccountID = approvalWorkflow?.approvers.find((approver) => approver?.pendingAction === CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD)?.accountID;
-    const pendingAgentPromptKey = pendingApproverAccountID !== undefined ? `${ONYXKEYS.COLLECTION.SHARED_NVP_AGENT_PROMPT}${pendingApproverAccountID}` : undefined;
-    const livePendingAgentPrompt = pendingAgentPromptKey ? agentPrompts?.[pendingAgentPromptKey]?.prompt : undefined;
-    useEffect(() => {
-        if (pendingApproverAccountID === undefined || !livePendingAgentPrompt) {
-            return;
-        }
-        if (capturedPendingAgentPromptsRef.current.has(pendingApproverAccountID)) {
-            return;
-        }
-        capturedPendingAgentPromptsRef.current.set(pendingApproverAccountID, livePendingAgentPrompt);
-    }, [pendingApproverAccountID, livePendingAgentPrompt]);
-
     const updateApprovalWorkflowCallback = () => {
         if (!approvalWorkflow || !initialApprovalWorkflow) {
             return;
@@ -87,21 +62,6 @@ function WorkspaceWorkflowsApprovalsEditPage({policy, isLoadingReportData = true
             return;
         }
 
-        // If any approver is still being created (seeded from Workflows > Add agent with an
-        // optimistic accountID), defer the actual save. We can't push it to the server yet —
-        // the approver's email is empty until CREATE_AGENT resolves — but the admin shouldn't
-        // be trapped on this screen either. Stash the workflow in `DEFERRED_AGENT_WORKFLOW_SAVES`
-        // and dismiss; WorkspaceWorkflowsPage will render the workflow with the faded agent
-        // and fire the real save once the agent's email lands.
-        const pendingApprover = approvalWorkflow.approvers.find((approver) => approver?.pendingAction === CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD);
-        if (pendingApprover?.accountID !== undefined && route.params.firstApproverEmail) {
-            const pendingPromptKey = `${ONYXKEYS.COLLECTION.SHARED_NVP_AGENT_PROMPT}${pendingApprover.accountID}` as const;
-            const pendingPrompt = capturedPendingAgentPromptsRef.current.get(pendingApprover.accountID) ?? agentPrompts?.[pendingPromptKey]?.prompt ?? '';
-            queueDeferredAgentWorkflowSave(route.params.policyID, route.params.firstApproverEmail, approvalWorkflow, initialApprovalWorkflow, pendingApprover.accountID, pendingPrompt);
-            Navigation.dismissModal();
-            return;
-        }
-
         // We need to remove members and approvers that are no longer in the updated workflow
         const membersToRemove = initialApprovalWorkflow.members.filter((initialMember) => !approvalWorkflow.members.some((member) => member.email === initialMember.email));
         const approversToRemove = initialApprovalWorkflow.approvers.filter((initialApprover) => !approvalWorkflow.approvers.some((approver) => approver.email === initialApprover.email));
@@ -175,73 +135,19 @@ function WorkspaceWorkflowsApprovalsEditPage({policy, isLoadingReportData = true
             return clearApprovalWorkflow();
         }
 
-        // Resume after a sub-page round-trip: keep onyx state to avoid wiping the user's pending edits (seed params force a fresh init).
-        const hasSeedRequest = !!route.params.seedApproverEmail || !!route.params.seedApproverAccountID;
+        // Resume after a sub-page round-trip: keep onyx state to avoid wiping the user's pending edits.
         const isResumingEdit =
-            !hasSeedRequest && approvalWorkflow?.action === CONST.APPROVAL_WORKFLOW.ACTION.EDIT && approvalWorkflow?.originalApprovers?.at(0)?.email === route.params.firstApproverEmail;
+            approvalWorkflow?.action === CONST.APPROVAL_WORKFLOW.ACTION.EDIT && approvalWorkflow?.originalApprovers?.at(0)?.email === route.params.firstApproverEmail;
         if (isResumingEdit) {
             // eslint-disable-next-line react-hooks/set-state-in-effect -- one-time snapshot guarded by isResumingEdit + early return; runs at most once per mount
             setInitialApprovalWorkflow(currentApprovalWorkflow);
             return;
         }
 
-        // Seed approver[0] when opened from Workflows > Add agent (skip if already in the workflow).
-        // Two entry points are supported:
-        //   1. `seedApproverEmail` — used when the new agent already has a server-assigned login
-        //      (the original happy path: AddAgentPage used to wait for CREATE_AGENT before navigating).
-        //   2. `seedApproverAccountID` — used when AddAgentPage navigates immediately with the
-        //      optimistic accountID from `createAgent`. The optimistic personal detail has a display
-        //      name and an avatar but no `login` yet; we seed the approver anyway, mark it as
-        //      pending so the row renders with opacity, and rely on the reconciliation effect below
-        //      to upgrade it to the real email/accountID once CREATE_AGENT resolves.
-        const seedApproverEmail = route.params.seedApproverEmail;
-        const seedApproverAccountID = route.params.seedApproverAccountID ? Number(route.params.seedApproverAccountID) : undefined;
-        const hasSeedApproverEmail = seedApproverEmail !== undefined && seedApproverEmail !== '';
-        let seedPersonalDetails;
-        if (hasSeedApproverEmail) {
-            seedPersonalDetails = getPersonalDetailByEmail(seedApproverEmail);
-        } else if (seedApproverAccountID !== undefined) {
-            seedPersonalDetails = personalDetails?.[seedApproverAccountID];
-        }
-
-        // `createAgent` queues the optimistic personal detail merge and AddAgentPage navigates
-        // here on the next tick — so on the first render the optimistic detail may still be
-        // undefined. Bail out without locking `initialApprovalWorkflow` so the effect re-runs
-        // when `personalDetails` next updates; that's when we'll actually find the seed and
-        // commit the seeded workflow. Without this guard the un-seeded workflow gets committed
-        // and the seed is lost forever (the bug that just showed up in testing).
-        if (hasSeedRequest && !seedPersonalDetails) {
-            return;
-        }
-
-        let approvers: Approver[] = currentApprovalWorkflow.approvers;
-        if (seedPersonalDetails) {
-            const seededEmail = seedApproverEmail ?? seedPersonalDetails.login ?? '';
-            const seededAccountID = seedPersonalDetails.accountID ?? seedApproverAccountID;
-            const isApproverAlreadyInWorkflow = currentApprovalWorkflow.approvers.some(
-                (approver) => (!!seededEmail && approver.email === seededEmail) || (seededAccountID !== undefined && approver.accountID === seededAccountID),
-            );
-            if (!isApproverAlreadyInWorkflow) {
-                const seededApprover: Approver = {
-                    email: seededEmail,
-                    accountID: seededAccountID,
-                    displayName: seedPersonalDetails.displayName ?? seededEmail,
-                    avatar: seedPersonalDetails.avatar,
-                    approvalLimit: null,
-                    overLimitForwardsTo: '',
-                    // Mark as pending only when the personal detail is optimistic (no login yet) so
-                    // the row renders with reduced opacity while CREATE_AGENT is in flight.
-                    ...(seedPersonalDetails.isOptimisticPersonalDetail ? {pendingAction: CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD} : {}),
-                };
-                approvers = isControlPolicy(policy) ? [seededApprover, ...currentApprovalWorkflow.approvers] : [seededApprover, ...currentApprovalWorkflow.approvers.slice(1)];
-            }
-        }
-
         selectApprovalWorkflowForEdit({
             workflow: currentApprovalWorkflow,
             defaultWorkflowMembers,
             usedApproverEmails,
-            approvers,
         });
         // Snapshot for diffing on save; runs alongside selectApprovalWorkflowForEdit above.
         setInitialApprovalWorkflow(currentApprovalWorkflow);
@@ -253,81 +159,11 @@ function WorkspaceWorkflowsApprovalsEditPage({policy, isLoadingReportData = true
         policy,
         route.params.policyID,
         route.params.firstApproverEmail,
-        route.params.seedApproverEmail,
-        route.params.seedApproverAccountID,
-        personalDetails,
         approvalWorkflow?.action,
         approvalWorkflow?.originalApprovers,
         isLoadingApprovalWorkflow,
     ]);
 
-    // Reconcile a pending (optimistic) seeded approver with the real personal detail once
-    // CREATE_AGENT resolves. The optimistic personal detail is deleted in `createAgent`'s
-    // successData and a new one with a positive accountID + real login is added by the
-    // server response. The server also echoes a `{optimisticID: realID}` mapping in
-    // `OPTIMISTIC_AGENT_ACCOUNT_ID_MAPPING` — the primary resolution path — so we can look up
-    // the real accountID without guessing. Prompt matching stays as a cross-tab fallback:
-    // the mapping write only lands on the originating tab's Onyx, so a different tab still
-    // needs the prompt heuristic to reconcile (with the caveat that it's ambiguous when two
-    // agents share the same prompt text — captured in `capturedPendingAgentPromptsRef` while
-    // the optimistic entry was still live).
-    useEffect(() => {
-        if (!approvalWorkflow || !policy?.employeeList || !personalDetails || !agentPrompts) {
-            return;
-        }
-        const pendingApprover = approvalWorkflow.approvers.find((approver) => approver?.pendingAction === CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD);
-        if (!pendingApprover?.accountID) {
-            return;
-        }
-
-        const knownApproverEmails = new Set(approvalWorkflow.approvers.map((approver) => approver?.email).filter((email): email is string => !!email));
-        const resolved = resolveOptimisticAgent({
-            optimisticAccountID: pendingApprover.accountID,
-            pendingAgentPrompt: capturedPendingAgentPromptsRef.current.get(pendingApprover.accountID),
-            personalDetails,
-            employeeList: policy.employeeList,
-            agentPrompts,
-            optimisticAccountIDMapping: optimisticAgentAccountIDMapping,
-            knownApproverEmails,
-        });
-        if (!resolved) {
-            return;
-        }
-        const {personalDetail: resolvedPersonalDetail, email: resolvedEmail} = resolved;
-
-        const upgradedApprovers = approvalWorkflow.approvers.map((approver) =>
-            approver === pendingApprover
-                ? {
-                      ...approver,
-                      email: resolvedEmail,
-                      accountID: resolvedPersonalDetail.accountID,
-                      avatar: resolvedPersonalDetail.avatar ?? approver.avatar,
-                      displayName: resolvedPersonalDetail.displayName ?? approver.displayName,
-                      pendingAction: undefined,
-                  }
-                : approver,
-        );
-
-        // Mirror the deferred-save reconciliation in WorkspaceWorkflowsPage: when the new agent
-        // becomes the default approver, inject it into `members` so the subsequent save updates
-        // their `submitsTo` to point at themselves. Without this, `convertApprovalWorkflowToPolicyEmployees`
-        // never rewrites the agent's `submitsTo` (set to the previous default approver by
-        // `shareWithEmployees` in CreateAgent.cpp), leaving an orphan "Expenses from agent → previous
-        // approver" workflow card on the workflows page.
-        const upgradedMembers =
-            approvalWorkflow.isDefault && !approvalWorkflow.members.some((member) => member.email === resolvedEmail)
-                ? [
-                      ...approvalWorkflow.members,
-                      {
-                          email: resolvedEmail,
-                          displayName: resolvedPersonalDetail.displayName ?? resolvedEmail,
-                          avatar: resolvedPersonalDetail.avatar,
-                      },
-                  ]
-                : approvalWorkflow.members;
-        setApprovalWorkflow({...approvalWorkflow, approvers: upgradedApprovers, members: upgradedMembers});
-    }, [approvalWorkflow, policy?.employeeList, personalDetails, agentPrompts, optimisticAgentAccountIDMapping]);
-
     const submitButtonContainerStyles = useBottomSafeSafeAreaPaddingStyle({addBottomSafeAreaPadding: true, style: [styles.mb5, styles.mh5]});
 
     return (

From e9075021c435b3f3773f415454d75a4fc7bd3278 Mon Sep 17 00:00:00 2001
From: Puneet Lath <puneet@expensify.com>
Date: Thu, 11 Jun 2026 16:15:41 -0400
Subject: [PATCH 402/435] Remove deferred agent workflow save plumbing from
 action libs

Delete deferred-save helpers, optimistic agent reconciliation, and
workflows-only createAgent policy error handling.

Co-authored-by: Cursor <cursoragent@cursor.com>
---
 src/libs/WorkflowUtils.ts                     | 88 -------------------
 src/libs/actions/Agent.ts                     | 57 ------------
 src/libs/actions/Workflow.ts                  | 49 -----------
 .../WorkspaceWorkflowsApprovalsEditPage.tsx   |  3 +-
 4 files changed, 1 insertion(+), 196 deletions(-)

diff --git a/src/libs/WorkflowUtils.ts b/src/libs/WorkflowUtils.ts
index fe355b114ad9..8919ed7d7e7e 100644
--- a/src/libs/WorkflowUtils.ts
+++ b/src/libs/WorkflowUtils.ts
@@ -718,93 +718,6 @@ function mergeWorkflowMembersWithAvailableMembers(workflowMembers: Member[], all
     return [...workflowMembers, ...additionalMembers];
 }
 
-type ResolveOptimisticAgentParams = {
-    /** Optimistic accountID assigned to the pending agent before CREATE_AGENT resolved */
-    optimisticAccountID: number;
-
-    /** Agent prompt captured while the optimistic entry was still live; used for cross-tab fallback */
-    pendingAgentPrompt: string | undefined;
-
-    /** Live personal details map */
-    personalDetails: PersonalDetailsList;
-
-    /** The owning policy's employeeList */
-    employeeList: Policy['employeeList'];
-
-    /** SHARED_NVP_AGENT_PROMPT collection */
-    agentPrompts: OnyxCollection<AgentPrompt> | undefined;
-
-    /** `{optimisticID: realID}` map written by CREATE_AGENT's onyxData */
-    optimisticAccountIDMapping: Record<string, number> | undefined;
-
-    /** Emails already on the workflow's approver chain — skipped to avoid resolving to a pre-existing approver */
-    knownApproverEmails: Set<string>;
-};
-
-type ResolvedOptimisticAgent = {
-    personalDetail: PersonalDetails;
-    accountID: number;
-    email: string;
-};
-
-/**
- * Resolves a pending (optimistic) agent approver to its real personal detail after CREATE_AGENT
- * lands. Tries the `OPTIMISTIC_AGENT_ACCOUNT_ID_MAPPING` lookup first (the originating tab's
- * primary path), then falls back to matching by agent prompt — needed when a different tab
- * reconciles and never saw the mapping write. When several agents share the same prompt text the
- * loop picks the highest positive accountID, since the server assigns IDs monotonically and the
- * freshest agent is therefore the largest.
- */
-function resolveOptimisticAgent({
-    optimisticAccountID,
-    pendingAgentPrompt,
-    personalDetails,
-    employeeList,
-    agentPrompts,
-    optimisticAccountIDMapping,
-    knownApproverEmails,
-}: ResolveOptimisticAgentParams): ResolvedOptimisticAgent | undefined {
-    const mappedRealAccountID = optimisticAccountIDMapping?.[optimisticAccountID];
-    if (mappedRealAccountID) {
-        const mappedDetail = personalDetails[mappedRealAccountID];
-        if (mappedDetail?.login && employeeList?.[mappedDetail.login] && !knownApproverEmails.has(mappedDetail.login)) {
-            return {
-                personalDetail: mappedDetail,
-                accountID: mappedDetail.accountID ?? mappedRealAccountID,
-                email: mappedDetail.login,
-            };
-        }
-    }
-
-    if (!pendingAgentPrompt || !agentPrompts) {
-        return undefined;
-    }
-
-    const optimisticPromptKey = `${ONYXKEYS.COLLECTION.SHARED_NVP_AGENT_PROMPT}${optimisticAccountID}`;
-    let bestCandidateAccountID = -Infinity;
-    let bestCandidate: ResolvedOptimisticAgent | undefined;
-    for (const [promptKey, promptValue] of Object.entries(agentPrompts)) {
-        if (promptKey === optimisticPromptKey || !promptValue || promptValue.prompt !== pendingAgentPrompt) {
-            continue;
-        }
-        const candidateAccountID = Number(promptKey.slice(ONYXKEYS.COLLECTION.SHARED_NVP_AGENT_PROMPT.length));
-        if (!Number.isFinite(candidateAccountID) || candidateAccountID <= 0 || candidateAccountID <= bestCandidateAccountID) {
-            continue;
-        }
-        const candidateDetail = personalDetails[candidateAccountID];
-        if (!candidateDetail?.login || !employeeList?.[candidateDetail.login] || knownApproverEmails.has(candidateDetail.login)) {
-            continue;
-        }
-        bestCandidate = {
-            personalDetail: candidateDetail,
-            accountID: candidateDetail.accountID ?? candidateAccountID,
-            email: candidateDetail.login,
-        };
-        bestCandidateAccountID = candidateAccountID;
-    }
-    return bestCandidate;
-}
-
 export {
     calculateApprovers,
     convertPolicyEmployeesToApprovalWorkflows,
@@ -815,6 +728,5 @@ export {
     getOverLimitForwardsToDisplayName,
     INITIAL_APPROVAL_WORKFLOW,
     mergeWorkflowMembersWithAvailableMembers,
-    resolveOptimisticAgent,
     updateWorkflowDataOnApproverRemoval,
 };
diff --git a/src/libs/actions/Agent.ts b/src/libs/actions/Agent.ts
index 247e9c5135b3..8d00bfc446a4 100644
--- a/src/libs/actions/Agent.ts
+++ b/src/libs/actions/Agent.ts
@@ -72,11 +72,6 @@ function createAgent(
             key: `${ONYXKEYS.COLLECTION.SHARED_NVP_AGENT_PROMPT}${optimisticAccountID}`,
             value: null,
         },
-        {
-            onyxMethod: Onyx.METHOD.MERGE,
-            key: ONYXKEYS.OPTIMISTIC_AGENT_ACCOUNT_ID_MAPPING,
-            value: {[optimisticAccountID]: null},
-        },
     ];
 
     const failureData: AnyOnyxUpdate[] = [
@@ -94,45 +89,8 @@ function createAgent(
                 errors: getMicroSecondOnyxErrorWithTranslationKey('agentsPage.error.genericAdd'),
             },
         },
-        {
-            onyxMethod: Onyx.METHOD.MERGE,
-            key: ONYXKEYS.OPTIMISTIC_AGENT_ACCOUNT_ID_MAPPING,
-            value: {[optimisticAccountID]: null},
-        },
     ];
 
-    // When the agent is being created as part of a workspace flow, also mirror the
-    // pending/error state onto the policy. That way the failure surfaces as a brick road
-    // indicator on the workspace and an inline error on the Workflows page, instead of
-    // being hidden away in Settings > Agents (where the admin may never look).
-    if (policyID) {
-        const policyKey = `${ONYXKEYS.COLLECTION.POLICY}${policyID}` as const;
-        optimisticData.push({
-            onyxMethod: Onyx.METHOD.MERGE,
-            key: policyKey,
-            value: {
-                pendingFields: {[CONST.POLICY.COLLECTION_KEYS.ADD_AGENT]: CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD},
-                errorFields: {[CONST.POLICY.COLLECTION_KEYS.ADD_AGENT]: null},
-            },
-        });
-        successData.push({
-            onyxMethod: Onyx.METHOD.MERGE,
-            key: policyKey,
-            value: {
-                pendingFields: {[CONST.POLICY.COLLECTION_KEYS.ADD_AGENT]: null},
-                errorFields: {[CONST.POLICY.COLLECTION_KEYS.ADD_AGENT]: null},
-            },
-        });
-        failureData.push({
-            onyxMethod: Onyx.METHOD.MERGE,
-            key: policyKey,
-            value: {
-                pendingFields: {[CONST.POLICY.COLLECTION_KEYS.ADD_AGENT]: null},
-                errorFields: {[CONST.POLICY.COLLECTION_KEYS.ADD_AGENT]: getMicroSecondOnyxErrorWithTranslationKey('agentsPage.error.genericAdd')},
-            },
-        });
-    }
-
     write(
         WRITE_COMMANDS.CREATE_AGENT,
         {firstName, prompt, customExpensifyAvatarID, file, policyID, optimisticAccountID: String(optimisticAccountID)},
@@ -147,20 +105,6 @@ function clearAgentError(optimisticAccountID: number) {
     Onyx.set(`${ONYXKEYS.COLLECTION.SHARED_NVP_AGENT_PROMPT}${optimisticAccountID}`, null);
 }
 
-/**
- * Discard a failed optimistic agent that was seeded into an approval workflow. Wipes the
- * deferred workflow save (so the agent stops appearing as a pending approver), the optimistic
- * personal detail + prompt entry, the optimistic->real ID mapping slot, and the policy-level
- * addAgent error. Used by the RBR X click on the workflows page.
- */
-function clearPendingAgentFromApprovalWorkflow(policyID: string, firstApproverEmail: string, optimisticAccountID: number) {
-    Onyx.merge(ONYXKEYS.DEFERRED_AGENT_WORKFLOW_SAVES, {[`${policyID}:${firstApproverEmail}`]: null});
-    Onyx.merge(ONYXKEYS.PERSONAL_DETAILS_LIST, {[optimisticAccountID]: null});
-    Onyx.set(`${ONYXKEYS.COLLECTION.SHARED_NVP_AGENT_PROMPT}${optimisticAccountID}`, null);
-    Onyx.merge(ONYXKEYS.OPTIMISTIC_AGENT_ACCOUNT_ID_MAPPING, {[optimisticAccountID]: null});
-    Onyx.merge(`${ONYXKEYS.COLLECTION.POLICY}${policyID}`, {errorFields: {[CONST.POLICY.COLLECTION_KEYS.ADD_AGENT]: null}});
-}
-
 function clearAgentUpdateError(accountID: number) {
     Onyx.merge(`${ONYXKEYS.COLLECTION.SHARED_NVP_AGENT_PROMPT}${accountID}`, {errors: null, nameErrors: null, promptErrors: null, avatarErrors: null});
 }
@@ -385,7 +329,6 @@ export {
     openProfilePage,
     createAgent,
     clearAgentError,
-    clearPendingAgentFromApprovalWorkflow,
     clearAgentUpdateError,
     clearAgentNameUpdateError,
     clearAgentPromptUpdateError,
diff --git a/src/libs/actions/Workflow.ts b/src/libs/actions/Workflow.ts
index 3e3d7c598bdb..1bf80b830df2 100644
--- a/src/libs/actions/Workflow.ts
+++ b/src/libs/actions/Workflow.ts
@@ -421,52 +421,6 @@ function validateApprovalWorkflow(approvalWorkflow: ApprovalWorkflowOnyx): appro
     return isEmptyObject(errors);
 }
 
-/**
- * Build the key used to identify a deferred agent workflow save. We pin it to the policy +
- * the workflow's primary approver email so two different workflows in the same policy don't
- * stomp on each other, and so the WorkflowsPage watcher can look up the right entry when it
- * comes time to fire the real save.
- */
-function buildDeferredAgentWorkflowSaveKey(policyID: string, firstApproverEmail: string) {
-    return `${policyID}:${firstApproverEmail}`;
-}
-
-/**
- * Persist a workflow save the admin issued while a freshly-created agent was still pending.
- * The Edit Approvers modal dismisses immediately on save, the WorkspaceWorkflowsPage shows
- * the workflow with the agent rendered faded, and the watcher fires the actual save once
- * the agent's real email lands.
- */
-function queueDeferredAgentWorkflowSave(
-    policyID: string,
-    firstApproverEmail: string,
-    approvalWorkflow: ApprovalWorkflowOnyx,
-    initialApprovalWorkflow: ApprovalWorkflow,
-    pendingAgentAccountID: number,
-    pendingAgentPrompt: string,
-) {
-    const key = buildDeferredAgentWorkflowSaveKey(policyID, firstApproverEmail);
-    Onyx.merge(ONYXKEYS.DEFERRED_AGENT_WORKFLOW_SAVES, {
-        [key]: {
-            policyID,
-            firstApproverEmail,
-            approvalWorkflow,
-            initialApprovalWorkflow,
-            pendingAgentAccountID,
-            pendingAgentPrompt,
-        },
-    });
-}
-
-/**
- * Remove a deferred save entry. Called by the watcher after it has fired the actual save
- * (or when the user manually navigates back to the editor and saves with the real email).
- */
-function clearDeferredAgentWorkflowSave(policyID: string, firstApproverEmail: string) {
-    const key = buildDeferredAgentWorkflowSaveKey(policyID, firstApproverEmail);
-    Onyx.merge(ONYXKEYS.DEFERRED_AGENT_WORKFLOW_SAVES, {[key]: null});
-}
-
 export {
     createApprovalWorkflow,
     updateApprovalWorkflow,
@@ -480,7 +434,4 @@ export {
     clearApprovalWorkflow,
     validateApprovalWorkflow,
     setApprovalWorkflowIsInitialFlow,
-    buildDeferredAgentWorkflowSaveKey,
-    queueDeferredAgentWorkflowSave,
-    clearDeferredAgentWorkflowSave,
 };
diff --git a/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsEditPage.tsx b/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsEditPage.tsx
index fd0f78f5bc90..f827936c63b1 100644
--- a/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsEditPage.tsx
+++ b/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsEditPage.tsx
@@ -17,7 +17,7 @@ import {isAnyHRReadOnlyWorkflowMode} from '@libs/HRUtils';
 import Navigation from '@libs/Navigation/Navigation';
 import type {PlatformStackScreenProps} from '@libs/Navigation/PlatformStackNavigation/types';
 import type {WorkspaceSplitNavigatorParamList} from '@libs/Navigation/types';
-import {canEditWorkspaceSettings, goBackFromInvalidPolicy, isControlPolicy, isPendingDeletePolicy} from '@libs/PolicyUtils';
+import {canEditWorkspaceSettings, goBackFromInvalidPolicy, isPendingDeletePolicy} from '@libs/PolicyUtils';
 import {convertPolicyEmployeesToApprovalWorkflows} from '@libs/WorkflowUtils';
 import AccessOrNotFoundWrapper from '@pages/workspace/AccessOrNotFoundWrapper';
 import withPolicyAndFullscreenLoading from '@pages/workspace/withPolicyAndFullscreenLoading';
@@ -26,7 +26,6 @@ import {
     clearApprovalWorkflow,
     removeApprovalWorkflow,
     selectApprovalWorkflowForEdit,
-    setApprovalWorkflow,
     updateApprovalWorkflow,
     validateApprovalWorkflow,
 } from '@userActions/Workflow';

From 97635efd4444fed411c913e66f2d58d4337e17b0 Mon Sep 17 00:00:00 2001
From: Puneet Lath <puneet@expensify.com>
Date: Thu, 11 Jun 2026 16:16:30 -0400
Subject: [PATCH 403/435] Remove workflows add-agent route and seed navigation
 params

Delete WORKSPACE_WORKFLOWS_ADD_AGENT and trim seed/workflow query
params from approval edit and Settings add-agent routes.

Co-authored-by: Cursor <cursoragent@cursor.com>
---
 src/ROUTES.ts                                 | 17 +++-----------
 src/SCREENS.ts                                |  1 -
 .../ModalStackNavigators/index.tsx            |  1 -
 .../RELATIONS/WORKSPACE_TO_RHP.ts             |  1 -
 src/libs/Navigation/linkingConfig/config.ts   |  3 ---
 src/libs/Navigation/types.ts                  | 22 -------------------
 6 files changed, 3 insertions(+), 42 deletions(-)

diff --git a/src/ROUTES.ts b/src/ROUTES.ts
index aeef18968fe5..15539a1ce74a 100644
--- a/src/ROUTES.ts
+++ b/src/ROUTES.ts
@@ -1315,14 +1315,11 @@ const ROUTES = {
     SETTINGS_AGENTS: 'settings/agents',
     SETTINGS_AGENTS_ADD: {
         route: 'settings/agents/new',
-        getRoute: ({policyID, workflowApproverEmail}: {policyID?: string; workflowApproverEmail?: string} = {}) => {
+        getRoute: ({policyID}: {policyID?: string} = {}) => {
             const params = new URLSearchParams();
             if (policyID) {
                 params.set('policyID', policyID);
             }
-            if (workflowApproverEmail) {
-                params.set('workflowApproverEmail', workflowApproverEmail);
-            }
             const query = params.toString();
             return `settings/agents/new${query ? `?${query}` : ''}` as const;
         },
@@ -2315,11 +2312,8 @@ const ROUTES = {
     },
     WORKSPACE_WORKFLOWS_APPROVALS_EDIT: {
         route: 'workspaces/:policyID/workflows/approvals/:firstApproverEmail/edit',
-        getRoute: (policyID: string, firstApproverEmail: string, seedApproverEmail?: string, seedApproverAccountID?: number) =>
-            getUrlWithParams(`workspaces/${policyID}/workflows/approvals/${encodeURIComponent(firstApproverEmail)}/edit`, {
-                seedApproverEmail,
-                seedApproverAccountID: seedApproverAccountID !== undefined ? String(seedApproverAccountID) : undefined,
-            }),
+        getRoute: (policyID: string, firstApproverEmail: string) =>
+            `workspaces/${policyID}/workflows/approvals/${encodeURIComponent(firstApproverEmail)}/edit` as const,
     },
     WORKSPACE_WORKFLOWS_APPROVALS_EXPENSES_FROM: {
         route: 'workspaces/:policyID/workflows/approvals/expenses-from',
@@ -2342,11 +2336,6 @@ const ROUTES = {
         route: 'workspaces/:policyID/workflows/approvals/over-limit-approver',
         getRoute: (policyID: string, approverIndex: number) => `workspaces/${policyID}/workflows/approvals/over-limit-approver?approverIndex=${approverIndex}` as const,
     },
-    WORKSPACE_WORKFLOWS_ADD_AGENT: {
-        route: 'workspaces/:policyID/workflows/add-agent',
-        getRoute: ({policyID, workflowApproverEmail}: {policyID: string; workflowApproverEmail?: string}) =>
-            getUrlWithParams(`workspaces/${policyID}/workflows/add-agent`, {workflowApproverEmail}),
-    },
     WORKSPACE_WORKFLOWS_PAYER: {
         route: 'workspaces/:policyID/workflows/payer',
         getRoute: (policyId: string) => `workspaces/${policyId}/workflows/payer` as const,
diff --git a/src/SCREENS.ts b/src/SCREENS.ts
index 75310a8b0408..cc9c10d594ad 100644
--- a/src/SCREENS.ts
+++ b/src/SCREENS.ts
@@ -826,7 +826,6 @@ const SCREENS = {
         WORKFLOWS_APPROVALS_APPROVER_CHANGE: 'Workspace_Workflows_Approvals_Approver_Change',
         WORKFLOWS_APPROVALS_APPROVAL_LIMIT: 'Workspace_Workflows_Approvals_Approval_Limit',
         WORKFLOWS_APPROVALS_OVER_LIMIT_APPROVER: 'Workspace_Workflows_Approvals_Over_Limit_Approver',
-        WORKFLOWS_ADD_AGENT: 'Workspace_Workflows_Add_Agent',
         WORKFLOWS_AUTO_REPORTING_FREQUENCY: 'Workspace_Workflows_Auto_Reporting_Frequency',
         WORKFLOWS_AUTO_REPORTING_MONTHLY_OFFSET: 'Workspace_Workflows_Auto_Reporting_Monthly_Offset',
         DESCRIPTION: 'Workspace_Overview_Description',
diff --git a/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx b/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx
index cf78130bf3fd..668a25069717 100644
--- a/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx
+++ b/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx
@@ -576,7 +576,6 @@ const SettingsModalStackNavigator = createModalStackNavigator<SettingsNavigatorP
         require<ReactComponentModule>('../../../../pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsApprovalLimitPage').default,
     [SCREENS.WORKSPACE.WORKFLOWS_APPROVALS_OVER_LIMIT_APPROVER]: () =>
         require<ReactComponentModule>('../../../../pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsOverLimitApproverPage').default,
-    [SCREENS.WORKSPACE.WORKFLOWS_ADD_AGENT]: withAgentAccessDenied(() => require<ReactComponentModule>('../../../../pages/settings/Agents/AddAgentPage').default),
     [SCREENS.WORKSPACE.DYNAMIC_WORKSPACE_INVITE_MESSAGE]: () => require<ReactComponentModule>('../../../../pages/workspace/DynamicWorkspaceInviteMessagePage').default,
     [SCREENS.WORKSPACE.DYNAMIC_WORKSPACE_INVITE_MESSAGE_ROLE]: () => require<ReactComponentModule>('../../../../pages/workspace/DynamicWorkspaceInviteMessageRolePage').default,
     [SCREENS.WORKSPACE.INVITE_MESSAGE_APPROVER]: () => require<ReactComponentModule>('../../../../pages/workspace/WorkspaceInviteMessageApproverPage').default,
diff --git a/src/libs/Navigation/linkingConfig/RELATIONS/WORKSPACE_TO_RHP.ts b/src/libs/Navigation/linkingConfig/RELATIONS/WORKSPACE_TO_RHP.ts
index 7b125ea4c269..a4963bdf1ee4 100755
--- a/src/libs/Navigation/linkingConfig/RELATIONS/WORKSPACE_TO_RHP.ts
+++ b/src/libs/Navigation/linkingConfig/RELATIONS/WORKSPACE_TO_RHP.ts
@@ -35,7 +35,6 @@ const WORKSPACE_TO_RHP: Partial<Record<keyof WorkspaceSplitNavigatorParamList, s
         SCREENS.WORKSPACE.WORKFLOWS_APPROVALS_APPROVER_CHANGE,
         SCREENS.WORKSPACE.WORKFLOWS_APPROVALS_APPROVAL_LIMIT,
         SCREENS.WORKSPACE.WORKFLOWS_APPROVALS_OVER_LIMIT_APPROVER,
-        SCREENS.WORKSPACE.WORKFLOWS_ADD_AGENT,
         SCREENS.WORKSPACE.WORKFLOWS_AUTO_REPORTING_FREQUENCY,
         SCREENS.WORKSPACE.WORKFLOWS_AUTO_REPORTING_MONTHLY_OFFSET,
         SCREENS.WORKSPACE.WORKFLOWS_PAYER,
diff --git a/src/libs/Navigation/linkingConfig/config.ts b/src/libs/Navigation/linkingConfig/config.ts
index 80771539ee49..470bfeec483e 100644
--- a/src/libs/Navigation/linkingConfig/config.ts
+++ b/src/libs/Navigation/linkingConfig/config.ts
@@ -990,9 +990,6 @@ const config: LinkingOptions<RootNavigatorParamList>['config'] = {
                         [SCREENS.WORKSPACE.WORKFLOWS_APPROVALS_OVER_LIMIT_APPROVER]: {
                             path: ROUTES.WORKSPACE_WORKFLOWS_APPROVALS_OVER_LIMIT_APPROVER.route,
                         },
-                        [SCREENS.WORKSPACE.WORKFLOWS_ADD_AGENT]: {
-                            path: ROUTES.WORKSPACE_WORKFLOWS_ADD_AGENT.route,
-                        },
                         [SCREENS.WORKSPACE.DYNAMIC_WORKSPACE_INVITE_MESSAGE]: DYNAMIC_ROUTES.WORKSPACE_INVITE_MESSAGE.path,
                         [SCREENS.WORKSPACE.DYNAMIC_WORKSPACE_INVITE_MESSAGE_ROLE]: DYNAMIC_ROUTES.WORKSPACE_INVITE_MESSAGE_ROLE.path,
                         [SCREENS.WORKSPACE.INVITE_MESSAGE_APPROVER]: {
diff --git a/src/libs/Navigation/types.ts b/src/libs/Navigation/types.ts
index f7798fdc946b..6bd1d14f56dd 100644
--- a/src/libs/Navigation/types.ts
+++ b/src/libs/Navigation/types.ts
@@ -247,7 +247,6 @@ type SettingsNavigatorParamList = {
     [SCREENS.SETTINGS.ADD_BANK_ACCOUNT_SELECT_COUNTRY_VERIFY_ACCOUNT]: undefined;
     [SCREENS.SETTINGS.AGENTS.ADD]: {
         policyID?: string;
-        workflowApproverEmail?: string;
     };
     [SCREENS.SETTINGS.AGENTS.ADD_AVATAR]: undefined;
     [SCREENS.SETTINGS.AGENTS.EDIT]: {
@@ -2775,23 +2774,6 @@ type WorkspaceSplitNavigatorParamList = {
     [SCREENS.WORKSPACE.WORKFLOWS_APPROVALS_EDIT]: {
         policyID: string;
         firstApproverEmail: string;
-
-        /**
-         * Optional email of a person/agent to seed as approver[0] when the editor mounts. Used by
-         * the inline Add Agent flow on the Workflows page so the freshly-created agent can be
-         * dropped into the workflow without coordinating cross-page state.
-         */
-        seedApproverEmail?: string;
-
-        /**
-         * Optional optimistic accountID of an agent that was just created locally but does not
-         * have a server-assigned email yet. The Edit Approvers screen reads the personal
-         * details by accountID and seeds the workflow with whatever is there (display name,
-         * avatar, optimistic pendingAction). When the CREATE_AGENT response arrives the
-         * personal detail is upgraded with the real login, which then becomes the approver
-         * email for the workflow save.
-         */
-        seedApproverAccountID?: string;
     };
     [SCREENS.WORKSPACE.WORKFLOWS_APPROVALS_EXPENSES_FROM]: {
         policyID: string;
@@ -2814,10 +2796,6 @@ type WorkspaceSplitNavigatorParamList = {
         policyID: string;
         approverIndex: number;
     };
-    [SCREENS.WORKSPACE.WORKFLOWS_ADD_AGENT]: {
-        policyID: string;
-        workflowApproverEmail?: string;
-    };
     [SCREENS.WORKSPACE.WORKFLOWS_AUTO_REPORTING_FREQUENCY]: {
         policyID: string;
     };

From decc1fb13e2d81448c271a0dcce3a6cb0f99398c Mon Sep 17 00:00:00 2001
From: Puneet Lath <puneet@expensify.com>
Date: Thu, 11 Jun 2026 16:16:50 -0400
Subject: [PATCH 404/435] Remove workflows-only Onyx keys, CONST entries, and
 locale strings

Drop deferred agent workflow saves, workflows banner constants, and
workflowsPage agent promo copy across all locale files.

Co-authored-by: Cursor <cursoragent@cursor.com>
---
 src/CONST/index.ts                         |  5 -----
 src/ONYXKEYS.ts                            | 21 ---------------------
 src/languages/de.ts                        |  3 ---
 src/languages/en.ts                        |  3 ---
 src/languages/es.ts                        |  3 ---
 src/languages/fr.ts                        |  3 ---
 src/languages/it.ts                        |  3 ---
 src/languages/ja.ts                        |  3 ---
 src/languages/nl.ts                        |  3 ---
 src/languages/pl.ts                        |  3 ---
 src/languages/pt-BR.ts                     |  3 ---
 src/languages/zh-hans.ts                   |  3 ---
 src/types/onyx/DismissedProductTraining.ts |  5 -----
 13 files changed, 61 deletions(-)

diff --git a/src/CONST/index.ts b/src/CONST/index.ts
index d7febfb648a7..da43e3b220e8 100644
--- a/src/CONST/index.ts
+++ b/src/CONST/index.ts
@@ -4041,7 +4041,6 @@ const CONST = {
             AUTOREPORTING_FREQUENCY: 'autoReportingFrequency',
             AUTOREPORTING_OFFSET: 'autoReportingOffset',
             GENERAL_SETTINGS: 'generalSettings',
-            ADD_AGENT: 'addAgent',
         },
         EXPENSE_REPORT_RULES: {
             PREVENT_SELF_APPROVAL: 'preventSelfApproval',
@@ -7753,7 +7752,6 @@ const CONST = {
         HAS_FILTER_NEGATION: 'hasFilterNegation',
     },
     CHANGE_POLICY_TRAINING_MODAL: 'changePolicyModal',
-    AGENTS_WORKFLOWS_BANNER: 'agentsWorkflowsBanner',
     AGENTS_RULES_BANNER: 'agentsRulesBanner',
     SMART_BANNER_HEIGHT: 152,
 
@@ -7900,9 +7898,6 @@ const CONST = {
         HIGH_CONTRAST_MODE_SWITCHER: {
             TOGGLE: 'HighContrastModeSwitcher-Toggle',
         },
-        AGENTS_WORKFLOWS_BANNER: {
-            DISMISS: 'AgentsWorkflowsBanner-Dismiss',
-        },
         AGENTS_RULES_BANNER: {
             CTA: 'AgentsRulesBanner-CTA',
             DISMISS: 'AgentsRulesBanner-Dismiss',
diff --git a/src/ONYXKEYS.ts b/src/ONYXKEYS.ts
index f22984a038b1..4e8e2a3c9665 100755
--- a/src/ONYXKEYS.ts
+++ b/src/ONYXKEYS.ts
@@ -599,25 +599,6 @@ const ONYXKEYS = {
     /** Stores the information about currently edited advanced approval workflow */
     APPROVAL_WORKFLOW: 'approvalWorkflow',
 
-    /**
-     * Workflow saves the user committed while a freshly-created agent was still pending. Keyed
-     * by `${policyID}:${firstApproverEmail}`. WorkspaceWorkflowsPage overlays these entries on
-     * top of the regular workflows so the new agent shows up faded in the approver card, and
-     * a watcher fires the actual `updateApprovalWorkflow` once the agent gets its real email
-     * and clears the entry. This lets the admin "Save" before CREATE_AGENT resolves without
-     * the modal blocking on a `This field is required` validation error.
-     */
-    DEFERRED_AGENT_WORKFLOW_SAVES: 'deferredAgentWorkflowSaves',
-
-    /**
-     * Maps optimistic agent account IDs (randomly generated) to the real, server-assigned IDs returned
-     * by CREATE_AGENT. The server echoes this mapping in the response's `onyxData` (and queues
-     * it on the owner's account channel) so the WorkspaceWorkflowsPage and Edit Approvers
-     * reconciliation can swap the pending approver to the real agent without falling back to
-     * matching by prompt — which is ambiguous when multiple agents share the same prompt text.
-     */
-    OPTIMISTIC_AGENT_ACCOUNT_ID_MAPPING: 'optimisticAgentAccountIDMapping',
-
     /** Stores the user search value for persistence across the screens */
     ROOM_MEMBERS_USER_SEARCH_PHRASE: 'roomMembersUserSearchPhrase',
 
@@ -1639,8 +1620,6 @@ type OnyxValuesMapping = {
     [ONYXKEYS.NVP_PRIVATE_CANCELLATION_DETAILS]: OnyxTypes.CancellationDetails[];
     [ONYXKEYS.ROOM_MEMBERS_USER_SEARCH_PHRASE]: string;
     [ONYXKEYS.APPROVAL_WORKFLOW]: OnyxTypes.ApprovalWorkflowOnyx;
-    [ONYXKEYS.DEFERRED_AGENT_WORKFLOW_SAVES]: Record<string, OnyxTypes.DeferredAgentWorkflowSave>;
-    [ONYXKEYS.OPTIMISTIC_AGENT_ACCOUNT_ID_MAPPING]: Record<string, number>;
     [ONYXKEYS.IMPORTED_SPREADSHEET]: OnyxTypes.ImportedSpreadsheet;
     [ONYXKEYS.IMPORTED_SPREADSHEET_MEMBER_DATA]: OnyxTypes.ImportedSpreadsheetMemberData[];
     [ONYXKEYS.IMPORTED_SPREADSHEET_MEMBER_ROLE]: ValueOf<typeof CONST.POLICY.ROLE>;
diff --git a/src/languages/de.ts b/src/languages/de.ts
index 3842ab318068..48e5f1a32ea0 100644
--- a/src/languages/de.ts
+++ b/src/languages/de.ts
@@ -2604,13 +2604,10 @@ ${amount} für ${merchant} – ${date}`,
         accessibilityLabel: ({members, approvers}: {members: string; approvers: string}) => `Ausgaben von ${members} und die genehmigende Person ist ${approvers}`,
         addApprovalButton: 'Genehmigungsablauf hinzufügen',
         editWorkflowAction: 'Bearbeiten',
-        addAgentAction: 'Agent hinzufügen',
         findWorkflow: 'Workflow suchen',
         addApprovalTip: 'Dieser Standard-Workflow gilt für alle Mitglieder, sofern kein spezifischerer Workflow vorhanden ist.',
         approver: 'Genehmiger',
         addApprovalsDescription: 'Zusätzliche Genehmigung einholen, bevor eine Zahlung autorisiert wird.',
-        automateApprovalsWithAgentsTitle: 'Genehmigungen mit Agenten automatisieren',
-        automateApprovalsWithAgentsSubtitle: 'Fügen Sie die untenstehende Person zum Workflow hinzu, um Genehmigungen zu automatisieren.',
         makeOrTrackPaymentsTitle: 'Zahlungen',
         makeOrTrackPaymentsDescription:
             'Fügen Sie eine bevollmächtigte zahlende Person für in Expensify getätigte Zahlungen hinzu oder verfolgen Sie Zahlungen, die andernorts getätigt wurden.',
diff --git a/src/languages/en.ts b/src/languages/en.ts
index cdaedb280d7c..31e82260426f 100644
--- a/src/languages/en.ts
+++ b/src/languages/en.ts
@@ -2669,13 +2669,10 @@ const translations = {
         accessibilityLabel: ({members, approvers}: {members: string; approvers: string}) => `expenses from ${members}, and the approver is ${approvers}`,
         addApprovalButton: 'Add approval workflow',
         editWorkflowAction: 'Edit',
-        addAgentAction: 'Add agent',
         findWorkflow: 'Find workflow',
         addApprovalTip: 'This default workflow applies to all members, unless a more specific workflow exists.',
         approver: 'Approver',
         addApprovalsDescription: 'Require additional approval before authorizing a payment.',
-        automateApprovalsWithAgentsTitle: 'Automate approvals with agents',
-        automateApprovalsWithAgentsSubtitle: 'Add agent below to workflow to automate approvals.',
         configureViaHR: ({provider}: {provider: string}) => `Configure via ${provider}.`,
         hrApprovalWorkflowLockedPrompt: ({provider}: {provider: string}) =>
             `Approvals are managed by your ${provider} integration. To update your approval workflow, head to your ${provider} connection settings.`,
diff --git a/src/languages/es.ts b/src/languages/es.ts
index df26bc4e74fa..ffec1970a851 100644
--- a/src/languages/es.ts
+++ b/src/languages/es.ts
@@ -2478,13 +2478,10 @@ ${amount} para ${merchant} - ${date}`,
         accessibilityLabel: ({members, approvers}: {members: string; approvers: string}) => `gastos de ${members}, y el aprobador es ${approvers}`,
         addApprovalButton: 'Añadir flujo de aprobación',
         editWorkflowAction: 'Editar',
-        addAgentAction: 'Añadir agente',
         findWorkflow: 'Buscar flujo de trabajo',
         addApprovalTip: 'Este flujo de trabajo por defecto se aplica a todos los miembros, a menos que exista un flujo de trabajo más específico.',
         approver: 'Aprobador',
         addApprovalsDescription: 'Requiere una aprobación adicional antes de autorizar un pago.',
-        automateApprovalsWithAgentsTitle: 'Automatiza las aprobaciones con agentes',
-        automateApprovalsWithAgentsSubtitle: 'Añade el agente de abajo al flujo de trabajo para automatizar las aprobaciones.',
         configureViaHR: ({provider}: {provider: string}) => `Configurar mediante ${provider}.`,
         hrApprovalWorkflowLockedPrompt: ({provider}: {provider: string}) =>
             `Las aprobaciones se gestionan mediante tu integración de ${provider}. Para actualizar tu flujo de aprobación, ve a la configuración de conexión de ${provider}.`,
diff --git a/src/languages/fr.ts b/src/languages/fr.ts
index 7345b28425a2..a9d5ab602acf 100644
--- a/src/languages/fr.ts
+++ b/src/languages/fr.ts
@@ -2611,13 +2611,10 @@ ${amount} pour ${merchant} - ${date}`,
         accessibilityLabel: ({members, approvers}: {members: string; approvers: string}) => `dépenses de ${members}, et l'approbateur est ${approvers}`,
         addApprovalButton: 'Ajouter un workflow d’approbation',
         editWorkflowAction: 'Modifier',
-        addAgentAction: 'Ajouter un agent',
         findWorkflow: 'Rechercher un flux de travail',
         addApprovalTip: 'Ce workflow par défaut s’applique à tous les membres, sauf si un workflow plus spécifique existe.',
         approver: 'Approbateur',
         addApprovalsDescription: 'Exiger une approbation supplémentaire avant d’autoriser un paiement.',
-        automateApprovalsWithAgentsTitle: 'Automatisez les approbations avec des agents',
-        automateApprovalsWithAgentsSubtitle: 'Ajoutez l’agent ci-dessous au flux de travail pour automatiser les approbations.',
         makeOrTrackPaymentsTitle: 'Paiements',
         makeOrTrackPaymentsDescription: 'Ajoutez un payeur autorisé pour les paiements effectués dans Expensify ou suivez les paiements effectués ailleurs.',
         customApprovalWorkflowEnabled:
diff --git a/src/languages/it.ts b/src/languages/it.ts
index 7d0c2968c26e..44b917f81f1e 100644
--- a/src/languages/it.ts
+++ b/src/languages/it.ts
@@ -2600,13 +2600,10 @@ ${amount} per ${merchant} - ${date}`,
         accessibilityLabel: ({members, approvers}: {members: string; approvers: string}) => `spese di ${members} e l'approvatore è ${approvers}`,
         addApprovalButton: 'Aggiungi flusso di approvazione',
         editWorkflowAction: 'Modifica',
-        addAgentAction: 'Aggiungi agente',
         findWorkflow: 'Cerca flusso di lavoro',
         addApprovalTip: 'Questo flusso di lavoro predefinito si applica a tutti i membri, a meno che non esista un flusso di lavoro più specifico.',
         approver: 'Approvante',
         addApprovalsDescription: 'Richiedi un’approvazione aggiuntiva prima di autorizzare un pagamento.',
-        automateApprovalsWithAgentsTitle: 'Automatizza le approvazioni con gli agenti',
-        automateApprovalsWithAgentsSubtitle: 'Aggiungi l’agente qui sotto al workflow per automatizzare le approvazioni.',
         makeOrTrackPaymentsTitle: 'Pagamenti',
         makeOrTrackPaymentsDescription: 'Aggiungi un pagatore autorizzato per i pagamenti effettuati in Expensify o tieni traccia dei pagamenti effettuati altrove.',
         customApprovalWorkflowEnabled:
diff --git a/src/languages/ja.ts b/src/languages/ja.ts
index fe90c3318706..4ad4863a9bd7 100644
--- a/src/languages/ja.ts
+++ b/src/languages/ja.ts
@@ -2577,13 +2577,10 @@ ${date} の ${merchant} への ${amount}`,
         accessibilityLabel: ({members, approvers}: {members: string; approvers: string}) => `${members} の経費で、承認者は ${approvers} です`,
         addApprovalButton: '承認ワークフローを追加',
         editWorkflowAction: '編集',
-        addAgentAction: 'エージェントを追加',
         findWorkflow: 'ワークフローを検索',
         addApprovalTip: 'より詳細なワークフローが存在する場合を除き、このデフォルトのワークフローがすべてのメンバーに適用されます。',
         approver: '承認者',
         addApprovalsDescription: '支払いを承認する前に、追加の承認を必須にする。',
-        automateApprovalsWithAgentsTitle: '代理を使って承認を自動化する',
-        automateApprovalsWithAgentsSubtitle: '承認を自動化するには、以下のエージェントをワークフローに追加してください。',
         makeOrTrackPaymentsTitle: '支払',
         makeOrTrackPaymentsDescription: 'Expensifyでの支払いに対する承認済み支払者を追加するか、他の場所で行われた支払いを記録します。',
         customApprovalWorkflowEnabled:
diff --git a/src/languages/nl.ts b/src/languages/nl.ts
index 2092e64ccc2e..ff0ec697ccf3 100644
--- a/src/languages/nl.ts
+++ b/src/languages/nl.ts
@@ -2597,13 +2597,10 @@ ${amount} voor ${merchant} - ${date}`,
         accessibilityLabel: ({members, approvers}: {members: string; approvers: string}) => `de uitgaven van ${members}, en de goedkeurder is ${approvers}`,
         addApprovalButton: 'Goedkeuringsworkflow toevoegen',
         editWorkflowAction: 'Bewerken',
-        addAgentAction: 'Agent toevoegen',
         findWorkflow: 'Workflow zoeken',
         addApprovalTip: 'Deze standaardworkflow is van toepassing op alle leden, tenzij er een specifiekere workflow bestaat.',
         approver: 'Fiatteur',
         addApprovalsDescription: 'Extra goedkeuring vereisen voordat je een betaling autoriseert.',
-        automateApprovalsWithAgentsTitle: 'Automatiseer goedkeuringen met agents',
-        automateApprovalsWithAgentsSubtitle: 'Voeg hieronder een agent toe aan de workflow om goedkeuringen te automatiseren.',
         makeOrTrackPaymentsTitle: 'Betalingen',
         makeOrTrackPaymentsDescription: 'Voeg een gemachtigde betaler toe voor betalingen die in Expensify worden gedaan of volg betalingen die elders zijn gedaan.',
         customApprovalWorkflowEnabled:
diff --git a/src/languages/pl.ts b/src/languages/pl.ts
index df8984d69bd9..e7ff84969943 100644
--- a/src/languages/pl.ts
+++ b/src/languages/pl.ts
@@ -2593,13 +2593,10 @@ ${amount} dla ${merchant} - ${date}`,
         accessibilityLabel: ({members, approvers}: {members: string; approvers: string}) => `wydatki od ${members}, a zatwierdzającym jest ${approvers}`,
         addApprovalButton: 'Dodaj proces akceptacji',
         editWorkflowAction: 'Edytuj',
-        addAgentAction: 'Dodaj agenta',
         findWorkflow: 'Znajdź przepływ pracy',
         addApprovalTip: 'Domyślny proces pracy ma zastosowanie do wszystkich członków, chyba że istnieje bardziej szczegółowy proces pracy.',
         approver: 'Osoba zatwierdzająca',
         addApprovalsDescription: 'Wymagaj dodatkowej akceptacji przed autoryzacją płatności.',
-        automateApprovalsWithAgentsTitle: 'Automatyzuj zatwierdzanie z agentami',
-        automateApprovalsWithAgentsSubtitle: 'Dodaj agenta poniżej do przepływu pracy, aby zautomatyzować zatwierdzanie.',
         makeOrTrackPaymentsTitle: 'Płatności',
         makeOrTrackPaymentsDescription: 'Dodaj upoważnionego płatnika dla płatności dokonywanych w Expensify lub śledź płatności wykonywane gdzie indziej.',
         customApprovalWorkflowEnabled:
diff --git a/src/languages/pt-BR.ts b/src/languages/pt-BR.ts
index e643b89d4412..f70bf32ba38c 100644
--- a/src/languages/pt-BR.ts
+++ b/src/languages/pt-BR.ts
@@ -2591,13 +2591,10 @@ ${amount} para ${merchant} - ${date}`,
         accessibilityLabel: ({members, approvers}: {members: string; approvers: string}) => `despesas de ${members}, e o aprovador é ${approvers}`,
         addApprovalButton: 'Adicionar fluxo de aprovação',
         editWorkflowAction: 'Editar',
-        addAgentAction: 'Adicionar agente',
         findWorkflow: 'Buscar fluxo de trabalho',
         addApprovalTip: 'Este fluxo de trabalho padrão se aplica a todos os membros, a menos que exista um fluxo de trabalho mais específico.',
         approver: 'Aprovador',
         addApprovalsDescription: 'Exigir aprovação adicional antes de autorizar um pagamento.',
-        automateApprovalsWithAgentsTitle: 'Automatize aprovações com agentes',
-        automateApprovalsWithAgentsSubtitle: 'Adicione o agente abaixo ao fluxo de trabalho para automatizar as aprovações.',
         makeOrTrackPaymentsTitle: 'Pagamentos',
         makeOrTrackPaymentsDescription: 'Adicione um pagador autorizado para pagamentos feitos no Expensify ou acompanhe pagamentos feitos em outros lugares.',
         customApprovalWorkflowEnabled:
diff --git a/src/languages/zh-hans.ts b/src/languages/zh-hans.ts
index 4a648115fd4a..69688d7585cd 100644
--- a/src/languages/zh-hans.ts
+++ b/src/languages/zh-hans.ts
@@ -2526,13 +2526,10 @@ ${amount}，商户：${merchant} - 日期：${date}`,
         accessibilityLabel: ({members, approvers}: {members: string; approvers: string}) => `来自${members}的报销，审批人是${approvers}`,
         addApprovalButton: '添加审批工作流',
         editWorkflowAction: '编辑',
-        addAgentAction: '添加代理',
         findWorkflow: '查找工作流',
         addApprovalTip: '除非存在更具体的工作流程，否则此默认工作流程适用于所有成员。',
         approver: '审批人',
         addApprovalsDescription: '在付款前需要额外审批。',
-        automateApprovalsWithAgentsTitle: '使用代理自动化审批',
-        automateApprovalsWithAgentsSubtitle: '在下方添加代理到工作流程中以自动化审批。',
         makeOrTrackPaymentsTitle: '付款',
         makeOrTrackPaymentsDescription: '为在 Expensify 中进行的付款添加授权付款人，或跟踪在其他地方进行的付款。',
         customApprovalWorkflowEnabled:
diff --git a/src/types/onyx/DismissedProductTraining.ts b/src/types/onyx/DismissedProductTraining.ts
index 1a186f0534c1..640d97ccc883 100644
--- a/src/types/onyx/DismissedProductTraining.ts
+++ b/src/types/onyx/DismissedProductTraining.ts
@@ -59,11 +59,6 @@ type DismissedProductTraining = {
      */
     [CONST.CHANGE_POLICY_TRAINING_MODAL]: DismissedProductTrainingElement;
 
-    /**
-     * When user dismisses the agents workflows promo banner, we store the timestamp here.
-     */
-    [CONST.AGENTS_WORKFLOWS_BANNER]: DismissedProductTrainingElement;
-
     /**
      * When user dismisses the agents rules promo banner, we store the timestamp here.
      */

From 324e73e8ee0a885bef3301e049db42b4d2596acf Mon Sep 17 00:00:00 2001
From: Puneet Lath <puneet@expensify.com>
Date: Thu, 11 Jun 2026 16:17:16 -0400
Subject: [PATCH 405/435] Update tests after removing workflows agent
 integration

Remove Add-agent and workflows-banner test cases and align agent action
tests with the simplified createAgent flow.

Co-authored-by: Cursor <cursoragent@cursor.com>
---
 .../workflows/WorkspaceWorkflowsPage.tsx      |  1 -
 tests/ui/AgentsPromoBannersTest.tsx           | 58 +------------------
 tests/unit/AgentActionTest.ts                 | 32 ----------
 tests/unit/ApprovalWorkflowSectionTest.tsx    | 50 +---------------
 .../unit/pages/settings/AddAgentPageTest.tsx  | 12 +---
 5 files changed, 7 insertions(+), 146 deletions(-)

diff --git a/src/pages/workspace/workflows/WorkspaceWorkflowsPage.tsx b/src/pages/workspace/workflows/WorkspaceWorkflowsPage.tsx
index b496201f7bb6..4b7a025ee9bf 100644
--- a/src/pages/workspace/workflows/WorkspaceWorkflowsPage.tsx
+++ b/src/pages/workspace/workflows/WorkspaceWorkflowsPage.tsx
@@ -3,7 +3,6 @@ import {Str} from 'expensify-common';
 import React, {useCallback, useEffect, useMemo} from 'react';
 // eslint-disable-next-line no-restricted-imports
 import {InteractionManager, View} from 'react-native';
-import type {OnyxEntry} from 'react-native-onyx';
 import type {TupleToUnion} from 'type-fest';
 import ApprovalWorkflowSection from '@components/ApprovalWorkflowSection';
 import Icon from '@components/Icon';
diff --git a/tests/ui/AgentsPromoBannersTest.tsx b/tests/ui/AgentsPromoBannersTest.tsx
index fda49af792dd..fcf2531e33a5 100644
--- a/tests/ui/AgentsPromoBannersTest.tsx
+++ b/tests/ui/AgentsPromoBannersTest.tsx
@@ -5,7 +5,6 @@ import ComposeProviders from '@components/ComposeProviders';
 import {LocaleContextProvider} from '@components/LocaleContextProvider';
 import OnyxListItemProvider from '@components/OnyxListItemProvider';
 import PolicyRulesPage from '@pages/workspace/rules/PolicyRulesPage';
-import WorkspaceWorkflowsPage from '@pages/workspace/workflows/WorkspaceWorkflowsPage';
 import CONST from '@src/CONST';
 import en from '@src/languages/en';
 import ONYXKEYS from '@src/ONYXKEYS';
@@ -38,16 +37,6 @@ jest.mock('@libs/Navigation/Navigation', () => ({
     setNavigationActionToMicrotaskQueue: (cb: () => void) => cb(),
 }));
 
-jest.mock('@libs/actions/Policy/Policy', () => {
-    // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
-    const actual = jest.requireActual('@libs/actions/Policy/Policy');
-    // eslint-disable-next-line @typescript-eslint/no-unsafe-return
-    return {
-        ...actual,
-        openPolicyWorkflowsPage: jest.fn(),
-    };
-});
-
 jest.mock('@libs/actions/Policy/Rules', () => {
     // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
     const actual = jest.requireActual('@libs/actions/Policy/Rules');
@@ -58,10 +47,6 @@ jest.mock('@libs/actions/Policy/Rules', () => {
     };
 });
 
-jest.mock('@userActions/PaymentMethods', () => ({
-    getPaymentMethods: jest.fn(),
-}));
-
 jest.mock('@components/RenderHTML', () => {
     const ReactMock = require('react') as typeof React;
 
@@ -99,26 +84,12 @@ function buildPolicy(): Policy {
     } as Policy;
 }
 
-const workflowsRoute = {
-    key: 'workflows-route',
-    name: SCREENS.WORKSPACE.WORKFLOWS,
-    params: {policyID: POLICY_ID},
-} as never;
-
 const rulesRoute = {
     key: 'rules-route',
     name: SCREENS.WORKSPACE.RULES,
     params: {policyID: POLICY_ID},
 } as never;
 
-const renderWorkflowsPage = () =>
-    render(
-        <ComposeProviders components={[OnyxListItemProvider, LocaleContextProvider]}>
-            {/* @ts-expect-error - navigation prop is not used by the page in tests */}
-            <WorkspaceWorkflowsPage route={workflowsRoute} />
-        </ComposeProviders>,
-    );
-
 const renderRulesPage = () =>
     render(
         <ComposeProviders components={[OnyxListItemProvider, LocaleContextProvider]}>
@@ -154,28 +125,6 @@ describe('Agents promo banners', () => {
         });
     });
 
-    it('renders agentsWorkflowsBanner inside Approvals subMenuItems when customAgent beta is active, and hides it after dismissal', async () => {
-        await act(async () => {
-            await setupOnyxBaseline({withCustomAgentBeta: true});
-            await waitForBatchedUpdatesWithAct();
-        });
-
-        renderWorkflowsPage();
-        await waitForBatchedUpdatesWithAct();
-
-        // Title includes a nested "New" badge, so match on subtitle instead of the full title string.
-        expect(screen.getByText(en.workflowsPage.automateApprovalsWithAgentsSubtitle)).toBeTruthy();
-
-        await act(async () => {
-            await Onyx.merge(ONYXKEYS.NVP_DISMISSED_PRODUCT_TRAINING, {
-                [CONST.AGENTS_WORKFLOWS_BANNER]: {timestamp: '2026-05-20', dismissedMethod: 'x'},
-            });
-            await waitForBatchedUpdatesWithAct();
-        });
-
-        expect(screen.queryByText(en.workflowsPage.automateApprovalsWithAgentsSubtitle)).toBeNull();
-    });
-
     it('renders agentsRulesBanner above IndividualExpenseRulesSection when customAgent beta is active, and hides it after dismissal', async () => {
         await act(async () => {
             await setupOnyxBaseline({withCustomAgentBeta: true});
@@ -200,17 +149,12 @@ describe('Agents promo banners', () => {
         expect(screen.queryByText(en.workspace.rules.agentsPromoBanner.subtitle)).toBeNull();
     });
 
-    it('renders neither banner when customAgent beta is inactive', async () => {
+    it('does not render the agents rules banner when customAgent beta is inactive', async () => {
         await act(async () => {
             await setupOnyxBaseline({withCustomAgentBeta: false});
             await waitForBatchedUpdatesWithAct();
         });
 
-        const {unmount} = renderWorkflowsPage();
-        await waitForBatchedUpdatesWithAct();
-        expect(screen.queryByText(en.workflowsPage.automateApprovalsWithAgentsSubtitle)).toBeNull();
-        unmount();
-
         renderRulesPage();
         await waitForBatchedUpdatesWithAct();
         expect(screen.queryByText(en.workspace.rules.agentsPromoBanner.subtitle)).toBeNull();
diff --git a/tests/unit/AgentActionTest.ts b/tests/unit/AgentActionTest.ts
index 6b5c0847442d..051fc71dd932 100644
--- a/tests/unit/AgentActionTest.ts
+++ b/tests/unit/AgentActionTest.ts
@@ -178,26 +178,6 @@ describe('createAgent', () => {
         expect(result.avatarURI).toBeTruthy();
     });
 
-    it('mirrors pending/error state onto the policy so the workspace shows a brick road indicator', () => {
-        createAgent('Bot', 'My prompt', undefined, undefined, undefined, 'POLICY_42');
-
-        const {optimisticData, successData, failureData} = getWriteOptions();
-        const policyKey = `${ONYXKEYS.COLLECTION.POLICY}POLICY_42`;
-        const addAgentKey = CONST.POLICY.COLLECTION_KEYS.ADD_AGENT;
-
-        const optimisticPolicy = optimisticData.find((u) => u.key === policyKey);
-        expect((optimisticPolicy?.value as Record<string, Record<string, unknown>>)?.pendingFields?.[addAgentKey]).toBe(CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD);
-        expect((optimisticPolicy?.value as Record<string, Record<string, unknown>>)?.errorFields?.[addAgentKey]).toBeNull();
-
-        const successPolicy = successData.find((u) => u.key === policyKey);
-        expect((successPolicy?.value as Record<string, Record<string, unknown>>)?.pendingFields?.[addAgentKey]).toBeNull();
-        expect((successPolicy?.value as Record<string, Record<string, unknown>>)?.errorFields?.[addAgentKey]).toBeNull();
-
-        const failurePolicy = failureData.find((u) => u.key === policyKey);
-        expect((failurePolicy?.value as Record<string, Record<string, unknown>>)?.pendingFields?.[addAgentKey]).toBeNull();
-        expect((failurePolicy?.value as Record<string, Record<string, unknown>>)?.errorFields?.[addAgentKey]).toBeTruthy();
-    });
-
     it('does not touch the policy when no policyID is provided', () => {
         createAgent('Bot', 'My prompt');
 
@@ -247,18 +227,6 @@ describe('createAgent', () => {
         expect(mockWrite).toHaveBeenCalledWith(WRITE_COMMANDS.CREATE_AGENT, expect.objectContaining({optimisticAccountID: String(result.optimisticAccountID)}), expect.any(Object));
     });
 
-    it('success and failure data clear the optimistic→real ID mapping entry', () => {
-        const result = createAgent('Bot', 'My prompt');
-        const {successData, failureData} = getWriteOptions();
-        const optID = String(result.optimisticAccountID);
-
-        const successMappingUpdate = successData.find((u) => u.key === ONYXKEYS.OPTIMISTIC_AGENT_ACCOUNT_ID_MAPPING);
-        const failureMappingUpdate = failureData.find((u) => u.key === ONYXKEYS.OPTIMISTIC_AGENT_ACCOUNT_ID_MAPPING);
-
-        expect((successMappingUpdate?.value as Record<string, unknown>)[optID]).toBeNull();
-        expect((failureMappingUpdate?.value as Record<string, unknown>)[optID]).toBeNull();
-    });
-
     it('failure data preserves optimistic personal detail and merges errors onto the prompt entry', () => {
         createAgent('Bot', 'My prompt');
 
diff --git a/tests/unit/ApprovalWorkflowSectionTest.tsx b/tests/unit/ApprovalWorkflowSectionTest.tsx
index 109c6ee95534..d13ea570de11 100644
--- a/tests/unit/ApprovalWorkflowSectionTest.tsx
+++ b/tests/unit/ApprovalWorkflowSectionTest.tsx
@@ -4,14 +4,10 @@ import ApprovalWorkflowSection from '@components/ApprovalWorkflowSection';
 import OnyxListItemProvider from '@components/OnyxListItemProvider';
 import type ApprovalWorkflow from '@src/types/onyx/ApprovalWorkflow';
 
-let mockIsCustomAgentBetaEnabled = false;
-
 function mockTranslate(key: string): string {
     switch (key) {
         case 'workflowsPage.editWorkflowAction':
             return 'Edit';
-        case 'workflowsPage.addAgentAction':
-            return 'Add agent';
         case 'workflowsPage.approver':
             return 'Approver';
         case 'workflowsPage.addApprovalTip':
@@ -35,13 +31,6 @@ jest.mock('@hooks/useLocalize', () =>
     })),
 );
 
-jest.mock('@hooks/usePermissions', () => ({
-    __esModule: true,
-    default: () => ({
-        isBetaEnabled: () => mockIsCustomAgentBetaEnabled,
-    }),
-}));
-
 const baseWorkflow: ApprovalWorkflow = {
     isDefault: false,
     members: [
@@ -68,13 +57,12 @@ function renderSection(props: React.ComponentProps<typeof ApprovalWorkflowSectio
 
 describe('ApprovalWorkflowSection', () => {
     afterEach(() => {
-        mockIsCustomAgentBetaEnabled = false;
         jest.clearAllMocks();
     });
 
     it('renders the Edit pill that triggers the onPress handler', () => {
         const onPress = jest.fn();
-        renderSection({approvalWorkflow: baseWorkflow, onPress, onAddAgentPress: jest.fn(), canAddAgent: true});
+        renderSection({approvalWorkflow: baseWorkflow, onPress});
 
         const editButton = screen.getByLabelText('Edit');
         expect(editButton).toBeTruthy();
@@ -82,41 +70,9 @@ describe('ApprovalWorkflowSection', () => {
         expect(onPress).toHaveBeenCalledTimes(1);
     });
 
-    it('does not show the Add agent pill when the customAgent beta is disabled', () => {
-        mockIsCustomAgentBetaEnabled = false;
-        renderSection({approvalWorkflow: baseWorkflow, onPress: jest.fn(), onAddAgentPress: jest.fn(), canAddAgent: true});
-
-        expect(screen.queryByLabelText('Add agent')).toBeNull();
-    });
-
-    it('shows the Add agent pill when the customAgent beta is enabled and the caller allows it', () => {
-        mockIsCustomAgentBetaEnabled = true;
-        renderSection({approvalWorkflow: baseWorkflow, onPress: jest.fn(), onAddAgentPress: jest.fn(), canAddAgent: true});
-
-        expect(screen.getByLabelText('Add agent')).toBeTruthy();
-    });
-
-    it('does not show the Add agent pill when canAddAgent is false even if the beta is on', () => {
-        mockIsCustomAgentBetaEnabled = true;
-        renderSection({approvalWorkflow: baseWorkflow, onPress: jest.fn(), onAddAgentPress: jest.fn(), canAddAgent: false});
-
-        expect(screen.queryByLabelText('Add agent')).toBeNull();
-    });
-
-    it('invokes onAddAgentPress when the Add agent pill is pressed', () => {
-        mockIsCustomAgentBetaEnabled = true;
-        const onAddAgentPress = jest.fn();
-        renderSection({approvalWorkflow: baseWorkflow, onPress: jest.fn(), onAddAgentPress, canAddAgent: true});
-
-        fireEvent.press(screen.getByLabelText('Add agent'));
-        expect(onAddAgentPress).toHaveBeenCalledTimes(1);
-    });
-
-    it('hides both pill actions when the section is disabled (no-op for read-only workflows)', () => {
-        mockIsCustomAgentBetaEnabled = true;
-        renderSection({approvalWorkflow: baseWorkflow, onPress: jest.fn(), onAddAgentPress: jest.fn(), canAddAgent: true, isDisabled: true});
+    it('hides the Edit pill when the section is disabled (no-op for read-only workflows)', () => {
+        renderSection({approvalWorkflow: baseWorkflow, onPress: jest.fn(), isDisabled: true});
 
         expect(screen.queryByLabelText('Edit')).toBeNull();
-        expect(screen.queryByLabelText('Add agent')).toBeNull();
     });
 });
diff --git a/tests/unit/pages/settings/AddAgentPageTest.tsx b/tests/unit/pages/settings/AddAgentPageTest.tsx
index 976a43f88352..287e135d72e6 100644
--- a/tests/unit/pages/settings/AddAgentPageTest.tsx
+++ b/tests/unit/pages/settings/AddAgentPageTest.tsx
@@ -244,15 +244,10 @@ describe('AddAgentPage', () => {
             expect(mockNavigate).not.toHaveBeenCalled();
         });
 
-        it('navigates to Edit Approval Workflow with the optimistic accountID seed when policyID + workflowApproverEmail are set', () => {
-            // The Edit page seeds approver[0] from the optimistic personal detail keyed by the
-            // optimistic accountID, so we can hop directly to the editor without waiting for
-            // CREATE_AGENT to resolve. The server-echoed `optimisticAgentAccountIDMapping`
-            // (and a prompt-match fallback) reconciles the seed to the real email once the
-            // response lands.
+        it('goes back when policyID is present without navigating to a workflow editor', () => {
             render(
                 <AddAgentPage
-                    route={makeRoute({policyID: 'POL_42', workflowApproverEmail: 'manager@example.com'})}
+                    route={makeRoute({policyID: 'POL_42'})}
                     navigation={undefined as never}
                 />,
             );
@@ -260,8 +255,7 @@ describe('AddAgentPage', () => {
             mockFormOnSubmit?.({firstName: 'Bot', prompt: 'Reject gambling.'});
 
             expect(mockGoBack).toHaveBeenCalledTimes(1);
-            expect(mockNavigate).toHaveBeenCalledWith(expect.stringContaining('workspaces/POL_42/workflows/approvals/manager%40example.com/edit'));
-            expect(mockNavigate).toHaveBeenCalledWith(expect.stringContaining('seedApproverAccountID=-123456'));
+            expect(mockNavigate).not.toHaveBeenCalled();
         });
     });
 });

From 6ffcaab77b3915391120fb77573f23b0b440922e Mon Sep 17 00:00:00 2001
From: Puneet Lath <puneet@expensify.com>
Date: Thu, 11 Jun 2026 16:32:59 -0400
Subject: [PATCH 406/435] Fix Prettier and React Compiler compliance for
 workflows page

Apply prettier formatting and memoize approval workflow conversion so
availableMembers and usedApproverEmails stay stable for useCallback.

Co-authored-by: Cursor <cursoragent@cursor.com>
---
 src/ROUTES.ts                                 |  3 +-
 .../workflows/WorkspaceWorkflowsPage.tsx      | 98 ++++++++++---------
 .../WorkspaceWorkflowsApprovalsEditPage.tsx   | 11 +--
 3 files changed, 54 insertions(+), 58 deletions(-)

diff --git a/src/ROUTES.ts b/src/ROUTES.ts
index 15539a1ce74a..03d6054d2a70 100644
--- a/src/ROUTES.ts
+++ b/src/ROUTES.ts
@@ -2312,8 +2312,7 @@ const ROUTES = {
     },
     WORKSPACE_WORKFLOWS_APPROVALS_EDIT: {
         route: 'workspaces/:policyID/workflows/approvals/:firstApproverEmail/edit',
-        getRoute: (policyID: string, firstApproverEmail: string) =>
-            `workspaces/${policyID}/workflows/approvals/${encodeURIComponent(firstApproverEmail)}/edit` as const,
+        getRoute: (policyID: string, firstApproverEmail: string) => `workspaces/${policyID}/workflows/approvals/${encodeURIComponent(firstApproverEmail)}/edit` as const,
     },
     WORKSPACE_WORKFLOWS_APPROVALS_EXPENSES_FROM: {
         route: 'workspaces/:policyID/workflows/approvals/expenses-from',
diff --git a/src/pages/workspace/workflows/WorkspaceWorkflowsPage.tsx b/src/pages/workspace/workflows/WorkspaceWorkflowsPage.tsx
index 4b7a025ee9bf..7993669516d2 100644
--- a/src/pages/workspace/workflows/WorkspaceWorkflowsPage.tsx
+++ b/src/pages/workspace/workflows/WorkspaceWorkflowsPage.tsx
@@ -139,16 +139,16 @@ function WorkspaceWorkflowsPage({policy, route}: WorkspaceWorkflowsPageProps) {
     const delegateAccountID = useDelegateAccountID();
     const {accountID: currentUserAccountID, email: currentUserEmail = '', login: currentUserLogin = ''} = useCurrentUserPersonalDetails();
     const isUserReimburser = policy?.achAccount?.reimburser !== undefined && account?.primaryLogin !== undefined && policy?.achAccount?.reimburser === account?.primaryLogin;
-    const {
-        approvalWorkflows,
-        availableMembers,
-        usedApproverEmails,
-    } = convertPolicyEmployeesToApprovalWorkflows({
-        policy,
-        personalDetails: personalDetails ?? {},
-        localeCompare,
-        currentUserLogin,
-    });
+    const {approvalWorkflows, availableMembers, usedApproverEmails} = useMemo(
+        () =>
+            convertPolicyEmployeesToApprovalWorkflows({
+                policy,
+                personalDetails: personalDetails ?? {},
+                localeCompare,
+                currentUserLogin,
+            }),
+        [policy, personalDetails, localeCompare, currentUserLogin],
+    );
 
     const canAccessSubmit2026Features = canAccessSubmitWorkspaceFeatures(policy, isSubmit2026BetaEnabled);
     const hasValidExistingAccounts = getEligibleExistingBusinessBankAccounts(bankAccountList, policy?.outputCurrency, true).length > 0;
@@ -473,43 +473,47 @@ function WorkspaceWorkflowsPage({policy, route}: WorkspaceWorkflowsPageProps) {
                             shouldShow={searchFilteredWorkflows.length === 0 && workflowSearchInput.length > 0}
                             searchValue={workflowSearchInput}
                         />
-                        {searchFilteredWorkflows.map((workflow) => (
-                            <OfflineWithFeedback
-                                key={workflow.approvers.at(0)?.email ?? ''}
-                                pendingAction={workflow.pendingAction}
-                            >
-                                <ApprovalWorkflowSection
-                                    approvalWorkflow={workflow}
-                                    onPress={
-                                        shouldBlockApprovalWorkflowEditing || !canWriteApprovals
-                                            ? undefined
-                                            : () => {
-                                                  // Discard stale onyx edits or the Edit page's resume check would surface a prior abandoned session.
-                                                  clearApprovalWorkflow();
-                                                  Navigation.navigate(ROUTES.WORKSPACE_WORKFLOWS_APPROVALS_EDIT.getRoute(route.params.policyID, workflow.approvers.at(0)?.email ?? ''));
-                                              }
-                                    }
-                                    onShowAllMembersPress={
-                                        shouldBlockApprovalWorkflowEditing
-                                            ? undefined
-                                            : () => {
-                                                  selectApprovalWorkflowForEdit({workflow, defaultWorkflowMembers: availableMembers, usedApproverEmails});
-                                                  Navigation.navigate(
-                                                      ROUTES.WORKSPACE_WORKFLOWS_APPROVALS_EXPENSES_FROM.getRoute(
-                                                          route.params.policyID,
-                                                          ROUTES.WORKSPACE_WORKFLOWS.getRoute(route.params.policyID),
-                                                      ),
-                                                  );
-                                              }
-                                    }
-                                    currency={policy?.outputCurrency}
-                                    isDisabled={shouldBlockApprovalWorkflowEditing || !canWriteApprovals}
-                                    hrProviderName={isHRConnected ? hrProviderName : undefined}
-                                    isHRAdvancedMode={isHRAdvancedModeEnabled}
-                                    hrFinalApproverEmail={isHRAdvancedModeEnabled ? hrFinalApproverEmail : undefined}
-                                />
-                            </OfflineWithFeedback>
-                        ))}
+                        {searchFilteredWorkflows.map((workflow) => {
+                            const firstApproverEmail = workflow.approvers.at(0)?.email ?? '';
+
+                            return (
+                                <OfflineWithFeedback
+                                    key={firstApproverEmail}
+                                    pendingAction={workflow.pendingAction}
+                                >
+                                    <ApprovalWorkflowSection
+                                        approvalWorkflow={workflow}
+                                        onPress={
+                                            shouldBlockApprovalWorkflowEditing || !canWriteApprovals
+                                                ? undefined
+                                                : () => {
+                                                      // Discard stale onyx edits or the Edit page's resume check would surface a prior abandoned session.
+                                                      clearApprovalWorkflow();
+                                                      Navigation.navigate(ROUTES.WORKSPACE_WORKFLOWS_APPROVALS_EDIT.getRoute(route.params.policyID, firstApproverEmail));
+                                                  }
+                                        }
+                                        onShowAllMembersPress={
+                                            shouldBlockApprovalWorkflowEditing
+                                                ? undefined
+                                                : () => {
+                                                      selectApprovalWorkflowForEdit({workflow, defaultWorkflowMembers: availableMembers, usedApproverEmails});
+                                                      Navigation.navigate(
+                                                          ROUTES.WORKSPACE_WORKFLOWS_APPROVALS_EXPENSES_FROM.getRoute(
+                                                              route.params.policyID,
+                                                              ROUTES.WORKSPACE_WORKFLOWS.getRoute(route.params.policyID),
+                                                          ),
+                                                      );
+                                                  }
+                                        }
+                                        currency={policy?.outputCurrency}
+                                        isDisabled={shouldBlockApprovalWorkflowEditing || !canWriteApprovals}
+                                        hrProviderName={isHRConnected ? hrProviderName : undefined}
+                                        isHRAdvancedMode={isHRAdvancedModeEnabled}
+                                        hrFinalApproverEmail={isHRAdvancedModeEnabled ? hrFinalApproverEmail : undefined}
+                                    />
+                                </OfflineWithFeedback>
+                            );
+                        })}
                         {!shouldBlockApprovalWorkflowEditing && canWriteApprovals && (
                             <MenuItem
                                 title={translate('workflowsPage.addApprovalButton')}
diff --git a/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsEditPage.tsx b/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsEditPage.tsx
index f827936c63b1..a5e96772d802 100644
--- a/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsEditPage.tsx
+++ b/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsEditPage.tsx
@@ -22,13 +22,7 @@ import {convertPolicyEmployeesToApprovalWorkflows} from '@libs/WorkflowUtils';
 import AccessOrNotFoundWrapper from '@pages/workspace/AccessOrNotFoundWrapper';
 import withPolicyAndFullscreenLoading from '@pages/workspace/withPolicyAndFullscreenLoading';
 import type {WithPolicyAndFullscreenLoadingProps} from '@pages/workspace/withPolicyAndFullscreenLoading';
-import {
-    clearApprovalWorkflow,
-    removeApprovalWorkflow,
-    selectApprovalWorkflowForEdit,
-    updateApprovalWorkflow,
-    validateApprovalWorkflow,
-} from '@userActions/Workflow';
+import {clearApprovalWorkflow, removeApprovalWorkflow, selectApprovalWorkflowForEdit, updateApprovalWorkflow, validateApprovalWorkflow} from '@userActions/Workflow';
 import CONST from '@src/CONST';
 import ONYXKEYS from '@src/ONYXKEYS';
 import type SCREENS from '@src/SCREENS';
@@ -135,8 +129,7 @@ function WorkspaceWorkflowsApprovalsEditPage({policy, isLoadingReportData = true
         }
 
         // Resume after a sub-page round-trip: keep onyx state to avoid wiping the user's pending edits.
-        const isResumingEdit =
-            approvalWorkflow?.action === CONST.APPROVAL_WORKFLOW.ACTION.EDIT && approvalWorkflow?.originalApprovers?.at(0)?.email === route.params.firstApproverEmail;
+        const isResumingEdit = approvalWorkflow?.action === CONST.APPROVAL_WORKFLOW.ACTION.EDIT && approvalWorkflow?.originalApprovers?.at(0)?.email === route.params.firstApproverEmail;
         if (isResumingEdit) {
             // eslint-disable-next-line react-hooks/set-state-in-effect -- one-time snapshot guarded by isResumingEdit + early return; runs at most once per mount
             setInitialApprovalWorkflow(currentApprovalWorkflow);

From 08476f8869afb77d7ef1d73fe5b098a7473a07a8 Mon Sep 17 00:00:00 2001
From: OSBotify <infra+osbotify@expensify.com>
Date: Thu, 11 Jun 2026 20:55:37 +0000
Subject: [PATCH 407/435] Update version to 9.4.5-3

---
 android/app/build.gradle                    | 4 ++--
 ios/NewExpensify/Info.plist                 | 2 +-
 ios/NotificationServiceExtension/Info.plist | 2 +-
 ios/ShareViewController/Info.plist          | 2 +-
 package-lock.json                           | 4 ++--
 package.json                                | 2 +-
 6 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/android/app/build.gradle b/android/app/build.gradle
index a9b0db007444..2976112b9935 100644
--- a/android/app/build.gradle
+++ b/android/app/build.gradle
@@ -111,8 +111,8 @@ android {
         minSdkVersion rootProject.ext.minSdkVersion
         targetSdkVersion rootProject.ext.targetSdkVersion
         multiDexEnabled rootProject.ext.multiDexEnabled
-        versionCode 1009040502
-        versionName "9.4.5-2"
+        versionCode 1009040503
+        versionName "9.4.5-3"
         // Supported language variants must be declared here to avoid from being removed during the compilation.
         // This also helps us to not include unnecessary language variants in the APK.
         resConfigs "en", "es"
diff --git a/ios/NewExpensify/Info.plist b/ios/NewExpensify/Info.plist
index bc4f83ffa630..216306e75b80 100644
--- a/ios/NewExpensify/Info.plist
+++ b/ios/NewExpensify/Info.plist
@@ -44,7 +44,7 @@
 		</dict>
 	</array>
 	<key>CFBundleVersion</key>
-	<string>9.4.5.2</string>
+	<string>9.4.5.3</string>
 	<key>FullStory</key>
 	<dict>
 		<key>OrgId</key>
diff --git a/ios/NotificationServiceExtension/Info.plist b/ios/NotificationServiceExtension/Info.plist
index 0ca5c65db42c..8f1035289ade 100644
--- a/ios/NotificationServiceExtension/Info.plist
+++ b/ios/NotificationServiceExtension/Info.plist
@@ -13,7 +13,7 @@
 	<key>CFBundleShortVersionString</key>
 	<string>9.4.5</string>
 	<key>CFBundleVersion</key>
-	<string>9.4.5.2</string>
+	<string>9.4.5.3</string>
 	<key>NSExtension</key>
 	<dict>
 		<key>NSExtensionPointIdentifier</key>
diff --git a/ios/ShareViewController/Info.plist b/ios/ShareViewController/Info.plist
index e07414831f48..6dd97e61e7d1 100644
--- a/ios/ShareViewController/Info.plist
+++ b/ios/ShareViewController/Info.plist
@@ -13,7 +13,7 @@
 	<key>CFBundleShortVersionString</key>
 	<string>9.4.5</string>
 	<key>CFBundleVersion</key>
-	<string>9.4.5.2</string>
+	<string>9.4.5.3</string>
 	<key>NSExtension</key>
 	<dict>
 		<key>NSExtensionAttributes</key>
diff --git a/package-lock.json b/package-lock.json
index 837e387ab935..21b526bd9f89 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,12 +1,12 @@
 {
   "name": "new.expensify",
-  "version": "9.4.5-2",
+  "version": "9.4.5-3",
   "lockfileVersion": 3,
   "requires": true,
   "packages": {
     "": {
       "name": "new.expensify",
-      "version": "9.4.5-2",
+      "version": "9.4.5-3",
       "hasInstallScript": true,
       "license": "MIT",
       "workspaces": [
diff --git a/package.json b/package.json
index 6909b24e9868..a188d9022727 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
   "name": "new.expensify",
-  "version": "9.4.5-2",
+  "version": "9.4.5-3",
   "author": "Expensify, Inc.",
   "homepage": "https://new.expensify.com",
   "description": "New Expensify is the next generation of Expensify: a reimagination of payments based atop a foundation of chat.",

From a6ef060e62a6642361a6f082f24857a3874a153d Mon Sep 17 00:00:00 2001
From: OSBotify <infra+osbotify@expensify.com>
Date: Thu, 11 Jun 2026 20:55:37 +0000
Subject: [PATCH 408/435] Update Mobile-Expensify submodule version to 9.4.5-3

---
 Mobile-Expensify | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Mobile-Expensify b/Mobile-Expensify
index ba698f53f0ba..9bbc43ac9f84 160000
--- a/Mobile-Expensify
+++ b/Mobile-Expensify
@@ -1 +1 @@
-Subproject commit ba698f53f0ba205804541c0bcff6fbe51025a592
+Subproject commit 9bbc43ac9f84efcc058940a29fb48b4932ec597d

From d5f54361dfa7f53f423995a325691f083e6c45c4 Mon Sep 17 00:00:00 2001
From: OSBotify <infra+osbotify@expensify.com>
Date: Thu, 11 Jun 2026 21:09:29 +0000
Subject: [PATCH 409/435] Auto-tighten eslint-seatbelt baseline

---
 config/eslint/eslint.seatbelt.tsv | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/config/eslint/eslint.seatbelt.tsv b/config/eslint/eslint.seatbelt.tsv
index 42b222df02e3..318bf6a7f730 100644
--- a/config/eslint/eslint.seatbelt.tsv
+++ b/config/eslint/eslint.seatbelt.tsv
@@ -277,7 +277,6 @@
 "../../src/components/MoneyRequestConfirmationListFooter/sections/DistanceMapSection.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../src/components/MoneyRequestConfirmationListFooter/sections/ReceiptSection.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../src/components/MoneyRequestReportView/MoneyRequestReportActionsList.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
-"../../src/components/MoneyRequestReportView/MoneyRequestReportActionsList.tsx"	"no-restricted-imports"	1
 "../../src/components/MoneyRequestReportView/MoneyRequestReportActionsList.tsx"	"react-hooks/refs"	3
 "../../src/components/MoneyRequestReportView/MoneyRequestReportActionsList.tsx"	"react-hooks/set-state-in-effect"	3
 "../../src/components/MoneyRequestReportView/MoneyRequestReportTransactionList.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	3
@@ -1176,7 +1175,6 @@
 "../../src/pages/inbox/report/ReportActionItemMessageEdit.tsx"	"react-hooks/refs"	5
 "../../src/pages/inbox/report/ReportActionItemMessageEdit.tsx"	"react-hooks/set-state-in-effect"	1
 "../../src/pages/inbox/report/ReportActionsList.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
-"../../src/pages/inbox/report/ReportActionsList.tsx"	"no-restricted-imports"	1
 "../../src/pages/inbox/report/ReportActionsList.tsx"	"react-hooks/refs"	2
 "../../src/pages/inbox/report/TripSummary.tsx"	"rulesdir/no-default-id-values"	1
 "../../src/pages/inbox/report/UserTypingEventListener.tsx"	"no-restricted-imports"	1
@@ -1915,7 +1913,7 @@
 "../../tests/unit/SelectFeaturesEmptyTagGroupTest.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../tests/unit/SettlementButtonUtilsTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	4
 "../../tests/unit/SidebarTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	2
-"../../tests/unit/SidebarUtilsTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	38
+"../../tests/unit/SidebarUtilsTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	35
 "../../tests/unit/SidebarUtilsTest.ts"	"no-restricted-imports"	1
 "../../tests/unit/SplitExpenseAutoAdjustmentTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../tests/unit/SubscriptionUtilsTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	2

From 6d922d19e7d6431ef62ba8a844c72b7f4e7a12fc Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Nicol=C3=A1s=20Bonet=20=28via=20MelvinBot=29?=
 <infra+melvinbot@expensify.com>
Date: Thu, 11 Jun 2026 17:57:30 +0000
Subject: [PATCH 410/435] Fix: link agents promo banner to AI Rules instead of
 Workflows
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Co-authored-by: Nicolás Bonet <NicolasBonet@users.noreply.github.com>
---
 src/pages/workspace/rules/PolicyRulesPage.tsx | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/pages/workspace/rules/PolicyRulesPage.tsx b/src/pages/workspace/rules/PolicyRulesPage.tsx
index 987514bf1b0a..a7e8b8b8b94d 100644
--- a/src/pages/workspace/rules/PolicyRulesPage.tsx
+++ b/src/pages/workspace/rules/PolicyRulesPage.tsx
@@ -78,7 +78,7 @@ function PolicyRulesPage({route}: PolicyRulesPageProps) {
                             title={translate('workspace.rules.agentsPromoBanner.title')}
                             subtitle={translate('workspace.rules.agentsPromoBanner.subtitle')}
                             ctaText={translate('workspace.rules.agentsPromoBanner.cta')}
-                            onCtaPress={() => Navigation.navigate(ROUTES.WORKSPACE_WORKFLOWS.getRoute(policyID))}
+                            onCtaPress={() => Navigation.navigate(ROUTES.RULES_AI_NEW.getRoute(policyID))}
                             ctaSentryLabel={CONST.SENTRY_LABEL.AGENTS_RULES_BANNER.CTA}
                             onDismiss={() => dismissProductTraining(CONST.AGENTS_RULES_BANNER, true)}
                             dismissSentryLabel={CONST.SENTRY_LABEL.AGENTS_RULES_BANNER.DISMISS}

From ed38ccd00f6744a9e978adf86aa59a2fb99556bf Mon Sep 17 00:00:00 2001
From: Puneet Lath <puneet@expensify.com>
Date: Thu, 11 Jun 2026 17:20:34 -0400
Subject: [PATCH 411/435] Remove unused imports left after workflows agent
 cleanup

Fix ESLint no-unused-vars errors in ApprovalWorkflowSection and
WorkflowUtils after removing agent-related types and helpers.

Co-authored-by: Cursor <cursoragent@cursor.com>
---
 src/components/ApprovalWorkflowSection.tsx | 1 -
 src/libs/WorkflowUtils.ts                  | 4 +---
 2 files changed, 1 insertion(+), 4 deletions(-)

diff --git a/src/components/ApprovalWorkflowSection.tsx b/src/components/ApprovalWorkflowSection.tsx
index efad2f0081df..964711ae285f 100644
--- a/src/components/ApprovalWorkflowSection.tsx
+++ b/src/components/ApprovalWorkflowSection.tsx
@@ -11,7 +11,6 @@ import {sortAlphabetically} from '@libs/OptionsListUtils';
 import {getApprovalLimitDescription} from '@libs/WorkflowUtils';
 import CONST from '@src/CONST';
 import type ApprovalWorkflow from '@src/types/onyx/ApprovalWorkflow';
-import type {Approver} from '@src/types/onyx/ApprovalWorkflow';
 import Button from './Button';
 import Icon from './Icon';
 import MenuItem from './MenuItem';
diff --git a/src/libs/WorkflowUtils.ts b/src/libs/WorkflowUtils.ts
index 8919ed7d7e7e..c5cff6e27412 100644
--- a/src/libs/WorkflowUtils.ts
+++ b/src/libs/WorkflowUtils.ts
@@ -1,12 +1,10 @@
 import {Str} from 'expensify-common';
-import type {OnyxCollection, OnyxEntry} from 'react-native-onyx';
+import type {OnyxEntry} from 'react-native-onyx';
 import type {ValueOf} from 'type-fest';
 import type {LocaleContextProps} from '@components/LocaleContextProvider';
 import type {CurrencyListActionsContextType} from '@hooks/useCurrencyList';
 import CONST from '@src/CONST';
-import ONYXKEYS from '@src/ONYXKEYS';
 import type {BankAccountList} from '@src/types/onyx';
-import type AgentPrompt from '@src/types/onyx/AgentPrompt';
 import type {ApprovalWorkflowOnyx, Approver, Member} from '@src/types/onyx/ApprovalWorkflow';
 import type ApprovalWorkflow from '@src/types/onyx/ApprovalWorkflow';
 import type {PersonalDetailsList} from '@src/types/onyx/PersonalDetails';

From cdee876a958cf1997feb716078d91fdbd9fbc852 Mon Sep 17 00:00:00 2001
From: OSBotify <infra+osbotify@expensify.com>
Date: Thu, 11 Jun 2026 21:41:42 +0000
Subject: [PATCH 412/435] Auto-tighten eslint-seatbelt baseline

---
 config/eslint/eslint.seatbelt.tsv | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/config/eslint/eslint.seatbelt.tsv b/config/eslint/eslint.seatbelt.tsv
index 318bf6a7f730..7e1ced82a4d2 100644
--- a/config/eslint/eslint.seatbelt.tsv
+++ b/config/eslint/eslint.seatbelt.tsv
@@ -1681,7 +1681,7 @@
 "../../tests/perf-test/ReportUtils.perf-test.ts"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../tests/perf-test/SelectionList.perf-test.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../tests/perf-test/useFilterFormValues.perf-test.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	15
-"../../tests/ui/AgentsPromoBannersTest.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	4
+"../../tests/ui/AgentsPromoBannersTest.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	3
 "../../tests/ui/AssignCardFeed.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	3
 "../../tests/ui/AuthScreensInitHandlerTest.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	7
 "../../tests/ui/AvatarSelector.test.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	7
@@ -1772,7 +1772,7 @@
 "../../tests/ui/hooks/useHtmlPasteTest/index.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	10
 "../../tests/unit/APITest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	61
 "../../tests/unit/AddExistingExpenseSearchTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	6
-"../../tests/unit/AgentActionTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	61
+"../../tests/unit/AgentActionTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	53
 "../../tests/unit/AgentZeroStatusContextTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	5
 "../../tests/unit/AvatarButtonWithIconTest.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../tests/unit/AvatarUtilsTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	2

From 091e2cfff8b9b62cd76149b3fd1d36c51988d06a Mon Sep 17 00:00:00 2001
From: OSBotify <infra+osbotify@expensify.com>
Date: Thu, 11 Jun 2026 21:44:28 +0000
Subject: [PATCH 413/435] Update version to 9.4.5-4

---
 android/app/build.gradle                    | 4 ++--
 ios/NewExpensify/Info.plist                 | 2 +-
 ios/NotificationServiceExtension/Info.plist | 2 +-
 ios/ShareViewController/Info.plist          | 2 +-
 package-lock.json                           | 4 ++--
 package.json                                | 2 +-
 6 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/android/app/build.gradle b/android/app/build.gradle
index 2976112b9935..ab20a34c96cb 100644
--- a/android/app/build.gradle
+++ b/android/app/build.gradle
@@ -111,8 +111,8 @@ android {
         minSdkVersion rootProject.ext.minSdkVersion
         targetSdkVersion rootProject.ext.targetSdkVersion
         multiDexEnabled rootProject.ext.multiDexEnabled
-        versionCode 1009040503
-        versionName "9.4.5-3"
+        versionCode 1009040504
+        versionName "9.4.5-4"
         // Supported language variants must be declared here to avoid from being removed during the compilation.
         // This also helps us to not include unnecessary language variants in the APK.
         resConfigs "en", "es"
diff --git a/ios/NewExpensify/Info.plist b/ios/NewExpensify/Info.plist
index 216306e75b80..d65f260653ad 100644
--- a/ios/NewExpensify/Info.plist
+++ b/ios/NewExpensify/Info.plist
@@ -44,7 +44,7 @@
 		</dict>
 	</array>
 	<key>CFBundleVersion</key>
-	<string>9.4.5.3</string>
+	<string>9.4.5.4</string>
 	<key>FullStory</key>
 	<dict>
 		<key>OrgId</key>
diff --git a/ios/NotificationServiceExtension/Info.plist b/ios/NotificationServiceExtension/Info.plist
index 8f1035289ade..3121a19ec98a 100644
--- a/ios/NotificationServiceExtension/Info.plist
+++ b/ios/NotificationServiceExtension/Info.plist
@@ -13,7 +13,7 @@
 	<key>CFBundleShortVersionString</key>
 	<string>9.4.5</string>
 	<key>CFBundleVersion</key>
-	<string>9.4.5.3</string>
+	<string>9.4.5.4</string>
 	<key>NSExtension</key>
 	<dict>
 		<key>NSExtensionPointIdentifier</key>
diff --git a/ios/ShareViewController/Info.plist b/ios/ShareViewController/Info.plist
index 6dd97e61e7d1..82406750ed15 100644
--- a/ios/ShareViewController/Info.plist
+++ b/ios/ShareViewController/Info.plist
@@ -13,7 +13,7 @@
 	<key>CFBundleShortVersionString</key>
 	<string>9.4.5</string>
 	<key>CFBundleVersion</key>
-	<string>9.4.5.3</string>
+	<string>9.4.5.4</string>
 	<key>NSExtension</key>
 	<dict>
 		<key>NSExtensionAttributes</key>
diff --git a/package-lock.json b/package-lock.json
index 21b526bd9f89..2bff7a7519c6 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,12 +1,12 @@
 {
   "name": "new.expensify",
-  "version": "9.4.5-3",
+  "version": "9.4.5-4",
   "lockfileVersion": 3,
   "requires": true,
   "packages": {
     "": {
       "name": "new.expensify",
-      "version": "9.4.5-3",
+      "version": "9.4.5-4",
       "hasInstallScript": true,
       "license": "MIT",
       "workspaces": [
diff --git a/package.json b/package.json
index a188d9022727..b61a9b82a5fb 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
   "name": "new.expensify",
-  "version": "9.4.5-3",
+  "version": "9.4.5-4",
   "author": "Expensify, Inc.",
   "homepage": "https://new.expensify.com",
   "description": "New Expensify is the next generation of Expensify: a reimagination of payments based atop a foundation of chat.",

From 08cd06648d729cd599d5cfc02473c7c8ebd1d086 Mon Sep 17 00:00:00 2001
From: OSBotify <infra+osbotify@expensify.com>
Date: Thu, 11 Jun 2026 21:44:28 +0000
Subject: [PATCH 414/435] Update Mobile-Expensify submodule version to 9.4.5-4

---
 Mobile-Expensify | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Mobile-Expensify b/Mobile-Expensify
index 9bbc43ac9f84..326bce50b502 160000
--- a/Mobile-Expensify
+++ b/Mobile-Expensify
@@ -1 +1 @@
-Subproject commit 9bbc43ac9f84efcc058940a29fb48b4932ec597d
+Subproject commit 326bce50b50254584c701b0534314ae6f882c763

From 32e32a8ba89f92b1301dd7b690624fcfdad64552 Mon Sep 17 00:00:00 2001
From: OSBotify <infra+osbotify@expensify.com>
Date: Thu, 11 Jun 2026 21:51:10 +0000
Subject: [PATCH 415/435] Update version to 9.4.5-5

---
 android/app/build.gradle                    | 4 ++--
 ios/NewExpensify/Info.plist                 | 2 +-
 ios/NotificationServiceExtension/Info.plist | 2 +-
 ios/ShareViewController/Info.plist          | 2 +-
 package-lock.json                           | 4 ++--
 package.json                                | 2 +-
 6 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/android/app/build.gradle b/android/app/build.gradle
index ab20a34c96cb..b93e9340d7bb 100644
--- a/android/app/build.gradle
+++ b/android/app/build.gradle
@@ -111,8 +111,8 @@ android {
         minSdkVersion rootProject.ext.minSdkVersion
         targetSdkVersion rootProject.ext.targetSdkVersion
         multiDexEnabled rootProject.ext.multiDexEnabled
-        versionCode 1009040504
-        versionName "9.4.5-4"
+        versionCode 1009040505
+        versionName "9.4.5-5"
         // Supported language variants must be declared here to avoid from being removed during the compilation.
         // This also helps us to not include unnecessary language variants in the APK.
         resConfigs "en", "es"
diff --git a/ios/NewExpensify/Info.plist b/ios/NewExpensify/Info.plist
index d65f260653ad..fb188b5ba645 100644
--- a/ios/NewExpensify/Info.plist
+++ b/ios/NewExpensify/Info.plist
@@ -44,7 +44,7 @@
 		</dict>
 	</array>
 	<key>CFBundleVersion</key>
-	<string>9.4.5.4</string>
+	<string>9.4.5.5</string>
 	<key>FullStory</key>
 	<dict>
 		<key>OrgId</key>
diff --git a/ios/NotificationServiceExtension/Info.plist b/ios/NotificationServiceExtension/Info.plist
index 3121a19ec98a..749e924a6870 100644
--- a/ios/NotificationServiceExtension/Info.plist
+++ b/ios/NotificationServiceExtension/Info.plist
@@ -13,7 +13,7 @@
 	<key>CFBundleShortVersionString</key>
 	<string>9.4.5</string>
 	<key>CFBundleVersion</key>
-	<string>9.4.5.4</string>
+	<string>9.4.5.5</string>
 	<key>NSExtension</key>
 	<dict>
 		<key>NSExtensionPointIdentifier</key>
diff --git a/ios/ShareViewController/Info.plist b/ios/ShareViewController/Info.plist
index 82406750ed15..955d71c760f5 100644
--- a/ios/ShareViewController/Info.plist
+++ b/ios/ShareViewController/Info.plist
@@ -13,7 +13,7 @@
 	<key>CFBundleShortVersionString</key>
 	<string>9.4.5</string>
 	<key>CFBundleVersion</key>
-	<string>9.4.5.4</string>
+	<string>9.4.5.5</string>
 	<key>NSExtension</key>
 	<dict>
 		<key>NSExtensionAttributes</key>
diff --git a/package-lock.json b/package-lock.json
index 2bff7a7519c6..16d208ed64f7 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,12 +1,12 @@
 {
   "name": "new.expensify",
-  "version": "9.4.5-4",
+  "version": "9.4.5-5",
   "lockfileVersion": 3,
   "requires": true,
   "packages": {
     "": {
       "name": "new.expensify",
-      "version": "9.4.5-4",
+      "version": "9.4.5-5",
       "hasInstallScript": true,
       "license": "MIT",
       "workspaces": [
diff --git a/package.json b/package.json
index b61a9b82a5fb..c49474e5f842 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
   "name": "new.expensify",
-  "version": "9.4.5-4",
+  "version": "9.4.5-5",
   "author": "Expensify, Inc.",
   "homepage": "https://new.expensify.com",
   "description": "New Expensify is the next generation of Expensify: a reimagination of payments based atop a foundation of chat.",

From b5a65f6fc70304683b3c0f0004b2913854033173 Mon Sep 17 00:00:00 2001
From: OSBotify <infra+osbotify@expensify.com>
Date: Thu, 11 Jun 2026 21:51:10 +0000
Subject: [PATCH 416/435] Update Mobile-Expensify submodule version to 9.4.5-5

---
 Mobile-Expensify | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Mobile-Expensify b/Mobile-Expensify
index 326bce50b502..4eefc7be8223 160000
--- a/Mobile-Expensify
+++ b/Mobile-Expensify
@@ -1 +1 @@
-Subproject commit 326bce50b50254584c701b0534314ae6f882c763
+Subproject commit 4eefc7be822311b2216290b9ba771449e65b2707

From b39ebfccd077dd18c9c969e64363b4e9b77ec4f3 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Nicol=C3=A1s=20Bonet=20=28via=20MelvinBot=29?=
 <infra+melvinbot@expensify.com>
Date: Thu, 11 Jun 2026 22:01:58 +0000
Subject: [PATCH 417/435] Gate agents promo banner CTA for read-only rules
 users
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Co-authored-by: Nicolás Bonet <NicolasBonet@users.noreply.github.com>
---
 src/pages/workspace/rules/PolicyRulesPage.tsx | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/src/pages/workspace/rules/PolicyRulesPage.tsx b/src/pages/workspace/rules/PolicyRulesPage.tsx
index a7e8b8b8b94d..a56f3e7db238 100644
--- a/src/pages/workspace/rules/PolicyRulesPage.tsx
+++ b/src/pages/workspace/rules/PolicyRulesPage.tsx
@@ -78,7 +78,13 @@ function PolicyRulesPage({route}: PolicyRulesPageProps) {
                             title={translate('workspace.rules.agentsPromoBanner.title')}
                             subtitle={translate('workspace.rules.agentsPromoBanner.subtitle')}
                             ctaText={translate('workspace.rules.agentsPromoBanner.cta')}
-                            onCtaPress={() => Navigation.navigate(ROUTES.RULES_AI_NEW.getRoute(policyID))}
+                            onCtaPress={() => {
+                                if (!canWriteRules) {
+                                    showReadOnlyModal();
+                                    return;
+                                }
+                                Navigation.navigate(ROUTES.RULES_AI_NEW.getRoute(policyID));
+                            }}
                             ctaSentryLabel={CONST.SENTRY_LABEL.AGENTS_RULES_BANNER.CTA}
                             onDismiss={() => dismissProductTraining(CONST.AGENTS_RULES_BANNER, true)}
                             dismissSentryLabel={CONST.SENTRY_LABEL.AGENTS_RULES_BANNER.DISMISS}

From 42736c5fe88200397e077db75c1d899f5ee190eb Mon Sep 17 00:00:00 2001
From: OSBotify <infra+osbotify@expensify.com>
Date: Thu, 11 Jun 2026 22:24:48 +0000
Subject: [PATCH 418/435] Update version to 9.4.5-6

---
 android/app/build.gradle                    | 4 ++--
 ios/NewExpensify/Info.plist                 | 2 +-
 ios/NotificationServiceExtension/Info.plist | 2 +-
 ios/ShareViewController/Info.plist          | 2 +-
 package-lock.json                           | 4 ++--
 package.json                                | 2 +-
 6 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/android/app/build.gradle b/android/app/build.gradle
index b93e9340d7bb..c238c51a74cb 100644
--- a/android/app/build.gradle
+++ b/android/app/build.gradle
@@ -111,8 +111,8 @@ android {
         minSdkVersion rootProject.ext.minSdkVersion
         targetSdkVersion rootProject.ext.targetSdkVersion
         multiDexEnabled rootProject.ext.multiDexEnabled
-        versionCode 1009040505
-        versionName "9.4.5-5"
+        versionCode 1009040506
+        versionName "9.4.5-6"
         // Supported language variants must be declared here to avoid from being removed during the compilation.
         // This also helps us to not include unnecessary language variants in the APK.
         resConfigs "en", "es"
diff --git a/ios/NewExpensify/Info.plist b/ios/NewExpensify/Info.plist
index fb188b5ba645..7c2436a43827 100644
--- a/ios/NewExpensify/Info.plist
+++ b/ios/NewExpensify/Info.plist
@@ -44,7 +44,7 @@
 		</dict>
 	</array>
 	<key>CFBundleVersion</key>
-	<string>9.4.5.5</string>
+	<string>9.4.5.6</string>
 	<key>FullStory</key>
 	<dict>
 		<key>OrgId</key>
diff --git a/ios/NotificationServiceExtension/Info.plist b/ios/NotificationServiceExtension/Info.plist
index 749e924a6870..399f59fe2010 100644
--- a/ios/NotificationServiceExtension/Info.plist
+++ b/ios/NotificationServiceExtension/Info.plist
@@ -13,7 +13,7 @@
 	<key>CFBundleShortVersionString</key>
 	<string>9.4.5</string>
 	<key>CFBundleVersion</key>
-	<string>9.4.5.5</string>
+	<string>9.4.5.6</string>
 	<key>NSExtension</key>
 	<dict>
 		<key>NSExtensionPointIdentifier</key>
diff --git a/ios/ShareViewController/Info.plist b/ios/ShareViewController/Info.plist
index 955d71c760f5..8aa136af078d 100644
--- a/ios/ShareViewController/Info.plist
+++ b/ios/ShareViewController/Info.plist
@@ -13,7 +13,7 @@
 	<key>CFBundleShortVersionString</key>
 	<string>9.4.5</string>
 	<key>CFBundleVersion</key>
-	<string>9.4.5.5</string>
+	<string>9.4.5.6</string>
 	<key>NSExtension</key>
 	<dict>
 		<key>NSExtensionAttributes</key>
diff --git a/package-lock.json b/package-lock.json
index 16d208ed64f7..93ea9fb2db8e 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,12 +1,12 @@
 {
   "name": "new.expensify",
-  "version": "9.4.5-5",
+  "version": "9.4.5-6",
   "lockfileVersion": 3,
   "requires": true,
   "packages": {
     "": {
       "name": "new.expensify",
-      "version": "9.4.5-5",
+      "version": "9.4.5-6",
       "hasInstallScript": true,
       "license": "MIT",
       "workspaces": [
diff --git a/package.json b/package.json
index c49474e5f842..3561eb378b4b 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
   "name": "new.expensify",
-  "version": "9.4.5-5",
+  "version": "9.4.5-6",
   "author": "Expensify, Inc.",
   "homepage": "https://new.expensify.com",
   "description": "New Expensify is the next generation of Expensify: a reimagination of payments based atop a foundation of chat.",

From eb2b45930a530b44f6a44b1949665193863f45b9 Mon Sep 17 00:00:00 2001
From: OSBotify <infra+osbotify@expensify.com>
Date: Thu, 11 Jun 2026 22:24:48 +0000
Subject: [PATCH 419/435] Update Mobile-Expensify submodule version to 9.4.5-6

---
 Mobile-Expensify | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Mobile-Expensify b/Mobile-Expensify
index 4eefc7be8223..79b84a5bc7d6 160000
--- a/Mobile-Expensify
+++ b/Mobile-Expensify
@@ -1 +1 @@
-Subproject commit 4eefc7be822311b2216290b9ba771449e65b2707
+Subproject commit 79b84a5bc7d646262a811744af021a0c527402ca

From 6e4654b02a985d10effe877293faeea5986322f0 Mon Sep 17 00:00:00 2001
From: OSBotify <infra+osbotify@expensify.com>
Date: Thu, 11 Jun 2026 23:26:33 +0000
Subject: [PATCH 420/435] Update version to 9.4.6-0

---
 android/app/build.gradle                    | 4 ++--
 ios/NewExpensify/Info.plist                 | 4 ++--
 ios/NotificationServiceExtension/Info.plist | 4 ++--
 ios/ShareViewController/Info.plist          | 4 ++--
 package-lock.json                           | 4 ++--
 package.json                                | 2 +-
 6 files changed, 11 insertions(+), 11 deletions(-)

diff --git a/android/app/build.gradle b/android/app/build.gradle
index c238c51a74cb..a5b9d35d6bf0 100644
--- a/android/app/build.gradle
+++ b/android/app/build.gradle
@@ -111,8 +111,8 @@ android {
         minSdkVersion rootProject.ext.minSdkVersion
         targetSdkVersion rootProject.ext.targetSdkVersion
         multiDexEnabled rootProject.ext.multiDexEnabled
-        versionCode 1009040506
-        versionName "9.4.5-6"
+        versionCode 1009040600
+        versionName "9.4.6-0"
         // Supported language variants must be declared here to avoid from being removed during the compilation.
         // This also helps us to not include unnecessary language variants in the APK.
         resConfigs "en", "es"
diff --git a/ios/NewExpensify/Info.plist b/ios/NewExpensify/Info.plist
index 7c2436a43827..785a864e6500 100644
--- a/ios/NewExpensify/Info.plist
+++ b/ios/NewExpensify/Info.plist
@@ -23,7 +23,7 @@
 	<key>CFBundlePackageType</key>
 	<string>APPL</string>
 	<key>CFBundleShortVersionString</key>
-	<string>9.4.5</string>
+	<string>9.4.6</string>
 	<key>CFBundleSignature</key>
 	<string>????</string>
 	<key>CFBundleURLTypes</key>
@@ -44,7 +44,7 @@
 		</dict>
 	</array>
 	<key>CFBundleVersion</key>
-	<string>9.4.5.6</string>
+	<string>9.4.6.0</string>
 	<key>FullStory</key>
 	<dict>
 		<key>OrgId</key>
diff --git a/ios/NotificationServiceExtension/Info.plist b/ios/NotificationServiceExtension/Info.plist
index 399f59fe2010..e721b9d49276 100644
--- a/ios/NotificationServiceExtension/Info.plist
+++ b/ios/NotificationServiceExtension/Info.plist
@@ -11,9 +11,9 @@
 	<key>CFBundleName</key>
 	<string>$(PRODUCT_NAME)</string>
 	<key>CFBundleShortVersionString</key>
-	<string>9.4.5</string>
+	<string>9.4.6</string>
 	<key>CFBundleVersion</key>
-	<string>9.4.5.6</string>
+	<string>9.4.6.0</string>
 	<key>NSExtension</key>
 	<dict>
 		<key>NSExtensionPointIdentifier</key>
diff --git a/ios/ShareViewController/Info.plist b/ios/ShareViewController/Info.plist
index 8aa136af078d..bef8c163e2df 100644
--- a/ios/ShareViewController/Info.plist
+++ b/ios/ShareViewController/Info.plist
@@ -11,9 +11,9 @@
 	<key>CFBundleName</key>
 	<string>$(PRODUCT_NAME)</string>
 	<key>CFBundleShortVersionString</key>
-	<string>9.4.5</string>
+	<string>9.4.6</string>
 	<key>CFBundleVersion</key>
-	<string>9.4.5.6</string>
+	<string>9.4.6.0</string>
 	<key>NSExtension</key>
 	<dict>
 		<key>NSExtensionAttributes</key>
diff --git a/package-lock.json b/package-lock.json
index 93ea9fb2db8e..c5d5de5c1b9e 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,12 +1,12 @@
 {
   "name": "new.expensify",
-  "version": "9.4.5-6",
+  "version": "9.4.6-0",
   "lockfileVersion": 3,
   "requires": true,
   "packages": {
     "": {
       "name": "new.expensify",
-      "version": "9.4.5-6",
+      "version": "9.4.6-0",
       "hasInstallScript": true,
       "license": "MIT",
       "workspaces": [
diff --git a/package.json b/package.json
index 3561eb378b4b..583ffae8a05b 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
   "name": "new.expensify",
-  "version": "9.4.5-6",
+  "version": "9.4.6-0",
   "author": "Expensify, Inc.",
   "homepage": "https://new.expensify.com",
   "description": "New Expensify is the next generation of Expensify: a reimagination of payments based atop a foundation of chat.",

From eeb4322951bb110c30b004a38412dc235d0e2047 Mon Sep 17 00:00:00 2001
From: OSBotify <infra+osbotify@expensify.com>
Date: Thu, 11 Jun 2026 23:26:33 +0000
Subject: [PATCH 421/435] Update Mobile-Expensify submodule version to 9.4.6-0

---
 Mobile-Expensify | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Mobile-Expensify b/Mobile-Expensify
index 79b84a5bc7d6..fdf508981aff 160000
--- a/Mobile-Expensify
+++ b/Mobile-Expensify
@@ -1 +1 @@
-Subproject commit 79b84a5bc7d646262a811744af021a0c527402ca
+Subproject commit fdf508981aff5189c5c17c67493a3d1c4535c1a6

From 278b7b94361d187dd78af4ae0fe79885214c6c8b Mon Sep 17 00:00:00 2001
From: "daledah (via MelvinBot)" <infra+melvinbot@expensify.com>
Date: Fri, 12 Jun 2026 04:45:20 +0000
Subject: [PATCH 422/435] Update seatbelt baseline for SearchUIUtilsTest.ts
 (133 -> 136)

Co-authored-by: daledah <daledah@users.noreply.github.com>
---
 config/eslint/eslint.seatbelt.tsv | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/config/eslint/eslint.seatbelt.tsv b/config/eslint/eslint.seatbelt.tsv
index 2ca211aa316d..6d86e4316275 100644
--- a/config/eslint/eslint.seatbelt.tsv
+++ b/config/eslint/eslint.seatbelt.tsv
@@ -1822,7 +1822,7 @@
 "../../tests/unit/Search/SearchListRenderCountTest.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	2
 "../../tests/unit/Search/SearchQueryUtilsTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	9
 "../../tests/unit/Search/SearchSingleSelectionPickerTest.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
-"../../tests/unit/Search/SearchUIUtilsTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	133
+"../../tests/unit/Search/SearchUIUtilsTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	136
 "../../tests/unit/Search/buildCardFilterDataTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	22
 "../../tests/unit/Search/buildSubstitutionsMapTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	3
 "../../tests/unit/Search/getSpendOverTimeStateTest.ts"	"@typescript-eslint/no-unsafe-type-assertion"	2

From 081cf7517dbf6866ba474a1aa7e478599b9495fe Mon Sep 17 00:00:00 2001
From: OSBotify <infra+osbotify@expensify.com>
Date: Fri, 12 Jun 2026 06:48:57 +0000
Subject: [PATCH 423/435] Auto-tighten eslint-seatbelt baseline

---
 config/eslint/eslint.seatbelt.tsv | 1 -
 1 file changed, 1 deletion(-)

diff --git a/config/eslint/eslint.seatbelt.tsv b/config/eslint/eslint.seatbelt.tsv
index 9e8261d0855d..833ddba12297 100644
--- a/config/eslint/eslint.seatbelt.tsv
+++ b/config/eslint/eslint.seatbelt.tsv
@@ -409,7 +409,6 @@
 "../../src/components/Search/hooks/useOptimisticSearchTracking.ts"	"@typescript-eslint/no-unsafe-type-assertion"	4
 "../../src/components/Search/hooks/useStableOptimisticSortedData.ts"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../src/components/Search/index.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	14
-"../../src/components/Search/index.tsx"	"no-restricted-imports"	1
 "../../src/components/Search/index.tsx"	"react-hooks/preserve-manual-memoization"	2
 "../../src/components/Search/index.tsx"	"react-hooks/refs"	5
 "../../src/components/Search/index.tsx"	"react-hooks/set-state-in-effect"	1

From dc4e1bbc7c870e7050746755ab1dc85e4a155cf1 Mon Sep 17 00:00:00 2001
From: ShridharGoel <35566748+ShridharGoel@users.noreply.github.com>
Date: Fri, 12 Jun 2026 15:02:07 +0530
Subject: [PATCH 424/435] Add translations

---
 src/languages/de.ts      | 54 +++++++++++++++++++++++--------------
 src/languages/es.ts      | 54 +++++++++++++++++++++++--------------
 src/languages/fr.ts      | 54 +++++++++++++++++++++++--------------
 src/languages/it.ts      | 54 +++++++++++++++++++++++--------------
 src/languages/ja.ts      | 55 ++++++++++++++++++++++---------------
 src/languages/nl.ts      | 54 +++++++++++++++++++++++--------------
 src/languages/pl.ts      | 52 ++++++++++++++++++++++-------------
 src/languages/pt-BR.ts   | 58 +++++++++++++++++++++++++---------------
 src/languages/zh-hans.ts | 56 +++++++++++++++++++++++---------------
 9 files changed, 308 insertions(+), 183 deletions(-)

diff --git a/src/languages/de.ts b/src/languages/de.ts
index 3c84c48258e2..4f8f9913bcb5 100644
--- a/src/languages/de.ts
+++ b/src/languages/de.ts
@@ -4139,28 +4139,31 @@ ${amount} für ${merchant} – ${date}`,
         verificationFailed: 'Die Verifizierung ist fehlgeschlagen, daher benötigen wir zusätzliche Dokumente, um dich und dein Unternehmen zu überprüfen',
         taxIDVerification: 'Steuer-ID-Verifizierung',
         taxIDVerificationDescription: dedent(`
-        Bitte lade eine der folgenden Dateien hoch:
-        • IRS TIN/EIN-Zuweisungsschreiben
-        • IRS TIN/EIN-Antragsbestätigung (enthält normalerweise „Congratulations! The EIN has been successfully assigned“)
-        • IRS-Steuerbefreiungsschreiben mit Firmenname und EIN`),
+            Bitte lade eine der folgenden Dateien hoch:
+            • IRS TIN/EIN-Zuweisungsschreiben
+            • IRS TIN/EIN-Antragsbestätigung (enthält normalerweise „Congratulations! The EIN has been successfully assigned“)
+            • IRS-Steuerbefreiungsschreiben mit Firmenname und EIN
+        `),
         nameChangeDocument: 'Dokument zur Namensänderung',
         nameChangeDocumentDescription:
             'Wenn sich der Name deines Unternehmens seit der Beantragung der TIN/EIN geändert hat, benötigen wir dieses Dokument zur Verifizierung der angegebenen Steuer-ID',
         companyAddressVerification: 'Verifizierung der Unternehmensadresse',
         companyAddressVerificationDescription: dedent(`
-        Bitte lade eine der folgenden Dateien hoch:
-        • Aktuelle Strom-, Wasser- oder Gasrechnung mit Firmenname und Adresse
-        • Kontoauszug mit Firmenname und Adresse
-        • Aktueller Miet- oder Leasingvertrag inkl. Unterschriftsseite mit Firmenname und aktueller Adresse
-        • Versicherungsnachweis mit Firmenname und Adresse
-        • TIN-Zuweisungsdokument mit Firmenname und Adresse`),
+            Bitte lade eine der folgenden Dateien hoch:
+            • Aktuelle Strom-, Wasser- oder Gasrechnung mit Firmenname und Adresse
+            • Kontoauszug mit Firmenname und Adresse
+            • Aktueller Miet- oder Leasingvertrag inkl. Unterschriftsseite mit Firmenname und aktueller Adresse
+            • Versicherungsnachweis mit Firmenname und Adresse
+            • TIN-Zuweisungsdokument mit Firmenname und Adresse
+        `),
         userAddressVerification: 'Adressverifizierung',
         userAddressVerificationDescription: dedent(`
-        Bitte lade eine der folgenden Dateien hoch:
-        • Wählerregistrierungskarte
-        • Führerschein
-        • Kontoauszug
-        • Versorgungsrechnung`),
+            Bitte lade eine der folgenden Dateien hoch:
+            • Wählerregistrierungskarte
+            • Führerschein
+            • Kontoauszug
+            • Versorgungsrechnung
+        `),
         userDOBVerification: 'Geburtsdatumsverifizierung',
         userDOBVerificationDescription: 'Bitte lade einen in den USA ausgestellten Ausweis hoch',
         finishViaChat: 'Über Chat abschließen',
@@ -4426,13 +4429,13 @@ ${amount} für ${merchant} – ${date}`,
             roleName: (role?: string) => {
                 switch (role) {
                     case CONST.POLICY.ROLE.ADMIN:
-                        return 'Admin';
+                        return 'Workspace-Administrator';
                     case CONST.POLICY.ROLE.AUDITOR:
                         return 'Prüfer';
                     case CONST.POLICY.ROLE.EDITOR:
                         return 'Editor';
                     case CONST.POLICY.ROLE.CARD_ADMIN:
-                        return 'Kartenverwaltung';
+                        return 'Kartenadministrator';
                     case CONST.POLICY.ROLE.PEOPLE_ADMIN:
                         return 'Personenverwaltung';
                     case CONST.POLICY.ROLE.PAYMENTS_ADMIN:
@@ -6280,12 +6283,14 @@ _Für ausführlichere Anweisungen [besuchen Sie unsere Hilfeseite](${CONST.NETSU
             cannotRemoveUserDueToReport: ({memberName}: {memberName: string}) =>
                 `${memberName} hat einen ausstehenden Bericht in Bearbeitung, zu dem eine Aktion erforderlich ist. Bitte bitten Sie diese Person, die erforderliche Aktion abzuschließen, bevor Sie sie aus dem Workspace entfernen.`,
             allMembers: 'Alle Mitglieder',
-            admins: 'Admins',
+            admins: 'Workspace-Administratoren',
             approvers: 'Genehmigende',
             auditors: 'Prüfer',
             emptyRoleFilter: {title: 'Keine Mitglieder entsprechen diesem Filter', subtitle: 'Laden Sie ein Mitglied ein oder ändern Sie den Filter oben.'},
             configureHRSync: (providerName: string) => `Synchronisierung mit ${providerName} einrichten.`,
             syncWithHR: (providerName: string) => `Mit ${providerName} synchronisieren`,
+            makeCardAdmin: {one: 'Zum Karten-Admin machen', other: 'Karten-Admins festlegen'},
+            cardAdmins: 'Karten-Admins',
         },
         card: {
             getStartedIssuing: 'Beginne, indem du deine erste virtuelle oder physische Karte ausstellst.',
@@ -7037,6 +7042,12 @@ Fordern Sie Spesendetails wie Belege und Beschreibungen an, legen Sie Limits und
                 onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
                     `<muted-text>Die Rechnungsstellung ist in den Collect- und Control-Tarifen verfügbar, beginnend ab <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `pro Mitglied und Monat.` : `pro aktivem Mitglied und Monat.`}</muted-text>`,
             },
+            controlPolicyRoles: {
+                title: 'Rollen für Richtliniensteuerung',
+                description: 'Verwenden Sie spezialisierte Rollen wie Auditor und Karten-Admin, um Mitgliedern nur den Zugriff zu gewähren, den sie benötigen.',
+                onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
+                    `<muted-text>Spezialisierte Arbeitsbereichsrollen sind nur im Control-Tarif verfügbar, beginnend bei <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `pro Mitglied und Monat.` : `pro aktivem Mitglied und Monat.`}</muted-text>`,
+            },
         },
         downgrade: {
             commonFeatures: {
@@ -8497,8 +8508,11 @@ Fügen Sie weitere Ausgabelimits hinzu, um den Cashflow Ihres Unternehmens zu sc
                     `Die Verbindung für ${feedName} ist unterbrochen. Um Kartenimporte wiederherzustellen, <a href='${workspaceCompanyCardRoute}'>melden Sie sich bei Ihrer Bank an</a>.`,
                 plaidBalanceFailure: ({maskedAccountNumber, walletRoute}: {maskedAccountNumber: string; walletRoute: string}) =>
                     `Die Plaid-Verbindung zu Ihrem Geschäftskonto ist unterbrochen. Bitte <a href='${walletRoute}'>verbinden Sie Ihr Bankkonto ${maskedAccountNumber} erneut</a>, damit Sie Ihre Expensify Karten weiterhin verwenden können.`,
-                addEmployee: (email: string, role: string, didJoinPolicy?: boolean) =>
-                    didJoinPolicy ? `${email} ist über den Arbeitsbereichs-Einladungslink beigetreten` : `${email} als ${role === 'member' ? 'a' : 'an'} ${role} hinzugefügt`,
+                addEmployee: (email: string, role: string, didJoinPolicy?: boolean) => {
+                    const translatedRole = String(translations.workspace.common.roleName(role)).toLowerCase();
+                    const article = role === CONST.POLICY.ROLE.AUDITOR ? 'an' : 'a';
+                    return didJoinPolicy ? `${email} ist über den Arbeitsbereichs-Einladungslink beigetreten` : `${email} wurde als ${article} ${translatedRole} hinzugefügt`;
+                },
                 updateRole: ({email, currentRole, newRole}: UpdateRoleParams) => `hat die Rolle von ${email} in ${newRole} geändert (zuvor ${currentRole})`,
                 updatedCustomField1: (email: string, newValue: string, previousValue: string) => {
                     if (!newValue) {
diff --git a/src/languages/es.ts b/src/languages/es.ts
index 459fecd25837..4107af9c5538 100644
--- a/src/languages/es.ts
+++ b/src/languages/es.ts
@@ -4021,27 +4021,30 @@ ${amount} para ${merchant} - ${date}`,
         verificationFailed: 'La verificación falló, por lo que necesitaremos documentos adicionales para verificarte a ti y a tu empresa',
         taxIDVerification: 'Verificación del ID fiscal',
         taxIDVerificationDescription: dedent(`
-        Por favor, sube uno de los siguientes archivos:
-        • Carta de asignación de TIN/EIN del IRS
-        • Confirmación de solicitud de TIN/EIN del IRS (normalmente indica "Congratulations! The EIN has been successfully assigned")
-        • Carta de exención fiscal del IRS que incluya el nombre de la empresa y el EIN`),
+            Por favor, sube uno de los siguientes archivos:
+            • Carta de asignación de TIN/EIN del IRS
+            • Confirmación de solicitud de TIN/EIN del IRS (normalmente indica "Congratulations! The EIN has been successfully assigned")
+            • Carta de exención fiscal del IRS que incluya el nombre de la empresa y el EIN
+        `),
         nameChangeDocument: 'Documento de cambio de nombre',
         nameChangeDocumentDescription: 'Si el nombre de tu empresa cambió desde que solicitaste el TIN/EIN, necesitamos este documento para verificar el número de ID fiscal proporcionado',
         companyAddressVerification: 'Verificación de la dirección de la empresa',
         companyAddressVerificationDescription: dedent(`
-        Por favor, sube uno de los siguientes archivos:
-        • Factura reciente de servicios públicos con nombre y dirección de la empresa
-        • Estado de cuenta bancario con nombre y dirección de la empresa
-        • Contrato de arrendamiento vigente con página de firmas que muestre el nombre y la dirección actual de la empresa
-        • Estado de seguro con nombre y dirección de la empresa
-        • Documento de asignación de TIN con nombre y dirección de la empresa`),
+            Por favor, sube uno de los siguientes archivos:
+            • Factura reciente de servicios públicos con nombre y dirección de la empresa
+            • Estado de cuenta bancario con nombre y dirección de la empresa
+            • Contrato de arrendamiento vigente con página de firmas que muestre el nombre y la dirección actual de la empresa
+            • Estado de seguro con nombre y dirección de la empresa
+            • Documento de asignación de TIN con nombre y dirección de la empresa
+        `),
         userAddressVerification: 'Verificación de dirección',
         userAddressVerificationDescription: dedent(`
-        Por favor, sube uno de los siguientes archivos:
-        • Tarjeta de registro de votante
-        • Licencia de conducir
-        • Estado de cuenta bancario
-        • Factura de servicios públicos`),
+            Por favor, sube uno de los siguientes archivos:
+            • Tarjeta de registro de votante
+            • Licencia de conducir
+            • Estado de cuenta bancario
+            • Factura de servicios públicos
+        `),
         userDOBVerification: 'Verificación de fecha de nacimiento',
         userDOBVerificationDescription: 'Por favor, sube una identificación emitida en EE. UU.',
         finishViaChat: 'Finalizar por chat',
@@ -4316,13 +4319,13 @@ ${amount} para ${merchant} - ${date}`,
             roleName: (role?: string) => {
                 switch (role) {
                     case CONST.POLICY.ROLE.ADMIN:
-                        return 'Administrador';
+                        return 'Administrador del espacio de trabajo';
                     case CONST.POLICY.ROLE.AUDITOR:
                         return 'Auditor';
                     case CONST.POLICY.ROLE.EDITOR:
                         return 'Editor';
                     case CONST.POLICY.ROLE.CARD_ADMIN:
-                        return 'Administrador de tarjeta';
+                        return 'Administrador de tarjetas';
                     case CONST.POLICY.ROLE.PEOPLE_ADMIN:
                         return 'Administrador de personas';
                     case CONST.POLICY.ROLE.PAYMENTS_ADMIN:
@@ -6105,7 +6108,7 @@ ${amount} para ${merchant} - ${date}`,
             invitedBySecondaryLogin: (secondaryLogin) => `Agregado por nombre de usuario secundario ${secondaryLogin}.`,
             workspaceMembersCount: (count) => `Total de miembros del espacio de trabajo: ${count}`,
             allMembers: 'Todos los miembros',
-            admins: 'Administradores',
+            admins: 'Administradores del espacio de trabajo',
             approvers: 'Aprobadores',
             auditors: 'Auditores',
             emptyRoleFilter: {
@@ -6127,6 +6130,8 @@ ${amount} para ${merchant} - ${date}`,
                 `${memberName} tiene un informe en proceso pendiente de acción. Pídele que complete la acción requerida antes de eliminarlo del espacio de trabajo.`,
             configureHRSync: (providerName: string) => `Configura la sincronización de ${providerName}.`,
             syncWithHR: (providerName: string) => `Sincronizar con ${providerName}`,
+            makeCardAdmin: {one: 'Hacer administrador de tarjetas', other: 'Hacer administradores de tarjetas'},
+            cardAdmins: 'Administradores de tarjetas',
         },
         accounting: {
             settings: 'configuración',
@@ -6965,6 +6970,12 @@ ${amount} para ${merchant} - ${date}`,
                 upgradeWorkspaceWarningForRestrictedPolicyCreationPrompt:
                     'Su empresa ha restringido la creación de espacios de trabajo. Por favor, contacte a un administrador para obtener ayuda.',
             },
+            controlPolicyRoles: {
+                title: 'Controlar roles de la política',
+                description: 'Usa roles especializados como Auditor y Administrador de tarjetas para dar a los miembros acceso solo a lo que necesitan.',
+                onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
+                    `<muted-text>Los roles especializados del espacio de trabajo solo están disponibles en el plan Controlar, a partir de <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `por miembro al mes.` : `por miembro activo al mes.`}</muted-text>`,
+            },
         },
         downgrade: {
             commonFeatures: {
@@ -8290,8 +8301,11 @@ ${amount} para ${merchant} - ${date}`,
                     `La conexión ${feedName} está rota. Para restaurar las importaciones de tarjetas, <a href='${workspaceCompanyCardRoute}'>inicia sesión en tu banco</a>.`,
                 plaidBalanceFailure: ({maskedAccountNumber, walletRoute}: {maskedAccountNumber: string; walletRoute: string}) =>
                     `la conexión Plaid con tu cuenta bancaria de empresa está rota. Por favor, <a href='${walletRoute}'>reconecta tu cuenta bancaria ${maskedAccountNumber}</a> para poder seguir usando tus Tarjetas Expensify.`,
-                addEmployee: (email: string, role: string, didJoinPolicy?: boolean) =>
-                    didJoinPolicy ? `${email} se unió mediante el enlace de invitación del espacio de trabajo` : `se añadió ${email} como ${role === 'member' ? 'a' : 'a un'} ${role}`,
+                addEmployee: (email: string, role: string, didJoinPolicy?: boolean) => {
+                    const translatedRole = String(translations.workspace.common.roleName(role)).toLowerCase();
+                    const article = role === CONST.POLICY.ROLE.AUDITOR ? 'un' : 'a';
+                    return didJoinPolicy ? `${email} se unió mediante el enlace de invitación del espacio de trabajo` : `añadió ${email} como ${article} ${translatedRole}`;
+                },
                 updateRole: ({email, currentRole, newRole}) => `actualizó el rol ${email} a ${newRole} (previamente ${currentRole})`,
                 updatedCustomField1: (email, newValue, previousValue) => {
                     if (!newValue) {
diff --git a/src/languages/fr.ts b/src/languages/fr.ts
index 141e0e68d167..db4dfccd1f18 100644
--- a/src/languages/fr.ts
+++ b/src/languages/fr.ts
@@ -4152,28 +4152,31 @@ ${amount} pour ${merchant} - ${date}`,
         verificationFailed: 'La vérification a échoué, nous aurons donc besoin de documents supplémentaires pour te vérifier ainsi que ton entreprise',
         taxIDVerification: 'Vérification de l’identifiant fiscal',
         taxIDVerificationDescription: dedent(`
-        Veuillez téléverser l’un des fichiers suivants :
-        • Lettre d’attribution TIN/EIN de l’IRS
-        • Confirmation de demande TIN/EIN de l’IRS (indique généralement « Congratulations! The EIN has been successfully assigned »)
-        • Lettre d’exonération fiscale de l’IRS indiquant le nom de l’entreprise et l’EIN`),
+            Veuillez téléverser l’un des fichiers suivants :
+            • Lettre d’attribution TIN/EIN de l’IRS
+            • Confirmation de demande TIN/EIN de l’IRS (indique généralement « Congratulations! The EIN has been successfully assigned »)
+            • Lettre d’exonération fiscale de l’IRS indiquant le nom de l’entreprise et l’EIN
+        `),
         nameChangeDocument: 'Document de changement de nom',
         nameChangeDocumentDescription:
             'Si le nom de ton entreprise a changé depuis la demande du TIN/EIN, ce document est nécessaire pour vérifier le numéro d’identification fiscale fourni',
         companyAddressVerification: 'Vérification de l’adresse de l’entreprise',
         companyAddressVerificationDescription: dedent(`
-        Veuillez téléverser l’un des fichiers suivants :
-        • Facture récente de services publics indiquant le nom et l’adresse de l’entreprise
-        • Relevé bancaire indiquant le nom et l’adresse de l’entreprise
-        • Contrat de location en cours incluant la page de signature avec le nom et l’adresse actuelle de l’entreprise
-        • Attestation d’assurance indiquant le nom et l’adresse de l’entreprise
-        • Document d’attribution TIN indiquant le nom et l’adresse de l’entreprise`),
+            Veuillez téléverser l’un des fichiers suivants :
+            • Facture récente de services publics indiquant le nom et l’adresse de l’entreprise
+            • Relevé bancaire indiquant le nom et l’adresse de l’entreprise
+            • Contrat de location en cours incluant la page de signature avec le nom et l’adresse actuelle de l’entreprise
+            • Attestation d’assurance indiquant le nom et l’adresse de l’entreprise
+            • Document d’attribution TIN indiquant le nom et l’adresse de l’entreprise
+        `),
         userAddressVerification: 'Vérification de l’adresse',
         userAddressVerificationDescription: dedent(`
-        Veuillez téléverser l’un des fichiers suivants :
-        • Carte d’inscription électorale
-        • Permis de conduire
-        • Relevé bancaire
-        • Facture de services publics`),
+            Veuillez téléverser l’un des fichiers suivants :
+            • Carte d’inscription électorale
+            • Permis de conduire
+            • Relevé bancaire
+            • Facture de services publics
+        `),
         userDOBVerification: 'Vérification de la date de naissance',
         userDOBVerificationDescription: 'Veuillez téléverser une pièce d’identité délivrée aux États-Unis',
         finishViaChat: 'Finaliser via le chat',
@@ -4438,7 +4441,7 @@ ${amount} pour ${merchant} - ${date}`,
             roleName: (role?: string) => {
                 switch (role) {
                     case CONST.POLICY.ROLE.ADMIN:
-                        return 'Administrateur';
+                        return 'Administrateur d’espace de travail';
                     case CONST.POLICY.ROLE.AUDITOR:
                         return 'Auditeur';
                     case CONST.POLICY.ROLE.EDITOR:
@@ -4446,7 +4449,7 @@ ${amount} pour ${merchant} - ${date}`,
                     case CONST.POLICY.ROLE.CARD_ADMIN:
                         return 'Administrateur de carte';
                     case CONST.POLICY.ROLE.PEOPLE_ADMIN:
-                        return 'Administration des personnes';
+                        return 'Admin personnes';
                     case CONST.POLICY.ROLE.PAYMENTS_ADMIN:
                         return 'Administrateur des paiements';
                     case CONST.POLICY.ROLE.USER:
@@ -6305,12 +6308,14 @@ _Pour des instructions plus détaillées, [visitez notre site d’aide](${CONST.
             cannotRemoveUserDueToReport: ({memberName}: {memberName: string}) =>
                 `${memberName} a une note de frais en cours de traitement sur laquelle il doit agir. Veuillez lui demander d’effectuer l’action requise avant de le retirer de l’espace de travail.`,
             allMembers: 'Tous les membres',
-            admins: 'Administrateurs',
+            admins: 'Administrateurs de l’espace de travail',
             approvers: 'Approbateurs',
             auditors: 'Auditeurs',
             emptyRoleFilter: {title: 'Aucun membre ne correspond à ce filtre', subtitle: 'Invitez un membre ou modifiez le filtre ci-dessus.'},
             configureHRSync: (providerName: string) => `Configurer la synchronisation ${providerName}.`,
             syncWithHR: (providerName: string) => `Synchroniser avec ${providerName}`,
+            makeCardAdmin: {one: 'Nommer administrateur de carte', other: 'Nommer des administrateurs de carte'},
+            cardAdmins: 'Administrateurs de cartes',
         },
         card: {
             getStartedIssuing: 'Commencez par émettre votre première carte virtuelle ou physique.',
@@ -7065,6 +7070,12 @@ Rendez obligatoires des informations de dépense comme les reçus et les descrip
                 onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
                     `<muted-text>La facturation est disponible avec les offres Collect et Control, à partir de <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `par membre et par mois.` : `par membre actif et par mois.`}</muted-text>`,
             },
+            controlPolicyRoles: {
+                title: 'Contrôler les rôles de politique',
+                description: 'Utilisez des rôles spécialisés comme Auditeur et Administrateur de cartes pour donner aux membres accès uniquement à ce dont ils ont besoin.',
+                onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
+                    `<muted-text>Les rôles spécialisés dans l’espace de travail sont uniquement disponibles avec l’offre Control, à partir de <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `par membre et par mois.` : `par membre actif et par mois.`}</muted-text>`,
+            },
         },
         downgrade: {
             commonFeatures: {
@@ -8532,8 +8543,11 @@ Ajoutez davantage de règles de dépenses pour protéger la trésorerie de l’e
                     `La connexion ${feedName} est interrompue. Pour rétablir l’importation des cartes, <a href='${workspaceCompanyCardRoute}'>connectez-vous à votre banque</a>.`,
                 plaidBalanceFailure: ({maskedAccountNumber, walletRoute}: {maskedAccountNumber: string; walletRoute: string}) =>
                     `la connexion Plaid à votre compte bancaire professionnel est rompue. Veuillez <a href='${walletRoute}'>reconnecter votre compte bancaire ${maskedAccountNumber}</a> afin de pouvoir continuer à utiliser vos Cartes Expensify.`,
-                addEmployee: (email: string, role: string, didJoinPolicy?: boolean) =>
-                    didJoinPolicy ? `${email} a rejoint via le lien d’invitation de l’espace de travail` : `a ajouté ${email} en tant que ${role === 'member' ? 'a' : 'un'} ${role}`,
+                addEmployee: (email: string, role: string, didJoinPolicy?: boolean) => {
+                    const translatedRole = String(translations.workspace.common.roleName(role)).toLowerCase();
+                    const article = role === CONST.POLICY.ROLE.AUDITOR ? 'un' : 'a';
+                    return didJoinPolicy ? `${email} a rejoint via le lien d’invitation de l’espace de travail` : `a ajouté ${email} en tant que ${article} ${translatedRole}`;
+                },
                 updateRole: ({email, currentRole, newRole}: UpdateRoleParams) => `a mis à jour le rôle de ${email} en ${newRole} (précédemment ${currentRole})`,
                 updatedCustomField1: (email: string, newValue: string, previousValue: string) => {
                     if (!newValue) {
diff --git a/src/languages/it.ts b/src/languages/it.ts
index 7d2ec7147746..cba6775a290b 100644
--- a/src/languages/it.ts
+++ b/src/languages/it.ts
@@ -4127,28 +4127,31 @@ ${amount} per ${merchant} - ${date}`,
         verificationFailed: 'La verifica non è riuscita, quindi avremo bisogno di documenti aggiuntivi per verificare te e la tua azienda',
         taxIDVerification: 'Verifica dell’ID fiscale',
         taxIDVerificationDescription: dedent(`
-        Carica uno dei seguenti file:
-        • Lettera di assegnazione TIN/EIN dell’IRS
-        • Conferma della richiesta TIN/EIN dell’IRS (di solito indica "Congratulations! The EIN has been successfully assigned")
-        • Lettera di esenzione fiscale dell’IRS con nome dell’azienda ed EIN`),
+            Carica uno dei seguenti file:
+            • Lettera di assegnazione TIN/EIN dell’IRS
+            • Conferma della richiesta TIN/EIN dell’IRS (di solito indica "Congratulations! The EIN has been successfully assigned")
+            • Lettera di esenzione fiscale dell’IRS con nome dell’azienda ed EIN
+        `),
         nameChangeDocument: 'Documento di cambio nome',
         nameChangeDocumentDescription:
             'Se il nome della tua azienda è cambiato dopo la richiesta del TIN/EIN, abbiamo bisogno di questo documento per verificare il numero di ID fiscale fornito',
         companyAddressVerification: 'Verifica dell’indirizzo aziendale',
         companyAddressVerificationDescription: dedent(`
-        Carica uno dei seguenti file:
-        • Bolletta recente con nome e indirizzo dell’azienda
-        • Estratto conto bancario con nome e indirizzo dell’azienda
-        • Contratto di locazione attuale con pagina firme che mostri nome e indirizzo attuale dell’azienda
-        • Documento assicurativo con nome e indirizzo dell’azienda
-        • Documento di assegnazione TIN con nome e indirizzo dell’azienda`),
+            Carica uno dei seguenti file:
+            • Bolletta recente con nome e indirizzo dell’azienda
+            • Estratto conto bancario con nome e indirizzo dell’azienda
+            • Contratto di locazione attuale con pagina firme che mostri nome e indirizzo attuale dell’azienda
+            • Documento assicurativo con nome e indirizzo dell’azienda
+            • Documento di assegnazione TIN con nome e indirizzo dell’azienda
+        `),
         userAddressVerification: 'Verifica dell’indirizzo',
         userAddressVerificationDescription: dedent(`
-        Carica uno dei seguenti file:
-        • Tessera elettorale
-        • Patente di guida
-        • Estratto conto bancario
-        • Bolletta`),
+            Carica uno dei seguenti file:
+            • Tessera elettorale
+            • Patente di guida
+            • Estratto conto bancario
+            • Bolletta
+        `),
         userDOBVerification: 'Verifica della data di nascita',
         userDOBVerificationDescription: 'Carica un documento di identità rilasciato negli Stati Uniti',
         finishViaChat: 'Completa via chat',
@@ -4412,7 +4415,7 @@ ${amount} per ${merchant} - ${date}`,
             roleName: (role?: string) => {
                 switch (role) {
                     case CONST.POLICY.ROLE.ADMIN:
-                        return 'Amministratore';
+                        return 'Amministratore spazio di lavoro';
                     case CONST.POLICY.ROLE.AUDITOR:
                         return 'Revisore';
                     case CONST.POLICY.ROLE.EDITOR:
@@ -4422,7 +4425,7 @@ ${amount} per ${merchant} - ${date}`,
                     case CONST.POLICY.ROLE.PEOPLE_ADMIN:
                         return 'Amministrazione persone';
                     case CONST.POLICY.ROLE.PAYMENTS_ADMIN:
-                        return 'Amministrazione pagamenti';
+                        return 'Amministratore pagamenti';
                     case CONST.POLICY.ROLE.USER:
                         return 'Membro';
                     default:
@@ -6268,12 +6271,14 @@ _Per istruzioni più dettagliate, [visita il nostro sito di assistenza](${CONST.
             cannotRemoveUserDueToReport: ({memberName}: {memberName: string}) =>
                 `${memberName} ha un rapporto in sospeso su cui deve intervenire. Chiedi loro di completare l’azione richiesta prima di rimuoverlə dallo spazio di lavoro.`,
             allMembers: 'Tutti i membri',
-            admins: 'Amministratori',
+            admins: 'Amministratori dello spazio di lavoro',
             approvers: 'Approvatori',
             auditors: 'Revisori',
             emptyRoleFilter: {title: 'Nessun membro corrisponde a questo filtro', subtitle: 'Invita un membro o modifica il filtro qui sopra.'},
             configureHRSync: (providerName: string) => `Configura la sincronizzazione di ${providerName}.`,
             syncWithHR: (providerName: string) => `Sincronizza con ${providerName}`,
+            makeCardAdmin: {one: 'Rendi amministratore carta', other: 'Rendi amministratori carta'},
+            cardAdmins: 'Amministratori carta',
         },
         card: {
             getStartedIssuing: 'Inizia emettendo la tua prima carta virtuale o fisica.',
@@ -7021,6 +7026,12 @@ Richiedi dettagli sulle spese come ricevute e descrizioni, imposta limiti e valo
                 onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
                     `<muted-text>La fatturazione è disponibile nei piani Collect e Control, a partire da <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `per membro al mese.` : `per membro attivo al mese.`}</muted-text>`,
             },
+            controlPolicyRoles: {
+                title: 'Ruoli dei criteri di controllo',
+                description: 'Usa ruoli specializzati come Revisore e Amministratore carte per concedere ai membri l’accesso solo a ciò di cui hanno bisogno.',
+                onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
+                    `<muted-text>I ruoli specializzati dello spazio di lavoro sono disponibili solo con il piano Control, a partire da <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `per membro al mese.` : `per membro attivo al mese.`}</muted-text>`,
+            },
         },
         downgrade: {
             commonFeatures: {
@@ -8486,8 +8497,11 @@ Aggiungi altre regole di spesa per proteggere il flusso di cassa aziendale.`,
                     `La connessione ${feedName} è interrotta. Per ripristinare le importazioni della carta, <a href='${workspaceCompanyCardRoute}'>accedi alla tua banca</a>.`,
                 plaidBalanceFailure: ({maskedAccountNumber, walletRoute}: {maskedAccountNumber: string; walletRoute: string}) =>
                     `la connessione Plaid al conto bancario della tua azienda non funziona. Per favore, <a href='${walletRoute}'>ricollega il conto bancario ${maskedAccountNumber}</a> così puoi continuare a usare le tue Carte Expensify.`,
-                addEmployee: (email: string, role: string, didJoinPolicy?: boolean) =>
-                    didJoinPolicy ? `${email} si è unito tramite il link di invito allo spazio di lavoro` : `ha aggiunto ${email} come ${role === 'member' ? 'a' : 'un'} ${role}`,
+                addEmployee: (email: string, role: string, didJoinPolicy?: boolean) => {
+                    const translatedRole = String(translations.workspace.common.roleName(role)).toLowerCase();
+                    const article = role === CONST.POLICY.ROLE.AUDITOR ? 'un' : 'a';
+                    return didJoinPolicy ? `${email} si è unito tramite il link di invito allo spazio di lavoro` : `ha aggiunto ${email} come ${article} ${translatedRole}`;
+                },
                 updateRole: ({email, currentRole, newRole}: UpdateRoleParams) => `ha aggiornato il ruolo di ${email} a ${newRole} (in precedenza ${currentRole})`,
                 updatedCustomField1: (email: string, newValue: string, previousValue: string) => {
                     if (!newValue) {
diff --git a/src/languages/ja.ts b/src/languages/ja.ts
index 53b23c695e98..a4d64c20b681 100644
--- a/src/languages/ja.ts
+++ b/src/languages/ja.ts
@@ -4099,27 +4099,30 @@ ${integrationName === CONST.ONBOARDING_ACCOUNTING_MAPPING.other ? 'あなたの'
         verificationFailed: '確認に失敗したため、追加の書類で本人および事業の確認が必要です',
         taxIDVerification: '納税者番号の確認',
         taxIDVerificationDescription: dedent(`
-        以下のいずれかの書類をアップロードしてください：
-        • IRS TIN/EIN 割当通知書
-        • IRS TIN/EIN 申請確認書（通常「Congratulations! The EIN has been successfully assigned」と記載）
-        • 会社名と EIN が記載された IRS の免税通知書`),
+            以下のいずれかの書類をアップロードしてください：
+            • IRS TIN/EIN 割当通知書
+            • IRS TIN/EIN 申請確認書（通常「Congratulations! The EIN has been successfully assigned」と記載）
+            • 会社名と EIN が記載された IRS の免税通知書
+        `),
         nameChangeDocument: '名称変更書類',
         nameChangeDocumentDescription: 'TIN/EIN 申請後に会社名が変更された場合、提供された納税者番号を確認するためにこの書類が必要です',
         companyAddressVerification: '会社住所の確認',
         companyAddressVerificationDescription: dedent(`
-        以下のいずれかの書類をアップロードしてください：
-        • 会社名と住所が記載された最近の公共料金請求書
-        • 会社名と住所が記載された銀行取引明細書
-        • 署名ページを含む現行の賃貸契約書（会社名と現住所が記載されたもの）
-        • 会社名と住所が記載された保険証書
-        • 会社名と住所が記載された TIN 割当書類`),
+            以下のいずれかの書類をアップロードしてください：
+            • 会社名と住所が記載された最近の公共料金請求書
+            • 会社名と住所が記載された銀行取引明細書
+            • 署名ページを含む現行の賃貸契約書（会社名と現住所が記載されたもの）
+            • 会社名と住所が記載された保険証書
+            • 会社名と住所が記載された TIN 割当書類
+        `),
         userAddressVerification: '住所確認',
         userAddressVerificationDescription: dedent(`
-        以下のいずれかの書類をアップロードしてください：
-        • 有権者登録カード
-        • 運転免許証
-        • 銀行取引明細書
-        • 公共料金請求書`),
+            以下のいずれかの書類をアップロードしてください：
+            • 有権者登録カード
+            • 運転免許証
+            • 銀行取引明細書
+            • 公共料金請求書
+        `),
         userDOBVerification: '生年月日の確認',
         userDOBVerificationDescription: '米国発行の身分証明書をアップロードしてください',
         finishViaChat: 'チャットで完了',
@@ -4382,18 +4385,17 @@ ${integrationName === CONST.ONBOARDING_ACCOUNTING_MAPPING.other ? 'あなたの'
             roleName: (role?: string) => {
                 switch (role) {
                     case CONST.POLICY.ROLE.ADMIN:
-                        return '管理者';
+                        return 'ワークスペース管理者';
                     case CONST.POLICY.ROLE.AUDITOR:
                         return '監査人';
                     case CONST.POLICY.ROLE.EDITOR:
                         return '編集者';
-                        return '監査担当者';
                     case CONST.POLICY.ROLE.CARD_ADMIN:
                         return 'カード管理者';
                     case CONST.POLICY.ROLE.PEOPLE_ADMIN:
                         return 'メンバー管理';
                     case CONST.POLICY.ROLE.PAYMENTS_ADMIN:
-                        return '支払管理者';
+                        return '支払い管理者';
                     case CONST.POLICY.ROLE.USER:
                         return 'メンバー';
                     default:
@@ -6198,12 +6200,14 @@ _詳しい手順については、[ヘルプサイトをご覧ください](${CO
             cannotRemoveUserDueToReport: ({memberName}: {memberName: string}) =>
                 `${memberName} は、対応が必要な未処理のレポートがあります。ワークスペースから削除する前に、必要な対応を完了するよう依頼してください。`,
             allMembers: 'すべてのメンバー',
-            admins: '管理者',
+            admins: 'ワークスペース管理者',
             approvers: '承認者',
             auditors: '監査担当者',
             emptyRoleFilter: {title: 'このフィルターに一致するメンバーはいません', subtitle: 'メンバーを招待するか、上のフィルターを変更してください。'},
             configureHRSync: (providerName: string) => `${providerName} の同期を設定します。`,
             syncWithHR: (providerName: string) => `${providerName}と同期`,
+            makeCardAdmin: {one: 'カード管理者にする', other: 'カード管理者に設定'},
+            cardAdmins: 'カード管理者',
         },
         card: {
             getStartedIssuing: 'まずは最初のバーチャルカードまたは物理カードを発行しましょう。',
@@ -6943,6 +6947,12 @@ ${reportName}
                 onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
                     `<muted-text>請求書発行機能は、Collect プランと Control プランでご利用いただけます。<strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `メンバー1人あたり月額` : `アクティブメンバー1人あたり月額`}からご利用可能です。</muted-text>`,
             },
+            controlPolicyRoles: {
+                title: 'コントロールポリシーのロール',
+                description: '監査人やカード管理者などの専用ロールを使って、メンバーが必要なものにだけアクセスできるようにします。',
+                onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
+                    `<muted-text>特別なワークスペースロールは Control プランでのみご利用いただけます（<strong>${formattedPrice}</strong> から、${hasTeam2025Pricing ? `メンバー1人あたり月額。` : `アクティブメンバー1人あたり／月`}）。</muted-text>`,
+            },
         },
         downgrade: {
             commonFeatures: {
@@ -8379,8 +8389,11 @@ ${reportName}
                     `${feedName} との接続が切断されています。カードの取引明細の取込を再開するには、<a href='${workspaceCompanyCardRoute}'>銀行にログイン</a>してください。`,
                 plaidBalanceFailure: ({maskedAccountNumber, walletRoute}: {maskedAccountNumber: string; walletRoute: string}) =>
                     `Plaid によるビジネス銀行口座との接続が切断されています。Expensify カードを引き続きご利用いただくために、<a href='${walletRoute}'>銀行口座 ${maskedAccountNumber} を再接続</a>してください。`,
-                addEmployee: (email: string, role: string, didJoinPolicy?: boolean) =>
-                    didJoinPolicy ? `${email} さんがワークスペースの招待リンクから参加しました` : `${role === 'member' ? 'a' : '1つの'} ${role} として ${email} を追加しました`,
+                addEmployee: (email: string, role: string, didJoinPolicy?: boolean) => {
+                    const translatedRole = String(translations.workspace.common.roleName(role)).toLowerCase();
+                    const article = role === CONST.POLICY.ROLE.AUDITOR ? '1つの' : 'a';
+                    return didJoinPolicy ? `${email} さんがワークスペースの招待リンクから参加しました` : `${email} を ${article} ${translatedRole} として追加しました`;
+                },
                 updateRole: ({email, currentRole, newRole}: UpdateRoleParams) => `${email} のロールを ${currentRole} から ${newRole} に更新しました`,
                 updatedCustomField1: (email: string, newValue: string, previousValue: string) => {
                     if (!newValue) {
diff --git a/src/languages/nl.ts b/src/languages/nl.ts
index 249cc7fb942f..803e591df534 100644
--- a/src/languages/nl.ts
+++ b/src/languages/nl.ts
@@ -4123,27 +4123,30 @@ ${amount} voor ${merchant} - ${date}`,
         verificationFailed: 'De verificatie is mislukt, daarom hebben we extra documenten nodig om jou en je bedrijf te verifiëren',
         taxIDVerification: 'Belastingnummerverificatie',
         taxIDVerificationDescription: dedent(`
-        Upload een van de volgende bestanden:
-        • IRS TIN/EIN-toewijzingsbrief
-        • IRS TIN/EIN-aanvraagbevestiging (bevat meestal "Congratulations! The EIN has been successfully assigned")
-        • IRS-belastingvrijstellingsbrief met bedrijfsnaam en EIN`),
+            Upload een van de volgende bestanden:
+            • IRS TIN/EIN-toewijzingsbrief
+            • IRS TIN/EIN-aanvraagbevestiging (bevat meestal "Congratulations! The EIN has been successfully assigned")
+            • IRS-belastingvrijstellingsbrief met bedrijfsnaam en EIN
+        `),
         nameChangeDocument: 'Document naamswijziging',
         nameChangeDocumentDescription: 'Als de naam van je bedrijf is gewijzigd sinds de TIN/EIN-aanvraag, hebben we dit document nodig om het opgegeven belastingnummer te verifiëren',
         companyAddressVerification: 'Verificatie van bedrijfsadres',
         companyAddressVerificationDescription: dedent(`
-        Upload een van de volgende bestanden:
-        • Recente energierekening met bedrijfsnaam en adres
-        • Bankafschrift met bedrijfsnaam en adres
-        • Huidige huur- of leaseovereenkomst inclusief ondertekeningspagina met bedrijfsnaam en huidig adres
-        • Verzekeringsverklaring met bedrijfsnaam en adres
-        • TIN-toewijzingsdocument met bedrijfsnaam en adres`),
+            Upload een van de volgende bestanden:
+            • Recente energierekening met bedrijfsnaam en adres
+            • Bankafschrift met bedrijfsnaam en adres
+            • Huidige huur- of leaseovereenkomst inclusief ondertekeningspagina met bedrijfsnaam en huidig adres
+            • Verzekeringsverklaring met bedrijfsnaam en adres
+            • TIN-toewijzingsdocument met bedrijfsnaam en adres
+        `),
         userAddressVerification: 'Adresverificatie',
         userAddressVerificationDescription: dedent(`
-        Upload een van de volgende bestanden:
-        • Kiezersregistratiekaart
-        • Rijbewijs
-        • Bankafschrift
-        • Energierekening`),
+            Upload een van de volgende bestanden:
+            • Kiezersregistratiekaart
+            • Rijbewijs
+            • Bankafschrift
+            • Energierekening
+        `),
         userDOBVerification: 'Verificatie van geboortedatum',
         userDOBVerificationDescription: 'Upload een in de VS uitgegeven identiteitsbewijs',
         finishViaChat: 'Afronden via chat',
@@ -4407,7 +4410,7 @@ ${amount} voor ${merchant} - ${date}`,
             roleName: (role?: string) => {
                 switch (role) {
                     case CONST.POLICY.ROLE.ADMIN:
-                        return 'Beheer';
+                        return 'Werkruimtebeheerder';
                     case CONST.POLICY.ROLE.AUDITOR:
                         return 'Auditor';
                     case CONST.POLICY.ROLE.EDITOR:
@@ -4415,7 +4418,7 @@ ${amount} voor ${merchant} - ${date}`,
                     case CONST.POLICY.ROLE.CARD_ADMIN:
                         return 'Kaartbeheer';
                     case CONST.POLICY.ROLE.PEOPLE_ADMIN:
-                        return 'Mensenbeheer';
+                        return 'Personenbeheer';
                     case CONST.POLICY.ROLE.PAYMENTS_ADMIN:
                         return 'Beheerder betalingen';
                     case CONST.POLICY.ROLE.USER:
@@ -6246,12 +6249,14 @@ _Voor meer gedetailleerde instructies, [bezoek onze help-site](${CONST.NETSUITE_
             cannotRemoveUserDueToReport: ({memberName}: {memberName: string}) =>
                 `${memberName} heeft een openstaand rapport in verwerking waarop actie moet worden ondernomen. Vraag hen dit vereiste actiepunt af te ronden voordat je hen uit de workspace verwijdert.`,
             allMembers: 'Alle leden',
-            admins: 'Beheerders',
+            admins: 'Workspace-beheerders',
             approvers: 'Fiatteurs',
             auditors: 'Accountants',
             emptyRoleFilter: {title: 'Geen leden komen overeen met dit filter', subtitle: 'Nodig een lid uit of wijzig het filter hierboven.'},
             configureHRSync: (providerName: string) => `Stel ${providerName}-synchronisatie in.`,
             syncWithHR: (providerName: string) => `Synchroniseren met ${providerName}`,
+            makeCardAdmin: {one: 'Kaartbeheerder maken', other: 'Kaartbeheerders maken'},
+            cardAdmins: 'Kaartbeheerders',
         },
         card: {
             getStartedIssuing: 'Begin met het uitgeven van je eerste virtuele of fysieke kaart.',
@@ -6997,6 +7002,12 @@ Vereis onkostendetails zoals bonnen en beschrijvingen, stel limieten en standaar
                 onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
                     `<muted-text>Facturatie is beschikbaar in de Collect- en Control-abonnementen, vanaf <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `per lid per maand.` : `per actieve deelnemer per maand.`}</muted-text>`,
             },
+            controlPolicyRoles: {
+                title: 'Beleidsrollen controleren',
+                description: 'Gebruik gespecialiseerde rollen zoals Auditor en Kaartbeheerder om leden alleen toegang te geven tot wat ze nodig hebben.',
+                onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
+                    `<muted-text>Gespecialiseerde werkruimterollen zijn alleen beschikbaar in het Control-abonnement, vanaf <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `per lid per maand.` : `per actief lid per maand.`}</muted-text>`,
+            },
         },
         downgrade: {
             commonFeatures: {
@@ -8453,8 +8464,11 @@ er bestedingsregels toe om de kasstroom van het bedrijf te beschermen.`,
                     `De verbinding met ${feedName} is verbroken. <a href='${workspaceCompanyCardRoute}'>Log in bij je bank</a> om kaartimports te herstellen.`,
                 plaidBalanceFailure: ({maskedAccountNumber, walletRoute}: {maskedAccountNumber: string; walletRoute: string}) =>
                     `de Plaid-verbinding met je zakelijke bankrekening is verbroken. <a href='${walletRoute}'>Verbind je bankrekening ${maskedAccountNumber} opnieuw</a> zodat je je Expensify Kaarten kunt blijven gebruiken.`,
-                addEmployee: (email: string, role: string, didJoinPolicy?: boolean) =>
-                    didJoinPolicy ? `${email} is via de werkruimte-uitnodigingslink lid geworden` : `heeft ${email} toegevoegd als ${role === 'member' ? 'een' : 'een'} ${role}`,
+                addEmployee: (email: string, role: string, didJoinPolicy?: boolean) => {
+                    const translatedRole = String(translations.workspace.common.roleName(role)).toLowerCase();
+                    const article = role === CONST.POLICY.ROLE.AUDITOR ? 'een' : 'een';
+                    return didJoinPolicy ? `${email} is lid geworden via de uitnodigingslink voor de workspace` : `${email} toegevoegd als ${article} ${translatedRole}`;
+                },
                 updateRole: ({email, currentRole, newRole}: UpdateRoleParams) => `heeft de rol van ${email} bijgewerkt naar ${newRole} (voorheen ${currentRole})`,
                 updatedCustomField1: (email: string, newValue: string, previousValue: string) => {
                     if (!newValue) {
diff --git a/src/languages/pl.ts b/src/languages/pl.ts
index b348de513305..3701ca73b0f9 100644
--- a/src/languages/pl.ts
+++ b/src/languages/pl.ts
@@ -4115,27 +4115,30 @@ ${amount} dla ${merchant} - ${date}`,
         verificationFailed: 'Weryfikacja nie powiodła się, dlatego potrzebujemy dodatkowych dokumentów do potwierdzenia Twojej tożsamości i firmy',
         taxIDVerification: 'Weryfikacja numeru podatkowego',
         taxIDVerificationDescription: dedent(`
-        Prześlij jeden z poniższych plików:
-        • List przydziału TIN/EIN z IRS
-        • Potwierdzenie wniosku TIN/EIN z IRS (zwykle zawiera „Congratulations! The EIN has been successfully assigned”)
-        • Pismo o zwolnieniu podatkowym z IRS zawierające nazwę firmy i EIN`),
+            Prześlij jeden z poniższych plików:
+            • List przydziału TIN/EIN z IRS
+            • Potwierdzenie wniosku TIN/EIN z IRS (zwykle zawiera „Congratulations! The EIN has been successfully assigned”)
+            • Pismo o zwolnieniu podatkowym z IRS zawierające nazwę firmy i EIN
+        `),
         nameChangeDocument: 'Dokument zmiany nazwy',
         nameChangeDocumentDescription: 'Jeśli nazwa firmy zmieniła się od momentu złożenia wniosku o TIN/EIN, dokument ten jest wymagany do weryfikacji podanego numeru podatkowego',
         companyAddressVerification: 'Weryfikacja adresu firmy',
         companyAddressVerificationDescription: dedent(`
-        Prześlij jeden z poniższych plików:
-        • Aktualny rachunek za media z nazwą i adresem firmy
-        • Wyciąg bankowy z nazwą i adresem firmy
-        • Aktualna umowa najmu z podpisaną stroną zawierającą nazwę i adres firmy
-        • Dokument ubezpieczeniowy z nazwą i adresem firmy
-        • Dokument przydziału TIN z nazwą i adresem firmy`),
+            Prześlij jeden z poniższych plików:
+            • Aktualny rachunek za media z nazwą i adresem firmy
+            • Wyciąg bankowy z nazwą i adresem firmy
+            • Aktualna umowa najmu z podpisaną stroną zawierającą nazwę i adres firmy
+            • Dokument ubezpieczeniowy z nazwą i adresem firmy
+            • Dokument przydziału TIN z nazwą i adresem firmy
+        `),
         userAddressVerification: 'Weryfikacja adresu',
         userAddressVerificationDescription: dedent(`
-        Prześlij jeden z poniższych plików:
-        • Karta rejestracji wyborcy
-        • Prawo jazdy
-        • Wyciąg bankowy
-        • Rachunek za media`),
+            Prześlij jeden z poniższych plików:
+            • Karta rejestracji wyborcy
+            • Prawo jazdy
+            • Wyciąg bankowy
+            • Rachunek za media
+        `),
         userDOBVerification: 'Weryfikacja daty urodzenia',
         userDOBVerificationDescription: 'Prześlij dokument tożsamości wydany w USA',
         finishViaChat: 'Zakończ przez czat',
@@ -4399,7 +4402,7 @@ ${amount} dla ${merchant} - ${date}`,
             roleName: (role?: string) => {
                 switch (role) {
                     case CONST.POLICY.ROLE.ADMIN:
-                        return 'Administrator';
+                        return 'Administrator przestrzeni roboczej';
                     case CONST.POLICY.ROLE.AUDITOR:
                         return 'Audytor';
                     case CONST.POLICY.ROLE.EDITOR:
@@ -6241,12 +6244,14 @@ _Aby uzyskać bardziej szczegółowe instrukcje, [odwiedź naszą stronę pomocy
             cannotRemoveUserDueToReport: ({memberName}: {memberName: string}) =>
                 `${memberName} ma nierozliczony raport w trakcie przetwarzania, który wymaga działania. Poproś tę osobę o wykonanie wymaganej czynności przed jej usunięciem z przestrzeni roboczej.`,
             allMembers: 'Wszyscy członkowie',
-            admins: 'Administratorzy',
+            admins: 'Administratorzy przestrzeni roboczej',
             approvers: 'Osoby zatwierdzające',
             auditors: 'Audytorzy',
             emptyRoleFilter: {title: 'Żadni członkowie nie pasują do tego filtra', subtitle: 'Zaproś członka lub zmień filtr powyżej.'},
             configureHRSync: (providerName: string) => `Skonfiguruj synchronizację ${providerName}.`,
             syncWithHR: (providerName: string) => `Synchronizuj z ${providerName}`,
+            makeCardAdmin: {one: 'Ustaw jako administratora karty', other: 'Ustaw administratorów kart'},
+            cardAdmins: 'Administratorzy kart',
         },
         card: {
             getStartedIssuing: 'Zacznij od wydania swojej pierwszej wirtualnej lub fizycznej karty.',
@@ -6993,6 +6998,12 @@ Wymagaj szczegółów wydatków, takich jak paragony i opisy, ustawiaj limity i
                 onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
                     `<muted-text>Fakturowanie jest dostępne w planach Collect i Control, zaczynając od <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `za członka za miesiąc.` : `za aktywnego członka miesięcznie.`}</muted-text>`,
             },
+            controlPolicyRoles: {
+                title: 'Role zasad kontroli',
+                description: 'Użyj wyspecjalizowanych ról, takich jak Audytor i Administrator kart, żeby dać członkom dostęp tylko do tego, czego potrzebują.',
+                onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
+                    `<muted-text>Specjalistyczne role w przestrzeni roboczej są dostępne tylko w planie Control, od <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `za członka miesięcznie.` : `za aktywnego członka miesięcznie.`}</muted-text>`,
+            },
         },
         downgrade: {
             commonFeatures: {
@@ -8445,8 +8456,11 @@ Dodaj więcej zasad wydatków, żeby chronić płynność finansową firmy.`,
                     `Połączenie ${feedName} jest przerwane. Aby przywrócić importy kart, <a href='${workspaceCompanyCardRoute}'>zaloguj się do swojego banku</a>.`,
                 plaidBalanceFailure: ({maskedAccountNumber, walletRoute}: {maskedAccountNumber: string; walletRoute: string}) =>
                     `połączenie Plaid z twoim firmowym kontem bankowym jest przerwane. Proszę, <a href='${walletRoute}'>połącz ponownie swoje konto bankowe ${maskedAccountNumber}</a>, aby móc dalej używać Kart Expensify.`,
-                addEmployee: (email: string, role: string, didJoinPolicy?: boolean) =>
-                    didJoinPolicy ? `${email} dołączył(a) przez link z zaproszeniem do przestrzeni roboczej` : `dodano ${email} jako ${role === 'member' ? 'a' : 'jeden'} ${role}`,
+                addEmployee: (email: string, role: string, didJoinPolicy?: boolean) => {
+                    const translatedRole = String(translations.workspace.common.roleName(role)).toLowerCase();
+                    const article = role === CONST.POLICY.ROLE.AUDITOR ? 'an' : 'a';
+                    return didJoinPolicy ? `${email} dołączył za pomocą linku z zaproszeniem do przestrzeni roboczej` : `dodano ${email} jako ${article} ${translatedRole}`;
+                },
                 updateRole: ({email, currentRole, newRole}: UpdateRoleParams) => `zaktualizowano rolę użytkownika ${email} na ${newRole} (wcześniej ${currentRole})`,
                 updatedCustomField1: (email: string, newValue: string, previousValue: string) => {
                     if (!newValue) {
diff --git a/src/languages/pt-BR.ts b/src/languages/pt-BR.ts
index 5b85581c34d0..795ffd274738 100644
--- a/src/languages/pt-BR.ts
+++ b/src/languages/pt-BR.ts
@@ -4115,27 +4115,30 @@ ${amount} para ${merchant} - ${date}`,
         verificationFailed: 'A verificação falhou, então precisaremos de documentos adicionais para verificar você e sua empresa',
         taxIDVerification: 'Verificação de ID fiscal',
         taxIDVerificationDescription: dedent(`
-        Envie um dos seguintes arquivos:
-        • Carta de atribuição de TIN/EIN do IRS
-        • Confirmação de solicitação de TIN/EIN do IRS (normalmente contém "Congratulations! The EIN has been successfully assigned")
-        • Carta de isenção fiscal do IRS com o nome da empresa e o EIN`),
+            Envie um dos seguintes arquivos:
+            • Carta de atribuição de TIN/EIN do IRS
+            • Confirmação de solicitação de TIN/EIN do IRS (normalmente contém "Congratulations! The EIN has been successfully assigned")
+            • Carta de isenção fiscal do IRS com o nome da empresa e o EIN
+        `),
         nameChangeDocument: 'Documento de alteração de nome',
         nameChangeDocumentDescription: 'Se o nome da sua empresa mudou desde a solicitação do TIN/EIN, precisamos deste documento para verificar o número de identificação fiscal informado',
         companyAddressVerification: 'Verificação de endereço da empresa',
         companyAddressVerificationDescription: dedent(`
-        Envie um dos seguintes arquivos:
-        • Conta recente de serviços públicos com nome e endereço da empresa
-        • Extrato bancário com nome e endereço da empresa
-        • Contrato de locação atual incluindo a página de assinatura com nome e endereço atual da empresa
-        • Apólice ou declaração de seguro com nome e endereço da empresa
-        • Documento de atribuição de TIN com nome e endereço da empresa`),
+            Envie um dos seguintes arquivos:
+            • Conta recente de serviços públicos com nome e endereço da empresa
+            • Extrato bancário com nome e endereço da empresa
+            • Contrato de locação atual incluindo a página de assinatura com nome e endereço atual da empresa
+            • Apólice ou declaração de seguro com nome e endereço da empresa
+            • Documento de atribuição de TIN com nome e endereço da empresa
+        `),
         userAddressVerification: 'Verificação de endereço',
         userAddressVerificationDescription: dedent(`
-        Envie um dos seguintes arquivos:
-        • Título de eleitor
-        • Carteira de motorista
-        • Extrato bancário
-        • Conta de serviços públicos`),
+            Envie um dos seguintes arquivos:
+            • Título de eleitor
+            • Carteira de motorista
+            • Extrato bancário
+            • Conta de serviços públicos
+        `),
         userDOBVerification: 'Verificação de data de nascimento',
         userDOBVerificationDescription: 'Envie um documento de identidade emitido nos EUA',
         finishViaChat: 'Finalizar pelo chat',
@@ -4400,17 +4403,17 @@ ${amount} para ${merchant} - ${date}`,
             roleName: (role?: string) => {
                 switch (role) {
                     case CONST.POLICY.ROLE.ADMIN:
-                        return 'Admin';
+                        return 'Admin. do workspace';
                     case CONST.POLICY.ROLE.AUDITOR:
                         return 'Auditor';
                     case CONST.POLICY.ROLE.EDITOR:
                         return 'Editor';
                     case CONST.POLICY.ROLE.CARD_ADMIN:
-                        return 'Admin. do Cartão';
+                        return 'Admin. de Cartão';
                     case CONST.POLICY.ROLE.PEOPLE_ADMIN:
-                        return 'Administração de pessoas';
+                        return 'Administração de Pessoas';
                     case CONST.POLICY.ROLE.PAYMENTS_ADMIN:
-                        return 'Admin de pagamentos';
+                        return 'Admin de Pagamentos';
                     case CONST.POLICY.ROLE.USER:
                         return 'Membro';
                     default:
@@ -6245,12 +6248,14 @@ _Para instruções mais detalhadas, [visite nossa central de ajuda](${CONST.NETS
             cannotRemoveUserDueToReport: ({memberName}: {memberName: string}) =>
                 `${memberName} tem um relatório pendente de processamento que requer ação. Peça para que concluam a ação necessária antes de removê-los do workspace.`,
             allMembers: 'Todos os membros',
-            admins: 'Administradores',
+            admins: 'Admins do workspace',
             approvers: 'Aprovadores',
             auditors: 'Auditores',
             emptyRoleFilter: {title: 'Nenhum membro corresponde a este filtro', subtitle: 'Convide um membro ou altere o filtro acima.'},
             configureHRSync: (providerName: string) => `Configurar a sincronização do ${providerName}.`,
             syncWithHR: (providerName: string) => `Sincronizar com ${providerName}`,
+            makeCardAdmin: {one: 'Tornar admin do cartão', other: 'Tornar administradores do cartão'},
+            cardAdmins: 'Administradores de cartões',
         },
         card: {
             getStartedIssuing: 'Comece emitindo seu primeiro cartão virtual ou físico.',
@@ -6995,6 +7000,12 @@ Exija dados de despesas como recibos e descrições, defina limites e padrões e
                 onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
                     `<muted-text>O faturamento está disponível nos planos Collect e Control, a partir de <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `por membro por mês.` : `por membro ativo por mês.`}</muted-text>`,
             },
+            controlPolicyRoles: {
+                title: 'Funções da política de controle',
+                description: 'Use funções especializadas como Auditor e Administrador de Cartão para conceder aos membros acesso apenas ao que precisam.',
+                onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
+                    `<muted-text>Funções especializadas no espaço de trabalho estão disponíveis apenas no plano Control, a partir de <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `por membro por mês.` : `por membro ativo por mês.`}</muted-text>`,
+            },
         },
         downgrade: {
             commonFeatures: {
@@ -8448,8 +8459,11 @@ Adicione mais regras de gasto para proteger o fluxo de caixa da empresa.`,
                     `A conexão de ${feedName} está interrompida. Para restaurar as importações do cartão, <a href='${workspaceCompanyCardRoute}'>faça login no seu banco</a>.`,
                 plaidBalanceFailure: ({maskedAccountNumber, walletRoute}: {maskedAccountNumber: string; walletRoute: string}) =>
                     `a conexão Plaid com a sua conta bancária empresarial foi interrompida. Por favor, <a href='${walletRoute}'>reconecte sua conta bancária ${maskedAccountNumber}</a> para continuar usando seus Cartões Expensify.`,
-                addEmployee: (email: string, role: string, didJoinPolicy?: boolean) =>
-                    didJoinPolicy ? `${email} entrou pelo link de convite do workspace` : `adicionou ${email} como ${role === 'member' ? 'a' : 'um'} ${role}`,
+                addEmployee: (email: string, role: string, didJoinPolicy?: boolean) => {
+                    const translatedRole = String(translations.workspace.common.roleName(role)).toLowerCase();
+                    const article = role === CONST.POLICY.ROLE.AUDITOR ? 'um' : 'um';
+                    return didJoinPolicy ? `${email} entrou pelo link de convite do workspace` : `adicionou ${email} como ${article} ${translatedRole}`;
+                },
                 updateRole: ({email, currentRole, newRole}: UpdateRoleParams) => `atualizou a função de ${email} para ${newRole} (anteriormente ${currentRole})`,
                 updatedCustomField1: (email: string, newValue: string, previousValue: string) => {
                     if (!newValue) {
diff --git a/src/languages/zh-hans.ts b/src/languages/zh-hans.ts
index 50ea96e21b6b..05372444f05b 100644
--- a/src/languages/zh-hans.ts
+++ b/src/languages/zh-hans.ts
@@ -4027,27 +4027,30 @@ ${amount}，商户：${merchant} - 日期：${date}`,
         verificationFailed: '验证失败，因此我们需要额外的文件来验证你及你的企业',
         taxIDVerification: '税务识别号验证',
         taxIDVerificationDescription: dedent(`
-        请上传以下任一文件：
-        • IRS TIN/EIN 分配函
-        • IRS TIN/EIN 申请确认函（通常包含“Congratulations! The EIN has been successfully assigned”）
-        • 显示公司名称和 EIN 的 IRS 免税函`),
+            请上传以下任一文件：
+            • IRS TIN/EIN 分配函
+            • IRS TIN/EIN 申请确认函（通常包含“Congratulations! The EIN has been successfully assigned”）
+            • 显示公司名称和 EIN 的 IRS 免税函
+        `),
         nameChangeDocument: '名称变更文件',
         nameChangeDocumentDescription: '如果你的公司名称在申请 TIN/EIN 后发生更改，我们需要此文件来验证你提供的税务识别号',
         companyAddressVerification: '公司地址验证',
         companyAddressVerificationDescription: dedent(`
-        请上传以下任一文件：
-        • 显示公司名称和地址的近期水电账单
-        • 显示公司名称和地址的银行对账单
-        • 包含签字页的有效租赁协议，显示公司名称和当前地址
-        • 显示公司名称和地址的保险声明
-        • 显示公司名称和地址的 TIN 分配文件`),
+            请上传以下任一文件：
+            • 显示公司名称和地址的近期水电账单
+            • 显示公司名称和地址的银行对账单
+            • 包含签字页的有效租赁协议，显示公司名称和当前地址
+            • 显示公司名称和地址的保险声明
+            • 显示公司名称和地址的 TIN 分配文件
+        `),
         userAddressVerification: '地址验证',
         userAddressVerificationDescription: dedent(`
-        请上传以下任一文件：
-        • 选民登记卡
-        • 驾驶证
-        • 银行对账单
-        • 水电账单`),
+            请上传以下任一文件：
+            • 选民登记卡
+            • 驾驶证
+            • 银行对账单
+            • 水电账单
+        `),
         userDOBVerification: '出生日期验证',
         userDOBVerificationDescription: '请上传美国签发的身份证件',
         finishViaChat: '通过聊天完成',
@@ -4306,15 +4309,15 @@ ${amount}，商户：${merchant} - 日期：${date}`,
             roleName: (role?: string) => {
                 switch (role) {
                     case CONST.POLICY.ROLE.ADMIN:
-                        return '管理员';
+                        return '工作区管理员';
                     case CONST.POLICY.ROLE.AUDITOR:
                         return '审计员';
                     case CONST.POLICY.ROLE.EDITOR:
-                        return '编辑';
+                        return '编辑器';
                     case CONST.POLICY.ROLE.CARD_ADMIN:
                         return '卡片管理员';
                     case CONST.POLICY.ROLE.PEOPLE_ADMIN:
-                        return '人员管理';
+                        return '人员管理员';
                     case CONST.POLICY.ROLE.PAYMENTS_ADMIN:
                         return '付款管理员';
                     case CONST.POLICY.ROLE.USER:
@@ -6085,12 +6088,14 @@ _如需更详细的说明，请[访问我们的帮助网站](${CONST.NETSUITE_IM
                 `如果您将 ${memberName} 从此工作区中移除，我们会将其技术联系人替换为工作区所有者 ${workspaceOwner}。`,
             cannotRemoveUserDueToReport: ({memberName}: {memberName: string}) => `${memberName} 还有一份待处理报告需要处理。请在将其从工作区中移除之前，先让 TA 完成所需操作。`,
             allMembers: '所有成员',
-            admins: '管理员',
+            admins: '工作区管理员',
             approvers: '审批人',
             auditors: '审计员',
             emptyRoleFilter: {title: '没有成员符合此筛选条件', subtitle: '邀请成员或更改上方的筛选条件。'},
             configureHRSync: (providerName: string) => `配置 ${providerName} 同步。`,
             syncWithHR: (providerName: string) => `与 ${providerName} 同步`,
+            makeCardAdmin: {one: '设为卡片管理员', other: '设为卡管理员'},
+            cardAdmins: '卡片管理员',
         },
         card: {
             getStartedIssuing: '从发放您的第一张虚拟卡或实体卡开始使用。',
@@ -6817,6 +6822,12 @@ ${reportName}
                 onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
                     `<muted-text>开票功能适用于 Collect 和 Control 方案，起价为 <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `每位成员每月。` : `每位活跃成员每月。`}</muted-text>`,
             },
+            controlPolicyRoles: {
+                title: '控制策略角色',
+                description: '使用审计员、卡片管理员等专门角色，只授予成员完成工作所需的访问权限。',
+                onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
+                    `<muted-text>专用工作区角色仅在 Control 方案中提供，起价为 <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `每位成员每月。` : `每位活跃成员每月。`}</muted-text>`,
+            },
         },
         downgrade: {
             commonFeatures: {
@@ -8217,8 +8228,11 @@ ${reportName}
                     `${feedName} 连接已中断。要恢复银行卡导入，请<a href='${workspaceCompanyCardRoute}'>登录您的银行账户</a>。`,
                 plaidBalanceFailure: ({maskedAccountNumber, walletRoute}: {maskedAccountNumber: string; walletRoute: string}) =>
                     `您与企业银行账户的 Plaid 连接已中断。请<a href='${walletRoute}'>重新连接您的银行账户 ${maskedAccountNumber}</a>，以便继续使用 Expensify 卡。`,
-                addEmployee: (email: string, role: string, didJoinPolicy?: boolean) =>
-                    didJoinPolicy ? `${email} 通过工作区邀请链接加入` : `已将 ${email} 添加为 ${role === 'member' ? '一个' : '一个'} 的 ${role}`,
+                addEmployee: (email: string, role: string, didJoinPolicy?: boolean) => {
+                    const translatedRole = String(translations.workspace.common.roleName(role)).toLowerCase();
+                    const article = role === CONST.POLICY.ROLE.AUDITOR ? '一个' : 'a';
+                    return didJoinPolicy ? `${email} 通过工作区邀请链接加入` : `已将 ${email} 添加为 ${article} ${translatedRole}`;
+                },
                 updateRole: ({email, currentRole, newRole}: UpdateRoleParams) => `已将 ${email} 的角色更新为 ${newRole}（先前为 ${currentRole}）`,
                 updatedCustomField1: (email: string, newValue: string, previousValue: string) => {
                     if (!newValue) {

From faecbed56c72e1b93f3591b78dd0c6fe3a2da35a Mon Sep 17 00:00:00 2001
From: bartlomiej obudzinski <bartlomiej.obudzinski@callstack.com>
Date: Fri, 12 Jun 2026 11:32:21 +0200
Subject: [PATCH 425/435] refactor: mount last-report subscriptions only in
 wide InboxTabButton

---
 .../NavigationTabBar/InboxTabButton.tsx       | 111 +++++++++++-------
 1 file changed, 71 insertions(+), 40 deletions(-)

diff --git a/src/components/Navigation/NavigationTabBar/InboxTabButton.tsx b/src/components/Navigation/NavigationTabBar/InboxTabButton.tsx
index 2784633a7e58..7f415b5060ae 100644
--- a/src/components/Navigation/NavigationTabBar/InboxTabButton.tsx
+++ b/src/components/Navigation/NavigationTabBar/InboxTabButton.tsx
@@ -35,6 +35,13 @@ function getStringParam(params: unknown, key: string): string | undefined {
     return undefined;
 }
 
+function startNavigateToInboxTabSpan() {
+    startSpan(CONST.TELEMETRY.SPAN_NAVIGATE_TO_INBOX_TAB, {
+        name: CONST.TELEMETRY.SPAN_NAVIGATE_TO_INBOX_TAB,
+        op: CONST.TELEMETRY.SPAN_NAVIGATE_TO_INBOX_TAB,
+    });
+}
+
 type InboxTabButtonProps = {
     selectedTab: ValueOf<typeof NAVIGATION_TABS>;
     isWideLayout: boolean;
@@ -51,25 +58,22 @@ function makeDoesLastReportActionExistSelector(actionID: string | undefined) {
     };
 }
 
-function InboxTabButton({selectedTab, isWideLayout}: InboxTabButtonProps) {
+type WideInboxTabButtonProps = {
+    selectedTab: ValueOf<typeof NAVIGATION_TABS>;
+    statusIndicatorColor: string | undefined;
+    accessibilityLabel: string;
+};
+
+// The last-viewed report deep link only exists in the wide layout, so the report and report-action
+// Onyx subscriptions live here and are only created when the wide layout is rendered. In the narrow
+// layout tapping Inbox always routes to ROUTES.INBOX, so these subscriptions are never set up.
+function WideInboxTabButton({selectedTab, statusIndicatorColor, accessibilityLabel}: WideInboxTabButtonProps) {
     const styles = useThemeStyles();
-    const theme = useTheme();
     const {translate} = useLocalize();
-    const {chatTabBrickRoad} = useSidebarOrderedReportsState();
     const expensifyIcons = useMemoizedLazyExpensifyIcons(['Inbox']);
 
-    let statusIndicatorColor: string | undefined;
-    if (chatTabBrickRoad === CONST.BRICK_ROAD_INDICATOR_STATUS.INFO) {
-        statusIndicatorColor = theme.iconSuccessFill;
-    } else if (chatTabBrickRoad) {
-        statusIndicatorColor = theme.danger;
-    }
-
-    // The last-report deep link only runs in the wide layout, so gate the lookups on isWideLayout.
-    // In the narrow layout this keeps reportID/reportActionID undefined, leaving the report and
-    // report-action Onyx subscriptions below inert (tapping Inbox always routes to ROUTES.INBOX).
     const lastReportRouteReportID = useRootNavigationState((rootState) => {
-        if (!isWideLayout || !rootState) {
+        if (!rootState) {
             return undefined;
         }
         const route = getLastRoute(rootState, NAVIGATORS.REPORTS_SPLIT_NAVIGATOR, SCREENS.REPORT);
@@ -77,7 +81,7 @@ function InboxTabButton({selectedTab, isWideLayout}: InboxTabButtonProps) {
     });
 
     const lastReportRouteReportActionID = useRootNavigationState((rootState) => {
-        if (!isWideLayout || !rootState) {
+        if (!rootState) {
             return undefined;
         }
         const route = getLastRoute(rootState, NAVIGATORS.REPORTS_SPLIT_NAVIGATOR, SCREENS.REPORT);
@@ -92,19 +96,14 @@ function InboxTabButton({selectedTab, isWideLayout}: InboxTabButtonProps) {
         lastReportRouteReportActionID,
     ]);
 
-    const inboxAccessibilityState = {selected: selectedTab === NAVIGATION_TABS.INBOX};
-
     const navigateToChats = () => {
         if (selectedTab === NAVIGATION_TABS.INBOX) {
             return;
         }
 
-        startSpan(CONST.TELEMETRY.SPAN_NAVIGATE_TO_INBOX_TAB, {
-            name: CONST.TELEMETRY.SPAN_NAVIGATE_TO_INBOX_TAB,
-            op: CONST.TELEMETRY.SPAN_NAVIGATE_TO_INBOX_TAB,
-        });
+        startNavigateToInboxTabSpan();
 
-        if (isWideLayout && doesLastReportExist) {
+        if (doesLastReportExist) {
             // Fetch route params on-demand to avoid storing the full route object in render-time state
             const rootState = navigationRef.getRootState();
             const lastRoute = rootState ? getLastRoute(rootState, NAVIGATORS.REPORTS_SPLIT_NAVIGATOR, SCREENS.REPORT) : undefined;
@@ -121,37 +120,69 @@ function InboxTabButton({selectedTab, isWideLayout}: InboxTabButtonProps) {
         Navigation.navigate(ROUTES.INBOX);
     };
 
+    return (
+        <PressableWithFeedback
+            onPress={navigateToChats}
+            role={CONST.ROLE.TAB}
+            accessibilityLabel={accessibilityLabel}
+            accessibilityState={{selected: selectedTab === NAVIGATION_TABS.INBOX}}
+            style={({hovered}) => [styles.leftNavigationTabBarItem, hovered && styles.navigationTabBarItemHovered]}
+            sentryLabel={CONST.SENTRY_LABEL.NAVIGATION_TAB_BAR.INBOX}
+        >
+            {({hovered}) => (
+                <TabBarItem
+                    icon={expensifyIcons.Inbox}
+                    label={translate('common.inbox')}
+                    isSelected={selectedTab === NAVIGATION_TABS.INBOX}
+                    isHovered={hovered}
+                    statusIndicatorColor={statusIndicatorColor}
+                />
+            )}
+        </PressableWithFeedback>
+    );
+}
+
+function InboxTabButton({selectedTab, isWideLayout}: InboxTabButtonProps) {
+    const styles = useThemeStyles();
+    const theme = useTheme();
+    const {translate} = useLocalize();
+    const {chatTabBrickRoad} = useSidebarOrderedReportsState();
+    const expensifyIcons = useMemoizedLazyExpensifyIcons(['Inbox']);
+
+    let statusIndicatorColor: string | undefined;
+    if (chatTabBrickRoad === CONST.BRICK_ROAD_INDICATOR_STATUS.INFO) {
+        statusIndicatorColor = theme.iconSuccessFill;
+    } else if (chatTabBrickRoad) {
+        statusIndicatorColor = theme.danger;
+    }
+
     const accessibilityLabel = chatTabBrickRoad ? `${translate('common.inbox')}. ${translate('common.yourReviewIsRequired')}` : translate('common.inbox');
 
     if (isWideLayout) {
         return (
-            <PressableWithFeedback
-                onPress={navigateToChats}
-                role={CONST.ROLE.TAB}
+            <WideInboxTabButton
+                selectedTab={selectedTab}
+                statusIndicatorColor={statusIndicatorColor}
                 accessibilityLabel={accessibilityLabel}
-                accessibilityState={inboxAccessibilityState}
-                style={({hovered}) => [styles.leftNavigationTabBarItem, hovered && styles.navigationTabBarItemHovered]}
-                sentryLabel={CONST.SENTRY_LABEL.NAVIGATION_TAB_BAR.INBOX}
-            >
-                {({hovered}) => (
-                    <TabBarItem
-                        icon={expensifyIcons.Inbox}
-                        label={translate('common.inbox')}
-                        isSelected={selectedTab === NAVIGATION_TABS.INBOX}
-                        isHovered={hovered}
-                        statusIndicatorColor={statusIndicatorColor}
-                    />
-                )}
-            </PressableWithFeedback>
+            />
         );
     }
 
+    const navigateToChats = () => {
+        if (selectedTab === NAVIGATION_TABS.INBOX) {
+            return;
+        }
+
+        startNavigateToInboxTabSpan();
+        Navigation.navigate(ROUTES.INBOX);
+    };
+
     return (
         <PressableWithFeedback
             onPress={navigateToChats}
             role={CONST.ROLE.TAB}
             accessibilityLabel={accessibilityLabel}
-            accessibilityState={inboxAccessibilityState}
+            accessibilityState={{selected: selectedTab === NAVIGATION_TABS.INBOX}}
             wrapperStyle={styles.flex1}
             style={styles.navigationTabBarItem}
             sentryLabel={CONST.SENTRY_LABEL.NAVIGATION_TAB_BAR.INBOX}

From be1a01c95a8d0ed5d835e471eb18424ed54b5d66 Mon Sep 17 00:00:00 2001
From: war-in <war-in@users.noreply.github.com>
Date: Fri, 12 Jun 2026 11:38:18 +0200
Subject: [PATCH 426/435] fix: add patch dirs to rock's fingerprint sources so
 patch changes trigger a rebuild

---
 rock.config.mjs | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/rock.config.mjs b/rock.config.mjs
index 3f441f1ac5a3..fd354e8f6832 100644
--- a/rock.config.mjs
+++ b/rock.config.mjs
@@ -22,7 +22,7 @@ export default {
         android: platformAndroid({sourceDir: isHybrid ? './Mobile-Expensify/Android' : './android'}),
     },
     fingerprint: {
-        extraSources: ['android/gradle.properties', 'ios/Podfile', 'scripts/compute-patches-hash.sh'],
+        extraSources: ['android/gradle.properties', 'ios/Podfile', 'scripts/compute-patches-hash.sh', 'patches', ...(isHybrid ? ['Mobile-Expensify/patches'] : [])],
         env: ['USE_WEB_PROXY', 'PUSHER_DEV_SUFFIX', 'SECURE_NGROK_URL', 'NGROK_URL', 'USE_NGROK', 'FORCE_NATIVE_BUILD'],
         ignorePaths: ['Mobile-Expensify/Android/assets/app/shared/bundle.js'],
     },

From f8f8daaed2e9d3dff3513ff932d7d07ad87da959 Mon Sep 17 00:00:00 2001
From: ShridharGoel <35566748+ShridharGoel@users.noreply.github.com>
Date: Fri, 12 Jun 2026 15:15:16 +0530
Subject: [PATCH 427/435] Fix generated locale role translations

---
 src/languages/de.ts      | 8 +-------
 src/languages/es.ts      | 8 +-------
 src/languages/fr.ts      | 8 +-------
 src/languages/it.ts      | 8 +-------
 src/languages/ja.ts      | 8 +-------
 src/languages/nl.ts      | 8 +-------
 src/languages/pl.ts      | 8 +-------
 src/languages/pt-BR.ts   | 8 +-------
 src/languages/zh-hans.ts | 8 +-------
 9 files changed, 9 insertions(+), 63 deletions(-)

diff --git a/src/languages/de.ts b/src/languages/de.ts
index 4f8f9913bcb5..405b109a055b 100644
--- a/src/languages/de.ts
+++ b/src/languages/de.ts
@@ -6289,7 +6289,7 @@ _Für ausführlichere Anweisungen [besuchen Sie unsere Hilfeseite](${CONST.NETSU
             emptyRoleFilter: {title: 'Keine Mitglieder entsprechen diesem Filter', subtitle: 'Laden Sie ein Mitglied ein oder ändern Sie den Filter oben.'},
             configureHRSync: (providerName: string) => `Synchronisierung mit ${providerName} einrichten.`,
             syncWithHR: (providerName: string) => `Mit ${providerName} synchronisieren`,
-            makeCardAdmin: {one: 'Zum Karten-Admin machen', other: 'Karten-Admins festlegen'},
+            makeCardAdmin: () => ({one: 'Zum Karten-Admin machen', other: 'Karten-Admins festlegen'}),
             cardAdmins: 'Karten-Admins',
         },
         card: {
@@ -6937,12 +6937,6 @@ Fordern Sie Spesendetails wie Belege und Beschreibungen an, legen Sie Limits und
                 onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
                     `<muted-text>Entfernungsraten sind im Collect-Tarif verfügbar, beginnend bei <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `pro Mitglied und Monat.` : `pro aktivem Mitglied und Monat.`}</muted-text>`,
             },
-            auditor: {
-                title: 'Prüfer',
-                description: 'Prüfer erhalten schreibgeschützten Zugriff auf alle Berichte für vollständige Transparenz und Compliance-Überwachung.',
-                onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
-                    `<muted-text>Auditor:innen sind nur im Control-Tarif verfügbar, ab <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `pro Mitglied und Monat.` : `pro aktivem Mitglied und Monat.`}</muted-text>`,
-            },
             [CONST.UPGRADE_FEATURE_INTRO_MAPPING.multiApprovalLevels.id]: {
                 title: 'Mehrere Genehmigungsstufen',
                 description:
diff --git a/src/languages/es.ts b/src/languages/es.ts
index 4107af9c5538..b31c2abcc693 100644
--- a/src/languages/es.ts
+++ b/src/languages/es.ts
@@ -6130,7 +6130,7 @@ ${amount} para ${merchant} - ${date}`,
                 `${memberName} tiene un informe en proceso pendiente de acción. Pídele que complete la acción requerida antes de eliminarlo del espacio de trabajo.`,
             configureHRSync: (providerName: string) => `Configura la sincronización de ${providerName}.`,
             syncWithHR: (providerName: string) => `Sincronizar con ${providerName}`,
-            makeCardAdmin: {one: 'Hacer administrador de tarjetas', other: 'Hacer administradores de tarjetas'},
+            makeCardAdmin: () => ({one: 'Hacer administrador de tarjetas', other: 'Hacer administradores de tarjetas'}),
             cardAdmins: 'Administradores de tarjetas',
         },
         accounting: {
@@ -6891,12 +6891,6 @@ ${amount} para ${merchant} - ${date}`,
                 onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}) =>
                     `<muted-text>Las tasas de distancia están disponibles en el plan Recopilar, a partir de <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `por miembro al mes.` : `por miembro activo al mes.`}</muted-text>`,
             },
-            auditor: {
-                title: 'Auditor',
-                description: 'Los auditores tienen acceso de lectura a todos los informes para una visibilidad completa y la supervisión del cumplimiento.',
-                onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
-                    `<muted-text>Los auditores solo están disponibles con el plan Control, a partir de <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `por miembro al mes.` : `por miembro activo al mes.`}</muted-text>`,
-            },
             [CONST.UPGRADE_FEATURE_INTRO_MAPPING.multiApprovalLevels.id]: {
                 title: 'Múltiples niveles de aprobación',
                 description:
diff --git a/src/languages/fr.ts b/src/languages/fr.ts
index db4dfccd1f18..6313cd238d51 100644
--- a/src/languages/fr.ts
+++ b/src/languages/fr.ts
@@ -6314,7 +6314,7 @@ _Pour des instructions plus détaillées, [visitez notre site d’aide](${CONST.
             emptyRoleFilter: {title: 'Aucun membre ne correspond à ce filtre', subtitle: 'Invitez un membre ou modifiez le filtre ci-dessus.'},
             configureHRSync: (providerName: string) => `Configurer la synchronisation ${providerName}.`,
             syncWithHR: (providerName: string) => `Synchroniser avec ${providerName}`,
-            makeCardAdmin: {one: 'Nommer administrateur de carte', other: 'Nommer des administrateurs de carte'},
+            makeCardAdmin: () => ({one: 'Nommer administrateur de carte', other: 'Nommer des administrateurs de carte'}),
             cardAdmins: 'Administrateurs de cartes',
         },
         card: {
@@ -6964,12 +6964,6 @@ Rendez obligatoires des informations de dépense comme les reçus et les descrip
                 onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
                     `<muted-text>Les taux de distance sont disponibles avec l’abonnement Collect, à partir de <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `par membre et par mois.` : `par membre actif et par mois.`}</muted-text>`,
             },
-            auditor: {
-                title: 'Auditeur',
-                description: 'Les auditeurs obtiennent un accès en lecture seule à toutes les notes de frais pour une visibilité complète et le suivi de la conformité.',
-                onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
-                    `<muted-text>Les auditeurs ne sont disponibles que dans l’offre Control, à partir de <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `par membre et par mois.` : `par membre actif et par mois.`}</muted-text>`,
-            },
             [CONST.UPGRADE_FEATURE_INTRO_MAPPING.multiApprovalLevels.id]: {
                 title: 'Niveaux d’approbation multiples',
                 description:
diff --git a/src/languages/it.ts b/src/languages/it.ts
index cba6775a290b..09620be9e504 100644
--- a/src/languages/it.ts
+++ b/src/languages/it.ts
@@ -6277,7 +6277,7 @@ _Per istruzioni più dettagliate, [visita il nostro sito di assistenza](${CONST.
             emptyRoleFilter: {title: 'Nessun membro corrisponde a questo filtro', subtitle: 'Invita un membro o modifica il filtro qui sopra.'},
             configureHRSync: (providerName: string) => `Configura la sincronizzazione di ${providerName}.`,
             syncWithHR: (providerName: string) => `Sincronizza con ${providerName}`,
-            makeCardAdmin: {one: 'Rendi amministratore carta', other: 'Rendi amministratori carta'},
+            makeCardAdmin: () => ({one: 'Rendi amministratore carta', other: 'Rendi amministratori carta'}),
             cardAdmins: 'Amministratori carta',
         },
         card: {
@@ -6921,12 +6921,6 @@ Richiedi dettagli sulle spese come ricevute e descrizioni, imposta limiti e valo
                 onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
                     `<muted-text>Le tariffe chilometriche sono disponibili con il piano Collect, a partire da <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `per utente al mese.` : `per membro attivo al mese.`}</muted-text>`,
             },
-            auditor: {
-                title: 'Revisore',
-                description: 'I revisori ottengono accesso in sola lettura a tutti i report per garantire completa visibilità e monitoraggio della conformità.',
-                onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
-                    `<muted-text>Gli auditor sono disponibili solo con il piano Control, a partire da <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `per utente al mese.` : `per membro attivo al mese.`}</muted-text>`,
-            },
             [CONST.UPGRADE_FEATURE_INTRO_MAPPING.multiApprovalLevels.id]: {
                 title: 'Livelli di approvazione multipli',
                 description:
diff --git a/src/languages/ja.ts b/src/languages/ja.ts
index a4d64c20b681..6f42c4fe5cd6 100644
--- a/src/languages/ja.ts
+++ b/src/languages/ja.ts
@@ -6206,7 +6206,7 @@ _詳しい手順については、[ヘルプサイトをご覧ください](${CO
             emptyRoleFilter: {title: 'このフィルターに一致するメンバーはいません', subtitle: 'メンバーを招待するか、上のフィルターを変更してください。'},
             configureHRSync: (providerName: string) => `${providerName} の同期を設定します。`,
             syncWithHR: (providerName: string) => `${providerName}と同期`,
-            makeCardAdmin: {one: 'カード管理者にする', other: 'カード管理者に設定'},
+            makeCardAdmin: () => ({one: 'カード管理者にする', other: 'カード管理者に設定'}),
             cardAdmins: 'カード管理者',
         },
         card: {
@@ -6847,12 +6847,6 @@ ${reportName}
                 onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
                     `<muted-text>距離レートはCollectプランで利用できます。<strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `メンバー1人あたり月額` : `アクティブメンバー1人あたり月額`}からご利用になれます</muted-text>`,
             },
-            auditor: {
-                title: '監査人',
-                description: '監査担当者は、可視性とコンプライアンス監視を徹底するため、すべてのレポートを閲覧専用で確認できます。',
-                onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
-                    `<muted-text>監査人は、<strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `メンバー1人あたり月額` : `アクティブメンバー1人あたり月額`} からの Control プランでのみ利用できます</muted-text>`,
-            },
             [CONST.UPGRADE_FEATURE_INTRO_MAPPING.multiApprovalLevels.id]: {
                 title: '複数の承認レベル',
                 description: '複数承認レベルは、精算前にレポートを複数人で承認する必要がある会社向けのワークフローツールです。',
diff --git a/src/languages/nl.ts b/src/languages/nl.ts
index 803e591df534..73809f684589 100644
--- a/src/languages/nl.ts
+++ b/src/languages/nl.ts
@@ -6255,7 +6255,7 @@ _Voor meer gedetailleerde instructies, [bezoek onze help-site](${CONST.NETSUITE_
             emptyRoleFilter: {title: 'Geen leden komen overeen met dit filter', subtitle: 'Nodig een lid uit of wijzig het filter hierboven.'},
             configureHRSync: (providerName: string) => `Stel ${providerName}-synchronisatie in.`,
             syncWithHR: (providerName: string) => `Synchroniseren met ${providerName}`,
-            makeCardAdmin: {one: 'Kaartbeheerder maken', other: 'Kaartbeheerders maken'},
+            makeCardAdmin: () => ({one: 'Kaartbeheerder maken', other: 'Kaartbeheerders maken'}),
             cardAdmins: 'Kaartbeheerders',
         },
         card: {
@@ -6899,12 +6899,6 @@ Vereis onkostendetails zoals bonnen en beschrijvingen, stel limieten en standaar
                 onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
                     `<muted-text>Afstandstarieven zijn beschikbaar in het Collect-abonnement, vanaf <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `per lid per maand.` : `per actieve deelnemer per maand.`}</muted-text>`,
             },
-            auditor: {
-                title: 'Auditor',
-                description: 'Auditors krijgen alleen-lezen-toegang tot alle rapporten voor volledige transparantie en nalevingsbewaking.',
-                onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
-                    `<muted-text>Auditors zijn alleen beschikbaar in het Control-abonnement, vanaf <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `per lid per maand.` : `per actieve deelnemer per maand.`}</muted-text>`,
-            },
             [CONST.UPGRADE_FEATURE_INTRO_MAPPING.multiApprovalLevels.id]: {
                 title: 'Meerdere goedkeuringsniveaus',
                 description:
diff --git a/src/languages/pl.ts b/src/languages/pl.ts
index 3701ca73b0f9..82798313f45c 100644
--- a/src/languages/pl.ts
+++ b/src/languages/pl.ts
@@ -6250,7 +6250,7 @@ _Aby uzyskać bardziej szczegółowe instrukcje, [odwiedź naszą stronę pomocy
             emptyRoleFilter: {title: 'Żadni członkowie nie pasują do tego filtra', subtitle: 'Zaproś członka lub zmień filtr powyżej.'},
             configureHRSync: (providerName: string) => `Skonfiguruj synchronizację ${providerName}.`,
             syncWithHR: (providerName: string) => `Synchronizuj z ${providerName}`,
-            makeCardAdmin: {one: 'Ustaw jako administratora karty', other: 'Ustaw administratorów kart'},
+            makeCardAdmin: () => ({one: 'Ustaw jako administratora karty', other: 'Ustaw administratorów kart'}),
             cardAdmins: 'Administratorzy kart',
         },
         card: {
@@ -6893,12 +6893,6 @@ Wymagaj szczegółów wydatków, takich jak paragony i opisy, ustawiaj limity i
                 onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
                     `<muted-text>Stawki za przejazdy są dostępne w planie Collect, zaczynając od <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `za użytkownika miesięcznie.` : `na aktywnego członka miesięcznie.`}</muted-text>`,
             },
-            auditor: {
-                title: 'Audytor',
-                description: 'Biegli rewidentci otrzymują dostęp tylko do odczytu do wszystkich raportów, aby zapewnić pełną widoczność i monitorowanie zgodności.',
-                onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
-                    `<muted-text>Audytorzy są dostępni tylko w planie Control, zaczynającym się od <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `za użytkownika miesięcznie.` : `na aktywnego członka miesięcznie.`}</muted-text>`,
-            },
             [CONST.UPGRADE_FEATURE_INTRO_MAPPING.multiApprovalLevels.id]: {
                 title: 'Wiele poziomów zatwierdzania',
                 description:
diff --git a/src/languages/pt-BR.ts b/src/languages/pt-BR.ts
index 795ffd274738..99e98fd3c672 100644
--- a/src/languages/pt-BR.ts
+++ b/src/languages/pt-BR.ts
@@ -6254,7 +6254,7 @@ _Para instruções mais detalhadas, [visite nossa central de ajuda](${CONST.NETS
             emptyRoleFilter: {title: 'Nenhum membro corresponde a este filtro', subtitle: 'Convide um membro ou altere o filtro acima.'},
             configureHRSync: (providerName: string) => `Configurar a sincronização do ${providerName}.`,
             syncWithHR: (providerName: string) => `Sincronizar com ${providerName}`,
-            makeCardAdmin: {one: 'Tornar admin do cartão', other: 'Tornar administradores do cartão'},
+            makeCardAdmin: () => ({one: 'Tornar admin do cartão', other: 'Tornar administradores do cartão'}),
             cardAdmins: 'Administradores de cartões',
         },
         card: {
@@ -6897,12 +6897,6 @@ Exija dados de despesas como recibos e descrições, defina limites e padrões e
                 onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
                     `<muted-text>Tarifas por distância estão disponíveis no plano Collect, a partir de <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `por membro por mês.` : `por membro ativo por mês.`}</muted-text>`,
             },
-            auditor: {
-                title: 'Auditor',
-                description: 'Auditores têm acesso somente leitura a todos os relatórios para total visibilidade e monitoramento de conformidade.',
-                onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
-                    `<muted-text>Auditores estão disponíveis apenas no plano Control, a partir de <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `por membro por mês.` : `por membro ativo por mês.`}</muted-text>`,
-            },
             [CONST.UPGRADE_FEATURE_INTRO_MAPPING.multiApprovalLevels.id]: {
                 title: 'Múltiplos níveis de aprovação',
                 description:
diff --git a/src/languages/zh-hans.ts b/src/languages/zh-hans.ts
index 05372444f05b..0aa5169d1c32 100644
--- a/src/languages/zh-hans.ts
+++ b/src/languages/zh-hans.ts
@@ -6094,7 +6094,7 @@ _如需更详细的说明，请[访问我们的帮助网站](${CONST.NETSUITE_IM
             emptyRoleFilter: {title: '没有成员符合此筛选条件', subtitle: '邀请成员或更改上方的筛选条件。'},
             configureHRSync: (providerName: string) => `配置 ${providerName} 同步。`,
             syncWithHR: (providerName: string) => `与 ${providerName} 同步`,
-            makeCardAdmin: {one: '设为卡片管理员', other: '设为卡管理员'},
+            makeCardAdmin: () => ({one: '设为卡片管理员', other: '设为卡管理员'}),
             cardAdmins: '卡片管理员',
         },
         card: {
@@ -6723,12 +6723,6 @@ ${reportName}
                 onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
                     `<muted-text>里程费率适用于 Collect 方案，起始价格为 <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `每位成员每月。` : `每位活跃成员每月。`}</muted-text>`,
             },
-            auditor: {
-                title: '审计员',
-                description: '审计员将获得所有报表的只读访问权限，以实现全面可见性和合规监控。',
-                onlyAvailableOnPlan: ({formattedPrice, hasTeam2025Pricing}: {formattedPrice: string; hasTeam2025Pricing: boolean}) =>
-                    `<muted-text>审核员仅适用于 Control 方案，起价为 <strong>${formattedPrice}</strong> ${hasTeam2025Pricing ? `每位成员每月。` : `每位活跃成员每月。`}</muted-text>`,
-            },
             [CONST.UPGRADE_FEATURE_INTRO_MAPPING.multiApprovalLevels.id]: {
                 title: '多级审批',
                 description: '多级审批是一个工作流程工具，适用于在报销前需要多个人批准报销单的公司。',

From 625298b5c2c1f4aaa3abd4d41e5d878957a63af1 Mon Sep 17 00:00:00 2001
From: OSBotify <infra+osbotify@expensify.com>
Date: Fri, 12 Jun 2026 10:36:24 +0000
Subject: [PATCH 428/435] Auto-tighten eslint-seatbelt baseline

---
 config/eslint/eslint.seatbelt.tsv | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/config/eslint/eslint.seatbelt.tsv b/config/eslint/eslint.seatbelt.tsv
index 833ddba12297..b045bfee5fdd 100644
--- a/config/eslint/eslint.seatbelt.tsv
+++ b/config/eslint/eslint.seatbelt.tsv
@@ -279,7 +279,7 @@
 "../../src/components/MoneyRequestReportView/MoneyRequestReportActionsList.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../src/components/MoneyRequestReportView/MoneyRequestReportActionsList.tsx"	"react-hooks/refs"	3
 "../../src/components/MoneyRequestReportView/MoneyRequestReportActionsList.tsx"	"react-hooks/set-state-in-effect"	3
-"../../src/components/MoneyRequestReportView/MoneyRequestReportTransactionList.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	3
+"../../src/components/MoneyRequestReportView/MoneyRequestReportTransactionList.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	2
 "../../src/components/MoneyRequestReportView/MoneyRequestReportTransactionsNavigation.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	2
 "../../src/components/MoneyRequestReportView/MoneyRequestViewReportFields.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../src/components/MultiGestureCanvas/index.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1

From 5bd9a67b623d95d49c6906ead7449d47a293da04 Mon Sep 17 00:00:00 2001
From: OSBotify <infra+osbotify@expensify.com>
Date: Fri, 12 Jun 2026 11:35:26 +0000
Subject: [PATCH 429/435] Auto-tighten eslint-seatbelt baseline

---
 config/eslint/eslint.seatbelt.tsv | 1 -
 1 file changed, 1 deletion(-)

diff --git a/config/eslint/eslint.seatbelt.tsv b/config/eslint/eslint.seatbelt.tsv
index b045bfee5fdd..9c4056941975 100644
--- a/config/eslint/eslint.seatbelt.tsv
+++ b/config/eslint/eslint.seatbelt.tsv
@@ -296,7 +296,6 @@
 "../../src/components/MultifactorAuthentication/config/scenarios/ChangePIN.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../src/components/MultifactorAuthentication/config/scenarios/DefaultUserInterface.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../src/components/Navigation/NavigationTabBar/SearchTabButton.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
-"../../src/components/Navigation/NavigationTabBar/index.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	3
 "../../src/components/Navigation/QuickCreationActionsBar/index.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../src/components/Navigation/QuickCreationActionsBar/index.tsx"	"no-restricted-imports"	1
 "../../src/components/Navigation/TopLevelNavigationTabBar/index.tsx"	"react-hooks/set-state-in-effect"	1

From 2baae502933674a4921201c0b910a6739cac0748 Mon Sep 17 00:00:00 2001
From: ShridharGoel <35566748+ShridharGoel@users.noreply.github.com>
Date: Fri, 12 Jun 2026 17:25:29 +0530
Subject: [PATCH 430/435] Update policy admins room role membership

---
 src/libs/actions/Policy/Member.ts | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/src/libs/actions/Policy/Member.ts b/src/libs/actions/Policy/Member.ts
index df06bd7018db..a7d6574023d8 100644
--- a/src/libs/actions/Policy/Member.ts
+++ b/src/libs/actions/Policy/Member.ts
@@ -46,7 +46,13 @@ type WorkspaceMembersRoleData = {
 };
 
 function shouldBeInPolicyAdminsRoom(role: string | undefined): boolean {
-    return role === CONST.POLICY.ROLE.ADMIN || role === CONST.POLICY.ROLE.AUDITOR || role === CONST.POLICY.ROLE.CARD_ADMIN || role === CONST.POLICY.ROLE.EDITOR;
+    return (
+        role === CONST.POLICY.ROLE.ADMIN ||
+        role === CONST.POLICY.ROLE.CARD_ADMIN ||
+        role === CONST.POLICY.ROLE.PEOPLE_ADMIN ||
+        role === CONST.POLICY.ROLE.PAYMENTS_ADMIN ||
+        role === CONST.POLICY.ROLE.EDITOR
+    );
 }
 
 let allReportActions: OnyxCollection<ReportActions>;

From afc316f2c3054c2645b881434d9365df1f3040db Mon Sep 17 00:00:00 2001
From: ShridharGoel <35566748+ShridharGoel@users.noreply.github.com>
Date: Fri, 12 Jun 2026 17:39:47 +0530
Subject: [PATCH 431/435] Rename policy admins room access helper

---
 src/libs/actions/Policy/Member.ts | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/src/libs/actions/Policy/Member.ts b/src/libs/actions/Policy/Member.ts
index a7d6574023d8..18d2cfe83ee9 100644
--- a/src/libs/actions/Policy/Member.ts
+++ b/src/libs/actions/Policy/Member.ts
@@ -45,7 +45,7 @@ type WorkspaceMembersRoleData = {
     role: ValueOf<typeof CONST.POLICY.ROLE>;
 };
 
-function shouldBeInPolicyAdminsRoom(role: string | undefined): boolean {
+function hasPolicyAdminsRoomsAccess(role: string | undefined): boolean {
     return (
         role === CONST.POLICY.ROLE.ADMIN ||
         role === CONST.POLICY.ROLE.CARD_ADMIN ||
@@ -359,7 +359,7 @@ function removeMembers(policy: OnyxEntry<Policy>, selectedMemberEmails: string[]
         selectedMemberEmails
             .filter((login) => {
                 const role = login ? policy?.employeeList?.[login]?.role : '';
-                return shouldBeInPolicyAdminsRoom(role);
+                return hasPolicyAdminsRoomsAccess(role);
             })
             .map((login) => policyMemberEmailsToAccountIDs[login]),
     );
@@ -653,7 +653,7 @@ function buildUpdateWorkspaceMembersRoleOnyxData(policy: OnyxEntry<Policy>, sele
     if (adminRoom) {
         const failureDataParticipants: Record<number, Participant | null> = {...adminRoom.participants};
         const optimisticParticipants: Record<number, Participant | null> = {};
-        if (shouldBeInPolicyAdminsRoom(newRole)) {
+        if (hasPolicyAdminsRoomsAccess(newRole)) {
             for (const accountID of selectedMemberAccountIDs) {
                 if (adminRoom?.participants?.[accountID]) {
                     continue;
@@ -829,7 +829,7 @@ function buildAddMembersToWorkspaceOnyxData(
     const newPersonalDetailsOnyxData = PersonalDetailsUtils.getPersonalDetailsOnyxDataForOptimisticUsers(newLogins, newAccountIDs, formatPhoneNumber);
 
     const announceRoomMembers = buildRoomMembersOnyxData(CONST.REPORT.CHAT_TYPE.POLICY_ANNOUNCE, policyID, accountIDs);
-    const adminRoomMembers = buildRoomMembersOnyxData(CONST.REPORT.CHAT_TYPE.POLICY_ADMINS, policyID, shouldBeInPolicyAdminsRoom(effectiveRole) ? accountIDs : []);
+    const adminRoomMembers = buildRoomMembersOnyxData(CONST.REPORT.CHAT_TYPE.POLICY_ADMINS, policyID, hasPolicyAdminsRoomsAccess(effectiveRole) ? accountIDs : []);
     const optimisticAnnounceChat = ReportUtils.buildOptimisticAnnounceChat(policyID, [...policyMemberAccountIDs, ...accountIDs], currentUser.accountID);
     const announceRoomChat = optimisticAnnounceChat.announceChatData;
 

From a637f5b63680794a60cdc226ece5a2251eb6782e Mon Sep 17 00:00:00 2001
From: ShridharGoel <35566748+ShridharGoel@users.noreply.github.com>
Date: Fri, 12 Jun 2026 18:00:59 +0530
Subject: [PATCH 432/435] Update policy admins room tests

---
 tests/actions/PolicyMemberTest.ts | 30 ++++++++++++++----------------
 1 file changed, 14 insertions(+), 16 deletions(-)

diff --git a/tests/actions/PolicyMemberTest.ts b/tests/actions/PolicyMemberTest.ts
index 414995f62ed0..db7be5d7e88d 100644
--- a/tests/actions/PolicyMemberTest.ts
+++ b/tests/actions/PolicyMemberTest.ts
@@ -399,7 +399,7 @@ describe('actions/PolicyMember', () => {
             await mockFetch?.resume?.();
         });
 
-        it('Add new members with admin/auditor role to the #admins room', async () => {
+        it('Add new members with admin/scoped admin role to the #admins room', async () => {
             // Given a policy and an #admins room
             const policyID = '1';
             const adminRoomID = '1';
@@ -407,8 +407,8 @@ describe('actions/PolicyMember', () => {
             const ownerAccountID = 1;
             const adminAccountID = 1234;
             const adminEmail = 'admin@example.com';
-            const auditorAccountID = 1235;
-            const auditorEmail = 'auditor@example.com';
+            const cardAdminAccountID = 1235;
+            const cardAdminEmail = 'card-admin@example.com';
             const userAccountID = 1236;
             const userEmail = 'user@example.com';
             const policy = {
@@ -425,18 +425,18 @@ describe('actions/PolicyMember', () => {
                 },
             });
             await Onyx.set(ONYXKEYS.PERSONAL_DETAILS_LIST, {
-                [auditorAccountID]: {login: auditorEmail},
+                [cardAdminAccountID]: {login: cardAdminEmail},
             });
 
-            // When adding a new admin, auditor, and user members
+            // When adding a new admin, scoped admin, and user members
             mockFetch?.pause?.();
             Member.addMembersToWorkspace({[adminEmail]: adminAccountID}, 'Welcome', policy, [], CONST.POLICY.ROLE.ADMIN, TestHelper.formatPhoneNumber, currentUser, {});
-            Member.addMembersToWorkspace({[auditorEmail]: auditorAccountID}, 'Welcome', policy, [], CONST.POLICY.ROLE.AUDITOR, TestHelper.formatPhoneNumber, currentUser, {});
+            Member.addMembersToWorkspace({[cardAdminEmail]: cardAdminAccountID}, 'Welcome', policy, [], CONST.POLICY.ROLE.CARD_ADMIN, TestHelper.formatPhoneNumber, currentUser, {});
             Member.addMembersToWorkspace({[userEmail]: userAccountID}, 'Welcome', policy, [], CONST.POLICY.ROLE.USER, TestHelper.formatPhoneNumber, currentUser, {});
 
             await waitForBatchedUpdates();
 
-            // Then only the admin and auditor should be added to the #admins room optimistically
+            // Then only the admin and scoped admin should be added to the #admins room optimistically
             const adminRoom = await new Promise<OnyxEntry<Report>>((resolve) => {
                 const connection = Onyx.connect({
                     key: `${ONYXKEYS.COLLECTION.REPORT}${adminRoomID}`,
@@ -447,7 +447,7 @@ describe('actions/PolicyMember', () => {
                 });
             });
             expect(adminRoom?.participants?.[adminAccountID]).toBeTruthy();
-            expect(adminRoom?.participants?.[auditorAccountID]).toBeTruthy();
+            expect(adminRoom?.participants?.[cardAdminAccountID]).toBeTruthy();
             expect(adminRoom?.participants?.[userAccountID]).toBeUndefined();
 
             // and removed if the account is optimistic
@@ -462,7 +462,7 @@ describe('actions/PolicyMember', () => {
                 });
             });
             expect(adminRoomSuccess?.participants?.[adminAccountID]).toBeUndefined();
-            expect(adminRoomSuccess?.participants?.[auditorAccountID]).toBeTruthy();
+            expect(adminRoomSuccess?.participants?.[cardAdminAccountID]).toBeTruthy();
         });
 
         it('overrides the invited role to Editor on Submit workspaces, regardless of what the caller passes', async () => {
@@ -737,7 +737,7 @@ describe('actions/PolicyMember', () => {
     });
 
     describe('removeMembers', () => {
-        it('Remove members with admin/auditor role from the #admins room', async () => {
+        it('Remove members with admin role from the #admins room', async () => {
             // Given a policy and an #admins room
             const policyID = '1';
             const adminRoomID = '1';
@@ -777,7 +777,7 @@ describe('actions/PolicyMember', () => {
                 },
             });
 
-            // When removing am admin, auditor, and user members
+            // When removing an admin, auditor, and user members
             mockFetch?.pause?.();
             const memberEmailsToAccountIDs = {
                 [adminEmail]: adminAccountID,
@@ -788,7 +788,7 @@ describe('actions/PolicyMember', () => {
 
             await waitForBatchedUpdates();
 
-            // Then only the admin and auditor should be removed from the #admins room
+            // Then only the admin should be removed from the #admins room
             const optimisticAdminRoomMetadata = await new Promise<OnyxEntry<ReportMetadata>>((resolve) => {
                 const connection = Onyx.connect({
                     key: `${ONYXKEYS.COLLECTION.REPORT_METADATA}${adminRoomID}`,
@@ -798,13 +798,11 @@ describe('actions/PolicyMember', () => {
                     },
                 });
             });
-            expect(optimisticAdminRoomMetadata?.pendingChatMembers?.length).toBe(2);
+            expect(optimisticAdminRoomMetadata?.pendingChatMembers?.length).toBe(1);
             expect(optimisticAdminRoomMetadata?.pendingChatMembers?.find((pendingMember) => pendingMember.accountID === String(adminAccountID))?.pendingAction).toBe(
                 CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE,
             );
-            expect(optimisticAdminRoomMetadata?.pendingChatMembers?.find((pendingMember) => pendingMember.accountID === String(auditorAccountID))?.pendingAction).toBe(
-                CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE,
-            );
+            expect(optimisticAdminRoomMetadata?.pendingChatMembers?.find((pendingMember) => pendingMember.accountID === String(auditorAccountID))).toBeUndefined();
             await mockFetch?.resume?.();
 
             const successAdminRoomMetadata = await new Promise<OnyxEntry<ReportMetadata>>((resolve) => {

From 0866ef836648e5d211c4ad80fe6f7406ac480f35 Mon Sep 17 00:00:00 2001
From: ShridharGoel <35566748+ShridharGoel@users.noreply.github.com>
Date: Fri, 12 Jun 2026 19:01:56 +0530
Subject: [PATCH 433/435] Update workspace admin role action labels

---
 src/languages/de.ts      | 4 ++--
 src/languages/en.ts      | 8 ++++----
 src/languages/es.ts      | 4 ++--
 src/languages/fr.ts      | 4 ++--
 src/languages/it.ts      | 4 ++--
 src/languages/ja.ts      | 4 ++--
 src/languages/nl.ts      | 4 ++--
 src/languages/pl.ts      | 4 ++--
 src/languages/pt-BR.ts   | 4 ++--
 src/languages/zh-hans.ts | 4 ++--
 10 files changed, 22 insertions(+), 22 deletions(-)

diff --git a/src/languages/de.ts b/src/languages/de.ts
index 405b109a055b..249b791aa36f 100644
--- a/src/languages/de.ts
+++ b/src/languages/de.ts
@@ -6253,8 +6253,8 @@ _Für ausführlichere Anweisungen [besuchen Sie unsere Hilfeseite](${CONST.NETSU
                 other: 'Mitglieder erstellen',
             }),
             makeAdmin: () => ({
-                one: 'Als Admin festlegen',
-                other: 'Admins ernennen',
+                one: 'Als Workspace-Admin festlegen',
+                other: 'Workspace-Admins ernennen',
             }),
             makeAuditor: () => ({
                 one: 'Zum Prüfer machen',
diff --git a/src/languages/en.ts b/src/languages/en.ts
index 7465fe6209ff..ef78e2b70835 100644
--- a/src/languages/en.ts
+++ b/src/languages/en.ts
@@ -6300,16 +6300,16 @@ const translations = {
                 other: 'Make members',
             }),
             makeAdmin: () => ({
-                one: 'Make admin',
-                other: 'Make admins',
+                one: 'Make workspace admin',
+                other: 'Make workspace admins',
             }),
             makeAuditor: () => ({
                 one: 'Make auditor',
                 other: 'Make auditors',
             }),
             makeCardAdmin: () => ({
-                one: 'Make Card Admin',
-                other: 'Make Card Admins',
+                one: 'Make card admin',
+                other: 'Make card admins',
             }),
             selectAll: 'Select all',
             error: {
diff --git a/src/languages/es.ts b/src/languages/es.ts
index b31c2abcc693..05e235a4be81 100644
--- a/src/languages/es.ts
+++ b/src/languages/es.ts
@@ -6091,8 +6091,8 @@ ${amount} para ${merchant} - ${date}`,
                 other: 'Convertir en miembros',
             }),
             makeAdmin: () => ({
-                one: 'Hacer administrador',
-                other: 'Convertir en administradores',
+                one: 'Hacer administrador del espacio de trabajo',
+                other: 'Convertir en administradores del espacio de trabajo',
             }),
             makeAuditor: () => ({
                 one: 'Convertir en auditor',
diff --git a/src/languages/fr.ts b/src/languages/fr.ts
index 6313cd238d51..c40bfb262462 100644
--- a/src/languages/fr.ts
+++ b/src/languages/fr.ts
@@ -6278,8 +6278,8 @@ _Pour des instructions plus détaillées, [visitez notre site d’aide](${CONST.
                 other: 'Créer des membres',
             }),
             makeAdmin: () => ({
-                one: 'Nommer administrateur',
-                other: 'Nommer des administrateurs',
+                one: 'Nommer administrateur de l’espace de travail',
+                other: 'Nommer des administrateurs de l’espace de travail',
             }),
             makeAuditor: () => ({
                 one: 'Nommer auditeur',
diff --git a/src/languages/it.ts b/src/languages/it.ts
index 09620be9e504..19fcf5948f96 100644
--- a/src/languages/it.ts
+++ b/src/languages/it.ts
@@ -6241,8 +6241,8 @@ _Per istruzioni più dettagliate, [visita il nostro sito di assistenza](${CONST.
                 other: 'Rendi membri',
             }),
             makeAdmin: () => ({
-                one: 'Rendi amministratore',
-                other: 'Rendi amministratori',
+                one: 'Rendi amministratore dello spazio di lavoro',
+                other: 'Rendi amministratori dello spazio di lavoro',
             }),
             makeAuditor: () => ({
                 one: 'Rendi revisore',
diff --git a/src/languages/ja.ts b/src/languages/ja.ts
index 6f42c4fe5cd6..ae87ab640314 100644
--- a/src/languages/ja.ts
+++ b/src/languages/ja.ts
@@ -6170,8 +6170,8 @@ _詳しい手順については、[ヘルプサイトをご覧ください](${CO
                 other: 'メンバーにする',
             }),
             makeAdmin: () => ({
-                one: '管理者にする',
-                other: '管理者にする',
+                one: 'ワークスペース管理者にする',
+                other: 'ワークスペース管理者にする',
             }),
             makeAuditor: () => ({
                 one: '監査担当者に設定',
diff --git a/src/languages/nl.ts b/src/languages/nl.ts
index 73809f684589..6a1a9553d645 100644
--- a/src/languages/nl.ts
+++ b/src/languages/nl.ts
@@ -6219,8 +6219,8 @@ _Voor meer gedetailleerde instructies, [bezoek onze help-site](${CONST.NETSUITE_
                 other: 'Leden maken',
             }),
             makeAdmin: () => ({
-                one: 'Admin maken',
-                other: 'Beheerders maken',
+                one: 'Workspace-beheerder maken',
+                other: 'Workspace-beheerders maken',
             }),
             makeAuditor: () => ({
                 one: 'Auditeur maken',
diff --git a/src/languages/pl.ts b/src/languages/pl.ts
index 82798313f45c..c48483b2d623 100644
--- a/src/languages/pl.ts
+++ b/src/languages/pl.ts
@@ -6214,8 +6214,8 @@ _Aby uzyskać bardziej szczegółowe instrukcje, [odwiedź naszą stronę pomocy
                 other: 'Utwórz członków',
             }),
             makeAdmin: () => ({
-                one: 'Ustaw jako administratora',
-                other: 'Ustaw jako administratorów',
+                one: 'Ustaw jako administratora przestrzeni roboczej',
+                other: 'Ustaw jako administratorów przestrzeni roboczej',
             }),
             makeAuditor: () => ({
                 one: 'Ustaw jako audytora',
diff --git a/src/languages/pt-BR.ts b/src/languages/pt-BR.ts
index 99e98fd3c672..c9d1d64749c3 100644
--- a/src/languages/pt-BR.ts
+++ b/src/languages/pt-BR.ts
@@ -6218,8 +6218,8 @@ _Para instruções mais detalhadas, [visite nossa central de ajuda](${CONST.NETS
                 other: 'Tornar membros',
             }),
             makeAdmin: () => ({
-                one: 'Tornar admin',
-                other: 'Tornar admins',
+                one: 'Tornar admin do workspace',
+                other: 'Tornar admins do workspace',
             }),
             makeAuditor: () => ({
                 one: 'Tornar auditor',
diff --git a/src/languages/zh-hans.ts b/src/languages/zh-hans.ts
index 0aa5169d1c32..46e25daeaa0c 100644
--- a/src/languages/zh-hans.ts
+++ b/src/languages/zh-hans.ts
@@ -6062,8 +6062,8 @@ _如需更详细的说明，请[访问我们的帮助网站](${CONST.NETSUITE_IM
                 other: '设为成员',
             }),
             makeAdmin: () => ({
-                one: '设为管理员',
-                other: '设为管理员',
+                one: '设为工作区管理员',
+                other: '设为工作区管理员',
             }),
             makeAuditor: () => ({
                 one: '设为审计员',

From 04cac8b81c8dc530c6e7973a4043284db1b849fe Mon Sep 17 00:00:00 2001
From: OSBotify <infra+osbotify@expensify.com>
Date: Fri, 12 Jun 2026 13:49:18 +0000
Subject: [PATCH 434/435] Auto-tighten eslint-seatbelt baseline

---
 config/eslint/eslint.seatbelt.tsv | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/config/eslint/eslint.seatbelt.tsv b/config/eslint/eslint.seatbelt.tsv
index 45ee6de278c1..7efae31cde1c 100644
--- a/config/eslint/eslint.seatbelt.tsv
+++ b/config/eslint/eslint.seatbelt.tsv
@@ -377,9 +377,9 @@
 "../../src/components/Search/SearchList/ListItem/ChatListItem.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../src/components/Search/SearchList/ListItem/ExpenseReportListItem.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	5
 "../../src/components/Search/SearchList/ListItem/ExpenseReportListItemRow/ExpenseReportListItemRowWide.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
-"../../src/components/Search/SearchList/ListItem/MemberListItemHeader.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	2
 "../../src/components/Search/SearchList/ListItem/GroupChildrenContent.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	4
 "../../src/components/Search/SearchList/ListItem/GroupHeader.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	3
+"../../src/components/Search/SearchList/ListItem/MemberListItemHeader.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	2
 "../../src/components/Search/SearchList/ListItem/ReportListItemHeader.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	4
 "../../src/components/Search/SearchList/ListItem/TaskListItem.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../src/components/Search/SearchList/ListItem/TransactionGroupListExpanded.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	3
@@ -448,7 +448,7 @@
 "../../src/components/Table/TableContext.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	3
 "../../src/components/Table/TableFilterButtons/buildFilterItems.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	2
 "../../src/components/Table/middlewares/filtering.ts"	"@typescript-eslint/no-unsafe-type-assertion"	3
-"../../src/components/Tables/WorkspaceCompanyCardsTable/WorkspaceCompanyCardsTableRow.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	3
+"../../src/components/Tables/WorkspaceCompanyCardsTable/WorkspaceCompanyCardsTableRow.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../src/components/TagPicker/index.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../src/components/TaxPicker.tsx"	"@typescript-eslint/no-unsafe-type-assertion"	1
 "../../src/components/TestDrive/Modal/AdminTestDriveModal.tsx"	"no-restricted-imports"	1

From 31c3240d44991da1265bd92e6e62c689d4f5c320 Mon Sep 17 00:00:00 2001
From: RanuK12 <ranucoliemilio@gmail.com>
Date: Fri, 12 Jun 2026 16:22:05 +0000
Subject: [PATCH 435/435] fix: add optimistic state update to
 submitMoneyRequestOnSearch for offline submit [ranukita:f5e7e7]

---
 src/libs/actions/Search.ts | 15 +++++++++++++--
 1 file changed, 13 insertions(+), 2 deletions(-)

diff --git a/src/libs/actions/Search.ts b/src/libs/actions/Search.ts
index f5c969ebd0cd..f7441b0a8bab 100644
--- a/src/libs/actions/Search.ts
+++ b/src/libs/actions/Search.ts
@@ -31,7 +31,7 @@ import type {SearchFullscreenNavigatorParamList} from '@libs/Navigation/types';
 import enhanceParameters from '@libs/Network/enhanceParameters';
 import {rand64} from '@libs/NumberUtils';
 import {getActivePaymentType} from '@libs/PaymentUtils';
-import {getSubmitReportManagerAccountID, getValidConnectedIntegration, isDelayedSubmissionEnabled} from '@libs/PolicyUtils';
+import {getSubmitReportManagerAccountID, getValidConnectedIntegration, isDelayedSubmissionEnabled, isSubmitAndClose} from '@libs/PolicyUtils';
 import type {OptimisticExportIntegrationAction} from '@libs/ReportUtils';
 import {
     buildOptimisticExportIntegrationAction,
@@ -840,12 +840,23 @@ function search({
 
 function submitMoneyRequestOnSearch(hash: number, reportList: Report[], policy: Policy[], currentSearchKey?: SearchKey) {
     const firstReport = (reportList.at(0) ?? {}) as Report;
-    const optimisticData: Array<OnyxUpdate<typeof ONYXKEYS.COLLECTION.RAM_ONLY_REPORT_LOADING_STATE>> = [
+    const isSubmitAndClosePolicy = isSubmitAndClose(policy.at(0));
+    const optimisticData: Array<
+        OnyxUpdate<typeof ONYXKEYS.COLLECTION.RAM_ONLY_REPORT_LOADING_STATE | typeof ONYXKEYS.COLLECTION.REPORT>
+    > = [
         {
             onyxMethod: Onyx.METHOD.MERGE_COLLECTION,
             key: ONYXKEYS.COLLECTION.RAM_ONLY_REPORT_LOADING_STATE,
             value: Object.fromEntries(reportList.map((report) => [`${ONYXKEYS.COLLECTION.RAM_ONLY_REPORT_LOADING_STATE}${report?.reportID}`, {isActionLoading: true}])),
         },
+        ...reportList.map((report) => ({
+            onyxMethod: Onyx.METHOD.MERGE as const,
+            key: `${ONYXKEYS.COLLECTION.REPORT}${report?.reportID}`,
+            value: {
+                stateNum: isSubmitAndClosePolicy ? CONST.REPORT.STATE_NUM.APPROVED : CONST.REPORT.STATE_NUM.SUBMITTED,
+                statusNum: isSubmitAndClosePolicy ? CONST.REPORT.STATUS_NUM.CLOSED : CONST.REPORT.STATUS_NUM.SUBMITTED,
+            },
+        })),
     ];
 
     const successData: Array<OnyxUpdate<typeof ONYXKEYS.COLLECTION.RAM_ONLY_REPORT_LOADING_STATE | typeof ONYXKEYS.COLLECTION.SNAPSHOT>> = [
