diff --git a/pkg/expr/mongo.go b/pkg/expr/mongo.go
index bb4187dda74adce707798781b77d23a648db0eb1..5a503a7ee76eaa7a7d0197b955868a298b5fad73 100644
--- a/pkg/expr/mongo.go
+++ b/pkg/expr/mongo.go
@@ -23,6 +23,7 @@ var geoTypes = map[string]string{
 type MongoExprConfig struct {
 	Env                map[string]any
 	IdentifierRenameFn func(s string) string
+	Visitors           []ast.Visitor
 	Ops                []expr.Option
 }
 
@@ -55,6 +56,7 @@ func convertToMongo(ctx context.Context, config *MongoExprConfig, tree *parser.T
 
 	env[EnvContextKey] = ctx
 	exprConfig := GetDefaultConfig(env)
+	exprConfig.Visitors = config.Visitors
 
 	for _, op := range config.Ops {
 		op(exprConfig)
@@ -62,13 +64,16 @@ func convertToMongo(ctx context.Context, config *MongoExprConfig, tree *parser.T
 
 	env = exprConfig.Env.(map[string]interface{})
 
-	if len(exprConfig.Visitors) >= 0 {
-		for _, v := range exprConfig.Visitors {
-			ast.Walk(&tree.Node, v)
-		}
+	c := &compiler{
+		tree:               tree,
+		env:                env,
+		config:             exprConfig,
+		identifierRenameFn: config.IdentifierRenameFn,
+		visitors:           config.Visitors,
+	}
+	for _, v := range c.visitors {
+		ast.Walk(&tree.Node, v)
 	}
-
-	c := &compiler{tree: tree, env: env, config: exprConfig, identifierRenameFn: config.IdentifierRenameFn}
 	v, ok := c.compile(tree.Node).(bson.M)
 	if !ok || v == nil {
 		return nil, fmt.Errorf("invalid expression")
@@ -81,6 +86,7 @@ type compiler struct {
 	tree               *parser.Tree
 	config             *conf.Config
 	identifierRenameFn func(string) string
+	visitors           []ast.Visitor
 }
 
 func (c *compiler) eval(node ast.Node) interface{} {
@@ -162,43 +168,43 @@ func (c *compiler) IdentifierNode(node *ast.IdentifierNode) string {
 
 func (c *compiler) IntegerNode(node *ast.IntegerNode) int {
 	return node.Value
-	//t := node.Type()
-	//if t == nil {
+	// t := node.Type()
+	// if t == nil {
 	//	c.emitPush(node.Value)
 	//	return
-	//}
+	// }
 	//
-	//switch t.Kind() {
-	//case reflect.Float32:
+	// switch t.Kind() {
+	// case reflect.Float32:
 	//	c.emitPush(float32(node.Value))
-	//case reflect.Float64:
+	// case reflect.Float64:
 	//	c.emitPush(float64(node.Value))
 	//
-	//case reflect.Int:
+	// case reflect.Int:
 	//	c.emitPush(int(node.Value))
-	//case reflect.Int8:
+	// case reflect.Int8:
 	//	c.emitPush(int8(node.Value))
-	//case reflect.Int16:
+	// case reflect.Int16:
 	//	c.emitPush(int16(node.Value))
-	//case reflect.Int32:
+	// case reflect.Int32:
 	//	c.emitPush(int32(node.Value))
-	//case reflect.Int64:
+	// case reflect.Int64:
 	//	c.emitPush(int64(node.Value))
 	//
-	//case reflect.Uint:
+	// case reflect.Uint:
 	//	c.emitPush(uint(node.Value))
-	//case reflect.Uint8:
+	// case reflect.Uint8:
 	//	c.emitPush(uint8(node.Value))
-	//case reflect.Uint16:
+	// case reflect.Uint16:
 	//	c.emitPush(uint16(node.Value))
-	//case reflect.Uint32:
+	// case reflect.Uint32:
 	//	c.emitPush(uint32(node.Value))
-	//case reflect.Uint64:
+	// case reflect.Uint64:
 	//	c.emitPush(uint64(node.Value))
 	//
-	//default:
+	// default:
 	//	c.emitPush(node.Value)
-	//}
+	// }
 }
 
 func (c *compiler) FloatNode(node *ast.FloatNode) float64 {
@@ -277,32 +283,32 @@ func (c *compiler) BinaryNode(node *ast.BinaryNode) interface{} {
 	case ">=":
 		return bson.M{c.identifier(node.Left): bson.M{"$gte": c.eval(node.Right)}}
 
-	//case "+":
+	// case "+":
 	//	c.compile(node.Left)
 	//	c.compile(node.Right)
 	//	c.emit(OpAdd)
 	//
-	//case "-":
+	// case "-":
 	//	c.compile(node.Left)
 	//	c.compile(node.Right)
 	//	c.emit(OpSubtract)
 	//
-	//case "*":
+	// case "*":
 	//	c.compile(node.Left)
 	//	c.compile(node.Right)
 	//	c.emit(OpMultiply)
 	//
-	//case "/":
+	// case "/":
 	//	c.compile(node.Left)
 	//	c.compile(node.Right)
 	//	c.emit(OpDivide)
 	//
-	//case "%":
+	// case "%":
 	//	c.compile(node.Left)
 	//	c.compile(node.Right)
 	//	c.emit(OpModulo)
 	//
-	//case "**":
+	// case "**":
 	//	c.compile(node.Left)
 	//	c.compile(node.Right)
 	//	c.emit(OpExponent)
@@ -454,26 +460,26 @@ func (c *compiler) CallNode(node *ast.CallNode) interface{} {
 		return bson.M{v: bson.M{"$regex": fmt.Sprintf(".*%s$", regexp.QuoteMeta(t)), "$options": "i"}}
 	}
 	panic("unsupported function")
-	//for _, arg := range node.Arguments {
+	// for _, arg := range node.Arguments {
 	//	c.compile(arg)
-	//}
-	//op := OpCall
-	//if node.Fast {
+	// }
+	// op := OpCall
+	// if node.Fast {
 	//	op = OpCallFast
-	//}
-	//c.emit(op, c.makeConstant(Call{Name: node.Name, Size: len(node.Arguments)})...)
+	// }
+	// c.emit(op, c.makeConstant(Call{Name: node.Name, Size: len(node.Arguments)})...)
 }
 
 func (c *compiler) BuiltinNode(node *ast.BuiltinNode) interface{} {
 	panic("unsupported builin node")
-	//switch node.Name {
-	//case "len":
+	// switch node.Name {
+	// case "len":
 	//	c.compile(node.Arguments[0])
 	//	c.emit(OpLen)
 	//	c.emit(OpRot)
 	//	c.emit(OpPop)
 	//
-	//case "all":
+	// case "all":
 	//	c.compile(node.Arguments[0])
 	//	c.emit(OpBegin)
 	//	var loopBreak int
@@ -486,7 +492,7 @@ func (c *compiler) BuiltinNode(node *ast.BuiltinNode) interface{} {
 	//	c.patchJump(loopBreak)
 	//	c.emit(OpEnd)
 	//
-	//case "none":
+	// case "none":
 	//	c.compile(node.Arguments[0])
 	//	c.emit(OpBegin)
 	//	var loopBreak int
@@ -500,7 +506,7 @@ func (c *compiler) BuiltinNode(node *ast.BuiltinNode) interface{} {
 	//	c.patchJump(loopBreak)
 	//	c.emit(OpEnd)
 	//
-	//case "any":
+	// case "any":
 	//	c.compile(node.Arguments[0])
 	//	c.emit(OpBegin)
 	//	var loopBreak int
@@ -513,7 +519,7 @@ func (c *compiler) BuiltinNode(node *ast.BuiltinNode) interface{} {
 	//	c.patchJump(loopBreak)
 	//	c.emit(OpEnd)
 	//
-	//case "one":
+	// case "one":
 	//	count := c.makeConstant("count")
 	//	c.compile(node.Arguments[0])
 	//	c.emit(OpBegin)
@@ -530,7 +536,7 @@ func (c *compiler) BuiltinNode(node *ast.BuiltinNode) interface{} {
 	//	c.emit(OpEqual)
 	//	c.emit(OpEnd)
 	//
-	//case "filter":
+	// case "filter":
 	//	count := c.makeConstant("count")
 	//	c.compile(node.Arguments[0])
 	//	c.emit(OpBegin)
@@ -550,7 +556,7 @@ func (c *compiler) BuiltinNode(node *ast.BuiltinNode) interface{} {
 	//	c.emit(OpEnd)
 	//	c.emit(OpArray)
 	//
-	//case "map":
+	// case "map":
 	//	c.compile(node.Arguments[0])
 	//	c.emit(OpBegin)
 	//	size := c.emitLoop(func() {
@@ -560,7 +566,7 @@ func (c *compiler) BuiltinNode(node *ast.BuiltinNode) interface{} {
 	//	c.emit(OpEnd)
 	//	c.emit(OpArray)
 	//
-	//case "count":
+	// case "count":
 	//	count := c.makeConstant("count")
 	//	c.compile(node.Arguments[0])
 	//	c.emit(OpBegin)
@@ -575,12 +581,12 @@ func (c *compiler) BuiltinNode(node *ast.BuiltinNode) interface{} {
 	//	c.emit(OpLoad, count...)
 	//	c.emit(OpEnd)
 	//
-	//default:
+	// default:
 	//	panic(fmt.Sprintf("unknown builtin %v", node.Name))
-	//}
+	// }
 }
 
-//func (c *compiler) emitLoop(body func()) []byte {
+// func (c *compiler) emitLoop(body func()) []byte {
 //	i := c.makeConstant("i")
 //	size := c.makeConstant("size")
 //	array := c.makeConstant("array")
@@ -607,7 +613,7 @@ func (c *compiler) BuiltinNode(node *ast.BuiltinNode) interface{} {
 //	c.emit(OpPop)
 //
 //	return size
-//}
+// }
 
 func (c *compiler) ClosureNode(node *ast.ClosureNode) interface{} {
 	return c.compile(node.Node)
@@ -615,25 +621,25 @@ func (c *compiler) ClosureNode(node *ast.ClosureNode) interface{} {
 
 func (c *compiler) PointerNode(node *ast.PointerNode) interface{} {
 	panic("unsupported pointer node")
-	//c.emit(OpLoad, c.makeConstant("array")...)
-	//c.emit(OpLoad, c.makeConstant("i")...)
-	//c.emit(OpIndex)
+	// c.emit(OpLoad, c.makeConstant("array")...)
+	// c.emit(OpLoad, c.makeConstant("i")...)
+	// c.emit(OpIndex)
 }
 
 func (c *compiler) ConditionalNode(node *ast.ConditionalNode) interface{} {
 	panic("unsupported conditional node")
-	//c.compile(node.Cond)
-	//otherwise := c.emit(OpJumpIfFalse, c.placeholder()...)
+	// c.compile(node.Cond)
+	// otherwise := c.emit(OpJumpIfFalse, c.placeholder()...)
 	//
-	//c.emit(OpPop)
-	//c.compile(node.Exp1)
-	//end := c.emit(OpJump, c.placeholder()...)
+	// c.emit(OpPop)
+	// c.compile(node.Exp1)
+	// end := c.emit(OpJump, c.placeholder()...)
 	//
-	//c.patchJump(otherwise)
-	//c.emit(OpPop)
-	//c.compile(node.Exp2)
+	// c.patchJump(otherwise)
+	// c.emit(OpPop)
+	// c.compile(node.Exp2)
 	//
-	//c.patchJump(end)
+	// c.patchJump(end)
 }
 
 func (c *compiler) VariableDeclaratorNode(node *ast.VariableDeclaratorNode) int {
@@ -642,28 +648,28 @@ func (c *compiler) VariableDeclaratorNode(node *ast.VariableDeclaratorNode) int
 
 func (c *compiler) ArrayNode(node *ast.ArrayNode) interface{} {
 	panic("unsupported array node")
-	//for _, node := range node.Nodes {
+	// for _, node := range node.Nodes {
 	//	c.compile(node)
-	//}
+	// }
 	//
-	//c.emitPush(len(node.Nodes))
-	//c.emit(OpArray)
+	// c.emitPush(len(node.Nodes))
+	// c.emit(OpArray)
 }
 
 func (c *compiler) MapNode(node *ast.MapNode) interface{} {
 	panic("unsupported map node")
-	//for _, pair := range node.Pairs {
+	// for _, pair := range node.Pairs {
 	//	c.compile(pair)
-	//}
+	// }
 	//
-	//c.emitPush(len(node.Pairs))
-	//c.emit(OpMap)
+	// c.emitPush(len(node.Pairs))
+	// c.emit(OpMap)
 }
 
 func (c *compiler) PairNode(node *ast.PairNode) interface{} {
 	panic("unsupported pair node")
-	//c.compile(node.Key)
-	//c.compile(node.Value)
+	// c.compile(node.Key)
+	// c.compile(node.Value)
 }
 
 // handleLenNode получает узел AST и возвращает запрос для mongo,
@@ -731,6 +737,9 @@ func (c *compiler) handleTryNode(node *ast.CallNode) (result interface{}) {
 	if err != nil {
 		panic(err)
 	}
+	for _, v := range c.visitors {
+		ast.Walk(&tree.Node, v)
+	}
 	subcompiler := &compiler{tree: tree, env: c.env, config: c.config, identifierRenameFn: c.identifierRenameFn}
 	result = subcompiler.compile(tree.Node).(bson.M)
 	return
diff --git a/pkg/schema/schema.go b/pkg/schema/schema.go
index 4fec4c174684745be718abf4c2a595f7fe1ae3fe..bb91b4203cf6c7e44991a41f5bdc31294aeedb4d 100644
--- a/pkg/schema/schema.go
+++ b/pkg/schema/schema.go
@@ -111,6 +111,11 @@ func (s Schema) SetMetadata(md map[string]string) *Schema {
 	return &s
 }
 
+func (f Schema) SetSingleLocale(r bool) *Schema {
+	f.SingleLocale = r
+	return &f
+}
+
 func (s *Schema) ConvertTypes() error {
 	b, err := s.MarshalJSON()
 	if err != nil {