Browse Source

#385, #387: Provide the default error messages; Support I18n

phuoc 11 years ago
parent
commit
d2bdaf9b3a

+ 2 - 0
CHANGELOG.md

@@ -3,6 +3,8 @@
 ## v0.5.0 (not released yet) - It will be the big release
 
 __New Features__
+* [#2](https://github.com/nghuuphuoc/bootstrapvalidator/issues/2), [#387](https://github.com/nghuuphuoc/bootstrapvalidator/issues/387): Provide the default error messages
+* [#93](https://github.com/nghuuphuoc/bootstrapvalidator/issues/93), [#385](https://github.com/nghuuphuoc/bootstrapvalidator/issues/385): Support translating error messages
 * [#121](https://github.com/nghuuphuoc/bootstrapvalidator/issues/121): Add events for form validate successfully or not
 * [#125](https://github.com/nghuuphuoc/bootstrapvalidator/issues/125): Support dynamic fields
 * [#130](https://github.com/nghuuphuoc/bootstrapvalidator/pull/130): Add ```addField()``` and ```removeField()``` methods for managing dynamic fields, thanks to [@jcnmulio](https://github.com/jcnmulio)

+ 322 - 0
demo/i18n.html

@@ -0,0 +1,322 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <title>BootstrapValidator demo</title>
+
+    <link rel="stylesheet" href="../vendor/bootstrap/css/bootstrap.css"/>
+    <link rel="stylesheet" href="../dist/css/bootstrapValidator.css"/>
+
+    <!-- Include the FontAwesome CSS if you want to use feedback icons provided by FontAwesome -->
+    <!--<link rel="stylesheet" href="http://netdna.bootstrapcdn.com/font-awesome/4.0.3/css/font-awesome.css" />-->
+
+    <script type="text/javascript" src="../vendor/jquery/jquery-1.10.2.min.js"></script>
+    <script type="text/javascript" src="../vendor/bootstrap/js/bootstrap.min.js"></script>
+    <script type="text/javascript" src="../dist/js/bootstrapValidator.js"></script>
+</head>
+<body>
+    <div class="container">
+        <div class="row">
+            <!-- form: -->
+            <section>
+                <div class="col-lg-8 col-lg-offset-2">
+                    <div class="page-header">
+                        <h2>Sign up</h2>
+                    </div>
+
+                    <form id="defaultForm" method="post" class="form-horizontal" action="target.php">
+                        <div class="form-group">
+                            <label class="col-lg-3 control-label">Full name</label>
+                            <div class="col-lg-4">
+                                <input type="text" class="form-control" name="firstName" placeholder="First name" />
+                            </div>
+                            <div class="col-lg-4">
+                                <input type="text" class="form-control" name="lastName" placeholder="Last name" />
+                            </div>
+                        </div>
+
+                        <div class="form-group">
+                            <label class="col-lg-3 control-label">Username</label>
+                            <div class="col-lg-5">
+                                <input type="text" class="form-control" name="username" />
+                            </div>
+                        </div>
+
+                        <div class="form-group">
+                            <label class="col-lg-3 control-label">Email address</label>
+                            <div class="col-lg-5">
+                                <input type="text" class="form-control" name="email" />
+                            </div>
+                        </div>
+
+                        <div class="form-group">
+                            <label class="col-lg-3 control-label">Password</label>
+                            <div class="col-lg-5">
+                                <input type="password" class="form-control" name="password" />
+                            </div>
+                        </div>
+
+                        <div class="form-group">
+                            <label class="col-lg-3 control-label">Retype password</label>
+                            <div class="col-lg-5">
+                                <input type="password" class="form-control" name="confirmPassword" />
+                            </div>
+                        </div>
+
+                        <div class="form-group">
+                            <label class="col-lg-3 control-label">Gender</label>
+                            <div class="col-lg-5">
+                                <div class="radio">
+                                    <label>
+                                        <input type="radio" name="gender" value="male" /> Male
+                                    </label>
+                                </div>
+                                <div class="radio">
+                                    <label>
+                                        <input type="radio" name="gender" value="female" /> Female
+                                    </label>
+                                </div>
+                                <div class="radio">
+                                    <label>
+                                        <input type="radio" name="gender" value="other" /> Other
+                                    </label>
+                                </div>
+                            </div>
+                        </div>
+
+                        <div class="form-group">
+                            <label class="col-lg-3 control-label">Birthday</label>
+                            <div class="col-lg-5">
+                                <input type="text" class="form-control" name="birthday" /> (YYYY/MM/DD)
+                            </div>
+                        </div>
+
+                        <div class="form-group">
+                            <label class="col-lg-3 control-label">Languages</label>
+                            <div class="col-lg-5">
+                                <div class="checkbox">
+                                    <label>
+                                        <input type="checkbox" name="languages[]" value="english" /> English
+                                    </label>
+                                </div>
+                                <div class="checkbox">
+                                    <label>
+                                        <input type="checkbox" name="languages[]" value="french" /> French
+                                    </label>
+                                </div>
+                                <div class="checkbox">
+                                    <label>
+                                        <input type="checkbox" name="languages[]" value="german" /> German
+                                    </label>
+                                </div>
+                                <div class="checkbox">
+                                    <label>
+                                        <input type="checkbox" name="languages[]" value="russian" /> Russian
+                                    </label>
+                                </div>
+                                <div class="checkbox">
+                                    <label>
+                                        <input type="checkbox" name="languages[]" value="other" /> Other
+                                    </label>
+                                </div>
+                            </div>
+                        </div>
+
+                        <div class="form-group">
+                            <label class="col-lg-3 control-label">Programming Languages</label>
+                            <div class="col-lg-5">
+                                <div class="checkbox">
+                                    <label>
+                                        <input type="checkbox" name="programs[]" value="net" /> .Net
+                                    </label>
+                                </div>
+                                <div class="checkbox">
+                                    <label>
+                                        <input type="checkbox" name="programs[]" value="java" /> Java
+                                    </label>
+                                </div>
+                                <div class="checkbox">
+                                    <label>
+                                        <input type="checkbox" name="programs[]" value="c" /> C/C++
+                                    </label>
+                                </div>
+                                <div class="checkbox">
+                                    <label>
+                                        <input type="checkbox" name="programs[]" value="php" /> PHP
+                                    </label>
+                                </div>
+                                <div class="checkbox">
+                                    <label>
+                                        <input type="checkbox" name="programs[]" value="perl" /> Perl
+                                    </label>
+                                </div>
+                                <div class="checkbox">
+                                    <label>
+                                        <input type="checkbox" name="programs[]" value="ruby" /> Ruby
+                                    </label>
+                                </div>
+                                <div class="checkbox">
+                                    <label>
+                                        <input type="checkbox" name="programs[]" value="python" /> Python
+                                    </label>
+                                </div>
+                                <div class="checkbox">
+                                    <label>
+                                        <input type="checkbox" name="programs[]" value="javascript" /> Javascript
+                                    </label>
+                                </div>
+                            </div>
+                        </div>
+
+                        <div class="form-group">
+                            <label class="col-lg-3 control-label" id="captchaOperation"></label>
+                            <div class="col-lg-2">
+                                <input type="text" class="form-control" name="captcha" />
+                            </div>
+                        </div>
+
+                        <div class="form-group">
+                            <div class="col-lg-9 col-lg-offset-3">
+                                <button type="submit" class="btn btn-primary" name="signup" value="Sign up">Sign up</button>
+                                <button type="submit" class="btn btn-primary" name="signup2" value="Sign up 2">Sign up 2</button>
+                                <button type="button" class="btn btn-info" id="validateBtn">Manual validate</button>
+                                <button type="button" class="btn btn-info" id="resetBtn">Reset form</button>
+                            </div>
+                        </div>
+                    </form>
+                </div>
+            </section>
+            <!-- :form -->
+        </div>
+    </div>
+
+<script type="text/javascript">
+$(document).ready(function() {
+    // Generate a simple captcha
+    function randomNumber(min, max) {
+        return Math.floor(Math.random() * (max - min + 1) + min);
+    };
+    $('#captchaOperation').html([randomNumber(1, 100), '+', randomNumber(1, 200), '='].join(' '));
+
+    $('#defaultForm').bootstrapValidator({
+        message: 'This value is not valid',
+        feedbackIcons: {
+            valid: 'glyphicon glyphicon-ok',
+            invalid: 'glyphicon glyphicon-remove',
+            validating: 'glyphicon glyphicon-refresh'
+        },
+        fields: {
+            firstName: {
+                validators: {
+                    notEmpty: {}
+                }
+            },
+            lastName: {
+                validators: {
+                    notEmpty: {}
+                }
+            },
+            username: {
+                message: 'The username is not valid',
+                validators: {
+                    notEmpty: {},
+                    stringLength: {
+                        min: 6,
+                        max: 20
+                    },
+                    regexp: {
+                        regexp: /^[a-zA-Z0-9_\.]+$/,
+                        message: 'The username can only consist of alphabetical, number, dot and underscore'
+                    },
+                    remote: {
+                        url: 'remote.php',
+                        message: 'The username is not available'
+                    },
+                    different: {
+                        field: 'password',
+                        message: 'The username and password cannot be the same as each other'
+                    }
+                }
+            },
+            email: {
+                validators: {
+                    emailAddress: {}
+                }
+            },
+            password: {
+                validators: {
+                    notEmpty: {},
+                    identical: {
+                        field: 'confirmPassword',
+                        message: 'The password and its confirm are not the same'
+                    },
+                    different: {
+                        field: 'username',
+                        message: 'The password cannot be the same as username'
+                    }
+                }
+            },
+            confirmPassword: {
+                validators: {
+                    notEmpty: {},
+                    identical: {
+                        field: 'password',
+                        message: 'The password and its confirm are not the same'
+                    },
+                    different: {
+                        field: 'username',
+                        message: 'The password cannot be the same as username'
+                    }
+                }
+            },
+            birthday: {
+                validators: {
+                    date: {
+                        format: 'YYYY/MM/DD',
+                        message: 'The birthday is not valid'
+                    }
+                }
+            },
+            gender: {
+                validators: {
+                    notEmpty: {}
+                }
+            },
+            'languages[]': {
+                validators: {
+                    notEmpty: {}
+                }
+            },
+            'programs[]': {
+                validators: {
+                    choice: {
+                        min: 2,
+                        max: 4
+                    }
+                }
+            },
+            captcha: {
+                validators: {
+                    callback: {
+                        message: 'Wrong answer',
+                        callback: function(value, validator) {
+                            var items = $('#captchaOperation').html().split(' '), sum = parseInt(items[0]) + parseInt(items[2]);
+                            return value == sum;
+                        }
+                    }
+                }
+            }
+        }
+    });
+
+    // Validate the form manually
+    $('#validateBtn').click(function() {
+        $('#defaultForm').bootstrapValidator('validate');
+    });
+
+    $('#resetBtn').click(function() {
+        $('#defaultForm').data('bootstrapValidator').resetForm(true);
+    });
+});
+</script>
+</body>
+</html>

+ 202 - 1
dist/js/bootstrapValidator.js

@@ -255,7 +255,7 @@
                             .attr('data-bv-validator', validatorName)
                             .attr('data-bv-for', field)
                             .attr('data-bv-result', this.STATUS_NOT_VALIDATED)
-                            .html(this.options.fields[field].validators[validatorName].message || this.options.fields[field].message || this.options.message)
+                            .html(this._getMessage(field, validatorName))
                             .appendTo($message);
                     }
                 }
@@ -319,6 +319,35 @@
         },
 
         /**
+         * Get the error message for given field and validator
+         *
+         * @param {String} field The field name
+         * @param {String} validatorName The validator name
+         * @returns {String}
+         */
+        _getMessage: function(field, validatorName) {
+            if (!this.options.fields[field] || !$.fn.bootstrapValidator.validators[validatorName]
+                || !this.options.fields[field].validators || !this.options.fields[field].validators[validatorName])
+            {
+                return '';
+            }
+
+            var options = this.options.fields[field].validators[validatorName];
+            switch (true) {
+                case (!!options.message):
+                    return options.message;
+                case (!!$.fn.bootstrapValidator.i18n[validatorName]):
+                    return ('function' == typeof $.fn.bootstrapValidator.i18n[validatorName].getMessage)
+                            ? $.fn.bootstrapValidator.i18n[validatorName].getMessage(options)
+                            : $.fn.bootstrapValidator.i18n[validatorName]['default'];
+                case (!!this.options.fields[field].message):
+                    return this.options.fields[field].message;
+                default:
+                    this.options.message
+            }
+        },
+
+        /**
          * Get the element to place the error messages
          *
          * @param {jQuery} $field The field element
@@ -1354,12 +1383,30 @@
 
     // Available validators
     $.fn.bootstrapValidator.validators = {};
+    $.fn.bootstrapValidator.i18n       = {};
 
     $.fn.bootstrapValidator.Constructor = BootstrapValidator;
 
     // Helper methods, which can be used in validator class
     $.fn.bootstrapValidator.helpers = {
         /**
+         * Format a string
+         * It's used to format the error message
+         * format('The field must between %s and %s', [10, 20]) = 'The field must between 10 and 20'
+         *
+         * @param {String} message
+         * @param {Array} parameters
+         * @returns {String}
+         */
+        format: function(message, parameters) {
+            for (var i in parameters) {
+                message = message.replace('%s', parameters[i]);
+            }
+
+            return message;
+        },
+
+        /**
          * Validate a date
          *
          * @param {Number} year The full year in 4 digits
@@ -1460,6 +1507,10 @@
     };
 }(window.jQuery));
 ;(function($) {
+    $.fn.bootstrapValidator.i18n.base64 = $.extend($.fn.bootstrapValidator.i18n.base64 || {}, {
+        'default': 'The value is not a valid base 64 encoded'
+    });
+
     $.fn.bootstrapValidator.validators.base64 = {
         /**
          * Return true if the input value is a base 64 encoded string.
@@ -1481,6 +1532,18 @@
     };
 }(window.jQuery));
 ;(function($) {
+    $.fn.bootstrapValidator.i18n.between = $.extend($.fn.bootstrapValidator.i18n.between || {}, {
+        'default': 'The value is not valid',
+        inclusive: 'The value must be between %s and %s',
+        notInclusive: 'The value must be between %s and %s strictly',
+
+        getMessage: function(options) {
+            return (options.inclusive === true || options.inclusive == undefined)
+                    ? $.fn.bootstrapValidator.helpers.format(this.inclusive, [options.min, options.max])
+                    : $.fn.bootstrapValidator.helpers.format(this.notInclusive, [options.min, options.max]);
+        }
+    });
+
     $.fn.bootstrapValidator.validators.between = {
         html5Attributes: {
             message: 'message',
@@ -1526,6 +1589,10 @@
     };
 }(window.jQuery));
 ;(function($) {
+    $.fn.bootstrapValidator.i18n.callback = $.extend($.fn.bootstrapValidator.i18n.callback || {}, {
+        'default': 'The value is not valid'
+    });
+
     $.fn.bootstrapValidator.validators.callback = {
         /**
          * Return result from the callback method
@@ -1555,6 +1622,25 @@
     };
 }(window.jQuery));
 ;(function($) {
+    $.fn.bootstrapValidator.i18n.choice = $.extend($.fn.bootstrapValidator.i18n.choice || {}, {
+        'default': 'The value is not valid',
+        less: 'Choose %s options at minimum',
+        more: 'Choose %s options at maximum',
+        between: 'Choose %s - %s options',
+
+        getMessage: function(options) {
+            switch (true) {
+                case (!!options.min && !!options.max):
+                    return $.fn.bootstrapValidator.helpers.format(this.between, [options.min, options.max]);
+                    break;
+                case (!!options.min):
+                    return $.fn.bootstrapValidator.helpers.format(this.less, [options.min]);
+                case (!!options.max):
+                    return $.fn.bootstrapValidator.helpers.format(this.more, [options.max]);
+            }
+        }
+    });
+
     $.fn.bootstrapValidator.validators.choice = {
         html5Attributes: {
             message: 'message',
@@ -1587,6 +1673,10 @@
     };
 }(window.jQuery));
 ;(function($) {
+    $.fn.bootstrapValidator.i18n.creditCard = $.extend($.fn.bootstrapValidator.i18n.creditCard || {}, {
+        'default': 'The value is not a valid credit card number'
+    });
+
     $.fn.bootstrapValidator.validators.creditCard = {
         /**
          * Return true if the input value is valid credit card number
@@ -1686,6 +1776,10 @@
     };
 }(window.jQuery));
 ;(function($) {
+    $.fn.bootstrapValidator.i18n.cusip = $.extend($.fn.bootstrapValidator.i18n.cusip || {}, {
+        'default': 'The value is not a valid CUSIP number'
+    });
+
     $.fn.bootstrapValidator.validators.cusip = {
         /**
          * Validate a CUSIP
@@ -1737,6 +1831,10 @@
     };
 }(window.jQuery));
 ;(function($) {
+    $.fn.bootstrapValidator.i18n.cvv = $.extend($.fn.bootstrapValidator.i18n.cvv || {}, {
+        'default': 'The value is not a valid CVV number'
+    });
+
     $.fn.bootstrapValidator.validators.cvv = {
         html5Attributes: {
             message: 'message',
@@ -2016,6 +2114,10 @@
     }
 }(window.jQuery));
 ;(function($) {
+    $.fn.bootstrapValidator.i18n.ean = $.extend($.fn.bootstrapValidator.i18n.ean || {}, {
+        'default': 'The value is not a valid EAN number'
+    });
+
     $.fn.bootstrapValidator.validators.ean = {
         /**
          * Validate EAN (International Article Number)
@@ -2052,6 +2154,10 @@
     };
 }(window.jQuery));
 ;(function($) {
+    $.fn.bootstrapValidator.i18n.emailAddress = $.extend($.fn.bootstrapValidator.i18n.emailAddress || {}, {
+        'default': 'The value is not a valid email address'
+    });
+
     $.fn.bootstrapValidator.validators.emailAddress = {
         enableByHtml5: function($field) {
             return ('email' == $field.attr('type'));
@@ -2184,6 +2290,10 @@
     }
 }(window.jQuery));
 ;(function($) {
+    $.fn.bootstrapValidator.i18n.grid = $.extend($.fn.bootstrapValidator.i18n.grid || {}, {
+        'default': 'The value is not a valid GRId number'
+    });
+
     $.fn.bootstrapValidator.validators.grid = {
         /**
          * Validate GRId (Global Release Identifier)
@@ -2217,6 +2327,10 @@
     };
 }(window.jQuery));
 ;(function($) {
+    $.fn.bootstrapValidator.i18n.hex = $.extend($.fn.bootstrapValidator.i18n.hex || {}, {
+        'default': 'The value is not a valid hexadecimal number'
+    });
+
     $.fn.bootstrapValidator.validators.hex = {
         /**
          * Return true if and only if the input value is a valid hexadecimal number
@@ -2238,6 +2352,10 @@
     };
 }(window.jQuery));
 ;(function($) {
+    $.fn.bootstrapValidator.i18n.hexColor = $.extend($.fn.bootstrapValidator.i18n.hexColor || {}, {
+        'default': 'The value is not a valid hex color'
+    });
+
     $.fn.bootstrapValidator.validators.hexColor = {
         enableByHtml5: function($field) {
             return ('color' == $field.attr('type'));
@@ -2262,6 +2380,10 @@
     };
 }(window.jQuery));
 ;(function($) {
+    $.fn.bootstrapValidator.i18n.iban = $.extend($.fn.bootstrapValidator.i18n.iban || {}, {
+        'default': 'The value is not a valid IBAN number'
+    });
+
     $.fn.bootstrapValidator.validators.iban = {
         html5Attributes: {
             message: 'message',
@@ -3195,6 +3317,10 @@
     };
 }(window.jQuery));
 ;(function($) {
+    $.fn.bootstrapValidator.i18n.imei = $.extend($.fn.bootstrapValidator.i18n.imei || {}, {
+        'default': 'The value is not a valid IMEI number'
+    });
+
     $.fn.bootstrapValidator.validators.imei = {
         /**
          * Validate IMEI (International Mobile Station Equipment Identity)
@@ -3260,6 +3386,10 @@
     };
 }(window.jQuery));
 ;(function($) {
+    $.fn.bootstrapValidator.i18n.ip = $.extend($.fn.bootstrapValidator.i18n.ip || {}, {
+        'default': 'The value is not a valid IP address'
+    });
+
     $.fn.bootstrapValidator.validators.ip = {
         html5Attributes: {
             message: 'message',
@@ -3295,6 +3425,10 @@
     };
 }(window.jQuery));
 ;(function($) {
+    $.fn.bootstrapValidator.i18n.isbn = $.extend($.fn.bootstrapValidator.i18n.isbn || {}, {
+        'default': 'The value is not a valid ISBN number'
+    });
+
     $.fn.bootstrapValidator.validators.isbn = {
         /**
          * Return true if the input value is a valid ISBN 10 or ISBN 13 number
@@ -3376,6 +3510,10 @@
     };
 }(window.jQuery));
 ;(function($) {
+    $.fn.bootstrapValidator.i18n.isin = $.extend($.fn.bootstrapValidator.i18n.isin || {}, {
+        'default': 'The value is not a valid ISIN number'
+    });
+
     $.fn.bootstrapValidator.validators.isin = {
         // Available country codes
         // See http://isin.net/country-codes/
@@ -3431,6 +3569,10 @@
     };
 }(window.jQuery));
 ;(function($) {
+    $.fn.bootstrapValidator.i18n.ismn = $.extend($.fn.bootstrapValidator.i18n.ismn || {}, {
+        'default': 'The value is not a valid ISMN number'
+    });
+
     $.fn.bootstrapValidator.validators.ismn = {
         /**
          * Validate ISMN (International Standard Music Number)
@@ -3486,6 +3628,10 @@
     };
 }(window.jQuery));
 ;(function($) {
+    $.fn.bootstrapValidator.i18n.issn = $.extend($.fn.bootstrapValidator.i18n.issn || {}, {
+        'default': 'The value is not a valid ISSN number'
+    });
+
     $.fn.bootstrapValidator.validators.issn = {
         /**
          * Validate ISSN (International Standard Serial Number)
@@ -3568,6 +3714,10 @@
     };
 }(window.jQuery));
 ;(function($) {
+    $.fn.bootstrapValidator.i18n.mac = $.extend($.fn.bootstrapValidator.i18n.mac || {}, {
+        'default': 'The value is not a valid MAC address'
+    });
+
     $.fn.bootstrapValidator.validators.mac = {
         /**
          * Return true if the input value is a MAC address.
@@ -3589,6 +3739,10 @@
     };
 }(window.jQuery));
 ;(function($) {
+    $.fn.bootstrapValidator.i18n.notEmpty = $.extend($.fn.bootstrapValidator.i18n.notEmpty || {}, {
+        'default': 'The value is required'
+    });
+
     $.fn.bootstrapValidator.validators.notEmpty = {
         enableByHtml5: function($field) {
             var required = $field.attr('required') + '';
@@ -3788,6 +3942,10 @@
     };
 }(window.jQuery));
 ;(function($) {
+    $.fn.bootstrapValidator.i18n.rtn = $.extend($.fn.bootstrapValidator.i18n.rtn || {}, {
+        'default': 'The value is not a valid RTN number'
+    });
+
     $.fn.bootstrapValidator.validators.rtn = {
         /**
          * Validate a RTN (Routing transit number)
@@ -3822,6 +3980,10 @@
     };
 }(window.jQuery));
 ;(function($) {
+    $.fn.bootstrapValidator.i18n.sedol = $.extend($.fn.bootstrapValidator.i18n.sedol || {}, {
+        'default': 'The value is not a valid SEDOL number'
+    });
+
     $.fn.bootstrapValidator.validators.sedol = {
         /**
          * Validate a SEDOL (Stock Exchange Daily Official List)
@@ -3858,6 +4020,10 @@
     };
 }(window.jQuery));
 ;(function($) {
+    $.fn.bootstrapValidator.i18n.siren = $.extend($.fn.bootstrapValidator.i18n.siren || {}, {
+        'default': 'The value is not a valid siren number'
+    });
+
 	$.fn.bootstrapValidator.validators.siren = {
 		/**
 		 * Check if a string is a siren number
@@ -3882,6 +4048,10 @@
 	};
 }(window.jQuery));
 ;(function($) {
+    $.fn.bootstrapValidator.i18n.siret = $.extend($.fn.bootstrapValidator.i18n.siret || {}, {
+        'default': 'The value is not a valid siret number'
+    });
+
 	$.fn.bootstrapValidator.validators.siret = {
         /**
          * Check if a string is a siret number
@@ -4007,6 +4177,25 @@
     };
 }(window.jQuery));
 ;(function($) {
+    $.fn.bootstrapValidator.i18n.stringLength = $.extend($.fn.bootstrapValidator.i18n.stringLength || {}, {
+        'default': 'The value length is not valid',
+        less: 'The value must be less than %s characters long',
+        more: 'The value must be more than %s characters long',
+        between: 'The value must be between %s and %s characters long',
+
+        getMessage: function(options) {
+            switch (true) {
+                case (!!options.min && !!options.max):
+                    return $.fn.bootstrapValidator.helpers.format(this.between, [options.min, options.max]);
+                    break;
+                case (!!options.min):
+                    return $.fn.bootstrapValidator.helpers.format(this.more, [options.min]);
+                case (!!options.max):
+                    return $.fn.bootstrapValidator.helpers.format(this.less, [options.max]);
+            }
+        }
+    });
+
     $.fn.bootstrapValidator.validators.stringLength = {
         html5Attributes: {
             message: 'message',
@@ -4053,6 +4242,10 @@
     };
 }(window.jQuery));
 ;(function($) {
+    $.fn.bootstrapValidator.i18n.uri = $.extend($.fn.bootstrapValidator.i18n.uri || {}, {
+        'default': 'The value is not a valid URI'
+    });
+
     $.fn.bootstrapValidator.validators.uri = {
         html5Attributes: {
             message: 'message',
@@ -4150,6 +4343,10 @@
     };
 }(window.jQuery));
 ;(function($) {
+    $.fn.bootstrapValidator.i18n.uuid = $.extend($.fn.bootstrapValidator.i18n.uuid || {}, {
+        'default': 'The value is not a valid UUID'
+    });
+
     $.fn.bootstrapValidator.validators.uuid = {
         html5Attributes: {
             message: 'message',
@@ -5342,6 +5539,10 @@
     };
 }(window.jQuery));
 ;(function($) {
+    $.fn.bootstrapValidator.i18n.vin = $.extend($.fn.bootstrapValidator.i18n.vin || {}, {
+        'default': 'The value is not a valid VIN number'
+    });
+
     $.fn.bootstrapValidator.validators.vin = {
         /**
          * Validate an US VIN (Vehicle Identification Number)

File diff suppressed because it is too large
+ 3 - 2
dist/js/bootstrapValidator.min.js


+ 48 - 1
src/js/bootstrapValidator.js

@@ -254,7 +254,7 @@
                             .attr('data-bv-validator', validatorName)
                             .attr('data-bv-for', field)
                             .attr('data-bv-result', this.STATUS_NOT_VALIDATED)
-                            .html(this.options.fields[field].validators[validatorName].message || this.options.fields[field].message || this.options.message)
+                            .html(this._getMessage(field, validatorName))
                             .appendTo($message);
                     }
                 }
@@ -318,6 +318,35 @@
         },
 
         /**
+         * Get the error message for given field and validator
+         *
+         * @param {String} field The field name
+         * @param {String} validatorName The validator name
+         * @returns {String}
+         */
+        _getMessage: function(field, validatorName) {
+            if (!this.options.fields[field] || !$.fn.bootstrapValidator.validators[validatorName]
+                || !this.options.fields[field].validators || !this.options.fields[field].validators[validatorName])
+            {
+                return '';
+            }
+
+            var options = this.options.fields[field].validators[validatorName];
+            switch (true) {
+                case (!!options.message):
+                    return options.message;
+                case (!!$.fn.bootstrapValidator.i18n[validatorName]):
+                    return ('function' == typeof $.fn.bootstrapValidator.i18n[validatorName].getMessage)
+                            ? $.fn.bootstrapValidator.i18n[validatorName].getMessage(options)
+                            : $.fn.bootstrapValidator.i18n[validatorName]['default'];
+                case (!!this.options.fields[field].message):
+                    return this.options.fields[field].message;
+                default:
+                    this.options.message
+            }
+        },
+
+        /**
          * Get the element to place the error messages
          *
          * @param {jQuery} $field The field element
@@ -1353,12 +1382,30 @@
 
     // Available validators
     $.fn.bootstrapValidator.validators = {};
+    $.fn.bootstrapValidator.i18n       = {};
 
     $.fn.bootstrapValidator.Constructor = BootstrapValidator;
 
     // Helper methods, which can be used in validator class
     $.fn.bootstrapValidator.helpers = {
         /**
+         * Format a string
+         * It's used to format the error message
+         * format('The field must between %s and %s', [10, 20]) = 'The field must between 10 and 20'
+         *
+         * @param {String} message
+         * @param {Array} parameters
+         * @returns {String}
+         */
+        format: function(message, parameters) {
+            for (var i in parameters) {
+                message = message.replace('%s', parameters[i]);
+            }
+
+            return message;
+        },
+
+        /**
          * Validate a date
          *
          * @param {Number} year The full year in 4 digits

+ 4 - 0
src/js/validator/base64.js

@@ -1,4 +1,8 @@
 (function($) {
+    $.fn.bootstrapValidator.i18n.base64 = $.extend($.fn.bootstrapValidator.i18n.base64 || {}, {
+        'default': 'The value is not a valid base 64 encoded'
+    });
+
     $.fn.bootstrapValidator.validators.base64 = {
         /**
          * Return true if the input value is a base 64 encoded string.

+ 12 - 0
src/js/validator/between.js

@@ -1,4 +1,16 @@
 (function($) {
+    $.fn.bootstrapValidator.i18n.between = $.extend($.fn.bootstrapValidator.i18n.between || {}, {
+        'default': 'The value is not valid',
+        inclusive: 'The value must be between %s and %s',
+        notInclusive: 'The value must be between %s and %s strictly',
+
+        getMessage: function(options) {
+            return (options.inclusive === true || options.inclusive == undefined)
+                    ? $.fn.bootstrapValidator.helpers.format(this.inclusive, [options.min, options.max])
+                    : $.fn.bootstrapValidator.helpers.format(this.notInclusive, [options.min, options.max]);
+        }
+    });
+
     $.fn.bootstrapValidator.validators.between = {
         html5Attributes: {
             message: 'message',

+ 4 - 0
src/js/validator/callback.js

@@ -1,4 +1,8 @@
 (function($) {
+    $.fn.bootstrapValidator.i18n.callback = $.extend($.fn.bootstrapValidator.i18n.callback || {}, {
+        'default': 'The value is not valid'
+    });
+
     $.fn.bootstrapValidator.validators.callback = {
         /**
          * Return result from the callback method

+ 19 - 0
src/js/validator/choice.js

@@ -1,4 +1,23 @@
 (function($) {
+    $.fn.bootstrapValidator.i18n.choice = $.extend($.fn.bootstrapValidator.i18n.choice || {}, {
+        'default': 'The value is not valid',
+        less: 'Choose %s options at minimum',
+        more: 'Choose %s options at maximum',
+        between: 'Choose %s - %s options',
+
+        getMessage: function(options) {
+            switch (true) {
+                case (!!options.min && !!options.max):
+                    return $.fn.bootstrapValidator.helpers.format(this.between, [options.min, options.max]);
+                    break;
+                case (!!options.min):
+                    return $.fn.bootstrapValidator.helpers.format(this.less, [options.min]);
+                case (!!options.max):
+                    return $.fn.bootstrapValidator.helpers.format(this.more, [options.max]);
+            }
+        }
+    });
+
     $.fn.bootstrapValidator.validators.choice = {
         html5Attributes: {
             message: 'message',

+ 4 - 0
src/js/validator/creditCard.js

@@ -1,4 +1,8 @@
 (function($) {
+    $.fn.bootstrapValidator.i18n.creditCard = $.extend($.fn.bootstrapValidator.i18n.creditCard || {}, {
+        'default': 'The value is not a valid credit card number'
+    });
+
     $.fn.bootstrapValidator.validators.creditCard = {
         /**
          * Return true if the input value is valid credit card number

+ 4 - 0
src/js/validator/cusip.js

@@ -1,4 +1,8 @@
 (function($) {
+    $.fn.bootstrapValidator.i18n.cusip = $.extend($.fn.bootstrapValidator.i18n.cusip || {}, {
+        'default': 'The value is not a valid CUSIP number'
+    });
+
     $.fn.bootstrapValidator.validators.cusip = {
         /**
          * Validate a CUSIP

+ 4 - 0
src/js/validator/cvv.js

@@ -1,4 +1,8 @@
 (function($) {
+    $.fn.bootstrapValidator.i18n.cvv = $.extend($.fn.bootstrapValidator.i18n.cvv || {}, {
+        'default': 'The value is not a valid CVV number'
+    });
+
     $.fn.bootstrapValidator.validators.cvv = {
         html5Attributes: {
             message: 'message',

+ 4 - 0
src/js/validator/ean.js

@@ -1,4 +1,8 @@
 (function($) {
+    $.fn.bootstrapValidator.i18n.ean = $.extend($.fn.bootstrapValidator.i18n.ean || {}, {
+        'default': 'The value is not a valid EAN number'
+    });
+
     $.fn.bootstrapValidator.validators.ean = {
         /**
          * Validate EAN (International Article Number)

+ 4 - 0
src/js/validator/emailAddress.js

@@ -1,4 +1,8 @@
 (function($) {
+    $.fn.bootstrapValidator.i18n.emailAddress = $.extend($.fn.bootstrapValidator.i18n.emailAddress || {}, {
+        'default': 'The value is not a valid email address'
+    });
+
     $.fn.bootstrapValidator.validators.emailAddress = {
         enableByHtml5: function($field) {
             return ('email' == $field.attr('type'));

+ 4 - 0
src/js/validator/grid.js

@@ -1,4 +1,8 @@
 (function($) {
+    $.fn.bootstrapValidator.i18n.grid = $.extend($.fn.bootstrapValidator.i18n.grid || {}, {
+        'default': 'The value is not a valid GRId number'
+    });
+
     $.fn.bootstrapValidator.validators.grid = {
         /**
          * Validate GRId (Global Release Identifier)

+ 4 - 0
src/js/validator/hex.js

@@ -1,4 +1,8 @@
 (function($) {
+    $.fn.bootstrapValidator.i18n.hex = $.extend($.fn.bootstrapValidator.i18n.hex || {}, {
+        'default': 'The value is not a valid hexadecimal number'
+    });
+
     $.fn.bootstrapValidator.validators.hex = {
         /**
          * Return true if and only if the input value is a valid hexadecimal number

+ 4 - 0
src/js/validator/hexColor.js

@@ -1,4 +1,8 @@
 (function($) {
+    $.fn.bootstrapValidator.i18n.hexColor = $.extend($.fn.bootstrapValidator.i18n.hexColor || {}, {
+        'default': 'The value is not a valid hex color'
+    });
+
     $.fn.bootstrapValidator.validators.hexColor = {
         enableByHtml5: function($field) {
             return ('color' == $field.attr('type'));

+ 4 - 0
src/js/validator/iban.js

@@ -1,4 +1,8 @@
 (function($) {
+    $.fn.bootstrapValidator.i18n.iban = $.extend($.fn.bootstrapValidator.i18n.iban || {}, {
+        'default': 'The value is not a valid IBAN number'
+    });
+
     $.fn.bootstrapValidator.validators.iban = {
         html5Attributes: {
             message: 'message',

+ 4 - 0
src/js/validator/imei.js

@@ -1,4 +1,8 @@
 (function($) {
+    $.fn.bootstrapValidator.i18n.imei = $.extend($.fn.bootstrapValidator.i18n.imei || {}, {
+        'default': 'The value is not a valid IMEI number'
+    });
+
     $.fn.bootstrapValidator.validators.imei = {
         /**
          * Validate IMEI (International Mobile Station Equipment Identity)

+ 4 - 0
src/js/validator/ip.js

@@ -1,4 +1,8 @@
 (function($) {
+    $.fn.bootstrapValidator.i18n.ip = $.extend($.fn.bootstrapValidator.i18n.ip || {}, {
+        'default': 'The value is not a valid IP address'
+    });
+
     $.fn.bootstrapValidator.validators.ip = {
         html5Attributes: {
             message: 'message',

+ 4 - 0
src/js/validator/isbn.js

@@ -1,4 +1,8 @@
 (function($) {
+    $.fn.bootstrapValidator.i18n.isbn = $.extend($.fn.bootstrapValidator.i18n.isbn || {}, {
+        'default': 'The value is not a valid ISBN number'
+    });
+
     $.fn.bootstrapValidator.validators.isbn = {
         /**
          * Return true if the input value is a valid ISBN 10 or ISBN 13 number

+ 4 - 0
src/js/validator/isin.js

@@ -1,4 +1,8 @@
 (function($) {
+    $.fn.bootstrapValidator.i18n.isin = $.extend($.fn.bootstrapValidator.i18n.isin || {}, {
+        'default': 'The value is not a valid ISIN number'
+    });
+
     $.fn.bootstrapValidator.validators.isin = {
         // Available country codes
         // See http://isin.net/country-codes/

+ 4 - 0
src/js/validator/ismn.js

@@ -1,4 +1,8 @@
 (function($) {
+    $.fn.bootstrapValidator.i18n.ismn = $.extend($.fn.bootstrapValidator.i18n.ismn || {}, {
+        'default': 'The value is not a valid ISMN number'
+    });
+
     $.fn.bootstrapValidator.validators.ismn = {
         /**
          * Validate ISMN (International Standard Music Number)

+ 4 - 0
src/js/validator/issn.js

@@ -1,4 +1,8 @@
 (function($) {
+    $.fn.bootstrapValidator.i18n.issn = $.extend($.fn.bootstrapValidator.i18n.issn || {}, {
+        'default': 'The value is not a valid ISSN number'
+    });
+
     $.fn.bootstrapValidator.validators.issn = {
         /**
          * Validate ISSN (International Standard Serial Number)

+ 4 - 0
src/js/validator/mac.js

@@ -1,4 +1,8 @@
 (function($) {
+    $.fn.bootstrapValidator.i18n.mac = $.extend($.fn.bootstrapValidator.i18n.mac || {}, {
+        'default': 'The value is not a valid MAC address'
+    });
+
     $.fn.bootstrapValidator.validators.mac = {
         /**
          * Return true if the input value is a MAC address.

+ 4 - 0
src/js/validator/notEmpty.js

@@ -1,4 +1,8 @@
 (function($) {
+    $.fn.bootstrapValidator.i18n.notEmpty = $.extend($.fn.bootstrapValidator.i18n.notEmpty || {}, {
+        'default': 'The value is required'
+    });
+
     $.fn.bootstrapValidator.validators.notEmpty = {
         enableByHtml5: function($field) {
             var required = $field.attr('required') + '';

+ 4 - 0
src/js/validator/rtn.js

@@ -1,4 +1,8 @@
 (function($) {
+    $.fn.bootstrapValidator.i18n.rtn = $.extend($.fn.bootstrapValidator.i18n.rtn || {}, {
+        'default': 'The value is not a valid RTN number'
+    });
+
     $.fn.bootstrapValidator.validators.rtn = {
         /**
          * Validate a RTN (Routing transit number)

+ 4 - 0
src/js/validator/sedol.js

@@ -1,4 +1,8 @@
 (function($) {
+    $.fn.bootstrapValidator.i18n.sedol = $.extend($.fn.bootstrapValidator.i18n.sedol || {}, {
+        'default': 'The value is not a valid SEDOL number'
+    });
+
     $.fn.bootstrapValidator.validators.sedol = {
         /**
          * Validate a SEDOL (Stock Exchange Daily Official List)

+ 4 - 0
src/js/validator/siren.js

@@ -1,4 +1,8 @@
 (function($) {
+    $.fn.bootstrapValidator.i18n.siren = $.extend($.fn.bootstrapValidator.i18n.siren || {}, {
+        'default': 'The value is not a valid siren number'
+    });
+
 	$.fn.bootstrapValidator.validators.siren = {
 		/**
 		 * Check if a string is a siren number

+ 4 - 0
src/js/validator/siret.js

@@ -1,4 +1,8 @@
 (function($) {
+    $.fn.bootstrapValidator.i18n.siret = $.extend($.fn.bootstrapValidator.i18n.siret || {}, {
+        'default': 'The value is not a valid siret number'
+    });
+
 	$.fn.bootstrapValidator.validators.siret = {
         /**
          * Check if a string is a siret number

+ 19 - 0
src/js/validator/stringLength.js

@@ -1,4 +1,23 @@
 (function($) {
+    $.fn.bootstrapValidator.i18n.stringLength = $.extend($.fn.bootstrapValidator.i18n.stringLength || {}, {
+        'default': 'The value length is not valid',
+        less: 'The value must be less than %s characters long',
+        more: 'The value must be more than %s characters long',
+        between: 'The value must be between %s and %s characters long',
+
+        getMessage: function(options) {
+            switch (true) {
+                case (!!options.min && !!options.max):
+                    return $.fn.bootstrapValidator.helpers.format(this.between, [options.min, options.max]);
+                    break;
+                case (!!options.min):
+                    return $.fn.bootstrapValidator.helpers.format(this.more, [options.min]);
+                case (!!options.max):
+                    return $.fn.bootstrapValidator.helpers.format(this.less, [options.max]);
+            }
+        }
+    });
+
     $.fn.bootstrapValidator.validators.stringLength = {
         html5Attributes: {
             message: 'message',

+ 4 - 0
src/js/validator/uri.js

@@ -1,4 +1,8 @@
 (function($) {
+    $.fn.bootstrapValidator.i18n.uri = $.extend($.fn.bootstrapValidator.i18n.uri || {}, {
+        'default': 'The value is not a valid URI'
+    });
+
     $.fn.bootstrapValidator.validators.uri = {
         html5Attributes: {
             message: 'message',

+ 4 - 0
src/js/validator/uuid.js

@@ -1,4 +1,8 @@
 (function($) {
+    $.fn.bootstrapValidator.i18n.uuid = $.extend($.fn.bootstrapValidator.i18n.uuid || {}, {
+        'default': 'The value is not a valid UUID'
+    });
+
     $.fn.bootstrapValidator.validators.uuid = {
         html5Attributes: {
             message: 'message',

+ 4 - 0
src/js/validator/vin.js

@@ -1,4 +1,8 @@
 (function($) {
+    $.fn.bootstrapValidator.i18n.vin = $.extend($.fn.bootstrapValidator.i18n.vin || {}, {
+        'default': 'The value is not a valid VIN number'
+    });
+
     $.fn.bootstrapValidator.validators.vin = {
         /**
          * Validate an US VIN (Vehicle Identification Number)