Skip to content

plugin-timeline hardcodes 'en-US' at four date sites, so timeline headers stay English on every non-English session #4513

Description

@yinlianghui

Found while measuring the date-locale census for #4468 (PR #4512). Out of that card's scope — different package, and the timeline view was not one of the surfaces #4468 measured — so recorded here rather than fixed on a rider.

What was measured

packages/plugin-timeline/src/renderer.tsx passes the literal 'en-US' to four Intl calls, so nothing a user or a tenant configures can change them:

  • renderer.tsx:71 — current.toLocaleString('en-US', { month: 'short', day: 'numeric', hour: 'numeric' }) (hour-granularity header)
  • renderer.tsx:77 — current.toLocaleDateString('en-US', { month: 'short', day: 'numeric' }) (day header)
  • renderer.tsx:108 — current.toLocaleDateString('en-US', { month: 'short', year: 'numeric' }) (month header)
  • renderer.tsx:160 — date.toLocaleDateString('en-US', { … }) (item date)

renderer.tsx:157 is the sibling case in the other direction: a bare date.toLocaleDateString(), which reads the machine's locale rather than the session's — the same defect class #4468 fixed in @object-ui/fields, just spelled as an omission instead of a literal.

Why it matters

A zh console renders a fully Chinese timeline widget whose axis reads Aug 11 / Sep 2026. This is user-visible on any non-English session, not dormant code.

The fix this wants

The same one #4468 used: resolve through useDisplayLocale() from @object-ui/i18n (tenant regional default → active UI language → 'en'), which is already the single channel every field, number and currency renderer uses. renderer.tsx's date helpers are module-level functions, so the locale has to be threaded from the component that calls them, the way GridField's displayText was in PR #4512.

Worth checking the whole plugin-timeline surface in one pass rather than only these five lines — the measurement above was a grep for 'en-US' and bare toLocale*, not a review of the package.

Activity

  1. self-assigned this
    on Aug 13, 2026
  2. yinlianghui commented on Aug 13, 2026

    @yinlianghui
    CollaboratorAuthor

    CLAIM — session session_017Qqyix2QcnpUC9XeYVDzx3, branch claude/issue-4513-timeline-locale.

    Ruling (delegated authority; open veto window): converge the four hardcoded 'en-US' sites + the bare toLocaleDateString() in packages/plugin-timeline/src/renderer.tsx onto the established one-resolver — useDisplayLocale() from @object-ui/i18n (the channel PR #4512 just confirmed for all six fields sites; measured there: Intl accepts 'zh' directly, no mapping table). Same discipline as #4468's dispatch: if the renderer structure can't host the hook at a call site, evaluate at component level and thread the locale down; no per-site variants.

    Red-first: zh session → each of the five sites captured verbatim pre-fix (en-US output) → zh post-fix. Must-not-change (green both sides): en byte-identical at every site; the machine-pinned-expectation trap from #4468's report applies — if existing timeline tests pin bare-toLocale* output, respell them against 'en' (the provider-less resolution) with reasoning, per the PR #4512 precedent.

    Grading: patch @object-ui/plugin-timeline (.d.ts measured both ways). Never major.

    Surface (mutual exclusion): packages/plugin-timeline/** + tests + one changeset. Disjoint from in-flight #4446 (metadata-admin), #4252 (AppContent), #4213 (RecordDetailView), #4503r (plugin-grid/plugin-list). ⛔ NOT: packages/fields (#4272's re-scoped residue — its formatDate 'short'/formatDateTime halves wait for the plugin-grid surface to free), content/docs/releases/.


    Generated by Claude Code


    Generated by Claude Code

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

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions