Files
summercms/.planning/phases/14.2.1-translate-plugin/14.2.1-05-SUMMARY.md

11 KiB

phase, plan, subsystem, tags, requires, provides, affects, actuals, plan_head_before, plan_head_after, plugin_repo_head_after, tech-stack, key-files, key-decisions, patterns-established, requirements-completed, coverage, duration, completed, status
phase plan subsystem tags requires provides affects actuals plan_head_before plan_head_after plugin_repo_head_after tech-stack key-files key-decisions patterns-established requirements-completed coverage duration completed status
14.2.1-translate-plugin 05 i18n
translate
cabana
mltext
mlmarkdown
TranslatedExact
hydrateMLRecord
FORM_ENABLED_LOCALES
CR-01
phase provides
14.2.1-04 ML nested save, TranslationWriter adapter, TestMLNestedSave, SPA MLFields, phase gate
FormMeta.EnabledLocales on protect()'d form and relation schemas
TranslationWriter.TranslatedExact plus hydrateMLRecord on Show/save record maps
SPA FORM_ENABLED_LOCALES inject, create seed maps, and adopt merge
Regenerated OpenAPI, schema.d.ts, docs, and boardwalk dist
14.2.1-06
15-journal-plugin
tokens tasks commits
12147 3 2
ed81f2a0c1 424fe9ccc0 11ac3288d2f6775bfc22598c94ffe7dacf3c3dd1
added patterns
Admin GET/save hydrates declared ML fields through TranslationWriter.TranslatedExact; missing non-default locales stay empty (no D-11 fallback)
SPA ML selectors read FORM_ENABLED_LOCALES from schema meta; adopt merges maps instead of replacing with a host scalar
created modified
modules/cabana/schema_types.go
modules/cabana/field_ml.go
modules/cabana/crud.go
modules/cabana/http.go
modules/cabana/ml_test.go
modules/cabana/ml_smoke_test.go
modules/cabana/README.md
docs/backend/forms.md
docs/backend/admin-controllers.md
admin/src/components/form/formContext.ts
admin/src/components/form/formState.ts
admin/src/views/FormView.vue
admin/src/components/form/fields/MLTextField.vue
admin/src/components/form/fields/MLMarkdownField.vue
admin/src/components/relation/RelationChildModal.vue
admin/src/components/relation/RelationPickerModal.vue
admin/tests/form/MLFields.test.ts
admin/tests/form/formState.test.ts
admin/openapi/admin.json
admin/src/api/schema.d.ts
modules/boardwalk/dist/
../sm-translate-plugin/classes/admin_writer.go
writer-exact: add TranslatedExact to cabana.TranslationWriter; AdminWriter delegates to classes.TranslatedExact
hydrateMLRecord runs after projectFullRecord on Show/save only; list rows stay host scalars
FORM_ENABLED_LOCALES is SPA-only; docs name cabana identifiers EnabledLocales, TranslatedExact, hydrateMLRecord
Exact admin reads go through TranslationWriter.TranslatedExact on the same Lookup as WriteTranslated; cabana never imports sm-translate-plugin
Create seeds {code: ""} for every enabled locale; adopt overlays localeRecord and places a host string on the default locale without dropping siblings
D-06
D-17
id description requirement verification human_judgment
D1 Show/save RecordResult.Data for declared mltext/mlmarkdown is a locale map; missing pl is empty, not D-11 English; host column stays the default scalar D-17
kind ref status
unit modules/cabana#TestMLHydration pass
kind ref status
unit modules/cabana#TestMLNestedSave pass
false
id description requirement verification human_judgment
D2 Create seeds empty maps for every enabled locale; FormView.adopt merges a GET host string without dropping sibling keys; MLTextField options equal FORM_ENABLED_LOCALES D-06
kind ref status
automated_ui admin/tests/form/MLFields.test.ts pass
kind ref status
unit admin/tests/form/formState.test.ts pass
false
id description requirement verification human_judgment
D3 MLMarkdownField and RelationChildModal share the inject/seed/adopt path; OpenAPI FormMeta.enabledLocales, docs, and boardwalk dist stay in sync D-06
kind ref status
automated_ui admin/tests/form/MLFields.test.ts pass
kind ref status
other bash scripts/check-admin-openapi.sh --check pass
kind ref status
other go test ./cmd/summer -run TestDocsTree pass
kind ref status
unit sm-translate-plugin/classes#TestTranslatableGetSet pass
false
11min 2026-10-06 complete

Phase 14.2.1 Plan 05: Hydrate enabled locales on admin ML forms Summary

Admin ML create/GET/save hydrates every enabled locale through TranslationWriter.TranslatedExact so the SPA lists en+pl together and posts full locale maps (CR-01)

Performance

  • Duration: 11 min
  • Started: 2026-10-06T13:32:15Z
  • Completed: 2026-10-06T13:43:26Z
  • Tasks: 3
  • Files modified: 24

Accomplishments

  • Task 1 locked writer-exact: TranslatedExact is a required method on cabana.TranslationWriter. Cabana does not import the plugin. classes.TranslatedExact still skips D-11 fallback.
  • Show/save record payloads expand declared mltext/mlmarkdown fields to {locale: value} via hydrateMLRecord. Default locale comes from the host column; other codes come from exact stored values; missing non-default codes are empty strings. List rows stay scalars.
  • Protect()'d formSchema and relationSchema copy TranslationWriter.EnabledLocales onto FormMeta.enabledLocales. Create seeds {en: "", pl: ""}. FormView / RelationChildModal adopt merges maps so a host string cannot wipe sibling locales. ML selectors read FORM_ENABLED_LOCALES.
  • OpenAPI, schema.d.ts, cabana README, forms/admin-controllers docs, and modules/boardwalk/dist/ regenerated. WR-02 fillChild is unchanged (Plan 06).

Task Commits

Each task was committed atomically:

  1. Task 1: Confirm TranslationWriter.TranslatedExact as the hydration contract — decision writer-exact (no code commit)
  2. Task 2: Hydrate one mltext create/GET/save path and show en+pl on the SPA
    • 0f8d137 (feat) summercms.go — hydrate ML create/GET/save through TranslatedExact
    • 11ac328 (feat) sm-translate-plugin — AdminWriter.TranslatedExact delegates to classes.TranslatedExact
  3. Task 3: Cover mlmarkdown, relation-child adopt, and regenerate docs/OpenAPI/TS/dist
    • 424fe9c (feat) summercms.go — mlmarkdown, child adopt, docs/OpenAPI/dist

Plan metadata: this SUMMARY commit

Nothing was pushed. Dist replacement deleted modules/boardwalk/dist/assets/index-CT96jdWe.js and added index-B08bxLq5.js (intentional Vite hash).

Files Created/Modified

  • modules/cabana/schema_types.go — FormMeta.EnabledLocales (json:"enabledLocales,omitempty")
  • modules/cabana/field_ml.go — TranslationWriter.TranslatedExact, hydrateMLRecord, recordingWriter exact reads
  • modules/cabana/crud.go — hydrate after projectFullRecord on Show and save
  • modules/cabana/http.go — form/relation schema Lookup copies enabled locales onto envelope meta
  • modules/cabana/ml_test.go — TestMLHydration; TestMLNestedSave projected title is the hydrated map
  • modules/cabana/ml_smoke_test.go — nested-save smoke expects the hydrated title map
  • admin/src/components/form/formContext.ts — FORM_ENABLED_LOCALES
  • admin/src/components/form/formState.ts — initialValues(fields, enabledLocales), mergeMLValue
  • admin/src/views/FormView.vue — provide inject; create seed; adopt merge
  • admin/src/components/form/fields/MLTextField.vue / MLMarkdownField.vue — selector options from inject
  • admin/src/components/relation/RelationChildModal.vue — re-provide inject; seed and adopt merge
  • admin/src/components/relation/RelationPickerModal.vue — pivot initialValues(..., [])
  • admin/tests/form/MLFields.test.ts — create-empty and GET-string merge for mltext and mlmarkdown
  • admin/tests/form/formState.test.ts — seed maps and merge helper
  • admin/openapi/admin.json, admin/src/api/schema.d.ts — enabledLocales?: string[]
  • modules/boardwalk/dist/ — Vite build matching the SPA change
  • modules/cabana/README.md, docs/backend/forms.md, docs/backend/admin-controllers.md — hydration contract
  • ../sm-translate-plugin/classes/admin_writer.go — AdminWriter.TranslatedExact

Decisions Made

  • writer-exact (Task 1, user-selected): add TranslatedExact to the published cabana.TranslationWriter interface; AdminWriter delegates to classes.TranslatedExact. Rejected optional-reader (hydration would silently no-op) and import-plugin (cabana must not import sm-translate-plugin).
  • Hydration is Show/save only; Localize stays cache/no-DB; list Meta stays locale-only.
  • FORM_ENABLED_LOCALES is documented as SPA-only so the docs identifier checker does not treat it as a Go ident.

Deviations from Plan

Auto-fixed Issues

1. [Rule 3 - Blocking] Vitest --run path vs include glob

  • Found during: Task 2 verify
  • Issue: npm --prefix admin test -- --run admin/tests/form/MLFields.test.ts finds no files because Vitest include is tests/** under admin/.
  • Fix: Ran tests/form/MLFields.test.ts (and the same relative paths in Task 3). Same pattern as 14.2.1-04.
  • Files modified: none (verify command only)
  • Verification: Task 2 then Task 3 Vitest PASS
  • Committed in: n/a

2. [Rule 1 - Bug] vue-tsc rejected MLFields mount props

  • Found during: Task 3 npm --prefix admin run typecheck
  • Issue: mlMount passed Record<string, unknown> into Vue props (TS2322).
  • Fix: Cast mount props as never.
  • Files modified: admin/tests/form/MLFields.test.ts
  • Verification: npm --prefix admin run typecheck PASS
  • Committed in: 424fe9c

Total deviations: 2 auto-fixed (1 blocking verify path, 1 typecheck) Impact on plan: Required for green Task 2/3 gates. No scope creep. fillChild untouched. No gormigrate file. No npm pin change (T-14.2.1-SC).

Issues Encountered

  • Task 3 combined gate used the Vitest relative paths above; plugin TestTranslatableGetSet still PASS after AdminWriter.TranslatedExact.
  • Unrelated dirty .planning/ files from other sessions were left unstaged.
  • requirements.mark-complete D-06 D-17 was a no-op: those IDs are CONTEXT.md decisions, not rows in REQUIREMENTS.md (not_found). They remain recorded on this SUMMARY's requirements-completed.

User Setup Required

None - no external service configuration required.

Next Phase Readiness

CR-01 is closed on the admin form path (D-06, D-17). Plan 06 still owns WR-02 (fillChild must lift nested ML maps on relation-child saves) and named tests last. Journal (Phase 15) can keep translatable fields once WR-02 lands.


Phase: 14.2.1-translate-plugin Completed: 2026-10-06

Self-Check: PASSED