Skip to content

Commit 83f7743

Browse files
os-zhuangclaude
andauthored
fix(plugin-audit): localize select option labels in the tracked-change activity summary (#7289) (#7389)
`displayFieldValue` rendered a select/picklist value by returning the matching option's authored `label` from `engine.getSchema(name)` — locale-independent metadata — while the shipped bundles carry those labels under `objects.<object>.fields.<field>.options.<value>`. After #7230 localized the field label, a zh-CN workspace read `阶段: Proposal → Closed Won`. The tracked-change branch now resolves the option label through the same locale-bound translator its field label already uses, authored label as fallback. The fired-milestone branch is deliberately NOT localized and the opt-out is by construction: it passes no option resolver, so its author-written sentence and the author's own option label stay in one language. Zero added reads on every write shape — a bundle lookup, not I/O — so #6656 / PR #6977's retirement, preserved by #7291 and #7333, still stands, and `displayFieldValue` stays synchronous. Claude-Session: https://claude.ai/code/session_01BM1tNf5U3nEbHKR4fo5qVQ Co-authored-by: Claude <noreply@anthropic.com>
1 parent 2443bb4 commit 83f7743

3 files changed

Lines changed: 707 additions & 4 deletions

File tree

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
---
2+
"@objectstack/plugin-audit": patch
3+
---
4+
5+
fix(plugin-audit): localize select option labels in the tracked-change activity summary (#7289)
6+
7+
`sys_activity.summary` is composed at **write time** and shipped verbatim to
8+
every consumer at once — the record discussion feed, console home activity, the
9+
header inbox, the Setup `sys_activity` list, and mobile/REST/SDUI.
10+
`displayFieldValue` rendered a select/picklist value by scanning `field.options[]`
11+
and returning the matching option's **authored** `label`. `field.options` comes
12+
from `engine.getSchema(name)`, which is locale-independent metadata, while the
13+
shipped bundles carry those same labels under
14+
`objects.<object>.fields.<field>.options.<value>` (`sys_audit_log.fields.action.options.create = "创建"`).
15+
Nothing on this path read them.
16+
17+
After #7230 localized the field label, that left a zh-CN workspace with
18+
19+
```
20+
阶段: Proposal → Closed Won
21+
```
22+
23+
— a half-localized string at the bottom of a fully-localized page. The tracked-change
24+
branch now resolves the option label through the same locale-bound translator its
25+
field label already uses, on the bundles' own key shape, with the authored label as
26+
the fallback. A bundle miss returns `undefined`, so the authored label and then
27+
`String(value)` answer exactly as before: the change can only replace an authored
28+
label with that label's translation, never the reverse.
29+
30+
**The fired-milestone branch is deliberately left alone**, and the opt-out is by
31+
construction rather than by omission — `renderMilestoneSummary` passes no option
32+
resolver, so a select token there still renders its authored label byte-for-byte.
33+
A milestone summary is an author-written sentence with no bundle key of its own,
34+
and #7290 ruled leaving templates untranslated a contract decision. #7290's own
35+
change (a reference id → the referenced record's title) is locale-*independent*
36+
data — the same string in every locale — which is why it could be added to an
37+
untranslated sentence; an option label is locale-*dependent* rendering, so reading
38+
the bundle there would guarantee a split sentence (`Deal moved to 已赢单`) in
39+
exactly the case the bundle exists for. The tracked-change branch has the opposite
40+
geometry: its frame is fully localized, so there the authored value is the mismatch.
41+
42+
**Read cost is unchanged.** This is a bundle lookup, not I/O: zero added reads on
43+
every write shape, so the #6656 / PR #6977 retirement (2 → 1 reads per single-id
44+
write, 3 → 0 per predicate write) that #7291 and #7333 preserved still stands,
45+
and `displayFieldValue` stays synchronous.
46+
47+
Historical rows keep their write-time composition; only new writes improve.

0 commit comments

Comments
 (0)