diff --git a/go.mod b/go.mod index df53035d50..9759ec248b 100644 --- a/go.mod +++ b/go.mod @@ -16,7 +16,7 @@ require ( github.com/allegro/bigcache v1.2.1 github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc github.com/caos/logging v0.0.2 - github.com/caos/oidc v0.15.3 + github.com/caos/oidc v0.15.6 github.com/caos/orbos v1.5.14-0.20210428081839-983ffc569980 github.com/cockroachdb/cockroach-go/v2 v2.1.0 github.com/duo-labs/webauthn v0.0.0-20200714211715-1daaee874e43 diff --git a/go.sum b/go.sum index 21f2bb0fec..5b31d36795 100644 --- a/go.sum +++ b/go.sum @@ -145,8 +145,8 @@ github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc/go.mod h1:paBW github.com/caos/logging v0.0.2 h1:ebg5C/HN0ludYR+WkvnFjwSExF4wvyiWPyWGcKMYsoo= github.com/caos/logging v0.0.2/go.mod h1:9LKiDE2ChuGv6CHYif/kiugrfEXu9AwDiFWSreX7Wp0= github.com/caos/oidc v0.14.4/go.mod h1:H5Y2zw3YIrWqQOoy0wcmZva2a66bumDyU2iOhXiM9uA= -github.com/caos/oidc v0.15.3 h1:DNzzvSgUbhUewrZKOVF9nDop0AfMy0wjnMy/rD9f8xA= -github.com/caos/oidc v0.15.3/go.mod h1:doQ1B/mGnQWbgS+UOANIQCPJe1+KACyxQ8wjV2d11h0= +github.com/caos/oidc v0.15.6 h1:DKX5gGBbN0j7fpcDNNTjlVCA+I9D0gePFGnZFteTERs= +github.com/caos/oidc v0.15.6/go.mod h1:doQ1B/mGnQWbgS+UOANIQCPJe1+KACyxQ8wjV2d11h0= github.com/caos/orbos v1.5.14-0.20210428081839-983ffc569980 h1:Fz0aYUwGMA2tsu5w7SryqFGjqGClJVHbyhBMT5SXtPU= github.com/caos/orbos v1.5.14-0.20210428081839-983ffc569980/go.mod h1:2I8oiZb5SMRm/qTLvwpSmdV0M6ex8J/UKyxUGfKaqJo= github.com/casbin/casbin/v2 v2.1.2/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n9yuLkIJQ= diff --git a/internal/api/oidc/op.go b/internal/api/oidc/op.go index e683892881..beb8860ba8 100644 --- a/internal/api/oidc/op.go +++ b/internal/api/oidc/op.go @@ -6,6 +6,8 @@ import ( "github.com/caos/logging" "github.com/caos/oidc/pkg/op" + "github.com/rakyll/statik/fs" + "golang.org/x/text/language" http_utils "github.com/caos/zitadel/internal/api/http" "github.com/caos/zitadel/internal/api/http/middleware" @@ -13,6 +15,7 @@ import ( "github.com/caos/zitadel/internal/command" "github.com/caos/zitadel/internal/config/types" "github.com/caos/zitadel/internal/crypto" + "github.com/caos/zitadel/internal/i18n" "github.com/caos/zitadel/internal/id" "github.com/caos/zitadel/internal/query" "github.com/caos/zitadel/internal/telemetry/metrics" @@ -74,6 +77,9 @@ func NewProvider(ctx context.Context, config OPHandlerConfig, command *command.C copy(config.OPConfig.CryptoKey[:], cryptoKey) config.OPConfig.CodeMethodS256 = true config.OPConfig.GrantTypeRefreshToken = true + supportedLanguages, err := getSupportedLanguages() + logging.Log("OIDC-GBd3t").OnError(err).Panic("cannot get supported languages") + config.OPConfig.SupportedUILocales = supportedLanguages metricTypes := []metrics.MetricType{metrics.MetricTypeRequestCount, metrics.MetricTypeStatusCode, metrics.MetricTypeTotalCount} provider, err := op.NewOpenIDProvider( ctx, @@ -114,3 +120,11 @@ func newStorage(config StorageConfig, command *command.Commands, query *query.Qu func (o *OPStorage) Health(ctx context.Context) error { return o.repo.Health(ctx) } + +func getSupportedLanguages() ([]language.Tag, error) { + statikLoginFS, err := fs.NewWithNamespace("login") + if err != nil { + return nil, err + } + return i18n.SupportedLanguages(statikLoginFS) +} diff --git a/internal/i18n/i18n.go b/internal/i18n/i18n.go index dc2d04e222..c2888eb879 100644 --- a/internal/i18n/i18n.go +++ b/internal/i18n/i18n.go @@ -6,6 +6,7 @@ import ( "io/ioutil" "net/http" "os" + "strings" "github.com/BurntSushi/toml" "github.com/caos/logging" @@ -24,9 +25,10 @@ const ( ) type Translator struct { - bundle *i18n.Bundle - cookieName string - cookieHandler *http_util.CookieHandler + bundle *i18n.Bundle + cookieName string + cookieHandler *http_util.CookieHandler + preferredLanguages []string } type TranslatorConfig struct { @@ -87,6 +89,30 @@ func addFileFromFileSystemToBundle(dir http.FileSystem, bundle *i18n.Bundle, fil return nil } +func SupportedLanguages(dir http.FileSystem) ([]language.Tag, error) { + i18nDir, err := dir.Open("/i18n") + if err != nil { + return nil, errors.ThrowNotFound(err, "I18N-Dbt42", "cannot open dir") + } + defer i18nDir.Close() + files, err := i18nDir.Readdir(0) + if err != nil { + return nil, errors.ThrowNotFound(err, "I18N-Gh4zk", "cannot read dir") + } + languages := make([]language.Tag, 0, len(files)) + for _, file := range files { + lang := language.Make(strings.TrimSuffix(file.Name(), ".yaml")) + if lang != language.Und { + languages = append(languages, lang) + } + } + return languages, nil +} + +func (t *Translator) SupportedLanguages() []language.Tag { + return t.bundle.LanguageTags() +} + func (t *Translator) AddMessages(tag language.Tag, messages ...Message) error { if len(messages) == 0 { return nil @@ -136,7 +162,7 @@ func (t *Translator) localizer(langs ...string) *i18n.Localizer { } func (t *Translator) langsFromRequest(r *http.Request) []string { - langs := make([]string, 0) + langs := t.preferredLanguages if r != nil { lang, err := t.cookieHandler.GetCookieValue(r, t.cookieName) if err == nil { @@ -148,7 +174,7 @@ func (t *Translator) langsFromRequest(r *http.Request) []string { } func (t *Translator) langsFromCtx(ctx context.Context) []string { - langs := make([]string, 0) + langs := t.preferredLanguages if ctx != nil { ctxData := authz.GetCtxData(ctx) if ctxData.PreferredLanguage != "" { @@ -159,6 +185,10 @@ func (t *Translator) langsFromCtx(ctx context.Context) []string { return langs } +func (t *Translator) SetPreferredLanguages(langs ...string) { + t.preferredLanguages = langs +} + func getAcceptLanguageHeader(ctx context.Context) string { return metautils.ExtractIncoming(ctx).Get("grpcgateway-accept-language") } diff --git a/internal/ui/login/handler/renderer.go b/internal/ui/login/handler/renderer.go index d618c21eaf..b6b264d361 100644 --- a/internal/ui/login/handler/renderer.go +++ b/internal/ui/login/handler/renderer.go @@ -343,6 +343,7 @@ func (l *Login) getTranslator(authReq *domain.AuthRequest) *i18n.Translator { if authReq != nil { l.addLoginTranslations(translator, authReq.DefaultTranslations) l.addLoginTranslations(translator, authReq.OrgTranslations) + translator.SetPreferredLanguages(authReq.UiLocales...) } return translator }