Frontend bug: LabelEditor silently drops other-language labels when editing #55

Closed
opened 2026-06-06 18:52:34 +00:00 by logaritmisk · 1 comment
Owner

Severity: Medium–High (data loss). From a frontend UX audit.

Problem

web/src/components/label-editor.tsx:23-27 reads value.find(l => l.lang === default_language)?.label ?? value[0]?.label and on change emits a single-entry array [{ lang: default_language, label }]. Term/authority edit rows seed the editor from the existing labels (term-row.tsx:64, authority-row.tsx), so editing a term/authority that already has labels in other languages and saving replaces the whole multilingual set with one default-language entry — silently discarding e.g. the English label of a Swedish-edited term. The component comment claims "the multilingual data model is unchanged," but on the edit path it is destructively collapsed.

This is a consequence of the single-language authoring decision (instance-locale milestone), but the destructive collapse of pre-existing other-language data on edit is unintended.

Suggested fix

Make the editor's onChange preserve non-default-language entries:

onChange([
  ...value.filter(l => l.lang !== default_language),
  ...(label.trim() ? [{ lang: default_language, label }] : []),
])

Optionally surface a hint when other-language labels exist on the entry being edited.

Source: frontend UX/design audit, 2026-06-06.

**Severity: Medium–High (data loss).** _From a frontend UX audit._ ## Problem `web/src/components/label-editor.tsx:23-27` reads `value.find(l => l.lang === default_language)?.label ?? value[0]?.label` and on change emits a **single-entry** array `[{ lang: default_language, label }]`. Term/authority edit rows seed the editor from the existing labels (`term-row.tsx:64`, `authority-row.tsx`), so editing a term/authority that already has labels in **other** languages and saving **replaces the whole multilingual set with one default-language entry** — silently discarding e.g. the English label of a Swedish-edited term. The component comment claims "the multilingual data model is unchanged," but on the edit path it is destructively collapsed. This is a consequence of the single-language authoring decision (instance-locale milestone), but the *destructive collapse of pre-existing other-language data on edit* is unintended. ## Suggested fix Make the editor's `onChange` preserve non-default-language entries: ```ts onChange([ ...value.filter(l => l.lang !== default_language), ...(label.trim() ? [{ lang: default_language, label }] : []), ]) ``` Optionally surface a hint when other-language labels exist on the entry being edited. _Source: frontend UX/design audit, 2026-06-06._
Author
Owner

Fixed — merged to main (d0e3772).

LabelEditor.onChange now preserves non-default-language entries instead of collapsing the record to a single default-language label:

onChange([
  ...value.filter((l) => l.lang !== default_language),
  ...(label.trim() ? [{ lang: default_language, label }] : []),
]);

Editing a term/authority/field that already has e.g. an English label now keeps it.

Also fixed a related display flaw surfaced while testing: current fell back to value[0]?.label (an other-language label) when no default-language entry existed, so after clearing the field it jumped to the English text and a subsequent edit would save English content under the default-language lang. The editor now shows only the default-language label (?? "").

Per the issue's optional suggestion, a muted hint now appears when the edited record has labels in other languages (labels.otherLanguages, en/sv): "This entry also has labels in other languages, which are kept."

Regression tests added (preserve-on-edit, hint shown/hidden) + a WithOtherLanguages Storybook story. Gate green: typecheck, lint, 173 tests, build, check:size (183.6 KB gz), check:colors; en/sv parity; no codename.

Fixed — merged to `main` (`d0e3772`). `LabelEditor.onChange` now preserves non-default-language entries instead of collapsing the record to a single default-language label: ```ts onChange([ ...value.filter((l) => l.lang !== default_language), ...(label.trim() ? [{ lang: default_language, label }] : []), ]); ``` Editing a term/authority/field that already has e.g. an English label now keeps it. Also fixed a related display flaw surfaced while testing: `current` fell back to `value[0]?.label` (an *other-language* label) when no default-language entry existed, so after clearing the field it jumped to the English text and a subsequent edit would save English content under the default-language `lang`. The editor now shows **only** the default-language label (`?? ""`). Per the issue's optional suggestion, a muted hint now appears when the edited record has labels in other languages (`labels.otherLanguages`, en/sv): _"This entry also has labels in other languages, which are kept."_ Regression tests added (preserve-on-edit, hint shown/hidden) + a `WithOtherLanguages` Storybook story. Gate green: typecheck, lint, 173 tests, build, check:size (183.6 KB gz), check:colors; en/sv parity; no codename.
Sign in to join this conversation.
No Label
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: logaritmisk/biggus-dickus#55