feat(10-02): backend strings, controller messages and declarative toolbar

- phrasebook ships the backend::lang admin strings (pl, en) with CLDR
  plural maps, loads them as namespace backend, applies
  pact.HasLangOverrides trees (lang/<locale>/<namespace>/<group>.yaml)
  after every namespace, and fails activation when a backend key cannot
  convert to plural forms
- Translator.Forms, Bundle, Resolved and Has serve keys as CLDR form maps
- Public GET /lang returns every backend::lang key for the request
  locale over the fallback locale, Cache-Control no-cache
- config_list, config_form and config_relation accept a strict messages
  block; omitted keys take framework defaults, schemas serve every message
  as CLDR forms, and activation fails on a missing phrase key
- toolbar.buttons is an ordered [create, delete] list; the Winter string
  form, duplicates, unknown actions and delete without showCheckboxes fail
  at boot, and create is dropped when the controller has no form
- Form schema serves the raw Winter redirects; scaffold emits the list
  syntax; form and relation schema routes are typed in the admin OpenAPI
This commit is contained in:
Jakub Zych
2026-09-27 16:16:32 +02:00
parent fe04dbc89e
commit c87148a34f
24 changed files with 2148 additions and 45 deletions

View File

@@ -119,6 +119,20 @@ func AdminLogin() {}
// @Router /auth/refresh [post]
func AdminRefresh() {}
// LangBundle is the public string bundle: full backend::lang key to CLDR
// forms (D-20).
type LangBundle map[string]MessageForms
// AdminLang documents GET /lang.
//
// @Summary Admin UI strings
// @Description Every backend::lang key as CLDR plural forms for the Accept-Language locale, over the fallback locale's keys. Public: the login screen loads it before signing in. meta.locale is the locale the bundle resolved to.
// @Tags admin
// @Produce json
// @Success 200 {object} Envelope[LangBundle]
// @Router /lang [get]
func AdminLang() {}
// AdminLogout documents POST /auth/logout.
//
// @Summary Admin logout
@@ -233,7 +247,7 @@ func AdminListSchema() {}
// @Param vendor path string true "Vendor"
// @Param plugin path string true "Plugin"
// @Param controller path string true "Controller"
// @Success 200 {object} SuccessEnvelope
// @Success 200 {object} Envelope[FormView]
// @Failure 401 {object} ErrorEnvelope
// @Failure 403 {object} ErrorEnvelope
// @Failure 404 {object} ErrorEnvelope
@@ -250,7 +264,7 @@ func AdminFormSchema() {}
// @Param plugin path string true "Plugin"
// @Param controller path string true "Controller"
// @Param name path string true "Relation name"
// @Success 200 {object} SuccessEnvelope
// @Success 200 {object} Envelope[RelationSchema]
// @Failure 401 {object} ErrorEnvelope
// @Failure 403 {object} ErrorEnvelope
// @Failure 404 {object} ErrorEnvelope