Skip to content

objectui: a second hardcoded aria-label of "Resize drawer" in plugin-detail's RecordDetailDrawer — same literal #5506 localized in NavigationOverlay #5733

Description

@yinlianghui

Found while sweeping the consumption radius for objectstack#5506 (objectui PR objectstack-ai/objectui#3423). Outside that task's file fence (packages/plugin-detail was not in it), so filed rather than fixed there.

(Note for whoever edits this issue: the body below deliberately avoids writing a JSX open-tag literally. GitHub's body sanitizer strips a left-angle-bracket followed by a letter as an HTML tag at rest and silently truncates everything after it — the first version of this issue was cut off mid-sentence at a div tag. Describe tags, don't paste them.)

The finding

packages/plugin-detail/src/RecordDetailDrawer.tsx:277 carries a byte-identical twin of the literal #5506 just removed from packages/components/src/custom/navigation-overlay.tsx:

  • guarded by {resizable && ()}
  • a plain div element carrying role="separator", aria-orientation="vertical", aria-label="Resize drawer", and onPointerDown={handleResizePointerDown}
  • className "hidden sm:block absolute left-0 top-0 h-full w-1.5 cursor-col-resize …"

Same control (a drag-resize handle on a record drawer's left edge), same shape (a separator with no visible label, so the literal is the control to a screen reader), same defect: a zh/ja/de session gets one English string in an otherwise localized drawer.

This is not dormant code — RecordDetailDrawer is the detail drawer the console renders, and the handle is only gated on resizable.

Why this should be a one-liner

Two halves of the fix already exist once objectui PR objectstack-ai/objectui#3423 merges:

  1. The key common.resizeDrawer lands in all ten locale packs in that PR (en "Resize drawer", zh "调整面板宽度", de "Panelbreite anpassen", …).
  2. RecordDetailDrawer.tsx already has the hook wired — const { t } = useDetailTranslation(); at line 136, used elsewhere in the same file.

So the change is: add 'common.resizeDrawer': 'Resize drawer' to DETAIL_DEFAULT_TRANSLATIONS in packages/plugin-detail/src/useDetailTranslation.ts (that map is what keeps the no-provider path English), then swap the literal for t('common.resizeDrawer') at line 277.

Acceptance

  • RecordDetailDrawer's separator announces the session locale's value; a zh session sees no "Resize drawer" anywhere.

  • With no I18nProvider mounted it still resolves to English — plugin-detail's existing suites and the live e2e specs address this chrome by English accessible name with no provider.

  • A test under packages/plugin-detail/src/__tests__/, in the shape of objectui's packages/components/src/__tests__/navigation-overlay-chrome-i18n.test.tsx.

    Note the trap that PR hit and paid for: createI18n calls instance.use(initReactI18next), and initReactI18next registers that instance as react-i18next's module-global default. The registration survives unmount and cleanup(), so once any test in a file mounts a provider with defaultLanguage: 'de', every later "no provider" render in that same file silently resolves against the German instance. Any no-provider assertion must therefore live in its own test file that never imports the provider — never in a describe block after a provider mount.

Blocked-by: the common.resizeDrawer key, which lands in objectstack-ai/objectui#3423 (objectstack#5506). Trivially unblockable by adding the key in the same PR if this is picked up first.

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions