Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(isAlpha): multiple locale support in isAlpha #1752

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Expand Up @@ -85,7 +85,7 @@ Validator | Description
**contains(str, seed [, options ])** | check if the string contains the seed.<br/><br/>`options` is an object that defaults to `{ ignoreCase: false}`.<br/>`ignoreCase` specified whether the case of the substring be same or not.
**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', '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', '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.
**isAlpha(str [, locale, options])** | check if the string contains only letters (a-zA-Z).<br/><br/>Locale is either an array of locales (e.g `['sk-SK', 'sr-RS']`) OR `['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', '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', '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', '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', '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)** | check if a string is base32 encoded.
Expand Down
64 changes: 32 additions & 32 deletions src/lib/alpha.js
@@ -1,36 +1,36 @@
export const alpha = {
'en-US': /^[A-Z]+$/i,
'az-AZ': /^[A-VXYZÇƏĞİıÖŞÜ]+$/i,
'bg-BG': /^[А-Я]+$/i,
'cs-CZ': /^[A-ZÁČĎÉĚÍŇÓŘŠŤÚŮÝŽ]+$/i,
'da-DK': /^[A-ZÆØÅ]+$/i,
'de-DE': /^[A-ZÄÖÜß]+$/i,
'el-GR': /^[Α-ώ]+$/i,
'es-ES': /^[A-ZÁÉÍÑÓÚÜ]+$/i,
'fa-IR': /^[ابپتثجچحخدذرزژسشصضطظعغفقکگلمنوهی]+$/i,
'fr-FR': /^[A-ZÀÂÆÇÉÈÊËÏÎÔŒÙÛÜŸ]+$/i,
'it-IT': /^[A-ZÀÉÈÌÎÓÒÙ]+$/i,
'nb-NO': /^[A-ZÆØÅ]+$/i,
'nl-NL': /^[A-ZÁÉËÏÓÖÜÚ]+$/i,
'nn-NO': /^[A-ZÆØÅ]+$/i,
'hu-HU': /^[A-ZÁÉÍÓÖŐÚÜŰ]+$/i,
'pl-PL': /^[A-ZĄĆĘŚŁŃÓŻŹ]+$/i,
'pt-PT': /^[A-ZÃÁÀÂÄÇÉÊËÍÏÕÓÔÖÚÜ]+$/i,
'ru-RU': /^[А-ЯЁ]+$/i,
'sl-SI': /^[A-ZČĆĐŠŽ]+$/i,
'sk-SK': /^[A-ZÁČĎÉÍŇÓŠŤÚÝŽĹŔĽÄÔ]+$/i,
'sr-RS@latin': /^[A-ZČĆŽŠĐ]+$/i,
'sr-RS': /^[А-ЯЂЈЉЊЋЏ]+$/i,
'sv-SE': /^[A-ZÅÄÖ]+$/i,
'th-TH': /^[ก-๐\s]+$/i,
'tr-TR': /^[A-ZÇĞİıÖŞÜ]+$/i,
'uk-UA': /^[А-ЩЬЮЯЄIЇҐі]+$/i,
'vi-VN': /^[A-ZÀÁẠẢÃÂẦẤẬẨẪĂẰẮẶẲẴĐÈÉẸẺẼÊỀẾỆỂỄÌÍỊỈĨÒÓỌỎÕÔỒỐỘỔỖƠỜỚỢỞỠÙÚỤỦŨƯỪỨỰỬỮỲÝỴỶỸ]+$/i,
'ku-IQ': /^[ئابپتجچحخدرڕزژسشعغفڤقکگلڵمنوۆھەیێيطؤثآإأكضصةظذ]+$/i,
ar: /^[ءآأؤإئابةتثجحخدذرزسشصضطظعغفقكلمنهوىيًٌٍَُِّْٰ]+$/,
he: /^[א-ת]+$/,
fa: /^['آاءأؤئبپتثجچحخدذرزژسشصضطظعغفقکگلمنوهةی']+$/i,
'hi-IN': /^[\u0900-\u0961]+[\u0972-\u097F]*$/i,
'en-US': 'A-Z',
'az-AZ': 'A-VXYZÇƏĞİıÖŞÜ',
'bg-BG': 'А-Я',
'cs-CZ': 'A-ZÁČĎÉĚÍŇÓŘŠŤÚŮÝŽ',
'da-DK': 'A-ZÆØÅ',
'de-DE': 'A-ZÄÖÜß',
'el-GR': 'Α-ώ',
'es-ES': 'A-ZÁÉÍÑÓÚÜ',
'fa-IR': 'ابپتثجچحخدذرزژسشصضطظعغفقکگلمنوهی',
'fr-FR': 'A-ZÀÂÆÇÉÈÊËÏÎÔŒÙÛÜŸ',
'it-IT': 'A-ZÀÉÈÌÎÓÒÙ',
'nb-NO': 'A-ZÆØÅ',
'nl-NL': 'A-ZÁÉËÏÓÖÜÚ',
'nn-NO': 'A-ZÆØÅ',
'hu-HU': 'A-ZÁÉÍÓÖŐÚÜŰ',
'pl-PL': 'A-ZĄĆĘŚŁŃÓŻŹ',
'pt-PT': 'A-ZÃÁÀÂÄÇÉÊËÍÏÕÓÔÖÚÜ',
'ru-RU': 'А-ЯЁ',
'sl-SI': 'A-ZČĆĐŠŽ',
'sk-SK': 'A-ZÁČĎÉÍŇÓŠŤÚÝŽĹŔĽÄÔ',
'sr-RS@latin': 'A-ZČĆŽŠĐ',
'sr-RS': 'А-ЯЂЈЉЊЋЏ',
'sv-SE': 'A-ZÅÄÖ',
'th-TH': 'ก-๐\\s',
'tr-TR': 'A-ZÇĞİıÖŞÜ',
'uk-UA': 'А-ЩЬЮЯЄIЇҐі',
'vi-VN': 'A-ZÀÁẠẢÃÂẦẤẬẨẪĂẰẮẶẲẴĐÈÉẸẺẼÊỀẾỆỂỄÌÍỊỈĨÒÓỌỎÕÔỒỐỘỔỖƠỜỚỢỞỠÙÚỤỦŨƯỪỨỰỬỮỲÝỴỶỸ',
'ku-IQ': 'ئابپتجچحخدرڕزژسشعغفڤقکگلڵمنوۆھەیێيطؤثآإأكضصةظذ',
ar: 'ءآأؤإئابةتثجحخدذرزسشصضطظعغفقكلمنهوىيًٌٍَُِّْٰ',
he: 'א-ת',
fa: 'آاءأؤئبپتثجچحخدذرزژسشصضطظعغفقکگلمنوهةی',
'hi-IN': '\u0900-\u0961\u0972-\u097F',
};

export const alphanumeric = {
Expand Down
28 changes: 24 additions & 4 deletions src/lib/isAlpha.js
@@ -1,6 +1,28 @@
import assertString from './util/assertString';
import { alpha } from './alpha';


function getLocaleChars(locale) {
if (locale in alpha) {
return alpha[locale];
}
throw new Error(`Invalid locale '${locale}'`);
}

function buildRegex(locale) {
let allowedCharRanges = '';
if (Array.isArray(locale)) {
if (locale.length === 0) {
throw new Error('No locales specified');
}
allowedCharRanges = locale.map(l => getLocaleChars(l)).join('');
} else {
allowedCharRanges = getLocaleChars(locale);
}

return new RegExp(`^[${allowedCharRanges}]+$`, 'i');
}

export default function isAlpha(_str, locale = 'en-US', options = {}) {
assertString(_str);

Expand All @@ -17,10 +39,8 @@ export default function isAlpha(_str, locale = 'en-US', options = {}) {
}
}

if (locale in alpha) {
return alpha[locale].test(str);
}
throw new Error(`Invalid locale '${locale}'`);
const regex = buildRegex(locale);
return regex.test(str);
}

export const locales = Object.keys(alpha);
34 changes: 34 additions & 0 deletions test/validators.js
Expand Up @@ -1715,6 +1715,32 @@ describe('Validators', () => {
});
});

it('should validate multiple locales', () => {
test({
validator: 'isAlpha',
args: [['en-US', 'ru-RU']],
valid: [
'ТипцветкаTulip',
],
invalid: [
'สวัสดี',
'ยินดีต้อนรับ เทสเคส',
],
});
});

it('should error on no locale specified in array', () => {
test({
validator: 'isAlpha',
args: [[]],
error: [
'ТипцветкаTulip',
'สวัสดี',
'ยินดีต้อนรับ เทสเคส',
],
});
});

it('should error on invalid locale', () => {
test({
validator: 'isAlpha',
Expand All @@ -1724,6 +1750,14 @@ describe('Validators', () => {
'ABC',
],
});
test({
validator: 'isAlpha',
args: [['is-NOT']],
error: [
'1234568960',
'abc123',
],
});
});

it('should validate alphanumeric strings', () => {
Expand Down