diff --git a/pkg/items/item.go b/pkg/items/item.go
index 52cc0e36d4fe38892c7c8bba0f080803236a339a..c0a0ef935f60e14a5c2543e2fac98f1a9a52c41e 100644
--- a/pkg/items/item.go
+++ b/pkg/items/item.go
@@ -3,14 +3,13 @@ package items
 import (
 	"context"
 	"fmt"
+	"reflect"
 	"time"
 
 	"git.perx.ru/perxis/perxis-go/pkg/data"
 	"git.perx.ru/perxis/perxis-go/pkg/errors"
-	"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"
-	"git.perx.ru/perxis/perxis-go/pkg/schema/localizer"
 	pb "git.perx.ru/perxis/perxis-go/proto/items"
 	"google.golang.org/protobuf/types/known/structpb"
 	"google.golang.org/protobuf/types/known/timestamppb"
@@ -162,21 +161,23 @@ func (i *Item) ToMap() map[string]interface{} {
 	}
 }
 
-func (i *Item) SetData(data map[string]interface{}, localizer *localizer.Localizer) (err error) {
-	if localizer != nil && localizer.LocaleID != locales.DefaultID {
-		i.Translations[localizer.LocaleID], err = localizer.ExtractTranslation(i.Data, i.Translations)
+func (i *Item) SetData(locale string, data map[string]interface{}) {
+	if locale != "" {
+		if i.Translations == nil {
+			i.Translations = make(map[string]map[string]interface{})
+		}
+		i.Translations[locale] = data
 		return
 	}
-
 	i.Data = data
-	return
 }
 
-func (i *Item) GetData(localizer *localizer.Localizer) (map[string]interface{}, error) {
-	if localizer != nil {
-		return localizer.Localize(i.Data, i.Translations)
+func (i *Item) GetData(locale string) map[string]interface{} {
+	if locale != "" && i.Translations != nil {
+		translation := i.Translations[locale]
+		return MergeData(i.Data, translation)
 	}
-	return i.Data, nil
+	return i.Data
 }
 
 func (i Item) Encode(ctx context.Context, s *schema.Schema) (*Item, error) {
@@ -214,9 +215,40 @@ func (i Item) Decode(ctx context.Context, s *schema.Schema) (res *Item, err erro
 	return &i, nil
 }
 
+// MergeData дополняет отсутствующие данные из оригинальных данных
+func MergeData(data ...map[string]interface{}) map[string]interface{} {
+	merge := make(map[string]interface{})
+	for _, d := range data {
+		for k, v := range d {
+			merge[k] = v
+		}
+	}
+	return merge
+}
+
+// ClearData убирает данные которые не изменились по сравнению с оригинальными данными
+func ClearData(data ...map[string]interface{}) map[string]interface{} {
+	var clear map[string]interface{}
+
+	for _, d := range data {
+		if clear == nil {
+			clear = d
+			continue
+		}
+
+		for k, v := range d {
+			if reflect.DeepEqual(clear[k], v) {
+				delete(clear, k)
+			}
+		}
+	}
+
+	return clear
+}
+
 type ProcessDataFunc func(ctx context.Context, sch *schema.Schema, data map[string]interface{}) (map[string]interface{}, error)
 
-func (i Item) ProcessData(ctx context.Context, sch *schema.Schema, fn ProcessDataFunc, locales ...*locales.Locale) (*Item, error) {
+func (i Item) ProcessData(ctx context.Context, sch *schema.Schema, fn ProcessDataFunc, locales ...string) (*Item, error) {
 	if i.Data != nil {
 		dt, err := fn(ctx, sch, i.Data)
 		if err != nil {
@@ -227,16 +259,14 @@ func (i Item) ProcessData(ctx context.Context, sch *schema.Schema, fn ProcessDat
 
 	tr := make(map[string]map[string]interface{})
 	for _, l := range locales {
-		data, err := i.GetData(localizer.NewLocalizer(sch, locales, l.ID))
-		if err != nil {
-			return nil, errors.WithField(err, fmt.Sprintf("translations.%s", l.ID))
-		}
+
+		data := i.GetData(l)
 
 		dt, err := fn(ctx, sch, data)
 		if err != nil {
-			return nil, errors.WithField(err, fmt.Sprintf("translations.%s", l.ID))
+			return nil, errors.WithField(err, fmt.Sprintf("translations.%s", l))
 		}
-		tr[l.ID] = dt
+		tr[l] = dt
 
 	}