Skip to content

plugin-audit: select option labels in sys_activity.summary are never localized — the same defect class as #7230, one line over in displayFieldValue #7289

Description

@os-zhuang

Found while implementing #7230 (packages/plugins/plugin-audit/src/audit-writers.ts). Filed rather than fixed: #7230's scope is recommendation A's two halves (field label + lookup value), and this is a third change to the same function.

Mechanism

displayFieldValue renders a select/picklist value by scanning field.options[] and returning the matching option's label:

const ov = o && typeof o === 'object' ? (o.value ?? o.name ?? o.label) : o;
if (ov === value) {
  const ol = o && typeof o === 'object' ? (o.label ?? o.name ?? ov) : o;
  return String(ol);
}

field.options comes from engine.getSchema(name) — the authored metadata, which is locale-independent. The shipped translation bundles carry option labels under objects.[object].fields.[field].options.[value] (see packages/plugins/plugin-audit/src/translations/zh-CN.objects.generated.ts, e.g. sys_audit_log.fields.action.options.create = "创建"), and nothing on this path reads them.

Net effect on a zh-CN workspace, after #7230 lands: the field label is localized and the reference value resolves to a title, but a select value still renders its authored-language label —

阶段: Proposal → Closed Won

— a half-localized string on a fully-localized page. Before #7230 the whole thing was English, so the mixed rendering is new visibility, not a new defect.

Why it is the same class as #7230, and why it is still separate

Same root shape (a display string composed at write time that skips the locale-bound translator), same function, same blast radius — every sys_activity.summary consumer at once: record discussion feed, console home activity, header inbox, the Setup sys_activity list, mobile/REST/SDUI. But it is a distinct decision: the fix has to thread translate and the object name into displayFieldValue itself (today it receives neither, and #7230 deliberately kept it synchronous and translator-free so matchMilestone could keep calling it unchanged).

Suggested shape, if taken

In displayFieldValue's option branch, prefer translate(\objects.${objectName}.fields.${key}.options.${value}`)overo.label, with the authored label as the fallback — mirroring exactly what #7230 did for the field label. matchMilestone`'s call site would need the same two arguments or an explicit opt-out.

Anchors at a768f81a1 (pre-#7230): displayFieldValue audit-writers.ts:308, option branch :310-319.

Refs: #7230, ADR-0053, #3039.

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions