Repository: codingedward/flask-sieve

Issue:
Custom message in manual validation
Hi bro, 
I do not see that we can custom messages in docs in manual validation mode. 

Can you add these features? 
this what I need. 

Comments:

Patch:
diff --git a/docs/source/index.md b/docs/source/index.md
index fedf4c7..8a4e9ce 100644
--- a/docs/source/index.md
+++ b/docs/source/index.md
@@ -112,7 +112,11 @@ def register():
         'avatar': ['image', 'dimensions:200x200'],
         'username': ['required', 'string', 'min:6'],
     }
-    validator = Validator(rules=rules, request=request)
+    messages = {
+        'email.required': 'Yikes! The email is required',
+        'avatar.dimensions': 'Please provide an avatar with the right dimensions'
+    }
+    validator = Validator(rules=rules, messages=messages, request=request)
     if validator.passes():
         return jsonify({'message': 'Registered!'}), 200
     return jsonify(validator.messages()), 400
diff --git a/flask_sieve/translator.py b/flask_sieve/translator.py
index c57d3d0..12fdc1e 100644
--- a/flask_sieve/translator.py
+++ b/flask_sieve/translator.py
@@ -26,9 +26,9 @@ class Translator:
             translated = []
             for validation in validations:
                 if not validation['is_valid']:
-                    custom_message_key = validation['attribute'] + '.' + validation['rule']
-                    if custom_message_key in self._custom_messages:
-                        translated.append(self._custom_messages[custom_message_key])
+                    validation_key = validation['attribute'] + '.' + validation['rule']
+                    if validation_key in self._custom_messages:
+                        translated.append(self._custom_messages[validation_key])
                     else:
                         translated.append(self._translate_validation(validation))
             if len(translated):
@@ -41,13 +41,13 @@ class Translator:
         if validation['rule'] in self._size_rules:
             message = message[validation['attribute_type']]
         message_fields = self._extract_message_fields(message)
-        fields_to_params = self._zip_fields_to_params(
-            fields=message_fields,
-            params=validation['params']
-        )
+        fields_to_params = \
+            self._zip_fields_to_params(fields=message_fields,
+                                       params=validation['params'])
         for field in message_fields:
             if field == ':attribute':
-                message = message.replace(field, validation['attribute'])
+                message = message.replace(field, ' '.join([word for word in
+                        validation['attribute'].split('_') if word != '']))
             else:
                 message = message.replace(field, fields_to_params[field])
         return message
diff --git a/flask_sieve/validator.py b/flask_sieve/validator.py
index 0c205c0..17eaf6e 100644
--- a/flask_sieve/validator.py
+++ b/flask_sieve/validator.py
@@ -8,9 +8,10 @@ from flask_sieve.rules_processor import RulesProcessor
 
 
 class Validator:
-    def __init__(self, rules=None, request=None, custom_handlers=None):
+    def __init__(self, rules=None, request=None, custom_handlers=None,
+            messages=None, **kwargs):
         self._parser = Parser()
-        self._translator = Translator()
+        self._translator = Translator(custom_messages=messages)
         self._processor = RulesProcessor()
         self._rules = rules or {}
         self._custom_handlers = custom_handlers or {}
diff --git a/setup.py b/setup.py
index adc5945..c8e2469 100644
--- a/setup.py
+++ b/setup.py
@@ -5,7 +5,7 @@ setup(
     name='flask-sieve',
     description='A Laravel inspired requests validator for Flask',
     long_description='Find the documentation at https://flask-sieve.readthedocs.io/en/latest/',
-    version='1.2.0',
+    version='1.2.1',
     url='https://github.com/codingedward/flask-sieve',
     license='BSD-2',
     author='Edward Njoroge',


Test patch:
diff --git a/tests/test_validator.py b/tests/test_validator.py
index a29371a..d41ebd9 100644
--- a/tests/test_validator.py
+++ b/tests/test_validator.py
@@ -11,19 +11,20 @@ class TestValidator(unittest.TestCase):
 
     def test_translates_validations(self):
         self.set_validator_params(
-            rules={'email': ['required', 'email']},
-            request={'email': 'invalid_email'},
+            rules={'email_address': ['required', 'email']},
+            request={'email_address': 'invalid_email'},
         )
         self.assertTrue(self._validator.fails())
-        self.assertIn('valid email', str(self._validator.messages()))
+        self.assertIn('valid email address', str(self._validator.messages()))
 
     def test_translates_validations_with_param(self):
         self.set_validator_params(
-            rules={'name': ['required', 'string', 'min:6']},
-            request={'name': 'joe'},
+            rules={'first_name': ['required', 'string', 'min:6']},
+            request={'first_name': 'joe'},
         )
         self.assertTrue(self._validator.fails())
         self.assertIn('6 characters', str(self._validator.messages()))
+        self.assertIn('first name', str(self._validator.messages()))
 
     def test_translates_validations_with_rest_params(self):
         self.set_validator_params(
@@ -95,6 +96,23 @@ class TestValidator(unittest.TestCase):
             ]
         }, self._validator.messages())
 
+    def test_translates_validations_with_custom_messages_on_constructor(self):
+        validator = Validator(
+            rules={'email': ['required', 'email']},
+            request={'email': ''},
+            messages={
+                'email.required': 'Kindly provide the email',
+                'email.email': 'Whoa! That is not valid',
+            }
+        )
+        self.assertTrue(validator.fails())
+        self.assertDictEqual({
+            'email': [
+                'Kindly provide the email',
+                'Whoa! That is not valid'
+            ]
+        }, validator.messages())
+
     def test_translates_validations_with_custom_handler(self):
         def validate_odd(value, **kwargs):
             return int(value) % 2