From f1a7214cdd04ce95b339bc91fc30d885e7dd2bc9 Mon Sep 17 00:00:00 2001
From: Anton Sattarov <dirty.mew@gmail.com>
Date: Wed, 10 Jul 2024 13:22:34 +0200
Subject: [PATCH] =?UTF-8?q?=D0=98=D1=81=D0=BF=D1=80=D0=B0=D0=B2=D0=BB?=
 =?UTF-8?q?=D0=B5=D0=BD=D0=B0=20=D0=BE=D1=88=D0=B8=D0=B1=D0=BA=D0=B0=20-?=
 =?UTF-8?q?=20Localizer=20=D1=84=D0=BE=D1=80=D0=BC=D0=B8=D1=80=D0=BE=D0=B2?=
 =?UTF-8?q?=D0=B0=D0=BB=20=D0=BF=D0=B5=D1=80=D0=B5=D0=B2=D0=BE=D0=B4=20?=
 =?UTF-8?q?=D0=B1=D0=B5=D0=B7=20=D1=83=D1=87=D0=B5=D1=82=D0=B0=20=D0=B4?=
 =?UTF-8?q?=D0=B0=D0=BD=D0=BD=D1=8B=D1=85=20=D1=8F=D0=B7=D1=8B=D0=BA=D0=B0?=
 =?UTF-8?q?=20=D0=BF=D0=BE=20=D1=83=D0=BC=D0=BE=D0=BB=D1=87=D0=B0=D0=BD?=
 =?UTF-8?q?=D0=B8=D1=8E?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 perxis-proto                           |   2 +-
 pkg/schema/localizer/localizer.go      |  19 ++--
 pkg/schema/localizer/localizer_test.go | 148 ++++++++++++++++++++++++-
 3 files changed, 159 insertions(+), 10 deletions(-)

diff --git a/perxis-proto b/perxis-proto
index fc23183a..e0a5fab4 160000
--- a/perxis-proto
+++ b/perxis-proto
@@ -1 +1 @@
-Subproject commit fc23183a86463b2aa81e3b7570fad1f873c1e435
+Subproject commit e0a5fab4b9acafc339c182afd64077640c88fecd
diff --git a/pkg/schema/localizer/localizer.go b/pkg/schema/localizer/localizer.go
index 907ade5b..86e43ed4 100644
--- a/pkg/schema/localizer/localizer.go
+++ b/pkg/schema/localizer/localizer.go
@@ -98,19 +98,22 @@ func (l *Localizer) ExtractTranslation(data map[string]interface{}, translations
 		return data, nil
 	}
 
-	fallbackData := data
 	var exist bool
-	if !fallback.IsDefault() {
-		if fallbackData, exist = translations[fallback.ID]; !exist {
-			fallbackData = data
-		}
-	}
-
-	// extract translation fallback -> target
 	if translation, exist = translations[target.ID]; !exist {
 		return make(map[string]interface{}), nil
 	}
 
+	var fallbackData map[string]interface{}
+	if fallbackData, exist = translations[fallback.ID]; !exist {
+		return l.extractTranslation(translation, data)
+	}
+
+	// localize default -> fallback - нужно для корректного сравнения нельзя делать просто extract из прореженных данных fallback
+	if fallbackData, err = l.localize(fallbackData, data); err != nil {
+		return nil, err
+	}
+
+	// extract translation default -> target
 	return l.extractTranslation(translation, fallbackData)
 }
 
diff --git a/pkg/schema/localizer/localizer_test.go b/pkg/schema/localizer/localizer_test.go
index 21b334d4..ded5628d 100644
--- a/pkg/schema/localizer/localizer_test.go
+++ b/pkg/schema/localizer/localizer_test.go
@@ -369,7 +369,7 @@ func TestLocalizer_localize(t *testing.T) {
 	}
 }
 
-func TestLocalizer_deLocalize(t *testing.T) {
+func TestLocalizer_extractTranslation(t *testing.T) {
 
 	s := schema.New(
 		"a", field.String(),
@@ -757,3 +757,149 @@ func TestLocalizer_getTargetAndFallBackLocales(t *testing.T) {
 		})
 	}
 }
+
+func TestLocalizer_ExtractTranslations(t *testing.T) {
+
+	s := schema.New(
+		"a", 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"}},
+			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)
+		})
+	}
+}
-- 
GitLab