Add localization to API server
ci/woodpecker/push/woodpecker Pipeline was successful
Details
ci/woodpecker/push/woodpecker Pipeline was successful
Details
This commit is contained in:
parent
c41e7e1c18
commit
238f4cf682
|
@ -9,9 +9,11 @@ import (
|
||||||
|
|
||||||
"github.com/jmoiron/sqlx"
|
"github.com/jmoiron/sqlx"
|
||||||
"github.com/twitchtv/twirp"
|
"github.com/twitchtv/twirp"
|
||||||
|
"go.arsenm.dev/logger/log"
|
||||||
"go.arsenm.dev/lure/internal/api"
|
"go.arsenm.dev/lure/internal/api"
|
||||||
"go.arsenm.dev/lure/internal/config"
|
"go.arsenm.dev/lure/internal/config"
|
||||||
"go.arsenm.dev/lure/internal/db"
|
"go.arsenm.dev/lure/internal/db"
|
||||||
|
"golang.org/x/text/language"
|
||||||
)
|
)
|
||||||
|
|
||||||
type lureWebAPI struct {
|
type lureWebAPI struct {
|
||||||
|
@ -59,7 +61,7 @@ func (l lureWebAPI) Search(ctx context.Context, req *api.SearchRequest) (*api.Se
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
out.Packages = append(out.Packages, dbPkgToAPI(pkg))
|
out.Packages = append(out.Packages, dbPkgToAPI(ctx, pkg))
|
||||||
}
|
}
|
||||||
|
|
||||||
return out, err
|
return out, err
|
||||||
|
@ -70,7 +72,7 @@ func (l lureWebAPI) GetPkg(ctx context.Context, req *api.GetPackageRequest) (*ap
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return dbPkgToAPI(pkg), nil
|
return dbPkgToAPI(ctx, pkg), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l lureWebAPI) GetBuildScript(ctx context.Context, req *api.GetBuildScriptRequest) (*api.GetBuildScriptResponse, error) {
|
func (l lureWebAPI) GetBuildScript(ctx context.Context, req *api.GetBuildScriptRequest) (*api.GetBuildScriptResponse, error) {
|
||||||
|
@ -94,16 +96,16 @@ func (l lureWebAPI) GetBuildScript(ctx context.Context, req *api.GetBuildScriptR
|
||||||
return &api.GetBuildScriptResponse{Script: string(data)}, nil
|
return &api.GetBuildScriptResponse{Script: string(data)}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func dbPkgToAPI(pkg *db.Package) *api.Package {
|
func dbPkgToAPI(ctx context.Context, pkg *db.Package) *api.Package {
|
||||||
return &api.Package{
|
return &api.Package{
|
||||||
Name: pkg.Name,
|
Name: pkg.Name,
|
||||||
Repository: pkg.Repository,
|
Repository: pkg.Repository,
|
||||||
Version: pkg.Version,
|
Version: pkg.Version,
|
||||||
Release: int64(pkg.Release),
|
Release: int64(pkg.Release),
|
||||||
Epoch: ptr(int64(pkg.Epoch)),
|
Epoch: ptr(int64(pkg.Epoch)),
|
||||||
Description: &pkg.Description,
|
Description: performTranslation(ctx, pkg.Description.Val),
|
||||||
Homepage: &pkg.Homepage,
|
Homepage: performTranslation(ctx, pkg.Homepage.Val),
|
||||||
Maintainer: &pkg.Maintainer,
|
Maintainer: performTranslation(ctx, pkg.Maintainer.Val),
|
||||||
Architectures: pkg.Architectures.Val,
|
Architectures: pkg.Architectures.Val,
|
||||||
Licenses: pkg.Licenses.Val,
|
Licenses: pkg.Licenses.Val,
|
||||||
Provides: pkg.Provides.Val,
|
Provides: pkg.Provides.Val,
|
||||||
|
@ -125,3 +127,61 @@ func dbMapToAPI(m map[string][]string) map[string]*api.StringList {
|
||||||
}
|
}
|
||||||
return out
|
return out
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func performTranslation(ctx context.Context, v map[string]string) *string {
|
||||||
|
alVal := ctx.Value(acceptLanguageKey{})
|
||||||
|
langVal := ctx.Value(langParameterKey{})
|
||||||
|
|
||||||
|
if alVal == nil && langVal == nil {
|
||||||
|
val, ok := v[""]
|
||||||
|
if !ok {
|
||||||
|
return ptr("<unknown>")
|
||||||
|
}
|
||||||
|
return &val
|
||||||
|
}
|
||||||
|
|
||||||
|
al, _ := alVal.(string)
|
||||||
|
lang, _ := langVal.(string)
|
||||||
|
|
||||||
|
tags, _, err := language.ParseAcceptLanguage(al)
|
||||||
|
if err != nil {
|
||||||
|
log.Warn("Error parsing Accept-Language header").Err(err).Send()
|
||||||
|
}
|
||||||
|
|
||||||
|
var bases []string
|
||||||
|
if lang != "" {
|
||||||
|
langTag, err := language.Parse(lang)
|
||||||
|
if err != nil {
|
||||||
|
log.Warn("Error parsing lang parameter").Err(err).Send()
|
||||||
|
bases = getLangBases(tags)
|
||||||
|
} else {
|
||||||
|
bases = getLangBases(append([]language.Tag{langTag}, tags...))
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
bases = getLangBases(tags)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(bases) == 1 {
|
||||||
|
bases = []string{"en", ""}
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, name := range bases {
|
||||||
|
val, ok := v[name]
|
||||||
|
if !ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
return &val
|
||||||
|
}
|
||||||
|
|
||||||
|
return ptr("<unknown>")
|
||||||
|
}
|
||||||
|
|
||||||
|
func getLangBases(langs []language.Tag) []string {
|
||||||
|
out := make([]string, len(langs)+1)
|
||||||
|
for i, lang := range langs {
|
||||||
|
base, _ := lang.Base()
|
||||||
|
out[i] = base.String()
|
||||||
|
}
|
||||||
|
out[len(out)-1] = ""
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
|
@ -49,6 +49,7 @@ func main() {
|
||||||
lureWebAPI{db: gdb},
|
lureWebAPI{db: gdb},
|
||||||
twirp.WithServerPathPrefix(""),
|
twirp.WithServerPathPrefix(""),
|
||||||
)
|
)
|
||||||
|
handler = withAcceptLanguage(handler)
|
||||||
handler = allowAllCORSHandler(handler)
|
handler = allowAllCORSHandler(handler)
|
||||||
handler = handleWebhook(handler, sigCh)
|
handler = handleWebhook(handler, sigCh)
|
||||||
|
|
||||||
|
@ -75,3 +76,22 @@ func allowAllCORSHandler(h http.Handler) http.Handler {
|
||||||
h.ServeHTTP(res, req)
|
h.ServeHTTP(res, req)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type acceptLanguageKey struct{}
|
||||||
|
type langParameterKey struct{}
|
||||||
|
|
||||||
|
func withAcceptLanguage(h http.Handler) http.Handler {
|
||||||
|
return http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) {
|
||||||
|
ctx := req.Context()
|
||||||
|
|
||||||
|
langs := req.Header.Get("Accept-Language")
|
||||||
|
ctx = context.WithValue(ctx, acceptLanguageKey{}, langs)
|
||||||
|
|
||||||
|
lang := req.URL.Query().Get("lang")
|
||||||
|
ctx = context.WithValue(ctx, langParameterKey{}, lang)
|
||||||
|
|
||||||
|
req = req.WithContext(ctx)
|
||||||
|
|
||||||
|
h.ServeHTTP(res, req)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue