Skip to content

Conversation

@yuwenmemon
Copy link
Contributor

@yuwenmemon yuwenmemon commented Jan 28, 2026

@arosiclair please review

Explanation of Change

Add support for the PLAIDBALANCEFAILURE ReportAction in NewDot.

Fixed Issues

For https://github.com/Expensify/Expensify/issues/593012

Tests

Followed internal steps here: https://github.com/Expensify/Web-Expensify/pull/50360

QA Steps

No QA

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
  • 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
      • If any non-english text was added/modified, I used JaimeGPT to get English > Spanish translation. I then posted it in #expensify-open-source and it was approved by an internal Expensify engineer. Link to Slack message:
    • 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
Android: mWeb Chrome
iOS: Native
iOS: mWeb Safari
MacOS: Chrome / Safari

@yuwenmemon yuwenmemon self-assigned this Jan 28, 2026
@yuwenmemon yuwenmemon requested review from a team as code owners January 28, 2026 00:03
@melvin-bot melvin-bot bot requested review from Julesssss and trjExpensify and removed request for a team January 28, 2026 00:03
@melvin-bot
Copy link

melvin-bot bot commented Jan 28, 2026

@Julesssss 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]

@OSBotify
Copy link
Contributor

🦜 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 eb5af716..501eb6e5 100644
--- a/src/languages/de.ts
+++ b/src/languages/de.ts
@@ -1524,13 +1524,7 @@ const translations: TranslationDeepObject<typeof en> = {
     notificationPreferencesPage: {
         header: 'Benachrichtigungseinstellungen',
         label: 'Benachrichtige mich über neue Nachrichten',
-        notificationPreferences: {
-            always: 'Sofort',
-            daily: 'Täglich',
-            mute: 'Stummschalten',
-            // @context UI label indicating that something is concealed or not visible to the user.
-            hidden: 'Ausgeblendet',
-        },
+        notificationPreferences: {always: 'Sofort', daily: 'Täglich', mute: 'Stummschalten', hidden: 'Ausgeblendet'},
     },
     loginField: {
         numberHasNotBeenValidated: 'Die Nummer wurde nicht bestätigt. Klicke auf die Schaltfläche, um den Bestätigungslink per SMS erneut zu senden.',
@@ -4908,11 +4902,12 @@ _Für ausführlichere Anweisungen [besuchen Sie unsere Hilfeseite](${CONST.NETSU
             cardAlreadyAssignedError: 'This card is already assigned to a user in another workspace.',
             unassignCardFailedError: 'Aufhebung der Kartenzuweisung fehlgeschlagen.',
             error: {
-                workspaceFeedsCouldNotBeLoadedTitle: 'Kartenfeeds konnten nicht geladen werden',
+                workspaceFeedsCouldNotBeLoadedTitle: 'Karten-Feeds konnten nicht geladen werden',
                 workspaceFeedsCouldNotBeLoadedMessage:
-                    'Beim Laden der Workspace-Kartenfeeds ist ein Fehler aufgetreten. Bitte versuche es erneut oder wende dich an deine Administratorin bzw. deinen Administrator.',
+                    'Beim Laden der Workspace-Kartenfeeds ist ein Fehler aufgetreten. Bitte versuche es erneut oder kontaktiere deine Administratorin bzw. deinen Administrator.',
                 feedCouldNotBeLoadedTitle: 'Dieser Feed konnte nicht geladen werden',
-                feedCouldNotBeLoadedMessage: 'Beim Laden dieses Feeds ist ein Fehler aufgetreten. Bitte versuche es erneut oder kontaktiere deine Administratorin/deinen Administrator.',
+                feedCouldNotBeLoadedMessage:
+                    'Beim Laden dieses Feeds ist ein Fehler aufgetreten. Bitte versuchen Sie es erneut oder wenden Sie sich an Ihre Administratorin bzw. Ihren Administrator.',
                 tryAgain: 'Erneut versuchen',
             },
         },
@@ -6906,7 +6901,7 @@ Fordere Spesendetails wie Belege und Beschreibungen an, lege Limits und Standard
                 on: (date?: string) => `Am ${date ?? ''}`,
                 presets: {
                     [CONST.SEARCH.DATE_PRESETS.NEVER]: 'Nie',
-                    [CONST.SEARCH.DATE_PRESETS.LAST_MONTH]: 'Letzter Monat',
+                    [CONST.SEARCH.DATE_PRESETS.LAST_MONTH]: 'Letzten Monat',
                     [CONST.SEARCH.DATE_PRESETS.THIS_MONTH]: 'Diesen Monat',
                     [CONST.SEARCH.DATE_PRESETS.LAST_STATEMENT]: 'Letzter Kontoauszug',
                 },
@@ -7126,6 +7121,8 @@ Fordere Spesendetails wie Belege und Beschreibungen an, lege Limits und Standard
                 leftTheChat: 'hat den Chat verlassen',
                 companyCardConnectionBroken: ({feedName, workspaceCompanyCardRoute}: {feedName: string; workspaceCompanyCardRoute: string}) =>
                     `Die ${feedName}-Verbindung 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 Cards weiterhin verwenden können.`,
             },
             error: {
                 invalidCredentials: 'Ungültige Anmeldedaten. Bitte überprüfen Sie die Konfiguration Ihrer Verbindung.',
diff --git a/src/languages/fr.ts b/src/languages/fr.ts
index d8a12569..8127f8a4 100644
--- a/src/languages/fr.ts
+++ b/src/languages/fr.ts
@@ -1527,13 +1527,7 @@ const translations: TranslationDeepObject<typeof en> = {
     notificationPreferencesPage: {
         header: 'Préférences de notification',
         label: 'M’avertir des nouveaux messages',
-        notificationPreferences: {
-            always: 'Immédiatement',
-            daily: 'Quotidien',
-            mute: 'Muet',
-            // @context UI label indicating that something is concealed or not visible to the user.
-            hidden: 'Masqué',
-        },
+        notificationPreferences: {always: 'Immédiatement', daily: 'Quotidien', mute: 'Muet', hidden: 'Masqué'},
     },
     loginField: {
         numberHasNotBeenValidated: 'Le numéro n’a pas été validé. Cliquez sur le bouton pour renvoyer le lien de validation par SMS.',
@@ -7137,6 +7131,8 @@ Exigez des informations de dépense comme les reçus et les descriptions, défin
                 leftTheChat: 'a quitté la discussion',
                 companyCardConnectionBroken: ({feedName, workspaceCompanyCardRoute}: {feedName: string; workspaceCompanyCardRoute: string}) =>
                     `La connexion à ${feedName} est rompue. 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.`,
             },
             error: {
                 invalidCredentials: 'Identifiants invalides, veuillez vérifier la configuration de votre connexion.',
diff --git a/src/languages/it.ts b/src/languages/it.ts
index c657ec51..91b89d42 100644
--- a/src/languages/it.ts
+++ b/src/languages/it.ts
@@ -1521,13 +1521,7 @@ const translations: TranslationDeepObject<typeof en> = {
     notificationPreferencesPage: {
         header: 'Preferenze di notifica',
         label: 'Avvisami dei nuovi messaggi',
-        notificationPreferences: {
-            always: 'Immediatamente',
-            daily: 'Giornaliero',
-            mute: 'Silenzia',
-            // @context UI label indicating that something is concealed or not visible to the user.
-            hidden: 'Nascosto',
-        },
+        notificationPreferences: {always: 'Immediatamente', daily: 'Giornaliero', mute: 'Silenzia', hidden: 'Nascosto'},
     },
     loginField: {
         numberHasNotBeenValidated: 'Il numero non è stato convalidato. Fai clic sul pulsante per inviare nuovamente il link di convalida tramite SMS.',
@@ -4894,9 +4888,9 @@ _Per istruzioni più dettagliate, [visita il nostro sito di assistenza](${CONST.
             cardAlreadyAssignedError: 'This card is already assigned to a user in another workspace.',
             unassignCardFailedError: 'Rimozione della carta non riuscita.',
             error: {
-                workspaceFeedsCouldNotBeLoadedTitle: 'Impossibile caricare i feed delle carte',
+                workspaceFeedsCouldNotBeLoadedTitle: 'Impossibile caricare i feed della carta',
                 workspaceFeedsCouldNotBeLoadedMessage:
-                    'Si è verificato un errore durante il caricamento dei feed della scheda dell’area di lavoro. Riprova o contatta il tuo amministratore.',
+                    'Si è verificato un errore durante il caricamento dei feed delle schede dell’area di lavoro. Riprova o contatta il tuo amministratore.',
                 feedCouldNotBeLoadedTitle: 'Impossibile caricare questo feed',
                 feedCouldNotBeLoadedMessage: 'Si è verificato un errore durante il caricamento di questo feed. Riprova o contatta il tuo amministratore.',
                 tryAgain: 'Riprova',
@@ -6937,7 +6931,7 @@ Richiedi dettagli di spesa come ricevute e descrizioni, imposta limiti e valori
             groupBy: {
                 [CONST.SEARCH.GROUP_BY.FROM]: 'Da',
                 [CONST.SEARCH.GROUP_BY.CARD]: 'Carta',
-                [CONST.SEARCH.GROUP_BY.WITHDRAWAL_ID]: 'ID prelievo',
+                [CONST.SEARCH.GROUP_BY.WITHDRAWAL_ID]: 'ID prelievo', //_/\__/_/  \_,_/\__/\__/\_,_/
                 [CONST.SEARCH.GROUP_BY.CATEGORY]: 'Categoria',
             },
             feed: 'Feed',
@@ -7116,6 +7110,8 @@ Richiedi dettagli di spesa come ricevute e descrizioni, imposta limiti e valori
                 leftTheChat: 'ha lasciato la chat',
                 companyCardConnectionBroken: ({feedName, workspaceCompanyCardRoute}: {feedName: string; workspaceCompanyCardRoute: string}) =>
                     `La connessione ${feedName} non funziona. Per ripristinare le importazioni delle carte, <a href='${workspaceCompanyCardRoute}'>accedi alla tua banca</a>`,
+                plaidBalanceFailure: ({maskedAccountNumber, walletRoute}: {maskedAccountNumber: string; walletRoute: string}) =>
+                    `la connessione Plaid al tuo conto bancario aziendale non funziona. Per favore <a href='${walletRoute}'>ricollega il tuo conto bancario ${maskedAccountNumber}</a> così potrai continuare a usare le tue Expensify Card.`,
             },
             error: {
                 invalidCredentials: 'Credenziali non valide, controlla la configurazione della connessione.',
diff --git a/src/languages/ja.ts b/src/languages/ja.ts
index 5785b79d..955f9ec4 100644
--- a/src/languages/ja.ts
+++ b/src/languages/ja.ts
@@ -1516,17 +1516,7 @@ const translations: TranslationDeepObject<typeof en> = {
         shareToExpensify: 'Expensify で共有',
         messageInputLabel: 'メッセージ',
     },
-    notificationPreferencesPage: {
-        header: '通知設定',
-        label: '新しいメッセージの通知',
-        notificationPreferences: {
-            always: '今すぐ',
-            daily: '毎日',
-            mute: 'ミュート',
-            // @context UI label indicating that something is concealed or not visible to the user.
-            hidden: '非表示',
-        },
-    },
+    notificationPreferencesPage: {header: '通知設定', label: '新しいメッセージの通知', notificationPreferences: {always: '今すぐ', daily: '毎日', mute: 'ミュート', hidden: '非表示'}},
     loginField: {
         numberHasNotBeenValidated: 'この番号はまだ認証されていません。ボタンをクリックして、認証リンクをテキストメッセージで再送信してください。',
         emailHasNotBeenValidated: 'メールが認証されていません。ボタンをクリックして、テキストメッセージで認証リンクを再送信してください。',
@@ -4868,7 +4858,7 @@ _より詳しい手順については、[ヘルプサイトをご覧ください
             unassignCardFailedError: 'カードの割り当て解除に失敗しました。',
             error: {
                 workspaceFeedsCouldNotBeLoadedTitle: 'カードフィードを読み込めませんでした',
-                workspaceFeedsCouldNotBeLoadedMessage: 'ワークスペースのカードフィードを読み込む際にエラーが発生しました。もう一度お試しいただくか、管理者に連絡してください。',
+                workspaceFeedsCouldNotBeLoadedMessage: 'ワークスペースカードフィードの読み込み中にエラーが発生しました。もう一度お試しいただくか、管理者に連絡してください。',
                 feedCouldNotBeLoadedTitle: 'このフィードを読み込めませんでした',
                 feedCouldNotBeLoadedMessage: 'このフィードの読み込み中にエラーが発生しました。もう一度お試しいただくか、管理者に連絡してください。',
                 tryAgain: '再試行',
@@ -6838,7 +6828,7 @@ ${reportName}
                     [CONST.SEARCH.DATE_PRESETS.NEVER]: 'しない',
                     [CONST.SEARCH.DATE_PRESETS.LAST_MONTH]: '先月',
                     [CONST.SEARCH.DATE_PRESETS.THIS_MONTH]: '今月',
-                    [CONST.SEARCH.DATE_PRESETS.LAST_STATEMENT]: '最新の明細',
+                    [CONST.SEARCH.DATE_PRESETS.LAST_STATEMENT]: '最新の明細書',
                 },
             },
             status: 'ステータス',
@@ -6877,8 +6867,8 @@ ${reportName}
             groupBy: {
                 [CONST.SEARCH.GROUP_BY.FROM]: '差出人',
                 [CONST.SEARCH.GROUP_BY.CARD]: 'カード',
-                [CONST.SEARCH.GROUP_BY.WITHDRAWAL_ID]: '出金ID',
-                [CONST.SEARCH.GROUP_BY.CATEGORY]: 'カテゴリー',
+                [CONST.SEARCH.GROUP_BY.WITHDRAWAL_ID]: '出金 ID',
+                [CONST.SEARCH.GROUP_BY.CATEGORY]: 'カテゴリ',
             },
             feed: 'フィード',
             withdrawalType: {
@@ -7055,6 +7045,8 @@ ${reportName}
                 leftTheChat: 'チャットを退出しました',
                 companyCardConnectionBroken: ({feedName, workspaceCompanyCardRoute}: {feedName: string; workspaceCompanyCardRoute: string}) =>
                     `${feedName} との接続が切断されています。カードの取引明細の取り込みを再開するには、<a href='${workspaceCompanyCardRoute}'>銀行にログイン</a>してください`,
+                plaidBalanceFailure: ({maskedAccountNumber, walletRoute}: {maskedAccountNumber: string; walletRoute: string}) =>
+                    `Plaid とビジネス銀行口座の連携が切断されています。Expensify Card を引き続きご利用いただくために、<a href='${walletRoute}'>銀行口座 ${maskedAccountNumber} を再連携</a>してください。`,
             },
             error: {
                 invalidCredentials: '認証情報が無効です。接続の設定を確認してください。',
diff --git a/src/languages/nl.ts b/src/languages/nl.ts
index 8d36ee42..4007c1e4 100644
--- a/src/languages/nl.ts
+++ b/src/languages/nl.ts
@@ -1520,13 +1520,7 @@ const translations: TranslationDeepObject<typeof en> = {
     notificationPreferencesPage: {
         header: 'Meldingsvoorkeuren',
         label: 'Meld me over nieuwe berichten',
-        notificationPreferences: {
-            always: 'Onmiddellijk',
-            daily: 'Dagelijks',
-            mute: 'Dempen',
-            // @context UI label indicating that something is concealed or not visible to the user.
-            hidden: 'Verborgen',
-        },
+        notificationPreferences: {always: 'Onmiddellijk', daily: 'Dagelijks', mute: 'Dempen', hidden: 'Verborgen'},
     },
     loginField: {
         numberHasNotBeenValidated: 'Het nummer is nog niet gevalideerd. Klik op de knop om de bevestigingslink opnieuw via sms te versturen.',
@@ -4895,7 +4889,7 @@ _Voor gedetailleerdere instructies, [bezoek onze helpsite](${CONST.NETSUITE_IMPO
                     'Er is een fout opgetreden bij het laden van de kaartfeeds van de werkruimte. Probeer het opnieuw of neem contact op met uw beheerder.',
                 feedCouldNotBeLoadedTitle: 'Kon deze feed niet laden',
                 feedCouldNotBeLoadedMessage: 'Er is een fout opgetreden bij het laden van deze feed. Probeer het opnieuw of neem contact op met uw beheerder.',
-                tryAgain: 'Opnieuw proberen',
+                tryAgain: 'Probeer het opnieuw',
             },
         },
         expensifyCard: {
@@ -7098,6 +7092,8 @@ Vraag verplichte uitgavedetails zoals bonnetjes en beschrijvingen, stel limieten
                 leftTheChat: 'heeft de chat verlaten',
                 companyCardConnectionBroken: ({feedName, workspaceCompanyCardRoute}: {feedName: string; workspaceCompanyCardRoute: string}) =>
                     `De ${feedName}-verbinding is verbroken. Om kaartimporten te herstellen, <a href='${workspaceCompanyCardRoute}'>log in bij uw bank</a>`,
+                plaidBalanceFailure: ({maskedAccountNumber, walletRoute}: {maskedAccountNumber: string; walletRoute: string}) =>
+                    `de Plaid-verbinding met uw zakelijke bankrekening is verbroken. <a href='${walletRoute}'>Verbind uw bankrekening ${maskedAccountNumber} opnieuw</a> zodat u uw Expensify Cards kunt blijven gebruiken.`,
             },
             error: {
                 invalidCredentials: 'Ongeldige inloggegevens, controleer de configuratie van uw verbinding.',
diff --git a/src/languages/pl.ts b/src/languages/pl.ts
index 4254a4f8..3c1d3139 100644
--- a/src/languages/pl.ts
+++ b/src/languages/pl.ts
@@ -1519,13 +1519,7 @@ const translations: TranslationDeepObject<typeof en> = {
     notificationPreferencesPage: {
         header: 'Preferencje powiadomień',
         label: 'Powiadom mnie o nowych wiadomościach',
-        notificationPreferences: {
-            always: 'Natychmiast',
-            daily: 'Codziennie',
-            mute: 'Wycisz',
-            // @context UI label indicating that something is concealed or not visible to the user.
-            hidden: 'Ukryte',
-        },
+        notificationPreferences: {always: 'Natychmiast', daily: 'Codziennie', mute: 'Wycisz', hidden: 'Ukryte'},
     },
     loginField: {
         numberHasNotBeenValidated: 'Numer nie został zweryfikowany. Kliknij przycisk, aby ponownie wysłać link weryfikacyjny w wiadomości SMS.',
@@ -4879,9 +4873,9 @@ _Aby uzyskać bardziej szczegółowe instrukcje, [odwiedź naszą stronę pomocy
             cardAlreadyAssignedError: 'This card is already assigned to a user in another workspace.',
             unassignCardFailedError: 'Nie udało się odłączyć karty.',
             error: {
-                workspaceFeedsCouldNotBeLoadedTitle: 'Nie można było wczytać kanałów kart',
-                workspaceFeedsCouldNotBeLoadedMessage: 'Wystąpił błąd podczas ładowania kanałów kart w przestrzeni roboczej. Spróbuj ponownie lub skontaktuj się z administratorem.',
-                feedCouldNotBeLoadedTitle: 'Nie można było wczytać tego kanału',
+                workspaceFeedsCouldNotBeLoadedTitle: 'Nie udało się wczytać danych karty',
+                workspaceFeedsCouldNotBeLoadedMessage: 'Wystąpił błąd podczas ładowania kanałów kart przestrzeni roboczej. Spróbuj ponownie lub skontaktuj się z administratorem.',
+                feedCouldNotBeLoadedTitle: 'Nie udało się wczytać tego kanału',
                 feedCouldNotBeLoadedMessage: 'Wystąpił błąd podczas ładowania tego kanału. Spróbuj ponownie lub skontaktuj się ze swoim administratorem.',
                 tryAgain: 'Spróbuj ponownie',
             },
@@ -7086,6 +7080,8 @@ Wymagaj szczegółów wydatków, takich jak paragony i opisy, ustawiaj limity i
                 leftTheChat: 'opuścił czat',
                 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}'>ponownie połącz swoje konto bankowe ${maskedAccountNumber}</a>, aby móc dalej korzystać z kart Expensify.`,
             },
             error: {
                 invalidCredentials: 'Nieprawidłowe dane logowania, sprawdź konfigurację swojego połączenia.',
diff --git a/src/languages/pt-BR.ts b/src/languages/pt-BR.ts
index 73c03540..a7516778 100644
--- a/src/languages/pt-BR.ts
+++ b/src/languages/pt-BR.ts
@@ -1517,13 +1517,7 @@ const translations: TranslationDeepObject<typeof en> = {
     notificationPreferencesPage: {
         header: 'Preferências de notificação',
         label: 'Notificar-me sobre novas mensagens',
-        notificationPreferences: {
-            always: 'Imediatamente',
-            daily: 'Diário',
-            mute: 'Silenciar',
-            // @context UI label indicating that something is concealed or not visible to the user.
-            hidden: 'Oculto',
-        },
+        notificationPreferences: {always: 'Imediatamente', daily: 'Diário', mute: 'Silenciar', hidden: 'Oculto'},
     },
     loginField: {
         numberHasNotBeenValidated: 'O número não foi validado. Clique no botão para reenviar o link de validação por mensagem de texto.',
@@ -4879,8 +4873,8 @@ _Para instruções mais detalhadas, [visite nosso site de ajuda](${CONST.NETSUIT
             cardAlreadyAssignedError: 'This card is already assigned to a user in another workspace.',
             unassignCardFailedError: 'Falha ao desatribuir o cartão.',
             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 entre em contato com o administrador.',
+                workspaceFeedsCouldNotBeLoadedTitle: 'Não foi possível carregar os feeds de cartão',
+                workspaceFeedsCouldNotBeLoadedMessage: 'Ocorreu um erro ao carregar os feeds de cartões do workspace. Tente novamente ou entre em contato com seu administrador.',
                 feedCouldNotBeLoadedTitle: 'Não foi possível carregar este feed',
                 feedCouldNotBeLoadedMessage: 'Ocorreu um erro ao carregar este feed. Tente novamente ou entre em contato com o seu administrador.',
                 tryAgain: 'Tentar novamente',
@@ -6909,7 +6903,7 @@ Exija detalhes de despesas como recibos e descrições, defina limites e padrõe
             groupBy: {
                 [CONST.SEARCH.GROUP_BY.FROM]: 'De',
                 [CONST.SEARCH.GROUP_BY.CARD]: 'Cartão',
-                [CONST.SEARCH.GROUP_BY.WITHDRAWAL_ID]: 'ID de saque',
+                [CONST.SEARCH.GROUP_BY.WITHDRAWAL_ID]: 'ID de retirada',
                 [CONST.SEARCH.GROUP_BY.CATEGORY]: 'Categoria',
             },
             feed: 'Feed',
@@ -7088,6 +7082,8 @@ Exija detalhes de despesas como recibos e descrições, defina limites e padrõe
                 leftTheChat: 'saiu do chat',
                 companyCardConnectionBroken: ({feedName, workspaceCompanyCardRoute}: {feedName: string; workspaceCompanyCardRoute: string}) =>
                     `A conexão ${feedName} está quebrada. 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 que você possa continuar usando seus Cartões Expensify.`,
             },
             error: {
                 invalidCredentials: 'Credenciais inválidas, verifique a configuração da sua conexão.',
diff --git a/src/languages/zh-hans.ts b/src/languages/zh-hans.ts
index 3dda4ab0..4f0f46b1 100644
--- a/src/languages/zh-hans.ts
+++ b/src/languages/zh-hans.ts
@@ -1493,17 +1493,7 @@ const translations: TranslationDeepObject<typeof en> = {
         shareToExpensify: '分享至 Expensify',
         messageInputLabel: '消息',
     },
-    notificationPreferencesPage: {
-        header: '通知偏好',
-        label: '提醒我有新消息',
-        notificationPreferences: {
-            always: '立即',
-            daily: '每天',
-            mute: '静音',
-            // @context UI label indicating that something is concealed or not visible to the user.
-            hidden: '已隐藏',
-        },
-    },
+    notificationPreferencesPage: {header: '通知偏好', label: '提醒我有新消息', notificationPreferences: {always: '立即', daily: '每天', mute: '静音', hidden: '已隐藏'}},
     loginField: {
         numberHasNotBeenValidated: '该号码尚未验证。点击按钮通过短信重新发送验证链接。',
         emailHasNotBeenValidated: '电子邮箱尚未验证。点击按钮通过短信重新发送验证链接。',
@@ -4788,10 +4778,10 @@ _如需更详细的说明,请[访问我们的帮助网站](${CONST.NETSUITE_IM
             cardAlreadyAssignedError: 'This card is already assigned to a user in another workspace.',
             unassignCardFailedError: '卡片取消分配失败。',
             error: {
-                workspaceFeedsCouldNotBeLoadedTitle: '无法加载卡片信息流',
-                workspaceFeedsCouldNotBeLoadedMessage: '加载工作区卡片动态时出错。请重试或联系您的管理员。',
-                feedCouldNotBeLoadedTitle: '无法加载此订阅内容',
-                feedCouldNotBeLoadedMessage: '加载此信息流时出错。请重试或联系您的管理员。',
+                workspaceFeedsCouldNotBeLoadedTitle: '无法加载卡片数据源',
+                workspaceFeedsCouldNotBeLoadedMessage: '加载工作区卡片信息流时出错。请重试或联系您的管理员。',
+                feedCouldNotBeLoadedTitle: '无法加载此订阅',
+                feedCouldNotBeLoadedMessage: '加载此订阅源时发生错误。请重试或联系您的管理员。',
                 tryAgain: '重试',
             },
         },
@@ -6718,7 +6708,7 @@ ${reportName}
                     [CONST.SEARCH.DATE_PRESETS.NEVER]: '从不',
                     [CONST.SEARCH.DATE_PRESETS.LAST_MONTH]: '上个月',
                     [CONST.SEARCH.DATE_PRESETS.THIS_MONTH]: '本月',
-                    [CONST.SEARCH.DATE_PRESETS.LAST_STATEMENT]: '最新结单',
+                    [CONST.SEARCH.DATE_PRESETS.LAST_STATEMENT]: '最新对账单',
                 },
             },
             status: '状态',
@@ -6755,9 +6745,9 @@ ${reportName}
             reimbursable: '可报销',
             purchaseCurrency: '购买货币',
             groupBy: {
-                [CONST.SEARCH.GROUP_BY.FROM]: '从',
-                [CONST.SEARCH.GROUP_BY.CARD]: '卡片',
-                [CONST.SEARCH.GROUP_BY.WITHDRAWAL_ID]: '提款 ID',
+                [CONST.SEARCH.GROUP_BY.FROM]: '来自',
+                [CONST.SEARCH.GROUP_BY.CARD]: '卡',
+                [CONST.SEARCH.GROUP_BY.WITHDRAWAL_ID]: '提现 ID',
                 [CONST.SEARCH.GROUP_BY.CATEGORY]: '类别',
             },
             feed: '动态',
@@ -6930,6 +6920,8 @@ ${reportName}
                 leftTheChat: '已离开聊天',
                 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 卡。`,
             },
             error: {
                 invalidCredentials: '凭证无效,请检查您的连接配置。',

Note

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

Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 6104447157

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@codecov
Copy link

codecov bot commented Jan 28, 2026

Codecov Report

❌ Looks like you've decreased code coverage for some files. Please write tests to increase, or at least maintain, the existing level of code coverage. See our documentation here for how to interpret this table.

Files with missing lines Coverage Δ
src/CONST/index.ts 84.03% <ø> (ø)
src/libs/ReportNameUtils.ts 81.61% <50.00%> (-0.21%) ⬇️
src/libs/ReportUtils.ts 72.06% <50.00%> (+0.01%) ⬆️
src/libs/SidebarUtils.ts 79.56% <50.00%> (-0.12%) ⬇️
src/pages/inbox/report/PureReportActionItem.tsx 53.62% <50.00%> (-0.01%) ⬇️
...es/inbox/report/ContextMenu/ContextMenuActions.tsx 0.72% <0.00%> (-0.01%) ⬇️
src/libs/ReportActionsUtils.ts 54.94% <0.00%> (-0.13%) ⬇️
... and 9 files with indirect coverage changes

trjExpensify
trjExpensify previously approved these changes Jan 28, 2026
Copy link
Contributor

@trjExpensify trjExpensify left a comment

Choose a reason for hiding this comment

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

Core PR for a WN project 👍

@yuwenmemon yuwenmemon force-pushed the yuwen-reportActionPlaidBalance branch from 625fe36 to cb82e9f Compare January 28, 2026 00:57
This file will be broken up in a separate PR.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
yuwenmemon and others added 3 commits January 27, 2026 23:23
Co-authored-by: Andrew Rosiclair <arosiclair@expensify.com>
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.

5 participants