docs(14.2.1): lock Go tables to golem15_translate_*
Execute-phase Task 2 chose golem15-prefix over the researched winter_translate_* names so the plugin ships vendor tables; PHP winter names stay a later import mapping. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -838,7 +838,7 @@ Plans:
|
|||||||
**Repos:** `sm-translate-plugin` (new); `sm-grzybyfunkcjonalne-app` (proof host); `summercms.go` for ML field types and the surf locale seam
|
**Repos:** `sm-translate-plugin` (new); `sm-grzybyfunkcjonalne-app` (proof host); `summercms.go` for ML field types and the surf locale seam
|
||||||
**Success Criteria** (what must be TRUE):
|
**Success Criteria** (what must be TRUE):
|
||||||
|
|
||||||
1. Plugin repo exists with `winter_translate_*` schema (locales, attributes, indexes, empty messages table), Locale model, en/pl seed, and context-safe Translator.
|
1. Plugin repo exists with `golem15_translate_*` schema (locales, attributes, indexes, empty messages table), Locale model, en/pl seed, and context-safe Translator.
|
||||||
2. Translatable API (`Translatable()`, `WithLocale`, get/set, default-locale fallback) and permissioned Locales admin work; a fixture model saves and reads `en`+`pl`.
|
2. Translatable API (`Translatable()`, `WithLocale`, get/set, default-locale fallback) and permissioned Locales admin work; a fixture model saves and reads `en`+`pl`.
|
||||||
3. Cabana `markdown`/`mltext`/`mlmarkdown` compose; nested locale writes are not dropped; docs, OpenAPI, TS types and `boardwalk` `dist/` update in the same change.
|
3. Cabana `markdown`/`mltext`/`mlmarkdown` compose; nested locale writes are not dropped; docs, OpenAPI, TS types and `boardwalk` `dist/` update in the same change.
|
||||||
4. Proof host `sm-grzybyfunkcjonalne-app` boots with user+translate; unit tests are the last plan.
|
4. Proof host `sm-grzybyfunkcjonalne-app` boots with user+translate; unit tests are the last plan.
|
||||||
@@ -848,7 +848,7 @@ Plans:
|
|||||||
Plans:
|
Plans:
|
||||||
|
|
||||||
**Wave 1**
|
**Wave 1**
|
||||||
- [ ] 14.2.1-01-PLAN.md — Plugin repo, `winter_translate_*` schema, Locale, en/pl seed, Translator, surf Resolver
|
- [ ] 14.2.1-01-PLAN.md — Plugin repo, `golem15_translate_*` schema, Locale, en/pl seed, Translator, surf Resolver
|
||||||
|
|
||||||
**Wave 2** *(blocked on Wave 1 completion)*
|
**Wave 2** *(blocked on Wave 1 completion)*
|
||||||
- [ ] 14.2.1-02-PLAN.md — Translatable API, Locales admin, fixture save/read
|
- [ ] 14.2.1-02-PLAN.md — Translatable API, Locales admin, fixture save/read
|
||||||
|
|||||||
@@ -207,6 +207,7 @@ Progress: [███████░░░] 67%
|
|||||||
Decisions are logged in PROJECT.md Key Decisions table.
|
Decisions are logged in PROJECT.md Key Decisions table.
|
||||||
Recent decisions affecting current work:
|
Recent decisions affecting current work:
|
||||||
|
|
||||||
|
- [Phase 14.2.1]: D-10 Go tables are `golem15_translate_*` (execute Task 2 `golem15-prefix`, 2026-10-06). PHP pin still uses `winter_translate_*`; do not copy those names into Go DDL.
|
||||||
- [Phase 14.1]: 14.1-01 Task 1 `ship-shared-full` — create `golem15_user_oauth_identities` in the shared sm-user-plugin with the full PHP column set (locked D-01 and D-07).
|
- [Phase 14.1]: 14.1-01 Task 1 `ship-shared-full` — create `golem15_user_oauth_identities` in the shared sm-user-plugin with the full PHP column set (locked D-01 and D-07).
|
||||||
- [Phase 14.1]: Identity Index/Destroy are host-mounted on the JWT group; the user plugin does not register them under `/_user`. `/me` unrestricted `collection_ids` is JSON null (D-09); `scopes` stay `[]`.
|
- [Phase 14.1]: Identity Index/Destroy are host-mounted on the JWT group; the user plugin does not register them under `/_user`. `/me` unrestricted `collection_ids` is JSON null (D-09); `scopes` stay `[]`.
|
||||||
- [Phase 14.1]: Corpus is 175/175/0 with zero pending routes. Live Nuxt Connected accounts and fonoteka-mcp `me()` stay Phase 15 UAT.
|
- [Phase 14.1]: Corpus is 175/175/0 with zero pending routes. Live Nuxt Connected accounts and fonoteka-mcp `me()` stay Phase 15 UAT.
|
||||||
|
|||||||
@@ -12,10 +12,10 @@ files_modified:
|
|||||||
- ../sm-translate-plugin/models/registry.go
|
- ../sm-translate-plugin/models/registry.go
|
||||||
- ../sm-translate-plugin/models/locale.go
|
- ../sm-translate-plugin/models/locale.go
|
||||||
- ../sm-translate-plugin/updates/registry.go
|
- ../sm-translate-plugin/updates/registry.go
|
||||||
- ../sm-translate-plugin/updates/202610060001_create_winter_translate_locales.go
|
- ../sm-translate-plugin/updates/202610060001_create_golem15_translate_locales.go
|
||||||
- ../sm-translate-plugin/updates/202610060002_create_winter_translate_attributes.go
|
- ../sm-translate-plugin/updates/202610060002_create_golem15_translate_attributes.go
|
||||||
- ../sm-translate-plugin/updates/202610060003_create_winter_translate_indexes.go
|
- ../sm-translate-plugin/updates/202610060003_create_golem15_translate_indexes.go
|
||||||
- ../sm-translate-plugin/updates/202610060004_create_winter_translate_messages.go
|
- ../sm-translate-plugin/updates/202610060004_create_golem15_translate_messages.go
|
||||||
- ../sm-translate-plugin/updates/202610060005_seed_en_pl_locales.go
|
- ../sm-translate-plugin/updates/202610060005_seed_en_pl_locales.go
|
||||||
- ../sm-translate-plugin/classes/translator.go
|
- ../sm-translate-plugin/classes/translator.go
|
||||||
- modules/surf/locale_resolver.go
|
- modules/surf/locale_resolver.go
|
||||||
@@ -26,7 +26,7 @@ requirements: [D-01, D-02, D-03, D-04, D-07, D-08, D-10, D-12, D-15, D-16]
|
|||||||
must_haves:
|
must_haves:
|
||||||
truths:
|
truths:
|
||||||
- "D-01/D-02/D-03/D-04: implementation is derived only from the read-only PHP tree at SHA 725d547ec839f02b5fdc0f0a6faaed601a414d50; no PHP file changes."
|
- "D-01/D-02/D-03/D-04: implementation is derived only from the read-only PHP tree at SHA 725d547ec839f02b5fdc0f0a6faaed601a414d50; no PHP file changes."
|
||||||
- "D-10: gormigrate creates final `winter_translate_locales`, `winter_translate_attributes`, `winter_translate_indexes`, and empty `winter_translate_messages`; it creates no rainlab-era or `golem15_translate_*` tables."
|
- "D-10: gormigrate creates final `golem15_translate_locales`, `golem15_translate_attributes`, `golem15_translate_indexes`, and empty `golem15_translate_messages`; it creates no rainlab-era or `winter_translate_*` tables."
|
||||||
- "D-08: an idempotent seed creates enabled `en` as default at sort_order 1 and enabled non-default `pl` as Polski at sort_order 2, and never seeds `de`."
|
- "D-08: an idempotent seed creates enabled `en` as default at sort_order 1 and enabled non-default `pl` as Polski at sort_order 2, and never seeds `de`."
|
||||||
- "D-07/D-12: a backpack-published resolver selects URL prefix, valid user preferred_locale, remembered `golem15.translate.locale`, cookie-gated Accept-Language, then default, and surf stores only a validated code on context."
|
- "D-07/D-12: a backpack-published resolver selects URL prefix, valid user preferred_locale, remembered `golem15.translate.locale`, cookie-gated Accept-Language, then default, and surf stores only a validated code on context."
|
||||||
- "KERN-07: no package-level mutable current locale exists; `Translator.Locale(ctx)` and `towel.WithLocale` carry request state."
|
- "KERN-07: no package-level mutable current locale exists; `Translator.Locale(ctx)` and `towel.WithLocale` carry request state."
|
||||||
@@ -35,12 +35,12 @@ must_haves:
|
|||||||
- path: "../sm-translate-plugin/plugin.go"
|
- path: "../sm-translate-plugin/plugin.go"
|
||||||
provides: "compiled Plugin registration, migrations/models/config, Resolver publication"
|
provides: "compiled Plugin registration, migrations/models/config, Resolver publication"
|
||||||
contains: "golem15.translate"
|
contains: "golem15.translate"
|
||||||
- path: "../sm-translate-plugin/updates/202610060001_create_winter_translate_locales.go"
|
- path: "../sm-translate-plugin/updates/202610060001_create_golem15_translate_locales.go"
|
||||||
provides: "squashed Locale schema"
|
provides: "squashed Locale schema"
|
||||||
contains: "winter_translate_locales"
|
contains: "golem15_translate_locales"
|
||||||
- path: "../sm-translate-plugin/updates/202610060004_create_winter_translate_messages.go"
|
- path: "../sm-translate-plugin/updates/202610060004_create_golem15_translate_messages.go"
|
||||||
provides: "empty compatibility Messages table without admin"
|
provides: "empty compatibility Messages table without admin"
|
||||||
contains: "winter_translate_messages"
|
contains: "golem15_translate_messages"
|
||||||
- path: "../sm-translate-plugin/classes/translator.go"
|
- path: "../sm-translate-plugin/classes/translator.go"
|
||||||
provides: "context-only Translator and request Resolver"
|
provides: "context-only Translator and request Resolver"
|
||||||
contains: "func ("
|
contains: "func ("
|
||||||
@@ -93,7 +93,7 @@ Phase 14.2.1 has no mapped REQUIREMENTS.md IDs, so requirement probing is visibl
|
|||||||
## Artifacts this phase produces
|
## Artifacts this phase produces
|
||||||
|
|
||||||
- Module `git.golem15.com/golem15/sm-translate-plugin`, package `translate`, `Plugin.ID() == "golem15.translate"`.
|
- Module `git.golem15.com/golem15/sm-translate-plugin`, package `translate`, `Plugin.ID() == "golem15.translate"`.
|
||||||
- `models.Locale`, model and migration registries, five gormigrate entries, and exact `winter_translate_*` tables.
|
- `models.Locale`, model and migration registries, five gormigrate entries, and exact `golem15_translate_*` tables.
|
||||||
- `classes.Translator`, `Translator.Locale(context.Context)`, and a request resolver implementing surf's `LocaleResolver`.
|
- `classes.Translator`, `Translator.Locale(context.Context)`, and a request resolver implementing surf's `LocaleResolver`.
|
||||||
- Surf optional resolver seam with unchanged fallback behavior when the translate plugin is absent.
|
- Surf optional resolver seam with unchanged fallback behavior when the translate plugin is absent.
|
||||||
- Application-neutral plugin and surf README updates for exported contracts.
|
- Application-neutral plugin and surf README updates for exported contracts.
|
||||||
@@ -122,22 +122,22 @@ Phase 14.2.1 has no mapped REQUIREMENTS.md IDs, so requirement probing is visibl
|
|||||||
</task>
|
</task>
|
||||||
|
|
||||||
<task type="checkpoint:decision" gate="blocking-human">
|
<task type="checkpoint:decision" gate="blocking-human">
|
||||||
<name>Task 2: Confirm the one-way Winter table contract</name>
|
<name>Task 2: Confirm the one-way table contract</name>
|
||||||
<files>../sm-translate-plugin/updates/</files>
|
<files>../sm-translate-plugin/updates/</files>
|
||||||
<read_first>.planning/phases/14.2.1-translate-plugin/14.2.1-CONTEXT.md (D-10), .planning/phases/14.2.1-translate-plugin/14.2.1-RESEARCH.md (Tables, columns, indexes), /media/nvme/dev/golem15/fonoteka/plugins/golem15/translate/updates/version.yaml, /media/nvme/dev/golem15/fonoteka/plugins/golem15/translate/models/Locale.php</read_first>
|
<read_first>.planning/phases/14.2.1-translate-plugin/14.2.1-CONTEXT.md (D-10), .planning/phases/14.2.1-translate-plugin/14.2.1-RESEARCH.md (Tables, columns, indexes), /media/nvme/dev/golem15/fonoteka/plugins/golem15/translate/updates/version.yaml, /media/nvme/dev/golem15/fonoteka/plugins/golem15/translate/models/Locale.php</read_first>
|
||||||
<action>Record the selected schema contract before migrations are implemented. Research resolved D-10's provisional prefix against the frozen source: the only compatible selection is the final `winter_translate_*` table family. This gate records the one-way import/storage choice; it does not reopen the PHP pin or permit a JSON-column alternative.</action>
|
<action>Record the selected schema contract before migrations are implemented. Execute-phase Task 2 locked `golem15-prefix`: Go tables are `golem15_translate_*` with the PHP pin's columns and indexes. PHP still uses `winter_translate_*`; do not copy those names into Go DDL. This gate does not reopen the PHP pin or permit a JSON-column alternative.</action>
|
||||||
<decision>Which persistent table contract should this shared plugin publish?</decision>
|
<decision>Which persistent table contract should this shared plugin publish?</decision>
|
||||||
<context>Once released and imported by Journal, renaming these tables requires coordinated data migrations in every host. The frozen PHP pin explicitly reads `winter_translate_*` after its RainLab rename history.</context>
|
<context>Once released and imported by Journal, renaming these tables requires coordinated data migrations in every host. The frozen PHP pin reads `winter_translate_*`; the Go plugin deliberately uses `golem15_translate_*`.</context>
|
||||||
<options>
|
<options>
|
||||||
<option id="winter-final">
|
<option id="winter-final">
|
||||||
<name>Squash directly to the four final winter_translate_* tables</name>
|
<name>Squash directly to the four final winter_translate_* tables</name>
|
||||||
<pros>Matches SHA 725d547, Winter imports, and Journal cutover.</pros>
|
<pros>Matches SHA 725d547, Winter imports, and Journal cutover.</pros>
|
||||||
<cons>The names become a shared persistent contract.</cons>
|
<cons>Not the locked Go contract.</cons>
|
||||||
</option>
|
</option>
|
||||||
<option id="golem15-prefix">
|
<option id="golem15-prefix">
|
||||||
<name>Use provisional golem15_translate_* names</name>
|
<name>Use golem15_translate_* names</name>
|
||||||
<pros>Vendor-style naming.</pros>
|
<pros>Vendor-style naming; locked D-10 execute decision.</pros>
|
||||||
<cons>Contradicts the frozen source and breaks direct imports.</cons>
|
<cons>Winter import needs a later mapping; PHP source still says winter_translate_*.</cons>
|
||||||
</option>
|
</option>
|
||||||
<option id="host-json">
|
<option id="host-json">
|
||||||
<name>Store translations on host-model JSON columns</name>
|
<name>Store translations on host-model JSON columns</name>
|
||||||
@@ -151,22 +151,22 @@ Phase 14.2.1 has no mapped REQUIREMENTS.md IDs, so requirement probing is visibl
|
|||||||
</verify>
|
</verify>
|
||||||
<acceptance_criteria>
|
<acceptance_criteria>
|
||||||
- The response is recorded in the summary.
|
- The response is recorded in the summary.
|
||||||
- Task 3 starts only for `winter-final`; either alternative stops execution as a locked-decision conflict.
|
- Task 3 starts only for `golem15-prefix`; `host-json` stops as a locked-decision conflict. `winter-final` is the discarded research recommendation.
|
||||||
</acceptance_criteria>
|
</acceptance_criteria>
|
||||||
<resume-signal>Select `winter-final` to implement the locked/researched contract, or select an alternative to stop.</resume-signal>
|
<resume-signal>Select `golem15-prefix` (locked). `winter-final` is no longer the implementation path.</resume-signal>
|
||||||
</task>
|
</task>
|
||||||
|
|
||||||
<task type="tracer">
|
<task type="tracer">
|
||||||
<name>Task 3: Resolve one URL-prefixed request through the plugin, enabled Locale row, surf, and context</name>
|
<name>Task 3: Resolve one URL-prefixed request through the plugin, enabled Locale row, surf, and context</name>
|
||||||
<reversibility rating="one-way">The four table names and columns become the import target; changing them after release requires data migrations in every host.</reversibility>
|
<reversibility rating="one-way">The four table names and columns become the import target; changing them after release requires data migrations in every host.</reversibility>
|
||||||
<precondition>Tasks 1 and 2 completed, with schema option `winter-final`.</precondition>
|
<precondition>Tasks 1 and 2 completed, with schema option `golem15-prefix`.</precondition>
|
||||||
<files>../sm-translate-plugin/go.mod, ../sm-translate-plugin/plugin.go, ../sm-translate-plugin/README.md, ../sm-translate-plugin/config/config.yaml, ../sm-translate-plugin/models/registry.go, ../sm-translate-plugin/models/locale.go, ../sm-translate-plugin/updates/registry.go, ../sm-translate-plugin/updates/202610060001_create_winter_translate_locales.go, ../sm-translate-plugin/updates/202610060002_create_winter_translate_attributes.go, ../sm-translate-plugin/updates/202610060003_create_winter_translate_indexes.go, ../sm-translate-plugin/updates/202610060004_create_winter_translate_messages.go, ../sm-translate-plugin/updates/202610060005_seed_en_pl_locales.go, ../sm-translate-plugin/classes/translator.go, modules/surf/locale_resolver.go, modules/surf/router.go, modules/surf/README.md</files>
|
<files>../sm-translate-plugin/go.mod, ../sm-translate-plugin/plugin.go, ../sm-translate-plugin/README.md, ../sm-translate-plugin/config/config.yaml, ../sm-translate-plugin/models/registry.go, ../sm-translate-plugin/models/locale.go, ../sm-translate-plugin/updates/registry.go, ../sm-translate-plugin/updates/202610060001_create_golem15_translate_locales.go, ../sm-translate-plugin/updates/202610060002_create_golem15_translate_attributes.go, ../sm-translate-plugin/updates/202610060003_create_golem15_translate_indexes.go, ../sm-translate-plugin/updates/202610060004_create_golem15_translate_messages.go, ../sm-translate-plugin/updates/202610060005_seed_en_pl_locales.go, ../sm-translate-plugin/classes/translator.go, modules/surf/locale_resolver.go, modules/surf/router.go, modules/surf/README.md</files>
|
||||||
<read_first>../fonoteka.go/plugins/golem15/user/go.mod, ../fonoteka.go/plugins/golem15/user/plugin.go, ../fonoteka.go/plugins/golem15/user/models/registry.go, ../fonoteka.go/plugins/golem15/user/updates/registry.go, ../fonoteka.go/plugins/golem15/user/updates/00_base.go, modules/backpack/app.go, modules/surf/router.go, modules/surf/locale_from_principal.go, modules/towel/context.go, /media/nvme/dev/golem15/fonoteka/plugins/golem15/translate/classes/Translator.php, /media/nvme/dev/golem15/fonoteka/plugins/golem15/translate/classes/LocaleMiddleware.php, /media/nvme/dev/golem15/fonoteka/plugins/golem15/translate/classes/ApiLocaleMiddleware.php, /media/nvme/dev/golem15/fonoteka/plugins/golem15/translate/config/config.php, .planning/phases/14.2.1-translate-plugin/14.2.1-PATTERNS.md</read_first>
|
<read_first>../fonoteka.go/plugins/golem15/user/go.mod, ../fonoteka.go/plugins/golem15/user/plugin.go, ../fonoteka.go/plugins/golem15/user/models/registry.go, ../fonoteka.go/plugins/golem15/user/updates/registry.go, ../fonoteka.go/plugins/golem15/user/updates/00_base.go, modules/backpack/app.go, modules/surf/router.go, modules/surf/locale_from_principal.go, modules/towel/context.go, /media/nvme/dev/golem15/fonoteka/plugins/golem15/translate/classes/Translator.php, /media/nvme/dev/golem15/fonoteka/plugins/golem15/translate/classes/LocaleMiddleware.php, /media/nvme/dev/golem15/fonoteka/plugins/golem15/translate/classes/ApiLocaleMiddleware.php, /media/nvme/dev/golem15/fonoteka/plugins/golem15/translate/config/config.php, .planning/phases/14.2.1-translate-plugin/14.2.1-PATTERNS.md</read_first>
|
||||||
<action>Implement the production tracer and the complete Plan 01 scope.
|
<action>Implement the production tracer and the complete Plan 01 scope.
|
||||||
|
|
||||||
Create the Go 1.27 module using only existing GORM/gormigrate/framework dependencies. Register the compiled plugin in `init`, expose config/models/migrations, and publish a framework-owned `surf.LocaleResolver` in Boot. Keep `Requires()` empty so user-preference lookup is optional.
|
Create the Go 1.27 module using only existing GORM/gormigrate/framework dependencies. Register the compiled plugin in `init`, expose config/models/migrations, and publish a framework-owned `surf.LocaleResolver` in Boot. Keep `Requires()` empty so user-preference lookup is optional.
|
||||||
|
|
||||||
Implement exact squashed DDL for `winter_translate_locales`, `winter_translate_attributes`, `winter_translate_indexes`, and `winter_translate_messages`, including all final columns and PHP-indexed columns from RESEARCH. Messages is DDL only and remains empty. Use explicit gormigrate up/down; never AutoMigrate and never create rainlab or provisional-prefixed tables. Seed only en/pl idempotently with D-08 values.
|
Implement exact squashed DDL for `golem15_translate_locales`, `golem15_translate_attributes`, `golem15_translate_indexes`, and `golem15_translate_messages`, including all final columns and PHP-indexed columns from RESEARCH. Messages is DDL only and remains empty. Use explicit gormigrate up/down; never AutoMigrate and never create rainlab or `winter_translate_*` tables. Seed only en/pl idempotently with D-08 values.
|
||||||
|
|
||||||
Implement `Locale` with no timestamps, table name, code/name rules, and Fillable limited to code/name/is_enabled. Implement Translator/Resolver with the exact D-07 order: enabled URL first segment; valid principal preferred_locale; remembered `golem15.translate.locale`; Accept-Language only when browser detection is enabled and `locale_manually_set` is absent; enabled default. The manual cookie is a flag with value 1, never a locale. Validate every candidate against enabled rows. URL-prefix handling strips only a valid enabled prefix before routing and sets the manual flag using configured expiry. Provide the API resolver variant preferred → Accept-Language → default without persistence. All current-locale access takes context.
|
Implement `Locale` with no timestamps, table name, code/name rules, and Fillable limited to code/name/is_enabled. Implement Translator/Resolver with the exact D-07 order: enabled URL first segment; valid principal preferred_locale; remembered `golem15.translate.locale`; Accept-Language only when browser detection is enabled and `locale_manually_set` is absent; enabled default. The manual cookie is a flag with value 1, never a locale. Validate every candidate against enabled rows. URL-prefix handling strips only a valid enabled prefix before routing and sets the manual flag using configured expiry. Provide the API resolver variant preferred → Accept-Language → default without persistence. All current-locale access takes context.
|
||||||
|
|
||||||
@@ -176,7 +176,7 @@ Add the surf interface and optional lookup without importing the plugin. When no
|
|||||||
<fails_when>Non-zero exit, any package reports build failed, or either test command reports FAIL.</fails_when>
|
<fails_when>Non-zero exit, any package reports build failed, or either test command reports FAIL.</fails_when>
|
||||||
</verify>
|
</verify>
|
||||||
<acceptance_criteria>
|
<acceptance_criteria>
|
||||||
- All four migration files contain their exact `winter_translate_*` table name; no source file contains `golem15_translate_` or `rainlab_translate_`.
|
- All four migration files contain their exact `golem15_translate_*` table name; no source file contains `winter_translate_` or `rainlab_translate_`.
|
||||||
- Seed source contains en and pl with en default/enabled and pl enabled/non-default, and contains no Deutsch seed.
|
- Seed source contains en and pl with en default/enabled and pl enabled/non-default, and contains no Deutsch seed.
|
||||||
- Plugin module/ID/package match D-15 and plugin Boot publishes the framework resolver interface.
|
- Plugin module/ID/package match D-15 and plugin Boot publishes the framework resolver interface.
|
||||||
- Resolver order is URL → principal → remembered locale → cookie-gated Accept-Language → default.
|
- Resolver order is URL → principal → remembered locale → cookie-gated Accept-Language → default.
|
||||||
@@ -217,7 +217,7 @@ Run the Task 3 command. Confirm `git diff -- /media/nvme/dev/golem15/fonoteka/pl
|
|||||||
|
|
||||||
<success_criteria>
|
<success_criteria>
|
||||||
- The plugin and surf packages compile and pass short tests.
|
- The plugin and surf packages compile and pass short tests.
|
||||||
- Exact final tables and en/pl seed are implemented through gormigrate.
|
- Exact final `golem15_translate_*` tables and en/pl seed are implemented through gormigrate.
|
||||||
- Full resolver order is implemented without process-wide locale state.
|
- Full resolver order is implemented without process-wide locale state.
|
||||||
- No deferred Messages UI, CMS components, AI/theme commands, import/export, or PHP edits are introduced.
|
- No deferred Messages UI, CMS components, AI/theme commands, import/export, or PHP edits are introduced.
|
||||||
</success_criteria>
|
</success_criteria>
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ requirements: [D-05, D-08, D-09, D-10, D-11, D-12, D-17]
|
|||||||
must_haves:
|
must_haves:
|
||||||
truths:
|
truths:
|
||||||
- "D-09/D-12: a host model declares `Translatable() []string`, `TranslatableIndexes() []string`, and `MorphName() string`; callers use exported get/set and `WithLocale` APIs."
|
- "D-09/D-12: a host model declares `Translatable() []string`, `TranslatableIndexes() []string`, and `MorphName() string`; callers use exported get/set and `WithLocale` APIs."
|
||||||
- "D-10: default-locale values remain in host columns; each non-default locale is one JSON object row in `winter_translate_attributes`, and indexed values are mirrored to `winter_translate_indexes`."
|
- "D-10: default-locale values remain in host columns; each non-default locale is one JSON object row in `golem15_translate_attributes`, and indexed values are mirrored to `golem15_translate_indexes`."
|
||||||
- "D-11: a missing non-default value reads the host model's default-locale field."
|
- "D-11: a missing non-default value reads the host model's default-locale field."
|
||||||
- "D-05: Locales is ordinary cabana CRUD, permission-gated by exactly `golem15.translate.manage_locales`; no Messages controller, permission, or navigation exists."
|
- "D-05: Locales is ordinary cabana CRUD, permission-gated by exactly `golem15.translate.manage_locales`; no Messages controller, permission, or navigation exists."
|
||||||
- "Locale form writes only code/name/is_enabled; is_default and sort_order cannot be mass-assigned, while a permissioned make-default action preserves disabled/default lifecycle guards."
|
- "Locale form writes only code/name/is_enabled; is_default and sort_order cannot be mass-assigned, while a permissioned make-default action preserves disabled/default lifecycle guards."
|
||||||
@@ -47,11 +47,11 @@ must_haves:
|
|||||||
contains: "locale:"
|
contains: "locale:"
|
||||||
key_links:
|
key_links:
|
||||||
- from: "../sm-translate-plugin/classes/translatable.go"
|
- from: "../sm-translate-plugin/classes/translatable.go"
|
||||||
to: "winter_translate_attributes"
|
to: "golem15_translate_attributes"
|
||||||
via: "non-default SetTranslated upserts one locale/model row"
|
via: "non-default SetTranslated upserts one locale/model row"
|
||||||
pattern: "attribute_data"
|
pattern: "attribute_data"
|
||||||
- from: "../sm-translate-plugin/classes/translatable.go"
|
- from: "../sm-translate-plugin/classes/translatable.go"
|
||||||
to: "winter_translate_indexes"
|
to: "golem15_translate_indexes"
|
||||||
via: "indexed fields upsert locale/model/item/value"
|
via: "indexed fields upsert locale/model/item/value"
|
||||||
pattern: "TranslatableIndexes"
|
pattern: "TranslatableIndexes"
|
||||||
- from: "../sm-translate-plugin/controllers/locales.go"
|
- from: "../sm-translate-plugin/controllers/locales.go"
|
||||||
@@ -99,10 +99,10 @@ No REQUIREMENTS.md IDs are mapped to this phase. Probe predicates are intentiona
|
|||||||
<task type="tracer">
|
<task type="tracer">
|
||||||
<name>Task 1: Save one fixture title in en and pl, then read pl through the exported API</name>
|
<name>Task 1: Save one fixture title in en and pl, then read pl through the exported API</name>
|
||||||
<files>../sm-translate-plugin/classes/translatable.go, ../sm-translate-plugin/classes/translatable_smoke_test.go, ../sm-translate-plugin/models/attribute.go, ../sm-translate-plugin/models/index.go, ../sm-translate-plugin/models/registry.go</files>
|
<files>../sm-translate-plugin/classes/translatable.go, ../sm-translate-plugin/classes/translatable_smoke_test.go, ../sm-translate-plugin/models/attribute.go, ../sm-translate-plugin/models/index.go, ../sm-translate-plugin/models/registry.go</files>
|
||||||
<read_first>/media/nvme/dev/golem15/fonoteka/plugins/golem15/translate/behaviors/TranslatableModel.php, /media/nvme/dev/golem15/fonoteka/plugins/golem15/translate/classes/TranslatableBehavior.php, /media/nvme/dev/golem15/fonoteka/plugins/golem15/translate/tests/unit/behaviors/TranslatableModelTest.php, ../sm-translate-plugin/models/locale.go, ../sm-translate-plugin/updates/202610060002_create_winter_translate_attributes.go, ../sm-translate-plugin/updates/202610060003_create_winter_translate_indexes.go, ../fonoteka.go/plugins/golem15/user/models/user.go (MorphName), .planning/phases/14.2.1-translate-plugin/14.2.1-PATTERNS.md (Translatable assignment)</read_first>
|
<read_first>/media/nvme/dev/golem15/fonoteka/plugins/golem15/translate/behaviors/TranslatableModel.php, /media/nvme/dev/golem15/fonoteka/plugins/golem15/translate/classes/TranslatableBehavior.php, /media/nvme/dev/golem15/fonoteka/plugins/golem15/translate/tests/unit/behaviors/TranslatableModelTest.php, ../sm-translate-plugin/models/locale.go, ../sm-translate-plugin/updates/202610060002_create_golem15_translate_attributes.go, ../sm-translate-plugin/updates/202610060003_create_golem15_translate_indexes.go, ../fonoteka.go/plugins/golem15/user/models/user.go (MorphName), .planning/phases/14.2.1-translate-plugin/14.2.1-PATTERNS.md (Translatable assignment)</read_first>
|
||||||
<action>Implement the minimum stable D-09/D-12 API without Eloquent-style magic. Define a host-model contract with `Translatable() []string` and `MorphName() string`, plus an explicit indexed-field contract `TranslatableIndexes() []string`. Reject fields not declared by the model and locale codes not enabled in `winter_translate_locales`.
|
<action>Implement the minimum stable D-09/D-12 API without Eloquent-style magic. Define a host-model contract with `Translatable() []string` and `MorphName() string`, plus an explicit indexed-field contract `TranslatableIndexes() []string`. Reject fields not declared by the model and locale codes not enabled in `golem15_translate_locales`.
|
||||||
|
|
||||||
`SetTranslated` writes the default locale directly to the host model field/column and writes non-default values to one `(locale, model_id, model_type)` `winter_translate_attributes` row as a JSON object keyed by field. Use explicit model primary-key extraction and explicit exported-field/GORM-column mapping; do not use `reflect.Type.String()` as morph identity. Attribute rows have no public controller.
|
`SetTranslated` writes the default locale directly to the host model field/column and writes non-default values to one `(locale, model_id, model_type)` `golem15_translate_attributes` row as a JSON object keyed by field. Use explicit model primary-key extraction and explicit exported-field/GORM-column mapping; do not use `reflect.Type.String()` as morph identity. Attribute rows have no public controller.
|
||||||
|
|
||||||
`Translated` returns the host field for default locale; for another enabled locale it reads the JSON key and, when absent, returns the default host field per D-11. Keep an explicit locale argument even when context has a UI locale.
|
`Translated` returns the host field for default locale; for another enabled locale it reads the JSON key and, when absent, returns the default host field per D-11. Keep an explicit locale argument even when context has a UI locale.
|
||||||
|
|
||||||
@@ -113,7 +113,7 @@ Create a neutral fixture model only in the smoke test, migrate its host table ex
|
|||||||
</verify>
|
</verify>
|
||||||
<acceptance_criteria>
|
<acceptance_criteria>
|
||||||
- Exported interfaces and functions compile from an external test package.
|
- Exported interfaces and functions compile from an external test package.
|
||||||
- The default English value is in the fixture host row, not duplicated into `winter_translate_attributes`.
|
- The default English value is in the fixture host row, not duplicated into `golem15_translate_attributes`.
|
||||||
- The Polish value is present under `attribute_data.title` in exactly one pl/model row.
|
- The Polish value is present under `attribute_data.title` in exactly one pl/model row.
|
||||||
- Undeclared fields and unenabled locale codes return errors without database writes.
|
- Undeclared fields and unenabled locale codes return errors without database writes.
|
||||||
- Test fixture is test-only and no production fixture plugin is globally registered.
|
- Test fixture is test-only and no production fixture plugin is globally registered.
|
||||||
@@ -125,7 +125,7 @@ Create a neutral fixture model only in the smoke test, migrate its host table ex
|
|||||||
<name>Task 2: Add indexed locale lookup, WithLocale query scope, and default fallback</name>
|
<name>Task 2: Add indexed locale lookup, WithLocale query scope, and default fallback</name>
|
||||||
<files>../sm-translate-plugin/classes/translatable.go, ../sm-translate-plugin/classes/translatable_smoke_test.go, ../sm-translate-plugin/README.md</files>
|
<files>../sm-translate-plugin/classes/translatable.go, ../sm-translate-plugin/classes/translatable_smoke_test.go, ../sm-translate-plugin/README.md</files>
|
||||||
<read_first>../sm-translate-plugin/classes/translatable.go, /media/nvme/dev/golem15/fonoteka/plugins/golem15/translate/behaviors/TranslatableModel.php (scopeTransWhere and index writes), /media/nvme/dev/golem15/fonoteka/plugins/golem15/journal/models/Post.php, /media/nvme/dev/golem15/fonoteka/plugins/golem15/journal/models/Category.php, .planning/phases/14.2.1-translate-plugin/14.2.1-RESEARCH.md (Minimum exported Go API)</read_first>
|
<read_first>../sm-translate-plugin/classes/translatable.go, /media/nvme/dev/golem15/fonoteka/plugins/golem15/translate/behaviors/TranslatableModel.php (scopeTransWhere and index writes), /media/nvme/dev/golem15/fonoteka/plugins/golem15/journal/models/Post.php, /media/nvme/dev/golem15/fonoteka/plugins/golem15/journal/models/Category.php, .planning/phases/14.2.1-translate-plugin/14.2.1-RESEARCH.md (Minimum exported Go API)</read_first>
|
||||||
<action>Expand from the proven save/read path. `WithLocale(ctx, db, locale)` validates the explicit locale and carries it on the GORM statement context; it must not mutate global state. Add an indexed equality helper/scope that joins `winter_translate_indexes` by locale, morph name, model id, and item, while default-locale lookup uses the host column and non-default lookup falls back to that host column only when no translated index match exists, matching the frozen PHP behavior.
|
<action>Expand from the proven save/read path. `WithLocale(ctx, db, locale)` validates the explicit locale and carries it on the GORM statement context; it must not mutate global state. Add an indexed equality helper/scope that joins `golem15_translate_indexes` by locale, morph name, model id, and item, while default-locale lookup uses the host column and non-default lookup falls back to that host column only when no translated index match exists, matching the frozen PHP behavior.
|
||||||
|
|
||||||
When SetTranslated writes a declared indexed field, upsert the corresponding index row atomically with the attribute JSON update. Rewriting one locale/field must preserve other translated fields in the same JSON object. Empty translated values stay explicit empty values rather than silently borrowing fallback during admin editing; ordinary `Translated` still applies D-11 fallback.
|
When SetTranslated writes a declared indexed field, upsert the corresponding index row atomically with the attribute JSON update. Rewriting one locale/field must preserve other translated fields in the same JSON object. Empty translated values stay explicit empty values rather than silently borrowing fallback during admin editing; ordinary `Translated` still applies D-11 fallback.
|
||||||
|
|
||||||
@@ -136,7 +136,7 @@ Document only the exported identifiers that exist, MorphName's import-stability
|
|||||||
</verify>
|
</verify>
|
||||||
<acceptance_criteria>
|
<acceptance_criteria>
|
||||||
- `WithLocale` returns a GORM handle carrying an explicit validated locale on context and has no singleton mutation.
|
- `WithLocale` returns a GORM handle carrying an explicit validated locale on context and has no singleton mutation.
|
||||||
- Setting an indexed Polish slug writes one matching `winter_translate_indexes` row.
|
- Setting an indexed Polish slug writes one matching `golem15_translate_indexes` row.
|
||||||
- Polish indexed lookup finds the fixture; default-locale lookup uses the host slug.
|
- Polish indexed lookup finds the fixture; default-locale lookup uses the host slug.
|
||||||
- Missing Polish title returns English under normal reads per D-11.
|
- Missing Polish title returns English under normal reads per D-11.
|
||||||
- README names every exported API identifier accurately and remains application-neutral.
|
- README names every exported API identifier accurately and remains application-neutral.
|
||||||
@@ -166,7 +166,7 @@ Port the plugin.* and locale.* UI phrases to `lang/en/lang.yaml` and `lang/pl/la
|
|||||||
- Unknown/unprivileged admin gets 403; privileged admin gets the Locales schema/list.
|
- Unknown/unprivileged admin gets 403; privileged admin gets the Locales schema/list.
|
||||||
- A crafted body cannot persist is_default or sort_order.
|
- A crafted body cannot persist is_default or sort_order.
|
||||||
- The permissioned make-default action rejects disabled locales and atomically leaves exactly one enabled default locale.
|
- The permissioned make-default action rejects disabled locales and atomically leaves exactly one enabled default locale.
|
||||||
- English/Polish phrasebook files are independent from `winter_translate_attributes`.
|
- English/Polish phrasebook files are independent from `golem15_translate_attributes`.
|
||||||
</acceptance_criteria>
|
</acceptance_criteria>
|
||||||
<done>Authorized administrators can manage the lean Locale surface while default-state and phrasebook/model-translation boundaries remain enforced.</done>
|
<done>Authorized administrators can manage the lean Locale surface while default-state and phrasebook/model-translation boundaries remain enforced.</done>
|
||||||
</task>
|
</task>
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ autonomous: true
|
|||||||
requirements: [D-01, D-02, D-03, D-04, D-05, D-06, D-07, D-08, D-09, D-10, D-11, D-12, D-13, D-14, D-15, D-16, D-17]
|
requirements: [D-01, D-02, D-03, D-04, D-05, D-06, D-07, D-08, D-09, D-10, D-11, D-12, D-13, D-14, D-15, D-16, D-17]
|
||||||
must_haves:
|
must_haves:
|
||||||
truths:
|
truths:
|
||||||
- "A real-Postgres integration test migrates all four winter_translate tables, activates user+translate+fixture, saves en/pl through cabana ML fields, reads via WithLocale, and reaches Locales admin."
|
- "A real-Postgres integration test migrates all four golem15_translate tables, activates user+translate+fixture, saves en/pl through cabana ML fields, reads via WithLocale, and reaches Locales admin."
|
||||||
- "Migration up/down verifies every final column/index, empty Messages table, idempotent en/pl seed, absence of de, and complete rollback."
|
- "Migration up/down verifies every final column/index, empty Messages table, idempotent en/pl seed, absence of de, and complete rollback."
|
||||||
- "Translator tests prove URL → preferred_locale → remembered locale → cookie-gated Accept-Language → default, invalid-code rejection, API order, plugin-absent surf behavior, and concurrent request isolation."
|
- "Translator tests prove URL → preferred_locale → remembered locale → cookie-gated Accept-Language → default, invalid-code rejection, API order, plugin-absent surf behavior, and concurrent request isolation."
|
||||||
- "Translatable tests prove default-row storage, non-default JSON, default fallback, indexed lookup, undeclared-field rejection, invalid-locale rejection, and atomic preservation of sibling fields."
|
- "Translatable tests prove default-row storage, non-default JSON, default fallback, indexed lookup, undeclared-field rejection, invalid-locale rejection, and atomic preservation of sibling fields."
|
||||||
@@ -38,7 +38,7 @@ must_haves:
|
|||||||
contains: "TestTranslateEndToEnd"
|
contains: "TestTranslateEndToEnd"
|
||||||
- path: "../sm-translate-plugin/updates/migrations_test.go"
|
- path: "../sm-translate-plugin/updates/migrations_test.go"
|
||||||
provides: "real Postgres migration up/down and seed proof"
|
provides: "real Postgres migration up/down and seed proof"
|
||||||
contains: "winter_translate_messages"
|
contains: "golem15_translate_messages"
|
||||||
- path: "modules/surf/locale_resolver_test.go"
|
- path: "modules/surf/locale_resolver_test.go"
|
||||||
provides: "resolver-present/absent and request-isolation tests"
|
provides: "resolver-present/absent and request-isolation tests"
|
||||||
contains: "TestLocaleResolver"
|
contains: "TestLocaleResolver"
|
||||||
@@ -154,7 +154,7 @@ Expand host `TestBootUserTranslate` to prove both actual gitlink plugins activat
|
|||||||
<task type="auto">
|
<task type="auto">
|
||||||
<name>Task 2: Complete migration, Translator, Translatable, admin, ML, markdown, and SPA test matrices</name>
|
<name>Task 2: Complete migration, Translator, Translatable, admin, ML, markdown, and SPA test matrices</name>
|
||||||
<files>../sm-translate-plugin/updates/migrations_test.go, ../sm-translate-plugin/classes/translator_test.go, ../sm-translate-plugin/classes/translatable_test.go, ../sm-translate-plugin/locales_admin_test.go, modules/surf/locale_resolver_test.go, modules/cabana/ml_test.go, modules/cabana/markdown_test.go, modules/cabana/openapi_conformance_test.go, admin/tests/form/MLFields.test.ts, admin/tests/form/MarkdownField.test.ts</files>
|
<files>../sm-translate-plugin/updates/migrations_test.go, ../sm-translate-plugin/classes/translator_test.go, ../sm-translate-plugin/classes/translatable_test.go, ../sm-translate-plugin/locales_admin_test.go, modules/surf/locale_resolver_test.go, modules/cabana/ml_test.go, modules/cabana/markdown_test.go, modules/cabana/openapi_conformance_test.go, admin/tests/form/MLFields.test.ts, admin/tests/form/MarkdownField.test.ts</files>
|
||||||
<read_first>/media/nvme/dev/golem15/fonoteka/plugins/golem15/translate/tests/unit/behaviors/TranslatableModelTest.php, ../sm-translate-plugin/integration_test.go, ../sm-translate-plugin/updates/202610060001_create_winter_translate_locales.go, ../sm-translate-plugin/classes/translator.go, ../sm-translate-plugin/classes/translatable.go, modules/surf/locale_from_principal_test.go, modules/cabana/form_schema_test.go, modules/cabana/field_permission.go, admin/tests/form/DatepickerField.test.ts, admin/tests/form/registry.test.ts</read_first>
|
<read_first>/media/nvme/dev/golem15/fonoteka/plugins/golem15/translate/tests/unit/behaviors/TranslatableModelTest.php, ../sm-translate-plugin/integration_test.go, ../sm-translate-plugin/updates/202610060001_create_golem15_translate_locales.go, ../sm-translate-plugin/classes/translator.go, ../sm-translate-plugin/classes/translatable.go, modules/surf/locale_from_principal_test.go, modules/cabana/form_schema_test.go, modules/cabana/field_permission.go, admin/tests/form/DatepickerField.test.ts, admin/tests/form/registry.test.ts</read_first>
|
||||||
<action>Complete the decision and security matrix without adding unrelated PHP-suite surfaces.
|
<action>Complete the decision and security matrix without adding unrelated PHP-suite surfaces.
|
||||||
|
|
||||||
Migration tests: assert every final table, column type/default, PHP-indexed column, empty Messages row count, no rainlab/provisional tables, idempotent seed, en/pl exact flags/order/names, no de, and rollback removes all four tables in reverse-safe order. Re-migrate after rollback.
|
Migration tests: assert every final table, column type/default, PHP-indexed column, empty Messages row count, no rainlab/provisional tables, idempotent seed, en/pl exact flags/order/names, no de, and rollback removes all four tables in reverse-safe order. Re-migrate after rollback.
|
||||||
|
|||||||
@@ -33,19 +33,19 @@ Out of scope: the Messages catalogue and `manage_messages` admin, locale-picker
|
|||||||
|
|
||||||
### Model API
|
### Model API
|
||||||
- **D-09:** A Go model declares translatable attributes with a `Translatable() []string` (or equivalent tagged list) the way PHP uses `$translatable`. Journal copies the PHP Post/Category lists. — **Reversibility:** costly — every translatable model in shared plugins will call this.
|
- **D-09:** A Go model declares translatable attributes with a `Translatable() []string` (or equivalent tagged list) the way PHP uses `$translatable`. Journal copies the PHP Post/Category lists. — **Reversibility:** costly — every translatable model in shared plugins will call this.
|
||||||
- **D-10:** Storage uses the same tables and columns as this PHP pin (`golem15_translate_*` attributes/indexes/locales — researcher confirms exact names from the frozen updates). No JSON-column alternative. — **Reversibility:** one-way — Winter import and Journal cutover expect those tables.
|
- **D-10:** Go storage tables are `golem15_translate_locales`, `golem15_translate_attributes`, `golem15_translate_indexes`, and `golem15_translate_messages`, with the PHP pin's columns and indexes. No JSON-column alternative. PHP at SHA `725d547` uses `winter_translate_*`; do not copy those names into Go DDL. Winter import needs a later mapping. Locked at execute-phase Task 2 (2026-10-06) as `golem15-prefix`. — **Reversibility:** one-way — Journal and every host migrate against these names.
|
||||||
- **D-11:** A missing translation falls back to the default locale, as PHP does.
|
- **D-11:** A missing translation falls back to the default locale, as PHP does.
|
||||||
- **D-12:** The exported API other plugins call this phase is the minimum: `WithLocale` on queries, get/set an attribute in a locale, and current locale from Translator. Do not 1:1 every PHP `TranslatableModel` / `Translator` method name unless research shows Journal needs it.
|
- **D-12:** The exported API other plugins call this phase is the minimum: `WithLocale` on queries, get/set an attribute in a locale, and current locale from Translator. Do not 1:1 every PHP `TranslatableModel` / `Translator` method name unless research shows Journal needs it.
|
||||||
|
|
||||||
### Where it boots
|
### Where it boots
|
||||||
- **D-13:** The host is `sm-grzybyfunkcjonalne-app` (same as Phase 15 D-18). This phase mounts `sm-user-plugin` + `sm-translate-plugin`; Journal is added in Phase 15. — **Reversibility:** one-way — submodule layout lands in that app.
|
- **D-13:** The host is `sm-grzybyfunkcjonalne-app` (same as Phase 15 D-18). This phase mounts `sm-user-plugin` + `sm-translate-plugin`; Journal is added in Phase 15. — **Reversibility:** one-way — submodule layout lands in that app.
|
||||||
- **D-14:** Local app checkout: `/media/nvme/dev/golem15/summercms.io/summercms/sm-grzybyfunkcjonalne-app/` (sibling of `summercms.go`).
|
- **D-14:** Local app checkout: `/media/nvme/dev/golem15/summercms.io/summercms/sm-grzybyfunkcjonalne-app/` (sibling of `summercms.go`).
|
||||||
- **D-15:** The user creates the public Gitea remote `git@git.golem15.com:golem15/sm-translate-plugin.git` as a manual plan step (it does not exist yet). Module path `git.golem15.com/golem15/sm-translate-plugin`, package `translate`, plugin ID `golem15.translate`.
|
- **D-15:** The public Gitea remote is `git@git.golem15.com:golem15/sm-translate-plugin.git` (created 2026-10-06). Module path `git.golem15.com/golem15/sm-translate-plugin`, package `translate`, plugin ID `golem15.translate`.
|
||||||
- **D-16:** Local plugin checkout: `/media/nvme/dev/golem15/summercms.io/summercms/sm-translate-plugin/` (sibling of `summercms.go`). The host mounts it as a submodule at `plugins/golem15/translate` with a `go.work` replace.
|
- **D-16:** Local plugin checkout: `/media/nvme/dev/golem15/summercms.io/summercms/sm-translate-plugin/` (sibling of `summercms.go`). The host mounts it as a submodule at `plugins/golem15/translate` with a `go.work` replace.
|
||||||
- **D-17:** Phase proof: the app boots with user+translate; Locales admin works; a fixture model can save and read `en`+`pl` through ML fields and `WithLocale`.
|
- **D-17:** Phase proof: the app boots with user+translate; Locales admin works; a fixture model can save and read `en`+`pl` through ML fields and `WithLocale`.
|
||||||
|
|
||||||
### Claude's Discretion
|
### Claude's Discretion
|
||||||
- Exact `golem15_translate_*` table/column names and migration IDs, taken from the frozen PHP updates (D-10), not invented.
|
- Exact `golem15_translate_*` Go table names (D-10 execute lock); column/index shapes still come from the frozen PHP updates, not invented.
|
||||||
- ML field YAML type names and SPA locale-switcher chrome, provided they follow cabana fail-loud rules and update the module README, `docs/`, admin OpenAPI, generated TS types and committed `dist/` in the same change.
|
- ML field YAML type names and SPA locale-switcher chrome, provided they follow cabana fail-loud rules and update the module README, `docs/`, admin OpenAPI, generated TS types and committed `dist/` in the same change.
|
||||||
- How `mlmarkdown` shares implementation with Phase 15's markdown field (land the shared primitive here if Journal is otherwise blocked).
|
- How `mlmarkdown` shares implementation with Phase 15's markdown field (land the shared primitive here if Journal is otherwise blocked).
|
||||||
- Plan count and split, subject to the plan-count checkpoint and "unit tests are the last plan".
|
- Plan count and split, subject to the plan-count checkpoint and "unit tests are the last plan".
|
||||||
@@ -85,7 +85,7 @@ Out of scope: the Messages catalogue and `manage_messages` admin, locale-picker
|
|||||||
- `docs/backend/forms.md`, `docs/backend/admin-controllers.md`
|
- `docs/backend/forms.md`, `docs/backend/admin-controllers.md`
|
||||||
|
|
||||||
### Remotes
|
### Remotes
|
||||||
- `git@git.golem15.com:golem15/sm-translate-plugin.git` — **does not exist yet**; user creates it, public
|
- `git@git.golem15.com:golem15/sm-translate-plugin.git` — public, created; local sibling checkout on `main`
|
||||||
- `git@git.golem15.com:golem15/sm-grzybyfunkcjonalne-app.git` — empty proof host, already created
|
- `git@git.golem15.com:golem15/sm-grzybyfunkcjonalne-app.git` — empty proof host, already created
|
||||||
- `git@git.golem15.com:golem15/sm-journal-plugin.git` — public, empty; mounted in Phase 15
|
- `git@git.golem15.com:golem15/sm-journal-plugin.git` — public, empty; mounted in Phase 15
|
||||||
|
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ Path roots:
|
|||||||
|
|
||||||
All analog paths below are git-tracked (`git ls-files` in `summercms.go`, inside the user submodule, inside `sm-bm-app`, and inside the PHP plugin). No gitignored mirror is named. `modules/boardwalk/dist`, `admin/openapi/admin.json` and `admin/src/api/schema.d.ts` are generated outputs: regenerate them, never hand-edit.
|
All analog paths below are git-tracked (`git ls-files` in `summercms.go`, inside the user submodule, inside `sm-bm-app`, and inside the PHP plugin). No gitignored mirror is named. `modules/boardwalk/dist`, `admin/openapi/admin.json` and `admin/src/api/schema.d.ts` are generated outputs: regenerate them, never hand-edit.
|
||||||
|
|
||||||
**Table names (locked by RESEARCH against the frozen PHP models):** `winter_translate_locales`, `winter_translate_attributes`, `winter_translate_indexes`, `winter_translate_messages`. CONTEXT D-10's `golem15_translate_*` placeholder is wrong. Do not invent `golem15_translate_*`.
|
**Table names (locked D-10 execute-phase 2026-10-06):** Go tables are `golem15_translate_locales`, `golem15_translate_attributes`, `golem15_translate_indexes`, `golem15_translate_messages`. PHP at SHA 725d547 still uses `winter_translate_*`; copy column/index shape from PHP, not the Winter table names. Do not emit `winter_translate_*` or `rainlab_translate_*` in Go DDL.
|
||||||
|
|
||||||
Suggested plan split from RESEARCH (present at the plan-count checkpoint; unit tests last): **14.2.1-01** plugin repo + squashed schema + Locale + Translator + surf Resolver seam; **14.2.1-02** Translatable API + Locales admin + fixture; **14.2.1-03** cabana `markdown`/`mltext`/`mlmarkdown` + SPA + proof host boot; **14.2.1-04** unit/integration tests last.
|
Suggested plan split from RESEARCH (present at the plan-count checkpoint; unit tests last): **14.2.1-01** plugin repo + squashed schema + Locale + Translator + surf Resolver seam; **14.2.1-02** Translatable API + Locales admin + fixture; **14.2.1-03** cabana `markdown`/`mltext`/`mlmarkdown` + SPA + proof host boot; **14.2.1-04** unit/integration tests last.
|
||||||
|
|
||||||
@@ -37,10 +37,10 @@ Suggested plan split from RESEARCH (present at the plan-count checkpoint; unit t
|
|||||||
| `TR/models/locale.go` | model | CRUD | `USR/models/user_group.go` (Fillable/Rules/TableName) + `PHP/models/Locale.php` (guards) | exact |
|
| `TR/models/locale.go` | model | CRUD | `USR/models/user_group.go` (Fillable/Rules/TableName) + `PHP/models/Locale.php` (guards) | exact |
|
||||||
| `TR/models/attribute.go` | model | CRUD | `USR/models/api_token.go` shape + `PHP/models/Attribute.php` fillable | exact |
|
| `TR/models/attribute.go` | model | CRUD | `USR/models/api_token.go` shape + `PHP/models/Attribute.php` fillable | exact |
|
||||||
| `TR/updates/registry.go` | utility | — | `USR/updates/registry.go` | exact |
|
| `TR/updates/registry.go` | utility | — | `USR/updates/registry.go` | exact |
|
||||||
| `TR/updates/202610060001_create_winter_translate_locales.go` | migration | CRUD | `USR/updates/00_base.go` + `USR/updates/202610020001_create_user_groups.go` (CREATE + seed style) | exact |
|
| `TR/updates/202610060001_create_golem15_translate_locales.go` | migration | CRUD | `USR/updates/00_base.go` + `USR/updates/202610020001_create_user_groups.go` (CREATE + seed style) | exact |
|
||||||
| `TR/updates/202610060002_create_winter_translate_attributes.go` | migration | CRUD | `USR/updates/00_base.go` | exact |
|
| `TR/updates/202610060002_create_golem15_translate_attributes.go` | migration | CRUD | `USR/updates/00_base.go` | exact |
|
||||||
| `TR/updates/202610060003_create_winter_translate_indexes.go` | migration | CRUD | `USR/updates/00_base.go` | exact |
|
| `TR/updates/202610060003_create_golem15_translate_indexes.go` | migration | CRUD | `USR/updates/00_base.go` | exact |
|
||||||
| `TR/updates/202610060004_create_winter_translate_messages.go` | migration | CRUD | `USR/updates/00_base.go` (DDL only; no Message admin) | exact |
|
| `TR/updates/202610060004_create_golem15_translate_messages.go` | migration | CRUD | `USR/updates/00_base.go` (DDL only; no Message admin) | exact |
|
||||||
| `TR/updates/202610060005_seed_en_pl_locales.go` | migration | CRUD | `USR/updates/202610020001_create_user_groups.go` INSERT + `PHP/updates/v1.3.1/seed_all_tables.php` and `v2.4.0/seed_additional_locales.php` | exact |
|
| `TR/updates/202610060005_seed_en_pl_locales.go` | migration | CRUD | `USR/updates/202610020001_create_user_groups.go` INSERT + `PHP/updates/v1.3.1/seed_all_tables.php` and `v2.4.0/seed_additional_locales.php` | exact |
|
||||||
| `TR/classes/translator.go` | service | request-response | `PHP/classes/Translator.php` + `LocaleMiddleware.php` + `ApiLocaleMiddleware.php` (contract) and `USR/plugin.go` Boot `app.Publish` | role-match |
|
| `TR/classes/translator.go` | service | request-response | `PHP/classes/Translator.php` + `LocaleMiddleware.php` + `ApiLocaleMiddleware.php` (contract) and `USR/plugin.go` Boot `app.Publish` | role-match |
|
||||||
| `TR/classes/translatable.go` | service | CRUD | `PHP/behaviors/TranslatableModel.php` + `classes/TranslatableBehavior.php` (no Go translatable analog) | partial |
|
| `TR/classes/translatable.go` | service | CRUD | `PHP/behaviors/TranslatableModel.php` + `classes/TranslatableBehavior.php` (no Go translatable analog) | partial |
|
||||||
@@ -221,7 +221,7 @@ public $timestamps = false;
|
|||||||
// makeDefault: cannot make a disabled locale default
|
// makeDefault: cannot make a disabled locale default
|
||||||
```
|
```
|
||||||
|
|
||||||
Copy: `TableName() "winter_translate_locales"`, no `CreatedAt`/`UpdatedAt`, Fillable **only** `code`, `name`, `is_enabled`. `is_default` and `sort_order` are **not** fillable (PHP). Rules: `code` required, `name` required. Port delete/unset/disabled-default as `FormBeforeDelete` / `FormBeforeUpdate` returning `&cabana.ValidationError{Details: ...}` (422) — analog `USR/controllers/usergroups_admin_controller.go` 162-175.
|
Copy: `TableName() "golem15_translate_locales"`, no `CreatedAt`/`UpdatedAt`, Fillable **only** `code`, `name`, `is_enabled`. `is_default` and `sort_order` are **not** fillable (PHP). Rules: `code` required, `name` required. Port delete/unset/disabled-default as `FormBeforeDelete` / `FormBeforeUpdate` returning `&cabana.ValidationError{Details: ...}` (422) — analog `USR/controllers/usergroups_admin_controller.go` 162-175.
|
||||||
|
|
||||||
`isValid` = code in enabled list (`PHP/models/Locale.php` 228-232). Default locale: `is_default` true row; seed `en` as default.
|
`isValid` = code in enabled list (`PHP/models/Locale.php` 228-232). Default locale: `is_default` true row; seed `en` as default.
|
||||||
|
|
||||||
@@ -231,7 +231,7 @@ Copy: `TableName() "winter_translate_locales"`, no `CreatedAt`/`UpdatedAt`, Fill
|
|||||||
|
|
||||||
**Contract:** `PHP/models/Attribute.php` lines 15-34 — table `winter_translate_attributes`, fillable `locale`, `model_type`, `model_id`, `attribute_data`, `$guarded = ['*']`.
|
**Contract:** `PHP/models/Attribute.php` lines 15-34 — table `winter_translate_attributes`, fillable `locale`, `model_type`, `model_id`, `attribute_data`, `$guarded = ['*']`.
|
||||||
|
|
||||||
**Go analog:** `USR/models/user_group.go` TableName + Register. No public Attribute controller. Writes only through Translatable helpers (RESEARCH T-SEC). Optional: omit a Message model entirely and only DDL `winter_translate_messages` (RESEARCH §9). If Attribute exists, Fillable matches PHP; never expose an admin controller.
|
**Go analog:** `USR/models/user_group.go` TableName + Register. No public Attribute controller. Writes only through Translatable helpers (RESEARCH T-SEC). Optional: omit a Message model entirely and only DDL `golem15_translate_messages` (RESEARCH §9). If Attribute exists, Fillable matches PHP; never expose an admin controller. Go `TableName()` is `golem15_translate_attributes` even though PHP's `$table` is `winter_translate_attributes`.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -269,7 +269,7 @@ func init() { Register(migrations...) }
|
|||||||
| `winter_translate_indexes` | `id`, `locale` indexed, `model_id` indexed nullable, `model_type` indexed nullable, `item` indexed nullable, `value TEXT` nullable |
|
| `winter_translate_indexes` | `id`, `locale` indexed, `model_id` indexed nullable, `model_type` indexed nullable, `item` indexed nullable, `value TEXT` nullable |
|
||||||
| `winter_translate_messages` | `id`, `code` indexed nullable, `message_data TEXT` nullable, `found BOOLEAN DEFAULT TRUE`, `code_pre_2_1_0 TEXT` indexed nullable — create empty; no Messages admin |
|
| `winter_translate_messages` | `id`, `code` indexed nullable, `message_data TEXT` nullable, `found BOOLEAN DEFAULT TRUE`, `code_pre_2_1_0 TEXT` indexed nullable — create empty; no Messages admin |
|
||||||
|
|
||||||
Suggested IDs (planner may adjust date prefix, not table names): `202610060001_create_winter_translate_locales` … `202610060005_seed_en_pl_locales`.
|
Suggested IDs (planner may adjust date prefix, not table names): `202610060001_create_golem15_translate_locales` … `202610060005_seed_en_pl_locales`.
|
||||||
|
|
||||||
**Seed contract:** `PHP/updates/v1.3.1/seed_all_tables.php` 16-22 (`en` / English / default / enabled) and `PHP/updates/v2.4.0/seed_additional_locales.php` 13-20 (`pl` / Polski / not default / enabled / `sort_order` 2). Set `en.sort_order = 1`. **Do not seed `de`.** Idempotent: insert by `code` if missing (`$exists` check lines 33-36).
|
**Seed contract:** `PHP/updates/v1.3.1/seed_all_tables.php` 16-22 (`en` / English / default / enabled) and `PHP/updates/v2.4.0/seed_additional_locales.php` 13-20 (`pl` / Polski / not default / enabled / `sort_order` 2). Set `en.sort_order = 1`. **Do not seed `de`.** Idempotent: insert by `code` if missing (`$exists` check lines 33-36).
|
||||||
|
|
||||||
|
|||||||
@@ -71,9 +71,9 @@
|
|||||||
|
|
||||||
Phase 14.2.1 ports the lean core of `Golem15.Translate` at SHA `725d547ec839f02b5fdc0f0a6faaed601a414d50` so Journal (Phase 15) can keep translatable fields. The frozen tree is present at `/media/nvme/dev/golem15/fonoteka/plugins/golem15/translate` and matches the pin. Do not clone a second copy.
|
Phase 14.2.1 ports the lean core of `Golem15.Translate` at SHA `725d547ec839f02b5fdc0f0a6faaed601a414d50` so Journal (Phase 15) can keep translatable fields. The frozen tree is present at `/media/nvme/dev/golem15/fonoteka/plugins/golem15/translate` and matches the pin. Do not clone a second copy.
|
||||||
|
|
||||||
**Primary recommendation:** Create `sm-translate-plugin` on the user-plugin mount pattern; squash PHP's rainlab→winter rename history into four final Postgres tables named `winter_translate_*` (not `golem15_translate_*`); export `Translatable() []string`, `WithLocale`, get/set-in-locale, and Translator current locale; land cabana `markdown` plus `mltext`/`mlmarkdown` in this phase so Phase 15 is not blocked; replace surf's Accept-Language-only house locale middleware with a backpack-published Translator when the plugin is mounted.
|
**Primary recommendation:** Create `sm-translate-plugin` on the user-plugin mount pattern; squash PHP's rainlab→winter rename history into four final Postgres tables named `golem15_translate_*` (not PHP's `winter_translate_*`); export `Translatable() []string`, `WithLocale`, get/set-in-locale, and Translator current locale; land cabana `markdown` plus `mltext`/`mlmarkdown` in this phase so Phase 15 is not blocked; replace surf's Accept-Language-only house locale middleware with a backpack-published Translator when the plugin is mounted.
|
||||||
|
|
||||||
PHP table names in this pin are `winter_translate_locales`, `winter_translate_attributes`, `winter_translate_indexes`, and `winter_translate_messages`. CONTEXT D-10's `golem15_translate_*` placeholder is wrong against the frozen source. Use the verified `winter_translate_*` names so a Winter import and Journal cutover see the same tables.
|
PHP table names in this pin are `winter_translate_locales`, `winter_translate_attributes`, `winter_translate_indexes`, and `winter_translate_messages`. **Execution override (2026-10-06):** D-10 is locked to Go names `golem15_translate_*` with the PHP column/index shapes. Do not emit `winter_translate_*` in Go DDL. A Winter import will need a mapping later.
|
||||||
|
|
||||||
## Architectural Responsibility Map
|
## Architectural Responsibility Map
|
||||||
|
|
||||||
@@ -115,8 +115,8 @@ Do not use these. CONTEXT locked the storage, locale order, and YAML types.
|
|||||||
|
|
||||||
| Instead of | Could Use | Why rejected |
|
| Instead of | Could Use | Why rejected |
|
||||||
|------------|-----------|--------------|
|
|------------|-----------|--------------|
|
||||||
| `winter_translate_*` tables | JSON columns on host models | D-10 forbids it |
|
| `golem15_translate_*` tables | JSON columns on host models | D-10 forbids it |
|
||||||
| `winter_translate_*` | Invented `golem15_translate_*` | Frozen models use `winter_translate_*` |
|
| `golem15_translate_*` | PHP's `winter_translate_*` copied into Go | Execute lock 2026-10-06; Winter import is a later mapping |
|
||||||
| URL/session/cookie/default | Accept-Language only | D-07 forbids reducing to it |
|
| URL/session/cookie/default | Accept-Language only | D-07 forbids reducing to it |
|
||||||
| Cabana `mltext`/`mlmarkdown` | Plugin `type: widget` | Field types belong in cabana (12.1 pattern) |
|
| Cabana `mltext`/`mlmarkdown` | Plugin `type: widget` | Field types belong in cabana (12.1 pattern) |
|
||||||
|
|
||||||
@@ -194,10 +194,10 @@ From `updates/version.yaml` [VERIFIED: `updates/version.yaml:1-155`]:
|
|||||||
|
|
||||||
Go migration IDs: follow the user-plugin pattern `"202609170001_create_users"` [VERIFIED: `../fonoteka.go/plugins/golem15/user/updates/00_base.go:13`]. Suggested squash IDs (planner may adjust date prefix, not the table names):
|
Go migration IDs: follow the user-plugin pattern `"202609170001_create_users"` [VERIFIED: `../fonoteka.go/plugins/golem15/user/updates/00_base.go:13`]. Suggested squash IDs (planner may adjust date prefix, not the table names):
|
||||||
|
|
||||||
- `202610060001_create_winter_translate_locales`
|
- `202610060001_create_golem15_translate_locales`
|
||||||
- `202610060002_create_winter_translate_attributes`
|
- `202610060002_create_golem15_translate_attributes`
|
||||||
- `202610060003_create_winter_translate_indexes`
|
- `202610060003_create_golem15_translate_indexes`
|
||||||
- `202610060004_create_winter_translate_messages`
|
- `202610060004_create_golem15_translate_messages`
|
||||||
- `202610060005_seed_en_pl_locales`
|
- `202610060005_seed_en_pl_locales`
|
||||||
|
|
||||||
Postgres types: `SERIAL` PK, `TEXT` for strings, `BOOLEAN`, `INTEGER` for `sort_order`, `TEXT` for `attribute_data`/`message_data`/`value` (PHP mediumText). Add btree indexes on the PHP-indexed columns (`code`, `name`, `locale`, `model_id`, `model_type`, `item`).
|
Postgres types: `SERIAL` PK, `TEXT` for strings, `BOOLEAN`, `INTEGER` for `sort_order`, `TEXT` for `attribute_data`/`message_data`/`value` (PHP mediumText). Add btree indexes on the PHP-indexed columns (`code`, `name`, `locale`, `model_id`, `model_type`, `item`).
|
||||||
@@ -505,7 +505,7 @@ Four plans. Present this count at the plan-count checkpoint. Unit tests last.
|
|||||||
|
|
||||||
| Plan | One-line scope |
|
| Plan | One-line scope |
|
||||||
|------|----------------|
|
|------|----------------|
|
||||||
| **14.2.1-01** | Plugin repo + squashed `winter_translate_*` schema (all four tables) + Locale model + en/pl seed + Translator + surf Resolver seam. Manual: Gitea remote + local checkouts. |
|
| **14.2.1-01** | Plugin repo + squashed `golem15_translate_*` schema (all four tables) + Locale model + en/pl seed + Translator + surf Resolver seam. Manual: Gitea remote + local checkouts. |
|
||||||
| **14.2.1-02** | Translatable API (`Translatable`, `WithLocale`, get/set, fallback, indexes) + Locales admin (`manage_locales`, YAML, phrasebook) + fixture save/read. |
|
| **14.2.1-02** | Translatable API (`Translatable`, `WithLocale`, get/set, fallback, indexes) + Locales admin (`manage_locales`, YAML, phrasebook) + fixture save/read. |
|
||||||
| **14.2.1-03** | Cabana `markdown` + `mltext` + `mlmarkdown` (SPA switcher, nested save, docs/OpenAPI/TS/`dist/`) + proof host `sm-grzybyfunkcjonalne-app` boots user+translate. |
|
| **14.2.1-03** | Cabana `markdown` + `mltext` + `mlmarkdown` (SPA switcher, nested save, docs/OpenAPI/TS/`dist/`) + proof host `sm-grzybyfunkcjonalne-app` boots user+translate. |
|
||||||
| **14.2.1-04** | Unit/integration tests last: Translator order, Translatable fallback, admin authz, ML save, migrations up/down. |
|
| **14.2.1-04** | Unit/integration tests last: Translator order, Translatable fallback, admin authz, ML save, migrations up/down. |
|
||||||
@@ -526,13 +526,13 @@ Public/Admin HTTP
|
|||||||
|
|
||||||
Admin Locales CRUD
|
Admin Locales CRUD
|
||||||
→ cabana.CRUDService (permission golem15.translate.manage_locales)
|
→ cabana.CRUDService (permission golem15.translate.manage_locales)
|
||||||
→ winter_translate_locales
|
→ golem15_translate_locales
|
||||||
|
|
||||||
Admin Journal-like form (fixture / Phase 15)
|
Admin Journal-like form (fixture / Phase 15)
|
||||||
→ mltext / mlmarkdown controls
|
→ mltext / mlmarkdown controls
|
||||||
→ default locale → host table columns
|
→ default locale → host table columns
|
||||||
→ other locales → winter_translate_attributes.attribute_data JSON
|
→ other locales → golem15_translate_attributes.attribute_data JSON
|
||||||
→ indexed fields → winter_translate_indexes
|
→ indexed fields → golem15_translate_indexes
|
||||||
|
|
||||||
Journal query (Phase 15)
|
Journal query (Phase 15)
|
||||||
→ Translator.Locale(ctx) or WithLocale(..., "pl")
|
→ Translator.Locale(ctx) or WithLocale(..., "pl")
|
||||||
@@ -578,8 +578,8 @@ Framework touches: `modules/surf/router.go` locale seam; `modules/cabana/form_sc
|
|||||||
|
|
||||||
### Anti-Patterns to Avoid
|
### Anti-Patterns to Avoid
|
||||||
|
|
||||||
- **JSON-column "simpler" storage:** violates D-10 and Winter import.
|
- **JSON-column "simpler" storage:** violates D-10 and PHP attribute-row semantics.
|
||||||
- **Renaming tables to `golem15_translate_*`:** frozen PHP uses `winter_translate_*`.
|
- **Copying PHP `winter_translate_*` names into Go DDL:** D-10 is locked to `golem15_translate_*`; Winter import needs a later mapping.
|
||||||
- **Translator singleton holding the request locale:** violates KERN-07.
|
- **Translator singleton holding the request locale:** violates KERN-07.
|
||||||
- **Accept-Language as the only resolver:** violates D-07; also stop stuffing the raw header into context when Resolver runs.
|
- **Accept-Language as the only resolver:** violates D-07; also stop stuffing the raw header into context when Resolver runs.
|
||||||
- **Plugin-owned `type: widget` ML controls:** field types belong in cabana.
|
- **Plugin-owned `type: widget` ML controls:** field types belong in cabana.
|
||||||
@@ -603,10 +603,10 @@ Framework touches: `modules/surf/router.go` locale seam; `modules/cabana/form_sc
|
|||||||
## Common Pitfalls
|
## Common Pitfalls
|
||||||
|
|
||||||
### Pitfall 1: Wrong table prefix
|
### Pitfall 1: Wrong table prefix
|
||||||
**What goes wrong:** Creating `golem15_translate_locales` because CONTEXT guessed that name.
|
**What goes wrong:** Creating `winter_translate_locales` in Go because PHP models use that name.
|
||||||
**Why:** D-10 asked the researcher to confirm; models say `winter_translate_*`.
|
**Why:** Execute-phase D-10 is locked to `golem15_translate_*`; PHP `winter_translate_*` stays a mapping concern.
|
||||||
**How to avoid:** Use the verified names in every migration and query.
|
**How to avoid:** Use `golem15_translate_*` in every Go migration and query.
|
||||||
**Warning signs:** `Schema::hasTable('winter_translate_locales')` in Translator.
|
**Warning signs:** Go source containing `winter_translate_` or `rainlab_translate_`.
|
||||||
|
|
||||||
### Pitfall 2: Nested ML save dropped
|
### Pitfall 2: Nested ML save dropped
|
||||||
**What goes wrong:** SPA posts `{title: {en, pl}}`; cabana drops maps; only default locale saves.
|
**What goes wrong:** SPA posts `{title: {en, pl}}`; cabana drops maps; only default locale saves.
|
||||||
@@ -680,7 +680,7 @@ DATA_r3t6y0ab_END
|
|||||||
|
|
||||||
| Old Approach (PHP) | Current Approach (Go) | When | Impact |
|
| Old Approach (PHP) | Current Approach (Go) | When | Impact |
|
||||||
|--------------------|----------------------|------|--------|
|
|--------------------|----------------------|------|--------|
|
||||||
| RainLab then Winter table names | Squash to `winter_translate_*` | 2.0.0 rename | Do not emit rainlab tables |
|
| RainLab then Winter table names | Squash to `golem15_translate_*` | 2.0.0 rename in PHP; Go never emits rainlab or winter table names | Winter import needs a later mapping |
|
||||||
| Eloquent `$implement` behavior | Go interface + GORM callbacks | this port | Explicit `Translatable()` |
|
| Eloquent `$implement` behavior | Go interface + GORM callbacks | this port | Explicit `Translatable()` |
|
||||||
| Winter formwidget swap at runtime | Explicit YAML `mltext`/`mlmarkdown` | compiled admin | Journal YAML names ML types |
|
| Winter formwidget swap at runtime | Explicit YAML `mltext`/`mlmarkdown` | compiled admin | Journal YAML names ML types |
|
||||||
| Translator singleton | `towel.WithLocale` + backpack service | KERN-07 | No request globals |
|
| Translator singleton | `towel.WithLocale` + backpack service | KERN-07 | No request globals |
|
||||||
@@ -753,7 +753,7 @@ No REQUIREMENTS.md IDs were mapped (TBD). Map locked decisions:
|
|||||||
| D-07 | URL prefix wins; invalid code ignored; session/cookie flag; not header-only | unit | `go test ./classes -run TestTranslatorResolve -count=1` | ❌ Wave 0 |
|
| D-07 | URL prefix wins; invalid code ignored; session/cookie flag; not header-only | unit | `go test ./classes -run TestTranslatorResolve -count=1` | ❌ Wave 0 |
|
||||||
| D-08 | Seed inserts `en` (default, enabled) and `pl` (enabled, not default); not `de` | integration | `go test ./updates -run TestSeedEnPl -count=1` | ❌ Wave 0 |
|
| D-08 | Seed inserts `en` (default, enabled) and `pl` (enabled, not default); not `de` | integration | `go test ./updates -run TestSeedEnPl -count=1` | ❌ Wave 0 |
|
||||||
| D-09/D-12 | `Translatable()` + get/set + `WithLocale` | unit | `go test ./classes -run TestTranslatableGetSet -count=1` | ❌ Wave 0 |
|
| D-09/D-12 | `Translatable()` + get/set + `WithLocale` | unit | `go test ./classes -run TestTranslatableGetSet -count=1` | ❌ Wave 0 |
|
||||||
| D-10 | Tables `winter_translate_locales\|attributes\|indexes\|messages` exist after migrate | integration | `go test ./updates -run TestTranslateTables -count=1` | ❌ Wave 0 |
|
| D-10 | Tables `golem15_translate_locales\|attributes\|indexes\|messages` exist after migrate | integration | `go test ./updates -run TestTranslateTables -count=1` | ❌ Wave 0 |
|
||||||
| D-11 | Missing `pl` falls back to default locale column | unit | `go test ./classes -run TestFallbackDefaultLocale -count=1` | ❌ Wave 0 |
|
| D-11 | Missing `pl` falls back to default locale column | unit | `go test ./classes -run TestFallbackDefaultLocale -count=1` | ❌ Wave 0 |
|
||||||
| D-17 | Host/plugin Activate with user+translate | smoke | `go test ./... -run TestBootUserTranslate -count=1` | ❌ Wave 0 |
|
| D-17 | Host/plugin Activate with user+translate | smoke | `go test ./... -run TestBootUserTranslate -count=1` | ❌ Wave 0 |
|
||||||
| T-SEC-01 | Unlisted locale never stored | unit | `go test ./classes -run TestInvalidLocaleRejected -count=1` | ❌ Wave 0 |
|
| T-SEC-01 | Unlisted locale never stored | unit | `go test ./classes -run TestInvalidLocaleRejected -count=1` | ❌ Wave 0 |
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ created: "2026-10-06"
|
|||||||
| 14.2.1-W0 | 04 | 0 | D-07 | T-14.2.1-02 | URL prefix wins; invalid code ignored; session/cookie flag; not header-only | unit | `go test ./classes -run TestTranslatorResolve -count=1` | ❌ W0 | ⬜ pending |
|
| 14.2.1-W0 | 04 | 0 | D-07 | T-14.2.1-02 | URL prefix wins; invalid code ignored; session/cookie flag; not header-only | unit | `go test ./classes -run TestTranslatorResolve -count=1` | ❌ W0 | ⬜ pending |
|
||||||
| 14.2.1-W0 | 04 | 0 | D-08 | — | Seed inserts `en` (default, enabled) and `pl` (enabled, not default); not `de` | integration | `go test ./updates -run TestSeedEnPl -count=1` | ❌ W0 | ⬜ pending |
|
| 14.2.1-W0 | 04 | 0 | D-08 | — | Seed inserts `en` (default, enabled) and `pl` (enabled, not default); not `de` | integration | `go test ./updates -run TestSeedEnPl -count=1` | ❌ W0 | ⬜ pending |
|
||||||
| 14.2.1-W0 | 04 | 0 | D-09/D-12 | — | `Translatable()` + get/set + `WithLocale` | unit | `go test ./classes -run TestTranslatableGetSet -count=1` | ❌ W0 | ⬜ pending |
|
| 14.2.1-W0 | 04 | 0 | D-09/D-12 | — | `Translatable()` + get/set + `WithLocale` | unit | `go test ./classes -run TestTranslatableGetSet -count=1` | ❌ W0 | ⬜ pending |
|
||||||
| 14.2.1-W0 | 04 | 0 | D-10 | — | Tables `winter_translate_locales\|attributes\|indexes\|messages` exist after migrate | integration | `go test ./updates -run TestTranslateTables -count=1` | ❌ W0 | ⬜ pending |
|
| 14.2.1-W0 | 04 | 0 | D-10 | — | Tables `golem15_translate_locales\|attributes\|indexes\|messages` exist after migrate | integration | `go test ./updates -run TestTranslateTables -count=1` | ❌ W0 | ⬜ pending |
|
||||||
| 14.2.1-W0 | 04 | 0 | D-11 | — | Missing `pl` falls back to default locale column | unit | `go test ./classes -run TestFallbackDefaultLocale -count=1` | ❌ W0 | ⬜ pending |
|
| 14.2.1-W0 | 04 | 0 | D-11 | — | Missing `pl` falls back to default locale column | unit | `go test ./classes -run TestFallbackDefaultLocale -count=1` | ❌ W0 | ⬜ pending |
|
||||||
| 14.2.1-W0 | 04 | 0 | D-17 | — | Host/plugin Activate with user+translate | smoke | `go test ./... -run TestBootUserTranslate -count=1` | ❌ W0 | ⬜ pending |
|
| 14.2.1-W0 | 04 | 0 | D-17 | — | Host/plugin Activate with user+translate | smoke | `go test ./... -run TestBootUserTranslate -count=1` | ❌ W0 | ⬜ pending |
|
||||||
| 14.2.1-W0 | 04 | 0 | T-SEC-01 | T-14.2.1-03 | Unlisted locale never stored | unit | `go test ./classes -run TestInvalidLocaleRejected -count=1` | ❌ W0 | ⬜ pending |
|
| 14.2.1-W0 | 04 | 0 | T-SEC-01 | T-14.2.1-03 | Unlisted locale never stored | unit | `go test ./classes -run TestInvalidLocaleRejected -count=1` | ❌ W0 | ⬜ pending |
|
||||||
|
|||||||
Reference in New Issue
Block a user