Repository: validatorjs/validator.js
Pull request #1678 (2021-05-27 10:15:36)

feat(isAlpha, isAlphanumeric): Added support for Bengali language
<!--
Add a descriptive title textbox above, e.g.
feat(isAlpha, isAlphanumeric): Added support for Bengali language
-->

- feat(isAlpha, isAlphanumeric): Added support for Bengali language
- Made some changes in alpha.js according to ```npm test``` results
- Written tests for Bengali language features in isAlpha and is Alpha


## Checklist

- [x] PR contains only changes related; no stray files, etc.
- [x] README updated (where applicable)
- [x] Tests written (where applicable)



Patch:
diff --git a/.gitignore b/.gitignore
index 9c8fa47..86aaede 100644
--- a/.gitignore
+++ b/.gitignore
@@ -10,3 +10,4 @@ yarn.lock
 /index.js
 validator.js
 validator.min.js
+
diff --git a/README.md b/README.md
index 49097c0..0b2e9b7 100644
--- a/README.md
+++ b/README.md
@@ -1,5 +1,5 @@
 # validator.js
-
+# Changes made - 1707074
 [![NPM version][npm-image]][npm-url]
 [![CI][ci-image]][ci-url]
 [![Coverage][codecov-image]][codecov-url]
@@ -92,8 +92,8 @@ Validator                               | Description
 **contains(str, seed [, options ])**    | check if the string contains the seed.<br/><br/>`options` is an object that defaults to `{ ignoreCase: false, minOccurrences: 1 }`.<br />Options: <br/> `ignoreCase`: Ignore case when doing comparison, default false<br/>`minOccurences`: Minimum number of occurrences for the seed in the string. Defaults to 1.
 **equals(str, comparison)**             | check if the string matches the comparison.
 **isAfter(str [, date])**               | check if the string is a date that's after the specified date (defaults to now).
-**isAlpha(str [, locale, options])**    | check if the string contains only letters (a-zA-Z).<br/><br/>Locale is one of `['ar', 'ar-AE', 'ar-BH', 'ar-DZ', 'ar-EG', 'ar-IQ', 'ar-JO', 'ar-KW', 'ar-LB', 'ar-LY', 'ar-MA', 'ar-QA', 'ar-QM', 'ar-SA', 'ar-SD', 'ar-SY', 'ar-TN', 'ar-YE', 'bg-BG', 'cs-CZ', 'da-DK', 'de-DE', 'el-GR', 'en-AU', 'en-GB', 'en-HK', 'en-IN', 'en-NZ', 'en-US', 'en-ZA', 'en-ZM', 'es-ES', 'fa-IR', 'fi-FI', 'fr-CA', 'fr-FR', 'he', 'hi-IN', 'hu-HU', 'it-IT', 'ku-IQ', 'nb-NO', 'nl-NL', 'nn-NO', 'pl-PL', 'pt-BR', 'pt-PT', 'ru-RU', 'si-LK', 'sl-SI', 'sk-SK', 'sr-RS', 'sr-RS@latin', 'sv-SE', 'tr-TR', 'uk-UA']`) and defaults to `en-US`. Locale list is `validator.isAlphaLocales`. options is an optional object that can be supplied with the following key(s): ignore which can either be a String or RegExp of characters to be ignored e.g. " -" will ignore spaces and -'s.
-**isAlphanumeric(str [, locale, options])**      | check if the string contains only letters and numbers (a-zA-Z0-9).<br/><br/>Locale is one of `['ar', 'ar-AE', 'ar-BH', 'ar-DZ', 'ar-EG', 'ar-IQ', 'ar-JO', 'ar-KW', 'ar-LB', 'ar-LY', 'ar-MA', 'ar-QA', 'ar-QM', 'ar-SA', 'ar-SD', 'ar-SY', 'ar-TN', 'ar-YE', 'bg-BG', 'cs-CZ', 'da-DK', 'de-DE', 'el-GR', 'en-AU', 'en-GB', 'en-HK', 'en-IN', 'en-NZ', 'en-US', 'en-ZA', 'en-ZM', 'es-ES', 'fa-IR', 'fi-FI', 'fr-CA', 'fr-FR', 'he', 'hi-IN', 'hu-HU', 'it-IT', 'ku-IQ', 'nb-NO', 'nl-NL', 'nn-NO', 'pl-PL', 'pt-BR', 'pt-PT', 'ru-RU', 'si-LK', 'sl-SI', 'sk-SK', 'sr-RS', 'sr-RS@latin', 'sv-SE', 'tr-TR', 'uk-UA']`) and defaults to `en-US`. Locale list is `validator.isAlphanumericLocales`. options is an optional object that can be supplied with the following key(s): ignore which can either be a String or RegExp of characters to be ignored e.g. " -" will ignore spaces and -'s.
+**isAlpha(str [, locale, options])**    | check if the string contains only letters (a-zA-Z).<br/><br/>Locale is one of `['ar', 'ar-AE', 'ar-BH', 'ar-DZ', 'ar-EG', 'ar-IQ', 'ar-JO', 'ar-KW', 'ar-LB', 'ar-LY', 'ar-MA', 'ar-QA', 'ar-QM', 'ar-SA', 'ar-SD', 'ar-SY', 'ar-TN', 'ar-YE', 'bg-BG', 'bn', 'cs-CZ', 'da-DK', 'de-DE', 'el-GR', 'en-AU', 'en-GB', 'en-HK', 'en-IN', 'en-NZ', 'en-US', 'en-ZA', 'en-ZM', 'es-ES', 'fa-IR', 'fi-FI', 'fr-CA', 'fr-FR', 'he', 'hi-IN', 'hu-HU', 'it-IT', 'ku-IQ', 'nb-NO', 'nl-NL', 'nn-NO', 'pl-PL', 'pt-BR', 'pt-PT', 'ru-RU', 'si-LK', 'sl-SI', 'sk-SK', 'sr-RS', 'sr-RS@latin', 'sv-SE', 'tr-TR', 'uk-UA']`) and defaults to `en-US`. Locale list is `validator.isAlphaLocales`. options is an optional object that can be supplied with the following key(s): ignore which can either be a String or RegExp of characters to be ignored e.g. " -" will ignore spaces and -'s.
+**isAlphanumeric(str [, locale, options])**      | check if the string contains only letters and numbers (a-zA-Z0-9).<br/><br/>Locale is one of `['ar', 'ar-AE', 'ar-BH', 'ar-DZ', 'ar-EG', 'ar-IQ', 'ar-JO', 'ar-KW', 'ar-LB', 'ar-LY', 'ar-MA', 'ar-QA', 'ar-QM', 'ar-SA', 'ar-SD', 'ar-SY', 'ar-TN', 'ar-YE', 'bn', 'bg-BG', 'cs-CZ', 'da-DK', 'de-DE', 'el-GR', 'en-AU', 'en-GB', 'en-HK', 'en-IN', 'en-NZ', 'en-US', 'en-ZA', 'en-ZM', 'es-ES', 'fa-IR', 'fi-FI', 'fr-CA', 'fr-FR', 'he', 'hi-IN', 'hu-HU', 'it-IT', 'ku-IQ', 'nb-NO', 'nl-NL', 'nn-NO', 'pl-PL', 'pt-BR', 'pt-PT', 'ru-RU', 'si-LK', 'sl-SI', 'sk-SK', 'sr-RS', 'sr-RS@latin', 'sv-SE', 'tr-TR', 'uk-UA']`) and defaults to `en-US`. Locale list is `validator.isAlphanumericLocales`. options is an optional object that can be supplied with the following key(s): ignore which can either be a String or RegExp of characters to be ignored e.g. " -" will ignore spaces and -'s.
 **isAscii(str)**                        | check if the string contains ASCII chars only.
 **isBase32(str [, options])**           | check if a string is base32 encoded. `options` is optional and defaults to `{crockford: false}`.<br/> When `crockford` is true it tests the given base32 encoded string using [Crockford's base32 alternative](http://www.crockford.com/base32.html).
 **isBase58(str)**                       | check if a string is base58 encoded.
@@ -137,7 +137,9 @@ Validator                               | Description
 **isISO4217(str)**                      | check if the string is a valid [ISO 4217](https://en.wikipedia.org/wiki/ISO_4217) officially assigned currency code.
 **isISRC(str)**                         | check if the string is a [ISRC](https://en.wikipedia.org/wiki/International_Standard_Recording_Code).
 **isISSN(str [, options])**             | check if the string is an [ISSN](https://en.wikipedia.org/wiki/International_Standard_Serial_Number).<br/><br/>`options` is an object which defaults to `{ case_sensitive: false, require_hyphen: false }`. If `case_sensitive` is true, ISSNs with a lowercase `'x'` as the check digit are rejected.
-**isJSON(str [, options])**             | check if the string is valid JSON (note: uses JSON.parse).<br/><br/>`options` is an object which defaults to `{ allow_primitives: false }`. If `allow_primitives` is true, the primitives 'true', 'false' and 'null' are accepted as valid JSON values.
+**isJSON(str [, options])**             | check if the string is valid JSON (note: uses JSON.parse).<br/><br/>`options` is an object which defaults to `{ allow_primitives: false }`. If `allow_primitives` is true, the primitives 'true', 'false' and '
+
+null' are accepted as valid JSON values.
 **isJWT(str)**                         | check if the string is valid JWT token.
 **isLatLong(str [, options])**                      | check if the string is a valid latitude-longitude coordinate in the format `lat,long` or `lat, long`.<br/><br/>`options` is an object that defaults to `{ checkDMS: false }`. Pass `checkDMS` as `true` to validate DMS(degrees, minutes, and seconds) latitude-longitude format.
 **isLength(str [, options])**              | check if the string's length falls in a range.<br/><br/>`options` is an object which defaults to `{min:0, max: undefined}`. Note: this function takes into account surrogate pairs.
diff --git a/src/lib/alpha.js b/src/lib/alpha.js
index 445ef85..c941c9b 100644
--- a/src/lib/alpha.js
+++ b/src/lib/alpha.js
@@ -31,6 +31,7 @@ export const alpha = {
   ar: /^[ءآأؤإئابةتثجحخدذرزسشصضطظعغفقكلمنهوىيًٌٍَُِّْٰ]+$/,
   he: /^[א-ת]+$/,
   fa: /^['آاءأؤئبپتثجچحخدذرزژسشصضطظعغفقکگلمنوهةی']+$/i,
+  bn: /^['ঀঁংঃঅআইঈউঊঋঌএঐওঔকখগঘঙচছজঝঞটঠডঢণতথদধনপফবভমযরলশষসহ়ঽািীুূৃৄেৈোৌ্ৎৗড়ঢ়য়ৠৡৢৣৰৱ৲৳৴৵৶৷৸৹৺৻']+$/,
   'hi-IN': /^[\u0900-\u0961]+[\u0972-\u097F]*$/i,
   'si-LK': /^[\u0D80-\u0DFF]+$/,
 };
@@ -67,6 +68,7 @@ export const alphanumeric = {
   ar: /^[٠١٢٣٤٥٦٧٨٩0-9ءآأؤإئابةتثجحخدذرزسشصضطظعغفقكلمنهوىيًٌٍَُِّْٰ]+$/,
   he: /^[0-9א-ת]+$/,
   fa: /^['0-9آاءأؤئبپتثجچحخدذرزژسشصضطظعغفقکگلمنوهةی۱۲۳۴۵۶۷۸۹۰']+$/i,
+  bn: /^['ঀঁংঃঅআইঈউঊঋঌএঐওঔকখগঘঙচছজঝঞটঠডঢণতথদধনপফবভমযরলশষসহ়ঽািীুূৃৄেৈোৌ্ৎৗড়ঢ়য়ৠৡৢৣ০১২৩৪৫৬৭৮৯ৰৱ৲৳৴৵৶৷৸৹৺৻']+$/,
   'hi-IN': /^[\u0900-\u0963]+[\u0966-\u097F]*$/i,
   'si-LK': /^[0-9\u0D80-\u0DFF]+$/,
 };
@@ -87,10 +89,8 @@ for (let locale, i = 0; i < englishLocales.length; i++) {
 }
 
 // Source: http://www.localeplanet.com/java/
-export const arabicLocales = [
-  'AE', 'BH', 'DZ', 'EG', 'IQ', 'JO', 'KW', 'LB', 'LY',
-  'MA', 'QM', 'QA', 'SA', 'SD', 'SY', 'TN', 'YE',
-];
+export const arabicLocales = ['AE', 'BH', 'DZ', 'EG', 'IQ', 'JO', 'KW', 'LB', 'LY',
+  'MA', 'QM', 'QA', 'SA', 'SD', 'SY', 'TN', 'YE'];
 
 for (let locale, i = 0; i < arabicLocales.length; i++) {
   locale = `ar-${arabicLocales[i]}`;
@@ -99,9 +99,7 @@ for (let locale, i = 0; i < arabicLocales.length; i++) {
   decimal[locale] = decimal.ar;
 }
 
-export const farsiLocales = [
-  'IR', 'AF',
-];
+export const farsiLocales = ['IR', 'AF'];
 
 for (let locale, i = 0; i < farsiLocales.length; i++) {
   locale = `fa-${farsiLocales[i]}`;
@@ -109,6 +107,15 @@ for (let locale, i = 0; i < farsiLocales.length; i++) {
   decimal[locale] = decimal.ar;
 }
 
+export const bengaliLocales = ['BD', 'IN'];
+
+for (let locale, i = 0; i < bengaliLocales.length; i++) {
+  locale = `bn-${bengaliLocales[i]}`;
+  alpha[locale] = alpha.bn;
+  alphanumeric[locale] = alphanumeric.bn;
+  decimal[locale] = decimal['en-US'];
+}
+
 // Source: https://en.wikipedia.org/wiki/Decimal_mark
 export const dotDecimal = ['ar-EG', 'ar-LB', 'ar-LY'];
 export const commaDecimal = [


Test patch:
diff --git a/test/validators.js b/test/validators.js
index f84002a..0f96f03 100644
--- a/test/validators.js
+++ b/test/validators.js
@@ -1424,6 +1424,26 @@ describe('Validators', () => {
     });
   });
 
+  it('should validate Bengali alpha strings', () => {
+    test({
+      validator: 'isAlpha',
+      args: ['bn-BD'],
+      valid: [
+        'অয়াওর',
+        'ফগফদ্রত',
+        'ফদ্ম্যতভ',
+        'বেরেওভচনভন',
+        'আমারবাসগা',
+      ],
+      invalid: [
+        'দাস২৩৪',
+        '  দ্গফহ্নভ  ',
+        '',
+        '(গফদ)',
+      ],
+    });
+  });
+
   it('should validate czech alpha strings', () => {
     test({
       validator: 'isAlpha',
@@ -2095,6 +2115,25 @@ describe('Validators', () => {
     });
   });
 
+  it('should validate Bengali alphanumeric strings', () => {
+    test({
+      validator: 'isAlphanumeric',
+      args: ['bn-BD'],
+      valid: [
+        'দ্গজ্ঞহ্রত্য১২৩',
+        'দ্গগফ৮৯০',
+        'চব৩৬৫ভবচ',
+        '১২৩৪',
+        '৩৪২৩৪দফজ্ঞদফ',
+      ],
+      invalid: [
+        ' ',
+        '১২৩  ',
+        'hel৩২0',
+      ],
+    });
+  });
+
   it('should validate czech alphanumeric strings', () => {
     test({
       validator: 'isAlphanumeric',