Skip to content
Snippets Groups Projects
Commit 4244b43b authored by Pavel Antonov's avatar Pavel Antonov :asterisk:
Browse files

Merge branch 'feature/PRXS-2653-LocalizerCheckNoPublish' into 'master'

Добавлен метод `Locale` в пакет `localizer`

See merge request perxis/perxis-go!265
parents 752c6f62 e265e539
No related branches found
No related tags found
No related merge requests found
...@@ -12,25 +12,39 @@ import ( ...@@ -12,25 +12,39 @@ import (
) )
type Localizer struct { type Localizer struct {
schema *schema.Schema
localesKV map[string]*locales.Locale
locales []*locales.Locale
localeID string
allowNoPublished bool
allowDisabled bool
}
type Config struct {
Schema *schema.Schema Schema *schema.Schema
Locales map[string]*locales.Locale Locales []*locales.Locale
LocaleID string LocaleID string
AllowNoPublished bool
AllowDisabled bool
} }
// NewLocalizer создает экземпляр локализатора. Требуется указать "загруженную" схему // NewLocalizer создает экземпляр локализатора. Требуется указать "загруженную" схему
func NewLocalizer(s *schema.Schema, locs []*locales.Locale, localeID string) *Localizer { func NewLocalizer(cfg Config) *Localizer {
if localeID == "" { if cfg.LocaleID == "" {
localeID = locales.DefaultID cfg.LocaleID = locales.DefaultID
} }
loc := &Localizer{ loc := &Localizer{
Schema: s, schema: cfg.Schema,
Locales: make(map[string]*locales.Locale, len(locs)), localesKV: make(map[string]*locales.Locale, len(cfg.Locales)),
LocaleID: localeID, locales: cfg.Locales,
localeID: cfg.LocaleID,
allowDisabled: cfg.AllowDisabled,
allowNoPublished: cfg.AllowNoPublished,
} }
for _, l := range locs { for _, l := range cfg.Locales {
loc.Locales[l.ID] = l loc.localesKV[l.ID] = l
} }
return loc return loc
...@@ -43,15 +57,15 @@ func NewLocalizer(s *schema.Schema, locs []*locales.Locale, localeID string) *Lo ...@@ -43,15 +57,15 @@ func NewLocalizer(s *schema.Schema, locs []*locales.Locale, localeID string) *Lo
// При отсутствии каких-либо полей в переводе на `localeID` данные берутся сначала из fallback-локали, // При отсутствии каких-либо полей в переводе на `localeID` данные берутся сначала из fallback-локали,
// если перевод отсутствует то из `data` // если перевод отсутствует то из `data`
func (l *Localizer) Localize(data map[string]interface{}, translations map[string]map[string]interface{}) (localized map[string]interface{}, err error) { func (l *Localizer) Localize(data map[string]interface{}, translations map[string]map[string]interface{}) (localized map[string]interface{}, err error) {
if l.LocaleID == locales.DefaultID {
return data, nil
}
target, fallback, err := l.getTargetAndFallBackLocales() target, fallback, err := l.getTargetAndFallBackLocales()
if err != nil { if err != nil {
return nil, err return nil, err
} }
if target.IsDefault() {
return data, nil
}
// localize fallback -> target // localize fallback -> target
fallbackData := data fallbackData := data
var exist bool var exist bool
...@@ -75,15 +89,15 @@ func (l *Localizer) Localize(data map[string]interface{}, translations map[strin ...@@ -75,15 +89,15 @@ func (l *Localizer) Localize(data map[string]interface{}, translations map[strin
// ExtractTranslation Получить "просеянные" данные для локали localeID: все поля, значения которых совпадают // ExtractTranslation Получить "просеянные" данные для локали localeID: все поля, значения которых совпадают
// с переводом на fallback-локаль или основными данными, удаляются из перевода // с переводом на fallback-локаль или основными данными, удаляются из перевода
func (l *Localizer) ExtractTranslation(data map[string]interface{}, translations map[string]map[string]interface{}) (translation map[string]interface{}, err error) { func (l *Localizer) ExtractTranslation(data map[string]interface{}, translations map[string]map[string]interface{}) (translation map[string]interface{}, err error) {
if l.LocaleID == locales.DefaultID {
return data, nil
}
target, fallback, err := l.getTargetAndFallBackLocales() target, fallback, err := l.getTargetAndFallBackLocales()
if err != nil { if err != nil {
return nil, err return nil, err
} }
if target.IsDefault() {
return data, nil
}
fallbackData := data fallbackData := data
var exist bool var exist bool
if !fallback.IsDefault() { if !fallback.IsDefault() {
...@@ -100,13 +114,46 @@ func (l *Localizer) ExtractTranslation(data map[string]interface{}, translations ...@@ -100,13 +114,46 @@ func (l *Localizer) ExtractTranslation(data map[string]interface{}, translations
return l.extractTranslation(translation, fallbackData) return l.extractTranslation(translation, fallbackData)
} }
func (l *Localizer) locale(localeID string) (loc *locales.Locale, err error) {
if localeID == "" {
return nil, locales.ErrLocaleIDRequired
}
var exist bool
if loc, exist = l.localesKV[localeID]; !exist {
return nil, locales.ErrNotFound
}
if loc == nil {
return nil, locales.ErrNotFound
}
if !l.allowDisabled && loc.Disabled {
return nil, errors.New("locale is disabled")
}
if !l.allowNoPublished && localeID == l.localeID && loc.NoPublish { // can use non-publishing locale for fallback
return nil, errors.New("localizer not configured for non-publishing locales")
}
return
}
func (l *Localizer) Locale() (loc *locales.Locale, err error) {
return l.locale(l.localeID)
}
func (l *Localizer) Locales() []*locales.Locale {
return l.locales
}
func (l *Localizer) getTargetAndFallBackLocales() (target, fallback *locales.Locale, err error) { func (l *Localizer) getTargetAndFallBackLocales() (target, fallback *locales.Locale, err error) {
if target = l.Locales[l.LocaleID]; target == nil || target.Disabled { if target, err = l.locale(l.localeID); err != nil {
return nil, nil, errors.New("target locale not found or disabled") return nil, nil, errors.New("target locale not found or disabled")
} }
if fallback = l.Locales[target.Fallback]; fallback == nil || fallback.Disabled { if fallback, err = l.locale(target.Fallback); err != nil {
fallback = l.Locales[locales.DefaultID] fallback = l.localesKV[locales.DefaultID]
} }
return return
} }
...@@ -116,7 +163,7 @@ func (l *Localizer) localize(target, fallback map[string]interface{}) (map[strin ...@@ -116,7 +163,7 @@ func (l *Localizer) localize(target, fallback map[string]interface{}) (map[strin
return nil, nil return nil, nil
} }
single := l.Schema.GetFields(func(f *field.Field, p string) bool { single := l.schema.GetFields(func(f *field.Field, p string) bool {
return f.SingleLocale return f.SingleLocale
}) })
...@@ -125,7 +172,7 @@ func (l *Localizer) localize(target, fallback map[string]interface{}) (map[strin ...@@ -125,7 +172,7 @@ func (l *Localizer) localize(target, fallback map[string]interface{}) (map[strin
cfg.Fields[sn.Path] = walk.FieldConfig{Fn: walk.KeepSrc} cfg.Fields[sn.Path] = walk.FieldConfig{Fn: walk.KeepSrc}
} }
w := walk.NewWalker(l.Schema, cfg) w := walk.NewWalker(l.schema, cfg)
w.DefaultFn = localize w.DefaultFn = localize
res, _, err := w.DataWalk(context.Background(), target, fallback) res, _, err := w.DataWalk(context.Background(), target, fallback)
...@@ -145,7 +192,7 @@ func (l *Localizer) extractTranslation(target, fallback map[string]interface{}) ...@@ -145,7 +192,7 @@ func (l *Localizer) extractTranslation(target, fallback map[string]interface{})
return nil, nil return nil, nil
} }
single := l.Schema.GetFields(func(f *field.Field, p string) bool { single := l.schema.GetFields(func(f *field.Field, p string) bool {
return f.SingleLocale return f.SingleLocale
}) })
...@@ -154,7 +201,7 @@ func (l *Localizer) extractTranslation(target, fallback map[string]interface{}) ...@@ -154,7 +201,7 @@ func (l *Localizer) extractTranslation(target, fallback map[string]interface{})
cfg.Fields[sn.Path] = walk.FieldConfig{Fn: walk.RemoveValue} cfg.Fields[sn.Path] = walk.FieldConfig{Fn: walk.RemoveValue}
} }
w := walk.NewWalker(l.Schema, cfg) w := walk.NewWalker(l.schema, cfg)
w.DefaultFn = extractTranslation w.DefaultFn = extractTranslation
res, _, err := w.DataWalk(context.Background(), target, fallback) res, _, err := w.DataWalk(context.Background(), target, fallback)
......
...@@ -355,7 +355,7 @@ func TestLocalizer_localize(t *testing.T) { ...@@ -355,7 +355,7 @@ func TestLocalizer_localize(t *testing.T) {
for _, tt := range tests { for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) { t.Run(tt.name, func(t *testing.T) {
l := &Localizer{ l := &Localizer{
Schema: s, schema: s,
} }
got, err := l.localize(tt.target, tt.fallback) got, err := l.localize(tt.target, tt.fallback)
if !tt.wantErr { if !tt.wantErr {
...@@ -598,7 +598,7 @@ func TestLocalizer_deLocalize(t *testing.T) { ...@@ -598,7 +598,7 @@ func TestLocalizer_deLocalize(t *testing.T) {
for _, tt := range tests { for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) { t.Run(tt.name, func(t *testing.T) {
l := &Localizer{ l := &Localizer{
Schema: s, schema: s,
} }
got, err := l.extractTranslation(tt.target, tt.fallback) got, err := l.extractTranslation(tt.target, tt.fallback)
if !tt.wantErr { if !tt.wantErr {
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment