fix: localization dates not being localized correctly - #91569
Conversation
|
Hey! I see that you made changes to our Form component. Make sure to update the docs in FORMS.md accordingly. Cheers! |
Codecov Report✅ Changes either increased or maintained existing code coverage, great job!
|
…ation-dates-not-being-localized-correctly # Conflicts: # src/pages/Travel/FlightTripDetails.tsx
PR ReviewWell-executed migration from date-fns format strings to Issues to fix1. Mock type mismatch — 2. 3. Suggestions (non-blocking)4. 5. CalendarPicker missing 6. What's done well
|
|
@TaduJR you're missing native platform tests. Please test various timezones (US timezone UTC-X, Asia timezone UTC+X) |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: e56f6b81c3
ℹ️ About Codex in GitHub
Codex has been enabled to automatically 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 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
…ation-dates-not-being-localized-correctly # Conflicts: # src/components/FrozenCardHeader.tsx # src/pages/Travel/TrainTripDetails.tsx
…ation-dates-not-being-localized-correctly
This comment was marked as resolved.
This comment was marked as resolved.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: b6ef0867b4
ℹ️ About Codex in GitHub
Codex has been enabled to automatically 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 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
This comment was marked as resolved.
This comment was marked as resolved.
|
Codex Review: Didn't find any major issues. 👍 Reviewed commit: ℹ️ About Codex in GitHubCodex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback". |
This comment was marked as resolved.
This comment was marked as resolved.
|
Codex Review: Didn't find any major issues. Bravo. Reviewed commit: ℹ️ About Codex in GitHubCodex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback". |
|
Addressed the above valid concerns. Thanks. |
|
Was this addressed too? |
…ation-dates-not-being-localized-correctly
Yes @situchan
Addressed it Thanks! |
…ngeDisplayValueFromFormValue
…ation-dates-not-being-localized-correctly
Regression review 🔎Reviewed this date/localization refactor across 5 focused passes (DateUtils core, IntlStore + boot gating, One actionable risk and two minor notes below. 🟠 Actionable:
|
|
Please fix conflict |
…ation-dates-not-being-localized-correctly # Conflicts: # src/components/Search/SearchList/ListItem/ExpenseReportListItemRow/ExpenseReportListItemRowNarrow.tsx # src/pages/iou/SplitExpensePage.tsx # src/pages/workspace/distanceRates/PolicyDistanceRateDetailsPage.tsx
|
@codex review |
|
Codex Review: Didn't find any major issues. Keep them coming! Reviewed commit: ℹ️ About Codex in GitHubCodex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback". |
Done @situchan Thanks! |
|
There are still failing checks along with conflict |
…ation-dates-not-being-localized-correctly # Conflicts: # tests/unit/DateUtilsTest.ts
…ation-dates-not-being-localized-correctly
Addressed |
Explanation of Change
Intl.DateTimeFormat(dateStyle/timeStyle) across CalendarPicker, DateIcon, DOB step, receipts, travel, search, per-diem, status, schedule-call, and chat travel notifications.getWeekStartsOn/getWeekEndsOnare locale-aware viaIntl.Locale.getWeekInfo(); calendar shows the correct first day per locale.MM/DD/YYYY, de →DD.MM.YYYY, ja →YYYY/MM/DD).Enero, fr →Janvier, de →Januar).weekday: 'short'(fr →lun. mar. mer.) — narrow labels were ambiguous in fr/it/pt-BR.formatTravelDate(chat travel notifications) now respects locale; per-diem same-day "Time" row keeps the date.Architectural improvements:
Localeend-to-end —IntlStoreeager-seeds EN at module load sogetCurrentLocale(): Locale(neverundefined); cascades throughuseLocalize().preferredLocaleto every formatter signature. No?? CONST.LOCALES.DEFAULTfallbacks left.LocaleContextProviderreadsIntlStoreviauseSyncExternalStore— one re-render per locale change instead of the prioruseState+useEffect-on-Onyx-flag two-tick dance.useNowhook (new) —AutoUpdateTimeandParticipantLocalTimepreviously ran their own per-secondsetIntervals; both now share one ref-counted minute-tick viauseSyncExternalStore.Fixed Issues
$ #69562
PROPOSAL: #69562 (comment)
Tests
Setup
A. Language
B. Device timezone (OS-level — outside the app)
Set the device's timezone in the OS settings before each pass:
After changing OS timezone, fully close and reopen the App so it picks up the new zone.
C. In-app timezone (separate from device timezone)
In-app timezone is configured at: Settings → Profile → Timezone
America/Los_Angeles,Asia/Tokyo,Europe/Berlin).Tests 10, 11, 9, and R7-A explicitly require manipulating the in-app timezone.
Test 1 — Date Picker placeholder + selected value
Where: Settings → Profile → Personal Details → Date of birth.
Expected:
MM/DD/YYYY, saved value01/05/2026.DD/MM/AAAA(orDD/MM/YYYY), saved value05/01/2026.Test 2 — Calendar weekday headers and month names
Where: Any date picker.
Expected:
S M T W T F SorM T W T F S S; months read "January…".Test 3 — Calendar first day of week
Expected:
Test 4 — Travel reservations (Hotel / Flight / Car / Train)
Where: A chat with a travel booking → trip → individual reservation.
Expected:
2026-04-02T19:00-05:00must show consistent date+time, not "Apr 3 at 9:00 AM" vs "Apr 2 at 9:00 AM" split across the two halves of the row.Test 5 — Travel chat preview card
Where: Chat list showing a travel-room conversation.
Expected: Range uses the active language's month abbreviations. Single-day trips show one date.
Test 6 — Travel update messages in chat
Where: A travel chat with system notifications (ticket issued, flight changed, cancelled, etc.).
Expected: Both render in active language and describe the same moment regardless of device timezone.
Test 7 — Receipt full view (EReceipt)
Where: A transaction with a receipt → tap thumbnail → view receipt.
Expected: Date in active language (English: "January 5, 2026"; Spanish: "5 de enero de 2026"). Date does not shift across UTC−8 vs UTC+9.
Test 8 — Per-diem expense Time row
Where: Workspace with per-diem enabled.
Expected:
9:00 AM – 5:00 PM, Jan 5, 2026.9:00 AM, Jan 5, 2026 – 5:00 PM, Jan 6, 2026.Test 9 — Custom status (Clear after) — in-app timezone sensitive
Where: Settings → Profile → Status.
Run in two sub-passes:
9a. Device TZ = UTC−8, In-app TZ = Automatic (so in-app = UTC−8)
9b. Device TZ = UTC−8, In-app TZ = Manual →
Asia/Tokyo(UTC+9)Expected (both sub-passes):
Test 10 — Profile "Local time" row — in-app timezone sensitive
Where: Open your own profile (avatar → details) → find Local time row.
Run in two sub-passes:
10a. In-app Timezone = Automatic
Expected: Time matches the device clock. Auto-updates within ~60 seconds (e.g. "2:34 PM" → "2:35 PM"). 12-hour AM/PM in English, 24-hour in Spanish.
10b. In-app Timezone = Manual
Asia/TokyoExpected: Time now shows Tokyo wall-clock time (≈17 hours ahead of US Pacific), formatted in the active language. The displayed timezone abbreviation (e.g.
JST) reflects Tokyo. Auto-update at the minute boundary still works.Test 11 — Participant local time (chat header) — in-app timezone sensitive
Where: A 1:1 chat with a participant whose in-app timezone differs from yours.
Setup: You should be in (say)
America/Los_Angeles. The other participant should be inAsia/Tokyo. Both timezones set via Settings → Profile → Timezone → Manual in each account.Expected:
Test 12 — Search results date column
Where: Search → any search with dated results.
Expected: Dates use active language's month abbreviations. Past-year rows include year, current-year typically omit it. No row shows the wrong calendar day after changing device timezone.
Test 13 — Wallet statements
Where: Settings → Wallet → View statement → pick a month.
Expected: Month name fully localized.
Test 14 — Workspace distance rates start/end date
Where: Workspace with Date-bound mileage rate beta enabled. Workspace → Distance rates → tap a rate.
Expected: Rows in active language. Editor calendar shows correct localized placeholder. Saving a date and re-opening shows the same date even after switching device timezone.
Test 15 — Frozen card header
Where: Settings → Wallet → Expensify Card → A frozen card.
Expected: Frozen date follows the active language.
Test 16 — Schedule a call
Where: Any chat with the Schedule a call action.
Expected: Calendar and confirmation line both in active language. Selected date+time consistent across device timezones.
Test 17 — Out-of-office (Chronos) summary
Where: A chat with Chronos / OOO bot messages.
Expected: Both in active language, consistent date/time formatting.
Test 18 — Split expense date column
Where: An expense that has been split.
Expected: Dates in active language. No day-shift across device timezones.
Regression Test Cases (must pass before merge)
Each below reproduces a real bug from prior reverted attempts. They must all pass.
R1 — Merge expense: no crash on confirmation page (#80013)
Expected: Merge confirmation page opens normally. No crash, no white screen.
R2 — Merge expense: opening merged expense does not crash (PR #69945)
Expected: Detail page opens. Date row renders. No crash.
R3 — Date picker: picked date matches saved date (#76646)
Run on iOS App, Windows Chrome, and macOS Chrome/Safari.
Expected: Saved date is exactly Jan 15, 2000. Not Jan 14, not Jan 16.
Run this also under UTC+9 device timezone. The result must still be Jan 15.
R4 — Date picker: same-day select on Monday-start calendar (PR #69945 deploy-blocker)
Active language: English or Spanish.
Expected: Saved date is today. Every column in the grid saves the date its header letter says (M-cell → Monday, T-cell → Tuesday, etc.). Repeat for several weekdays.
R5 — Bank account DOB placeholder shows locale format (#80011)
Active language: English, Windows Chrome.
Expected: Placeholder reads
MM/DD/YYYY. NeverYYYY-MM-DD. Switch to Spanish and re-check.R6 — Split expense: opening a split does not crash on Android (#76643)
Run on Android (original repro: Redmi Note 10s, Android 13).
Expected: Detail page opens. Dates render in active language. No crash.
R7 — No day-shift across the app (#80024) — timezone-critical
Setup: Device language English. Run all three parts twice: once with device timezone US Pacific (UTC−08:00), then again with device timezone Asia/Tokyo (UTC+09:00). Test on iOS App and Windows Chrome.
R7-A — Status:
This also tests in-app timezone interaction.
Expected (both Pacific and Tokyo passes): Shows the date and time you picked. Never Jan 24 in one pass and Jan 25 in the other.
Then repeat R7-A with in-app Timezone set manually to
Europe/Berlin(UTC+01:00) — the saved value should now reflect Berlin wall-clock, not device wall-clock.R7-B — Date of birth:
Expected (both Pacific and Tokyo passes): Shows March 10, 1995 (or
03/10/1995). Not March 9, not March 11.R7-C — Company cards transaction start date:
Expected (both passes): Saved date is Feb 1, 2026.
Offline tests
Same as tests
QA Steps
// TODO: These must be filled out, or the issue title must include "[No QA]."
Same as tests
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
Mac-Chrome.mp4