Skip to content
Snippets Groups Projects
Select Git revision
  • 2d60b131f11d6bdae79b9b51194d631a1ca20e6d
  • master default protected
  • feature/PRXS-3383-CollectionsRankSortAPI
  • feature/PRXS-3383-CollectionsSort
  • feature/3109-SerializeFeature
  • release/0.33
  • feature/3109-RecoverySchema
  • feature/3109-feature
  • fix/PRXS-3369-ValidateFields
  • refactor/PRXS-3306-MovePkgGroup1
  • refactor/6-pkg-refactor-expr
  • fix/PRXS-3360-TemplateBuilderPatch
  • feature/3293-MongoV2
  • feature/3272-GoVersionUp
  • feature/PRXS-3218-HideTemplateActions
  • feature/PRXS-3234-PruneIdents
  • feature/3146-UpdateItemStorageInterface
  • feature/3274-ObjectIndexesFixes
  • feature/PRXS-3143-3235-ReferenceOptions
  • feature/PRXS-3143-3237-ExecuteOptions
  • feature/3149-LocaleCodeAsID-Implementation
  • v0.33.1
  • v0.32.0
  • v0.31.1
  • v0.31.0
  • v0.30.0
  • v0.29.0
  • v0.28.0
  • v0.27.0-alpha.1+16
  • v0.27.0-alpha.1+15
  • v0.27.0-alpha.1+14
  • v0.27.0-alpha.1+13
  • v0.27.0-alpha.1+12
  • v0.27.0-alpha.1+11
  • v0.27.0-alpha.1+10
  • v0.27.0-alpha.1+9
  • v0.27.0-alpha.1+8
  • v0.27.0-alpha.1+7
  • v0.27.0-alpha.1+6
  • v0.27.0-alpha.1+5
  • v0.27.0-alpha.1+4
41 results

localizer_test.go

Blame
  • localizer_test.go 21.11 KiB
    package localizer
    
    import (
    	"testing"
    
    	"git.perx.ru/perxis/perxis-go/pkg/locales"
    	"git.perx.ru/perxis/perxis-go/pkg/schema"
    	"git.perx.ru/perxis/perxis-go/pkg/schema/field"
    	"github.com/stretchr/testify/assert"
    	"github.com/stretchr/testify/require"
    )
    
    func TestLocalizer_localize(t *testing.T) {
    
    	s := schema.New(
    		"a", field.String(),
    		"b", field.Number(field.NumberFormatInt),
    		"c", field.String().SetSingleLocale(true),
    		"obj1", field.Object(
    			"a", field.String(),
    			"b", field.Number(field.NumberFormatInt),
    			"c", field.Number(field.NumberFormatInt).SetSingleLocale(true),
    			"obj2", field.Object(
    				"a", field.Number(field.NumberFormatInt),
    				"b", field.String(),
    				"c", field.String().SetSingleLocale(true),
    			),
    		),
    		"obj3", field.Object(
    			"a", field.String(),
    		).SetSingleLocale(true),
    		"slice", field.Array(field.String()),
    		"arr", field.Array(field.Object(
    			"num", field.Number(field.NumberFormatInt),
    		)),
    	)
    
    	tests := []struct {
    		fallback map[string]interface{}
    		target   map[string]interface{}
    		want     map[string]interface{}
    		name     string
    		wantErr  bool
    	}{
    		{
    			name:     "Nil",
    			fallback: nil,
    			target:   nil,
    			want:     nil,
    		},
    		{
    			name:     "Empty",
    			fallback: map[string]interface{}{},
    			target:   map[string]interface{}{},
    			want:     map[string]interface{}{},
    		},
    		{
    			name: "Target Empty",
    			fallback: map[string]interface{}{
    				"a": "en",
    				"b": 1,
    				"c": "single",
    				"obj1": map[string]interface{}{
    					"a": "obj1_en",
    					"b": 2,
    					"c": 20,
    					"obj2": map[string]interface{}{
    						"a": 3,
    						"b": "obj1_obj2_en",
    						"c": "obj1_obj2_single",
    					},
    				},
    				"obj3": map[string]interface{}{
    					"a": "obj3_en",
    				},
    				"slice": []interface{}{"en_s1", "en_s2"},
    				"arr": []interface{}{
    					map[string]interface{}{"num": 11},
    					map[string]interface{}{"num": 22},
    				},
    			},
    			target: map[string]interface{}{},
    			want: map[string]interface{}{
    				"a": "en",
    				"b": 1,
    				"c": "single",
    				"obj1": map[string]interface{}{
    					"a": "obj1_en",
    					"b": 2,
    					"c": 20,
    					"obj2": map[string]interface{}{
    						"a": 3,
    						"b": "obj1_obj2_en",
    						"c": "obj1_obj2_single",
    					},
    				},
    				"obj3": map[string]interface{}{
    					"a": "obj3_en",
    				},
    				"slice": []interface{}{"en_s1", "en_s2"},
    				"arr": []interface{}{
    					map[string]interface{}{"num": 11},
    					map[string]interface{}{"num": 22},
    				},
    			},
    		},
    		{
    			name:     "Fallback Empty",
    			fallback: map[string]interface{}{},
    			target: map[string]interface{}{
    				"a": "en",
    				"b": 1,
    				"c": "single",
    				"obj1": map[string]interface{}{
    					"a": "obj1_en",
    					"b": 2,
    					"c": 20,
    					"obj2": map[string]interface{}{
    						"a": 3,
    						"b": "obj1_obj2_en",
    						"c": "obj1_obj2_single",
    					},
    				},
    				"obj3": map[string]interface{}{
    					"a": "obj3_en",
    				},
    				"slice": []interface{}{"en_s1", "en_s2"},
    				"arr": []interface{}{
    					map[string]interface{}{"num": 11},
    					map[string]interface{}{"num": 22},
    				},
    			},
    			want: map[string]interface{}{
    				"a": "en",
    				"b": 1,
    				"obj1": map[string]interface{}{
    					"a": "obj1_en",
    					"b": 2,
    					"obj2": map[string]interface{}{
    						"a": 3,
    						"b": "obj1_obj2_en",
    					},
    				},
    				"slice": []interface{}{"en_s1", "en_s2"},
    				"arr": []interface{}{
    					map[string]interface{}{"num": 11},
    					map[string]interface{}{"num": 22},
    				},
    			},
    		},
    		{
    			name: "Equal",
    			fallback: map[string]interface{}{
    				"a": "en",
    				"b": 1,
    				"c": "single",
    				"obj1": map[string]interface{}{
    					"a": "obj1_en",
    					"b": 2,
    					"c": 20,
    					"obj2": map[string]interface{}{
    						"a": 3,
    						"b": "obj1_obj2_en",
    						"c": "obj1_obj2_single",
    					},
    				},
    				"obj3": map[string]interface{}{
    					"a": "obj3_en",
    				},
    				"slice": []interface{}{"en_s1", "en_s2"},
    				"arr": []interface{}{
    					map[string]interface{}{"num": 11},
    					map[string]interface{}{"num": 22},
    				},
    			},
    			target: map[string]interface{}{
    				"a": "en",
    				"b": 1,
    				"c": "single",
    				"obj1": map[string]interface{}{
    					"a": "obj1_en",
    					"b": 2,
    					"c": 20,
    					"obj2": map[string]interface{}{
    						"a": 3,
    						"b": "obj1_obj2_en",
    						"c": "obj1_obj2_single",
    					},
    				},
    				"obj3": map[string]interface{}{
    					"a": "obj3_en",
    				},
    				"slice": []interface{}{"en_s1", "en_s2"},
    				"arr": []interface{}{
    					map[string]interface{}{"num": 11},
    					map[string]interface{}{"num": 22},
    				},
    			},
    			want: map[string]interface{}{
    				"a": "en",
    				"b": 1,
    				"c": "single",
    				"obj1": map[string]interface{}{
    					"a": "obj1_en",
    					"b": 2,
    					"c": 20,
    					"obj2": map[string]interface{}{
    						"a": 3,
    						"b": "obj1_obj2_en",
    						"c": "obj1_obj2_single",
    					},
    				},
    				"obj3": map[string]interface{}{
    					"a": "obj3_en",
    				},
    				"slice": []interface{}{"en_s1", "en_s2"},
    				"arr": []interface{}{
    					map[string]interface{}{"num": 11},
    					map[string]interface{}{"num": 22},
    				},
    			},
    		},
    		{
    			name: "Target no single",
    			fallback: map[string]interface{}{
    				"a": "en",
    				"b": 1,
    				"c": "single",
    				"obj1": map[string]interface{}{
    					"a": "obj1_en",
    					"b": 2,
    					"c": 20,
    					"obj2": map[string]interface{}{
    						"a": 3,
    						"b": "obj1_obj2_en",
    						"c": "obj1_obj2_single",
    					},
    				},
    				"obj3": map[string]interface{}{
    					"a": "obj3_en",
    				},
    				"slice": []interface{}{"en_s1", "en_s2"},
    				"arr": []interface{}{
    					map[string]interface{}{"num": 11},
    					map[string]interface{}{"num": 22},
    				},
    			},
    			target: map[string]interface{}{
    				"a": "en",
    				"b": 1,
    				"obj1": map[string]interface{}{
    					"a": "obj1_en",
    					"b": 2,
    					"obj2": map[string]interface{}{
    						"a": 3,
    						"b": "obj1_obj2_en",
    					},
    				},
    				"slice": []interface{}{"en_s1", "en_s2"},
    				"arr": []interface{}{
    					map[string]interface{}{"num": 11},
    					map[string]interface{}{"num": 22},
    				},
    			},
    			want: map[string]interface{}{
    				"a": "en",
    				"b": 1,
    				"c": "single",
    				"obj1": map[string]interface{}{
    					"a": "obj1_en",
    					"b": 2,
    					"c": 20,
    					"obj2": map[string]interface{}{
    						"a": 3,
    						"b": "obj1_obj2_en",
    						"c": "obj1_obj2_single",
    					},
    				},
    				"obj3": map[string]interface{}{
    					"a": "obj3_en",
    				},
    				"slice": []interface{}{"en_s1", "en_s2"},
    				"arr": []interface{}{
    					map[string]interface{}{"num": 11},
    					map[string]interface{}{"num": 22},
    				},
    			},
    		},
    		{
    			name: "Success",
    			fallback: map[string]interface{}{
    				"a": "en",
    				"b": 1,
    				"c": "single",
    				"obj1": map[string]interface{}{
    					"a": "obj1_en",
    					"b": 2,
    					"c": 20,
    					"obj2": map[string]interface{}{
    						"a": 3,
    						"b": "obj1_obj2_en",
    						"c": "obj1_obj2_single",
    					},
    				},
    				"obj3": map[string]interface{}{
    					"a": "obj3_en",
    				},
    				"slice": []interface{}{"en_s1", "en_s2"},
    				"arr": []interface{}{
    					map[string]interface{}{"num": 11},
    					map[string]interface{}{"num": 22},
    				},
    			},
    			target: map[string]interface{}{
    				"a": "ru",
    				"b": 11,
    				"obj1": map[string]interface{}{
    					"a": "obj1_ru",
    					"b": 22,
    					"obj2": map[string]interface{}{
    						"a": 33,
    						"b": "obj1_obj2_ru",
    					},
    				},
    				"slice": []interface{}{"ru_s3"},
    				"arr": []interface{}{
    					map[string]interface{}{"num": 1},
    					map[string]interface{}{"num": 2},
    				},
    			},
    			want: map[string]interface{}{
    				"a": "ru",
    				"b": 11,
    				"c": "single",
    				"obj1": map[string]interface{}{
    					"a": "obj1_ru",
    					"b": 22,
    					"c": 20,
    					"obj2": map[string]interface{}{
    						"a": 33,
    						"b": "obj1_obj2_ru",
    						"c": "obj1_obj2_single",
    					},
    				},
    				"obj3": map[string]interface{}{
    					"a": "obj3_en",
    				},
    				"slice": []interface{}{"ru_s3"},
    				"arr": []interface{}{
    					map[string]interface{}{"num": 1},
    					map[string]interface{}{"num": 2},
    				},
    			},
    		},
    		{
    			name: "Success singlelocale obj",
    			fallback: map[string]interface{}{
    				"obj3": map[string]interface{}{
    					"a": "obj3_en",
    				},
    			},
    			target: map[string]interface{}{
    				"obj3": map[string]interface{}{
    					"a": "obj3",
    				},
    			},
    			want: map[string]interface{}{
    				"obj3": map[string]interface{}{
    					"a": "obj3_en",
    				},
    			},
    		},
    	}
    	for _, tt := range tests {
    		t.Run(tt.name, func(t *testing.T) {
    			l := &Localizer{
    				schema: s,
    			}
    			got, err := l.localize(tt.target, tt.fallback)
    			if !tt.wantErr {
    				require.NoError(t, err)
    				assert.Equal(t, tt.want, got)
    				return
    			}
    			require.Error(t, err)
    		})
    	}
    }
    
    func TestLocalizer_extractTranslation(t *testing.T) {
    
    	s := schema.New(
    		"a", field.String(),
    		"b", field.Number(field.NumberFormatInt),
    		"c", field.String().SetSingleLocale(true),
    		"obj1", field.Object(
    			"a", field.String(),
    			"b", field.Number(field.NumberFormatInt),
    			"c", field.Number(field.NumberFormatInt).SetSingleLocale(true),
    			"obj2", field.Object(
    				"a", field.Number(field.NumberFormatInt),
    				"b", field.String(),
    				"c", field.String().SetSingleLocale(true),
    			),
    		),
    		"obj3", field.Object(
    			"a", field.String(),
    		).SetSingleLocale(true),
    		"slice", field.Array(field.String()),
    		"arr", field.Array(field.Object(
    			"num", field.Number(field.NumberFormatInt),
    		)),
    	)
    
    	tests := []struct {
    		fallback map[string]interface{}
    		target   map[string]interface{}
    		want     map[string]interface{}
    		name     string
    		wantErr  bool
    	}{
    		{
    			name:     "Nil",
    			fallback: nil,
    			target:   nil,
    			want:     nil,
    		},
    		{
    			name:     "Empty",
    			fallback: map[string]interface{}{},
    			target:   map[string]interface{}{},
    			want:     map[string]interface{}{},
    		},
    		{
    			name: "Target Empty",
    			fallback: map[string]interface{}{
    				"a": "en",
    				"b": 1,
    				"c": "single",
    				"obj1": map[string]interface{}{
    					"a": "obj1_en",
    					"b": 2,
    					"c": 20,
    					"obj2": map[string]interface{}{
    						"a": 3,
    						"b": "obj1_obj2_en",
    						"c": "obj1_obj2_single",
    					},
    				},
    				"obj3": map[string]interface{}{
    					"a": "obj3_en",
    				},
    				"slice": []interface{}{"en_s1", "en_s2"},
    				"arr": []interface{}{
    					map[string]interface{}{"num": 11},
    					map[string]interface{}{"num": 22},
    				},
    			},
    			target: map[string]interface{}{},
    			want:   map[string]interface{}{},
    		},
    		{
    			name:     "Fallback Empty",
    			fallback: map[string]interface{}{},
    			target: map[string]interface{}{
    				"a": "en",
    				"b": 1,
    				"c": "single",
    				"obj1": map[string]interface{}{
    					"a": "obj1_en",
    					"b": 2,
    					"c": 20,
    					"obj2": map[string]interface{}{
    						"a": 3,
    						"b": "obj1_obj2_en",
    						"c": "obj1_obj2_single",
    					},
    				},
    				"obj3": map[string]interface{}{
    					"a": "obj3_en",
    				},
    				"slice": []interface{}{"en_s1", "en_s2"},
    				"arr": []interface{}{
    					map[string]interface{}{"num": 11},
    					map[string]interface{}{"num": 22},
    				},
    			},
    			want: map[string]interface{}{
    				"a": "en",
    				"b": 1,
    				"obj1": map[string]interface{}{
    					"a": "obj1_en",
    					"b": 2,
    					"obj2": map[string]interface{}{
    						"a": 3,
    						"b": "obj1_obj2_en",
    					},
    				},
    				"slice": []interface{}{"en_s1", "en_s2"},
    				"arr": []interface{}{
    					map[string]interface{}{"num": 11},
    					map[string]interface{}{"num": 22},
    				},
    			},
    		},
    		{
    			name: "Equal",
    			fallback: map[string]interface{}{
    				"a": "en",
    				"b": 1,
    				"c": "single",
    				"obj1": map[string]interface{}{
    					"a": "obj1_en",
    					"b": 2,
    					"c": 20,
    					"obj2": map[string]interface{}{
    						"a": 3,
    						"b": "obj1_obj2_en",
    						"c": "obj1_obj2_single",
    					},
    				},
    				"obj3": map[string]interface{}{
    					"a": "obj3_en",
    				},
    				"slice": []interface{}{"en_s1", "en_s2"},
    				"arr": []interface{}{
    					map[string]interface{}{"num": 11},
    					map[string]interface{}{"num": 22},
    				},
    			},
    			target: map[string]interface{}{
    				"a": "en",
    				"b": 1,
    				"c": "single",
    				"obj1": map[string]interface{}{
    					"a": "obj1_en",
    					"b": 2,
    					"c": 20,
    					"obj2": map[string]interface{}{
    						"a": 3,
    						"b": "obj1_obj2_en",
    						"c": "obj1_obj2_single",
    					},
    				},
    				"obj3": map[string]interface{}{
    					"a": "obj3_en",
    				},
    				"slice": []interface{}{"en_s1", "en_s2"},
    				"arr": []interface{}{
    					map[string]interface{}{"num": 11},
    					map[string]interface{}{"num": 22},
    				},
    			},
    			want: map[string]interface{}{},
    		},
    		{
    			name: "Success",
    			fallback: map[string]interface{}{
    				"a": "en",
    				"b": 1,
    				"c": "single",
    				"obj1": map[string]interface{}{
    					"a": "obj1_en",
    					"b": 2,
    					"c": 20,
    					"obj2": map[string]interface{}{
    						"a": 3,
    						"b": "obj1_obj2_en",
    						"c": "obj1_obj2_single",
    					},
    				},
    				"obj3": map[string]interface{}{
    					"a": "obj3_en",
    				},
    				"slice": []interface{}{"en_s1", "en_s2"},
    				"arr": []interface{}{
    					map[string]interface{}{"num": 11},
    					map[string]interface{}{"num": 22},
    				},
    			},
    			target: map[string]interface{}{
    				"a": "ru",
    				"b": 11,
    				"obj1": map[string]interface{}{
    					"a": "obj1_ru",
    					"b": 22,
    					"obj2": map[string]interface{}{
    						"a": 33,
    						"b": "obj1_obj2_ru",
    					},
    				},
    				"slice": []interface{}{"ru_s3"},
    				"arr": []interface{}{
    					map[string]interface{}{"num": 1},
    					map[string]interface{}{"num": 2},
    				},
    			},
    			want: map[string]interface{}{
    				"a": "ru",
    				"b": 11,
    				"obj1": map[string]interface{}{
    					"a": "obj1_ru",
    					"b": 22,
    					"obj2": map[string]interface{}{
    						"a": 33,
    						"b": "obj1_obj2_ru",
    					},
    				},
    				"slice": []interface{}{"ru_s3"},
    				"arr": []interface{}{
    					map[string]interface{}{"num": 1},
    					map[string]interface{}{"num": 2},
    				},
    			},
    		},
    		{
    			name: "Success singlelocale obj",
    			fallback: map[string]interface{}{
    				"obj3": map[string]interface{}{
    					"a": "obj3_en",
    				},
    			},
    			target: map[string]interface{}{
    				"obj3": map[string]interface{}{
    					"a": "obj3_ru",
    				},
    			},
    			want: map[string]interface{}{},
    		},
    	}
    	for _, tt := range tests {
    		t.Run(tt.name, func(t *testing.T) {
    			l := &Localizer{
    				schema: s,
    			}
    			got, err := l.extractTranslation(tt.target, tt.fallback)
    			if !tt.wantErr {
    				require.NoError(t, err)
    				assert.Equal(t, tt.want, got)
    				return
    			}
    			require.Error(t, err)
    		})
    	}
    }
    
    func TestLocalizer_getTargetAndFallBackLocales(t *testing.T) {
    
    	tests := []struct {
    		localizer    *Localizer
    		wantTarget   *locales.Locale
    		wantFallback *locales.Locale
    		name         string
    		wantErr      bool
    	}{
    		{
    			name:      "Empty",
    			localizer: &Localizer{},
    			wantErr:   true,
    		},
    		{
    			name: "Success",
    			localizer: &Localizer{
    				localeID: "en",
    				localesKV: map[string]*locales.Locale{
    					"en":      {ID: "en"},
    					"default": {ID: "default"},
    				},
    			},
    			wantTarget:   &locales.Locale{ID: "en"},
    			wantFallback: &locales.Locale{ID: "default"},
    		},
    		{
    			name: "Success fallback",
    			localizer: &Localizer{
    				localeID: "ru",
    				localesKV: map[string]*locales.Locale{
    					"en":      {ID: "en"},
    					"ru":      {ID: "ru", Fallback: "en"},
    					"default": {ID: "default"},
    				},
    			},
    			wantTarget:   &locales.Locale{ID: "ru", Fallback: "en"},
    			wantFallback: &locales.Locale{ID: "en"},
    		},
    		{
    			name: "Success fallback no default",
    			localizer: &Localizer{
    				localeID: "ru",
    				localesKV: map[string]*locales.Locale{
    					"en": {ID: "en"},
    					"ru": {ID: "ru", Fallback: "en"},
    				},
    			},
    			wantTarget:   &locales.Locale{ID: "ru", Fallback: "en"},
    			wantFallback: &locales.Locale{ID: "en"},
    		},
    		{
    			name: "Success fallback no fallback",
    			localizer: &Localizer{
    				localeID: "ru",
    				localesKV: map[string]*locales.Locale{
    					"ru":      {ID: "ru", Fallback: "en"},
    					"default": {ID: "default"},
    				},
    			},
    			wantTarget:   &locales.Locale{ID: "ru", Fallback: "en"},
    			wantFallback: &locales.Locale{ID: "default"},
    		},
    		{
    			name: "Fail fallback no fallback",
    			localizer: &Localizer{
    				localeID: "ru",
    				localesKV: map[string]*locales.Locale{
    					"ru": {ID: "ru", Fallback: "en"},
    				},
    			},
    			wantErr: true,
    		},
    		{
    			name: "Fail target nil",
    			localizer: &Localizer{
    				localeID: "ru",
    				localesKV: map[string]*locales.Locale{
    					"ru": nil,
    				},
    			},
    			wantErr: true,
    		},
    		{
    			name: "Fail target disabled",
    			localizer: &Localizer{
    				localeID: "ru",
    				localesKV: map[string]*locales.Locale{
    					"ru":      {ID: "ru", Fallback: "en", Disabled: true},
    					"default": {ID: "default"},
    				},
    			},
    			wantErr: true,
    		},
    		{
    			name: "Success fallback disabled",
    			localizer: &Localizer{
    				localeID: "ru",
    				localesKV: map[string]*locales.Locale{
    					"en":      {ID: "en", Disabled: true},
    					"ru":      {ID: "ru", Fallback: "en"},
    					"default": {ID: "default"},
    				},
    			},
    			wantTarget:   &locales.Locale{ID: "ru", Fallback: "en"},
    			wantFallback: &locales.Locale{ID: "default"},
    		},
    		{
    			name: "Fail target no publish",
    			localizer: &Localizer{
    				localeID: "ru",
    				localesKV: map[string]*locales.Locale{
    					"ru":      {ID: "ru", Fallback: "en", NoPublish: true},
    					"default": {ID: "default"},
    				},
    			},
    			wantErr: true,
    		},
    		{
    			name: "Success fallback no publish",
    			localizer: &Localizer{
    				localeID: "ru",
    				localesKV: map[string]*locales.Locale{
    					"en":      {ID: "en", NoPublish: true},
    					"ru":      {ID: "ru", Fallback: "en"},
    					"default": {ID: "default"},
    				},
    			},
    			wantTarget:   &locales.Locale{ID: "ru", Fallback: "en"},
    			wantFallback: &locales.Locale{ID: "en", NoPublish: true},
    		},
    	}
    	for _, tt := range tests {
    		t.Run(tt.name, func(t *testing.T) {
    			gotTarget, gotFallback, err := tt.localizer.getTargetAndFallBackLocales()
    			if tt.wantErr {
    				require.Error(t, err)
    				return
    			}
    			require.NoError(t, err)
    			assert.Equal(t, tt.wantTarget, gotTarget)
    			assert.Equal(t, tt.wantFallback, gotFallback)
    		})
    	}
    }
    
    func TestLocalizer_ExtractTranslations(t *testing.T) {
    
    	s := schema.New(
    		"a", field.String(),
    		"b", field.String(),
    	)
    
    	tests := []struct {
    		data         map[string]interface{}
    		translations map[string]map[string]interface{}
    		want         map[string]interface{}
    		cfg          Config
    		name         string
    		wantErr      bool
    	}{
    		{
    			name:         "Extract default",
    			data:         map[string]interface{}{"a": "bbb"},
    			translations: map[string]map[string]interface{}{"en": {"a": "bbb"}},
    			cfg: Config{
    				LocaleID: "en",
    				Schema:   s,
    				Locales: []*locales.Locale{
    					{ID: "en"},
    					{ID: "default"},
    				},
    			},
    			want: map[string]interface{}{},
    		},
    		{
    			name:         "Extract default not same",
    			data:         map[string]interface{}{"a": "aaa"},
    			translations: map[string]map[string]interface{}{"en": {"a": "bbb"}},
    			cfg: Config{
    				LocaleID: "en",
    				Schema:   s,
    				Locales: []*locales.Locale{
    					{ID: "en"},
    					{ID: "default"},
    				},
    			},
    			want: map[string]interface{}{"a": "bbb"},
    		},
    		{
    			name:         "Extract default empty",
    			data:         map[string]interface{}{"a": "aaa"},
    			translations: map[string]map[string]interface{}{"en": {}},
    			cfg: Config{
    				LocaleID: "en",
    				Schema:   s,
    				Locales: []*locales.Locale{
    					{ID: "en"},
    					{ID: "default"},
    				},
    			},
    			want: map[string]interface{}{},
    		},
    		{
    			name:         "Extract fallback",
    			data:         map[string]interface{}{"a": "aaa"},
    			translations: map[string]map[string]interface{}{"ru": {"a": "bbb"}, "en": {"a": "bbb"}},
    			cfg: Config{
    				LocaleID: "ru",
    				Schema:   s,
    				Locales: []*locales.Locale{
    					{ID: "ru", Fallback: "en"},
    					{ID: "en"},
    					{ID: "default"},
    				},
    			},
    			want: map[string]interface{}{},
    		},
    		{
    			name:         "Extract fallback with extracted field",
    			data:         map[string]interface{}{"a": "aaa"},
    			translations: map[string]map[string]interface{}{"ru": {"a": "bbb"}, "en": {}},
    			cfg: Config{
    				LocaleID: "ru",
    				Schema:   s,
    				Locales: []*locales.Locale{
    					{ID: "ru", Fallback: "en"},
    					{ID: "en"},
    					{ID: "default"},
    				},
    			},
    			want: map[string]interface{}{"a": "bbb"},
    		},
    		{
    			name:         "Extract fallback with empty field",
    			data:         map[string]interface{}{"a": "aaa"},
    			translations: map[string]map[string]interface{}{"ru": {}, "en": {"a": "bbb"}},
    			cfg: Config{
    				LocaleID: "ru",
    				Schema:   s,
    				Locales: []*locales.Locale{
    					{ID: "ru", Fallback: "en"},
    					{ID: "en"},
    					{ID: "default"},
    				},
    			},
    			want: map[string]interface{}{},
    		},
    		{
    			name:         "Extract fallback with same as default",
    			data:         map[string]interface{}{"a": "aaa"},
    			translations: map[string]map[string]interface{}{"ru": {"a": "aaa"}, "en": {"a": "bbb"}},
    			cfg: Config{
    				LocaleID: "ru",
    				Schema:   s,
    				Locales: []*locales.Locale{
    					{ID: "ru", Fallback: "en"},
    					{ID: "en"},
    					{ID: "default"},
    				},
    			},
    			want: map[string]interface{}{"a": "aaa"},
    		},
    		{
    			name:         "Extract fallback with same",
    			data:         map[string]interface{}{"a": "aaa"},
    			translations: map[string]map[string]interface{}{"ru": {"a": "aaa"}, "en": {"a": "aaa", "b": "bbb"}},
    			cfg: Config{
    				LocaleID: "ru",
    				Schema:   s,
    				Locales: []*locales.Locale{
    					{ID: "ru", Fallback: "en"},
    					{ID: "en"},
    					{ID: "default"},
    				},
    			},
    			want: map[string]interface{}{},
    		},
    	}
    	for _, tt := range tests {
    		t.Run(tt.name, func(t *testing.T) {
    			l := NewLocalizer(tt.cfg)
    			got, err := l.ExtractTranslation(tt.data, tt.translations)
    			if !tt.wantErr {
    				require.NoError(t, err)
    				assert.Equal(t, tt.want, got)
    				return
    			}
    			require.Error(t, err)
    		})
    	}
    }