From fc9061fee395bfbfe18fe90d8c0dfcdeea5c616c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Toma=C5=BE=20Jerman?= Date: Mon, 20 Sep 2021 18:53:31 +0200 Subject: [PATCH] Resource translation improvements * Fix locale context management * Assure proper locale context parameters are used when updating, listing translations * Return missing module field translations --- compose/service/locale.go | 30 +++++++++ compose/service/module.go | 2 +- compose/service/page.go | 4 +- compose/types/locale.gen.go | 32 +++++++++ compose/types/module_field.go | 122 ++++++++++++++++++++++++++++++++++ def/compose.module-field.yaml | 8 +-- pkg/locale/http.go | 8 ++- 7 files changed, 198 insertions(+), 8 deletions(-) diff --git a/compose/service/locale.go b/compose/service/locale.go index 3ffbf8cb2..e95976715 100644 --- a/compose/service/locale.go +++ b/compose/service/locale.go @@ -27,6 +27,36 @@ func (svc resourceTranslationsManager) moduleExtended(ctx context.Context, res * Msg: svc.locale.TResourceFor(tag, f.ResourceTranslation(), k.Path), }) + k = types.LocaleKeyModuleFieldDescriptionView + out = append(out, &locale.ResourceTranslation{ + Resource: f.ResourceTranslation(), + Lang: tag.String(), + Key: k.Path, + Msg: svc.locale.TResourceFor(tag, f.ResourceTranslation(), k.Path), + }) + k = types.LocaleKeyModuleFieldDescriptionEdit + out = append(out, &locale.ResourceTranslation{ + Resource: f.ResourceTranslation(), + Lang: tag.String(), + Key: k.Path, + Msg: svc.locale.TResourceFor(tag, f.ResourceTranslation(), k.Path), + }) + + k = types.LocaleKeyModuleFieldHintView + out = append(out, &locale.ResourceTranslation{ + Resource: f.ResourceTranslation(), + Lang: tag.String(), + Key: k.Path, + Msg: svc.locale.TResourceFor(tag, f.ResourceTranslation(), k.Path), + }) + k = types.LocaleKeyModuleFieldHintEdit + out = append(out, &locale.ResourceTranslation{ + Resource: f.ResourceTranslation(), + Lang: tag.String(), + Key: k.Path, + Msg: svc.locale.TResourceFor(tag, f.ResourceTranslation(), k.Path), + }) + // Extra field bits converted, err := svc.moduleFieldValidatorErrorHandler(ctx, tag, f, k.Path) if err != nil { diff --git a/compose/service/module.go b/compose/service/module.go index c08ae2ec0..0c996e48c 100644 --- a/compose/service/module.go +++ b/compose/service/module.go @@ -368,7 +368,7 @@ func (svc module) updater(ctx context.Context, namespaceID, moduleID uint64, act tt = append(tt, f.EncodeTranslations()...) } - tt.SetLanguage(locale.GetAcceptLanguageFromContext(ctx)) + tt.SetLanguage(contentLang) err = svc.locale.Upsert(ctx, tt) if err != nil { return err diff --git a/compose/service/page.go b/compose/service/page.go index cc3c082fb..ddf6b6802 100644 --- a/compose/service/page.go +++ b/compose/service/page.go @@ -296,7 +296,7 @@ func (svc page) Create(ctx context.Context, new *types.Page) (*types.Page, error // i18n if contentLang := locale.GetContentLanguageFromContext(ctx); contentLang != language.Und { tt := new.EncodeTranslations() - tt.SetLanguage(locale.GetAcceptLanguageFromContext(ctx)) + tt.SetLanguage(contentLang) err = svc.locale.Upsert(ctx, tt) if err != nil { return err @@ -374,7 +374,7 @@ func (svc page) updater(ctx context.Context, namespaceID, pageID uint64, action // i18n if contentLang := locale.GetContentLanguageFromContext(ctx); contentLang != language.Und { tt := p.EncodeTranslations() - tt.SetLanguage(locale.GetAcceptLanguageFromContext(ctx)) + tt.SetLanguage(contentLang) err = svc.locale.Upsert(ctx, tt) if err != nil { return err diff --git a/compose/types/locale.gen.go b/compose/types/locale.gen.go index 94d835813..ee94e8acc 100644 --- a/compose/types/locale.gen.go +++ b/compose/types/locale.gen.go @@ -48,6 +48,30 @@ var ( Resource: ModuleFieldResourceTranslationType, Path: "label", } + LocaleKeyModuleFieldDescriptionView = LocaleKey{ + Name: "descriptionView", + Resource: ModuleFieldResourceTranslationType, + Path: "meta.description.view", + CustomHandler: "descriptionView", + } + LocaleKeyModuleFieldDescriptionEdit = LocaleKey{ + Name: "descriptionEdit", + Resource: ModuleFieldResourceTranslationType, + Path: "meta.description.edit", + CustomHandler: "descriptionEdit", + } + LocaleKeyModuleFieldHintView = LocaleKey{ + Name: "hintView", + Resource: ModuleFieldResourceTranslationType, + Path: "meta.hint.view", + CustomHandler: "hintView", + } + LocaleKeyModuleFieldHintEdit = LocaleKey{ + Name: "hintEdit", + Resource: ModuleFieldResourceTranslationType, + Path: "meta.hint.edit", + CustomHandler: "hintEdit", + } LocaleKeyModuleFieldValidatorError = LocaleKey{ Name: "validatorError", Resource: ModuleFieldResourceTranslationType, @@ -178,6 +202,10 @@ func (r *ModuleField) DecodeTranslations(tt locale.ResourceTranslationIndex) { if aux = tt.FindByKey(LocaleKeyModuleFieldLabel.Path); aux != nil { r.Label = aux.Msg } + r.decodeTranslationsDescriptionView(tt) + r.decodeTranslationsDescriptionEdit(tt) + r.decodeTranslationsHintView(tt) + r.decodeTranslationsHintEdit(tt) r.decodeTranslationsValidatorError(tt) } @@ -191,6 +219,10 @@ func (r *ModuleField) EncodeTranslations() (out locale.ResourceTranslationSet) { }) } + out = append(out, r.encodeTranslationsDescriptionView()...) + out = append(out, r.encodeTranslationsDescriptionEdit()...) + out = append(out, r.encodeTranslationsHintView()...) + out = append(out, r.encodeTranslationsHintEdit()...) out = append(out, r.encodeTranslationsValidatorError()...) return out diff --git a/compose/types/module_field.go b/compose/types/module_field.go index 510fbc08f..fd81a90f6 100644 --- a/compose/types/module_field.go +++ b/compose/types/module_field.go @@ -10,6 +10,7 @@ import ( "github.com/cortezaproject/corteza-server/pkg/filter" "github.com/cortezaproject/corteza-server/pkg/locale" + "github.com/spf13/cast" ) type ( @@ -66,6 +67,38 @@ func (f *ModuleField) decodeTranslationsValidatorError(tt locale.ResourceTransla } } +func (f *ModuleField) decodeTranslationsDescriptionView(tt locale.ResourceTranslationIndex) { + var aux *locale.ResourceTranslation + + if aux = tt.FindByKey(LocaleKeyModuleFieldDescriptionView.Path); aux != nil { + f.setOptionKey(aux.Msg, "description", "edit") + } +} + +func (f *ModuleField) decodeTranslationsDescriptionEdit(tt locale.ResourceTranslationIndex) { + var aux *locale.ResourceTranslation + + if aux = tt.FindByKey(LocaleKeyModuleFieldDescriptionEdit.Path); aux != nil { + f.setOptionKey(aux.Msg, "description", "view") + } +} + +func (f *ModuleField) decodeTranslationsHintView(tt locale.ResourceTranslationIndex) { + var aux *locale.ResourceTranslation + + if aux = tt.FindByKey(LocaleKeyModuleFieldHintView.Path); aux != nil { + f.setOptionKey(aux.Msg, "hint", "edit") + } +} + +func (f *ModuleField) decodeTranslationsHintEdit(tt locale.ResourceTranslationIndex) { + var aux *locale.ResourceTranslation + + if aux = tt.FindByKey(LocaleKeyModuleFieldHintEdit.Path); aux != nil { + f.setOptionKey(aux.Msg, "hint", "view") + } +} + func (m *ModuleField) encodeTranslationsValidatorError() (out locale.ResourceTranslationSet) { out = make(locale.ResourceTranslationSet, 0, 3) @@ -86,10 +119,99 @@ func (m *ModuleField) encodeTranslationsValidatorError() (out locale.ResourceTra return } +func (f *ModuleField) encodeTranslationsDescriptionView() (out locale.ResourceTranslationSet) { + out = locale.ResourceTranslationSet{} + v := f.getOptionKey("description", "edit") + aux := cast.ToString(v) + if aux != "" { + out = append(out, &locale.ResourceTranslation{ + Resource: f.ResourceTranslation(), + Key: LocaleKeyModuleFieldDescriptionView.Path, + Msg: aux, + }) + } + return out +} + +func (f *ModuleField) encodeTranslationsDescriptionEdit() (out locale.ResourceTranslationSet) { + out = locale.ResourceTranslationSet{} + v := f.getOptionKey("description", "view") + aux := cast.ToString(v) + if aux != "" { + out = append(out, &locale.ResourceTranslation{ + Resource: f.ResourceTranslation(), + Key: LocaleKeyModuleFieldDescriptionEdit.Path, + Msg: aux, + }) + } + return out +} + +func (f *ModuleField) encodeTranslationsHintView() (out locale.ResourceTranslationSet) { + out = locale.ResourceTranslationSet{} + v := f.getOptionKey("hint", "edit") + aux := cast.ToString(v) + if aux != "" { + out = append(out, &locale.ResourceTranslation{ + Resource: f.ResourceTranslation(), + Key: LocaleKeyModuleFieldHintView.Path, + Msg: aux, + }) + } + return out +} + +func (f *ModuleField) encodeTranslationsHintEdit() (out locale.ResourceTranslationSet) { + out = locale.ResourceTranslationSet{} + v := f.getOptionKey("hint", "view") + aux := cast.ToString(v) + if aux != "" { + out = append(out, &locale.ResourceTranslation{ + Resource: f.ResourceTranslation(), + Key: LocaleKeyModuleFieldHintEdit.Path, + Msg: aux, + }) + } + return out +} + func (m ModuleField) Clone() *ModuleField { return &m } +func (m ModuleField) setOptionKey(v interface{}, kk ...string) { + opt := m.Options + + for _, k := range kk[0 : len(kk)-1] { + _, ok := opt[k] + if !ok { + opt = map[string]interface{}{k: make(map[string]interface{})} + } + aux := opt[k].(map[string]interface{}) + + opt = aux + } + + k := kk[len(kk)-1] + opt[k] = v +} + +func (m ModuleField) getOptionKey(kk ...string) interface{} { + opt := m.Options + + for _, k := range kk[0 : len(kk)-1] { + _, ok := opt[k] + if !ok { + opt = map[string]interface{}{k: make(map[string]interface{})} + } + aux := opt[k].(map[string]interface{}) + + opt = aux + } + + return opt[kk[len(kk)-1]] +} + func (set ModuleFieldSet) Clone() (out ModuleFieldSet) { out = make([]*ModuleField, len(set)) for i := range set { diff --git a/def/compose.module-field.yaml b/def/compose.module-field.yaml index 0819871fc..0277e2b33 100644 --- a/def/compose.module-field.yaml +++ b/def/compose.module-field.yaml @@ -17,8 +17,8 @@ locale: skipSvc: true keys: - label -# - { name: descriptionView, path: meta.description.view, custom: true } -# - { name: descriptionEdit, path: meta.description.edit, custom: true } -# - { name: hintView, path: meta.hint.view, custom: true } -# - { name: hintEdit, path: meta.hint.edit, custom: true } + - { name: descriptionView, path: meta.description.view, custom: true, customHandler: descriptionView } + - { name: descriptionEdit, path: meta.description.edit, custom: true, customHandler: descriptionEdit } + - { name: hintView, path: meta.hint.view, custom: true, customHandler: hintView } + - { name: hintEdit, path: meta.hint.edit, custom: true, customHandler: hintEdit } - { name: validatorError, path: "expression.validator.{{validatorID}}.error", custom: true, customHandler: validatorError } diff --git a/pkg/locale/http.go b/pkg/locale/http.go index 3a269d4d1..57e658c78 100644 --- a/pkg/locale/http.go +++ b/pkg/locale/http.go @@ -16,9 +16,11 @@ func DetectLanguage(ll *service) func(next http.Handler) http.Handler { var ctx = r.Context() // resolve accept-language header + // Accept-Language specifies the language of the response payload. ctx = SetAcceptLanguageToContext(ctx, resolveAcceptLanguageHeaders(ll, r)) // resolve content-language header + // Content-Language specifies the language of the request payload. ctx = SetContentLanguageToContext(ctx, resolveContentLanguageHeaders(r.Header, ll.Default().Tag)) next.ServeHTTP(w, r.WithContext(ctx)) @@ -37,7 +39,11 @@ func DetectLanguage(ll *service) func(next http.Handler) http.Handler { func resolveContentLanguageHeaders(h http.Header, def language.Tag) language.Tag { var cLang = h.Get(ContentLanguageHeader) - if cLang == "skip" || cLang == "" { + if cLang == "" { + return def + } + + if cLang == "skip" { // more than 1 header or value equal to skip return language.Und }