Skip to content

feat(labels): a host gives every word of templates, editors and forms with setReqraftLabels (0.10.73) - #161

Open
davidnich wants to merge 8 commits into
developfrom
feature/host-labels
Open

davidnich wants to merge 8 commits into
developfrom
feature/host-labels

Conversation

@davidnich

@davidnich davidnich commented Nov 5, 2026 •

Copy link
Copy Markdown
Member

What changed

setReqraftLabels() lets a host give Reqraft's words in its own language. It takes Partial words per part, merged over DEFAULT_REQRAFT_LABELS, so a host that gives nothing has today's English, and no story's look changes.

Part Covers
templateList buildTemplates: example values, tooltips, the example-value window
templateTree node kinds, record fields, template contexts, functions, keywords, color meanings, the "names nothing" message
templateBrowser, templatePicker the picker's search, levels, Use, load failure and empty states, Key action
templateField, valueTabs, savedValues a template field's menu, buttons and tooltips, its value tabs, its saved values
editor DPQL and SmartEditor: completion sections and kinds, empty and pending states, find and replace
formEngine rows, toolbar, boxes, footer, field messages, help dialog, what a value reads as in its row

Why one setting and not a prop: the words are read where no component is: trees and completions built outside React, and lists kept between forms in TemplatesCache.

Language change: useReqraftLabels() redraws a component; hooks that memoize trees list the words as a dependency; a cached list is built again from the payload it was built from, without another request.

Words a component or provider is given keep priority over the host's: buildTemplates' labels, TemplatePicker's labels, pickerLabels, valueTabsLabels, compactBoxLabels.

Types named once: a place that takes several types said the same words twice when they share a name, such as "a value of type Integer or a value of type Integer", because a soft or optional type is its base type and string and richtext are both "text". The builder and argumentLabel now share typesInASentence, which says each name once and takes its join from formEngine.typesJoin.

Opening a row of a drawn form: initialExpandedOptions is spent once, so a host that had to open a row later could only draw the form again, losing what was open and typed in its other rows. expandOptionsRequest: { options, key } opens the named rows for each new key, alongside those already open; a key already answered opens nothing again. qorus-ide uses it to take the reader to a field a save refused, in a row the reader had closed.

A picker opened in the text follows the text on a resize: since 0.10.72 a picker opened from a button or chip follows it when the window's width changes, but one opened by a click in the text had nothing to follow and stayed at the point of the window it opened at (qorus-ide #301, qlip #370: interfaces-qog-state-detail--state-data-is-shown, the picker at the left of the canvas and its field at the right). It now goes with the text it was opened in, as far from it as when it opened, so after a resize it is where opening it again would draw it. Reproduced in a browser by opening at 700 px and widening to 1280 px; checked again after the fix.

Comparison by word removed: DPQL completions compared kindLabel === 'Template context', which a translation would break; a row now carries isTemplateContext.

Not covered

  • The form engine's variants/ (focusDemo and the Variant components): imported only by their stories and not exported, so they never reach a user.
  • The expression builder and other field types (schema-definition, Cron, File and so on) still have their own English.
  • The two glyphs and format strings that are not words: Aa, byte units.

Stories

No story needs a review of its look, so there is no story table. Existing English is unchanged.

qlip build 20261105-215727, with images byte-identical to builds 463, 467 and 20261105-195204 (compared by image hash), shows 23 changed frames of 898, none new, each differing by 1 to 7 pixels. The toolbar's "N need attention" was two text nodes and is now one string, which a translation needs, so the likely cause is a change in anti-aliasing on that line. That cause is confirmed on one crop only (form-engine-formengine--compact, against its baseline), where nothing moves; for the other 22 frames it is inferred from where and how large their diff regions are. Each frame carries this cause on qlip.

Tests

__tests__/reqraftLabels.test.tsx covers the merge and each route (list, tree, picker, editor, form), including a language change. __tests__/reqraftLabelsDrawn.test.tsx draws a real form through a language change, and templateBrowserKeyAction.test.tsx a real picker. Unit: 3405 passed. TemplatePicker and DpqlEditor story plays: 77 passed. __tests__/autocompleteBeforeReady.test.ts keeps a picker opened at the caret with its text, and one opened from an element as far from it as when it opened, as the window is resized; both fail on 0.10.72. __tests__/formEngineExpandOptionsRequest.test.tsx opens a row of a drawn form while a row the reader opened stays open, answers each key once, and waits for a row the form does not have yet.

Version 0.10.73 (develop 0.10.72 + 1, as the version check requires). #160 also holds 0.10.73: whichever merges second merges develop and bumps once.

🤖 Generated with Claude Code

https://claude.ai/code/session_011GUDvpCiSMgFRNj1RYLYqv

… with setReqraftLabels (0.10.74)

setReqraftLabels() merges a host's words over the English defaults, so a host that gives nothing has the English it had. It covers the template list, tree and picker, a template field's controls, value tabs and saved values, the editors, and FormEngine. What is drawn changes when the language changes, and a list kept between forms is built again from what the server said.

Words are one setting for the page because trees, completions and cached lists are built outside components. No code decides anything by comparing a word: a template context says so with a flag.
@davidnich
davidnich requested a review from Foxhoundn as a code owner November 5, 2026 08:49
@davidnich davidnich changed the title feat(labels): a host gives every word of templates, editors and forms with setReqraftLabels (0.10.74) feat(labels): a host gives every word of templates, editors and forms with setReqraftLabels (0.10.73) Nov 5, 2026
@github-actions

github-actions Bot commented Nov 5, 2026 •

Copy link
Copy Markdown

📦 Prerelease published for this PR:

@qoretechnologies/reqraft@0.10.74-pr.161.gb78d5ca

Install it in a consumer (updates package.json + lockfile):

yarn add @qoretechnologies/reqraft@0.10.74-pr.161.gb78d5ca

Published under the pr dist-tag — latest/beta are untouched. Repoint consumers to the released version once this PR merges.

@qlip-qore-technologies

qlip-qore-technologies Bot commented Nov 5, 2026 •

Copy link
Copy Markdown

qlip visual regression

✅ No visual changes.

Review build 20261106-104258 in the dashboard →

An expected type listed the same words twice, "a value of type Integer or a value of type Integer": a place takes a list of types, and several of them are one name, because a soft or optional type is its base type and two types can share a sentence form (string and richtext are both "text"). The builder's sentence now says each once, through the one join argumentLabel also uses, and the word that joins them is a host's (formEngine.typesJoin).
…sRequest)

initialExpandedOptions is spent once, and a host that had to open a row later could only draw the form again, which threw away what was open and typed in its other rows. Each new expandOptionsRequest key opens the rows it names alongside those already open; a key already answered opens nothing again. qorus-ide needs it to take the reader to a field a save refused, in a row the reader has closed.
…the window is resized

A picker opened by a click in the text, at the caret, had nothing to follow when the window's width changed: it stayed at the point of the window it opened at while the text moved away (qorus-ide #301, qlip #370: the picker at the left of the canvas, its field at the right). It now goes with the text it was opened in, and any picker stays as far from what it was opened from as when it opened, so after a resize it is where opening it again would draw it.
Foxhoundn
Foxhoundn previously approved these changes Nov 6, 2026

@Foxhoundn Foxhoundn left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Visual review approved in Qlip (build #469). https://qlip.qoretechnologies.com/builds/20261105-215727

@davidnich

Copy link
Copy Markdown
Member Author

Merged develop (#159's CI change, no conflicts) and bumped to 0.10.74, because 0.10.73 was already released from #159. No source change since your approval; PullRequestTests and qlip both pass on b78d5ca. The new push dismissed the approval, so please re-approve.

🤖 Generated with Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants