Conversation
…ultiple languages
…les based on user permissions
…th attribution sources
…vation for admin users and update test descriptions for clarity
|
@linhvovan29546 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] |
Codecov Report✅ Changes either increased or maintained existing code coverage, great job!
|
🦜 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 diffdiff --git a/src/languages/de.ts b/src/languages/de.ts
index f4db04e4..c49bf8d6 100644
--- a/src/languages/de.ts
+++ b/src/languages/de.ts
@@ -1335,7 +1335,7 @@ const translations: TranslationDeepObject<typeof en> = {
updatedTheDistanceMerchant: ({translatedChangedField, newMerchant, oldMerchant, newAmountToDisplay, oldAmountToDisplay}: UpdatedTheDistanceMerchantParams) =>
`änderte das ${translatedChangedField} zu ${newMerchant} (zuvor ${oldMerchant}), wodurch der Betrag auf ${newAmountToDisplay} aktualisiert wurde (zuvor ${oldAmountToDisplay})`,
basedOnAI: 'basierend auf früheren Aktivitäten',
- basedOnMCC: ({rulesLink}: {rulesLink: string}) => (rulesLink ? `basierend auf <a href="${rulesLink}">Arbeitsbereichsregeln</a>` : 'basierend auf Arbeitsbereichsregel'),
+ basedOnMCC: ({rulesLink}: {rulesLink: string}) => (rulesLink ? `gemäß den <a href="${rulesLink}">Regeln des Arbeitsbereichs</a>` : 'gemäß der Arbeitsbereichsregel'),
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, comment}: ThreadSentMoneyReportNameParams) => `${formattedAmount} gesendet${comment ? `für ${comment}` : ''}`,
diff --git a/src/languages/fr.ts b/src/languages/fr.ts
index 4669ee92..e1ec6475 100644
--- a/src/languages/fr.ts
+++ b/src/languages/fr.ts
@@ -1339,7 +1339,7 @@ const translations: TranslationDeepObject<typeof en> = {
updatedTheDistanceMerchant: ({translatedChangedField, newMerchant, oldMerchant, newAmountToDisplay, oldAmountToDisplay}: UpdatedTheDistanceMerchantParams) =>
`a changé le ${translatedChangedField} en ${newMerchant} (précédemment ${oldMerchant}), ce qui a mis à jour le montant à ${newAmountToDisplay} (précédemment ${oldAmountToDisplay})`,
basedOnAI: "basé sur l'activité passée",
- basedOnMCC: ({rulesLink}: {rulesLink: string}) => (rulesLink ? `basé sur <a href="${rulesLink}">les règles de l'espace de travail</a>` : "basé sur la règle de l'espace de travail"),
+ basedOnMCC: ({rulesLink}: {rulesLink: string}) => (rulesLink ? `selon <a href="${rulesLink}">les règles de l'espace de travail</a>` : 'selon la règle de l’espace de travail'),
threadExpenseReportName: ({formattedAmount, comment}: ThreadRequestReportNameParams) => `${formattedAmount} ${comment ? `pour ${comment}` : 'dépense'}`,
invoiceReportName: ({linkedReportID}: OriginalMessage<typeof CONST.REPORT.ACTIONS.TYPE.REPORT_PREVIEW>) => `Rapport de Facture n°${linkedReportID}`,
threadPaySomeoneReportName: ({formattedAmount, comment}: ThreadSentMoneyReportNameParams) => `${formattedAmount} envoyé${comment ? `pour ${comment}` : ''}`,
diff --git a/src/languages/it.ts b/src/languages/it.ts
index 5b9f0368..308259f0 100644
--- a/src/languages/it.ts
+++ b/src/languages/it.ts
@@ -1333,7 +1333,8 @@ const translations: TranslationDeepObject<typeof en> = {
updatedTheDistanceMerchant: ({translatedChangedField, newMerchant, oldMerchant, newAmountToDisplay, oldAmountToDisplay}: UpdatedTheDistanceMerchantParams) =>
`ha cambiato il ${translatedChangedField} in ${newMerchant} (precedentemente ${oldMerchant}), il che ha aggiornato l'importo a ${newAmountToDisplay} (precedentemente ${oldAmountToDisplay})`,
basedOnAI: 'basato su attività passate',
- basedOnMCC: ({rulesLink}: {rulesLink: string}) => (rulesLink ? `basato su <a href="${rulesLink}">regole dello spazio di lavoro</a>` : 'basato su regola dello spazio di lavoro'),
+ basedOnMCC: ({rulesLink}: {rulesLink: string}) =>
+ rulesLink ? `in base alle <a href="${rulesLink}">regole dello spazio di lavoro</a>` : 'in base alla regola dello spazio di lavoro',
threadExpenseReportName: ({formattedAmount, comment}: ThreadRequestReportNameParams) => `${formattedAmount} ${comment ? `per ${comment}` : 'spesa'}`,
invoiceReportName: ({linkedReportID}: OriginalMessage<typeof CONST.REPORT.ACTIONS.TYPE.REPORT_PREVIEW>) => `Rapporto Fattura n. ${linkedReportID}`,
threadPaySomeoneReportName: ({formattedAmount, comment}: ThreadSentMoneyReportNameParams) => `${formattedAmount} inviato${comment ? `per ${comment}` : ''}`,
diff --git a/src/languages/ja.ts b/src/languages/ja.ts
index 2aa9799e..96e5051a 100644
--- a/src/languages/ja.ts
+++ b/src/languages/ja.ts
@@ -1335,7 +1335,7 @@ const translations: TranslationDeepObject<typeof en> = {
updatedTheDistanceMerchant: ({translatedChangedField, newMerchant, oldMerchant, newAmountToDisplay, oldAmountToDisplay}: UpdatedTheDistanceMerchantParams) =>
`${translatedChangedField}を${newMerchant}に変更しました(以前は${oldMerchant})、これにより金額が${newAmountToDisplay}に更新されました(以前は${oldAmountToDisplay})。`,
basedOnAI: '過去のアクティビティに基づく',
- basedOnMCC: ({rulesLink}: {rulesLink: string}) => (rulesLink ? `<a href="${rulesLink}">ワークスペースルール</a>に基づく` : 'ワークスペースルールに基づく'),
+ basedOnMCC: ({rulesLink}: {rulesLink: string}) => (rulesLink ? `<a href="${rulesLink}">ワークスペースのルール</a>に基づいて` : 'ワークスペースのルールに基づく'),
threadExpenseReportName: ({formattedAmount, comment}: ThreadRequestReportNameParams) => `${formattedAmount} ${comment ? `${comment}用` : '経費'}`,
invoiceReportName: ({linkedReportID}: OriginalMessage<typeof CONST.REPORT.ACTIONS.TYPE.REPORT_PREVIEW>) => `請求書レポート #${linkedReportID}`,
threadPaySomeoneReportName: ({formattedAmount, comment}: ThreadSentMoneyReportNameParams) => `${formattedAmount} 送信済み${comment ? `${comment} のために` : ''}`,
diff --git a/src/languages/nl.ts b/src/languages/nl.ts
index 53ccab58..a36413de 100644
--- a/src/languages/nl.ts
+++ b/src/languages/nl.ts
@@ -1333,7 +1333,7 @@ const translations: TranslationDeepObject<typeof en> = {
updatedTheDistanceMerchant: ({translatedChangedField, newMerchant, oldMerchant, newAmountToDisplay, oldAmountToDisplay}: UpdatedTheDistanceMerchantParams) =>
`veranderde de ${translatedChangedField} naar ${newMerchant} (voorheen ${oldMerchant}), wat het bedrag bijwerkte 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'),
+ basedOnMCC: ({rulesLink}: {rulesLink: string}) => (rulesLink ? `op basis van <a href="${rulesLink}">werkruimteregels</a>` : 'gebaseerd op werkruimteregel'),
threadExpenseReportName: ({formattedAmount, comment}: ThreadRequestReportNameParams) => `${formattedAmount} ${comment ? `voor ${comment}` : 'uitgave'}`,
invoiceReportName: ({linkedReportID}: OriginalMessage<typeof CONST.REPORT.ACTIONS.TYPE.REPORT_PREVIEW>) => `Factuurrapport #${linkedReportID}`,
threadPaySomeoneReportName: ({formattedAmount, comment}: ThreadSentMoneyReportNameParams) => `${formattedAmount} verzonden${comment ? `voor ${comment}` : ''}`,
diff --git a/src/languages/pl.ts b/src/languages/pl.ts
index 0a391c95..ab49d244 100644
--- a/src/languages/pl.ts
+++ b/src/languages/pl.ts
@@ -1332,7 +1332,7 @@ const translations: TranslationDeepObject<typeof en> = {
updatedTheDistanceMerchant: ({translatedChangedField, newMerchant, oldMerchant, newAmountToDisplay, oldAmountToDisplay}: UpdatedTheDistanceMerchantParams) =>
`zmienił ${translatedChangedField} na ${newMerchant} (wcześniej ${oldMerchant}), co zaktualizowało kwotę na ${newAmountToDisplay} (wcześniej ${oldAmountToDisplay})`,
basedOnAI: 'na podstawie wcześniejszej aktywności',
- basedOnMCC: ({rulesLink}: {rulesLink: string}) => (rulesLink ? `na podstawie <a href="${rulesLink}">reguł przestrzeni roboczej</a>` : 'na podstawie reguły przestrzeni roboczej'),
+ basedOnMCC: ({rulesLink}: {rulesLink: string}) => (rulesLink ? `na podstawie <a href="${rulesLink}">zasad obszaru roboczego</a>` : 'na podstawie reguły obszaru roboczego'),
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, comment}: ThreadSentMoneyReportNameParams) => `${formattedAmount} wysłano${comment ? `dla ${comment}` : ''}`,
diff --git a/src/languages/zh-hans.ts b/src/languages/zh-hans.ts
index 50da26db..f2729eb8 100644
--- a/src/languages/zh-hans.ts
+++ b/src/languages/zh-hans.ts
@@ -1313,7 +1313,7 @@ const translations: TranslationDeepObject<typeof en> = {
updatedTheDistanceMerchant: ({translatedChangedField, newMerchant, oldMerchant, newAmountToDisplay, oldAmountToDisplay}: UpdatedTheDistanceMerchantParams) =>
`将${translatedChangedField}更改为${newMerchant}(之前为${oldMerchant}),这更新了金额为${newAmountToDisplay}(之前为${oldAmountToDisplay})`,
basedOnAI: '基于过去的活动',
- basedOnMCC: ({rulesLink}: {rulesLink: string}) => (rulesLink ? `基于<a href="${rulesLink}">工作空间规则</a>` : '基于工作空间规则'),
+ basedOnMCC: ({rulesLink}: {rulesLink: string}) => (rulesLink ? `基于 <a href="${rulesLink}">工作区规则</a>` : '基于工作区规则'),
threadExpenseReportName: ({formattedAmount, comment}: ThreadRequestReportNameParams) => `${formattedAmount} ${comment ? `为${comment}` : '费用'}`,
invoiceReportName: ({linkedReportID}: OriginalMessage<typeof CONST.REPORT.ACTIONS.TYPE.REPORT_PREVIEW>) => `发票报告 #${linkedReportID}`,
threadPaySomeoneReportName: ({formattedAmount, comment}: ThreadSentMoneyReportNameParams) => `${formattedAmount} 已发送${comment ? `对于${comment}` : ''}`,
Note You can apply these changes to your branch by copying the patch to your clipboard, then running |
…ing unnecessary whitespace and ensuring consistent formatting of policyID in test cases.
… clarity and consistency in messaging.
@marcochavezf How can I setup this, or do I just need to mock the data to test this PR? |
Just mocking the data will be fine, since I think there's no easy way to test this locally without having access to a local backend service |
joekaufmanexpensify
left a comment
There was a problem hiding this comment.
Makes sense from a product perspective 👍
linhvovan29546
left a comment
There was a problem hiding this comment.
I mocked the data locally and it works as expected. But there are several deprecated
…icyID, improving type safety and clarity in context menus.
…s link generation for admin
|
Updated, thanks for the review! |
…o ensure consistent lowercase formatting and adjust source attribution logic.
…re consistent lowercase formatting and modify source attribution logic to prevent unnecessary conversions.
|
Updated, thanks for the review! |
Reviewer Checklist
Screenshots/VideosAndroid: HybridAppScreen.Recording.2025-11-25.at.09.18.17.movAndroid: mWeb ChromeScreen.Recording.2025-11-25.at.09.19.40.moviOS: HybridAppScreen.Recording.2025-11-25.at.09.14.00.moviOS: mWeb SafariScreen.Recording.2025-11-25.at.09.15.41.movMacOS: Chrome / SafariScreen.Recording.2025-11-25.at.09.11.10.mov |
linhvovan29546
left a comment
There was a problem hiding this comment.
LGTM and works well.
Note: the unit tests are failing due to a lowercase. I’ll approve since the core feature works as expected. Feel free to merge after the tests are fixed.
|
@srikarparsi 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] |
|
🎯 @linhvovan29546, thanks for reviewing and testing this PR! 🎉 An E/App issue has been created to issue payment here: #75952. |
|
Jest Unit tests are passing now |
|
@roryabraham 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] |
|
@srikarparsi All yours |
|
🚀 Deployed to staging by https://github.com/srikarparsi in version: 9.2.67-0 🚀
|
|
@marcochavezf @jasperhuangg we can't test this step as we don't have card transactions.
|
|
🚀 Deployed to staging by https://github.com/srikarparsi in version: 9.2.70-0 🚀
|
|
🚀 Deployed to production by https://github.com/mountiny in version: 9.2.70-0 🚀
|
|
|
||
| let allPolicyTags: OnyxCollection<PolicyTagLists> = {}; | ||
| Onyx.connect({ | ||
| Onyx.connectWithoutView({ |
There was a problem hiding this comment.
@marcochavezf this is wrong. The functions using these values are connected to UI components. Please fix this ASAP, it is already causing problems with people following this anti-pattern.
There was a problem hiding this comment.
Sure, working on this tomorrow morning
There was a problem hiding this comment.
I'm getting up to date with the Onyx migration; it looks like the correct solution here is to migrate remaining callers (ReportActionItem.tsx, BrowserNotifications.ts, ReportUtils.ts, etc.) to use getForReportActionTemp, correct?
There was a problem hiding this comment.
@tgolen AFAIK we need to update getForReportActionTemp to accept currentUserLogin as a parameter instead of reading it from Onyx.connect (because we added currentUserLogin in this PR). That would also updating both getForReportActionTemp and getForReportAction to accept a currentUserLogin parameter for this scope, right?
There was a problem hiding this comment.
That sounds right, yeah. I haven't dug into it super close though.
There was a problem hiding this comment.
Ok great, I outlined a plan here, since this requires multiple files, and I think we need to update them gradually in different PRs
Explanation of Change
This PR adds a hyperlink to "workspace rules" in MCC categorization system messages when the user is a workspace admin. When Concierge automatically categorizes an expense based on MCC (Merchant Category Code) mapping rules, admins will now see a clickable "workspace rules" link that takes them directly to the workspace rules page
Key technical changes:
ModifiedExpenseMessage.tsto detect admin status and generate hyperlinked text for MCC categorizationPureReportActionItem.tsxto use<RenderHTML>component for proper HTML anchor tag supportshouldConvertToLowercaseparameter to preserve policyID casing in URLs (prevents.toLowerCase()from corrupting the href attribute)Fixed Issues
$ https://github.com/Expensify/Expensify/issues/554975
PROPOSAL:
Tests
Pre-requisite:
/workspaces/{POLICYID}/ruleswith correct casing)Offline tests
N/A
QA Steps
Same as the steps from the test section
PR Author Checklist
### Fixed Issuessection aboveTestssectionOffline stepssectionQA stepssectioncanBeMissingparam foruseOnyxtoggleReportand notonIconClick)src/languages/*files and using the translation methodSTYLE.md) were followedAvatar, I verified the components usingAvatarare working as expected)StyleUtils.getBackgroundAndBorderStyle(theme.componentBG))npm run compress-svg)Avataris modified, I verified thatAvataris working as expected in all cases)Designlabel and/or tagged@Expensify/designso the design team can review the changes.ScrollViewcomponent to make it scrollable when more elements are added to the page.mainbranch was merged into this PR after a review, I tested again and verified the outcome was still expected according to theTeststeps.Screenshots/Videos
Android: Native
Android: mWeb Chrome
iOS: Native
iOS: mWeb Safari
MacOS: Chrome / Safari
Admin:
Employee:
MacOS: Desktop