Skip to content

translateAction ignores _actions.ACTION.description and _actions.ACTION.params.*, which the schema declares and the lint validates #14254

Description

@os-warren

Measured on @objectstack/spec 17.2.0.

Note: placeholders below are written ACTION / PARAM rather than in angle brackets — GitHub's body sanitizer strips <a>-shaped fragments, which silently ate them on the first revision of this issue.

TranslationItemSchema declares, per action:

_actions.ACTION.label
_actions.ACTION.description
_actions.ACTION.confirmText
_actions.ACTION.successMessage
_actions.ACTION.params.PARAM.{ label, helpText, placeholder, options }
_actions.ACTION.resultDialog.{ title, description, acknowledge, fields }

and @objectstack/rest's validateTranslationReferences validates the keys of both description and paramscheckActionParams reports a param key the action does not declare, with a hint naming the declared params.

But translateAction overlays only label, confirmText, successMessage and resultDialog. Reproduced directly against the shipped resolver:

const bundle = { 'zh-CN': { objects: { duly_task: { _actions: { duly_task_skip: {
  label: '跳过', description: '动作描述', confirmText: '确认', successMessage: '已跳过',
  params: { skip_reason: { label: '原因', helpText: '帮助', placeholder: '占位' } },
} } } } } };

translateAction(action, bundle, { locale: 'zh-CN' });
label:          '跳过'          ← translated
confirmText:    '确认'          ← translated
successMessage: '已跳过'        ← translated
description:    'D'             ← NOT translated
params[0]:      { label: 'Why skipped', helpText: 'H', placeholder: 'P' }   ← NOT translated

The asymmetry is what makes this expensive: the keys are declared, a linter checks them and suggests corrections for them, so an author has every reason to believe they work. An action's description is its tooltip/subtitle, and params[].label / .placeholder / .helpText are the entire parameter dialog — for duly_task_skip that dialog is the only place the reason can be entered, so a Chinese deployment gets a Chinese button opening an English form.

Same asymmetry for the globalActions branch.

Expected: translateAction overlays description, and each params[i] matched by name (falling back to field, the way checkActionParams collects them) for label / helpText / placeholder / options.

The application (objectstack-ai/duly) authors these keys today rather than leaving them empty — they are the spec's own keys, they are served to REST/OpenAPI/MCP callers reading the action, and they start rendering the moment this lands. Recorded there in src/translations/authored-text.ts with the measurement above.

Filed from objectstack-ai/duly#18.


Generated by Claude Code

Metadata

Metadata

Assignees

Labels

Type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions