From 9fa67f24cf18436e1dbee3da7f7cf64acf163dc8 Mon Sep 17 00:00:00 2001 From: tan7vir Date: Wed, 3 Jun 2026 16:04:42 +0600 Subject: [PATCH] fix(isFloat): use locale decimal separator for min/max comparison MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit isFloat builds its format regex from the locale's decimal separator (decimal[options.locale]), but the numeric value used for the min/max/lt/gt range checks was parsed with a hardcoded comma replacement: parseFloat(str.replace(',', '.')) For locales whose separator is neither '.' nor ',', the replacement was a no-op, so parseFloat stopped at the separator and dropped the fractional part. With the Arabic separator U+066B, parseFloat('3٫14') returned 3 instead of 3.14, corrupting every range comparison for the ar and fa-* locales -- producing both false negatives (valid values rejected) and false positives (out-of-range values accepted). Replace the locale's actual decimal separator before parsing. Format validation and all other locales are unchanged. --- src/lib/isFloat.js | 3 ++- test/validators.test.js | 20 ++++++++++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/src/lib/isFloat.js b/src/lib/isFloat.js index 84bdc782c..3d91b8af6 100644 --- a/src/lib/isFloat.js +++ b/src/lib/isFloat.js @@ -9,7 +9,8 @@ export default function isFloat(str, options) { if (str === '' || str === '.' || str === ',' || str === '-' || str === '+') { return false; } - const value = parseFloat(str.replace(',', '.')); + const decimalSeparator = options.locale ? decimal[options.locale] : '.'; + const value = parseFloat(str.replace(decimalSeparator, '.')); return float.test(str) && (!options.hasOwnProperty('min') || isNullOrUndefined(options.min) || value >= options.min) && (!options.hasOwnProperty('max') || isNullOrUndefined(options.max) || value <= options.max) && diff --git a/test/validators.test.js b/test/validators.test.js index a4c3d7193..323d2fe52 100644 --- a/test/validators.test.js +++ b/test/validators.test.js @@ -4857,6 +4857,26 @@ describe('Validators', () => { 'foo', ], }); + test({ + validator: 'isFloat', + args: [{ + locale: 'ar', + min: 3.1, + max: 4, + }], + valid: [ + '3٫1', + '3٫14', + '3٫999', + '4', + ], + invalid: [ + '3٫09', + '4٫01', + '9٫99', + '3', + ], + }); test({ validator: 'isFloat', args: [{