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:
@@ -61,6 +61,11 @@ type RelationSchema struct {
|
||||
Label string `json:"label"`
|
||||
View RelationPanel `json:"view"`
|
||||
Manage RelationPanel `json:"manage"`
|
||||
// Messages is the relation manager's copy (D-13); the cached schema
|
||||
// carries each phrase key as its own form.
|
||||
Messages *RelationMessages `json:"messages"`
|
||||
|
||||
messageKeys relationMessageKeys
|
||||
}
|
||||
|
||||
// CompiledRelation combines trusted YAML with model-owned metadata.
|
||||
@@ -100,6 +105,10 @@ type RelationMutationResult struct {
|
||||
type RelationService struct{ DB *gorm.DB }
|
||||
|
||||
func (s RelationSchema) MarshalJSON() ([]byte, error) {
|
||||
if s.Messages == nil {
|
||||
keys := localizeMessages[relationMessageKeys, RelationMessages](context.Background(), nil, s.relationMessageKeySet())
|
||||
s.Messages = &keys
|
||||
}
|
||||
type alias RelationSchema
|
||||
out := alias(s)
|
||||
ensureRelationArrays(&out.View)
|
||||
@@ -125,6 +134,8 @@ func (s *RelationSchema) Localize(ctx context.Context, tr *phrasebook.Translator
|
||||
out.Label = translateKey(ctx, tr, s.Label)
|
||||
out.View = localizeRelationPanel(ctx, tr, s.View)
|
||||
out.Manage = localizeRelationPanel(ctx, tr, s.Manage)
|
||||
messages := localizeMessages[relationMessageKeys, RelationMessages](ctx, tr, s.relationMessageKeySet())
|
||||
out.Messages = &messages
|
||||
return &out
|
||||
}
|
||||
|
||||
@@ -144,9 +155,10 @@ type relationRoot struct {
|
||||
}
|
||||
|
||||
type relationDocument struct {
|
||||
Label string `yaml:"label"`
|
||||
View relationPanelDocument `yaml:"view"`
|
||||
Manage relationPanelDocument `yaml:"manage"`
|
||||
Label string `yaml:"label"`
|
||||
View relationPanelDocument `yaml:"view"`
|
||||
Manage relationPanelDocument `yaml:"manage"`
|
||||
Messages *relationMessageKeys `yaml:"messages"`
|
||||
}
|
||||
|
||||
type relationPanelDocument struct {
|
||||
@@ -236,8 +248,14 @@ func compileRelations(pluginID string, ctl pact.AdminController, fsys fs.FS, for
|
||||
}
|
||||
orderRelationColumns(raw, &view)
|
||||
orderRelationColumns(raw, &manage)
|
||||
schema := &RelationSchema{Name: name, Label: doc.Label, View: view, Manage: manage}
|
||||
if doc.Messages != nil {
|
||||
schema.messageKeys = *doc.Messages
|
||||
}
|
||||
keys := localizeMessages[relationMessageKeys, RelationMessages](context.Background(), nil, schema.relationMessageKeySet())
|
||||
schema.Messages = &keys
|
||||
out[name] = &CompiledRelation{
|
||||
Schema: &RelationSchema{Name: name, Label: doc.Label, View: view, Manage: manage},
|
||||
Schema: schema,
|
||||
Contract: contract,
|
||||
RequiredPermissions: append([]string(nil), requiredOf(ctl)...),
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user