Handle multi-lang request for external translation

Frontend/client lib (i18next) sends request for multiple
languages at the same time (format: en+sl+de).

Some internal changes on ext. translation loading (storing) were needed.
This commit is contained in:
Denis Arh
2021-09-08 18:04:15 +02:00
parent 0b54171557
commit 2acaa0062e
3 changed files with 54 additions and 31 deletions
+3 -9
View File
@@ -178,20 +178,14 @@ func loadTranslations(lang *Language) (err error) {
return
}
// wraps JSON with namespaces under each app with a language tag:
// { <lang>: { namespace ..., namespace ... } }
//
// This simplifies and unifies the output and makes it compatible
// with the frontend libs
// encode all external (for webapps, clientS) translations
// into buffers that will be copied directly into responses
for app, nss := range auxExternal {
var (
buf = &bytes.Buffer{}
aux = make(map[string]interface{})
)
aux[lang.Tag.String()] = nss
if err = json.NewEncoder(buf).Encode(aux); err != nil {
if err = json.NewEncoder(buf).Encode(nss); err != nil {
return
}
lang.external[app] = bytes.NewReader(buf.Bytes())
+14 -7
View File
@@ -64,7 +64,7 @@ func Service(log *zap.Logger, opt options.LocaleOpt) (*service, error) {
lang = strings.TrimSpace(lang)
tag := language.Make(lang)
if tag.IsRoot() {
return nil, fmt.Errorf("failed to parse language '%s'", lang)
return nil, fmt.Errorf("failed to parse language '%s' (did you use comma to separate them?)", lang)
}
svc.tags = append(svc.tags, tag)
@@ -220,16 +220,23 @@ func (svc *service) HasApplication(lang language.Tag, app string) bool {
}
// EncodeExternal writes into
func (svc *service) EncodeExternal(w io.Writer, lang language.Tag, app string) (err error) {
func (svc *service) EncodeExternal(w io.Writer, app string, ll ...language.Tag) (err error) {
svc.l.RLock()
defer svc.l.RUnlock()
if svc.HasApplication(lang, app) {
svc.set[lang].external[app].Seek(0, 0)
_, err = io.Copy(w, svc.set[lang].external[app])
} else {
err = fmt.Errorf("application or language missing")
fmt.Fprint(w, "{")
for i, lang := range ll {
if i > 0 {
fmt.Fprint(w, ",")
}
if svc.HasApplication(lang, app) {
fmt.Fprintf(w, "%q:", lang)
svc.set[lang].external[app].Seek(0, 0)
_, _ = io.Copy(w, svc.set[lang].external[app])
}
}
fmt.Fprint(w, "}")
return err
}
+37 -15
View File
@@ -3,6 +3,7 @@ package rest
import (
"context"
"net/http"
"strings"
"github.com/cortezaproject/corteza-server/pkg/errors"
"github.com/cortezaproject/corteza-server/pkg/locale"
@@ -46,31 +47,52 @@ func (ctrl Locale) List(ctx context.Context, r *request.LocaleList) (interface{}
func (ctrl Locale) Get(ctx context.Context, r *request.LocaleGet) (interface{}, error) {
svc := locale.Global()
// We're using + as a language delimiter
// because webapp client i18n lib does this by default
// (url encoded space becomes a +)
const langSplit = "+"
return func(w http.ResponseWriter, req *http.Request) {
if !svc.HasLanguage(language.Make(r.Lang)) {
// @todo temp workaround until frontend knows what languages it can use
r.Lang = svc.List()[0].Tag.String()
}
if !svc.HasLanguage(language.Make(r.Lang)) {
if len(svc.List()) == 0 {
errors.ProperlyServeHTTP(w, req, errors.New(
errors.KindNotFound,
"no such language",
"no languages found",
errors.StackTrimAtFn("http.HandlerFunc.ServeHTTP"),
), true)
return
}
if !svc.HasApplication(language.Make(r.Lang), r.Application) {
errors.ProperlyServeHTTP(w, req, errors.New(
errors.KindNotFound,
"no such application",
errors.StackTrimAtFn("http.HandlerFunc.ServeHTTP"),
), true)
return
// default to 1st language
//var def = svc.List()[0].Tag
var ll = []language.Tag{}
for _, candidate := range strings.Split(r.Lang, langSplit) {
ll = append(ll, language.Make(candidate))
//if svc.HasLanguage(tmp) {
// ll = append(ll, lang)
// break
//}
}
if err := locale.Global().EncodeExternal(w, language.Make(r.Lang), r.Application); err != nil {
//if !svc.HasLanguage(lang) {
// errors.ProperlyServeHTTP(w, req, errors.New(
// errors.KindNotFound,
// "no such language",
// errors.StackTrimAtFn("http.HandlerFunc.ServeHTTP"),
// ), true)
// return
//}
//if !svc.HasApplication(lang, r.Application) {
// errors.ProperlyServeHTTP(w, req, errors.New(
// errors.KindNotFound,
// "no such application",
// errors.StackTrimAtFn("http.HandlerFunc.ServeHTTP"),
// ), true)
// return
//}
if err := locale.Global().EncodeExternal(w, r.Application, ll...); err != nil {
errors.ProperlyServeHTTP(w, req, err, true)
}