From 4a0a3ee17ceeed7144da5a1dca21c85da186b30b Mon Sep 17 00:00:00 2001 From: Robin van der Vliet Date: Mon, 21 Jul 2025 19:30:22 +0200 Subject: [PATCH 1/3] Create isISO6391.ts --- src/decorator/string/isISO6391.ts | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 src/decorator/string/isISO6391.ts diff --git a/src/decorator/string/isISO6391.ts b/src/decorator/string/isISO6391.ts new file mode 100644 index 000000000..514e5443f --- /dev/null +++ b/src/decorator/string/isISO6391.ts @@ -0,0 +1,31 @@ +import { ValidationOptions } from '../ValidationOptions'; +import { buildMessage, ValidateBy } from '../common/ValidateBy'; +import isISO6391Validator from 'validator/lib/isISO6391'; + +export const IS_ISO6391 = 'isISO6391'; + +/** + * Check if the string is a valid [ISO 639-1](https://en.wikipedia.org/wiki/ISO_639-1) officially assigned language code. + */ +export function isISO6391(value: unknown): boolean { + return typeof value === 'string' && isISO6391Validator(value); +} + +/** + * Check if the string is a valid [ISO 639-1](https://en.wikipedia.org/wiki/ISO_639-1) officially assigned language code. + */ +export function IsISO6391(validationOptions?: ValidationOptions): PropertyDecorator { + return ValidateBy( + { + name: IS_ISO6391, + validator: { + validate: (value, args): boolean => isISO6391(value), + defaultMessage: buildMessage( + eachPrefix => eachPrefix + '$property must be a valid ISO 639-1 language code', + validationOptions + ), + }, + }, + validationOptions + ); +} From 84e8fb9d1401e6f36c2e144b8a2b987f52747521 Mon Sep 17 00:00:00 2001 From: Robin van der Vliet Date: Mon, 21 Jul 2025 19:38:42 +0200 Subject: [PATCH 2/3] Document `@IsIso6391()` in `README.md` --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 886712dd7..1460c4e3e 100644 --- a/README.md +++ b/README.md @@ -874,6 +874,7 @@ isBoolean(value); | `@IsLatitude()` | Checks if the string or number is a valid latitude coordinate. | | `@IsLongitude()` | Checks if the string or number is a valid longitude coordinate. | | `@IsMobilePhone(locale: string)` | Checks if the string is a mobile phone number. | +| `@IsISO6391()` | Checks if the string is a valid ISO 639-1 officially assigned language code. | | `@IsISO31661Alpha2()` | Checks if the string is a valid ISO 3166-1 alpha-2 officially assigned country code. | | `@IsISO31661Alpha3()` | Checks if the string is a valid ISO 3166-1 alpha-3 officially assigned country code. | | `@IsLocale()` | Checks if the string is a locale. | From d46db0b2fe1f0aa1f8055dacb37b6a5f40ea5add Mon Sep 17 00:00:00 2001 From: Robin van der Vliet Date: Thu, 24 Jul 2025 19:04:38 +0200 Subject: [PATCH 3/3] Add unit tests --- ...validation-functions-and-decorators.spec.ts | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/test/functional/validation-functions-and-decorators.spec.ts b/test/functional/validation-functions-and-decorators.spec.ts index 9f938616c..0ba115ccd 100644 --- a/test/functional/validation-functions-and-decorators.spec.ts +++ b/test/functional/validation-functions-and-decorators.spec.ts @@ -193,6 +193,7 @@ import { isTaxId, IsTaxId, IsISO4217CurrencyCode, + IsISO6391, } from '../../src/decorator/decorators'; import { Validator } from '../../src/validation/Validator'; import { ValidatorOptions } from '../../src/validation/ValidatorOptions'; @@ -4789,3 +4790,20 @@ describe('IsISO4217', () => { return checkInvalidValues(new MyClass(), invalidValues); }); }); + +describe('IsISO6391', () => { + class MyClass { + @IsISO6391() + someProperty: string; + } + + it('should not fail for a valid ISO 639-1 language code', () => { + const validValues = ['de', 'en', 'eo', 'fy', 'nl']; + return checkValidValues(new MyClass(), validValues); + }); + + it('should fail for invalid values', () => { + const invalidValues = [undefined, null, '', 'FR', 'xx', 'tok']; + return checkInvalidValues(new MyClass(), invalidValues); + }); +});