-
Notifications
You must be signed in to change notification settings - Fork 4.4k
fix(desktop): timestamps follow the OS locale instead of en-US #6190
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -20,6 +20,39 @@ export function getTimestampFormatOptions( | |
| }; | ||
| } | ||
|
|
||
| /** | ||
| * Pick the locale to format wall-clock times in, given the locale the host | ||
| * reports. Hosts that report nothing fall back to `undefined`, which is the | ||
| * runtime default and the right answer in a browser. | ||
| * | ||
| * A host reports a locale only when it knows better than the runtime does — | ||
| * see `getSystemLocale` on the desktop bridge for why desktop does. | ||
| */ | ||
| export function resolveTimestampLocale( | ||
| systemLocale: string | null | undefined, | ||
| ): string | undefined { | ||
| const tag = systemLocale?.trim(); | ||
| if (!tag) return undefined; | ||
|
|
||
| try { | ||
| // Every timestamp in the UI runs through this formatter, so a tag the host | ||
| // could not normalize falls back rather than throwing. Throws on a | ||
| // structurally invalid tag; a well-formed tag ICU has no data for resolves | ||
| // here and is left to ICU's own fallback. | ||
| Intl.DateTimeFormat.supportedLocalesOf([tag]); | ||
| return tag; | ||
| } catch { | ||
| return undefined; | ||
| } | ||
| } | ||
|
|
||
| function readHostSystemLocale(): string | null { | ||
| if (typeof window === "undefined") return null; | ||
| return window.desktopBridge?.getSystemLocale?.() ?? null; | ||
| } | ||
|
|
||
| const timestampLocale = resolveTimestampLocale(readHostSystemLocale()); | ||
|
|
||
| const timestampFormatterCache = new Map<string, Intl.DateTimeFormat>(); | ||
|
|
||
| function getTimestampFormatter( | ||
|
|
@@ -33,7 +66,7 @@ function getTimestampFormatter( | |
| } | ||
|
|
||
| const formatter = new Intl.DateTimeFormat( | ||
| undefined, | ||
| timestampLocale, | ||
| getTimestampFormatOptions(timestampFormat, includeSeconds), | ||
| ); | ||
| timestampFormatterCache.set(cacheKey, formatter); | ||
|
|
@@ -51,6 +84,9 @@ export function formatTimestamp(isoDate: string, timestampFormat: TimestampForma | |
| return getTimestampFormatter(timestampFormat, true).format(date); | ||
| } | ||
|
|
||
| // Deliberately not the host locale: the tooltip's ordinal suffix and | ||
| // day-before-month order below are English, so a localized month alone would | ||
| // read "4th Juni 2026". Localizing the whole label is a separate change. | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Chat dates stay US-orderedMedium Severity
Additional Locations (1)Reviewed by Cursor Bugbot for commit 244ca16. Configure here. |
||
| const monthNameFormatter = new Intl.DateTimeFormat(undefined, { month: "long" }); | ||
|
|
||
| function ordinalSuffix(day: number): string { | ||
|
|
||


There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The English-tooltip exception is well justified, but the two numeric date formatters below (
numericDateFormatter,numericDateWithYearFormatter) are still built withundefinedwhile the time formatter now usestimestampLocale.formatDayAwareTimestampconcatenates the two, so on packaged desktop — where the runtime default is pinned toen-US— anen-GBmachine renders8/13 15:44instead of13/08 15:44, i.e. UK hour cycle with US month/day order in the same label. That also contradicts theformatDayAwareTimestampdocstring, which promises "locale digit order".These formatters emit no English words, so the reason given here for
monthNameFormatterdoesn't apply to them; suggest passingtimestampLocaleto both (they are declared after thetimestampLocalebinding, so no reordering is needed), or adding a short note if leaving them on the runtime default is deliberate.Posted via Macroscope — UI Consistency