fix(editor): code the engine-composed form labels and notes for translation #257

Merged
dominik.polakovics merged 1 commit from afk/236 into main 2026-10-13 11:04:04 +02:00

Closes #236

What

Every editor-facing label and note the engine composes in Go now carries an apimsg code next to its English text, which is unchanged byte for byte. The client translates the code through its catalog.

Server

  • New codes in internal/apimsg/codes_core.go:
    • label.title, label.date, label.status
    • label.addressSegment
    • label.backendLayout, label.backendLayoutNextLevel
    • note.followsSource, note.followsSourceElement, note.homeAlwaysPublished
  • element.FormField gains noteCode.
  • element.Param gains an internal LabelCode (json:"-"). Sidecars cannot set it, because they decode strictly into RawParam; a test pins this. Schema.Describe hands it on as FormField.LabelCode, so the engine-built params carry their codes: the implicit title, the translation slug and both layout pickers.
  • editormodule.FieldInfo and Filter gain labelCode. The built-in title/date/status label carries its code; a declared label clears it. buildFilter takes the resolved FieldInfo, so the filter's label and code have one owner.
  • Notes now come from the registry instead of English constants: the content root's read-only Enabled note, a translation's read-only fields, and a connected translation's synced element fields (internal/server/forms.go, found while grepping).
  • web/src/i18n/servermessages.json is regenerated.

Client

  • web/src/api/labels.ts displayLabel(text, code) is the one place that turns a coded label, note or built-in title into display text. #227 will extend it.
  • decodeFormDescription (forms.ts), fetchModules (modules.ts), decodeTree (tree.ts) and the pending list (publish.ts) call it; none inlines the lookup any more.
  • en.json and de.json have a server.* entry for every new code. The German follows glossary.md: Titel, Adresssegment, Backend-Layout, …

Docs: the README API section documents labelCode/noteCode on form fields and labelCode on module fields, filters and options. scaffold/site/AGENTS.md and the skills document none of these wire shapes and need no change.

Verification

  • make test passes: Go, and vitest with 121 files and 3125 tests, the i18n parity test included. make build passes, and go vet and gofmt are clean.
  • New Go tests cover the codes on the settings form, translation form and editor modules, and that a declared title or date carries no code. New vitest tests (labels.test.ts) cover the helper, and describeForm/fetchModules in German and in English, where the English result equals exactly what the server sent.
  • Live: harness serve on testdata/multilingual-site, then POST /api/form for the about.md translation (lang: de). The title field returns labelCode: label.title and the slug field labelCode: label.addressSegment, both with unchanged English labels.

Left as is

  • The Enabled switch's on/off hints are still English: "Page is built and reachable", "Shown on the site", …. They travel in settings.on/off, not in a label or note field; that could be a follow-up.
  • pageops/translation.go fallbackTitle writes "Home" into front matter. That is content, not a label.

🤖 Generated with Claude Code

Closes #236 ## What Every editor-facing label and note the engine composes in Go now carries an `apimsg` code next to its English text, which is unchanged byte for byte. The client translates the code through its catalog. **Server** - New codes in `internal/apimsg/codes_core.go`: - `label.title`, `label.date`, `label.status` - `label.addressSegment` - `label.backendLayout`, `label.backendLayoutNextLevel` - `note.followsSource`, `note.followsSourceElement`, `note.homeAlwaysPublished` - `element.FormField` gains `noteCode`. - `element.Param` gains an internal `LabelCode` (`json:"-"`). Sidecars cannot set it, because they decode strictly into `RawParam`; a test pins this. `Schema.Describe` hands it on as `FormField.LabelCode`, so the engine-built params carry their codes: the implicit title, the translation slug and both layout pickers. - `editormodule.FieldInfo` and `Filter` gain `labelCode`. The built-in title/date/status label carries its code; a declared label clears it. `buildFilter` takes the resolved `FieldInfo`, so the filter's label and code have one owner. - Notes now come from the registry instead of English constants: the content root's read-only Enabled note, a translation's read-only fields, and a connected translation's synced element fields (`internal/server/forms.go`, found while grepping). - `web/src/i18n/servermessages.json` is regenerated. **Client** - `web/src/api/labels.ts` `displayLabel(text, code)` is the one place that turns a coded label, note or built-in title into display text. #227 will extend it. - `decodeFormDescription` (`forms.ts`), `fetchModules` (`modules.ts`), `decodeTree` (`tree.ts`) and the pending list (`publish.ts`) call it; none inlines the lookup any more. - `en.json` and `de.json` have a `server.*` entry for every new code. The German follows `glossary.md`: Titel, Adresssegment, Backend-Layout, … **Docs:** the README API section documents `labelCode`/`noteCode` on form fields and `labelCode` on module fields, filters and options. `scaffold/site/AGENTS.md` and the skills document none of these wire shapes and need no change. ## Verification - `make test` passes: Go, and vitest with 121 files and 3125 tests, the i18n parity test included. `make build` passes, and `go vet` and `gofmt` are clean. - New Go tests cover the codes on the settings form, translation form and editor modules, and that a declared title or date carries no code. New vitest tests (`labels.test.ts`) cover the helper, and `describeForm`/`fetchModules` in German and in English, where the English result equals exactly what the server sent. - Live: `harness serve` on `testdata/multilingual-site`, then `POST /api/form` for the `about.md` translation (`lang: de`). The title field returns `labelCode: label.title` and the slug field `labelCode: label.addressSegment`, both with unchanged English labels. ## Left as is - The Enabled switch's on/off hints are still English: "Page is built and reachable", "Shown on the site", …. They travel in `settings.on/off`, not in a label or note field; that could be a follow-up. - `pageops/translation.go` `fallbackTitle` writes "Home" into front matter. That is content, not a label. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
fix(editor): code the engine-composed form labels and notes for translation
All checks were successful
ci / build-and-test (pull_request) Successful in 3m3s
ci / release (pull_request) Has been skipped
22f6f035a3
The labels and notes the engine builds in Go — a page's implicit title, a
translation's address segment and read-only note, the two backend-layout
pickers, the content root's Enabled note, a connected translation's synced
element note, and a module's built-in title/date/status fields and status
filter — now carry an apimsg code (label.*, note.*) next to their unchanged
English text: FormField gains noteCode, Param an internal LabelCode handed
on by Describe, FieldInfo and Filter a labelCode.

The client resolves every coded label, note and built-in title through one
helper, api/labels.ts displayLabel; forms.ts, modules.ts, tree.ts and
publish.ts call it instead of inlining the lookup. en.json and de.json
carry the new server.* entries.

Closes #236

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Author
Owner

[autoland] verdict: pass

PASS — validated by the autoland lander.

Signal: CI aggregate success (ci / build-and-test: npm build + vitest, go vet, go test ./..., go build — runs unconditionally, so it exercised every touched path). gofmt clean on the changed Go files.

Conventions: Conventional Commits title fix(editor): …; body carries Closes #236; branch is at main's head (2bbb43f), no conflict.

Scope vs #236: every engine-composed label/note is coded beside unchanged English — implicit title (internal/pageops/settings.go:620), address segment (translation_settings.go:761), both layout pickers (settings.go:429-430), module built-ins title/date/status + status filter (editormodule/load.go:135, :216), read-only translation note (translation_settings.go:74), home Enabled note (settings.go:189), plus the synced-element note (server/forms.go:575) found by the issue's grep check. Param.LabelCode is json:"-" and sidecar-unsettable (pinned by element/load_test.go). Client has one owner, web/src/api/labels.ts displayLabel, called by forms.ts, modules.ts, tree.ts, publish.ts; no inline lookup remains. en/de catalogs and servermessages.json updated; German follows glossary.md (Titel, Backend-Layout, Standardsprache; Adresssegment matches existing de.json usage). README documents labelCode/noteCode. AGENTS.md and the scaffolded skills document none of these wire shapes — no change needed.

[autoland] verdict: pass PASS — validated by the autoland lander. Signal: CI aggregate `success` (ci / build-and-test: npm build + vitest, go vet, go test ./..., go build — runs unconditionally, so it exercised every touched path). gofmt clean on the changed Go files. Conventions: Conventional Commits title `fix(editor): …`; body carries `Closes #236`; branch is at main's head (2bbb43f), no conflict. Scope vs #236: every engine-composed label/note is coded beside unchanged English — implicit title (internal/pageops/settings.go:620), address segment (translation_settings.go:761), both layout pickers (settings.go:429-430), module built-ins title/date/status + status filter (editormodule/load.go:135, :216), read-only translation note (translation_settings.go:74), home Enabled note (settings.go:189), plus the synced-element note (server/forms.go:575) found by the issue's grep check. Param.LabelCode is json:"-" and sidecar-unsettable (pinned by element/load_test.go). Client has one owner, web/src/api/labels.ts displayLabel, called by forms.ts, modules.ts, tree.ts, publish.ts; no inline lookup remains. en/de catalogs and servermessages.json updated; German follows glossary.md (Titel, Backend-Layout, Standardsprache; Adresssegment matches existing de.json usage). README documents labelCode/noteCode. AGENTS.md and the scaffolded skills document none of these wire shapes — no change needed.
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
Cloonar/deckle!257
No description provided.