Skip to content

Add 'Don't show this again' checkbox for empty reports dialog#75442

Merged
puneetlath merged 14 commits intoExpensify:mainfrom
ShridharGoel:emptyReportsCheckBox
Dec 9, 2025
Merged

Add 'Don't show this again' checkbox for empty reports dialog#75442
puneetlath merged 14 commits intoExpensify:mainfrom
ShridharGoel:emptyReportsCheckBox

Conversation

@ShridharGoel
Copy link
Contributor

@ShridharGoel ShridharGoel commented Nov 18, 2025

Explanation of Change

Add 'Don't show this again' checkbox for empty reports dialog.

Fixed Issues

$ #74962
PROPOSAL:

Tests

  1. Create the first empty report. It should get created without any dialog.
  2. Create another empty report. It should show confirmation dialog.
  3. Click "Create report" button in the dialog.
  4. Verify that new empty report is created.
  5. Create another empty report. It should show confirmation dialog.
  6. Select "Don't show me this again" checkbox.
  7. Click "Create report" button in the dialog.
  8. Verify that new empty report is created.
  9. Create another empty report. It should get created without any dialog.
  10. Create yet another empty report. It should get created without any dialog.
  • Verify that no errors appear in the JS console

Offline tests

QA Steps

Same as tests.

  • Verify that no errors appear in the JS console

PR Author Checklist

  • I linked the correct issue in the ### Fixed Issues section above
  • I wrote clear testing steps that cover the changes made in this PR
    • I added steps for local testing in the Tests section
    • I added steps for the expected offline behavior in the Offline steps section
    • I added steps for Staging and/or Production testing in the QA steps section
    • I added steps to cover failure scenarios (i.e. verify an input displays the correct error message if the entered data is not correct)
    • I turned off my network connection and tested it while offline to ensure it matches the expected behavior (i.e. verify the default avatar icon is displayed if app is offline)
    • I tested this PR with a High Traffic account against the staging or production API to ensure there are no regressions (e.g. long loading states that impact usability).
  • I included screenshots or videos for tests on all platforms
  • I ran the tests on all platforms & verified they passed on:
    • Android: Native
    • Android: mWeb Chrome
    • iOS: Native
    • iOS: mWeb Safari
    • MacOS: Chrome / Safari
    • MacOS: Desktop
  • I verified there are no console errors (if there's a console error not related to the PR, report it or open an issue for it to be fixed)
  • I verified there are no new alerts related to the canBeMissing param for useOnyx
  • I followed proper code patterns (see Reviewing the code)
    • I verified that any callback methods that were added or modified are named for what the method does and never what callback they handle (i.e. toggleReport and not onIconClick)
    • I verified that comments were added to code that is not self explanatory
    • I verified that any new or modified comments were clear, correct English, and explained "why" the code was doing something instead of only explaining "what" the code was doing.
    • I verified any copy / text shown in the product is localized by adding it to src/languages/* files and using the translation method
    • I verified all numbers, amounts, dates and phone numbers shown in the product are using the localization methods
    • I verified any copy / text that was added to the app is grammatically correct in English. It adheres to proper capitalization guidelines (note: only the first word of header/labels should be capitalized), and is either coming verbatim from figma or has been approved by marketing (in order to get marketing approval, ask the Bug Zero team member to add the Waiting for copy label to the issue)
    • I verified proper file naming conventions were followed for any new files or renamed files. All non-platform specific files are named after what they export and are not named "index.js". All platform-specific files are named for the platform the code supports as outlined in the README.
    • I verified the JSDocs style guidelines (in STYLE.md) were followed
  • If a new code pattern is added I verified it was agreed to be used by multiple Expensify engineers
  • I followed the guidelines as stated in the Review Guidelines
  • I tested other components that can be impacted by my changes (i.e. if the PR modifies a shared library or component like Avatar, I verified the components using Avatar are working as expected)
  • I verified all code is DRY (the PR doesn't include any logic written more than once, with the exception of tests)
  • I verified any variables that can be defined as constants (ie. in CONST.ts or at the top of the file that uses the constant) are defined as such
  • I verified that if a function's arguments changed that all usages have also been updated correctly
  • If any new file was added I verified that:
    • The file has a description of what it does and/or why is needed at the top of the file if the code is not self explanatory
  • If a new CSS style is added I verified that:
    • A similar style doesn't already exist
    • The style can't be created with an existing StyleUtils function (i.e. StyleUtils.getBackgroundAndBorderStyle(theme.componentBG))
  • If new assets were added or existing ones were modified, I verified that:
    • The assets are optimized and compressed (for SVG files, run npm run compress-svg)
    • The assets load correctly across all supported platforms.
  • If the PR modifies code that runs when editing or sending messages, I tested and verified there is no unexpected behavior for all supported markdown - URLs, single line code, code blocks, quotes, headings, bold, strikethrough, and italic.
  • If the PR modifies a generic component, I tested and verified that those changes do not break usages of that component in the rest of the App (i.e. if a shared library or component like Avatar is modified, I verified that Avatar is working as expected in all cases)
  • If the PR modifies a component related to any of the existing Storybook stories, I tested and verified all stories for that component are still working as expected.
  • If the PR modifies a component or page that can be accessed by a direct deeplink, I verified that the code functions as expected when the deeplink is used - from a logged in and logged out account.
  • If the PR modifies the UI (e.g. new buttons, new UI components, changing the padding/spacing/sizing, moving components, etc) or modifies the form input styles:
    • I verified that all the inputs inside a form are aligned with each other.
    • I added Design label and/or tagged @Expensify/design so the design team can review the changes.
  • If a new page is added, I verified it's using the ScrollView component to make it scrollable when more elements are added to the page.
  • I added unit tests for any new feature or bug fix in this PR to help automatically prevent regressions in this user flow.
  • If the main branch was merged into this PR after a review, I tested again and verified the outcome was still expected according to the Test steps.

Screenshots/Videos

Android: Native
Screen.Recording.2025-11-18.at.11.58.06.PM.mov
Android: mWeb Chrome
Screen.Recording.2025-11-18.at.11.59.06.PM.mov
iOS: Native
Screen.Recording.2025-11-19.at.12.04.29.AM.mov
iOS: mWeb Safari
Screen.Recording.2025-11-19.at.12.06.24.AM.mov
MacOS: Chrome / Safari
Screen.Recording.2025-11-18.at.11.56.52.PM.mov
MacOS: Desktop
Screen.Recording.2025-11-19.at.12.11.27.AM.mov

@melvin-bot
Copy link

melvin-bot bot commented Nov 18, 2025

Hey, I noticed you changed src/languages/en.ts in a PR from a fork. For security reasons, translations are not generated automatically for PRs from forks.

If you want to automatically generate translations for other locales, an Expensify employee will have to:

  1. Look at the code and make sure there are no malicious changes.
  2. Run the Generate static translations GitHub workflow. If you have write access and the K2 extension, you can simply click: [this button]

Alternatively, if you are an external contributor, you can run the translation script locally with your own OpenAI API key. To learn more, try running:

npx ts-node ./scripts/generateTranslations.ts --help

Typically, you'd want to translate only what you changed by running npx ts-node ./scripts/generateTranslations.ts --compare-ref main

@codecov
Copy link

codecov bot commented Nov 18, 2025

Codecov Report

✅ Changes either increased or maintained existing code coverage, great job!

Files with missing lines Coverage Δ
src/ONYXKEYS.ts 100.00% <ø> (ø)
src/hooks/useCreateEmptyReportConfirmation.tsx 100.00% <100.00%> (ø)
src/hooks/useSearchTypeMenuSections.ts 100.00% <100.00%> (ø)
src/libs/actions/Report.ts 54.27% <66.66%> (+0.02%) ⬆️
...rc/pages/Search/SearchTransactionsChangeReport.tsx 0.00% <0.00%> (ø)
...rc/pages/iou/request/step/IOURequestEditReport.tsx 0.00% <0.00%> (ø)
...rc/pages/iou/request/step/IOURequestStepReport.tsx 0.00% <0.00%> (ø)
src/pages/Search/EmptySearchView.tsx 87.09% <60.00%> (+0.14%) ⬆️
...ortActionCompose/AttachmentPickerWithMenuItems.tsx 48.43% <50.00%> (+0.81%) ⬆️
...oks/useConditionalCreateEmptyReportConfirmation.ts 0.00% <0.00%> (ø)
... and 2 more
... and 13 files with indirect coverage changes

@ShridharGoel ShridharGoel marked this pull request as ready for review November 18, 2025 18:42
@ShridharGoel ShridharGoel requested review from a team as code owners November 18, 2025 18:42
@melvin-bot melvin-bot bot requested review from heyjennahay and hungvu193 and removed request for a team November 18, 2025 18:42
@melvin-bot
Copy link

melvin-bot bot commented Nov 18, 2025

@hungvu193 Please copy/paste the Reviewer Checklist from here into a new comment on this PR and complete it. If you have the K2 extension, you can simply click: [this button]

@melvin-bot melvin-bot bot removed the request for review from a team November 18, 2025 18:42
<CheckboxWithLabel
accessibilityLabel={translate('report.newReport.emptyReportConfirmationDontShowAgain')}
label={translate('report.newReport.emptyReportConfirmationDontShowAgain')}
isChecked={shouldDismissEmptyReportsConfirmation}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

❌ PERF-4 (docs)

The inline arrow function (value) => setShouldDismissEmptyReportsConfirmation(!!value) creates a new function reference on every render, causing unnecessary re-renders of the CheckboxWithLabel component.

Suggested fix: Extract this into a memoized callback:

const handleCheckboxChange = useCallback((value: boolean) => {
    setShouldDismissEmptyReportsConfirmation(!!value);
}, []);

// Then in the prompt useMemo:
<CheckboxWithLabel
    accessibilityLabel={translate('report.newReport.emptyReportConfirmationDontShowAgain')}
    label={translate('report.newReport.emptyReportConfirmationDontShowAgain')}
    isChecked={shouldDismissEmptyReportsConfirmation}
    onInputChange={handleCheckboxChange}
/>

policyID: report?.policyID,
policyName: policy?.name ?? '',
onConfirm: () => selectOption(() => createNewReport(currentUserPersonalDetails, isASAPSubmitBetaEnabled, hasViolations, report?.policyID, true), true),
onConfirm: (shouldDismissEmptyReportsConfirmation) =>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

❌ PERF-4 (docs)

The inline arrow function (shouldDismissEmptyReportsConfirmation) => selectOption(...) creates a new function reference on every render, causing the useCreateEmptyReportConfirmation hook to potentially recreate its internal state unnecessarily.

Suggested fix: Memoize this callback using useCallback:

const handleConfirmCreateReport = useCallback(
    (shouldDismissEmptyReportsConfirmation: boolean) => {
        selectOption(
            () => createNewReport(currentUserPersonalDetails, isASAPSubmitBetaEnabled, hasViolations, report?.policyID, true, shouldDismissEmptyReportsConfirmation),
            true
        );
    },
    [currentUserPersonalDetails, hasViolations, isASAPSubmitBetaEnabled, report?.policyID, selectOption]
);

// Then use it:
const {openCreateReportConfirmation, CreateReportConfirmationModal} = useCreateEmptyReportConfirmation({
    policyID: report?.policyID,
    policyName: policy?.name ?? '',
    onConfirm: handleConfirmCreateReport,
});

@ShridharGoel
Copy link
Contributor Author

Typecheck issues will be fixed after someone runs the translations gen script.

heyjennahay
heyjennahay previously approved these changes Nov 18, 2025
Copy link
Contributor

@heyjennahay heyjennahay left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No concern with product change

reportID: optimisticReportID,
reportActionID,
reportPreviewReportActionID,
...(shouldDismissEmptyReportsConfirmation ? {shouldDismissEmptyReportsConfirmation} : {}),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why are we spreading this?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because this param is optional. We'll not be sending it during a normal report creation.

import ConfirmModal from '@components/ConfirmModal';
import Text from '@components/Text';
import TextLink from '@components/TextLink';
import useThemeStyles from '@hooks/useThemeStyles';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please fix the eslint

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can't see any ESLint issue here, can you check again?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You need to view it under github file 😄

Image

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok thanks, I was checking for errors in the list of checks.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please fix the linting 😄 .

Also @rushatgabhane, we also need to wait for BE updates right?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

they are deployed to production

@hungvu193
Copy link
Contributor

I'll be OOO till 29th Nov

@hungvu193
Copy link
Contributor

QA favorite testcase, after clear cache and restart the confirm modal show up again even when we checked the Don't show this again before.

Screen.Recording.2025-11-30.at.13.30.14.mov

@ShridharGoel
Copy link
Contributor Author

@hungvu193 I think that's because we don't have the value from the backend when trying after clearing the cache.

@puneetlath
Copy link
Contributor

Sounds good. I'll review that one, but it shouldn't need to block this one.

@hungvu193
Copy link
Contributor

@ShridharGoel Please merge main. I'll complete the checklist in the meantime.

@ShridharGoel ShridharGoel marked this pull request as draft December 4, 2025 15:11
@ShridharGoel ShridharGoel marked this pull request as ready for review December 4, 2025 17:17
@ShridharGoel
Copy link
Contributor Author

@hungvu193 Updated

@ShridharGoel
Copy link
Contributor Author

@puneetlath Can you help with running the translations job?

@OSBotify
Copy link
Contributor

OSBotify commented Dec 4, 2025

🦜 Polyglot Parrot! 🦜

Squawk! Looks like you added some shiny new English strings. Allow me to parrot them back to you in other tongues:

View the translation diff
diff --git a/src/languages/de.ts b/src/languages/de.ts
index bc1a19e7..fd97a740 100644
--- a/src/languages/de.ts
+++ b/src/languages/de.ts
@@ -2546,20 +2546,20 @@ ${amount} für ${merchant} - ${date}`,
                     `Verbinde${integrationName === CONST.ONBOARDING_ACCOUNTING_MAPPING.other ? '' : ' mit'} [${integrationName === CONST.ONBOARDING_ACCOUNTING_MAPPING.other ? 'deiner' : ''} ${integrationName}](${workspaceAccountingLink})`,
                 description: ({integrationName, workspaceAccountingLink}) =>
                     dedent(`
-                        Verbinde ${integrationName === CONST.ONBOARDING_ACCOUNTING_MAPPING.other ? 'Ihr' : 'bis'} ${integrationName} für die automatische Kategorisierung und Synchronisierung von Ausgaben, damit der Monatsabschluss zum Kinderspiel wird.
+                        Verbinden Sie ${integrationName === CONST.ONBOARDING_ACCOUNTING_MAPPING.other ? 'dein' : 'an'} ${integrationName} für automatische Ausgabenkodierung und Synchronisierung, die den Monatsabschluss zum Kinderspiel macht.
 
-                        1. Klicke auf *Workspaces*.
-                        2. Wähle deinen Workspace aus.
-                        3. Klicke auf *Accounting*.
-                        4. Suche nach ${integrationName}.
-                        5. Klicke auf *Connect*.
+                        1. Klicken Sie auf *Arbeitsbereiche*.
+                        2. Wählen Sie Ihren Arbeitsbereich aus.
+                        3. Klicken Sie auf *Buchhaltung*.
+                        4. Suchen Sie nach ${integrationName}.
+                        5. Klicken Sie auf *Verbinden*.
 
 ${
     integrationName && CONST.connectionsVideoPaths[integrationName]
-        ? dedent(`[Zur Buchhaltung](${workspaceAccountingLink}).
+        ? dedent(`[Bring mich zur Buchhaltung](${workspaceAccountingLink}).
 
-![Mit ${integrationName} verbinden](${CONST.CLOUDFRONT_URL}/${CONST.connectionsVideoPaths[integrationName]})`)
-        : `[Zur Buchhaltung](${workspaceAccountingLink}).`
+                                      ![Mit ${integrationName} verbinden](${CONST.CLOUDFRONT_URL}/${CONST.connectionsVideoPaths[integrationName]})`)
+        : `[Zur Buchhaltung wechseln](${workspaceAccountingLink}).`
 }`),
             },
             connectCorporateCardTask: {
@@ -6664,6 +6664,7 @@ ${
                 `Möchtest du wirklich einen weiteren Bericht in ${workspaceName} erstellen? Du kannst auf deine leeren Berichte zugreifen unter`,
             emptyReportConfirmationPromptLink: 'Berichte',
             genericWorkspaceName: 'diesem Arbeitsbereich',
+            emptyReportConfirmationDontShowAgain: 'Nicht mehr anzeigen',
         },
         genericCreateReportFailureMessage: 'Unerwarteter Fehler beim Erstellen dieses Chats. Bitte versuchen Sie es später erneut.',
         genericAddCommentFailureMessage: 'Unerwarteter Fehler beim Posten des Kommentars. Bitte versuchen Sie es später noch einmal.',
diff --git a/src/languages/fr.ts b/src/languages/fr.ts
index 89225386..814a4e08 100644
--- a/src/languages/fr.ts
+++ b/src/languages/fr.ts
@@ -2546,19 +2546,23 @@ ${amount} pour ${merchant} - ${date}`,
                     `Connecter${integrationName === CONST.ONBOARDING_ACCOUNTING_MAPPING.other ? '' : ' à'} [${integrationName === CONST.ONBOARDING_ACCOUNTING_MAPPING.other ? 'votre' : ''} ${integrationName}](${workspaceAccountingLink})`,
                 description: ({integrationName, workspaceAccountingLink}) =>
                     dedent(`
-                        Connectez ${integrationName === CONST.ONBOARDING_ACCOUNTING_MAPPING.other ? 'votre' : 'à'} ${integrationName} pour un codage et une synchronisation automatiques des dépenses qui rendent la clôture de fin de mois un jeu d'enfant.
+                        Connectez ${
+                            integrationName === CONST.ONBOARDING_ACCOUNTING_MAPPING.other
+                                ? 'votre' //_/\__/_/  \_,_/\__/\__/\_,_/
+                                : 'à'
+                        } ${integrationName} pour le codage et la synchronisation automatiques des dépenses qui rendent la clôture de fin de mois un jeu d’enfant.
 
                         1. Cliquez sur *Workspaces*.
                         2. Sélectionnez votre espace de travail.
                         3. Cliquez sur *Accounting*.
-                        4. Recherchez ${integrationName}.
+                        4. Trouvez ${integrationName}.
                         5. Cliquez sur *Connect*.
 
 ${
     integrationName && CONST.connectionsVideoPaths[integrationName]
-        ? dedent(`[Accéder à la comptabilité](${workspaceAccountingLink}).
+        ? dedent(`[Aller à la comptabilité](${workspaceAccountingLink}).
 
-                                      ![Se connecter à ${integrationName}](${CONST.CLOUDFRONT_URL}/${CONST.connectionsVideoPaths[integrationName]})`)
+![Se connecter à ${integrationName}](${CONST.CLOUDFRONT_URL}/${CONST.connectionsVideoPaths[integrationName]})`)
         : `[Accéder à la comptabilité](${workspaceAccountingLink}).`
 }`),
             },
@@ -6672,6 +6676,7 @@ ${
                 `Êtes-vous sûr de vouloir créer un autre rapport dans ${workspaceName} ? Vous pouvez accéder à vos rapports vides dans`,
             emptyReportConfirmationPromptLink: 'Rapports',
             genericWorkspaceName: 'cet espace de travail',
+            emptyReportConfirmationDontShowAgain: 'Ne plus afficher ce message',
         },
         genericCreateReportFailureMessage: 'Erreur inattendue lors de la création de ce chat. Veuillez réessayer plus tard.',
         genericAddCommentFailureMessage: 'Erreur inattendue lors de la publication du commentaire. Veuillez réessayer plus tard.',
diff --git a/src/languages/it.ts b/src/languages/it.ts
index 5c760116..0a97482f 100644
--- a/src/languages/it.ts
+++ b/src/languages/it.ts
@@ -2534,19 +2534,19 @@ ${amount} per ${merchant} - ${date}`,
                     `Connetti${integrationName === CONST.ONBOARDING_ACCOUNTING_MAPPING.other ? '' : ' a'} [${integrationName === CONST.ONBOARDING_ACCOUNTING_MAPPING.other ? 'il tuo' : ''} ${integrationName}](${workspaceAccountingLink})`,
                 description: ({integrationName, workspaceAccountingLink}) =>
                     dedent(`
-                        Collega ${integrationName === CONST.ONBOARDING_ACCOUNTING_MAPPING.other ? 'il tuo' : 'a'} ${integrationName} per la codifica e la sincronizzazione automatiche delle spese che rendono la chiusura di fine mese un gioco da ragazzi.
+                        Collega ${integrationName === CONST.ONBOARDING_ACCOUNTING_MAPPING.other ? 'il tuo' : 'a'} ${integrationName} per la codifica e la sincronizzazione automatica delle spese che rendono la chiusura di fine mese un gioco da ragazzi.
 
-                        1. Fai clic su *Workspaces*.
-                        2. Seleziona il tuo workspace.
-                        3. Fai clic su *Accounting*.
+                        1. Fai clic su *Spazi di lavoro*.
+                        2. Seleziona il tuo spazio di lavoro.
+                        3. Fai clic su *Contabilità*.
                         4. Trova ${integrationName}.
-                        5. Fai clic su *Connect*.
+                        5. Fai clic su *Connetti*.
 
 ${
     integrationName && CONST.connectionsVideoPaths[integrationName]
         ? dedent(`[Portami alla contabilità](${workspaceAccountingLink}).
 
-                                      ![Connetti a ${integrationName}](${CONST.CLOUDFRONT_URL}/${CONST.connectionsVideoPaths[integrationName]})`)
+![Connetti a ${integrationName}](${CONST.CLOUDFRONT_URL}/${CONST.connectionsVideoPaths[integrationName]})`)
         : `[Portami alla contabilità](${workspaceAccountingLink}).`
 }`),
             },
@@ -6653,6 +6653,7 @@ ${
                 `Sei sicuro di voler creare un altro rapporto in ${workspaceName}? Puoi accedere ai tuoi rapporti vuoti in`,
             emptyReportConfirmationPromptLink: 'Rapporti',
             genericWorkspaceName: 'questo spazio di lavoro',
+            emptyReportConfirmationDontShowAgain: 'Non mostrarmelo di nuovo',
         },
         genericCreateReportFailureMessage: 'Errore imprevisto durante la creazione di questa chat. Si prega di riprovare più tardi.',
         genericAddCommentFailureMessage: 'Errore imprevisto durante la pubblicazione del commento. Per favore riprova più tardi.',
diff --git a/src/languages/ja.ts b/src/languages/ja.ts
index 2b22bc05..469e6a01 100644
--- a/src/languages/ja.ts
+++ b/src/languages/ja.ts
@@ -2523,7 +2523,7 @@ ${date} - ${merchant}に${amount}`,
                     `${integrationName === CONST.ONBOARDING_ACCOUNTING_MAPPING.other ? '' : 'と'}[${integrationName === CONST.ONBOARDING_ACCOUNTING_MAPPING.other ? 'あなたの' : ''} ${integrationName}](${workspaceAccountingLink})と接続する`,
                 description: ({integrationName, workspaceAccountingLink}) =>
                     dedent(`
-${integrationName === CONST.ONBOARDING_ACCOUNTING_MAPPING.other ? 'あなたの' : 'まで'} の ${integrationName} を接続して、経費の自動分類と同期で月末締めをスムーズに。
+${integrationName === CONST.ONBOARDING_ACCOUNTING_MAPPING.other ? 'あなたの' : 'to'} ${integrationName} を接続して、月末締めがスムーズになる自動経費のコード化と同期を実現しましょう。
 
                         1. *Workspaces* をクリックします。
                         2. ワークスペースを選択します。
@@ -2535,8 +2535,8 @@ ${
     integrationName && CONST.connectionsVideoPaths[integrationName]
         ? dedent(`[会計に移動](${workspaceAccountingLink}).
 
-                                      ![${integrationName} に接続](${CONST.CLOUDFRONT_URL}/${CONST.connectionsVideoPaths[integrationName]})`)
-        : `[会計に移動](${workspaceAccountingLink}).`
+                                      ![${integrationName}に接続](${CONST.CLOUDFRONT_URL}/${CONST.connectionsVideoPaths[integrationName]})`)
+        : `[会計へ移動](${workspaceAccountingLink}).`
 }`),
             },
             connectCorporateCardTask: {
@@ -6586,6 +6586,7 @@ ${
             emptyReportConfirmationPrompt: ({workspaceName}: {workspaceName: string}) => `${workspaceName} で別のレポートを作成しますか? 空のレポートには次からアクセスできます`,
             emptyReportConfirmationPromptLink: 'レポート',
             genericWorkspaceName: 'このワークスペース',
+            emptyReportConfirmationDontShowAgain: '今後表示しない',
         },
         genericCreateReportFailureMessage: 'このチャットの作成中に予期しないエラーが発生しました。後でもう一度お試しください。',
         genericAddCommentFailureMessage: 'コメントの投稿中に予期しないエラーが発生しました。後でもう一度お試しください。',
diff --git a/src/languages/nl.ts b/src/languages/nl.ts
index 57ec44ef..452b008e 100644
--- a/src/languages/nl.ts
+++ b/src/languages/nl.ts
@@ -2533,9 +2533,9 @@ ${amount} voor ${merchant} - ${date}`,
                     `Verbind${integrationName === CONST.ONBOARDING_ACCOUNTING_MAPPING.other ? '' : ' met'} [${integrationName === CONST.ONBOARDING_ACCOUNTING_MAPPING.other ? 'uw' : ''} ${integrationName}](${workspaceAccountingLink})`,
                 description: ({integrationName, workspaceAccountingLink}) =>
                     dedent(`
-                        Verbind ${integrationName === CONST.ONBOARDING_ACCOUNTING_MAPPING.other ? 'jouw' : 'tot'} ${integrationName} voor automatische onkostencodering en synchronisatie, waardoor de maandafsluiting een fluitje van een cent wordt.
+                        Verbind ${integrationName === CONST.ONBOARDING_ACCOUNTING_MAPPING.other ? 'jouw' : 'tot'} ${integrationName} voor automatische uitgavencodering en synchronisatie, waardoor de maandafsluiting een fluitje van een cent wordt.
 
-                        1. Klik op *Werkruimtes*.
+                        1. Klik op *Werkruimten*.
                         2. Selecteer je werkruimte.
                         3. Klik op *Boekhouding*.
                         4. Zoek ${integrationName}.
@@ -2543,10 +2543,10 @@ ${amount} voor ${merchant} - ${date}`,
 
 ${
     integrationName && CONST.connectionsVideoPaths[integrationName]
-        ? dedent(`[Breng me naar de boekhouding](${workspaceAccountingLink}).
+        ? dedent(`[Ga naar de boekhouding](${workspaceAccountingLink}).
 
-                                      ![Verbinding maken met ${integrationName}](${CONST.CLOUDFRONT_URL}/${CONST.connectionsVideoPaths[integrationName]})`)
-        : `[Breng me naar de boekhouding](${workspaceAccountingLink}).`
+                                      ![Verbind met ${integrationName}](${CONST.CLOUDFRONT_URL}/${CONST.connectionsVideoPaths[integrationName]})`)
+        : `[Ga naar de boekhouding](${workspaceAccountingLink}).`
 }`),
             },
             connectCorporateCardTask: {
@@ -6634,6 +6634,7 @@ ${
                 `Weet je zeker dat je nog een rapport wilt maken in ${workspaceName}? Je kunt je lege rapporten vinden onder`,
             emptyReportConfirmationPromptLink: 'Rapporten',
             genericWorkspaceName: 'deze werkruimte',
+            emptyReportConfirmationDontShowAgain: 'Niet meer weergeven',
         },
         genericCreateReportFailureMessage: 'Onverwachte fout bij het maken van deze chat. Probeer het later opnieuw.',
         genericAddCommentFailureMessage: 'Onverwachte fout bij het plaatsen van de opmerking. Probeer het later opnieuw.',
diff --git a/src/languages/pl.ts b/src/languages/pl.ts
index c918fef6..f459f143 100644
--- a/src/languages/pl.ts
+++ b/src/languages/pl.ts
@@ -2528,13 +2528,13 @@ ${amount} dla ${merchant} - ${date}`,
                     `Połącz${integrationName === CONST.ONBOARDING_ACCOUNTING_MAPPING.other ? '' : ' z'} [${integrationName === CONST.ONBOARDING_ACCOUNTING_MAPPING.other ? 'swoim' : ''} ${integrationName}](${workspaceAccountingLink})`,
                 description: ({integrationName, workspaceAccountingLink}) =>
                     dedent(`
-                        Połącz ${integrationName === CONST.ONBOARDING_ACCOUNTING_MAPPING.other ? 'twój' : 'Do'} ${integrationName}, aby umożliwić automatyczne kategoryzowanie wydatków i synchronizację, co ułatwia zamknięcie miesiąca.
+                        Połącz ${integrationName === CONST.ONBOARDING_ACCOUNTING_MAPPING.other ? 'Twoje' : 'do'} ${integrationName}, aby automatycznie kodować wydatki i synchronizować dane, co ułatwia zamknięcie miesiąca.
 
-                        1. Kliknij *Workspaces*.
-                        2. Wybierz swoją przestrzeń roboczą.
-                        3. Kliknij *Accounting*.
+                        1. Kliknij *Obszary robocze*.
+                        2. Wybierz swój obszar roboczy.
+                        3. Kliknij *Księgowość*.
                         4. Znajdź ${integrationName}.
-                        5. Kliknij *Connect*.
+                        5. Kliknij *Połącz*.
 
 ${
     integrationName && CONST.connectionsVideoPaths[integrationName]
@@ -5253,7 +5253,7 @@ ${
                 cardType: 'Typ karty',
                 limit: 'Limit',
                 limitType: 'Typ limitu',
-                name: 'Imię',
+                name: 'Nazwa',
                 disabledApprovalForSmartLimitError: 'Proszę włączyć zatwierdzenia w <strong>Przepływy pracy > Dodaj zatwierdzenia</strong> przed skonfigurowaniem inteligentnych limitów',
             },
             deactivateCardModal: {
@@ -6621,6 +6621,7 @@ ${
                 `Czy na pewno chcesz utworzyć kolejny raport w ${workspaceName}? Do pustych raportów możesz przejść w`,
             emptyReportConfirmationPromptLink: 'Raporty',
             genericWorkspaceName: 'tej przestrzeni roboczej',
+            emptyReportConfirmationDontShowAgain: 'Nie pokazuj tego ponownie',
         },
         genericCreateReportFailureMessage: 'Nieoczekiwany błąd podczas tworzenia tego czatu. Proszę spróbować ponownie później.',
         genericAddCommentFailureMessage: 'Nieoczekiwany błąd podczas publikowania komentarza. Spróbuj ponownie później.',
diff --git a/src/languages/pt-BR.ts b/src/languages/pt-BR.ts
index 3ef34b54..6a640b29 100644
--- a/src/languages/pt-BR.ts
+++ b/src/languages/pt-BR.ts
@@ -2528,20 +2528,20 @@ ${amount} para ${merchant} - ${date}`,
                     `Conecte-se${integrationName === CONST.ONBOARDING_ACCOUNTING_MAPPING.other ? '' : ' ao'} [${integrationName === CONST.ONBOARDING_ACCOUNTING_MAPPING.other ? 'seu' : ''} ${integrationName}](${workspaceAccountingLink})`,
                 description: ({integrationName, workspaceAccountingLink}) =>
                     dedent(`
-                        Conecte ${integrationName === CONST.ONBOARDING_ACCOUNTING_MAPPING.other ? 'seu' : 'para'} ${integrationName} para classificação e sincronização automáticas de despesas que tornam o fechamento de fim de mês muito mais simples.
+                        Conecte ${integrationName === CONST.ONBOARDING_ACCOUNTING_MAPPING.other ? 'seu' : 'para'} ${integrationName} para codificação e sincronização automáticas de despesas que tornam o fechamento do mês muito mais fácil.
 
-                        1. Clique em *Espaços de trabalho*.
+                        1. Clique em *Workspaces*.
                         2. Selecione seu espaço de trabalho.
-                        3. Clique em *Contabilidade*.
+                        3. Clique em *Accounting*.
                         4. Encontre ${integrationName}.
-                        5. Clique em *Conectar*.
+                        5. Clique em *Connect*.
 
 ${
     integrationName && CONST.connectionsVideoPaths[integrationName]
         ? dedent(`[Ir para a contabilidade](${workspaceAccountingLink}).
 
                                       ![Conectar ao ${integrationName}](${CONST.CLOUDFRONT_URL}/${CONST.connectionsVideoPaths[integrationName]})`)
-        : `[Ir para a contabilidade](${workspaceAccountingLink}).`
+        : `[Leve-me para a contabilidade](${workspaceAccountingLink}).`
 }`),
             },
             connectCorporateCardTask: {
@@ -6633,6 +6633,7 @@ ${
                 `Tem certeza de que deseja criar outro relatório em ${workspaceName}? Você pode acessar seus relatórios vazios em`,
             emptyReportConfirmationPromptLink: 'Relatórios',
             genericWorkspaceName: 'este espaço de trabalho',
+            emptyReportConfirmationDontShowAgain: 'Não mostrar isso novamente',
         },
         genericCreateReportFailureMessage: 'Erro inesperado ao criar este chat. Por favor, tente novamente mais tarde.',
         genericAddCommentFailureMessage: 'Erro inesperado ao postar o comentário. Por favor, tente novamente mais tarde.',
diff --git a/src/languages/zh-hans.ts b/src/languages/zh-hans.ts
index f742e01f..25c84a82 100644
--- a/src/languages/zh-hans.ts
+++ b/src/languages/zh-hans.ts
@@ -2496,20 +2496,20 @@ ${merchant}的${amount} - ${date}`,
                     `连接${integrationName === CONST.ONBOARDING_ACCOUNTING_MAPPING.other ? '' : '到'}[${integrationName === CONST.ONBOARDING_ACCOUNTING_MAPPING.other ? '您的' : ''} ${integrationName}](${workspaceAccountingLink})`,
                 description: ({integrationName, workspaceAccountingLink}) =>
                     dedent(`
-                        连接 ${integrationName === CONST.ONBOARDING_ACCOUNTING_MAPPING.other ? '您的' : '至'} ${integrationName},实现自动费用编码与同步,让月末结账轻松无忧。
+                        连接 ${integrationName === CONST.ONBOARDING_ACCOUNTING_MAPPING.other ? '您的' : '至'} ${integrationName},实现自动费用编码和同步,让月末结账轻而易举。
 
-                        1. 点击*工作区*。
-                        2. 选择您的工作区。
-                        3. 点击*会计*。
+                        1. 点击 *Workspaces*。
+                        2. 选择你的工作区。
+                        3. 点击 *Accounting*。
                         4. 找到 ${integrationName}。
-                        5. 点击*连接*。
+                        5. 点击 *Connect*。
 
 ${
     integrationName && CONST.connectionsVideoPaths[integrationName]
-        ? dedent(`[前往会计](${workspaceAccountingLink}).
+        ? dedent(`[带我前往会计](${workspaceAccountingLink}).
 
 ![连接到 ${integrationName}](${CONST.CLOUDFRONT_URL}/${CONST.connectionsVideoPaths[integrationName]})`)
-        : `[前往会计](${workspaceAccountingLink}).`
+        : `[带我前往会计](${workspaceAccountingLink}).`
 }`),
             },
             connectCorporateCardTask: {
@@ -5159,7 +5159,7 @@ ${
                 cardType: '卡类型',
                 limit: '限制',
                 limitType: '限制类型',
-                name: '名称',
+                name: '姓名',
                 disabledApprovalForSmartLimitError: '请在<strong>工作流程 > 添加审批</strong>中启用审批,然后再设置智能限制',
             },
             deactivateCardModal: {
@@ -6496,6 +6496,7 @@ ${
             emptyReportConfirmationPrompt: ({workspaceName}: {workspaceName: string}) => `确定要在 ${workspaceName} 中再创建一个报告吗?你可以在以下位置访问你的空报告`,
             emptyReportConfirmationPromptLink: '报告',
             genericWorkspaceName: '此工作区',
+            emptyReportConfirmationDontShowAgain: '不再显示此内容',
         },
         genericCreateReportFailureMessage: '创建此聊天时出现意外错误。请稍后再试。',
         genericAddCommentFailureMessage: '发表评论时出现意外错误。请稍后再试。',

Note

You can apply these changes to your branch by copying the patch to your clipboard, then running pbpaste | git apply 😉

@hungvu193
Copy link
Contributor

hungvu193 commented Dec 6, 2025

Reviewer Checklist

  • I have verified the author checklist is complete (all boxes are checked off).
  • I verified the correct issue is linked in the ### Fixed Issues section above
  • I verified testing steps are clear and they cover the changes made in this PR
    • I verified the steps for local testing are in the Tests section
    • I verified the steps for Staging and/or Production testing are in the QA steps section
    • I verified the steps cover any possible failure scenarios (i.e. verify an input displays the correct error message if the entered data is not correct)
    • I turned off my network connection and tested it while offline to ensure it matches the expected behavior (i.e. verify the default avatar icon is displayed if app is offline)
  • I checked that screenshots or videos are included for tests on all platforms
  • I included screenshots or videos for tests on all platforms
  • I verified that the composer does not automatically focus or open the keyboard on mobile unless explicitly intended. This includes checking that returning the app from the background does not unexpectedly open the keyboard.
  • I verified tests pass on all platforms & I tested again on:
    • Android: HybridApp
    • Android: mWeb Chrome
    • iOS: HybridApp
    • iOS: mWeb Safari
    • MacOS: Chrome / Safari
  • If there are any errors in the console that are unrelated to this PR, I either fixed them (preferred) or linked to where I reported them in Slack
  • I verified there are no new alerts related to the canBeMissing param for useOnyx
  • I verified proper code patterns were followed (see Reviewing the code)
    • I verified that any callback methods that were added or modified are named for what the method does and never what callback they handle (i.e. toggleReport and not onIconClick).
    • I verified that comments were added to code that is not self explanatory
    • I verified that any new or modified comments were clear, correct English, and explained "why" the code was doing something instead of only explaining "what" the code was doing.
    • I verified any copy / text shown in the product is localized by adding it to src/languages/* files and using the translation method
    • I verified all numbers, amounts, dates and phone numbers shown in the product are using the localization methods
    • I verified any copy / text that was added to the app is grammatically correct in English. It adheres to proper capitalization guidelines (note: only the first word of header/labels should be capitalized), and is either coming verbatim from figma or has been approved by marketing (in order to get marketing approval, ask the Bug Zero team member to add the Waiting for copy label to the issue)
    • I verified proper file naming conventions were followed for any new files or renamed files. All non-platform specific files are named after what they export and are not named "index.js". All platform-specific files are named for the platform the code supports as outlined in the README.
    • I verified the JSDocs style guidelines (in STYLE.md) were followed
  • If a new code pattern is added I verified it was agreed to be used by multiple Expensify engineers
  • I verified that this PR follows the guidelines as stated in the Review Guidelines
  • I verified other components that can be impacted by these changes have been tested, and I retested again (i.e. if the PR modifies a shared library or component like Avatar, I verified the components using Avatar have been tested & I retested again)
  • I verified all code is DRY (the PR doesn't include any logic written more than once, with the exception of tests)
  • I verified any variables that can be defined as constants (ie. in CONST.ts or at the top of the file that uses the constant) are defined as such
  • If a new component is created I verified that:
    • A similar component doesn't exist in the codebase
    • All props are defined accurately and each prop has a /** comment above it */
    • The file is named correctly
    • The component has a clear name that is non-ambiguous and the purpose of the component can be inferred from the name alone
    • The only data being stored in the state is data necessary for rendering and nothing else
    • For Class Components, any internal methods passed to components event handlers are bound to this properly so there are no scoping issues (i.e. for onClick={this.submit} the method this.submit should be bound to this in the constructor)
    • Any internal methods bound to this are necessary to be bound (i.e. avoid this.submit = this.submit.bind(this); if this.submit is never passed to a component event handler like onClick)
    • All JSX used for rendering exists in the render method
    • The component has the minimum amount of code necessary for its purpose, and it is broken down into smaller components in order to separate concerns and functions
  • If any new file was added I verified that:
    • The file has a description of what it does and/or why is needed at the top of the file if the code is not self explanatory
  • If a new CSS style is added I verified that:
    • A similar style doesn't already exist
    • The style can't be created with an existing StyleUtils function (i.e. StyleUtils.getBackgroundAndBorderStyle(theme.componentBG)
  • If the PR modifies code that runs when editing or sending messages, I tested and verified there is no unexpected behavior for all supported markdown - URLs, single line code, code blocks, quotes, headings, bold, strikethrough, and italic.
  • If the PR modifies a generic component, I tested and verified that those changes do not break usages of that component in the rest of the App (i.e. if a shared library or component like Avatar is modified, I verified that Avatar is working as expected in all cases)
  • If the PR modifies a component related to any of the existing Storybook stories, I tested and verified all stories for that component are still working as expected.
  • If the PR modifies a component or page that can be accessed by a direct deeplink, I verified that the code functions as expected when the deeplink is used - from a logged in and logged out account.
  • If the PR modifies the UI (e.g. new buttons, new UI components, changing the padding/spacing/sizing, moving components, etc) or modifies the form input styles:
    • I verified that all the inputs inside a form are aligned with each other.
    • I added Design label and/or tagged @Expensify/design so the design team can review the changes.
  • If a new page is added, I verified it's using the ScrollView component to make it scrollable when more elements are added to the page.
  • For any bug fix or new feature in this PR, I verified that sufficient unit tests are included to prevent regressions in this flow.
  • If the main branch was merged into this PR after a review, I tested again and verified the outcome was still expected according to the Test steps.
  • I have checked off every checkbox in the PR reviewer checklist, including those that don't apply to this PR.

Screenshots/Videos

Android: HybridApp
Screen.Recording.2025-12-10.at.12.10.29.mov
Android: mWeb Chrome
Screen.Recording.2025-12-10.at.10.53.04.mov
iOS: HybridApp
ios.mov
iOS: mWeb Safari
msafari.mov
MacOS: Chrome / Safari
Screen.Recording.2025-11-30.at.13.35.01.mov

@hungvu193
Copy link
Contributor

@ShridharGoel you might need to merge main again

@ShridharGoel
Copy link
Contributor Author

@hungvu193 Done

generateReportID,
getDisplayNameForParticipant,
getIcons,
getIcons, // eslint-disable-next-line @typescript-eslint/no-deprecated
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a new way we're supposed to be getting the icons instead?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, #74599

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok got it. And so we update this file to use the new method of loading icons? Rather than suppressing the error?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just checked again, it is actually for getReportName

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But it is for existing code, not something we have added here

@puneetlath
Copy link
Contributor

Ok sounds good. @ShridharGoel looks like theres a Jest failure.

@puneetlath
Copy link
Contributor

@hungvu193 looks like you have some missing stuff on the reviewer checklist.

@ShridharGoel
Copy link
Contributor Author

Merged main.

@ShridharGoel
Copy link
Contributor Author

@puneetlath All checks are passing.

@puneetlath puneetlath merged commit 4a4d206 into Expensify:main Dec 9, 2025
30 checks passed
@OSBotify
Copy link
Contributor

OSBotify commented Dec 9, 2025

✋ This PR was not deployed to staging yet because QA is ongoing. It will be automatically deployed to staging after the next production release.

@hungvu193
Copy link
Contributor

@hungvu193 looks like you have some missing stuff on the reviewer checklist.

Sorry I forgot to save it. I've just updated

@OSBotify
Copy link
Contributor

🚀 Deployed to staging by https://github.com/puneetlath in version: 9.2.75-0 🚀

platform result
🖥 desktop 🖥 success ✅
🕸 web 🕸 success ✅
🤖 android 🤖 success ✅
🍎 iOS 🍎 cancelled 🔪

@OSBotify
Copy link
Contributor

🚀 Deployed to staging by https://github.com/puneetlath in version: 9.2.75-0 🚀

platform result
🖥 desktop 🖥 success ✅
🕸 web 🕸 success ✅
🤖 android 🤖 success ✅
🍎 iOS 🍎 success ✅

@OSBotify
Copy link
Contributor

🚀 Deployed to staging by https://github.com/puneetlath in version: 9.2.77-0 🚀

platform result
🖥 desktop 🖥 success ✅
🕸 web 🕸 success ✅
🤖 android 🤖 cancelled 🔪
🍎 iOS 🍎 cancelled 🔪

@OSBotify
Copy link
Contributor

🚀 Deployed to production by https://github.com/yuwenmemon in version: 9.2.77-1 🚀

platform result
🖥 desktop 🖥 success ✅
🕸 web 🕸 success ✅
🤖 android 🤖 success ✅
🍎 iOS 🍎 success ✅

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants